From 9f4624117366dfa03cb9093d750b9f830e45171c Mon Sep 17 00:00:00 2001
From: Alexandre Savard <alexandresavard@alexandresavard-desktop.(none)>
Date: Fri, 14 May 2010 16:08:28 -0400
Subject: [PATCH] [#1962] Add stream moved callback, add updateDevicelist in
 pulseaudio

---
 .../src/audio/codecs/celtcodec.cpp            |   1 -
 .../src/audio/pulseaudio/pulselayer.cpp       | 107 +++++++++++++++---
 .../src/audio/pulseaudio/pulselayer.h         |  15 +++
 3 files changed, 104 insertions(+), 19 deletions(-)

diff --git a/sflphone-common/src/audio/codecs/celtcodec.cpp b/sflphone-common/src/audio/codecs/celtcodec.cpp
index 612faa6791..65e7d1a0ea 100644
--- a/sflphone-common/src/audio/codecs/celtcodec.cpp
+++ b/sflphone-common/src/audio/codecs/celtcodec.cpp
@@ -42,7 +42,6 @@ class Celt : public AudioCodec
         Celt& operator= (const Celt&);
 
         void initCelt() {
-            printf ("Celt: Init Celt codec");
 
             int error = 0;
 
diff --git a/sflphone-common/src/audio/pulseaudio/pulselayer.cpp b/sflphone-common/src/audio/pulseaudio/pulselayer.cpp
index 82d5981aae..a7696ec56a 100644
--- a/sflphone-common/src/audio/pulseaudio/pulselayer.cpp
+++ b/sflphone-common/src/audio/pulseaudio/pulselayer.cpp
@@ -40,8 +40,7 @@ int framesPerBuffer = 2048;
   PA_SUBSCRIPTION_EVENT_TYPE_MASK = 0x0030U 
 */
 
-static  void playback_callback (pa_stream* s, size_t bytes, void* userdata)
-{
+static  void playback_callback (pa_stream* s, size_t bytes, void* userdata) {
 
     assert (s && bytes);
     assert (bytes > 0);
@@ -49,8 +48,7 @@ static  void playback_callback (pa_stream* s, size_t bytes, void* userdata)
 
 }
 
-static void capture_callback (pa_stream* s, size_t bytes, void* userdata)
-{
+static void capture_callback (pa_stream* s, size_t bytes, void* userdata) {
 
     assert (s && bytes);
     assert (bytes > 0);
@@ -58,8 +56,7 @@ static void capture_callback (pa_stream* s, size_t bytes, void* userdata)
     
 }
 
-static void ringtone_callback (pa_stream* s, size_t bytes, void* userdata)
-{
+static void ringtone_callback (pa_stream* s, size_t bytes, void* userdata) {
 
     assert(s && bytes);
     assert(bytes > 0);
@@ -67,6 +64,18 @@ static void ringtone_callback (pa_stream* s, size_t bytes, void* userdata)
 
 }
 
+
+static void stream_moved_callback(pa_stream *s, void *userdata) {
+
+  int streamIndex = pa_stream_get_index(s);
+  int deviceIndex = pa_stream_get_device_index(s);
+
+  _debug("stream_moved_callback: stream %d to %d", pa_stream_get_index(s), pa_stream_get_device_index(s));
+
+  // pa_context_get_sink_info_by_index(userdata->context, deviceIndex, sink_input_info_callback, userdata);
+
+}
+
 /*
   PA_SUBSCRIPTION_EVENT_SINK = 0x0000U,
   PA_SUBSCRIPTION_EVENT_SOURCE = 0x0001U,
@@ -84,15 +93,66 @@ static void ringtone_callback (pa_stream* s, size_t bytes, void* userdata)
   PA_SUBSCRIPTION_EVENT_TYPE_MASK = 0x0030U 
 */
 
-static void stream_changed_callback(pa_context* s, pa_subscription_event_type_t t, uint32_t idx, void* userdata)
+static void pa_success_callback(pa_context *c, int success, void *userdata) {
+
+  _debug("Audio: Success callback");
+}
+
+static void sink_input_info_callback(pa_context *c, const pa_sink_info *i, int eol, void *userdata) {
+  char s[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
+
+  if(!eol) {
+
+    _debug("Sink_input_info_callback: %d", eol);
+
+    // _debug("Audio: Sink info name: %s", i->name);
+    // _debug("Audio: Sing info index: %d", i->index);
+
+    printf("Sink #%u\n"
+           "    Name: %s\n"
+           "    Driver: %s\n"
+           "    Description: %s\n"
+           "    Sample Specification: %s\n"
+           "    Channel Map: %s\n"
+           "    Owner Module: %u\n"
+           "    Volume: %s\n"
+           "    Monitor Source: %u\n"
+           "    Latency: %0.0f usec\n"
+           "    Flags: %s%s%s\n",
+           i->index,
+           i->name,
+           i->driver,
+           i->description,
+           pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec),
+           pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
+           i->owner_module,
+           i->mute ? "muted" : pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
+           i->monitor_source,
+           (double) i->latency,
+           i->flags & PA_SINK_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "",
+           i->flags & PA_SINK_LATENCY ? "LATENCY " : "",
+           i->flags & PA_SINK_HARDWARE ? "HARDWARE" : "");
+
+
+  }
+}
+
+
+static void context_changed_callback(pa_context* c, pa_subscription_event_type_t t, uint32_t idx, void* userdata)
 {
 
+  _debug("---------------------- context_changed_callback %d ----------------------------", idx);
+
+  // AudioStream* ringtone = ((PulseLayer *)userdata)->getRingtoneStream();
+
   switch(t) {
 
   case PA_SUBSCRIPTION_EVENT_SINK:
+    pa_context_get_sink_info_list(c, sink_input_info_callback,  userdata);
     _debug("Audio: PA_SUBSCRIPTION_EVENT_SINK");
     break;
   case PA_SUBSCRIPTION_EVENT_SOURCE:
+    pa_context_get_sink_info_list(c, sink_input_info_callback,  userdata);
     _debug("Audio: PA_SUBSCRIPTION_EVENT_SOURCE");
     break;
   case PA_SUBSCRIPTION_EVENT_SINK_INPUT:
@@ -120,9 +180,12 @@ static void stream_changed_callback(pa_context* s, pa_subscription_event_type_t
     _debug("Audio: PA_SUBSCRIPTION_EVENT_FACILITY_MASK");
     break;
   case PA_SUBSCRIPTION_EVENT_CHANGE:
+    // pa_context_get_sink_info_by_index(c, idx, sink_input_info_callback, userdata);
+    // pa_context_get_sink_info_list(c, sink_input_info_callback,  userdata);
     _debug("Audio: PA_SUBSCRIPTION_EVENT_CHANGE");
     break;
   case PA_SUBSCRIPTION_EVENT_REMOVE:
+    // pa_context_get_sink_info_list(c, sink_input_info_callback,  userdata);
     _debug("Audio: PA_SUBSCRIPTION_EVENT_REMOVE");
     break;
   case PA_SUBSCRIPTION_EVENT_TYPE_MASK:
@@ -132,6 +195,10 @@ static void stream_changed_callback(pa_context* s, pa_subscription_event_type_t
     _debug("Audio: Unknown event type");
     
   }
+  // pa_stream_get_device_index
+  // pa_context_move_sink_input_by_name(c, );
+  // AudioStream* ringtone = userdata->getRingtoneStream();
+  //pa_context_get_sink_info_by_index (pa_context *c, uint32_t idx, pa_sink_info_cb_t cb, void *userdata);
 }
 
 /*
@@ -141,12 +208,6 @@ static void stream_suspended_callback (pa_stream *s UNUSED, void *userdata UNUSE
 }
 */
 
-/*
-static void stream_moved_callback(pa_stream *s UNUSED, void *userdata UNUSED)
-{
-    _debug("Audio: Stream Moved");
-}
-*/
 
 static void playback_underflow_callback (pa_stream* s,  void* userdata UNUSED)
 {
@@ -308,6 +369,10 @@ void PulseLayer::context_state_callback (pa_context* c, void* user_data)
         case PA_CONTEXT_READY:
             _debug ("Audio: Connection to PulseAudio server established");
             pa_threaded_mainloop_signal(pulse->m, 0);
+	    pa_context_subscribe (c, (pa_subscription_mask_t)(PA_SUBSCRIPTION_MASK_SINK|
+							      PA_SUBSCRIPTION_MASK_SOURCE), NULL, pulse);
+	    pa_context_set_subscribe_callback (c, context_changed_callback, pulse);
+	    pulse->updateDeviceList();
             break;
 
         case PA_CONTEXT_TERMINATED:
@@ -338,6 +403,14 @@ bool PulseLayer::openDevice (int indexIn UNUSED, int indexOut UNUSED, int sample
 }
 
 
+void PulseLayer::updateDeviceList(void) {
+
+  _debug("Audio: Update device list");
+
+  pa_context_get_sink_info_list(context, sink_input_info_callback,  this);
+}
+
+
 bool PulseLayer::createStreams (pa_context* c)
 {
     _info("Audio: Create streams");
@@ -355,7 +428,7 @@ bool PulseLayer::createStreams (pa_context* c)
     pa_stream_set_overflow_callback (playback->pulseStream(), playback_overflow_callback, this);
     pa_stream_set_underflow_callback (playback->pulseStream(), playback_underflow_callback, this);
     // pa_stream_set_suspended_callback(playback->pulseStream(), stream_suspended_callback, this);
-    // pa_stream_set_moved_callback(playback->pulseStream(), stream_moved_callback, this);
+    pa_stream_set_moved_callback(playback->pulseStream(), stream_moved_callback, this);
     delete playbackParam;
 
     PulseLayerType * recordParam = new PulseLayerType();
@@ -369,7 +442,7 @@ bool PulseLayer::createStreams (pa_context* c)
     record->connectStream();
     pa_stream_set_read_callback (record->pulseStream() , capture_callback, this);
     // pa_stream_set_suspended_callback(record->pulseStream(), stream_suspended_callback, this);
-    // pa_stream_set_moved_callback(record->pulseStream(), stream_moved_callback, this);
+    pa_stream_set_moved_callback(record->pulseStream(), stream_moved_callback, this);
     delete recordParam;
     
     PulseLayerType * ringtoneParam = new PulseLayerType();
@@ -382,11 +455,9 @@ bool PulseLayer::createStreams (pa_context* c)
     ringtone = new AudioStream (ringtoneParam, _audioSampleRate);
     ringtone->connectStream();
     pa_stream_set_write_callback(ringtone->pulseStream(), ringtone_callback, this);
+    pa_stream_set_moved_callback(ringtone->pulseStream(), stream_moved_callback, this);
     delete ringtoneParam;
 
-    pa_context_subscribe (c, PA_SUBSCRIPTION_MASK_SINK, NULL, this);
-    pa_context_set_subscribe_callback (c, stream_changed_callback, this);
-
     pa_threaded_mainloop_signal (m , 0);
 
     flushMain();
diff --git a/sflphone-common/src/audio/pulseaudio/pulselayer.h b/sflphone-common/src/audio/pulseaudio/pulselayer.h
index 59be37092f..8b0d9fa526 100644
--- a/sflphone-common/src/audio/pulseaudio/pulselayer.h
+++ b/sflphone-common/src/audio/pulseaudio/pulselayer.h
@@ -31,6 +31,9 @@
 
 #include <stdlib.h>
 
+#include <list>
+#include <string>
+
 #define PLAYBACK_STREAM_NAME	    "SFLphone playback"
 #define CAPTURE_STREAM_NAME	    "SFLphone capture"
 #define RINGTONE_STREAM_NAME        "SFLphone ringtone"
@@ -38,6 +41,8 @@
 class RingBuffer;
 class ManagerImpl;
 
+typedef std::list<std::string> DeviceList;
+
 class PulseLayer : public AudioLayer {
   public:
     PulseLayer(ManagerImpl* manager);
@@ -62,6 +67,8 @@ class PulseLayer : public AudioLayer {
      */
     bool openDevice(int indexIn, int indexOut, int sampleRate, int frameSize , int stream, std::string plugin) ;
 
+    void updateDeviceList(void);
+
     void startStream(void);
 
     void stopStream(void);
@@ -130,6 +137,12 @@ class PulseLayer : public AudioLayer {
      */
     AudioStream* getRecordStream(){ return record;}
 
+    /**
+     * Accessor
+     * @return AudioStream* The pointer on the ringtone AudioStream object
+     */
+    AudioStream* getRingtoneStream(){ return ringtone;}
+
     int getSpkrVolume( void ) { return spkrVolume; }
     void setSpkrVolume( int value ) { spkrVolume = value; }
 
@@ -219,6 +232,8 @@ class PulseLayer : public AudioLayer {
 
     DcBlocker* dcblocker;
 
+    DeviceList _deviceList;
+
     // private:
 
 public: 
-- 
GitLab