From 2b939453598cc1fd8f1c40e5d6cbfd63cb852fb4 Mon Sep 17 00:00:00 2001 From: charles kerr Date: Fri, 1 Jan 2016 13:53:48 -0600 Subject: use gstreamer to play the sound --- CMakeLists.txt | 1 + src/notifier.c | 4 ++- src/sound.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- src/sound.h | 2 +- 4 files changed, 83 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9cc29fe..927a0bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,6 +56,7 @@ pkg_check_modules(SERVICE_DEPS REQUIRED gio-2.0>=2.36 gio-unix-2.0>=2.36 libnotify>=0.7.6 + gstreamer-1.0>=1.2 libayatana-common>=0.9.1) include_directories (SYSTEM ${SERVICE_DEPS_INCLUDE_DIRS}) diff --git a/src/notifier.c b/src/notifier.c index 47690ca..63e7c89 100644 --- a/src/notifier.c +++ b/src/notifier.c @@ -149,7 +149,9 @@ play_low_battery_sound (void) filename = datafile_find(DATAFILE_TYPE_SOUND, key); if (filename != NULL) { - sound_play_file(filename); + gchar * uri = g_filename_to_uri(filename, NULL, NULL); + sound_play_uri(uri); + g_free(uri); g_free(filename); } else diff --git a/src/sound.c b/src/sound.c index d92aee8..37c2a8d 100644 --- a/src/sound.c +++ b/src/sound.c @@ -19,11 +19,86 @@ #include "sound.h" -#include +#include + +#include + +static void +gst_init_once(void) +{ + static gboolean gst_init_checked = FALSE; + + if (G_UNLIKELY(!gst_init_checked)) + { + GError* error = NULL; + if (!gst_init_check(NULL, NULL, &error)) + { + g_critical("Unable to play alarm sound: %s", error->message); + g_error_free(error); + } + gst_init_checked = TRUE; + } +} + +static gboolean bus_callback(GstBus* bus G_GNUC_UNUSED, GstMessage* msg, gpointer gelement) +{ + const GstMessageType message_type = GST_MESSAGE_TYPE(msg); + + if (GST_MESSAGE_SRC(msg) != gelement) + return G_SOURCE_CONTINUE; + + /* on eos, cleanup the element and cancel our gst bus subscription */ + if (message_type == GST_MESSAGE_EOS) + { + g_debug("got GST_MESSAGE_EOS on sound play"); + gst_element_set_state(GST_ELEMENT(gelement), GST_STATE_NULL); + gst_object_unref(gelement); + return G_SOURCE_REMOVE; + } + + /* on stream start, set the media role to 'alert' if we're using pulsesink */ + if (message_type == GST_MESSAGE_STREAM_START) + { + GstElement* audio_sink = NULL; + g_debug("got GST_MESSAGE_STREAM_START on sound play"); + g_object_get(gelement, "audio-sink", &audio_sink, NULL); + if (audio_sink != NULL) + { + GstPluginFeature* feature; + feature = GST_PLUGIN_FEATURE_CAST(GST_ELEMENT_GET_CLASS(audio_sink)->elementfactory); + if (feature && g_strcmp0(gst_plugin_feature_get_name(feature), "pulsesink") == 0) + { + const gchar* const props_str = "props,media.role=alert"; + GstStructure* props = gst_structure_from_string(props_str, NULL); + g_debug("setting audio sink properties to '%s'", props_str); + g_object_set(audio_sink, "stream-properties", props, NULL); + g_clear_pointer(&props, gst_structure_free); + } + gst_object_unref(audio_sink); + } + } + + return G_SOURCE_CONTINUE; +} void -sound_play_file(const char* filename) +sound_play_uri(const char* uri) { - g_message("playing sound '%s'", filename); + GstElement * element; + GstBus * bus; + + gst_init_once(); + + element = gst_element_factory_make("playbin", NULL); + + /* start listening for gst events */ + bus = gst_pipeline_get_bus(GST_PIPELINE(element)); + gst_bus_add_watch(bus, bus_callback, element); + gst_object_unref(bus); + + /* play the sound */ + g_debug("Playing '%s'", uri); + g_object_set(element, "uri", uri, NULL); + gst_element_set_state(element, GST_STATE_PLAYING); } diff --git a/src/sound.h b/src/sound.h index a241e5d..f201fe9 100644 --- a/src/sound.h +++ b/src/sound.h @@ -24,7 +24,7 @@ G_BEGIN_DECLS -void sound_play_file(const char* filename); +void sound_play_uri(const char* uri); G_END_DECLS -- cgit v1.2.3