rendered paste bodysGUI$ 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, ¤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