From 6fbccd32e945d5499d0bb06812ef0c129e621c95 Mon Sep 17 00:00:00 2001 From: charles kerr Date: Fri, 1 Jan 2016 12:09:52 -0600 Subject: add 'Low battery.ogg' --- data/CMakeLists.txt | 11 +++++++++++ data/Low battery.ogg | Bin 0 -> 71140 bytes 2 files changed, 11 insertions(+) create mode 100644 data/Low battery.ogg diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt index e15a81e..d6ffb35 100644 --- a/data/CMakeLists.txt +++ b/data/CMakeLists.txt @@ -68,3 +68,14 @@ set (AYATANA_INDICATOR_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${AYATANA_INDICATOR_NAM install (FILES "${AYATANA_INDICATOR_FILE}" DESTINATION "${AYATANA_INDICATOR_DIR}") + +## +## Sounds +## + +# where to install +set (SOUNDS_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/${CMAKE_PROJECT_NAME}/sounds") +message (STATUS "${SOUNDS_DIR} is the Sound install dir") + +install (FILES "Low battery.ogg" + DESTINATION "${SOUNDS_DIR}") diff --git a/data/Low battery.ogg b/data/Low battery.ogg new file mode 100644 index 0000000..f6f9fb6 Binary files /dev/null and b/data/Low battery.ogg differ -- cgit v1.2.3 From 522fdc6abbfee52dec5c6b0194cf87ffcc0f3dcd Mon Sep 17 00:00:00 2001 From: Marc Deslauriers Date: Tue, 2 Jun 2015 19:18:22 -0400 Subject: Don't prioritize discharging items with no time estimate that have more than 10% power remaining. Devices with no time estimates are most likely low-power devices that have long-lasting batteries, such as a mouse with AA batteries. For those type of devices that contain batteries that last weeks, there is no value in displaying their status in preference to devices that have a rapid charge/discharge cycle. However, there is value in knowing if the device has a battery that needs replacing imminently, so only display it if it falls to a 10% charge or under. --- src/service.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/service.c b/src/service.c index c93c4b6..73fcf46 100644 --- a/src/service.c +++ b/src/service.c @@ -162,12 +162,12 @@ get_device_kind_weight (const IndicatorPowerDevice * device) } /* sort devices from most interesting to least interesting on this criteria: - 1. device that supplied the power to the system - 2. discharging items from least time remaining until most time remaining - 3. charging items from most time left to charge to least time left to charge - 4. charging items with an unknown time remaining - 5. discharging items with an unknown time remaining - 6. batteries, then non-line power, then line-power */ + 1. discharging items from least time remaining until most time remaining + 2. charging items from most time left to charge to least time left to charge + 3. charging items with an unknown time remaining + 4. discharging items with an unknown time remaining, but 10% or below + 5. batteries, then non-line power, then line-power + 6. discharging items with an unknown time remaining, but above 10% */ static gint device_compare_func (gconstpointer ga, gconstpointer gb) { @@ -199,6 +199,14 @@ device_compare_func (gconstpointer ga, gconstpointer gb) } state = UP_DEVICE_STATE_DISCHARGING; + + /* discharging items with more than 10% remaining always lose */ + if (!ret && (((a_state == state) && !a_time && (a_percentage > 10)))) + ret = 1; + + if (!ret && (((b_state == state) && !b_time && (b_percentage > 10)))) + ret = -1; + if (!ret && (((a_state == state) && a_time) || ((b_state == state) && b_time))) { -- cgit v1.2.3 From c5f9fe4e21d24581aad7bfd7b73fb060aaf440ff Mon Sep 17 00:00:00 2001 From: charles kerr Date: Fri, 1 Jan 2016 12:14:40 -0600 Subject: add an XDG friendly way of finding app-specific datafiles --- src/CMakeLists.txt | 1 + src/datafiles.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/datafiles.h | 37 ++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 src/datafiles.c create mode 100644 src/datafiles.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fb8ffef..b68619c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,6 +10,7 @@ endif() # handwritten sources set(SERVICE_MANUAL_SOURCES brightness.c + datafiles.c device-provider-mock.c device-provider-upower.c device-provider.c diff --git a/src/datafiles.c b/src/datafiles.c new file mode 100644 index 0000000..dba8048 --- /dev/null +++ b/src/datafiles.c @@ -0,0 +1,71 @@ +/* + * Copyright 2015 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#include "datafiles.h" + +static const gchar* +get_directory_prefix_for_type (DatafileType type) +{ + switch (type) + { + case DATAFILE_TYPE_SOUND: + return "sounds"; + + default: + g_critical("unknown type"); + return ""; + } +} + +static gchar* +test_directory_for_file(const char* dir, DatafileType type, const char* basename) +{ + gchar* filename = g_build_filename(dir, + GETTEXT_PACKAGE, + get_directory_prefix_for_type(type), + basename, + NULL); + + g_debug("looking for \"%s\" at \"%s\"", basename, filename); + if (g_file_test(filename, G_FILE_TEST_EXISTS)) + return filename; + + g_free(filename); + return NULL; +} + +gchar* +datafile_find(DatafileType type, const char * basename) +{ + gchar * filename; + const gchar * user_data_dir; + const gchar * const * system_data_dirs; + gsize i; + + user_data_dir = g_get_user_data_dir(); + if ((filename = test_directory_for_file(user_data_dir, type, basename))) + return filename; + + system_data_dirs = g_get_system_data_dirs(); + for (i=0; system_data_dirs && system_data_dirs[i]; ++i) + if ((filename = test_directory_for_file(system_data_dirs[i], type, basename))) + return filename; + + return NULL; +} diff --git a/src/datafiles.h b/src/datafiles.h new file mode 100644 index 0000000..f624b9c --- /dev/null +++ b/src/datafiles.h @@ -0,0 +1,37 @@ +/* + * Copyright 2015 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#ifndef __INDICATOR_POWER_DATAFILES_H__ +#define __INDICATOR_POWER_DATAFILES_H__ + +#include + +G_BEGIN_DECLS + +typedef enum +{ + DATAFILE_TYPE_SOUND +} +DatafileType; + +gchar* datafile_find(DatafileType type, const char * basename); + +G_END_DECLS + +#endif /* __INDICATOR_POWER_DATAFILES_H__ */ -- cgit v1.2.3 From 4fc7a4e4d0346e1aad32057536301620e138bf30 Mon Sep 17 00:00:00 2001 From: charles kerr Date: Fri, 1 Jan 2016 12:34:41 -0600 Subject: add logic to call sound_play_file() when the low battery notification is shown --- src/CMakeLists.txt | 3 ++- src/notifier.c | 30 ++++++++++++++++++++++++++++++ src/sound.c | 29 +++++++++++++++++++++++++++++ src/sound.h | 31 +++++++++++++++++++++++++++++++ 4 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 src/sound.c create mode 100644 src/sound.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b68619c..ed0e0ff 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -19,7 +19,8 @@ set(SERVICE_MANUAL_SOURCES notifier.c testing.c service.c - utils.c) + utils.c + sound.c) # generated sources include(GdbusCodegen) diff --git a/src/notifier.c b/src/notifier.c index 123ee6f..47690ca 100644 --- a/src/notifier.c +++ b/src/notifier.c @@ -17,10 +17,16 @@ * Charles Kerr */ +#include "datafiles.h" #include "dbus-battery.h" #include "dbus-shared.h" #include "notifier.h" #include "utils.h" +#include "sound.h" + +#ifdef HAS_URLDISPATCHER +# include +#endif #include @@ -129,6 +135,29 @@ get_battery_power_level (IndicatorPowerDevice * battery) return ret; } +/*** +**** Sounds +***/ + +static void +play_low_battery_sound (void) +{ + const gchar * key; + gchar * filename; + + key = "Low battery.ogg"; + filename = datafile_find(DATAFILE_TYPE_SOUND, key); + if (filename != NULL) + { + sound_play_file(filename); + g_free(filename); + } + else + { + g_warning("Unable to find '%s' in XDG data dirs", key); + } +} + /*** **** Notifications ***/ @@ -299,6 +328,7 @@ on_battery_property_changed (IndicatorPowerNotifier * self) ((new_power_level != POWER_LEVEL_OK) && new_discharging && !old_discharging)) { notification_show (self); + play_low_battery_sound(); } else if (!new_discharging || (new_power_level == POWER_LEVEL_OK)) { diff --git a/src/sound.c b/src/sound.c new file mode 100644 index 0000000..d92aee8 --- /dev/null +++ b/src/sound.c @@ -0,0 +1,29 @@ +/* + * Copyright 2015 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#include "sound.h" + +#include + +void +sound_play_file(const char* filename) +{ + g_message("playing sound '%s'", filename); +} + diff --git a/src/sound.h b/src/sound.h new file mode 100644 index 0000000..a241e5d --- /dev/null +++ b/src/sound.h @@ -0,0 +1,31 @@ +/* + * Copyright 2015 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#ifndef __INDICATOR_POWER_SOUND_H__ +#define __INDICATOR_POWER_SOUND_H__ + +#include + +G_BEGIN_DECLS + +void sound_play_file(const char* filename); + +G_END_DECLS + +#endif /* __INDICATOR_POWER_SOUND_H__ */ -- cgit v1.2.3 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 From a8fd3f49bf6509bd4545aec3292d2fc022d847ca Mon Sep 17 00:00:00 2001 From: charles kerr Date: Fri, 1 Jan 2016 15:58:55 -0600 Subject: make a SoundPlayer interface so we can mock it in the tests this requires an annoying amount of scaffolding: 1. implement gst and mock classes to implement the SoundPlayer interface 2. modify notifier to take a SoundPlayer argument in its ctor 3. modify service to take a Notifier argument in its ctor instead of instantiating it on its own 4. change main to update the startup steps for player/notifier/service --- src/CMakeLists.txt | 4 +- src/main.c | 12 +++- src/notifier.c | 61 ++++++++++++++--- src/notifier.h | 6 +- src/service.c | 38 +++++++++-- src/service.h | 7 +- src/sound-player-gst.c | 173 ++++++++++++++++++++++++++++++++++++++++++++++++ src/sound-player-gst.h | 70 ++++++++++++++++++++ src/sound-player-mock.c | 94 ++++++++++++++++++++++++++ src/sound-player-mock.h | 75 +++++++++++++++++++++ src/sound-player.c | 45 +++++++++++++ src/sound-player.h | 72 ++++++++++++++++++++ src/sound.c | 104 ----------------------------- src/sound.h | 31 --------- 14 files changed, 639 insertions(+), 153 deletions(-) create mode 100644 src/sound-player-gst.c create mode 100644 src/sound-player-gst.h create mode 100644 src/sound-player-mock.c create mode 100644 src/sound-player-mock.h create mode 100644 src/sound-player.c create mode 100644 src/sound-player.h delete mode 100644 src/sound.c delete mode 100644 src/sound.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ed0e0ff..c99ce46 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -20,7 +20,9 @@ set(SERVICE_MANUAL_SOURCES testing.c service.c utils.c - sound.c) + sound-player.c + sound-player-gst.c + sound-player-mock.c) # generated sources include(GdbusCodegen) diff --git a/src/main.c b/src/main.c index 03e100d..2837b59 100644 --- a/src/main.c +++ b/src/main.c @@ -23,7 +23,9 @@ #include #include "device.h" +#include "notifier.h" #include "service.h" +#include "sound-player-gst.h" #include "testing.h" /*** @@ -40,6 +42,8 @@ on_name_lost (gpointer instance G_GNUC_UNUSED, gpointer loop) int main (int argc G_GNUC_UNUSED, char ** argv G_GNUC_UNUSED) { + IndicatorPowerSoundPlayer * sound_player; + IndicatorPowerNotifier * notifier; IndicatorPowerService * service; IndicatorPowerTesting * testing; GMainLoop * loop; @@ -50,7 +54,9 @@ main (int argc G_GNUC_UNUSED, char ** argv G_GNUC_UNUSED) textdomain (GETTEXT_PACKAGE); /* run */ - service = indicator_power_service_new (NULL); + sound_player = indicator_power_sound_player_gst_new (); + notifier = indicator_power_notifier_new (sound_player); + service = indicator_power_service_new(NULL, notifier); testing = indicator_power_testing_new (service); loop = g_main_loop_new (NULL, FALSE); g_signal_connect (service, INDICATOR_POWER_SERVICE_SIGNAL_NAME_LOST, @@ -59,7 +65,9 @@ main (int argc G_GNUC_UNUSED, char ** argv G_GNUC_UNUSED) /* cleanup */ g_main_loop_unref (loop); - g_clear_object (&service); g_clear_object (&testing); + g_clear_object (&service); + g_clear_object (¬ifier); + g_clear_object (&sound_player); return 0; } diff --git a/src/notifier.c b/src/notifier.c index 63e7c89..b50f48c 100644 --- a/src/notifier.c +++ b/src/notifier.c @@ -22,10 +22,10 @@ #include "dbus-shared.h" #include "notifier.h" #include "utils.h" -#include "sound.h" +#include "sound-player.h" #ifdef HAS_URLDISPATCHER -# include +#include #endif #include @@ -51,10 +51,12 @@ enum { PROP_0, PROP_BATTERY, + PROP_SOUND_PLAYER, LAST_PROP }; #define PROP_BATTERY_NAME "battery" +#define PROP_SOUND_PLAYER_NAME "sound-player" static GParamSpec * properties[LAST_PROP]; @@ -82,6 +84,8 @@ typedef struct gboolean caps_queried; gboolean actions_supported; + + IndicatorPowerSoundPlayer * sound_player; } IndicatorPowerNotifierPrivate; @@ -140,17 +144,19 @@ get_battery_power_level (IndicatorPowerDevice * battery) ***/ static void -play_low_battery_sound (void) +play_low_battery_sound (IndicatorPowerNotifier * self) { - const gchar * key; + const gchar * const key = "Low battery.ogg"; gchar * filename; + priv_t * const p = get_priv(self); + + g_return_if_fail (p->sound_player != NULL); - key = "Low battery.ogg"; filename = datafile_find(DATAFILE_TYPE_SOUND, key); if (filename != NULL) { gchar * uri = g_filename_to_uri(filename, NULL, NULL); - sound_play_uri(uri); + indicator_power_sound_player_play_uri (p->sound_player, uri); g_free(uri); g_free(filename); } @@ -330,7 +336,7 @@ on_battery_property_changed (IndicatorPowerNotifier * self) ((new_power_level != POWER_LEVEL_OK) && new_discharging && !old_discharging)) { notification_show (self); - play_low_battery_sound(); + play_low_battery_sound (self); } else if (!new_discharging || (new_power_level == POWER_LEVEL_OK)) { @@ -361,6 +367,10 @@ my_get_property (GObject * o, g_value_set_object (value, p->battery); break; + case PROP_SOUND_PLAYER: + g_value_set_object (value, p->sound_player); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec); } @@ -380,6 +390,10 @@ my_set_property (GObject * o, indicator_power_notifier_set_battery (self, g_value_get_object(value)); break; + case PROP_SOUND_PLAYER: + indicator_power_notifier_set_sound_player (self, g_value_get_object(value)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec); } @@ -446,6 +460,13 @@ indicator_power_notifier_class_init (IndicatorPowerNotifierClass * klass) G_TYPE_OBJECT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + properties[PROP_SOUND_PLAYER] = g_param_spec_object ( + PROP_SOUND_PLAYER_NAME, + "Sound Player", + "The current battery", + G_TYPE_OBJECT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (object_class, LAST_PROP, properties); } @@ -454,9 +475,11 @@ indicator_power_notifier_class_init (IndicatorPowerNotifierClass * klass) ***/ IndicatorPowerNotifier * -indicator_power_notifier_new (void) +indicator_power_notifier_new (IndicatorPowerSoundPlayer * sound_player) { - GObject * o = g_object_new (INDICATOR_TYPE_POWER_NOTIFIER, NULL); + GObject * o = g_object_new (INDICATOR_TYPE_POWER_NOTIFIER, + PROP_SOUND_PLAYER_NAME, sound_player, + NULL); return INDICATOR_POWER_NOTIFIER (o); } @@ -495,6 +518,26 @@ indicator_power_notifier_set_battery (IndicatorPowerNotifier * self, } } +void +indicator_power_notifier_set_sound_player (IndicatorPowerNotifier * self, + IndicatorPowerSoundPlayer * sound_player) +{ + priv_t * p; + + g_return_if_fail(INDICATOR_IS_POWER_NOTIFIER(self)); + g_return_if_fail((sound_player == NULL) || INDICATOR_IS_POWER_SOUND_PLAYER(sound_player)); + + p = get_priv (self); + + if (p->sound_player == sound_player) + return; + + g_clear_object(&p->sound_player); + + if (sound_player != NULL) + p->sound_player = g_object_ref(sound_player); +} + void indicator_power_notifier_set_bus (IndicatorPowerNotifier * self, GDBusConnection * bus) diff --git a/src/notifier.h b/src/notifier.h index 18e25d7..9625c07 100644 --- a/src/notifier.h +++ b/src/notifier.h @@ -23,6 +23,7 @@ #include #include "device.h" +#include "sound-player.h" G_BEGIN_DECLS @@ -55,7 +56,7 @@ struct _IndicatorPowerNotifierClass GType indicator_power_notifier_get_type (void); -IndicatorPowerNotifier * indicator_power_notifier_new (void); +IndicatorPowerNotifier * indicator_power_notifier_new (IndicatorPowerSoundPlayer * sound_player); void indicator_power_notifier_set_bus (IndicatorPowerNotifier * self, GDBusConnection * connection); @@ -63,6 +64,9 @@ void indicator_power_notifier_set_bus (IndicatorPowerNotifier * self, void indicator_power_notifier_set_battery (IndicatorPowerNotifier * self, IndicatorPowerDevice * battery); +void indicator_power_notifier_set_sound_player (IndicatorPowerNotifier * self, + IndicatorPowerSoundPlayer * battery); + #define POWER_LEVEL_STR_OK "ok" #define POWER_LEVEL_STR_LOW "low" #define POWER_LEVEL_STR_VERY_LOW "very_low" diff --git a/src/service.c b/src/service.c index 73fcf46..07f1106 100644 --- a/src/service.c +++ b/src/service.c @@ -52,6 +52,7 @@ enum PROP_0, PROP_BUS, PROP_DEVICE_PROVIDER, + PROP_NOTIFIER, LAST_PROP }; @@ -976,7 +977,8 @@ on_bus_acquired (GDBusConnection * connection, g_object_notify_by_pspec (G_OBJECT(self), properties[PROP_BUS]); /* export the battery properties */ - indicator_power_notifier_set_bus (p->notifier, connection); + if (p->notifier != NULL) + indicator_power_notifier_set_bus (p->notifier, connection); /* export the actions */ if ((id = g_dbus_connection_export_action_group (connection, @@ -1118,6 +1120,10 @@ my_get_property (GObject * o, g_value_set_object (value, p->device_provider); break; + case PROP_NOTIFIER: + g_value_set_object (value, p->notifier); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec); } @@ -1137,6 +1143,10 @@ my_set_property (GObject * o, indicator_power_service_set_device_provider (self, g_value_get_object (value)); break; + case PROP_NOTIFIER: + indicator_power_service_set_notifier (self, g_value_get_object (value)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec); } @@ -1179,6 +1189,7 @@ my_dispose (GObject * o) g_clear_object (&p->conn); indicator_power_service_set_device_provider (self, NULL); + indicator_power_service_set_notifier (self, NULL); G_OBJECT_CLASS (indicator_power_service_parent_class)->dispose (o); } @@ -1200,8 +1211,6 @@ indicator_power_service_init (IndicatorPowerService * self) p->settings = g_settings_new ("org.ayatana.indicator.power"); - p->notifier = indicator_power_notifier_new (); - p->brightness = indicator_power_brightness_new(); g_signal_connect_swapped(p->brightness, "notify::percentage", G_CALLBACK(update_brightness_action_state), self); @@ -1269,10 +1278,12 @@ indicator_power_service_class_init (IndicatorPowerServiceClass * klass) ***/ IndicatorPowerService * -indicator_power_service_new (IndicatorPowerDeviceProvider * device_provider) +indicator_power_service_new (IndicatorPowerDeviceProvider * device_provider, + IndicatorPowerNotifier * notifier) { GObject * o = g_object_new (INDICATOR_TYPE_POWER_SERVICE, "device-provider", device_provider, + "notifier", notifier, NULL); return INDICATOR_POWER_SERVICE (o); @@ -1311,6 +1322,25 @@ indicator_power_service_set_device_provider (IndicatorPowerService * self, } } +void +indicator_power_service_set_notifier (IndicatorPowerService * self, + IndicatorPowerNotifier * notifier) +{ + priv_t * p; + + g_return_if_fail (INDICATOR_IS_POWER_SERVICE (self)); + g_return_if_fail (!notifier || INDICATOR_IS_POWER_NOTIFIER (notifier)); + p = self->priv; + + if (p->notifier != notifier) + { + g_clear_object (&p->notifier); + p->notifier = g_object_ref (notifier); + indicator_power_notifier_set_bus (p->notifier, p->conn); + } +} + + /* If a device has multiple batteries and uses only one of them at a time, they should be presented as separate items inside the battery menu, but everywhere else they should be aggregated (bug 880881). diff --git a/src/service.h b/src/service.h index 76ed10f..00ed3e6 100644 --- a/src/service.h +++ b/src/service.h @@ -24,6 +24,7 @@ #include #include "device-provider.h" +#include "notifier.h" G_BEGIN_DECLS @@ -64,11 +65,15 @@ struct _IndicatorPowerServiceClass GType indicator_power_service_get_type (void); -IndicatorPowerService * indicator_power_service_new (IndicatorPowerDeviceProvider * provider); +IndicatorPowerService * indicator_power_service_new (IndicatorPowerDeviceProvider * provider, + IndicatorPowerNotifier * notifier); void indicator_power_service_set_device_provider (IndicatorPowerService * self, IndicatorPowerDeviceProvider * provider); +void indicator_power_service_set_notifier (IndicatorPowerService * self, + IndicatorPowerNotifier * notifier); + IndicatorPowerDevice * indicator_power_service_choose_primary_device (GList * devices); diff --git a/src/sound-player-gst.c b/src/sound-player-gst.c new file mode 100644 index 0000000..9b3f11a --- /dev/null +++ b/src/sound-player-gst.c @@ -0,0 +1,173 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "sound-player.h" +#include "sound-player-gst.h" + +#include + + +/*** +**** private struct +***/ + +typedef struct +{ + int unused; +} +IndicatorPowerSoundPlayerGSTPrivate; + +typedef IndicatorPowerSoundPlayerGSTPrivate priv_t; + +#define get_priv(o) ((priv_t*)indicator_power_sound_player_gst_get_instance_private(o)) + + +/*** +**** GObject boilerplate +***/ + +static void indicator_power_device_provider_interface_init ( + IndicatorPowerSoundPlayerInterface * iface); + +G_DEFINE_TYPE_WITH_CODE ( + IndicatorPowerSoundPlayerGST, + indicator_power_sound_player_gst, + G_TYPE_OBJECT, + G_ADD_PRIVATE(IndicatorPowerSoundPlayerGST) + G_IMPLEMENT_INTERFACE (INDICATOR_TYPE_POWER_SOUND_PLAYER, + indicator_power_device_provider_interface_init)) + +/*** +**** GSTREAMER +***/ + +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; +} + +/*** +**** IndicatorPowerSoundPlayer virtual functions +***/ + +static void +my_play_uri (IndicatorPowerSoundPlayer * self G_GNUC_UNUSED, const gchar * uri) +{ + GstElement * element; + GstBus * bus; + + /* create the element */ + 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); +} + +/*** +**** Instantiation +***/ + +static void +indicator_power_sound_player_gst_class_init (IndicatorPowerSoundPlayerGSTClass * klass) +{ + gst_init_once(); +} + +static void +indicator_power_device_provider_interface_init (IndicatorPowerSoundPlayerInterface * iface) +{ + iface->play_uri = my_play_uri; +} + +static void +indicator_power_sound_player_gst_init (IndicatorPowerSoundPlayerGST * self G_GNUC_UNUSED) +{ +} + +/*** +**** Public API +***/ + +IndicatorPowerSoundPlayer * +indicator_power_sound_player_gst_new(void) +{ + gpointer o = g_object_new (INDICATOR_TYPE_POWER_SOUND_PLAYER_GST, NULL); + + return INDICATOR_POWER_SOUND_PLAYER (o); +} diff --git a/src/sound-player-gst.h b/src/sound-player-gst.h new file mode 100644 index 0000000..6ef8866 --- /dev/null +++ b/src/sound-player-gst.h @@ -0,0 +1,70 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#ifndef __INDICATOR_POWER_SOUND_PLAYER_GST__H__ +#define __INDICATOR_POWER_SOUND_PLAYER_GST__H__ + +#include /* parent class */ + +#include "device-provider.h" + +G_BEGIN_DECLS + +#define INDICATOR_TYPE_POWER_SOUND_PLAYER_GST \ + (indicator_power_sound_player_gst_get_type()) + +#define INDICATOR_POWER_SOUND_PLAYER_GST(o) \ + (G_TYPE_CHECK_INSTANCE_CAST ((o), \ + INDICATOR_TYPE_POWER_SOUND_PLAYER_GST, \ + IndicatorPowerSoundPlayerGST)) + +#define INDICATOR_POWER_SOUND_PLAYER_GST_GET_CLASS(o) \ + (G_TYPE_INSTANCE_GET_CLASS ((o), \ + INDICATOR_TYPE_POWER_SOUND_PLAYER_GST, \ + IndicatorPowerSoundPlayerGSTClass)) + +#define INDICATOR_IS_POWER_SOUND_PLAYER_GST(o) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((o), \ + INDICATOR_TYPE_POWER_SOUND_PLAYER_GST)) + +typedef struct _IndicatorPowerSoundPlayerGST + IndicatorPowerSoundPlayerGST; +typedef struct _IndicatorPowerSoundPlayerGSTClass + IndicatorPowerSoundPlayerGSTClass; + +/** + * An IndicatorPowerSoundPlayer which gets its devices from GST. + */ +struct _IndicatorPowerSoundPlayerGST +{ + GObject parent_instance; +}; + +struct _IndicatorPowerSoundPlayerGSTClass +{ + GObjectClass parent_class; +}; + +GType indicator_power_sound_player_gst_get_type (void); + +IndicatorPowerSoundPlayer * indicator_power_sound_player_gst_new (void); + +G_END_DECLS + +#endif /* __INDICATOR_POWER_SOUND_PLAYER_GST__H__ */ diff --git a/src/sound-player-mock.c b/src/sound-player-mock.c new file mode 100644 index 0000000..17eff21 --- /dev/null +++ b/src/sound-player-mock.c @@ -0,0 +1,94 @@ +/* + * Copyright 2014 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#include "sound-player.h" +#include "sound-player-mock.h" + +enum +{ + SIGNAL_URI_PLAYED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +/*** +**** GObject boilerplate +***/ + +static void indicator_power_sound_player_interface_init ( + IndicatorPowerSoundPlayerInterface * iface); + +G_DEFINE_TYPE_WITH_CODE ( + IndicatorPowerSoundPlayerMock, + indicator_power_sound_player_mock, + G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (INDICATOR_TYPE_POWER_SOUND_PLAYER, + indicator_power_sound_player_interface_init)) + +/*** +**** IndicatorPowerSoundPlayer virtual functions +***/ + +static void +my_play_uri (IndicatorPowerSoundPlayer * self, const gchar * uri) +{ + g_signal_emit (self, signals[SIGNAL_URI_PLAYED], 0, uri, NULL); +} + +/*** +**** Instantiation +***/ + +static void +indicator_power_sound_player_mock_class_init (IndicatorPowerSoundPlayerMockClass * klass G_GNUC_UNUSED) +{ + signals[SIGNAL_URI_PLAYED] = g_signal_new ( + "uri-played", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IndicatorPowerSoundPlayerMockClass, uri_played), + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, G_TYPE_STRING); +} + +static void +indicator_power_sound_player_interface_init (IndicatorPowerSoundPlayerInterface * iface) +{ + iface->play_uri = my_play_uri; +} + +static void +indicator_power_sound_player_mock_init (IndicatorPowerSoundPlayerMock * self G_GNUC_UNUSED) +{ +} + +/*** +**** Public API +***/ + +IndicatorPowerSoundPlayer * +indicator_power_sound_player_mock_new (void) +{ + gpointer o = g_object_new (INDICATOR_TYPE_POWER_SOUND_PLAYER_MOCK, NULL); + + return INDICATOR_POWER_SOUND_PLAYER (o); +} + diff --git a/src/sound-player-mock.h b/src/sound-player-mock.h new file mode 100644 index 0000000..f7f2653 --- /dev/null +++ b/src/sound-player-mock.h @@ -0,0 +1,75 @@ +/* + * Copyright 2014 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#ifndef __INDICATOR_POWER_SOUND_PLAYER_MOCK__H__ +#define __INDICATOR_POWER_SOUND_PLAYER_MOCK__H__ + +#include /* parent class */ + +#include "sound-player.h" + +G_BEGIN_DECLS + +#define INDICATOR_TYPE_POWER_SOUND_PLAYER_MOCK \ + (indicator_power_sound_player_mock_get_type()) + +#define INDICATOR_POWER_SOUND_PLAYER_MOCK(o) \ + (G_TYPE_CHECK_INSTANCE_CAST ((o), \ + INDICATOR_TYPE_POWER_SOUND_PLAYER_MOCK, \ + IndicatorPowerSoundPlayerMock)) + +#define INDICATOR_POWER_SOUND_PLAYER_MOCK_GET_CLASS(o) \ + (G_TYPE_INSTANCE_GET_CLASS ((o), \ + INDICATOR_TYPE_POWER_SOUND_PLAYER_MOCK, \ + IndicatorPowerSoundPlayerMockClass)) + +#define INDICATOR_IS_POWER_SOUND_PLAYER_MOCK(o) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((o), \ + INDICATOR_TYPE_POWER_SOUND_PLAYER_MOCK)) + +typedef struct _IndicatorPowerSoundPlayerMock + IndicatorPowerSoundPlayerMock; +typedef struct _IndicatorPowerSoundPlayerMockPriv + IndicatorPowerSoundPlayerMockPriv; +typedef struct _IndicatorPowerSoundPlayerMockClass + IndicatorPowerSoundPlayerMockClass; + +/** + * An IndicatorPowerSoundPlayer which gets its devices from Mock. + */ +struct _IndicatorPowerSoundPlayerMock +{ + GObject parent_instance; +}; + +struct _IndicatorPowerSoundPlayerMockClass +{ + GObjectClass parent_class; + + /* signals */ + void (*uri_played) (IndicatorPowerSoundPlayer * self, const gchar* uri); +}; + +GType indicator_power_sound_player_mock_get_type (void); + +IndicatorPowerSoundPlayer * indicator_power_sound_player_mock_new (void); + +G_END_DECLS + +#endif /* __INDICATOR_POWER_SOUND_PLAYER_MOCK__H__ */ diff --git a/src/sound-player.c b/src/sound-player.c new file mode 100644 index 0000000..f6421ad --- /dev/null +++ b/src/sound-player.c @@ -0,0 +1,45 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "sound-player.h" + +G_DEFINE_INTERFACE (IndicatorPowerSoundPlayer, + indicator_power_sound_player, + 0) + +static void +indicator_power_sound_player_default_init (IndicatorPowerSoundPlayerInterface * klass G_GNUC_UNUSED) +{ +} + +/*** +**** PUBLIC API +***/ + +void +indicator_power_sound_player_play_uri (IndicatorPowerSoundPlayer * self, + const gchar * uri) +{ + IndicatorPowerSoundPlayerInterface * iface; + + g_return_if_fail (INDICATOR_IS_POWER_SOUND_PLAYER (self)); + iface = INDICATOR_POWER_SOUND_PLAYER_GET_INTERFACE (self); + g_return_if_fail (iface->play_uri != NULL); + iface->play_uri (self, uri); +} diff --git a/src/sound-player.h b/src/sound-player.h new file mode 100644 index 0000000..ac7e261 --- /dev/null +++ b/src/sound-player.h @@ -0,0 +1,72 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#ifndef __INDICATOR_POWER_SOUND_PLAYER__H__ +#define __INDICATOR_POWER_SOUND_PLAYER__H__ + +#include + +G_BEGIN_DECLS + +#define INDICATOR_TYPE_POWER_SOUND_PLAYER \ + (indicator_power_sound_player_get_type ()) + +#define INDICATOR_POWER_SOUND_PLAYER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + INDICATOR_TYPE_POWER_SOUND_PLAYER, \ + IndicatorPowerSoundPlayer)) + +#define INDICATOR_IS_POWER_SOUND_PLAYER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INDICATOR_TYPE_POWER_SOUND_PLAYER)) + +#define INDICATOR_POWER_SOUND_PLAYER_GET_INTERFACE(inst) \ + (G_TYPE_INSTANCE_GET_INTERFACE ((inst), \ + INDICATOR_TYPE_POWER_SOUND_PLAYER, \ + IndicatorPowerSoundPlayerInterface)) + +typedef struct _IndicatorPowerSoundPlayer + IndicatorPowerSoundPlayer; + +typedef struct _IndicatorPowerSoundPlayerInterface + IndicatorPowerSoundPlayerInterface; + +/** + * An interface class for an object that plays sounds. + */ +struct _IndicatorPowerSoundPlayerInterface +{ + GTypeInterface parent_iface; + + /* virtual functions */ + void (*play_uri) (IndicatorPowerSoundPlayer * self, + const gchar * uri); +}; + +GType indicator_power_sound_player_get_type (void); + +/*** +**** +***/ + +void indicator_power_sound_player_play_uri (IndicatorPowerSoundPlayer * self, + const gchar * uri); + +G_END_DECLS + +#endif /* __INDICATOR_POWER_SOUND_PLAYER__H__ */ diff --git a/src/sound.c b/src/sound.c deleted file mode 100644 index 37c2a8d..0000000 --- a/src/sound.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2015 Canonical Ltd. - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3, as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - * - * Authors: - * Charles Kerr - */ - -#include "sound.h" - -#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_uri(const char* uri) -{ - 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 deleted file mode 100644 index f201fe9..0000000 --- a/src/sound.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2015 Canonical Ltd. - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3, as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - * - * Authors: - * Charles Kerr - */ - -#ifndef __INDICATOR_POWER_SOUND_H__ -#define __INDICATOR_POWER_SOUND_H__ - -#include - -G_BEGIN_DECLS - -void sound_play_uri(const char* uri); - -G_END_DECLS - -#endif /* __INDICATOR_POWER_SOUND_H__ */ -- cgit v1.2.3 From d7d630dd5b250c4db489d797552129093c0c3ab0 Mon Sep 17 00:00:00 2001 From: charles kerr Date: Fri, 1 Jan 2016 16:08:07 -0600 Subject: add play-sound tests to test-notify --- tests/CMakeLists.txt | 8 ++++++++ tests/test-notify.cc | 34 +++++++++++++++++++++++++++++++--- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 1dc8a8f..96cabb2 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -14,6 +14,14 @@ set_directory_properties (PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES gschemas.compiled) set_source_files_properties (gschemas.compiled GENERATED) +# make a local install of the sounds +set(XDG_DATA_HOME "${CMAKE_CURRENT_BINARY_DIR}/share") +add_definitions(-DXDG_DATA_HOME="${XDG_DATA_HOME}") +file(COPY + DIRECTORY "${CMAKE_SOURCE_DIR}/data/" + DESTINATION "${XDG_DATA_HOME}/${CMAKE_PROJECT_NAME}/sounds" + FILES_MATCHING PATTERN "*.ogg") + # GSettings: # compile the ayatana-indicator-power schema into a gschemas.compiled file in this directory, # and help the tests to find that file by setting -DSCHEMA_DIR diff --git a/tests/test-notify.cc b/tests/test-notify.cc index 63214c2..cfa27bf 100644 --- a/tests/test-notify.cc +++ b/tests/test-notify.cc @@ -23,6 +23,7 @@ #include "dbus-shared.h" #include "device.h" #include "notifier.h" +#include "sound-player-mock.h" #include @@ -77,6 +78,8 @@ protected: { super::SetUp(); + g_setenv ("XDG_DATA_HOME", XDG_DATA_HOME, TRUE); + // init DBusMock / dbus-test-runner service = dbus_test_service_new(nullptr); @@ -275,7 +278,8 @@ TEST_F(NotifyFixture, LevelsDuringBatteryDrain) // set up a notifier and give it the battery so changing the battery's // charge should show up on the bus. - auto notifier = indicator_power_notifier_new (); + auto sound_player = indicator_power_sound_player_mock_new (); + auto notifier = indicator_power_notifier_new (sound_player); indicator_power_notifier_set_battery (notifier, battery); indicator_power_notifier_set_bus (notifier, bus); wait_msec(); @@ -317,14 +321,23 @@ TEST_F(NotifyFixture, LevelsDuringBatteryDrain) // cleanup g_dbus_connection_signal_unsubscribe (bus, sub_tag); - g_object_unref (notifier); g_object_unref (battery); + g_object_unref (notifier); + g_object_unref (sound_player); } /*** **** ***/ +namespace +{ + static void on_uri_played(IndicatorPowerSoundPlayer*, const char* uri, gpointer glast_uri) + { + *static_cast(glast_uri) = uri; + } +} + TEST_F(NotifyFixture, EventsThatChangeNotifications) { // GetCapabilities returns an array containing 'actions', so that we'll @@ -348,7 +361,11 @@ TEST_F(NotifyFixture, EventsThatChangeNotifications) // set up a notifier and give it the battery so changing the battery's // charge should show up on the bus. - auto notifier = indicator_power_notifier_new (); + const std::string low_power_uri {"file://" XDG_DATA_HOME "/" GETTEXT_PACKAGE "/sounds/Low%20battery.ogg"}; + std::string last_uri; + auto sound_player = indicator_power_sound_player_mock_new (); + g_signal_connect(sound_player, "uri-played", G_CALLBACK(on_uri_played), &last_uri); + auto notifier = indicator_power_notifier_new (sound_player); indicator_power_notifier_set_battery (notifier, battery); indicator_power_notifier_set_bus (notifier, bus); ChangedParams changed_params; @@ -366,6 +383,7 @@ TEST_F(NotifyFixture, EventsThatChangeNotifications) // test setup case wait_msec(); EXPECT_STREQ (POWER_LEVEL_STR_OK, changed_params.power_level.c_str()); + EXPECT_TRUE(last_uri.empty()); // change the percent past the 'low' threshold and confirm that // a) the power level changes @@ -376,38 +394,48 @@ TEST_F(NotifyFixture, EventsThatChangeNotifications) EXPECT_EQ (FIELD_POWER_LEVEL|FIELD_IS_WARNING, changed_params.fields); EXPECT_EQ (indicator_power_notifier_get_power_level(battery), changed_params.power_level); EXPECT_TRUE (changed_params.is_warning); + EXPECT_EQ (low_power_uri, last_uri); // now test that the warning changes if the level goes down even lower... + last_uri.clear(); changed_params = ChangedParams(); set_battery_percentage (battery, percent_very_low); wait_msec(); EXPECT_EQ (FIELD_POWER_LEVEL, changed_params.fields); EXPECT_STREQ (POWER_LEVEL_STR_VERY_LOW, changed_params.power_level.c_str()); + EXPECT_EQ (low_power_uri, last_uri); // ...and that the warning is taken down if the battery is plugged back in... + last_uri.clear(); changed_params = ChangedParams(); g_object_set (battery, INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_CHARGING, nullptr); wait_msec(); EXPECT_EQ (FIELD_IS_WARNING, changed_params.fields); EXPECT_FALSE (changed_params.is_warning); + EXPECT_TRUE(last_uri.empty()); // ...and that it comes back if we unplug again... + last_uri.clear(); changed_params = ChangedParams(); g_object_set (battery, INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_DISCHARGING, nullptr); wait_msec(); EXPECT_EQ (FIELD_IS_WARNING, changed_params.fields); EXPECT_TRUE (changed_params.is_warning); + EXPECT_EQ (low_power_uri, last_uri); // ...and that it's taken down if the power level is OK + last_uri.clear(); changed_params = ChangedParams(); set_battery_percentage (battery, percent_low+1); wait_msec(); EXPECT_EQ (FIELD_POWER_LEVEL|FIELD_IS_WARNING, changed_params.fields); EXPECT_STREQ (POWER_LEVEL_STR_OK, changed_params.power_level.c_str()); EXPECT_FALSE (changed_params.is_warning); + EXPECT_TRUE(last_uri.empty()); // cleanup g_dbus_connection_signal_unsubscribe (bus, sub_tag); g_object_unref (notifier); g_object_unref (battery); + g_object_unref (sound_player); } -- cgit v1.2.3 From bdc03e1cddb8811651f22e0bb423bf3385cbc793 Mon Sep 17 00:00:00 2001 From: charles kerr Date: Fri, 1 Jan 2016 16:12:16 -0600 Subject: update copyright years on changed/new files --- src/notifier.c | 2 +- src/notifier.h | 2 +- src/sound-player-gst.c | 8 ++++---- src/sound-player-gst.h | 8 ++++---- src/sound-player-mock.c | 2 +- src/sound-player-mock.h | 2 +- src/sound-player.c | 8 ++++---- src/sound-player.h | 8 ++++---- tests/test-notify.cc | 2 +- 9 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/notifier.c b/src/notifier.c index b50f48c..0907a14 100644 --- a/src/notifier.c +++ b/src/notifier.c @@ -1,5 +1,5 @@ /* - * Copyright 2014 Canonical Ltd. + * Copyright 2014-2016 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published diff --git a/src/notifier.h b/src/notifier.h index 9625c07..602f6e5 100644 --- a/src/notifier.h +++ b/src/notifier.h @@ -1,5 +1,5 @@ /* - * Copyright 2014 Canonical Ltd. + * Copyright 2014-2016 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published diff --git a/src/sound-player-gst.c b/src/sound-player-gst.c index 9b3f11a..25c3884 100644 --- a/src/sound-player-gst.c +++ b/src/sound-player-gst.c @@ -1,8 +1,5 @@ /* - * Copyright 2013 Canonical Ltd. - * - * Authors: - * Charles Kerr + * Copyright 2016 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published @@ -15,6 +12,9 @@ * * You should have received a copy of the GNU General Public License along * with this program. If not, see . + * + * Authors: + * Charles Kerr */ #include "sound-player.h" diff --git a/src/sound-player-gst.h b/src/sound-player-gst.h index 6ef8866..3075738 100644 --- a/src/sound-player-gst.h +++ b/src/sound-player-gst.h @@ -1,8 +1,5 @@ /* - * Copyright 2013 Canonical Ltd. - * - * Authors: - * Charles Kerr + * Copyright 2016 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published @@ -15,6 +12,9 @@ * * You should have received a copy of the GNU General Public License along * with this program. If not, see . + * + * Authors: + * Charles Kerr */ #ifndef __INDICATOR_POWER_SOUND_PLAYER_GST__H__ diff --git a/src/sound-player-mock.c b/src/sound-player-mock.c index 17eff21..35c3b57 100644 --- a/src/sound-player-mock.c +++ b/src/sound-player-mock.c @@ -1,5 +1,5 @@ /* - * Copyright 2014 Canonical Ltd. + * Copyright 2016 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published diff --git a/src/sound-player-mock.h b/src/sound-player-mock.h index f7f2653..f844924 100644 --- a/src/sound-player-mock.h +++ b/src/sound-player-mock.h @@ -1,5 +1,5 @@ /* - * Copyright 2014 Canonical Ltd. + * Copyright 2016 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published diff --git a/src/sound-player.c b/src/sound-player.c index f6421ad..dcbb27b 100644 --- a/src/sound-player.c +++ b/src/sound-player.c @@ -1,8 +1,5 @@ /* - * Copyright 2013 Canonical Ltd. - * - * Authors: - * Charles Kerr + * Copyright 2016 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published @@ -15,6 +12,9 @@ * * You should have received a copy of the GNU General Public License along * with this program. If not, see . + * + * Authors: + * Charles Kerr */ #include "sound-player.h" diff --git a/src/sound-player.h b/src/sound-player.h index ac7e261..adff924 100644 --- a/src/sound-player.h +++ b/src/sound-player.h @@ -1,8 +1,5 @@ /* - * Copyright 2013 Canonical Ltd. - * - * Authors: - * Charles Kerr + * Copyright 2016 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published @@ -15,6 +12,9 @@ * * You should have received a copy of the GNU General Public License along * with this program. If not, see . + * + * Authors: + * Charles Kerr */ #ifndef __INDICATOR_POWER_SOUND_PLAYER__H__ diff --git a/tests/test-notify.cc b/tests/test-notify.cc index cfa27bf..6fe7c59 100644 --- a/tests/test-notify.cc +++ b/tests/test-notify.cc @@ -1,5 +1,5 @@ /* - * Copyright 2014 Canonical Ltd. + * Copyright 2014-2016 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published -- cgit v1.2.3 From 46efcd909dc04f6474f275071aadf41e7547f6d8 Mon Sep 17 00:00:00 2001 From: charles kerr Date: Fri, 1 Jan 2016 16:17:52 -0600 Subject: in Notifier's destructor, unref its SoundPlayer field --- src/notifier.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/notifier.c b/src/notifier.c index 0907a14..d5e8b5d 100644 --- a/src/notifier.c +++ b/src/notifier.c @@ -406,6 +406,7 @@ my_dispose (GObject * o) priv_t * const p = get_priv (self); indicator_power_notifier_set_bus (self, NULL); + indicator_power_notifier_set_sound_player (self, NULL); notification_clear (self); indicator_power_notifier_set_battery (self, NULL); g_clear_object (&p->dbus_battery); -- cgit v1.2.3 From 61327b52f353c829ed10b452d17fec3d36b8c601 Mon Sep 17 00:00:00 2001 From: charles kerr Date: Fri, 1 Jan 2016 16:26:35 -0600 Subject: fix notifier property in service --- src/service.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/service.c b/src/service.c index 07f1106..a6c3432 100644 --- a/src/service.c +++ b/src/service.c @@ -1270,6 +1270,13 @@ indicator_power_service_class_init (IndicatorPowerServiceClass * klass) G_TYPE_OBJECT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + properties[PROP_NOTIFIER] = g_param_spec_object ( + "notifier", + "Notifier", + "Notifies user of important battery changes", + G_TYPE_OBJECT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (object_class, LAST_PROP, properties); } -- cgit v1.2.3 From 9b631e9353d206ab5c8bb64317f584024ebe0f4a Mon Sep 17 00:00:00 2001 From: charles kerr Date: Fri, 1 Jan 2016 18:49:13 -0600 Subject: fix another touched file's copyright date --- src/main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main.c b/src/main.c index 2837b59..34185b4 100644 --- a/src/main.c +++ b/src/main.c @@ -1,8 +1,5 @@ /* - * Copyright 2013 Canonical Ltd. - * - * Authors: - * Charles Kerr + * Copyright 2013-2016 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published @@ -15,6 +12,9 @@ * * You should have received a copy of the GNU General Public License along * with this program. If not, see . + * + * Authors: + * Charles Kerr */ #include -- cgit v1.2.3 From c7881a2d849191e1b6243da75ebf9140d29655cb Mon Sep 17 00:00:00 2001 From: charles kerr Date: Fri, 1 Jan 2016 19:25:16 -0600 Subject: create a data/sounds/ directory in the repo to hold Low battery.ogg We may be adding sounds for when we transition to battery charging/discharging, so set up a sounds/ directory now. --- .build.yml | 5 +++++ data/CMakeLists.txt | 8 +++----- data/Low battery.ogg | Bin 71140 -> 0 bytes data/sounds/Low battery.ogg | Bin 0 -> 71140 bytes tests/CMakeLists.txt | 9 +++------ 5 files changed, 11 insertions(+), 11 deletions(-) delete mode 100644 data/Low battery.ogg create mode 100644 data/sounds/Low battery.ogg diff --git a/.build.yml b/.build.yml index 90c2e9a..14f553b 100644 --- a/.build.yml +++ b/.build.yml @@ -17,6 +17,7 @@ requires: - glib2 - libnotify - systemd + - gstreamer debian: # Useful URL: https://salsa.debian.org/debian-ayatana-team/ayatana-indicator-power @@ -38,6 +39,7 @@ requires: - dbus-test-runner - libdbustest1-dev - systemd + - libgstreamer1.0-dev debian:stable: - autopoint @@ -57,6 +59,7 @@ requires: - dbus-test-runner - libdbustest1-dev - systemd + - libgstreamer1.0-dev ubuntu: - autopoint @@ -76,6 +79,7 @@ requires: - dbus-test-runner - libdbustest1-dev - systemd + - libgstreamer1.0-dev ubuntu:focal: - autopoint @@ -94,6 +98,7 @@ requires: - dbus-test-runner - libdbustest1-dev - systemd + - libgstreamer1.0-dev variables: - 'CHECKERS=" diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt index d6ffb35..2b8ab36 100644 --- a/data/CMakeLists.txt +++ b/data/CMakeLists.txt @@ -74,8 +74,6 @@ install (FILES "${AYATANA_INDICATOR_FILE}" ## # where to install -set (SOUNDS_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/${CMAKE_PROJECT_NAME}/sounds") -message (STATUS "${SOUNDS_DIR} is the Sound install dir") - -install (FILES "Low battery.ogg" - DESTINATION "${SOUNDS_DIR}") +set (DATA_HOME "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/${CMAKE_PROJECT_NAME}") +message (STATUS "${DATA_HOME} is the sounds/ install dir") +install (DIRECTORY sounds DESTINATION ${DATA_HOME}) diff --git a/data/Low battery.ogg b/data/Low battery.ogg deleted file mode 100644 index f6f9fb6..0000000 Binary files a/data/Low battery.ogg and /dev/null differ diff --git a/data/sounds/Low battery.ogg b/data/sounds/Low battery.ogg new file mode 100644 index 0000000..f6f9fb6 Binary files /dev/null and b/data/sounds/Low battery.ogg differ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 96cabb2..566132e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -14,13 +14,10 @@ set_directory_properties (PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES gschemas.compiled) set_source_files_properties (gschemas.compiled GENERATED) -# make a local install of the sounds -set(XDG_DATA_HOME "${CMAKE_CURRENT_BINARY_DIR}/share") +# make a XDG_DATA_HOME for sounds/ +set(XDG_DATA_HOME "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_DATADIR}") add_definitions(-DXDG_DATA_HOME="${XDG_DATA_HOME}") -file(COPY - DIRECTORY "${CMAKE_SOURCE_DIR}/data/" - DESTINATION "${XDG_DATA_HOME}/${CMAKE_PROJECT_NAME}/sounds" - FILES_MATCHING PATTERN "*.ogg") +file(COPY "${CMAKE_SOURCE_DIR}/data/sounds" DESTINATION "${XDG_DATA_HOME}/${CMAKE_PROJECT_NAME}") # GSettings: # compile the ayatana-indicator-power schema into a gschemas.compiled file in this directory, -- cgit v1.2.3 From 460f1464709a4c5e2c1594045961be9108ae2afd Mon Sep 17 00:00:00 2001 From: charles kerr Date: Fri, 1 Jan 2016 19:37:51 -0600 Subject: use a symbolic constant for the low battery sound's filename --- CMakeLists.txt | 3 ++- src/notifier.c | 2 +- tests/test-notify.cc | 7 ++++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 927a0bf..3d59545 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,7 +41,8 @@ set (CMAKE_INSTALL_FULL_PKGLIBEXECDIR "${CMAKE_INSTALL_FULL_LIBEXECDIR}/${CMAKE_ set(GETTEXT_PACKAGE "ayatana-indicator-power") add_definitions (-DGETTEXT_PACKAGE="${GETTEXT_PACKAGE}" - -DLOCALEDIR="${CMAKE_INSTALL_FULL_LOCALEDIR}") + -DLOCALEDIR="${CMAKE_INSTALL_FULL_LOCALEDIR}" + -DLOW_BATTERY_SOUND="Low battery.ogg") ## ## Check for prerequisites diff --git a/src/notifier.c b/src/notifier.c index d5e8b5d..7d81f3a 100644 --- a/src/notifier.c +++ b/src/notifier.c @@ -146,7 +146,7 @@ get_battery_power_level (IndicatorPowerDevice * battery) static void play_low_battery_sound (IndicatorPowerNotifier * self) { - const gchar * const key = "Low battery.ogg"; + const gchar * const key = LOW_BATTERY_SOUND; gchar * filename; priv_t * const p = get_priv(self); diff --git a/tests/test-notify.cc b/tests/test-notify.cc index 6fe7c59..0d92d7a 100644 --- a/tests/test-notify.cc +++ b/tests/test-notify.cc @@ -359,9 +359,14 @@ TEST_F(NotifyFixture, EventsThatChangeNotifications) 30, TRUE); + // the file we expect to play on a low battery notification... + const char* expected_file = XDG_DATA_HOME "/" GETTEXT_PACKAGE "/sounds/" LOW_BATTERY_SOUND; + char* tmp = g_filename_to_uri(expected_file, nullptr, nullptr); + const std::string low_power_uri {tmp}; + g_clear_pointer(&tmp, g_free); + // set up a notifier and give it the battery so changing the battery's // charge should show up on the bus. - const std::string low_power_uri {"file://" XDG_DATA_HOME "/" GETTEXT_PACKAGE "/sounds/Low%20battery.ogg"}; std::string last_uri; auto sound_player = indicator_power_sound_player_mock_new (); g_signal_connect(sound_player, "uri-played", G_CALLBACK(on_uri_played), &last_uri); -- cgit v1.2.3 From 97130ad08300c3ec6ab2165ff7506cd7f25af0d6 Mon Sep 17 00:00:00 2001 From: charles kerr Date: Fri, 1 Jan 2016 20:08:05 -0600 Subject: honor com.ubuntu.touch.AccountsService.Sound.SilentMode --- src/CMakeLists.txt | 5 ++ src/com.ubuntu.touch.AccountsService.Sound.xml | 47 +++++++++++++++++++ src/notifier.c | 64 +++++++++++++++++++++++++- 3 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 src/com.ubuntu.touch.AccountsService.Sound.xml diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c99ce46..01a0558 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -39,6 +39,11 @@ add_gdbus_codegen_with_namespace(SERVICE_GENERATED_SOURCES dbus-testing org.ayatana.indicator.power Dbus ${CMAKE_SOURCE_DIR}/data/org.ayatana.indicator.power.Testing.xml) +add_gdbus_codegen_with_namespace(SERVICE_GENERATED_SOURCES dbus-accounts-sound + com.ubuntu.touch + Dbus + ${CMAKE_SOURCE_DIR}/src/com.ubuntu.touch.AccountsService.Sound.xml) + # add the bin dir to our include path so the code can find the generated header files include_directories(${CMAKE_CURRENT_BINARY_DIR}) diff --git a/src/com.ubuntu.touch.AccountsService.Sound.xml b/src/com.ubuntu.touch.AccountsService.Sound.xml new file mode 100644 index 0000000..6e2ca5f --- /dev/null +++ b/src/com.ubuntu.touch.AccountsService.Sound.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/notifier.c b/src/notifier.c index 7d81f3a..ad7efb0 100644 --- a/src/notifier.c +++ b/src/notifier.c @@ -18,6 +18,7 @@ */ #include "datafiles.h" +#include "dbus-accounts-sound.h" #include "dbus-battery.h" #include "dbus-shared.h" #include "notifier.h" @@ -86,6 +87,9 @@ typedef struct gboolean actions_supported; IndicatorPowerSoundPlayer * sound_player; + + GCancellable * cancellable; + DbusAccountsServiceSound * accounts_service_sound_proxy; } IndicatorPowerNotifierPrivate; @@ -143,6 +147,40 @@ get_battery_power_level (IndicatorPowerDevice * battery) **** Sounds ***/ +static void +on_sound_proxy_ready (GObject * source_object G_GNUC_UNUSED, + GAsyncResult * res, + gpointer gself) +{ + GError * error; + DbusAccountsServiceSound * proxy; + + error = NULL; + proxy = dbus_accounts_service_sound_proxy_new_for_bus_finish (res, &error); + if (error != NULL) + { + if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + g_warning("%s Couldn't find accounts service sound proxy: %s", G_STRLOC, error->message); + + g_clear_error(&error); + } + else + { + IndicatorPowerNotifier * const self = INDICATOR_POWER_NOTIFIER(gself); + priv_t * const p = get_priv (self); + p->accounts_service_sound_proxy = proxy; + } +} + +static gboolean +silent_mode (IndicatorPowerNotifier * self) +{ + priv_t * const p = get_priv (self); + + return (p->accounts_service_sound_proxy != NULL) + && (dbus_accounts_service_sound_get_silent_mode(p->accounts_service_sound_proxy)); +} + static void play_low_battery_sound (IndicatorPowerNotifier * self) { @@ -150,8 +188,13 @@ play_low_battery_sound (IndicatorPowerNotifier * self) gchar * filename; priv_t * const p = get_priv(self); + /* can't play? */ g_return_if_fail (p->sound_player != NULL); + /* won't play? */ + if (silent_mode(self)) + return; + filename = datafile_find(DATAFILE_TYPE_SOUND, key); if (filename != NULL) { @@ -405,11 +448,18 @@ my_dispose (GObject * o) IndicatorPowerNotifier * const self = INDICATOR_POWER_NOTIFIER(o); priv_t * const p = get_priv (self); + if (p->cancellable != NULL) + { + g_cancellable_cancel(p->cancellable); + g_clear_object(&p->cancellable); + } + indicator_power_notifier_set_bus (self, NULL); indicator_power_notifier_set_sound_player (self, NULL); notification_clear (self); indicator_power_notifier_set_battery (self, NULL); g_clear_object (&p->dbus_battery); + g_clear_object (&p->accounts_service_sound_proxy); G_OBJECT_CLASS (indicator_power_notifier_parent_class)->dispose (o); } @@ -428,7 +478,6 @@ my_finalize (GObject * o G_GNUC_UNUSED) **** Instantiation ***/ - static void indicator_power_notifier_init (IndicatorPowerNotifier * self) { @@ -440,8 +489,21 @@ indicator_power_notifier_init (IndicatorPowerNotifier * self) p->power_level = POWER_LEVEL_OK; + p->cancellable = g_cancellable_new(); + if (!instance_count++ && !notify_init("ayatana-indicator-power-service")) g_critical("Unable to initialize libnotify! Notifications might not be shown."); + + gchar* object_path = g_strdup_printf("/org/freedesktop/Accounts/User%lu", (gulong)getuid()); + dbus_accounts_service_sound_proxy_new_for_bus( + G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES, + "org.freedesktop.Accounts", + object_path, + p->cancellable, + on_sound_proxy_ready, + self); + g_clear_pointer(&object_path, g_free); } static void -- cgit v1.2.3 From deca915372eddd1e0a1fa219cb26d7f6541d1f80 Mon Sep 17 00:00:00 2001 From: charles kerr Date: Fri, 1 Jan 2016 20:14:14 -0600 Subject: update copyright dates on changed files (again) --- src/datafiles.c | 2 +- src/datafiles.h | 2 +- src/service.c | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/datafiles.c b/src/datafiles.c index dba8048..6d9962c 100644 --- a/src/datafiles.c +++ b/src/datafiles.c @@ -1,5 +1,5 @@ /* - * Copyright 2015 Canonical Ltd. + * Copyright 2016 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published diff --git a/src/datafiles.h b/src/datafiles.h index f624b9c..95c5bc9 100644 --- a/src/datafiles.h +++ b/src/datafiles.h @@ -1,5 +1,5 @@ /* - * Copyright 2015 Canonical Ltd. + * Copyright 2016 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published diff --git a/src/service.c b/src/service.c index a6c3432..17414c7 100644 --- a/src/service.c +++ b/src/service.c @@ -1,12 +1,7 @@ /* - * Copyright 2013 Canonical Ltd. + * Copyright 2013-2016 Canonical Ltd. * Copytight 2021 AyatanaIndicators * - * Authors: - * Charles Kerr - * Ted Gould - * Robert Tari - * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. @@ -18,6 +13,11 @@ * * You should have received a copy of the GNU General Public License along * with this program. If not, see . + * + * Authors: + * Charles Kerr + * Ted Gould + * Robert Tari */ #include -- cgit v1.2.3 From 5d038638f58765ec3859797704c5d0e1c0fa7903 Mon Sep 17 00:00:00 2001 From: charles kerr Date: Fri, 1 Jan 2016 20:19:45 -0600 Subject: handle service_set_notifier(NULL) gracefully --- src/service.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/service.c b/src/service.c index 17414c7..c04122f 100644 --- a/src/service.c +++ b/src/service.c @@ -1339,9 +1339,13 @@ indicator_power_service_set_notifier (IndicatorPowerService * self, g_return_if_fail (!notifier || INDICATOR_IS_POWER_NOTIFIER (notifier)); p = self->priv; - if (p->notifier != notifier) + if (p->notifier == notifier) + return; + + g_clear_object (&p->notifier); + + if (notifier != NULL) { - g_clear_object (&p->notifier); p->notifier = g_object_ref (notifier); indicator_power_notifier_set_bus (p->notifier, p->conn); } -- cgit v1.2.3 From 1182c7fb79942c14f2a713063182778e6af94cd1 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 4 Jan 2016 09:38:01 -0600 Subject: add build-dep to accountsservice-ubuntu-schemas instead of bundling com.ubuntu.touch.AccountsService.Sound.xml into our source tree --- CMakeLists.txt | 7 ++++ debian/control | 1 + src/CMakeLists.txt | 11 +++--- src/com.ubuntu.touch.AccountsService.Sound.xml | 47 -------------------------- src/notifier.c | 23 +++++++++++-- 5 files changed, 35 insertions(+), 54 deletions(-) delete mode 100644 src/com.ubuntu.touch.AccountsService.Sound.xml diff --git a/CMakeLists.txt b/CMakeLists.txt index 3d59545..bc5729a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,6 +69,13 @@ pkg_check_modules( ) include_directories(${URLDISPATCHER_INCLUDE_DIRS}) +if(EXISTS "/usr/share/accountsservice/interfaces/com.ubuntu.touch.AccountsService.Sound.xml") + set (HAVE_UT_ACCTSERVICE_SYSTEMSOUND_SETTINGS ON) + add_definitions ( -DHAS_UT_ACCTSERVICE_SYSTEMSOUND_SETTINGS ) +else() + set (HAVE_UT_ACCTSERVICE_SYSTEMSOUND_SETTINGS OFF) +endif() + ## ## custom targets ## diff --git a/debian/control b/debian/control index a70647f..534e197 100644 --- a/debian/control +++ b/debian/control @@ -10,6 +10,7 @@ Build-Depends: cmake, libnotify-dev (>= 0.7.6), libglib2.0-dev (>= 2.36), liblomiri-url-dispatcher-dev | hello, + accountsservice-ubuntu-schemas | hello, # for packaging debhelper (>= 9), dpkg-dev (>= 1.16.1.1), diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 01a0558..4654380 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -39,10 +39,13 @@ add_gdbus_codegen_with_namespace(SERVICE_GENERATED_SOURCES dbus-testing org.ayatana.indicator.power Dbus ${CMAKE_SOURCE_DIR}/data/org.ayatana.indicator.power.Testing.xml) -add_gdbus_codegen_with_namespace(SERVICE_GENERATED_SOURCES dbus-accounts-sound - com.ubuntu.touch - Dbus - ${CMAKE_SOURCE_DIR}/src/com.ubuntu.touch.AccountsService.Sound.xml) + +if (HAVE_UT_ACCTSERVICE_SYSTEMSOUND_SETTINGS) + add_gdbus_codegen_with_namespace(SERVICE_GENERATED_SOURCES dbus-accounts-sound + com.ubuntu.touch + Dbus + /usr/share/accountsservice/interfaces/com.ubuntu.touch.AccountsService.Sound.xml) +endif() # add the bin dir to our include path so the code can find the generated header files include_directories(${CMAKE_CURRENT_BINARY_DIR}) diff --git a/src/com.ubuntu.touch.AccountsService.Sound.xml b/src/com.ubuntu.touch.AccountsService.Sound.xml deleted file mode 100644 index 6e2ca5f..0000000 --- a/src/com.ubuntu.touch.AccountsService.Sound.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/notifier.c b/src/notifier.c index ad7efb0..487f889 100644 --- a/src/notifier.c +++ b/src/notifier.c @@ -18,7 +18,11 @@ */ #include "datafiles.h" + +#ifdef HAS_UT_ACCTSERVICE_SYSTEMSOUND_SETTINGS #include "dbus-accounts-sound.h" +#endif + #include "dbus-battery.h" #include "dbus-shared.h" #include "notifier.h" @@ -89,7 +93,9 @@ typedef struct IndicatorPowerSoundPlayer * sound_player; GCancellable * cancellable; + #ifdef HAS_UT_ACCTSERVICE_SYSTEMSOUND_SETTINGS DbusAccountsServiceSound * accounts_service_sound_proxy; + #endif } IndicatorPowerNotifierPrivate; @@ -147,16 +153,18 @@ get_battery_power_level (IndicatorPowerDevice * battery) **** Sounds ***/ +#ifdef HAS_UT_ACCTSERVICE_SYSTEMSOUND_SETTINGS static void on_sound_proxy_ready (GObject * source_object G_GNUC_UNUSED, GAsyncResult * res, gpointer gself) { GError * error; - DbusAccountsServiceSound * proxy; - error = NULL; + + DbusAccountsServiceSound * proxy; proxy = dbus_accounts_service_sound_proxy_new_for_bus_finish (res, &error); + if (error != NULL) { if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -172,6 +180,7 @@ on_sound_proxy_ready (GObject * source_object G_GNUC_UNUSED, } } + static gboolean silent_mode (IndicatorPowerNotifier * self) { @@ -180,6 +189,7 @@ silent_mode (IndicatorPowerNotifier * self) return (p->accounts_service_sound_proxy != NULL) && (dbus_accounts_service_sound_get_silent_mode(p->accounts_service_sound_proxy)); } +#endif static void play_low_battery_sound (IndicatorPowerNotifier * self) @@ -191,9 +201,11 @@ play_low_battery_sound (IndicatorPowerNotifier * self) /* can't play? */ g_return_if_fail (p->sound_player != NULL); + #ifdef HAS_UT_ACCTSERVICE_SYSTEMSOUND_SETTINGS /* won't play? */ if (silent_mode(self)) return; + #endif filename = datafile_find(DATAFILE_TYPE_SOUND, key); if (filename != NULL) @@ -459,7 +471,10 @@ my_dispose (GObject * o) notification_clear (self); indicator_power_notifier_set_battery (self, NULL); g_clear_object (&p->dbus_battery); + + #ifdef HAS_UT_ACCTSERVICE_SYSTEMSOUND_SETTINGS g_clear_object (&p->accounts_service_sound_proxy); + #endif G_OBJECT_CLASS (indicator_power_notifier_parent_class)->dispose (o); } @@ -467,7 +482,7 @@ my_dispose (GObject * o) static void my_finalize (GObject * o G_GNUC_UNUSED) { - /* FIXME: This is an awkward place to put this. + /* FIXME: This is an awkward place to put this. Ordinarily something like this would go in main(), but we need libnotify to clean itself up before shutting down the bus in the unit tests as well. */ if (!--instance_count) @@ -494,6 +509,7 @@ indicator_power_notifier_init (IndicatorPowerNotifier * self) if (!instance_count++ && !notify_init("ayatana-indicator-power-service")) g_critical("Unable to initialize libnotify! Notifications might not be shown."); + #ifdef HAS_UT_ACCTSERVICE_SYSTEMSOUND_SETTINGS gchar* object_path = g_strdup_printf("/org/freedesktop/Accounts/User%lu", (gulong)getuid()); dbus_accounts_service_sound_proxy_new_for_bus( G_BUS_TYPE_SYSTEM, @@ -504,6 +520,7 @@ indicator_power_notifier_init (IndicatorPowerNotifier * self) on_sound_proxy_ready, self); g_clear_pointer(&object_path, g_free); + #endif } static void -- cgit v1.2.3 From afc091939635eb46f2947cfe1aaadcb408de2835 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 4 Jan 2016 10:08:39 -0600 Subject: add a leak safeguard to accounts_service_sound_proxy --- src/notifier.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/notifier.c b/src/notifier.c index 487f889..696556a 100644 --- a/src/notifier.c +++ b/src/notifier.c @@ -176,6 +176,7 @@ on_sound_proxy_ready (GObject * source_object G_GNUC_UNUSED, { IndicatorPowerNotifier * const self = INDICATOR_POWER_NOTIFIER(gself); priv_t * const p = get_priv (self); + g_clear_object (&p->accounts_service_sound_proxy); p->accounts_service_sound_proxy = proxy; } } -- cgit v1.2.3 From 27122e92856bbe4efcdfc4975b46a0c6dee67cb9 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 4 Jan 2016 10:10:25 -0600 Subject: assume we're in silent mode if we can't get an accounts-service proxy --- src/notifier.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/notifier.c b/src/notifier.c index 696556a..4b7aede 100644 --- a/src/notifier.c +++ b/src/notifier.c @@ -187,8 +187,12 @@ silent_mode (IndicatorPowerNotifier * self) { priv_t * const p = get_priv (self); - return (p->accounts_service_sound_proxy != NULL) - && (dbus_accounts_service_sound_get_silent_mode(p->accounts_service_sound_proxy)); + /* if we don't have a proxy yet, assume we're in silent mode + as a "do no harm" level of response */ + if (p->accounts_service_sound_proxy == NULL) + return TRUE; + + return dbus_accounts_service_sound_get_silent_mode(p->accounts_service_sound_proxy); } #endif -- cgit v1.2.3 From 1d9e1e532b6e52c974a6889706e02a500290ea51 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 4 Jan 2016 10:11:18 -0600 Subject: fix copy-paste typo --- src/notifier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/notifier.c b/src/notifier.c index 4b7aede..93ab461 100644 --- a/src/notifier.c +++ b/src/notifier.c @@ -548,7 +548,7 @@ indicator_power_notifier_class_init (IndicatorPowerNotifierClass * klass) properties[PROP_SOUND_PLAYER] = g_param_spec_object ( PROP_SOUND_PLAYER_NAME, "Sound Player", - "The current battery", + "The current sound player", G_TYPE_OBJECT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); -- cgit v1.2.3 From f829a7e9bc11614bf75dff270f161bff71c8ae4d Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 4 Jan 2016 10:19:59 -0600 Subject: move sound-player-mock into the tests/ directory --- src/CMakeLists.txt | 3 +- src/sound-player-mock.c | 94 ----------------------------------------------- src/sound-player-mock.h | 75 ------------------------------------- tests/CMakeLists.txt | 11 +++++- tests/sound-player-mock.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++ tests/sound-player-mock.h | 75 +++++++++++++++++++++++++++++++++++++ 6 files changed, 179 insertions(+), 173 deletions(-) delete mode 100644 src/sound-player-mock.c delete mode 100644 src/sound-player-mock.h create mode 100644 tests/sound-player-mock.c create mode 100644 tests/sound-player-mock.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4654380..8eac086 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -21,8 +21,7 @@ set(SERVICE_MANUAL_SOURCES service.c utils.c sound-player.c - sound-player-gst.c - sound-player-mock.c) + sound-player-gst.c) # generated sources include(GdbusCodegen) diff --git a/src/sound-player-mock.c b/src/sound-player-mock.c deleted file mode 100644 index 35c3b57..0000000 --- a/src/sound-player-mock.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2016 Canonical Ltd. - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3, as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - * - * Authors: - * Charles Kerr - */ - -#include "sound-player.h" -#include "sound-player-mock.h" - -enum -{ - SIGNAL_URI_PLAYED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -/*** -**** GObject boilerplate -***/ - -static void indicator_power_sound_player_interface_init ( - IndicatorPowerSoundPlayerInterface * iface); - -G_DEFINE_TYPE_WITH_CODE ( - IndicatorPowerSoundPlayerMock, - indicator_power_sound_player_mock, - G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (INDICATOR_TYPE_POWER_SOUND_PLAYER, - indicator_power_sound_player_interface_init)) - -/*** -**** IndicatorPowerSoundPlayer virtual functions -***/ - -static void -my_play_uri (IndicatorPowerSoundPlayer * self, const gchar * uri) -{ - g_signal_emit (self, signals[SIGNAL_URI_PLAYED], 0, uri, NULL); -} - -/*** -**** Instantiation -***/ - -static void -indicator_power_sound_player_mock_class_init (IndicatorPowerSoundPlayerMockClass * klass G_GNUC_UNUSED) -{ - signals[SIGNAL_URI_PLAYED] = g_signal_new ( - "uri-played", - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (IndicatorPowerSoundPlayerMockClass, uri_played), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); -} - -static void -indicator_power_sound_player_interface_init (IndicatorPowerSoundPlayerInterface * iface) -{ - iface->play_uri = my_play_uri; -} - -static void -indicator_power_sound_player_mock_init (IndicatorPowerSoundPlayerMock * self G_GNUC_UNUSED) -{ -} - -/*** -**** Public API -***/ - -IndicatorPowerSoundPlayer * -indicator_power_sound_player_mock_new (void) -{ - gpointer o = g_object_new (INDICATOR_TYPE_POWER_SOUND_PLAYER_MOCK, NULL); - - return INDICATOR_POWER_SOUND_PLAYER (o); -} - diff --git a/src/sound-player-mock.h b/src/sound-player-mock.h deleted file mode 100644 index f844924..0000000 --- a/src/sound-player-mock.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2016 Canonical Ltd. - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3, as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - * - * Authors: - * Charles Kerr - */ - -#ifndef __INDICATOR_POWER_SOUND_PLAYER_MOCK__H__ -#define __INDICATOR_POWER_SOUND_PLAYER_MOCK__H__ - -#include /* parent class */ - -#include "sound-player.h" - -G_BEGIN_DECLS - -#define INDICATOR_TYPE_POWER_SOUND_PLAYER_MOCK \ - (indicator_power_sound_player_mock_get_type()) - -#define INDICATOR_POWER_SOUND_PLAYER_MOCK(o) \ - (G_TYPE_CHECK_INSTANCE_CAST ((o), \ - INDICATOR_TYPE_POWER_SOUND_PLAYER_MOCK, \ - IndicatorPowerSoundPlayerMock)) - -#define INDICATOR_POWER_SOUND_PLAYER_MOCK_GET_CLASS(o) \ - (G_TYPE_INSTANCE_GET_CLASS ((o), \ - INDICATOR_TYPE_POWER_SOUND_PLAYER_MOCK, \ - IndicatorPowerSoundPlayerMockClass)) - -#define INDICATOR_IS_POWER_SOUND_PLAYER_MOCK(o) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((o), \ - INDICATOR_TYPE_POWER_SOUND_PLAYER_MOCK)) - -typedef struct _IndicatorPowerSoundPlayerMock - IndicatorPowerSoundPlayerMock; -typedef struct _IndicatorPowerSoundPlayerMockPriv - IndicatorPowerSoundPlayerMockPriv; -typedef struct _IndicatorPowerSoundPlayerMockClass - IndicatorPowerSoundPlayerMockClass; - -/** - * An IndicatorPowerSoundPlayer which gets its devices from Mock. - */ -struct _IndicatorPowerSoundPlayerMock -{ - GObject parent_instance; -}; - -struct _IndicatorPowerSoundPlayerMockClass -{ - GObjectClass parent_class; - - /* signals */ - void (*uri_played) (IndicatorPowerSoundPlayer * self, const gchar* uri); -}; - -GType indicator_power_sound_player_mock_get_type (void); - -IndicatorPowerSoundPlayer * indicator_power_sound_player_mock_new (void); - -G_END_DECLS - -#endif /* __INDICATOR_POWER_SOUND_PLAYER_MOCK__H__ */ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 566132e..41e48cd 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -9,6 +9,13 @@ include_directories (SYSTEM ${DBUSTEST_INCLUDE_DIRS}) # add warnings set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ${C_WARNING_ARGS}") +# build the mocks +set(MOCK_LIB "indicatorpowerservicemocks") +set(MOCK_SOURCES sound-player-mock.c) +set_source_files_properties(${MOCK_SOURCES} + PROPERTIES COMPILE_FLAGS "${C_WARNING_ARGS} -g -std=c99") +add_library(${MOCK_LIB} STATIC ${MOCK_SOURCES}) + # build the necessary schemas set_directory_properties (PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES gschemas.compiled) @@ -50,8 +57,8 @@ function(add_test_by_name name) add_executable (${TEST_NAME} ${TEST_NAME}.cc) target_link_options(${TEST_NAME} PRIVATE -no-pie) add_test (${TEST_NAME} ${TEST_NAME}) - add_dependencies (${TEST_NAME} ayatanaindicatorpowerservice gschemas-compiled) - target_link_libraries (${TEST_NAME} ayatanaindicatorpowerservice gtest ${DBUSTEST_LIBRARIES} ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBS} ${URLDISPATCHER_LIBRARIES} ${GMOCK_LIBRARIES}) + add_dependencies (${TEST_NAME} ${MOCK_LIB} ayatanaindicatorpowerservice gschemas-compiled) + target_link_libraries (${TEST_NAME} ${MOCK_LIB} ayatanaindicatorpowerservice gtest ${DBUSTEST_LIBRARIES} ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBS} ${URLDISPATCHER_LIBRARIES} ${GMOCK_LIBRARIES}) endfunction() add_test_by_name(test-notify) add_test(NAME dear-reader-the-next-test-takes-80-seconds COMMAND true) diff --git a/tests/sound-player-mock.c b/tests/sound-player-mock.c new file mode 100644 index 0000000..35c3b57 --- /dev/null +++ b/tests/sound-player-mock.c @@ -0,0 +1,94 @@ +/* + * Copyright 2016 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#include "sound-player.h" +#include "sound-player-mock.h" + +enum +{ + SIGNAL_URI_PLAYED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +/*** +**** GObject boilerplate +***/ + +static void indicator_power_sound_player_interface_init ( + IndicatorPowerSoundPlayerInterface * iface); + +G_DEFINE_TYPE_WITH_CODE ( + IndicatorPowerSoundPlayerMock, + indicator_power_sound_player_mock, + G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (INDICATOR_TYPE_POWER_SOUND_PLAYER, + indicator_power_sound_player_interface_init)) + +/*** +**** IndicatorPowerSoundPlayer virtual functions +***/ + +static void +my_play_uri (IndicatorPowerSoundPlayer * self, const gchar * uri) +{ + g_signal_emit (self, signals[SIGNAL_URI_PLAYED], 0, uri, NULL); +} + +/*** +**** Instantiation +***/ + +static void +indicator_power_sound_player_mock_class_init (IndicatorPowerSoundPlayerMockClass * klass G_GNUC_UNUSED) +{ + signals[SIGNAL_URI_PLAYED] = g_signal_new ( + "uri-played", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IndicatorPowerSoundPlayerMockClass, uri_played), + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, G_TYPE_STRING); +} + +static void +indicator_power_sound_player_interface_init (IndicatorPowerSoundPlayerInterface * iface) +{ + iface->play_uri = my_play_uri; +} + +static void +indicator_power_sound_player_mock_init (IndicatorPowerSoundPlayerMock * self G_GNUC_UNUSED) +{ +} + +/*** +**** Public API +***/ + +IndicatorPowerSoundPlayer * +indicator_power_sound_player_mock_new (void) +{ + gpointer o = g_object_new (INDICATOR_TYPE_POWER_SOUND_PLAYER_MOCK, NULL); + + return INDICATOR_POWER_SOUND_PLAYER (o); +} + diff --git a/tests/sound-player-mock.h b/tests/sound-player-mock.h new file mode 100644 index 0000000..f844924 --- /dev/null +++ b/tests/sound-player-mock.h @@ -0,0 +1,75 @@ +/* + * Copyright 2016 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#ifndef __INDICATOR_POWER_SOUND_PLAYER_MOCK__H__ +#define __INDICATOR_POWER_SOUND_PLAYER_MOCK__H__ + +#include /* parent class */ + +#include "sound-player.h" + +G_BEGIN_DECLS + +#define INDICATOR_TYPE_POWER_SOUND_PLAYER_MOCK \ + (indicator_power_sound_player_mock_get_type()) + +#define INDICATOR_POWER_SOUND_PLAYER_MOCK(o) \ + (G_TYPE_CHECK_INSTANCE_CAST ((o), \ + INDICATOR_TYPE_POWER_SOUND_PLAYER_MOCK, \ + IndicatorPowerSoundPlayerMock)) + +#define INDICATOR_POWER_SOUND_PLAYER_MOCK_GET_CLASS(o) \ + (G_TYPE_INSTANCE_GET_CLASS ((o), \ + INDICATOR_TYPE_POWER_SOUND_PLAYER_MOCK, \ + IndicatorPowerSoundPlayerMockClass)) + +#define INDICATOR_IS_POWER_SOUND_PLAYER_MOCK(o) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((o), \ + INDICATOR_TYPE_POWER_SOUND_PLAYER_MOCK)) + +typedef struct _IndicatorPowerSoundPlayerMock + IndicatorPowerSoundPlayerMock; +typedef struct _IndicatorPowerSoundPlayerMockPriv + IndicatorPowerSoundPlayerMockPriv; +typedef struct _IndicatorPowerSoundPlayerMockClass + IndicatorPowerSoundPlayerMockClass; + +/** + * An IndicatorPowerSoundPlayer which gets its devices from Mock. + */ +struct _IndicatorPowerSoundPlayerMock +{ + GObject parent_instance; +}; + +struct _IndicatorPowerSoundPlayerMockClass +{ + GObjectClass parent_class; + + /* signals */ + void (*uri_played) (IndicatorPowerSoundPlayer * self, const gchar* uri); +}; + +GType indicator_power_sound_player_mock_get_type (void); + +IndicatorPowerSoundPlayer * indicator_power_sound_player_mock_new (void); + +G_END_DECLS + +#endif /* __INDICATOR_POWER_SOUND_PLAYER_MOCK__H__ */ -- cgit v1.2.3 From d2e654d53f5dbe89cce2fe08a7e6dbcae4a6d835 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 4 Jan 2016 12:52:04 -0600 Subject: don't disable the warning sound when AccountServices is completely unavailable --- src/notifier.c | 13 ++++++++++--- tests/glib-fixture.h | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/notifier.c b/src/notifier.c index 93ab461..e6c511f 100644 --- a/src/notifier.c +++ b/src/notifier.c @@ -95,6 +95,7 @@ typedef struct GCancellable * cancellable; #ifdef HAS_UT_ACCTSERVICE_SYSTEMSOUND_SETTINGS DbusAccountsServiceSound * accounts_service_sound_proxy; + gboolean accounts_service_sound_proxy_pending; #endif } IndicatorPowerNotifierPrivate; @@ -168,7 +169,10 @@ on_sound_proxy_ready (GObject * source_object G_GNUC_UNUSED, if (error != NULL) { if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - g_warning("%s Couldn't find accounts service sound proxy: %s", G_STRLOC, error->message); + { + get_priv(gself)->accounts_service_sound_proxy_pending = FALSE; + g_warning("%s Couldn't find accounts service sound proxy: %s", G_STRLOC, error->message); + } g_clear_error(&error); } @@ -178,6 +182,7 @@ on_sound_proxy_ready (GObject * source_object G_GNUC_UNUSED, priv_t * const p = get_priv (self); g_clear_object (&p->accounts_service_sound_proxy); p->accounts_service_sound_proxy = proxy; + p->accounts_service_sound_proxy_pending = FALSE; } } @@ -189,10 +194,11 @@ silent_mode (IndicatorPowerNotifier * self) /* if we don't have a proxy yet, assume we're in silent mode as a "do no harm" level of response */ - if (p->accounts_service_sound_proxy == NULL) + if (p->accounts_service_sound_proxy_pending) return TRUE; - return dbus_accounts_service_sound_get_silent_mode(p->accounts_service_sound_proxy); + return (p->accounts_service_sound_proxy != NULL) + && dbus_accounts_service_sound_get_silent_mode(p->accounts_service_sound_proxy); } #endif @@ -515,6 +521,7 @@ indicator_power_notifier_init (IndicatorPowerNotifier * self) g_critical("Unable to initialize libnotify! Notifications might not be shown."); #ifdef HAS_UT_ACCTSERVICE_SYSTEMSOUND_SETTINGS + p->accounts_service_sound_proxy_pending = TRUE; gchar* object_path = g_strdup_printf("/org/freedesktop/Accounts/User%lu", (gulong)getuid()); dbus_accounts_service_sound_proxy_new_for_bus( G_BUS_TYPE_SYSTEM, diff --git a/tests/glib-fixture.h b/tests/glib-fixture.h index 09c37a3..9494df2 100644 --- a/tests/glib-fixture.h +++ b/tests/glib-fixture.h @@ -52,7 +52,7 @@ class GlibFixture : public ::testing::Test if (expected_log[level] != n) for (size_t i=0; i Date: Mon, 4 Jan 2016 14:25:56 -0600 Subject: demote a spurious warning to a debug message --- src/notifier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/notifier.c b/src/notifier.c index e6c511f..b481fdf 100644 --- a/src/notifier.c +++ b/src/notifier.c @@ -171,7 +171,7 @@ on_sound_proxy_ready (GObject * source_object G_GNUC_UNUSED, if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { get_priv(gself)->accounts_service_sound_proxy_pending = FALSE; - g_warning("%s Couldn't find accounts service sound proxy: %s", G_STRLOC, error->message); + g_debug("%s Couldn't find accounts service sound proxy: %s", G_STRLOC, error->message); } g_clear_error(&error); -- cgit v1.2.3 From f4d66118c3a845892b32495efec3d6473e17baca Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 1 Feb 2016 10:53:07 -0600 Subject: for low power notifications, use libnotify's 'sound-file' property instead of indicator-power calling the sound player directly --- src/CMakeLists.txt | 4 +- src/main.c | 6 +- src/notifier.c | 94 +++++-------------------- src/notifier.h | 6 +- src/sound-player-gst.c | 173 ---------------------------------------------- src/sound-player-gst.h | 70 ------------------- src/sound-player.c | 45 ------------ src/sound-player.h | 72 ------------------- tests/CMakeLists.txt | 11 +-- tests/sound-player-mock.c | 94 ------------------------- tests/sound-player-mock.h | 75 -------------------- tests/test-notify.cc | 88 +++++++++++++++-------- 12 files changed, 83 insertions(+), 655 deletions(-) delete mode 100644 src/sound-player-gst.c delete mode 100644 src/sound-player-gst.h delete mode 100644 src/sound-player.c delete mode 100644 src/sound-player.h delete mode 100644 tests/sound-player-mock.c delete mode 100644 tests/sound-player-mock.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8eac086..a5e6c57 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -19,9 +19,7 @@ set(SERVICE_MANUAL_SOURCES notifier.c testing.c service.c - utils.c - sound-player.c - sound-player-gst.c) + utils.c) # generated sources include(GdbusCodegen) diff --git a/src/main.c b/src/main.c index 34185b4..ce54ae8 100644 --- a/src/main.c +++ b/src/main.c @@ -25,7 +25,6 @@ #include "device.h" #include "notifier.h" #include "service.h" -#include "sound-player-gst.h" #include "testing.h" /*** @@ -42,7 +41,6 @@ on_name_lost (gpointer instance G_GNUC_UNUSED, gpointer loop) int main (int argc G_GNUC_UNUSED, char ** argv G_GNUC_UNUSED) { - IndicatorPowerSoundPlayer * sound_player; IndicatorPowerNotifier * notifier; IndicatorPowerService * service; IndicatorPowerTesting * testing; @@ -54,8 +52,7 @@ main (int argc G_GNUC_UNUSED, char ** argv G_GNUC_UNUSED) textdomain (GETTEXT_PACKAGE); /* run */ - sound_player = indicator_power_sound_player_gst_new (); - notifier = indicator_power_notifier_new (sound_player); + notifier = indicator_power_notifier_new(); service = indicator_power_service_new(NULL, notifier); testing = indicator_power_testing_new (service); loop = g_main_loop_new (NULL, FALSE); @@ -68,6 +65,5 @@ main (int argc G_GNUC_UNUSED, char ** argv G_GNUC_UNUSED) g_clear_object (&testing); g_clear_object (&service); g_clear_object (¬ifier); - g_clear_object (&sound_player); return 0; } diff --git a/src/notifier.c b/src/notifier.c index b481fdf..00a00e5 100644 --- a/src/notifier.c +++ b/src/notifier.c @@ -27,7 +27,6 @@ #include "dbus-shared.h" #include "notifier.h" #include "utils.h" -#include "sound-player.h" #ifdef HAS_URLDISPATCHER #include @@ -56,12 +55,10 @@ enum { PROP_0, PROP_BATTERY, - PROP_SOUND_PLAYER, LAST_PROP }; #define PROP_BATTERY_NAME "battery" -#define PROP_SOUND_PLAYER_NAME "sound-player" static GParamSpec * properties[LAST_PROP]; @@ -90,8 +87,6 @@ typedef struct gboolean caps_queried; gboolean actions_supported; - IndicatorPowerSoundPlayer * sound_player; - GCancellable * cancellable; #ifdef HAS_UT_ACCTSERVICE_SYSTEMSOUND_SETTINGS DbusAccountsServiceSound * accounts_service_sound_proxy; @@ -202,36 +197,6 @@ silent_mode (IndicatorPowerNotifier * self) } #endif -static void -play_low_battery_sound (IndicatorPowerNotifier * self) -{ - const gchar * const key = LOW_BATTERY_SOUND; - gchar * filename; - priv_t * const p = get_priv(self); - - /* can't play? */ - g_return_if_fail (p->sound_player != NULL); - - #ifdef HAS_UT_ACCTSERVICE_SYSTEMSOUND_SETTINGS - /* won't play? */ - if (silent_mode(self)) - return; - #endif - - filename = datafile_find(DATAFILE_TYPE_SOUND, key); - if (filename != NULL) - { - gchar * uri = g_filename_to_uri(filename, NULL, NULL); - indicator_power_sound_player_play_uri (p->sound_player, uri); - g_free(uri); - g_free(filename); - } - else - { - g_warning("Unable to find '%s' in XDG data dirs", key); - } -} - /*** **** Notifications ***/ @@ -346,6 +311,21 @@ notification_show(IndicatorPowerNotifier * self) if (are_actions_supported(self)) { + if (!silent_mode(self)) + { + gchar* filename = datafile_find(DATAFILE_TYPE_SOUND, LOW_BATTERY_SOUND); + if (filename != NULL) + { + gchar * uri = g_filename_to_uri(filename, NULL, NULL); + notify_notification_set_hint(nn, "sound-file", g_variant_new_take_string(uri)); + g_clear_pointer(&filename, g_free); + } + else + { + g_warning("Unable to find '%s' in XDG data dirs", LOW_BATTERY_SOUND); + } + } + notify_notification_set_hint(nn, "x-canonical-snap-decisions", g_variant_new_string("true")); notify_notification_set_hint(nn, "x-canonical-non-shaped-icon", g_variant_new_string("true")); notify_notification_set_hint(nn, "x-canonical-private-affirmative-tint", g_variant_new_string("true")); @@ -402,7 +382,6 @@ on_battery_property_changed (IndicatorPowerNotifier * self) ((new_power_level != POWER_LEVEL_OK) && new_discharging && !old_discharging)) { notification_show (self); - play_low_battery_sound (self); } else if (!new_discharging || (new_power_level == POWER_LEVEL_OK)) { @@ -433,10 +412,6 @@ my_get_property (GObject * o, g_value_set_object (value, p->battery); break; - case PROP_SOUND_PLAYER: - g_value_set_object (value, p->sound_player); - break; - default: G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec); } @@ -456,10 +431,6 @@ my_set_property (GObject * o, indicator_power_notifier_set_battery (self, g_value_get_object(value)); break; - case PROP_SOUND_PLAYER: - indicator_power_notifier_set_sound_player (self, g_value_get_object(value)); - break; - default: G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec); } @@ -478,7 +449,6 @@ my_dispose (GObject * o) } indicator_power_notifier_set_bus (self, NULL); - indicator_power_notifier_set_sound_player (self, NULL); notification_clear (self); indicator_power_notifier_set_battery (self, NULL); g_clear_object (&p->dbus_battery); @@ -552,13 +522,6 @@ indicator_power_notifier_class_init (IndicatorPowerNotifierClass * klass) G_TYPE_OBJECT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - properties[PROP_SOUND_PLAYER] = g_param_spec_object ( - PROP_SOUND_PLAYER_NAME, - "Sound Player", - "The current sound player", - G_TYPE_OBJECT, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, LAST_PROP, properties); } @@ -567,12 +530,9 @@ indicator_power_notifier_class_init (IndicatorPowerNotifierClass * klass) ***/ IndicatorPowerNotifier * -indicator_power_notifier_new (IndicatorPowerSoundPlayer * sound_player) +indicator_power_notifier_new (void) { - GObject * o = g_object_new (INDICATOR_TYPE_POWER_NOTIFIER, - PROP_SOUND_PLAYER_NAME, sound_player, - NULL); - + GObject * o = g_object_new (INDICATOR_TYPE_POWER_NOTIFIER, NULL); return INDICATOR_POWER_NOTIFIER (o); } @@ -610,26 +570,6 @@ indicator_power_notifier_set_battery (IndicatorPowerNotifier * self, } } -void -indicator_power_notifier_set_sound_player (IndicatorPowerNotifier * self, - IndicatorPowerSoundPlayer * sound_player) -{ - priv_t * p; - - g_return_if_fail(INDICATOR_IS_POWER_NOTIFIER(self)); - g_return_if_fail((sound_player == NULL) || INDICATOR_IS_POWER_SOUND_PLAYER(sound_player)); - - p = get_priv (self); - - if (p->sound_player == sound_player) - return; - - g_clear_object(&p->sound_player); - - if (sound_player != NULL) - p->sound_player = g_object_ref(sound_player); -} - void indicator_power_notifier_set_bus (IndicatorPowerNotifier * self, GDBusConnection * bus) diff --git a/src/notifier.h b/src/notifier.h index 602f6e5..1b04943 100644 --- a/src/notifier.h +++ b/src/notifier.h @@ -23,7 +23,6 @@ #include #include "device.h" -#include "sound-player.h" G_BEGIN_DECLS @@ -56,7 +55,7 @@ struct _IndicatorPowerNotifierClass GType indicator_power_notifier_get_type (void); -IndicatorPowerNotifier * indicator_power_notifier_new (IndicatorPowerSoundPlayer * sound_player); +IndicatorPowerNotifier * indicator_power_notifier_new (void); void indicator_power_notifier_set_bus (IndicatorPowerNotifier * self, GDBusConnection * connection); @@ -64,9 +63,6 @@ void indicator_power_notifier_set_bus (IndicatorPowerNotifier * self, void indicator_power_notifier_set_battery (IndicatorPowerNotifier * self, IndicatorPowerDevice * battery); -void indicator_power_notifier_set_sound_player (IndicatorPowerNotifier * self, - IndicatorPowerSoundPlayer * battery); - #define POWER_LEVEL_STR_OK "ok" #define POWER_LEVEL_STR_LOW "low" #define POWER_LEVEL_STR_VERY_LOW "very_low" diff --git a/src/sound-player-gst.c b/src/sound-player-gst.c deleted file mode 100644 index 25c3884..0000000 --- a/src/sound-player-gst.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright 2016 Canonical Ltd. - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3, as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - * - * Authors: - * Charles Kerr - */ - -#include "sound-player.h" -#include "sound-player-gst.h" - -#include - - -/*** -**** private struct -***/ - -typedef struct -{ - int unused; -} -IndicatorPowerSoundPlayerGSTPrivate; - -typedef IndicatorPowerSoundPlayerGSTPrivate priv_t; - -#define get_priv(o) ((priv_t*)indicator_power_sound_player_gst_get_instance_private(o)) - - -/*** -**** GObject boilerplate -***/ - -static void indicator_power_device_provider_interface_init ( - IndicatorPowerSoundPlayerInterface * iface); - -G_DEFINE_TYPE_WITH_CODE ( - IndicatorPowerSoundPlayerGST, - indicator_power_sound_player_gst, - G_TYPE_OBJECT, - G_ADD_PRIVATE(IndicatorPowerSoundPlayerGST) - G_IMPLEMENT_INTERFACE (INDICATOR_TYPE_POWER_SOUND_PLAYER, - indicator_power_device_provider_interface_init)) - -/*** -**** GSTREAMER -***/ - -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; -} - -/*** -**** IndicatorPowerSoundPlayer virtual functions -***/ - -static void -my_play_uri (IndicatorPowerSoundPlayer * self G_GNUC_UNUSED, const gchar * uri) -{ - GstElement * element; - GstBus * bus; - - /* create the element */ - 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); -} - -/*** -**** Instantiation -***/ - -static void -indicator_power_sound_player_gst_class_init (IndicatorPowerSoundPlayerGSTClass * klass) -{ - gst_init_once(); -} - -static void -indicator_power_device_provider_interface_init (IndicatorPowerSoundPlayerInterface * iface) -{ - iface->play_uri = my_play_uri; -} - -static void -indicator_power_sound_player_gst_init (IndicatorPowerSoundPlayerGST * self G_GNUC_UNUSED) -{ -} - -/*** -**** Public API -***/ - -IndicatorPowerSoundPlayer * -indicator_power_sound_player_gst_new(void) -{ - gpointer o = g_object_new (INDICATOR_TYPE_POWER_SOUND_PLAYER_GST, NULL); - - return INDICATOR_POWER_SOUND_PLAYER (o); -} diff --git a/src/sound-player-gst.h b/src/sound-player-gst.h deleted file mode 100644 index 3075738..0000000 --- a/src/sound-player-gst.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2016 Canonical Ltd. - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3, as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - * - * Authors: - * Charles Kerr - */ - -#ifndef __INDICATOR_POWER_SOUND_PLAYER_GST__H__ -#define __INDICATOR_POWER_SOUND_PLAYER_GST__H__ - -#include /* parent class */ - -#include "device-provider.h" - -G_BEGIN_DECLS - -#define INDICATOR_TYPE_POWER_SOUND_PLAYER_GST \ - (indicator_power_sound_player_gst_get_type()) - -#define INDICATOR_POWER_SOUND_PLAYER_GST(o) \ - (G_TYPE_CHECK_INSTANCE_CAST ((o), \ - INDICATOR_TYPE_POWER_SOUND_PLAYER_GST, \ - IndicatorPowerSoundPlayerGST)) - -#define INDICATOR_POWER_SOUND_PLAYER_GST_GET_CLASS(o) \ - (G_TYPE_INSTANCE_GET_CLASS ((o), \ - INDICATOR_TYPE_POWER_SOUND_PLAYER_GST, \ - IndicatorPowerSoundPlayerGSTClass)) - -#define INDICATOR_IS_POWER_SOUND_PLAYER_GST(o) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((o), \ - INDICATOR_TYPE_POWER_SOUND_PLAYER_GST)) - -typedef struct _IndicatorPowerSoundPlayerGST - IndicatorPowerSoundPlayerGST; -typedef struct _IndicatorPowerSoundPlayerGSTClass - IndicatorPowerSoundPlayerGSTClass; - -/** - * An IndicatorPowerSoundPlayer which gets its devices from GST. - */ -struct _IndicatorPowerSoundPlayerGST -{ - GObject parent_instance; -}; - -struct _IndicatorPowerSoundPlayerGSTClass -{ - GObjectClass parent_class; -}; - -GType indicator_power_sound_player_gst_get_type (void); - -IndicatorPowerSoundPlayer * indicator_power_sound_player_gst_new (void); - -G_END_DECLS - -#endif /* __INDICATOR_POWER_SOUND_PLAYER_GST__H__ */ diff --git a/src/sound-player.c b/src/sound-player.c deleted file mode 100644 index dcbb27b..0000000 --- a/src/sound-player.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2016 Canonical Ltd. - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3, as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - * - * Authors: - * Charles Kerr - */ - -#include "sound-player.h" - -G_DEFINE_INTERFACE (IndicatorPowerSoundPlayer, - indicator_power_sound_player, - 0) - -static void -indicator_power_sound_player_default_init (IndicatorPowerSoundPlayerInterface * klass G_GNUC_UNUSED) -{ -} - -/*** -**** PUBLIC API -***/ - -void -indicator_power_sound_player_play_uri (IndicatorPowerSoundPlayer * self, - const gchar * uri) -{ - IndicatorPowerSoundPlayerInterface * iface; - - g_return_if_fail (INDICATOR_IS_POWER_SOUND_PLAYER (self)); - iface = INDICATOR_POWER_SOUND_PLAYER_GET_INTERFACE (self); - g_return_if_fail (iface->play_uri != NULL); - iface->play_uri (self, uri); -} diff --git a/src/sound-player.h b/src/sound-player.h deleted file mode 100644 index adff924..0000000 --- a/src/sound-player.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2016 Canonical Ltd. - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3, as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - * - * Authors: - * Charles Kerr - */ - -#ifndef __INDICATOR_POWER_SOUND_PLAYER__H__ -#define __INDICATOR_POWER_SOUND_PLAYER__H__ - -#include - -G_BEGIN_DECLS - -#define INDICATOR_TYPE_POWER_SOUND_PLAYER \ - (indicator_power_sound_player_get_type ()) - -#define INDICATOR_POWER_SOUND_PLAYER(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - INDICATOR_TYPE_POWER_SOUND_PLAYER, \ - IndicatorPowerSoundPlayer)) - -#define INDICATOR_IS_POWER_SOUND_PLAYER(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INDICATOR_TYPE_POWER_SOUND_PLAYER)) - -#define INDICATOR_POWER_SOUND_PLAYER_GET_INTERFACE(inst) \ - (G_TYPE_INSTANCE_GET_INTERFACE ((inst), \ - INDICATOR_TYPE_POWER_SOUND_PLAYER, \ - IndicatorPowerSoundPlayerInterface)) - -typedef struct _IndicatorPowerSoundPlayer - IndicatorPowerSoundPlayer; - -typedef struct _IndicatorPowerSoundPlayerInterface - IndicatorPowerSoundPlayerInterface; - -/** - * An interface class for an object that plays sounds. - */ -struct _IndicatorPowerSoundPlayerInterface -{ - GTypeInterface parent_iface; - - /* virtual functions */ - void (*play_uri) (IndicatorPowerSoundPlayer * self, - const gchar * uri); -}; - -GType indicator_power_sound_player_get_type (void); - -/*** -**** -***/ - -void indicator_power_sound_player_play_uri (IndicatorPowerSoundPlayer * self, - const gchar * uri); - -G_END_DECLS - -#endif /* __INDICATOR_POWER_SOUND_PLAYER__H__ */ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 41e48cd..566132e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -9,13 +9,6 @@ include_directories (SYSTEM ${DBUSTEST_INCLUDE_DIRS}) # add warnings set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ${C_WARNING_ARGS}") -# build the mocks -set(MOCK_LIB "indicatorpowerservicemocks") -set(MOCK_SOURCES sound-player-mock.c) -set_source_files_properties(${MOCK_SOURCES} - PROPERTIES COMPILE_FLAGS "${C_WARNING_ARGS} -g -std=c99") -add_library(${MOCK_LIB} STATIC ${MOCK_SOURCES}) - # build the necessary schemas set_directory_properties (PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES gschemas.compiled) @@ -57,8 +50,8 @@ function(add_test_by_name name) add_executable (${TEST_NAME} ${TEST_NAME}.cc) target_link_options(${TEST_NAME} PRIVATE -no-pie) add_test (${TEST_NAME} ${TEST_NAME}) - add_dependencies (${TEST_NAME} ${MOCK_LIB} ayatanaindicatorpowerservice gschemas-compiled) - target_link_libraries (${TEST_NAME} ${MOCK_LIB} ayatanaindicatorpowerservice gtest ${DBUSTEST_LIBRARIES} ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBS} ${URLDISPATCHER_LIBRARIES} ${GMOCK_LIBRARIES}) + add_dependencies (${TEST_NAME} ayatanaindicatorpowerservice gschemas-compiled) + target_link_libraries (${TEST_NAME} ayatanaindicatorpowerservice gtest ${DBUSTEST_LIBRARIES} ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBS} ${URLDISPATCHER_LIBRARIES} ${GMOCK_LIBRARIES}) endfunction() add_test_by_name(test-notify) add_test(NAME dear-reader-the-next-test-takes-80-seconds COMMAND true) diff --git a/tests/sound-player-mock.c b/tests/sound-player-mock.c deleted file mode 100644 index 35c3b57..0000000 --- a/tests/sound-player-mock.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2016 Canonical Ltd. - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3, as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - * - * Authors: - * Charles Kerr - */ - -#include "sound-player.h" -#include "sound-player-mock.h" - -enum -{ - SIGNAL_URI_PLAYED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -/*** -**** GObject boilerplate -***/ - -static void indicator_power_sound_player_interface_init ( - IndicatorPowerSoundPlayerInterface * iface); - -G_DEFINE_TYPE_WITH_CODE ( - IndicatorPowerSoundPlayerMock, - indicator_power_sound_player_mock, - G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (INDICATOR_TYPE_POWER_SOUND_PLAYER, - indicator_power_sound_player_interface_init)) - -/*** -**** IndicatorPowerSoundPlayer virtual functions -***/ - -static void -my_play_uri (IndicatorPowerSoundPlayer * self, const gchar * uri) -{ - g_signal_emit (self, signals[SIGNAL_URI_PLAYED], 0, uri, NULL); -} - -/*** -**** Instantiation -***/ - -static void -indicator_power_sound_player_mock_class_init (IndicatorPowerSoundPlayerMockClass * klass G_GNUC_UNUSED) -{ - signals[SIGNAL_URI_PLAYED] = g_signal_new ( - "uri-played", - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (IndicatorPowerSoundPlayerMockClass, uri_played), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); -} - -static void -indicator_power_sound_player_interface_init (IndicatorPowerSoundPlayerInterface * iface) -{ - iface->play_uri = my_play_uri; -} - -static void -indicator_power_sound_player_mock_init (IndicatorPowerSoundPlayerMock * self G_GNUC_UNUSED) -{ -} - -/*** -**** Public API -***/ - -IndicatorPowerSoundPlayer * -indicator_power_sound_player_mock_new (void) -{ - gpointer o = g_object_new (INDICATOR_TYPE_POWER_SOUND_PLAYER_MOCK, NULL); - - return INDICATOR_POWER_SOUND_PLAYER (o); -} - diff --git a/tests/sound-player-mock.h b/tests/sound-player-mock.h deleted file mode 100644 index f844924..0000000 --- a/tests/sound-player-mock.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2016 Canonical Ltd. - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3, as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - * - * Authors: - * Charles Kerr - */ - -#ifndef __INDICATOR_POWER_SOUND_PLAYER_MOCK__H__ -#define __INDICATOR_POWER_SOUND_PLAYER_MOCK__H__ - -#include /* parent class */ - -#include "sound-player.h" - -G_BEGIN_DECLS - -#define INDICATOR_TYPE_POWER_SOUND_PLAYER_MOCK \ - (indicator_power_sound_player_mock_get_type()) - -#define INDICATOR_POWER_SOUND_PLAYER_MOCK(o) \ - (G_TYPE_CHECK_INSTANCE_CAST ((o), \ - INDICATOR_TYPE_POWER_SOUND_PLAYER_MOCK, \ - IndicatorPowerSoundPlayerMock)) - -#define INDICATOR_POWER_SOUND_PLAYER_MOCK_GET_CLASS(o) \ - (G_TYPE_INSTANCE_GET_CLASS ((o), \ - INDICATOR_TYPE_POWER_SOUND_PLAYER_MOCK, \ - IndicatorPowerSoundPlayerMockClass)) - -#define INDICATOR_IS_POWER_SOUND_PLAYER_MOCK(o) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((o), \ - INDICATOR_TYPE_POWER_SOUND_PLAYER_MOCK)) - -typedef struct _IndicatorPowerSoundPlayerMock - IndicatorPowerSoundPlayerMock; -typedef struct _IndicatorPowerSoundPlayerMockPriv - IndicatorPowerSoundPlayerMockPriv; -typedef struct _IndicatorPowerSoundPlayerMockClass - IndicatorPowerSoundPlayerMockClass; - -/** - * An IndicatorPowerSoundPlayer which gets its devices from Mock. - */ -struct _IndicatorPowerSoundPlayerMock -{ - GObject parent_instance; -}; - -struct _IndicatorPowerSoundPlayerMockClass -{ - GObjectClass parent_class; - - /* signals */ - void (*uri_played) (IndicatorPowerSoundPlayer * self, const gchar* uri); -}; - -GType indicator_power_sound_player_mock_get_type (void); - -IndicatorPowerSoundPlayer * indicator_power_sound_player_mock_new (void); - -G_END_DECLS - -#endif /* __INDICATOR_POWER_SOUND_PLAYER_MOCK__H__ */ diff --git a/tests/test-notify.cc b/tests/test-notify.cc index 0d92d7a..d01ef5f 100644 --- a/tests/test-notify.cc +++ b/tests/test-notify.cc @@ -23,7 +23,6 @@ #include "dbus-shared.h" #include "device.h" #include "notifier.h" -#include "sound-player-mock.h" #include @@ -160,6 +159,51 @@ protected: super::TearDown(); } + + /*** + **** + ***/ + + int get_notify_call_count() const + { + // confirm that we got exactly one call + guint len {0u}; + GError* error {nullptr}; + dbus_test_dbus_mock_object_get_method_calls(mock, obj, METHOD_NOTIFY, &len, &error); + g_assert_no_error(error); + return len; + } + + std::string get_notify_call_sound_file(int call_number) + { + std::string ret; + + guint len {0u}; + GError* error {nullptr}; + auto calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, METHOD_NOTIFY, &len, &error); + g_return_val_if_fail(int(len) > call_number, ret); + g_assert_no_error(error); + + constexpr int HINTS_PARAM_POSITION {6}; + const auto& call = calls[call_number]; + g_return_val_if_fail(g_variant_n_children(call.params) > HINTS_PARAM_POSITION, ret); + auto hints = g_variant_get_child_value(call.params, HINTS_PARAM_POSITION); + const gchar* sound_file = nullptr; + auto success = g_variant_lookup(hints, "sound-file", "&s", &sound_file); + g_return_val_if_fail(success, ret); + if (sound_file != nullptr) + ret = sound_file; + g_clear_pointer(&hints, g_variant_unref); + + return ret; + } + + void clear_method_calls() + { + GError* error{nullptr}; + ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, &error)); + g_assert_no_error(error); + } }; /*** @@ -278,8 +322,7 @@ TEST_F(NotifyFixture, LevelsDuringBatteryDrain) // set up a notifier and give it the battery so changing the battery's // charge should show up on the bus. - auto sound_player = indicator_power_sound_player_mock_new (); - auto notifier = indicator_power_notifier_new (sound_player); + auto notifier = indicator_power_notifier_new (); indicator_power_notifier_set_battery (notifier, battery); indicator_power_notifier_set_bus (notifier, bus); wait_msec(); @@ -323,21 +366,12 @@ TEST_F(NotifyFixture, LevelsDuringBatteryDrain) g_dbus_connection_signal_unsubscribe (bus, sub_tag); g_object_unref (battery); g_object_unref (notifier); - g_object_unref (sound_player); } /*** **** ***/ -namespace -{ - static void on_uri_played(IndicatorPowerSoundPlayer*, const char* uri, gpointer glast_uri) - { - *static_cast(glast_uri) = uri; - } -} - TEST_F(NotifyFixture, EventsThatChangeNotifications) { // GetCapabilities returns an array containing 'actions', so that we'll @@ -367,10 +401,7 @@ TEST_F(NotifyFixture, EventsThatChangeNotifications) // set up a notifier and give it the battery so changing the battery's // charge should show up on the bus. - std::string last_uri; - auto sound_player = indicator_power_sound_player_mock_new (); - g_signal_connect(sound_player, "uri-played", G_CALLBACK(on_uri_played), &last_uri); - auto notifier = indicator_power_notifier_new (sound_player); + auto notifier = indicator_power_notifier_new (); indicator_power_notifier_set_battery (notifier, battery); indicator_power_notifier_set_bus (notifier, bus); ChangedParams changed_params; @@ -388,7 +419,6 @@ TEST_F(NotifyFixture, EventsThatChangeNotifications) // test setup case wait_msec(); EXPECT_STREQ (POWER_LEVEL_STR_OK, changed_params.power_level.c_str()); - EXPECT_TRUE(last_uri.empty()); // change the percent past the 'low' threshold and confirm that // a) the power level changes @@ -399,48 +429,52 @@ TEST_F(NotifyFixture, EventsThatChangeNotifications) EXPECT_EQ (FIELD_POWER_LEVEL|FIELD_IS_WARNING, changed_params.fields); EXPECT_EQ (indicator_power_notifier_get_power_level(battery), changed_params.power_level); EXPECT_TRUE (changed_params.is_warning); - EXPECT_EQ (low_power_uri, last_uri); + EXPECT_EQ (1, get_notify_call_count()); + EXPECT_EQ (low_power_uri, get_notify_call_sound_file(0)); + clear_method_calls(); // now test that the warning changes if the level goes down even lower... - last_uri.clear(); changed_params = ChangedParams(); set_battery_percentage (battery, percent_very_low); wait_msec(); EXPECT_EQ (FIELD_POWER_LEVEL, changed_params.fields); EXPECT_STREQ (POWER_LEVEL_STR_VERY_LOW, changed_params.power_level.c_str()); - EXPECT_EQ (low_power_uri, last_uri); + EXPECT_EQ (1, get_notify_call_count()); + EXPECT_EQ (low_power_uri, get_notify_call_sound_file(0)); + clear_method_calls(); // ...and that the warning is taken down if the battery is plugged back in... - last_uri.clear(); + //last_uri.clear(); changed_params = ChangedParams(); g_object_set (battery, INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_CHARGING, nullptr); wait_msec(); EXPECT_EQ (FIELD_IS_WARNING, changed_params.fields); EXPECT_FALSE (changed_params.is_warning); - EXPECT_TRUE(last_uri.empty()); + EXPECT_EQ (0, get_notify_call_count()); // ...and that it comes back if we unplug again... - last_uri.clear(); + //last_uri.clear(); changed_params = ChangedParams(); g_object_set (battery, INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_DISCHARGING, nullptr); wait_msec(); EXPECT_EQ (FIELD_IS_WARNING, changed_params.fields); EXPECT_TRUE (changed_params.is_warning); - EXPECT_EQ (low_power_uri, last_uri); + EXPECT_EQ (1, get_notify_call_count()); + EXPECT_EQ (low_power_uri, get_notify_call_sound_file(0)); + clear_method_calls(); // ...and that it's taken down if the power level is OK - last_uri.clear(); + //last_uri.clear(); changed_params = ChangedParams(); set_battery_percentage (battery, percent_low+1); wait_msec(); EXPECT_EQ (FIELD_POWER_LEVEL|FIELD_IS_WARNING, changed_params.fields); EXPECT_STREQ (POWER_LEVEL_STR_OK, changed_params.power_level.c_str()); EXPECT_FALSE (changed_params.is_warning); - EXPECT_TRUE(last_uri.empty()); + EXPECT_EQ (0, get_notify_call_count()); // cleanup g_dbus_connection_signal_unsubscribe (bus, sub_tag); g_object_unref (notifier); g_object_unref (battery); - g_object_unref (sound_player); } -- cgit v1.2.3 From 557e10a031b886dc670bdf5918c3984edbace5ac Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 1 Feb 2016 12:24:34 -0600 Subject: remove dead code --- src/notifier.c | 2 ++ tests/test-notify.cc | 4 ---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/notifier.c b/src/notifier.c index 00a00e5..da5c5d5 100644 --- a/src/notifier.c +++ b/src/notifier.c @@ -311,7 +311,9 @@ notification_show(IndicatorPowerNotifier * self) if (are_actions_supported(self)) { + #ifdef HAS_UT_ACCTSERVICE_SYSTEMSOUND_SETTINGS if (!silent_mode(self)) + #endif { gchar* filename = datafile_find(DATAFILE_TYPE_SOUND, LOW_BATTERY_SOUND); if (filename != NULL) diff --git a/tests/test-notify.cc b/tests/test-notify.cc index d01ef5f..cd5b6f1 100644 --- a/tests/test-notify.cc +++ b/tests/test-notify.cc @@ -166,7 +166,6 @@ protected: int get_notify_call_count() const { - // confirm that we got exactly one call guint len {0u}; GError* error {nullptr}; dbus_test_dbus_mock_object_get_method_calls(mock, obj, METHOD_NOTIFY, &len, &error); @@ -444,7 +443,6 @@ TEST_F(NotifyFixture, EventsThatChangeNotifications) clear_method_calls(); // ...and that the warning is taken down if the battery is plugged back in... - //last_uri.clear(); changed_params = ChangedParams(); g_object_set (battery, INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_CHARGING, nullptr); wait_msec(); @@ -453,7 +451,6 @@ TEST_F(NotifyFixture, EventsThatChangeNotifications) EXPECT_EQ (0, get_notify_call_count()); // ...and that it comes back if we unplug again... - //last_uri.clear(); changed_params = ChangedParams(); g_object_set (battery, INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_DISCHARGING, nullptr); wait_msec(); @@ -464,7 +461,6 @@ TEST_F(NotifyFixture, EventsThatChangeNotifications) clear_method_calls(); // ...and that it's taken down if the power level is OK - //last_uri.clear(); changed_params = ChangedParams(); set_battery_percentage (battery, percent_low+1); wait_msec(); -- cgit v1.2.3 From 39571b0e05c78627d233b2f77250de459d73f4a6 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 16 May 2016 12:59:03 -0500 Subject: fix cmake warning of the test apps' dependency on the service library --- CMakeLists.txt | 13 ++++++++++--- src/CMakeLists.txt | 5 ----- src/notifier.c | 2 +- tests/CMakeLists.txt | 4 ++-- tests/test-device.cc | 4 ++-- tests/test-notify.cc | 4 +--- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bc5729a..258a111 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,14 +40,21 @@ set (CMAKE_INSTALL_FULL_PKGLIBEXECDIR "${CMAKE_INSTALL_FULL_LIBEXECDIR}/${CMAKE_ ## set(GETTEXT_PACKAGE "ayatana-indicator-power") -add_definitions (-DGETTEXT_PACKAGE="${GETTEXT_PACKAGE}" - -DLOCALEDIR="${CMAKE_INSTALL_FULL_LOCALEDIR}" - -DLOW_BATTERY_SOUND="Low battery.ogg") +add_definitions( + -DGETTEXT_PACKAGE="${GETTEXT_PACKAGE}" + -DG_LOG_DOMAIN="${GETTEXT_PACKAGE}" + -DLOCALEDIR="${CMAKE_INSTALL_FULL_LOCALEDIR}" + -DLOW_BATTERY_SOUND="Low battery.ogg" +) ## ## Check for prerequisites ## +set(SERVICE_LIB "ayatanaindicatorpowerservice") +set(SERVICE_EXEC "ayatana-indicator-power-service") +add_definitions(-DSERVICE_EXEC="${SERVICE_EXEC}") + find_package (PkgConfig REQUIRED) include (CheckIncludeFile) include (FindPkgConfig) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a5e6c57..bf85b77 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,8 +1,3 @@ -set (SERVICE_LIB "ayatanaindicatorpowerservice") -set (SERVICE_EXEC "ayatana-indicator-power-service") - -add_definitions(-DG_LOG_DOMAIN="ayatana-indicator-power") - if(URLDISPATCHER_FOUND) add_definitions( -DHAS_URLDISPATCHER ) endif() diff --git a/src/notifier.c b/src/notifier.c index da5c5d5..d982ac2 100644 --- a/src/notifier.c +++ b/src/notifier.c @@ -489,7 +489,7 @@ indicator_power_notifier_init (IndicatorPowerNotifier * self) p->cancellable = g_cancellable_new(); - if (!instance_count++ && !notify_init("ayatana-indicator-power-service")) + if (!instance_count++ && !notify_init(SERVICE_EXEC)) g_critical("Unable to initialize libnotify! Notifications might not be shown."); #ifdef HAS_UT_ACCTSERVICE_SYSTEMSOUND_SETTINGS diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 566132e..d7be386 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -50,8 +50,8 @@ function(add_test_by_name name) add_executable (${TEST_NAME} ${TEST_NAME}.cc) target_link_options(${TEST_NAME} PRIVATE -no-pie) add_test (${TEST_NAME} ${TEST_NAME}) - add_dependencies (${TEST_NAME} ayatanaindicatorpowerservice gschemas-compiled) - target_link_libraries (${TEST_NAME} ayatanaindicatorpowerservice gtest ${DBUSTEST_LIBRARIES} ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBS} ${URLDISPATCHER_LIBRARIES} ${GMOCK_LIBRARIES}) + add_dependencies (${TEST_NAME} ${SERVICE_LIB} gschemas-compiled) + target_link_libraries (${TEST_NAME} ${SERVICE_LIB} gtest ${DBUSTEST_LIBRARIES} ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBS} ${URLDISPATCHER_LIBRARIES} ${GMOCK_LIBRARIES}) endfunction() add_test_by_name(test-notify) add_test(NAME dear-reader-the-next-test-takes-80-seconds COMMAND true) diff --git a/tests/test-device.cc b/tests/test-device.cc index bdc29d1..a948857 100644 --- a/tests/test-device.cc +++ b/tests/test-device.cc @@ -53,7 +53,7 @@ class DeviceTest : public ::testing::Test virtual void SetUp() { const GLogLevelFlags flags = GLogLevelFlags(G_LOG_LEVEL_CRITICAL|G_LOG_LEVEL_WARNING); - log_handler_id = g_log_set_handler ("ayatana-indicator-power", flags, log_count_func, this); + log_handler_id = g_log_set_handler(G_LOG_DOMAIN, flags, log_count_func, this); log_count_ipower_expected = 0; log_count_ipower_actual = 0; } @@ -61,7 +61,7 @@ class DeviceTest : public ::testing::Test virtual void TearDown() { ASSERT_EQ (log_count_ipower_expected, log_count_ipower_actual); - g_log_remove_handler ("ayatana-indicator-power", log_handler_id); + g_log_remove_handler (G_LOG_DOMAIN, log_handler_id); } protected: diff --git a/tests/test-notify.cc b/tests/test-notify.cc index cd5b6f1..8d7f0d8 100644 --- a/tests/test-notify.cc +++ b/tests/test-notify.cc @@ -61,8 +61,6 @@ protected: static constexpr int NOTIFICATION_CLOSED_API {3}; static constexpr int NOTIFICATION_CLOSED_UNDEFINED {4}; - static constexpr char const * APP_NAME {"ayatana-indicator-power-service"}; - static constexpr char const * METHOD_CLOSE {"CloseNotification"}; static constexpr char const * METHOD_NOTIFY {"Notify"}; static constexpr char const * METHOD_GET_CAPS {"GetCapabilities"}; @@ -135,7 +133,7 @@ protected: g_dbus_connection_set_exit_on_close(bus, FALSE); g_object_add_weak_pointer(G_OBJECT(bus), reinterpret_cast(&bus)); - notify_init(APP_NAME); + notify_init(SERVICE_EXEC); } virtual void TearDown() -- cgit v1.2.3 From bcdc3cc3466c1e4802a4ec84e1d5d5aacc531cbf Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 16 May 2016 13:05:19 -0500 Subject: housekeeping: sync tests/glib-fixture with the up-to-date version in indicator-datetime --- tests/glib-fixture.h | 201 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 144 insertions(+), 57 deletions(-) diff --git a/tests/glib-fixture.h b/tests/glib-fixture.h index 9494df2..7f63473 100644 --- a/tests/glib-fixture.h +++ b/tests/glib-fixture.h @@ -1,5 +1,8 @@ /* - * Copyright 2014 Canonical Ltd. + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published @@ -12,12 +15,14 @@ * * You should have received a copy of the GNU General Public License along * with this program. If not, see . - * - * Authors: - * Charles Kerr */ +#pragma once + +#include +#include // std::function #include +#include // std::shared_ptr #include #include @@ -29,79 +34,48 @@ class GlibFixture : public ::testing::Test { - private: + public: - GLogFunc realLogHandler; - - std::map expected_log; - std::map> log; - - void test_log_counts() - { - const GLogLevelFlags levels_to_test[] = { G_LOG_LEVEL_ERROR, - G_LOG_LEVEL_CRITICAL, - G_LOG_LEVEL_MESSAGE, - G_LOG_LEVEL_WARNING }; - - for(const auto& level : levels_to_test) - { - const auto& v = log[level]; - const auto n = v.size(); - - EXPECT_EQ(expected_log[level], n); - - if (expected_log[level] != n) - for (size_t i=0; i(self)->log[log_level].push_back(tmp); - g_free(tmp); - } + virtual ~GlibFixture() =default; protected: - void increment_expected_errors(GLogLevelFlags level, size_t n=1) - { - expected_log[level] += n; - } - - virtual void SetUp() + virtual void SetUp() override { setlocale(LC_ALL, "C.UTF-8"); loop = g_main_loop_new(nullptr, false); - g_log_set_default_handler(default_log_handler, this); + // only use local, temporary settings + g_assert(g_setenv("GSETTINGS_SCHEMA_DIR", SCHEMA_DIR, true)); + g_assert(g_setenv("GSETTINGS_BACKEND", "memory", true)); + g_debug("SCHEMA_DIR is %s", SCHEMA_DIR); + + // fail on unexpected messages from this domain + g_log_set_fatal_mask(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING); g_unsetenv("DISPLAY"); + } - virtual void TearDown() + virtual void TearDown() override { - test_log_counts(); - - g_log_set_default_handler(realLogHandler, this); + g_test_assert_expected_messages (); g_clear_pointer(&loop, g_main_loop_unref); } + void expectLogMessage (const gchar *domain, GLogLevelFlags level, const gchar *pattern) + { + g_test_expect_message (domain, level, pattern); + } + private: static gboolean wait_for_signal__timeout(gpointer name) { - g_error("%s: timed out waiting for signal '%s'", G_STRLOC, static_cast(name)); + g_error("%s: timed out waiting for signal '%s'", G_STRLOC, (char*)name); return G_SOURCE_REMOVE; } @@ -115,7 +89,7 @@ class GlibFixture : public ::testing::Test protected: /* convenience func to loop while waiting for a GObject's signal */ - void wait_for_signal(gpointer o, const gchar * signal, const guint timeout_seconds=5) + void wait_for_signal(gpointer o, const gchar * signal, const int timeout_seconds=5) { // wait for the signal or for timeout, whichever comes first const auto handler_id = g_signal_connect_swapped(o, signal, @@ -130,12 +104,125 @@ class GlibFixture : public ::testing::Test } /* convenience func to loop for N msec */ - void wait_msec(guint msec=50) + void wait_msec(int msec=50) { const auto id = g_timeout_add(msec, wait_msec__timeout, loop); g_main_loop_run(loop); g_source_remove(id); } - GMainLoop * loop; + bool wait_for(std::function test_function, guint timeout_msec=1000) + { + auto timer = std::shared_ptr(g_timer_new(), [](GTimer* t){g_timer_destroy(t);}); + const auto timeout_sec = timeout_msec / 1000.0; + for (;;) { + if (test_function()) + return true; + //g_message("%f ... %f", g_timer_elapsed(timer.get(), nullptr), timeout_sec); + if (g_timer_elapsed(timer.get(), nullptr) >= timeout_sec) + return false; + wait_msec(); + } + } + + bool wait_for_name_owned( + GDBusConnection* connection, + const gchar* name, + guint timeout_msec=1000, + GBusNameWatcherFlags flags=G_BUS_NAME_WATCHER_FLAGS_AUTO_START) + { + struct Data { + GMainLoop* loop = nullptr; + bool owned = false; + }; + Data data; + + auto on_name_appeared = [](GDBusConnection* /*connection*/, + const gchar* /*name_*/, + const gchar* name_owner, + gpointer gdata){ + if (name_owner == nullptr) + return; + auto tmp = static_cast(gdata); + tmp->owned = true; + g_main_loop_quit(tmp->loop); + }; + + const auto timeout_id = g_timeout_add(timeout_msec, wait_msec__timeout, loop); + data.loop = loop; + const auto watch_id = g_bus_watch_name_on_connection( + connection, + name, + flags, + on_name_appeared, + nullptr, // name_vanished + &data, + nullptr // user_data_free_func + ); + + g_main_loop_run(loop); + + g_bus_unwatch_name(watch_id); + g_source_remove(timeout_id); + + return data.owned; + } + + void EXPECT_NAME_OWNED_EVENTUALLY(GDBusConnection* connection, + const gchar* name, + guint timeout_msec=1000, + GBusNameWatcherFlags flags=G_BUS_NAME_WATCHER_FLAGS_AUTO_START) + { + EXPECT_TRUE(wait_for_name_owned(connection, name, timeout_msec, flags)) << "name: " << name; + } + + void EXPECT_NAME_NOT_OWNED_EVENTUALLY(GDBusConnection* connection, + const gchar* name, + guint timeout_msec=1000, + GBusNameWatcherFlags flags=G_BUS_NAME_WATCHER_FLAGS_AUTO_START) + { + EXPECT_FALSE(wait_for_name_owned(connection, name, timeout_msec, flags)) << "name: " << name; + } + + void ASSERT_NAME_OWNED_EVENTUALLY(GDBusConnection* connection, + const gchar* name, + guint timeout_msec=1000, + GBusNameWatcherFlags flags=G_BUS_NAME_WATCHER_FLAGS_AUTO_START) + { + ASSERT_TRUE(wait_for_name_owned(connection, name, timeout_msec, flags)) << "name: " << name; + } + + void ASSERT_NAME_NOT_OWNED_EVENTUALLY(GDBusConnection* connection, + const gchar* name, + guint timeout_msec=1000, + GBusNameWatcherFlags flags=G_BUS_NAME_WATCHER_FLAGS_AUTO_START) + { + ASSERT_FALSE(wait_for_name_owned(connection, name, timeout_msec, flags)) << "name: " << name; + } + + using source_func = std::function; + + guint idle_add(source_func&& func) + { + return g_idle_add_full( + G_PRIORITY_DEFAULT_IDLE, + [](gpointer gf){return (*static_cast(gf))();}, + new std::function(func), + [](gpointer gf){delete static_cast(gf);} + ); + } + + guint timeout_add(source_func&& func, std::chrono::milliseconds msec) + { + return g_timeout_add_full( + G_PRIORITY_DEFAULT, + msec.count(), + [](gpointer gf){return (*static_cast(gf))();}, + new std::function(func), + [](gpointer gf){delete static_cast(gf);} + ); + } + + GMainLoop* loop {}; }; + -- cgit v1.2.3 From 4a4663acffea728b2d147447de32703f42a774bf Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 16 May 2016 13:09:57 -0500 Subject: since we're shopping audio out to org.freedesktop notifications, drop the gstreamer build dep --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 258a111..956c724 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,7 +64,6 @@ 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}) -- cgit v1.2.3 From ecb73d5a817e47598635523bfb04a8ac9c7ac5a9 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 16 May 2016 16:28:14 -0500 Subject: fix glib-fixture.h copyright year in header comment --- tests/glib-fixture.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/glib-fixture.h b/tests/glib-fixture.h index 7f63473..2350d49 100644 --- a/tests/glib-fixture.h +++ b/tests/glib-fixture.h @@ -1,5 +1,5 @@ /* - * Copyright 2013 Canonical Ltd. + * Copyright 2013-2016 Canonical Ltd. * * Authors: * Charles Kerr -- cgit v1.2.3 From 948a5107c479a72a2940316674fae6a3b55534ff Mon Sep 17 00:00:00 2001 From: Rodney <6557070+dobey@users.noreply.github.com> Date: Sun, 28 Oct 2018 13:54:40 -0400 Subject: Pull in many fixes from the bionic branch. (#7) * Pay attention to $SNAP prefix * Releasing 12.10.6+17.04.20161201-0ubuntu1 * give sorting priority to devices with power supplies * Releasing 12.10.6+17.04.20170116-0ubuntu1 * Remove old autostart files. * Use gmock module from cmake-extras. * Use coverage support from cmake-extras. * Add gcovr and lcov dependencies. * Use intltool support from cmake-extras. * Remove usage of extra GCOV variables. * Remove hard-coded -g compiler flag. * Releasing 12.10.6+17.04.20170210-0ubuntu1 * no change rebuild * Releasing 12.10.6+17.04.20170322-0ubuntu1 * Start indicator in systemd when indicators.target is started * Build for bionic * This is still xenial. * Update translations from launchpad too. --- CMakeLists.txt | 2 +- src/CMakeLists.txt | 2 +- src/service.c | 14 +++++++------- tests/CMakeLists.txt | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 956c724..72f4bde 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -125,7 +125,7 @@ if (ENABLE_TESTS) if (ENABLE_COVERAGE) find_package(CoverageReport) ENABLE_COVERAGE_REPORT( - TARGETS ayatanaindicatorpowerservice ayatana-indicator-power-service + TARGETS ${SERVICE_LIB} ${SERVICE_EXEC} TESTS ${COVERAGE_TEST_TARGETS} FILTER /usr/include ${CMAKE_BINARY_DIR}/* ) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bf85b77..b253d0a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -48,7 +48,7 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}) set(C_WARNING_ARGS "${C_WARNING_ARGS} -Wno-bad-function-cast") # g_clear_object() set(C_WARNING_ARGS "${C_WARNING_ARGS} -Wno-switch-enum") set_source_files_properties(${SERVICE_MANUAL_SOURCES} - PROPERTIES COMPILE_FLAGS "${C_WARNING_ARGS} -g -std=c99") + PROPERTIES COMPILE_FLAGS "${C_WARNING_ARGS} -std=c99") # the service library for tests to link against (basically, everything except main()) add_library(${SERVICE_LIB} STATIC ${SERVICE_MANUAL_SOURCES} ${SERVICE_GENERATED_SOURCES}) diff --git a/src/service.c b/src/service.c index c04122f..9b99a05 100644 --- a/src/service.c +++ b/src/service.c @@ -163,12 +163,12 @@ get_device_kind_weight (const IndicatorPowerDevice * device) } /* sort devices from most interesting to least interesting on this criteria: - 1. discharging items from least time remaining until most time remaining - 2. charging items from most time left to charge to least time left to charge - 3. charging items with an unknown time remaining - 4. discharging items with an unknown time remaining, but 10% or below - 5. batteries, then non-line power, then line-power - 6. discharging items with an unknown time remaining, but above 10% */ + 1. device that supplied the power to the system + 2. discharging items from least time remaining until most time remaining + 3. charging items from most time left to charge to least time left to charge + 4. charging items with an unknown time remaining + 5. discharging items with an unknown time remaining + 6. batteries, then non-line power, then line-power */ static gint device_compare_func (gconstpointer ga, gconstpointer gb) { @@ -600,7 +600,7 @@ create_brightness_menu_item(void) GMenuItem * item; item = g_menu_item_new(NULL, "indicator.brightness"); - g_menu_item_set_attribute(item, "x-ayatana-type", "s", "org.ayatana.unity.slider"); + g_menu_item_set_attribute(item, "x-ayatana-type", "s", "org.ayatana.indicator.slider"); g_menu_item_set_attribute(item, "min-value", "d", 0.0); g_menu_item_set_attribute(item, "max-value", "d", 1.0); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d7be386..9c0d222 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -51,7 +51,7 @@ function(add_test_by_name name) target_link_options(${TEST_NAME} PRIVATE -no-pie) add_test (${TEST_NAME} ${TEST_NAME}) add_dependencies (${TEST_NAME} ${SERVICE_LIB} gschemas-compiled) - target_link_libraries (${TEST_NAME} ${SERVICE_LIB} gtest ${DBUSTEST_LIBRARIES} ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBS} ${URLDISPATCHER_LIBRARIES} ${GMOCK_LIBRARIES}) + target_link_libraries (${TEST_NAME} ${SERVICE_LIB} ${DBUSTEST_LIBRARIES} ${SERVICE_DEPS_LIBRARIES} ${URLDISPATCHER_LIBRARIES} ${GMOCK_LIBRARIES}) endfunction() add_test_by_name(test-notify) add_test(NAME dear-reader-the-next-test-takes-80-seconds COMMAND true) -- cgit v1.2.3 From 333a4273eb26ffc47b29f3ea8ce3213d36803894 Mon Sep 17 00:00:00 2001 From: Jami Kettunen Date: Fri, 16 Oct 2020 23:54:54 +0300 Subject: flashlight: Add support for simpler sysfs toggles (#34) Unlike the overcomplicated Qualcomm mess, there are also simpler sysfs toggles which you can just write 1/0 to when enabling/disabling the flash. This is used by the MediaTek flashlight_core driver on the Volla Phone (Helio P23 / MT6763) for example, which this also adds support for. Pinephone also uses a simple sysfs toggle for flashlight. --- src/flashlight.c | 70 ++++++++++++++++++++++++++++++++++++++++++++------------ src/flashlight.h | 9 ++++++++ 2 files changed, 65 insertions(+), 14 deletions(-) diff --git a/src/flashlight.c b/src/flashlight.c index 55a108a..8aba2b5 100644 --- a/src/flashlight.c +++ b/src/flashlight.c @@ -26,6 +26,8 @@ #define QCOM_ENABLE "255" #define QCOM_DISABLE "0" +#define SIMPLE_ENABLE "1" +#define SIMPLE_DISABLE "0" const size_t qcom_sysfs_size = 5; const char* const qcom_sysfs[] = {"/sys/class/leds/torch-light/brightness", @@ -33,10 +35,14 @@ const char* const qcom_sysfs[] = {"/sys/class/leds/torch-light/brightness", "/sys/class/leds/flashlight/brightness", "/sys/class/leds/torch-light0/brightness", "/sys/class/leds/torch-light1/brightness"}; - const char* qcom_torch_enable = "/sys/class/leds/led:switch/brightness"; +const size_t simple_sysfs_size = 2; +const char* const simple_sysfs[] = {"/sys/class/flashlight_core/flashlight/flashlight_torch", + "/sys/class/leds/white:flash/brightness"}; + char* flash_sysfs_path = NULL; +enum TorchType torch_type = SIMPLE; gboolean activated = 0; int @@ -45,6 +51,13 @@ set_sysfs_path() for (size_t i = 0; i < qcom_sysfs_size; i++) { if (access(qcom_sysfs[i], F_OK ) != -1){ flash_sysfs_path = (char*)qcom_sysfs[i]; + torch_type = QCOM; + return 1; + } + } + for (size_t i = 0; i < simple_sysfs_size; i++) { + if (access(simple_sysfs[i], F_OK ) != -1){ + flash_sysfs_path = (char*)simple_sysfs[i]; return 1; } } @@ -57,22 +70,12 @@ flashlight_activated() return activated; } -void -toggle_flashlight_action(GAction *action, - GVariant *parameter G_GNUC_UNUSED, - gpointer data G_GNUC_UNUSED) +int +toggle_flashlight_action_qcom() { - GVariant *state; FILE *fd1 = NULL, *fd2 = NULL; - int needs_enable; - if (!set_sysfs_path()) - return; - - state = g_action_get_state(action); - activated = g_variant_get_boolean(state); - g_variant_unref(state); fd1 = fopen(flash_sysfs_path, "w"); if (fd1 != NULL) { needs_enable = access(qcom_torch_enable, F_OK ) != -1; @@ -91,8 +94,47 @@ toggle_flashlight_action(GAction *action, fclose(fd1); if (fd2 !=NULL) fclose(fd2); - g_action_change_state(action, g_variant_new_boolean(!activated)); + return 1; } + return 0; +} + +int +toggle_flashlight_action_simple() +{ + FILE *fd = NULL; + + fd = fopen(flash_sysfs_path, "w"); + if (fd != NULL) { + fprintf(fd, activated ? SIMPLE_DISABLE : SIMPLE_ENABLE); + fclose(fd); + return 1; + } + return 0; +} + +void +toggle_flashlight_action(GAction *action, + GVariant *parameter G_GNUC_UNUSED, + gpointer data G_GNUC_UNUSED) +{ + GVariant *state; + int toggled; + + if (!set_sysfs_path()) + return; + + state = g_action_get_state(action); + activated = g_variant_get_boolean(state); + g_variant_unref(state); + + if (torch_type == QCOM) + toggled = toggle_flashlight_action_qcom(); + else + toggled = toggle_flashlight_action_simple(); + + if (toggled) + g_action_change_state(action, g_variant_new_boolean(!activated)); } int diff --git a/src/flashlight.h b/src/flashlight.h index 51ed5e7..19f738e 100644 --- a/src/flashlight.h +++ b/src/flashlight.h @@ -24,6 +24,12 @@ G_BEGIN_DECLS +int +toggle_flashlight_action_qcom(); + +int +toggle_flashlight_action_simple(); + void toggle_flashlight_action(GAction *action, GVariant *parameter G_GNUC_UNUSED, @@ -35,6 +41,9 @@ flashlight_supported(); gboolean flashlight_activated(); +enum +TorchType { SIMPLE = 1, QCOM }; + G_END_DECLS #endif /* INDICATOR_POWER_FLASHLIGHT__H */ -- cgit v1.2.3 From 2432f6b35d49b5f7f270a2408f26bbb658541a9d Mon Sep 17 00:00:00 2001 From: Jami Kettunen Date: Thu, 3 Dec 2020 03:27:13 +0200 Subject: flashlight: Add support for PM8998 based SoCs These sysfs and switch paths are used on Qualcomm SoCs which contain a PM8998 PMIC block. This at the very least includes the Snapdragon 835 (MSM8998) and Snapdragon 845 (SDM845). This was tested as working on the OnePlus 5 (MSM8998) and OnePlus 6 (SDM845) smartphones. --- src/flashlight.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/flashlight.c b/src/flashlight.c index 8aba2b5..064bd31 100644 --- a/src/flashlight.c +++ b/src/flashlight.c @@ -29,19 +29,25 @@ #define SIMPLE_ENABLE "1" #define SIMPLE_DISABLE "0" -const size_t qcom_sysfs_size = 5; +const size_t qcom_sysfs_size = 7; const char* const qcom_sysfs[] = {"/sys/class/leds/torch-light/brightness", "/sys/class/leds/led:flash_torch/brightness", "/sys/class/leds/flashlight/brightness", "/sys/class/leds/torch-light0/brightness", - "/sys/class/leds/torch-light1/brightness"}; -const char* qcom_torch_enable = "/sys/class/leds/led:switch/brightness"; + "/sys/class/leds/torch-light1/brightness", + "/sys/class/leds/led:torch_0/brightness", + "/sys/class/leds/led:torch_1/brightness"}; +const size_t qcom_switch_size = 2; +const char* const qcom_switch[] = {"/sys/class/leds/led:switch/brightness", + "/sys/class/leds/led:switch_0/brightness"}; const size_t simple_sysfs_size = 2; const char* const simple_sysfs[] = {"/sys/class/flashlight_core/flashlight/flashlight_torch", "/sys/class/leds/white:flash/brightness"}; char* flash_sysfs_path = NULL; +char* qcom_switch_path = NULL; + enum TorchType torch_type = SIMPLE; gboolean activated = 0; @@ -52,6 +58,11 @@ set_sysfs_path() if (access(qcom_sysfs[i], F_OK ) != -1){ flash_sysfs_path = (char*)qcom_sysfs[i]; torch_type = QCOM; + /* Qualcomm torch; determine switch file (if one is needed) */ + for (size_t i = 0; i < qcom_switch_size; i++) { + if (access(qcom_switch[i], F_OK ) != -1) + qcom_switch_path = (char*)qcom_switch[i]; + } return 1; } } @@ -78,9 +89,9 @@ toggle_flashlight_action_qcom() fd1 = fopen(flash_sysfs_path, "w"); if (fd1 != NULL) { - needs_enable = access(qcom_torch_enable, F_OK ) != -1; + needs_enable = access(qcom_switch_path, F_OK ) != -1; if (needs_enable) - fd2 = fopen(qcom_torch_enable, "w"); + fd2 = fopen(qcom_switch_path, "w"); if (activated) if (needs_enable && fd2 != NULL) fprintf(fd2, "0"); -- cgit v1.2.3 From d5a53027e58b6153b86b6c4b832cfd393bcdefb0 Mon Sep 17 00:00:00 2001 From: Robert Tari Date: Tue, 27 Jul 2021 21:43:00 +0200 Subject: Rename com.canonical.powerd -> com.lomiri.Repowerd --- src/CMakeLists.txt | 6 ++-- src/brightness.c | 28 +++++++-------- src/com.canonical.powerd.xml | 84 -------------------------------------------- src/com.lomiri.Repowerd.xml | 84 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 101 insertions(+), 101 deletions(-) delete mode 100644 src/com.canonical.powerd.xml create mode 100644 src/com.lomiri.Repowerd.xml diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b253d0a..d6e3c7b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -19,10 +19,10 @@ set(SERVICE_MANUAL_SOURCES # generated sources include(GdbusCodegen) set(SERVICE_GENERATED_SOURCES) -add_gdbus_codegen_with_namespace(SERVICE_GENERATED_SOURCES dbus-powerd - com.canonical +add_gdbus_codegen_with_namespace(SERVICE_GENERATED_SOURCES dbus-repowerd + com.lomiri Dbus - ${CMAKE_SOURCE_DIR}/src/com.canonical.powerd.xml) + ${CMAKE_SOURCE_DIR}/src/com.lomiri.Repowerd.xml) add_gdbus_codegen_with_namespace(SERVICE_GENERATED_SOURCES dbus-battery org.ayatana.indicator.power Dbus diff --git a/src/brightness.c b/src/brightness.c index eb48515..4b00568 100644 --- a/src/brightness.c +++ b/src/brightness.c @@ -18,7 +18,7 @@ */ #include "brightness.h" -#include "dbus-powerd.h" +#include "dbus-repowerd.h" #include @@ -46,7 +46,7 @@ typedef struct GSettings * settings; - DbusPowerd * powerd_proxy; + DbusRepowerd * powerd_proxy; char * powerd_name_owner; double percentage; @@ -198,7 +198,7 @@ percentage_to_brightness(IndicatorPowerBrightness * self, double percentage) } /** - * DBus Chatter: com.canonical.powerd + * DBus Chatter: com.lomiri.Repowerd * * This is used to get default value, and upper and lower bounds, * of the brightness setting @@ -217,7 +217,7 @@ on_powerd_brightness_params_ready(GObject * oproxy, v = NULL; error = NULL; - if (dbus_powerd_call_get_brightness_params_finish(DBUS_POWERD(oproxy), &v, res, &error)) + if (dbus_repowerd_call_get_brightness_params_finish(DBUS_REPOWERD(oproxy), &v, res, &error)) { IndicatorPowerBrightness * self = INDICATOR_POWER_BRIGHTNESS(gself); priv_t * p = get_priv(self); @@ -235,12 +235,12 @@ on_powerd_brightness_params_ready(GObject * oproxy, p->powerd_max, p->powerd_default_value, (int)p->powerd_ab_supported); - + if (old_ab_supported != p->powerd_ab_supported) g_object_notify_by_pspec(G_OBJECT(self), properties[PROP_AUTO_SUPPORTED]); if (p->settings != NULL) - { + { if (g_settings_get_boolean(p->settings, KEY_NEED_DEFAULT)) { /* user's first session, so init the schema's default @@ -282,7 +282,7 @@ on_powerd_name_owner_changed(GDBusProxy * powerd_proxy, if (owner != NULL) { - dbus_powerd_call_get_brightness_params(DBUS_POWERD(powerd_proxy), + dbus_repowerd_call_get_brightness_params(DBUS_REPOWERD(powerd_proxy), p->cancellable, on_powerd_brightness_params_ready, gself); @@ -294,11 +294,11 @@ on_powerd_name_owner_changed(GDBusProxy * powerd_proxy, } static void -on_powerd_brightness_changed(DbusPowerd * powerd_proxy, +on_powerd_brightness_changed(DbusRepowerd * powerd_proxy, GParamSpec * pspec G_GNUC_UNUSED, gpointer gself) { - set_brightness_local(gself, dbus_powerd_get_brightness(powerd_proxy)); + set_brightness_local(gself, dbus_repowerd_get_brightness(powerd_proxy)); } static void @@ -307,10 +307,10 @@ on_powerd_proxy_ready(GObject * source_object G_GNUC_UNUSED, gpointer gself) { GError * error; - DbusPowerd * powerd_proxy; + DbusRepowerd * powerd_proxy; error = NULL; - powerd_proxy = dbus_powerd_proxy_new_for_bus_finish(res, &error); + powerd_proxy = dbus_repowerd_proxy_new_for_bus_finish(res, &error); if (powerd_proxy != NULL) { @@ -461,10 +461,10 @@ indicator_power_brightness_init(IndicatorPowerBrightness * self) g_settings_schema_unref(schema); } - dbus_powerd_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + dbus_repowerd_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES, - "com.canonical.powerd", - "/com/canonical/powerd", + "com.lomiri.Repowerd", + "/com/lomiri/Repowerd", p->cancellable, on_powerd_proxy_ready, self); diff --git a/src/com.canonical.powerd.xml b/src/com.canonical.powerd.xml deleted file mode 100644 index b5b4ac4..0000000 --- a/src/com.canonical.powerd.xml +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/com.lomiri.Repowerd.xml b/src/com.lomiri.Repowerd.xml new file mode 100644 index 0000000..377eeab --- /dev/null +++ b/src/com.lomiri.Repowerd.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3