All pastes #961960 Raw Edit

Unnamed

public text v1 · immutable
#961960 ·published 2008-03-29 11:11 UTC
rendered paste body
sGUI$ svn diff src/audio.c
Index: src/audio.c
===================================================================
--- src/audio.c (revision 2360)
+++ src/audio.c (working copy)
@@ -22,6 +22,35 @@
 #include "debug.h"
 #include "gpio.h"

+// define ENUMS for each audio pipeline.  This is used to
+// keep track of enabling speaker, etc.
+enum {
+  AUDIO_PIPELINE_KEYPRESS,
+  AUDIO_PIPELINE_ALERT,
+  AUDIO_PIPELINE_ALARM,
+  AUDIO_PIPELINE_PLAYBACK,
+  AUDIO_PIPELINE_RECORD,
+  AUDIO_PIPELINE_COUNT
+};
+
+#define AUDIO_PIPELINE_PLAYBACK_COUNT     AUDIO_PIPELINE_RECORD
+
+enum {
+  AUDIO_PIPELINE_STATE_STOPPED,
+  AUDIO_PIPELINE_STATE_RUNNING,
+};
+
+// Array used to keep track of the state of each
+// audio pipeline
+gint audio_pipeline_state[AUDIO_PIPELINE_COUNT];
+
+#define IS_PIPELINE_RUNNING(id)    (audio_pipeline_state[id] == AUDIO_PIPELINE_STATE_RUNNING)
+
+typedef struct {
+  GstElement * pipeline;
+  gint pipeline_id;
+} s_pipeline_t;
+
 // Shutdown logic
 gboolean audio_thread_closing = FALSE;
 G_LOCK_DEFINE_STATIC(audio_thread_closing);
@@ -30,7 +59,64 @@
 //   an error occurs.
 void (*recording_callback_function)(gint result) = NULL;

+G_LOCK_DEFINE_STATIC(speaker_control);

+static void speaker_on()
+{
+  s_debug(cl_d_sound, "Speaker Enable");
+  gpio_set(PP_GPIO_SPEAKER_AMP_DISABLE, 0);
+}
+
+static void speaker_off()
+{
+  s_debug(cl_d_sound, "Speaker Disable");
+  gpio_set(PP_GPIO_SPEAKER_AMP_DISABLE, 1);
+}
+
+static void speaker_control(gint pipeline_id, gboolean pipeline_start)
+{
+  int i;
+
+  G_LOCK(speaker_control);
+
+  if (pipeline_start == TRUE)
+    audio_pipeline_state[pipeline_id] = AUDIO_PIPELINE_STATE_RUNNING;
+  else
+    audio_pipeline_state[pipeline_id] = AUDIO_PIPELINE_STATE_STOPPED;
+
+  // if record is running, we disable speaker, and that's that!
+  if (pipeline_id == AUDIO_PIPELINE_RECORD) {
+    if (audio_pipeline_state[pipeline_id] == AUDIO_PIPELINE_STATE_RUNNING)
+      speaker_off();
+
+    goto speaker_control_done;
+  }
+
+  // if record is running, we don't want to do anything
+  if (audio_pipeline_state[pipeline_id] == AUDIO_PIPELINE_STATE_RUNNING)
+    goto speaker_control_done;
+
+  // we are dealing with playback
+  if (pipeline_start == TRUE) {
+    // turn on the speaker as at least one pipeline needs it
+    speaker_on();
+  } else {
+    // turn off the speaker if all pipelines are finished
+    for (i=0; i<AUDIO_PIPELINE_PLAYBACK_COUNT; i++) {
+      if (audio_pipeline_state[i] == AUDIO_PIPELINE_STATE_RUNNING)
+        goto speaker_control_done;
+    }
+
+    // all of the audio pipelines must be off
+    speaker_off();
+  }
+
+speaker_control_done:
+
+  G_UNLOCK(speaker_control);
+}
+
+
 // -----------------------------------------------------------------------------
 // close_audio_thread
 //   Routine used by the main signal handler to shut down the audio thread.
@@ -258,6 +344,7 @@
     gst_object_unref(GST_OBJECT(pipeline));
     return NULL;
   }
+  s_debug(1, "CLIFF: filename = %s", filename);
   g_object_set(G_OBJECT(filesink), "location", filename, NULL);

   // Add all off the elements to the main pipeline
