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; ipipeline; 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, ¤t_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(¤t_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