From 1a4b4d032ba625641a3d4ee4715d30f9ab5d1ffd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Adrien=20B=C3=A9raud?= <adrien.beraud@savoirfairelinux.com>
Date: Mon, 14 Sep 2015 12:28:45 -0400
Subject: [PATCH] audiolayer: properly wait for initialisation

Issue: #80355
Change-Id: I79b5a51549c30f0af14889d4e1d79ff32685de5c
---
 src/manager.cpp                        | 13 ++++---------
 src/media/audio/audiolayer.h           | 14 ++++++++++++--
 src/media/audio/opensl/opensllayer.cpp |  1 +
 3 files changed, 17 insertions(+), 11 deletions(-)

diff --git a/src/manager.cpp b/src/manager.cpp
index f1b92c3b42..0f8c549903 100644
--- a/src/manager.cpp
+++ b/src/manager.cpp
@@ -1505,9 +1505,6 @@ Manager::playDtmf(char code)
 
     std::lock_guard<std::mutex> lock(audioLayerMutex_);
 
-    // numbers of int = length in milliseconds / 1000 (number of seconds)
-    //                = number of seconds * SAMPLING_RATE by SECONDS
-
     // fast return, no sound, so no dtmf
     if (not audiodriver_ or not dtmfKey_) {
         RING_DBG("No audio layer...");
@@ -1515,6 +1512,10 @@ Manager::playDtmf(char code)
     }
 
     audiodriver_->startStream();
+    if (not audiodriver_->waitForStart(std::chrono::seconds(1))) {
+        RING_ERR("Failed to start audio layer...");
+        return;
+    }
 
     // number of data sampling in one pulselen depends on samplerate
     // size (n sampling) = time_ms * sampling/s
@@ -1533,12 +1534,6 @@ Manager::playDtmf(char code)
         // so size * 1 channel (mono) * sizeof (bytes for the data)
         // audiolayer->flushUrgent();
 
-        // FIXME: do real synchronization
-        int tries = 10;
-        while (not audiodriver_->isStarted() and tries--) {
-            RING_WARN("Audio layer not ready yet");
-            usleep(10000);
-        }
         audiodriver_->putUrgent(dtmfBuf_);
     }
 
diff --git a/src/media/audio/audiolayer.h b/src/media/audio/audiolayer.h
index 97ba729791..310bf80a1a 100644
--- a/src/media/audio/audiolayer.h
+++ b/src/media/audio/audiolayer.h
@@ -42,6 +42,8 @@
 #include <sys/time.h>
 #include <mutex>
 #include <vector>
+#include <atomic>
+#include <condition_variable>
 
 /**
  * @file  audiolayer.h
@@ -110,6 +112,13 @@ class AudioLayer {
             return isStarted_;
         }
 
+        template< class Rep, class Period >
+        bool waitForStart(const std::chrono::duration<Rep, Period>& rel_time) const {
+            std::unique_lock<std::mutex> lk(mutex_);
+            startedCv_.wait_for(lk, rel_time, [&]{return isStarted_.load();});
+            return isStarted_;
+        }
+
         /**
          * Send a chunk of data to the hardware buffer to start the playback
          * Copy data in the urgent buffer.
@@ -236,7 +245,8 @@ class AudioLayer {
         /**
          * Whether or not the audio layer stream is started
          */
-        bool isStarted_;
+        std::atomic_bool isStarted_;
+        mutable std::condition_variable startedCv_;
 
         /**
          * Sample Rate Ring should send sound data to the sound card
@@ -256,7 +266,7 @@ class AudioLayer {
         /**
          * Lock for the entire audio layer
          */
-        std::mutex mutex_;
+        mutable std::mutex mutex_;
 
         /**
          * Remove audio offset that can be introduced by certain cheap audio device
diff --git a/src/media/audio/opensl/opensllayer.cpp b/src/media/audio/opensl/opensllayer.cpp
index 4a9a9f7f0b..2fd1411e2c 100644
--- a/src/media/audio/opensl/opensllayer.cpp
+++ b/src/media/audio/opensl/opensllayer.cpp
@@ -132,6 +132,7 @@ OpenSLLayer::startStream()
         startAudioPlayback();
         startAudioCapture();
         isStarted_ = true;
+        startedCv_.notify_all();
     });
     launcher.detach();
 }
-- 
GitLab