@@ -279,7 +366,7 @@
 // -----------------------------------------------------------------------------
 static gboolean bus_callback(GstBus *bus, GstMessage *message, gpointer data)
 {
-  GstElement *pipeline = (GstElement *)data;
+  GstElement *pipeline = ((s_pipeline_t *)data)->pipeline;
   GError *gerror;
   gchar *debug;
   GstState current_state;
@@ -292,6 +379,8 @@
     //   back to the beginning in preparation for the next time the sound
     //   is played.
     case GST_MESSAGE_EOS:
+      // tell the speaker control that we are done playing
+      speaker_control(((s_pipeline_t *)data)->pipeline_id, FALSE);
       // Query the state of the pipeline
       gst_element_get_state(pipeline, &current_state, &pending_state, GST_MSECOND);

@@ -346,7 +435,7 @@
 // -----------------------------------------------------------------------------
 static gboolean playback_bus_callback(GstBus *bus, GstMessage *message, gpointer data)
 {
-  GstElement *pipeline = (GstElement *)data;
+  GstElement *pipeline = ((s_pipeline_t *)data)->pipeline;
   GError *gerror;
   gchar *debug;

@@ -354,6 +443,9 @@
   {
     // When the end of the stream is reached, notify the GUI thread.
     case GST_MESSAGE_EOS:
+      // Tell the speaker control we are done playing
+      speaker_control(((s_pipeline_t *)data)->pipeline_id, FALSE);
+
       if(recording_callback_function != NULL)
         recording_callback_function(TRUE);
       break;
@@ -385,11 +477,12 @@
 // play_pipeline
 //   Sets the specified pipeline state to PLAYING if it currently idle.
 // -----------------------------------------------------------------------------
-gboolean play_pipeline(GstElement *pipeline)
+gboolean play_pipeline(s_pipeline_t *s_pipeline)
 {
   gboolean return_val = FALSE;
   GstState current_state;
   GstState pending_state;
+  GstElement * pipeline = s_pipeline->pipeline;

   if(pipeline == NULL)
     return;
@@ -402,6 +495,8 @@
   if(current_state != GST_STATE_PLAYING &&
      pending_state == GST_STATE_VOID_PENDING)
   {
+    // tell the speaker control that we are starting playback
+    speaker_control(s_pipeline->pipeline_id, TRUE);
     gst_element_set_state(pipeline, GST_STATE_PLAYING);
     return_val = TRUE;
   }
@@ -483,6 +578,12 @@
   guint playback_callback_source_id = 0;
   GstBus *bus = NULL;

+  s_pipeline_t s_keypress_audio_pipeline;
+  s_pipeline_t s_alert_audio_pipeline;
+  s_pipeline_t s_alarm_audio_pipeline;
+  s_pipeline_t s_record_audio_pipeline;
+  s_pipeline_t s_playback_audio_pipeline;
+
   gst_init(NULL, NULL);
 #endif
   keypress_filename = g_string_new("");
@@ -532,11 +633,14 @@
             // Create a new pipeline with the specified filename
             g_string_printf(keypress_filename, "%s/%s", SOUNDS_DATA_PATH, audio_config_cmd->filename);
             keypress_audio_pipeline = create_pipeline(keypress_filename->str, &keypress_volume_control);
+            s_keypress_audio_pipeline.pipeline = keypress_audio_pipeline;
+            s_keypress_audio_pipeline.pipeline_id = AUDIO_PIPELINE_KEYPRESS;
+
             if(keypress_audio_pipeline != NULL)
             {
 #ifdef G_OS_UNIX
               bus = gst_element_get_bus(GST_ELEMENT(keypress_audio_pipeline));
-              keypress_callback_source_id = gst_bus_add_watch(bus, bus_callback, keypress_audio_pipeline);
+              keypress_callback_source_id = gst_bus_add_watch(bus, bus_callback, &s_keypress_audio_pipeline);
               gst_object_unref(bus);
 #endif
             }
@@ -570,7 +674,7 @@
           //g_get_current_time(&current_time);
           //s_debug(TRUE, "Play:      %d.%06d", current_time.tv_sec, current_time.tv_usec);
           if(keypress_audio_pipeline != NULL)
-            play_pipeline(keypress_audio_pipeline);
+            play_pipeline(&s_keypress_audio_pipeline);
           g_slice_free(audio_command_t, audio_cmd);
           break;

@@ -604,11 +708,14 @@
             // Create a new pipeline with the specified filename
             g_string_printf(alert_filename, "%s/%s", SOUNDS_DATA_PATH, audio_config_cmd->filename);
             alert_audio_pipeline = create_pipeline(alert_filename->str, &alert_volume_control);
+            s_alert_audio_pipeline.pipeline = alert_audio_pipeline;
+            s_alert_audio_pipeline.pipeline_id = AUDIO_PIPELINE_ALERT;
+
             if(alert_audio_pipeline != NULL)
             {
 #ifdef G_OS_UNIX
               bus = gst_element_get_bus(GST_ELEMENT(alert_audio_pipeline));
-              gst_bus_add_watch(bus, bus_callback, alert_audio_pipeline);
+              gst_bus_add_watch(bus, bus_callback, &s_alert_audio_pipeline);
               gst_object_unref(bus);
 #endif
             }
@@ -642,7 +749,7 @@
         // Test audible alert
         case AUDIO_ALERT_TEST:
           if(alert_audio_pipeline != NULL)
-            play_pipeline(alert_audio_pipeline);
+            play_pipeline(&s_alert_audio_pipeline);
           g_slice_free(audio_command_t, audio_cmd);
           break;

@@ -690,11 +797,14 @@
             // Create a new pipeline with the specified filename
             g_string_printf(alarm_filename, "%s/%s", SOUNDS_DATA_PATH, audio_config_cmd->filename);
             alarm_audio_pipeline = create_pipeline(alarm_filename->str, &alarm_volume_control);
+            s_alarm_audio_pipeline.pipeline = alarm_audio_pipeline;
+            s_alarm_audio_pipeline.pipeline_id = AUDIO_PIPELINE_ALARM;
+
             if(alarm_audio_pipeline != NULL)
             {
 #ifdef G_OS_UNIX
               bus = gst_element_get_bus(GST_ELEMENT(alarm_audio_pipeline));
-              gst_bus_add_watch(bus, bus_callback, alarm_audio_pipeline);
+              gst_bus_add_watch(bus, bus_callback, &s_alarm_audio_pipeline);
               gst_object_unref(bus);
 #endif
             }
@@ -728,7 +838,7 @@
         // Test audible alarm
         case AUDIO_ALARM_TEST:
           if(alarm_audio_pipeline != NULL)
-            play_pipeline(alarm_audio_pipeline);
+            play_pipeline(&s_alarm_audio_pipeline);
           g_slice_free(audio_command_t, audio_cmd);
           break;

@@ -817,10 +927,11 @@
                              record_volume_level, NULL);

               // Disable the speaker audio amplifier to reduce noise.
-              gpio_set(PP_GPIO_SPEAKER_AMP_DISABLE, 1);
+              // speaker_control(s_record_audio_pipeline.pipeline_id, FALSE);

               // Start the recording
-              play_pipeline(record_audio_pipeline);
+              s_debug(1, "CLIFF: starting record pipeline");
+              play_pipeline(&s_record_audio_pipeline);
             }
             else
             {
@@ -871,7 +982,7 @@

           // Enable the speaker audio amplifier.  It is disabled during
           //   recording to reduce noise.
-          gpio_set(PP_GPIO_SPEAKER_AMP_DISABLE, 0);
+          speaker_control(s_record_audio_pipeline.pipeline_id, TRUE);

           // Notify the GUI thread
           if(recording_callback_function != NULL)
@@ -908,20 +1019,23 @@

             // Create the audio pipeline to play back the recording
             playback_audio_pipeline = create_pipeline(audio_recording_cmd->filename->str, &playback_volume_control);
+            s_playback_audio_pipeline.pipeline = playback_audio_pipeline;
+            s_playback_audio_pipeline.pipeline_id = AUDIO_PIPELINE_PLAYBACK;
+
             if(playback_audio_pipeline != NULL)
             {
 #ifdef G_OS_UNIX
               // Add a callback to the bus so we know when the end of the
               //   stream is reached.
               bus = gst_element_get_bus(GST_ELEMENT(playback_audio_pipeline));
-              playback_callback_source_id = gst_bus_add_watch(bus, playback_bus_callback, playback_audio_pipeline);
+              playback_callback_source_id = gst_bus_add_watch(bus, playback_bus_callback, &s_playback_audio_pipeline);
               gst_object_unref(bus);
 #endif
               // Set the volume for the playback
               if(playback_volume_control != NULL)
                 g_object_set(G_OBJECT(playback_volume_control), "volume",
                              playback_volume_level, NULL);
-              play_pipeline(playback_audio_pipeline);
+              play_pipeline(&s_playback_audio_pipeline);
             }
             else
             {
@@ -953,7 +1067,7 @@
                               + (current_time.tv_usec - last_alarm_start_time.tv_usec)/(1e6));
       if(alarm_cycle_period > 0 && (elapsed_time < 0 || elapsed_time >= alarm_cycle_period))
       {
-        if(play_pipeline(alarm_audio_pipeline) == TRUE)
+        if(play_pipeline(&s_alarm_audio_pipeline) == TRUE)
         {
           g_get_current_time(&last_alarm_start_time);
           // Save the current time as the last alert time also in case we
@@ -974,7 +1088,7 @@
                               + (current_time.tv_usec - last_alert_start_time.tv_usec)/(1e6));
       if(alert_cycle_period > 0 && (elapsed_time < 0 || elapsed_time >= alert_cycle_period))
       {
-        if(play_pipeline(alert_audio_pipeline) == TRUE)
+        if(play_pipeline(&s_alert_audio_pipeline) == TRUE)
         {
           g_get_current_time(&last_alert_start_time);
           // Save the current time as the last alarm time also in case we