Merge lp:~charlesk/indicator-power/lp-1470767-low-battery-sound into lp:indicator-power/15.10

Proposed by Charles Kerr
Status: Merged
Approved by: Ted Gould
Approved revision: 314
Merged at revision: 291
Proposed branch: lp:~charlesk/indicator-power/lp-1470767-low-battery-sound
Merge into: lp:indicator-power/15.10
Diff against target: 1500 lines (+939/-31)
20 files modified
CMakeLists.txt (+3/-1)
data/CMakeLists.txt (+9/-0)
debian/control (+3/-0)
src/CMakeLists.txt (+9/-1)
src/datafiles.c (+71/-0)
src/datafiles.h (+37/-0)
src/main.c (+14/-6)
src/notifier.c (+150/-4)
src/notifier.h (+6/-2)
src/service.c (+50/-9)
src/service.h (+6/-1)
src/sound-player-gst.c (+173/-0)
src/sound-player-gst.h (+70/-0)
src/sound-player.c (+45/-0)
src/sound-player.h (+72/-0)
tests/CMakeLists.txt (+14/-2)
tests/glib-fixture.h (+1/-1)
tests/sound-player-mock.c (+94/-0)
tests/sound-player-mock.h (+75/-0)
tests/test-notify.cc (+37/-4)
To merge this branch: bzr merge lp:~charlesk/indicator-power/lp-1470767-low-battery-sound
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Ted Gould (community) Approve
Review via email: mp+281460@code.launchpad.net

Commit message

Play a 'low battery' sound when the low battery notification is shown.

Description of the change

Play a 'low battery' sound when the low battery notification is shown.

Why so many LOC for this simple feature? Here's what changed:

1. Add dependency on GST, copy gst code from indicator-datetime code
to set the playing sound's role to "alert"

2. Install the low battery sound into CMAKE_INSTALL_DATADIR/indicator-power/sounds/ and add code to search the XDG data paths to find the sound because (a) after discussion in #phablet with seb128 and Jouni we don't want to install this single-purpose sound in sounds/ubuntu/ but (b) we still want it to be possible to override the sound by putting something in XDG_DATA_HOME.

3. Create a SoundPlayer interface so a mock version can be plugged
in during unit tests instead of poking gst. (This is most of the LOC
since indicator-power is written in C)

4. Change startup steps so that dependency injection can be used
on the Notifier class to specify the SoundPlayer.

5. Add an AccountsServices DBus proxy so we can honor silent mode

6. Update tests

To post a comment you must log in.
301. By charles kerr <email address hidden>

fix another touched file's copyright date

302. By charles kerr <email address hidden>

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.

303. By charles kerr <email address hidden>

use a symbolic constant for the low battery sound's filename

304. By charles kerr <email address hidden>

honor com.ubuntu.touch.AccountsService.Sound.SilentMode

305. By charles kerr <email address hidden>

update copyright dates on changed files (again)

306. By charles kerr <email address hidden>

handle service_set_notifier(NULL) gracefully

Revision history for this message
Ted Gould (ted) wrote :

It seems you don't have <email address hidden> registered with LP, that makes it not associate the commits with your UID.

Little fixes. Seems big, but lots of boilerplate, we need to get this indicator converted to C++11 ;-)

307. By Charles Kerr

add 'bzr fixes' metainfo to the branch

308. By Charles Kerr

add build-dep to accountsservice-ubuntu-schemas instead of bundling com.ubuntu.touch.AccountsService.Sound.xml into our source tree

309. By Charles Kerr

add a leak safeguard to accounts_service_sound_proxy

310. By Charles Kerr

assume we're in silent mode if we can't get an accounts-service proxy

311. By Charles Kerr

fix copy-paste typo

312. By Charles Kerr

move sound-player-mock into the tests/ directory

Revision history for this message
Charles Kerr (charlesk) wrote :

> It seems you don't have <email address hidden> registered with LP, that makes it not associate the commits with your UID.

Oh dear. I may have broken my config last week. Fixed with a new bzr whoami for r307.

> we need to get this indicator converted to C++11 ;-)

I thought this a couple of times while writing the GObject/GInterface boilerplate, but didn't want to MP that for OTA 9 :)

Inline comments' responses are inline

Revision history for this message
Ted Gould (ted) wrote :

Thanks! +1

review: Approve
313. By Charles Kerr

don't disable the warning sound when AccountServices is completely unavailable

Revision history for this message
Ted Gould (ted) wrote :

Still +1 :-)

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
314. By Charles Kerr

demote a spurious warning to a debug message

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2014-07-21 21:08:29 +0000
+++ CMakeLists.txt 2016-01-04 20:26:17 +0000
@@ -7,7 +7,8 @@
7set(PACKAGE ${CMAKE_PROJECT_NAME})7set(PACKAGE ${CMAKE_PROJECT_NAME})
8set(GETTEXT_PACKAGE "indicator-power")8set(GETTEXT_PACKAGE "indicator-power")
9add_definitions (-DGETTEXT_PACKAGE="${GETTEXT_PACKAGE}"9add_definitions (-DGETTEXT_PACKAGE="${GETTEXT_PACKAGE}"
10 -DGNOMELOCALEDIR="${CMAKE_INSTALL_FULL_LOCALEDIR}")10 -DGNOMELOCALEDIR="${CMAKE_INSTALL_FULL_LOCALEDIR}"
11 -DLOW_BATTERY_SOUND="Low battery.ogg")
1112
12option (enable_tests "Build the package's automatic tests." ON)13option (enable_tests "Build the package's automatic tests." ON)
13option (enable_lcov "Generate lcov code coverage reports." ON)14option (enable_lcov "Generate lcov code coverage reports." ON)
@@ -38,6 +39,7 @@
38 gio-unix-2.0>=2.3639 gio-unix-2.0>=2.36
39 gudev-1.0>=20440 gudev-1.0>=204
40 libnotify>=0.7.641 libnotify>=0.7.6
42 gstreamer-1.0>=1.2
41 url-dispatcher-1>=1)43 url-dispatcher-1>=1)
4244
43include_directories (SYSTEM ${SERVICE_DEPS_INCLUDE_DIRS})45include_directories (SYSTEM ${SERVICE_DEPS_INCLUDE_DIRS})
4446
=== modified file 'data/CMakeLists.txt'
--- data/CMakeLists.txt 2014-09-09 03:58:48 +0000
+++ data/CMakeLists.txt 2016-01-04 20:26:17 +0000
@@ -88,3 +88,12 @@
8888
89install (FILES "${UNITY_INDICATOR_FILE}"89install (FILES "${UNITY_INDICATOR_FILE}"
90 DESTINATION "${UNITY_INDICATOR_DIR}")90 DESTINATION "${UNITY_INDICATOR_DIR}")
91
92##
93## Sounds
94##
95
96# where to install
97set (DATA_HOME "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/${CMAKE_PROJECT_NAME}")
98message (STATUS "${DATA_HOME} is the sounds/ install dir")
99install (DIRECTORY sounds DESTINATION ${DATA_HOME})
91100
=== added directory 'data/sounds'
=== added file 'data/sounds/Low battery.ogg'
92Binary files data/sounds/Low battery.ogg 1970-01-01 00:00:00 +0000 and data/sounds/Low battery.ogg 2016-01-04 20:26:17 +0000 differ101Binary files data/sounds/Low battery.ogg 1970-01-01 00:00:00 +0000 and data/sounds/Low battery.ogg 2016-01-04 20:26:17 +0000 differ
=== modified file 'debian/control'
--- debian/control 2015-02-25 14:49:06 +0000
+++ debian/control 2016-01-04 20:26:17 +0000
@@ -7,7 +7,10 @@
7 libglib2.0-dev (>= 2.36),7 libglib2.0-dev (>= 2.36),
8 libgudev-1.0-dev,8 libgudev-1.0-dev,
9 liburl-dispatcher1-dev,9 liburl-dispatcher1-dev,
10 libgstreamer1.0-dev,
10 python:any,11 python:any,
12# for com.ubuntu.touch.AccountsService.Sound.xml
13 accountsservice-ubuntu-schemas,
11# for packaging14# for packaging
12 debhelper (>= 9),15 debhelper (>= 9),
13 dh-translations,16 dh-translations,
1417
=== modified file 'src/CMakeLists.txt'
--- src/CMakeLists.txt 2015-05-20 15:34:26 +0000
+++ src/CMakeLists.txt 2016-01-04 20:26:17 +0000
@@ -6,13 +6,16 @@
6# handwritten sources6# handwritten sources
7set(SERVICE_MANUAL_SOURCES7set(SERVICE_MANUAL_SOURCES
8 brightness.c8 brightness.c
9 datafiles.c
9 device-provider-mock.c10 device-provider-mock.c
10 device-provider-upower.c11 device-provider-upower.c
11 device-provider.c12 device-provider.c
12 device.c13 device.c
13 notifier.c14 notifier.c
14 testing.c15 testing.c
15 service.c)16 service.c
17 sound-player.c
18 sound-player-gst.c)
1619
17# generated sources20# generated sources
18include(GdbusCodegen)21include(GdbusCodegen)
@@ -29,6 +32,11 @@
29 com.canonical.indicator.power32 com.canonical.indicator.power
30 Dbus33 Dbus
31 ${CMAKE_SOURCE_DIR}/data/com.canonical.indicator.power.Testing.xml)34 ${CMAKE_SOURCE_DIR}/data/com.canonical.indicator.power.Testing.xml)
35add_gdbus_codegen_with_namespace(SERVICE_GENERATED_SOURCES dbus-accounts-sound
36 com.ubuntu.touch
37 Dbus
38 /usr/share/accountsservice/interfaces/com.ubuntu.touch.AccountsService.Sound.xml)
39
32# add the bin dir to our include path so the code can find the generated header files40# add the bin dir to our include path so the code can find the generated header files
33include_directories(${CMAKE_CURRENT_BINARY_DIR})41include_directories(${CMAKE_CURRENT_BINARY_DIR})
3442
3543
=== added file 'src/datafiles.c'
--- src/datafiles.c 1970-01-01 00:00:00 +0000
+++ src/datafiles.c 2016-01-04 20:26:17 +0000
@@ -0,0 +1,71 @@
1/*
2 * Copyright 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 */
19
20#include "datafiles.h"
21
22static const gchar*
23get_directory_prefix_for_type (DatafileType type)
24{
25 switch (type)
26 {
27 case DATAFILE_TYPE_SOUND:
28 return "sounds";
29
30 default:
31 g_critical("unknown type");
32 return "";
33 }
34}
35
36static gchar*
37test_directory_for_file(const char* dir, DatafileType type, const char* basename)
38{
39 gchar* filename = g_build_filename(dir,
40 GETTEXT_PACKAGE,
41 get_directory_prefix_for_type(type),
42 basename,
43 NULL);
44
45 g_debug("looking for \"%s\" at \"%s\"", basename, filename);
46 if (g_file_test(filename, G_FILE_TEST_EXISTS))
47 return filename;
48
49 g_free(filename);
50 return NULL;
51}
52
53gchar*
54datafile_find(DatafileType type, const char * basename)
55{
56 gchar * filename;
57 const gchar * user_data_dir;
58 const gchar * const * system_data_dirs;
59 gsize i;
60
61 user_data_dir = g_get_user_data_dir();
62 if ((filename = test_directory_for_file(user_data_dir, type, basename)))
63 return filename;
64
65 system_data_dirs = g_get_system_data_dirs();
66 for (i=0; system_data_dirs && system_data_dirs[i]; ++i)
67 if ((filename = test_directory_for_file(system_data_dirs[i], type, basename)))
68 return filename;
69
70 return NULL;
71}
072
=== added file 'src/datafiles.h'
--- src/datafiles.h 1970-01-01 00:00:00 +0000
+++ src/datafiles.h 2016-01-04 20:26:17 +0000
@@ -0,0 +1,37 @@
1/*
2 * Copyright 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 */
19
20#ifndef __INDICATOR_POWER_DATAFILES_H__
21#define __INDICATOR_POWER_DATAFILES_H__
22
23#include <gio/gio.h>
24
25G_BEGIN_DECLS
26
27typedef enum
28{
29 DATAFILE_TYPE_SOUND
30}
31DatafileType;
32
33gchar* datafile_find(DatafileType type, const char * basename);
34
35G_END_DECLS
36
37#endif /* __INDICATOR_POWER_DATAFILES_H__ */
038
=== modified file 'src/main.c'
--- src/main.c 2014-10-14 19:09:32 +0000
+++ src/main.c 2016-01-04 20:26:17 +0000
@@ -1,8 +1,5 @@
1/*1/*
2 * Copyright 2013 Canonical Ltd.2 * Copyright 2013-2016 Canonical Ltd.
3 *
4 * Authors:
5 * Charles Kerr <charles.kerr@canonical.com>
6 *3 *
7 * This program is free software: you can redistribute it and/or modify it4 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 3, as published5 * under the terms of the GNU General Public License version 3, as published
@@ -15,6 +12,9 @@
15 *12 *
16 * You should have received a copy of the GNU General Public License along13 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 */18 */
1919
20#include <locale.h>20#include <locale.h>
@@ -23,7 +23,9 @@
23#include <glib/gi18n.h>23#include <glib/gi18n.h>
2424
25#include "device.h"25#include "device.h"
26#include "notifier.h"
26#include "service.h"27#include "service.h"
28#include "sound-player-gst.h"
27#include "testing.h"29#include "testing.h"
2830
29/***31/***
@@ -40,6 +42,8 @@
40int42int
41main (int argc G_GNUC_UNUSED, char ** argv G_GNUC_UNUSED)43main (int argc G_GNUC_UNUSED, char ** argv G_GNUC_UNUSED)
42{44{
45 IndicatorPowerSoundPlayer * sound_player;
46 IndicatorPowerNotifier * notifier;
43 IndicatorPowerService * service;47 IndicatorPowerService * service;
44 IndicatorPowerTesting * testing;48 IndicatorPowerTesting * testing;
45 GMainLoop * loop;49 GMainLoop * loop;
@@ -50,7 +54,9 @@
50 textdomain (GETTEXT_PACKAGE);54 textdomain (GETTEXT_PACKAGE);
5155
52 /* run */56 /* run */
53 service = indicator_power_service_new (NULL);57 sound_player = indicator_power_sound_player_gst_new ();
58 notifier = indicator_power_notifier_new (sound_player);
59 service = indicator_power_service_new(NULL, notifier);
54 testing = indicator_power_testing_new (service);60 testing = indicator_power_testing_new (service);
55 loop = g_main_loop_new (NULL, FALSE);61 loop = g_main_loop_new (NULL, FALSE);
56 g_signal_connect (service, INDICATOR_POWER_SERVICE_SIGNAL_NAME_LOST,62 g_signal_connect (service, INDICATOR_POWER_SERVICE_SIGNAL_NAME_LOST,
@@ -59,7 +65,9 @@
5965
60 /* cleanup */66 /* cleanup */
61 g_main_loop_unref (loop);67 g_main_loop_unref (loop);
68 g_clear_object (&testing);
62 g_clear_object (&service);69 g_clear_object (&service);
63 g_clear_object (&testing);70 g_clear_object (&notifier);
71 g_clear_object (&sound_player);
64 return 0;72 return 0;
65}73}
6674
=== modified file 'src/notifier.c'
--- src/notifier.c 2014-10-15 01:58:28 +0000
+++ src/notifier.c 2016-01-04 20:26:17 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright 2014 Canonical Ltd.2 * Copyright 2014-2016 Canonical Ltd.
3 *3 *
4 * This program is free software: you can redistribute it and/or modify it4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published5 * under the terms of the GNU General Public License version 3, as published
@@ -17,9 +17,12 @@
17 * Charles Kerr <charles.kerr@canonical.com>17 * Charles Kerr <charles.kerr@canonical.com>
18 */18 */
1919
20#include "datafiles.h"
21#include "dbus-accounts-sound.h"
20#include "dbus-battery.h"22#include "dbus-battery.h"
21#include "dbus-shared.h"23#include "dbus-shared.h"
22#include "notifier.h"24#include "notifier.h"
25#include "sound-player.h"
2326
24#include <url-dispatcher.h>27#include <url-dispatcher.h>
2528
@@ -46,10 +49,12 @@
46{49{
47 PROP_0,50 PROP_0,
48 PROP_BATTERY,51 PROP_BATTERY,
52 PROP_SOUND_PLAYER,
49 LAST_PROP53 LAST_PROP
50};54};
5155
52#define PROP_BATTERY_NAME "battery"56#define PROP_BATTERY_NAME "battery"
57#define PROP_SOUND_PLAYER_NAME "sound-player"
5358
54static GParamSpec * properties[LAST_PROP];59static GParamSpec * properties[LAST_PROP];
5560
@@ -77,6 +82,12 @@
7782
78 gboolean caps_queried;83 gboolean caps_queried;
79 gboolean actions_supported;84 gboolean actions_supported;
85
86 IndicatorPowerSoundPlayer * sound_player;
87
88 GCancellable * cancellable;
89 DbusAccountsServiceSound * accounts_service_sound_proxy;
90 gboolean accounts_service_sound_proxy_pending;
80}91}
81IndicatorPowerNotifierPrivate;92IndicatorPowerNotifierPrivate;
8293
@@ -131,6 +142,82 @@
131}142}
132143
133/***144/***
145**** Sounds
146***/
147
148static void
149on_sound_proxy_ready (GObject * source_object G_GNUC_UNUSED,
150 GAsyncResult * res,
151 gpointer gself)
152{
153 GError * error;
154 DbusAccountsServiceSound * proxy;
155
156 error = NULL;
157 proxy = dbus_accounts_service_sound_proxy_new_for_bus_finish (res, &error);
158 if (error != NULL)
159 {
160 if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
161 {
162 get_priv(gself)->accounts_service_sound_proxy_pending = FALSE;
163 g_debug("%s Couldn't find accounts service sound proxy: %s", G_STRLOC, error->message);
164 }
165
166 g_clear_error(&error);
167 }
168 else
169 {
170 IndicatorPowerNotifier * const self = INDICATOR_POWER_NOTIFIER(gself);
171 priv_t * const p = get_priv (self);
172 g_clear_object (&p->accounts_service_sound_proxy);
173 p->accounts_service_sound_proxy = proxy;
174 p->accounts_service_sound_proxy_pending = FALSE;
175 }
176}
177
178static gboolean
179silent_mode (IndicatorPowerNotifier * self)
180{
181 priv_t * const p = get_priv (self);
182
183 /* if we don't have a proxy yet, assume we're in silent mode
184 as a "do no harm" level of response */
185 if (p->accounts_service_sound_proxy_pending)
186 return TRUE;
187
188 return (p->accounts_service_sound_proxy != NULL)
189 && dbus_accounts_service_sound_get_silent_mode(p->accounts_service_sound_proxy);
190}
191
192static void
193play_low_battery_sound (IndicatorPowerNotifier * self)
194{
195 const gchar * const key = LOW_BATTERY_SOUND;
196 gchar * filename;
197 priv_t * const p = get_priv(self);
198
199 /* can't play? */
200 g_return_if_fail (p->sound_player != NULL);
201
202 /* won't play? */
203 if (silent_mode(self))
204 return;
205
206 filename = datafile_find(DATAFILE_TYPE_SOUND, key);
207 if (filename != NULL)
208 {
209 gchar * uri = g_filename_to_uri(filename, NULL, NULL);
210 indicator_power_sound_player_play_uri (p->sound_player, uri);
211 g_free(uri);
212 g_free(filename);
213 }
214 else
215 {
216 g_warning("Unable to find '%s' in XDG data dirs", key);
217 }
218}
219
220/***
134**** Notifications221**** Notifications
135***/222***/
136223
@@ -300,6 +387,7 @@
300 ((new_power_level != POWER_LEVEL_OK) && new_discharging && !old_discharging))387 ((new_power_level != POWER_LEVEL_OK) && new_discharging && !old_discharging))
301 {388 {
302 notification_show (self);389 notification_show (self);
390 play_low_battery_sound (self);
303 }391 }
304 else if (!new_discharging || (new_power_level == POWER_LEVEL_OK))392 else if (!new_discharging || (new_power_level == POWER_LEVEL_OK))
305 {393 {
@@ -330,6 +418,10 @@
330 g_value_set_object (value, p->battery);418 g_value_set_object (value, p->battery);
331 break;419 break;
332420
421 case PROP_SOUND_PLAYER:
422 g_value_set_object (value, p->sound_player);
423 break;
424
333 default:425 default:
334 G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec);426 G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec);
335 }427 }
@@ -349,6 +441,10 @@
349 indicator_power_notifier_set_battery (self, g_value_get_object(value));441 indicator_power_notifier_set_battery (self, g_value_get_object(value));
350 break;442 break;
351443
444 case PROP_SOUND_PLAYER:
445 indicator_power_notifier_set_sound_player (self, g_value_get_object(value));
446 break;
447
352 default:448 default:
353 G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec);449 G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec);
354 }450 }
@@ -360,10 +456,18 @@
360 IndicatorPowerNotifier * const self = INDICATOR_POWER_NOTIFIER(o);456 IndicatorPowerNotifier * const self = INDICATOR_POWER_NOTIFIER(o);
361 priv_t * const p = get_priv (self);457 priv_t * const p = get_priv (self);
362458
459 if (p->cancellable != NULL)
460 {
461 g_cancellable_cancel(p->cancellable);
462 g_clear_object(&p->cancellable);
463 }
464
363 indicator_power_notifier_set_bus (self, NULL);465 indicator_power_notifier_set_bus (self, NULL);
466 indicator_power_notifier_set_sound_player (self, NULL);
364 notification_clear (self);467 notification_clear (self);
365 indicator_power_notifier_set_battery (self, NULL);468 indicator_power_notifier_set_battery (self, NULL);
366 g_clear_object (&p->dbus_battery);469 g_clear_object (&p->dbus_battery);
470 g_clear_object (&p->accounts_service_sound_proxy);
367471
368 G_OBJECT_CLASS (indicator_power_notifier_parent_class)->dispose (o);472 G_OBJECT_CLASS (indicator_power_notifier_parent_class)->dispose (o);
369}473}
@@ -382,7 +486,6 @@
382**** Instantiation486**** Instantiation
383***/487***/
384488
385
386static void489static void
387indicator_power_notifier_init (IndicatorPowerNotifier * self)490indicator_power_notifier_init (IndicatorPowerNotifier * self)
388{491{
@@ -394,8 +497,22 @@
394497
395 p->power_level = POWER_LEVEL_OK;498 p->power_level = POWER_LEVEL_OK;
396499
500 p->cancellable = g_cancellable_new();
501
397 if (!instance_count++ && !notify_init("indicator-power-service"))502 if (!instance_count++ && !notify_init("indicator-power-service"))
398 g_critical("Unable to initialize libnotify! Notifications might not be shown.");503 g_critical("Unable to initialize libnotify! Notifications might not be shown.");
504
505 p->accounts_service_sound_proxy_pending = TRUE;
506 gchar* object_path = g_strdup_printf("/org/freedesktop/Accounts/User%lu", (gulong)getuid());
507 dbus_accounts_service_sound_proxy_new_for_bus(
508 G_BUS_TYPE_SYSTEM,
509 G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES,
510 "org.freedesktop.Accounts",
511 object_path,
512 p->cancellable,
513 on_sound_proxy_ready,
514 self);
515 g_clear_pointer(&object_path, g_free);
399}516}
400517
401static void518static void
@@ -415,6 +532,13 @@
415 G_TYPE_OBJECT,532 G_TYPE_OBJECT,
416 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);533 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
417534
535 properties[PROP_SOUND_PLAYER] = g_param_spec_object (
536 PROP_SOUND_PLAYER_NAME,
537 "Sound Player",
538 "The current sound player",
539 G_TYPE_OBJECT,
540 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
541
418 g_object_class_install_properties (object_class, LAST_PROP, properties);542 g_object_class_install_properties (object_class, LAST_PROP, properties);
419}543}
420544
@@ -423,9 +547,11 @@
423***/547***/
424548
425IndicatorPowerNotifier *549IndicatorPowerNotifier *
426indicator_power_notifier_new (void)550indicator_power_notifier_new (IndicatorPowerSoundPlayer * sound_player)
427{551{
428 GObject * o = g_object_new (INDICATOR_TYPE_POWER_NOTIFIER, NULL);552 GObject * o = g_object_new (INDICATOR_TYPE_POWER_NOTIFIER,
553 PROP_SOUND_PLAYER_NAME, sound_player,
554 NULL);
429555
430 return INDICATOR_POWER_NOTIFIER (o);556 return INDICATOR_POWER_NOTIFIER (o);
431}557}
@@ -465,6 +591,26 @@
465}591}
466592
467void593void
594indicator_power_notifier_set_sound_player (IndicatorPowerNotifier * self,
595 IndicatorPowerSoundPlayer * sound_player)
596{
597 priv_t * p;
598
599 g_return_if_fail(INDICATOR_IS_POWER_NOTIFIER(self));
600 g_return_if_fail((sound_player == NULL) || INDICATOR_IS_POWER_SOUND_PLAYER(sound_player));
601
602 p = get_priv (self);
603
604 if (p->sound_player == sound_player)
605 return;
606
607 g_clear_object(&p->sound_player);
608
609 if (sound_player != NULL)
610 p->sound_player = g_object_ref(sound_player);
611}
612
613void
468indicator_power_notifier_set_bus (IndicatorPowerNotifier * self,614indicator_power_notifier_set_bus (IndicatorPowerNotifier * self,
469 GDBusConnection * bus)615 GDBusConnection * bus)
470{616{
471617
=== modified file 'src/notifier.h'
--- src/notifier.h 2014-07-25 04:31:11 +0000
+++ src/notifier.h 2016-01-04 20:26:17 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright 2014 Canonical Ltd.2 * Copyright 2014-2016 Canonical Ltd.
3 *3 *
4 * This program is free software: you can redistribute it and/or modify it4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published5 * under the terms of the GNU General Public License version 3, as published
@@ -23,6 +23,7 @@
23#include <gio/gio.h>23#include <gio/gio.h>
2424
25#include "device.h"25#include "device.h"
26#include "sound-player.h"
2627
27G_BEGIN_DECLS28G_BEGIN_DECLS
2829
@@ -55,7 +56,7 @@
5556
56GType indicator_power_notifier_get_type (void);57GType indicator_power_notifier_get_type (void);
5758
58IndicatorPowerNotifier * indicator_power_notifier_new (void);59IndicatorPowerNotifier * indicator_power_notifier_new (IndicatorPowerSoundPlayer * sound_player);
5960
60void indicator_power_notifier_set_bus (IndicatorPowerNotifier * self,61void indicator_power_notifier_set_bus (IndicatorPowerNotifier * self,
61 GDBusConnection * connection);62 GDBusConnection * connection);
@@ -63,6 +64,9 @@
63void indicator_power_notifier_set_battery (IndicatorPowerNotifier * self,64void indicator_power_notifier_set_battery (IndicatorPowerNotifier * self,
64 IndicatorPowerDevice * battery);65 IndicatorPowerDevice * battery);
6566
67void indicator_power_notifier_set_sound_player (IndicatorPowerNotifier * self,
68 IndicatorPowerSoundPlayer * battery);
69
66#define POWER_LEVEL_STR_OK "ok"70#define POWER_LEVEL_STR_OK "ok"
67#define POWER_LEVEL_STR_LOW "low"71#define POWER_LEVEL_STR_LOW "low"
68#define POWER_LEVEL_STR_VERY_LOW "very_low"72#define POWER_LEVEL_STR_VERY_LOW "very_low"
6973
=== modified file 'src/service.c'
--- src/service.c 2015-08-27 14:18:40 +0000
+++ src/service.c 2016-01-04 20:26:17 +0000
@@ -1,9 +1,5 @@
1/*1/*
2 * Copyright 2013 Canonical Ltd.2 * Copyright 2013-2016 Canonical Ltd.
3 *
4 * Authors:
5 * Charles Kerr <charles.kerr@canonical.com>
6 * Ted Gould <ted@canonical.com>
7 *3 *
8 * This program is free software: you can redistribute it and/or modify it4 * This program is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 3, as published5 * under the terms of the GNU General Public License version 3, as published
@@ -16,6 +12,10 @@
16 *12 *
17 * You should have received a copy of the GNU General Public License along13 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 * Ted Gould <ted@canonical.com>
19 */19 */
2020
21#include <glib/gi18n.h>21#include <glib/gi18n.h>
@@ -53,6 +53,7 @@
53 PROP_0,53 PROP_0,
54 PROP_BUS,54 PROP_BUS,
55 PROP_DEVICE_PROVIDER,55 PROP_DEVICE_PROVIDER,
56 PROP_NOTIFIER,
56 LAST_PROP57 LAST_PROP
57};58};
5859
@@ -952,7 +953,8 @@
952 g_object_notify_by_pspec (G_OBJECT(self), properties[PROP_BUS]);953 g_object_notify_by_pspec (G_OBJECT(self), properties[PROP_BUS]);
953954
954 /* export the battery properties */955 /* export the battery properties */
955 indicator_power_notifier_set_bus (p->notifier, connection);956 if (p->notifier != NULL)
957 indicator_power_notifier_set_bus (p->notifier, connection);
956958
957 /* export the actions */959 /* export the actions */
958 if ((id = g_dbus_connection_export_action_group (connection,960 if ((id = g_dbus_connection_export_action_group (connection,
@@ -1094,6 +1096,10 @@
1094 g_value_set_object (value, p->device_provider);1096 g_value_set_object (value, p->device_provider);
1095 break;1097 break;
10961098
1099 case PROP_NOTIFIER:
1100 g_value_set_object (value, p->notifier);
1101 break;
1102
1097 default:1103 default:
1098 G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec);1104 G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec);
1099 }1105 }
@@ -1113,6 +1119,10 @@
1113 indicator_power_service_set_device_provider (self, g_value_get_object (value));1119 indicator_power_service_set_device_provider (self, g_value_get_object (value));
1114 break;1120 break;
11151121
1122 case PROP_NOTIFIER:
1123 indicator_power_service_set_notifier (self, g_value_get_object (value));
1124 break;
1125
1116 default:1126 default:
1117 G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec);1127 G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec);
1118 }1128 }
@@ -1155,6 +1165,7 @@
1155 g_clear_object (&p->conn);1165 g_clear_object (&p->conn);
11561166
1157 indicator_power_service_set_device_provider (self, NULL);1167 indicator_power_service_set_device_provider (self, NULL);
1168 indicator_power_service_set_notifier (self, NULL);
11581169
1159 G_OBJECT_CLASS (indicator_power_service_parent_class)->dispose (o);1170 G_OBJECT_CLASS (indicator_power_service_parent_class)->dispose (o);
1160}1171}
@@ -1178,8 +1189,6 @@
11781189
1179 p->settings = g_settings_new ("com.canonical.indicator.power");1190 p->settings = g_settings_new ("com.canonical.indicator.power");
11801191
1181 p->notifier = indicator_power_notifier_new ();
1182
1183 p->brightness = indicator_power_brightness_new();1192 p->brightness = indicator_power_brightness_new();
1184 g_signal_connect_swapped(p->brightness, "notify::percentage",1193 g_signal_connect_swapped(p->brightness, "notify::percentage",
1185 G_CALLBACK(update_brightness_action_state), self);1194 G_CALLBACK(update_brightness_action_state), self);
@@ -1241,6 +1250,13 @@
1241 G_TYPE_OBJECT,1250 G_TYPE_OBJECT,
1242 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);1251 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
12431252
1253 properties[PROP_NOTIFIER] = g_param_spec_object (
1254 "notifier",
1255 "Notifier",
1256 "Notifies user of important battery changes",
1257 G_TYPE_OBJECT,
1258 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1259
1244 g_object_class_install_properties (object_class, LAST_PROP, properties);1260 g_object_class_install_properties (object_class, LAST_PROP, properties);
1245}1261}
12461262
@@ -1249,10 +1265,12 @@
1249***/1265***/
12501266
1251IndicatorPowerService *1267IndicatorPowerService *
1252indicator_power_service_new (IndicatorPowerDeviceProvider * device_provider)1268indicator_power_service_new (IndicatorPowerDeviceProvider * device_provider,
1269 IndicatorPowerNotifier * notifier)
1253{1270{
1254 GObject * o = g_object_new (INDICATOR_TYPE_POWER_SERVICE,1271 GObject * o = g_object_new (INDICATOR_TYPE_POWER_SERVICE,
1255 "device-provider", device_provider,1272 "device-provider", device_provider,
1273 "notifier", notifier,
1256 NULL);1274 NULL);
12571275
1258 return INDICATOR_POWER_SERVICE (o);1276 return INDICATOR_POWER_SERVICE (o);
@@ -1291,6 +1309,29 @@
1291 }1309 }
1292}1310}
12931311
1312void
1313indicator_power_service_set_notifier (IndicatorPowerService * self,
1314 IndicatorPowerNotifier * notifier)
1315{
1316 priv_t * p;
1317
1318 g_return_if_fail (INDICATOR_IS_POWER_SERVICE (self));
1319 g_return_if_fail (!notifier || INDICATOR_IS_POWER_NOTIFIER (notifier));
1320 p = self->priv;
1321
1322 if (p->notifier == notifier)
1323 return;
1324
1325 g_clear_object (&p->notifier);
1326
1327 if (notifier != NULL)
1328 {
1329 p->notifier = g_object_ref (notifier);
1330 indicator_power_notifier_set_bus (p->notifier, p->conn);
1331 }
1332}
1333
1334
1294/* If a device has multiple batteries and uses only one of them at a time,1335/* If a device has multiple batteries and uses only one of them at a time,
1295 they should be presented as separate items inside the battery menu,1336 they should be presented as separate items inside the battery menu,
1296 but everywhere else they should be aggregated (bug 880881).1337 but everywhere else they should be aggregated (bug 880881).
12971338
=== modified file 'src/service.h'
--- src/service.h 2013-06-19 15:10:50 +0000
+++ src/service.h 2016-01-04 20:26:17 +0000
@@ -24,6 +24,7 @@
24#include <glib-object.h>24#include <glib-object.h>
2525
26#include "device-provider.h"26#include "device-provider.h"
27#include "notifier.h"
2728
28G_BEGIN_DECLS29G_BEGIN_DECLS
2930
@@ -64,11 +65,15 @@
6465
65GType indicator_power_service_get_type (void);66GType indicator_power_service_get_type (void);
6667
67IndicatorPowerService * indicator_power_service_new (IndicatorPowerDeviceProvider * provider);68IndicatorPowerService * indicator_power_service_new (IndicatorPowerDeviceProvider * provider,
69 IndicatorPowerNotifier * notifier);
6870
69void indicator_power_service_set_device_provider (IndicatorPowerService * self,71void indicator_power_service_set_device_provider (IndicatorPowerService * self,
70 IndicatorPowerDeviceProvider * provider);72 IndicatorPowerDeviceProvider * provider);
7173
74void indicator_power_service_set_notifier (IndicatorPowerService * self,
75 IndicatorPowerNotifier * notifier);
76
72IndicatorPowerDevice * indicator_power_service_choose_primary_device (GList * devices);77IndicatorPowerDevice * indicator_power_service_choose_primary_device (GList * devices);
7378
7479
7580
=== added file 'src/sound-player-gst.c'
--- src/sound-player-gst.c 1970-01-01 00:00:00 +0000
+++ src/sound-player-gst.c 2016-01-04 20:26:17 +0000
@@ -0,0 +1,173 @@
1/*
2 * Copyright 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 */
19
20#include "sound-player.h"
21#include "sound-player-gst.h"
22
23#include <gst/gst.h>
24
25
26/***
27**** private struct
28***/
29
30typedef struct
31{
32 int unused;
33}
34IndicatorPowerSoundPlayerGSTPrivate;
35
36typedef IndicatorPowerSoundPlayerGSTPrivate priv_t;
37
38#define get_priv(o) ((priv_t*)indicator_power_sound_player_gst_get_instance_private(o))
39
40
41/***
42**** GObject boilerplate
43***/
44
45static void indicator_power_device_provider_interface_init (
46 IndicatorPowerSoundPlayerInterface * iface);
47
48G_DEFINE_TYPE_WITH_CODE (
49 IndicatorPowerSoundPlayerGST,
50 indicator_power_sound_player_gst,
51 G_TYPE_OBJECT,
52 G_ADD_PRIVATE(IndicatorPowerSoundPlayerGST)
53 G_IMPLEMENT_INTERFACE (INDICATOR_TYPE_POWER_SOUND_PLAYER,
54 indicator_power_device_provider_interface_init))
55
56/***
57**** GSTREAMER
58***/
59
60static void
61gst_init_once(void)
62{
63 static gboolean gst_init_checked = FALSE;
64
65 if (G_UNLIKELY(!gst_init_checked))
66 {
67 GError* error = NULL;
68 if (!gst_init_check(NULL, NULL, &error))
69 {
70 g_critical("Unable to play alarm sound: %s", error->message);
71 g_error_free(error);
72 }
73 gst_init_checked = TRUE;
74 }
75}
76
77static gboolean bus_callback(GstBus* bus G_GNUC_UNUSED, GstMessage* msg, gpointer gelement)
78{
79 const GstMessageType message_type = GST_MESSAGE_TYPE(msg);
80
81 if (GST_MESSAGE_SRC(msg) != gelement)
82 return G_SOURCE_CONTINUE;
83
84 /* on eos, cleanup the element and cancel our gst bus subscription */
85 if (message_type == GST_MESSAGE_EOS)
86 {
87 g_debug("got GST_MESSAGE_EOS on sound play");
88 gst_element_set_state(GST_ELEMENT(gelement), GST_STATE_NULL);
89 gst_object_unref(gelement);
90 return G_SOURCE_REMOVE;
91 }
92
93 /* on stream start, set the media role to 'alert' if we're using pulsesink */
94 if (message_type == GST_MESSAGE_STREAM_START)
95 {
96 GstElement* audio_sink = NULL;
97 g_debug("got GST_MESSAGE_STREAM_START on sound play");
98 g_object_get(gelement, "audio-sink", &audio_sink, NULL);
99 if (audio_sink != NULL)
100 {
101 GstPluginFeature* feature;
102 feature = GST_PLUGIN_FEATURE_CAST(GST_ELEMENT_GET_CLASS(audio_sink)->elementfactory);
103 if (feature && g_strcmp0(gst_plugin_feature_get_name(feature), "pulsesink") == 0)
104 {
105 const gchar* const props_str = "props,media.role=alert";
106 GstStructure* props = gst_structure_from_string(props_str, NULL);
107 g_debug("setting audio sink properties to '%s'", props_str);
108 g_object_set(audio_sink, "stream-properties", props, NULL);
109 g_clear_pointer(&props, gst_structure_free);
110 }
111 gst_object_unref(audio_sink);
112 }
113 }
114
115 return G_SOURCE_CONTINUE;
116}
117
118/***
119**** IndicatorPowerSoundPlayer virtual functions
120***/
121
122static void
123my_play_uri (IndicatorPowerSoundPlayer * self G_GNUC_UNUSED, const gchar * uri)
124{
125 GstElement * element;
126 GstBus * bus;
127
128 /* create the element */
129 element = gst_element_factory_make("playbin", NULL);
130
131 /* start listening for gst events */
132 bus = gst_pipeline_get_bus(GST_PIPELINE(element));
133 gst_bus_add_watch(bus, bus_callback, element);
134 gst_object_unref(bus);
135
136 /* play the sound */
137 g_debug("Playing '%s'", uri);
138 g_object_set(element, "uri", uri, NULL);
139 gst_element_set_state(element, GST_STATE_PLAYING);
140}
141
142/***
143**** Instantiation
144***/
145
146static void
147indicator_power_sound_player_gst_class_init (IndicatorPowerSoundPlayerGSTClass * klass G_GNUC_UNUSED)
148{
149 gst_init_once();
150}
151
152static void
153indicator_power_device_provider_interface_init (IndicatorPowerSoundPlayerInterface * iface)
154{
155 iface->play_uri = my_play_uri;
156}
157
158static void
159indicator_power_sound_player_gst_init (IndicatorPowerSoundPlayerGST * self G_GNUC_UNUSED)
160{
161}
162
163/***
164**** Public API
165***/
166
167IndicatorPowerSoundPlayer *
168indicator_power_sound_player_gst_new(void)
169{
170 gpointer o = g_object_new (INDICATOR_TYPE_POWER_SOUND_PLAYER_GST, NULL);
171
172 return INDICATOR_POWER_SOUND_PLAYER (o);
173}
0174
=== added file 'src/sound-player-gst.h'
--- src/sound-player-gst.h 1970-01-01 00:00:00 +0000
+++ src/sound-player-gst.h 2016-01-04 20:26:17 +0000
@@ -0,0 +1,70 @@
1/*
2 * Copyright 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 */
19
20#ifndef __INDICATOR_POWER_SOUND_PLAYER_GST__H__
21#define __INDICATOR_POWER_SOUND_PLAYER_GST__H__
22
23#include <glib-object.h> /* parent class */
24
25#include "device-provider.h"
26
27G_BEGIN_DECLS
28
29#define INDICATOR_TYPE_POWER_SOUND_PLAYER_GST \
30 (indicator_power_sound_player_gst_get_type())
31
32#define INDICATOR_POWER_SOUND_PLAYER_GST(o) \
33 (G_TYPE_CHECK_INSTANCE_CAST ((o), \
34 INDICATOR_TYPE_POWER_SOUND_PLAYER_GST, \
35 IndicatorPowerSoundPlayerGST))
36
37#define INDICATOR_POWER_SOUND_PLAYER_GST_GET_CLASS(o) \
38 (G_TYPE_INSTANCE_GET_CLASS ((o), \
39 INDICATOR_TYPE_POWER_SOUND_PLAYER_GST, \
40 IndicatorPowerSoundPlayerGSTClass))
41
42#define INDICATOR_IS_POWER_SOUND_PLAYER_GST(o) \
43 (G_TYPE_CHECK_INSTANCE_TYPE ((o), \
44 INDICATOR_TYPE_POWER_SOUND_PLAYER_GST))
45
46typedef struct _IndicatorPowerSoundPlayerGST
47 IndicatorPowerSoundPlayerGST;
48typedef struct _IndicatorPowerSoundPlayerGSTClass
49 IndicatorPowerSoundPlayerGSTClass;
50
51/**
52 * An IndicatorPowerSoundPlayer which gets its devices from GST.
53 */
54struct _IndicatorPowerSoundPlayerGST
55{
56 GObject parent_instance;
57};
58
59struct _IndicatorPowerSoundPlayerGSTClass
60{
61 GObjectClass parent_class;
62};
63
64GType indicator_power_sound_player_gst_get_type (void);
65
66IndicatorPowerSoundPlayer * indicator_power_sound_player_gst_new (void);
67
68G_END_DECLS
69
70#endif /* __INDICATOR_POWER_SOUND_PLAYER_GST__H__ */
071
=== added file 'src/sound-player.c'
--- src/sound-player.c 1970-01-01 00:00:00 +0000
+++ src/sound-player.c 2016-01-04 20:26:17 +0000
@@ -0,0 +1,45 @@
1/*
2 * Copyright 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 */
19
20#include "sound-player.h"
21
22G_DEFINE_INTERFACE (IndicatorPowerSoundPlayer,
23 indicator_power_sound_player,
24 0)
25
26static void
27indicator_power_sound_player_default_init (IndicatorPowerSoundPlayerInterface * klass G_GNUC_UNUSED)
28{
29}
30
31/***
32**** PUBLIC API
33***/
34
35void
36indicator_power_sound_player_play_uri (IndicatorPowerSoundPlayer * self,
37 const gchar * uri)
38{
39 IndicatorPowerSoundPlayerInterface * iface;
40
41 g_return_if_fail (INDICATOR_IS_POWER_SOUND_PLAYER (self));
42 iface = INDICATOR_POWER_SOUND_PLAYER_GET_INTERFACE (self);
43 g_return_if_fail (iface->play_uri != NULL);
44 iface->play_uri (self, uri);
45}
046
=== added file 'src/sound-player.h'
--- src/sound-player.h 1970-01-01 00:00:00 +0000
+++ src/sound-player.h 2016-01-04 20:26:17 +0000
@@ -0,0 +1,72 @@
1/*
2 * Copyright 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 */
19
20#ifndef __INDICATOR_POWER_SOUND_PLAYER__H__
21#define __INDICATOR_POWER_SOUND_PLAYER__H__
22
23#include <glib-object.h>
24
25G_BEGIN_DECLS
26
27#define INDICATOR_TYPE_POWER_SOUND_PLAYER \
28 (indicator_power_sound_player_get_type ())
29
30#define INDICATOR_POWER_SOUND_PLAYER(obj) \
31 (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
32 INDICATOR_TYPE_POWER_SOUND_PLAYER, \
33 IndicatorPowerSoundPlayer))
34
35#define INDICATOR_IS_POWER_SOUND_PLAYER(obj) \
36 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INDICATOR_TYPE_POWER_SOUND_PLAYER))
37
38#define INDICATOR_POWER_SOUND_PLAYER_GET_INTERFACE(inst) \
39 (G_TYPE_INSTANCE_GET_INTERFACE ((inst), \
40 INDICATOR_TYPE_POWER_SOUND_PLAYER, \
41 IndicatorPowerSoundPlayerInterface))
42
43typedef struct _IndicatorPowerSoundPlayer
44 IndicatorPowerSoundPlayer;
45
46typedef struct _IndicatorPowerSoundPlayerInterface
47 IndicatorPowerSoundPlayerInterface;
48
49/**
50 * An interface class for an object that plays sounds.
51 */
52struct _IndicatorPowerSoundPlayerInterface
53{
54 GTypeInterface parent_iface;
55
56 /* virtual functions */
57 void (*play_uri) (IndicatorPowerSoundPlayer * self,
58 const gchar * uri);
59};
60
61GType indicator_power_sound_player_get_type (void);
62
63/***
64****
65***/
66
67void indicator_power_sound_player_play_uri (IndicatorPowerSoundPlayer * self,
68 const gchar * uri);
69
70G_END_DECLS
71
72#endif /* __INDICATOR_POWER_SOUND_PLAYER__H__ */
073
=== modified file 'tests/CMakeLists.txt'
--- tests/CMakeLists.txt 2014-10-10 21:11:36 +0000
+++ tests/CMakeLists.txt 2016-01-04 20:26:17 +0000
@@ -14,11 +14,23 @@
14set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -g ${C_WARNING_ARGS}")14set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -g ${C_WARNING_ARGS}")
15set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-weak-vtables -Wno-global-constructors") # Google Test15set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-weak-vtables -Wno-global-constructors") # Google Test
1616
17# build the mocks
18set(MOCK_LIB "indicatorpowerservicemocks")
19set(MOCK_SOURCES sound-player-mock.c)
20set_source_files_properties(${MOCK_SOURCES}
21 PROPERTIES COMPILE_FLAGS "${C_WARNING_ARGS} -g -std=c99")
22add_library(${MOCK_LIB} STATIC ${MOCK_SOURCES})
23
17# build the necessary schemas24# build the necessary schemas
18set_directory_properties (PROPERTIES25set_directory_properties (PROPERTIES
19 ADDITIONAL_MAKE_CLEAN_FILES gschemas.compiled)26 ADDITIONAL_MAKE_CLEAN_FILES gschemas.compiled)
20set_source_files_properties (gschemas.compiled GENERATED)27set_source_files_properties (gschemas.compiled GENERATED)
2128
29# make a XDG_DATA_HOME for sounds/
30set(XDG_DATA_HOME "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_DATADIR}")
31add_definitions(-DXDG_DATA_HOME="${XDG_DATA_HOME}")
32file(COPY "${CMAKE_SOURCE_DIR}/data/sounds" DESTINATION "${XDG_DATA_HOME}/${CMAKE_PROJECT_NAME}")
33
22# GSettings:34# GSettings:
23# compile the indicator-power schema into a gschemas.compiled file in this directory,35# compile the indicator-power schema into a gschemas.compiled file in this directory,
24# and help the tests to find that file by setting -DSCHEMA_DIR36# and help the tests to find that file by setting -DSCHEMA_DIR
@@ -44,8 +56,8 @@
44 set (TEST_NAME ${name})56 set (TEST_NAME ${name})
45 add_executable (${TEST_NAME} ${TEST_NAME}.cc gschemas.compiled)57 add_executable (${TEST_NAME} ${TEST_NAME}.cc gschemas.compiled)
46 add_test (${TEST_NAME} ${TEST_NAME})58 add_test (${TEST_NAME} ${TEST_NAME})
47 add_dependencies (${TEST_NAME} libindicatorpowerservice)59 add_dependencies (${TEST_NAME} ${MOCK_LIB} libindicatorpowerservice)
48 target_link_libraries (${TEST_NAME} indicatorpowerservice gtest ${DBUSTEST_LIBRARIES} ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBS})60 target_link_libraries (${TEST_NAME} ${MOCK_LIB} indicatorpowerservice gtest ${DBUSTEST_LIBRARIES} ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBS})
49endfunction()61endfunction()
50add_test_by_name(test-notify)62add_test_by_name(test-notify)
51add_test(NAME dear-reader-the-next-test-takes-80-seconds COMMAND true)63add_test(NAME dear-reader-the-next-test-takes-80-seconds COMMAND true)
5264
=== modified file 'tests/glib-fixture.h'
--- tests/glib-fixture.h 2014-09-08 04:56:10 +0000
+++ tests/glib-fixture.h 2016-01-04 20:26:17 +0000
@@ -52,7 +52,7 @@
5252
53 if (expected_log[level] != n)53 if (expected_log[level] != n)
54 for (size_t i=0; i<n; ++i)54 for (size_t i=0; i<n; ++i)
55 g_print("%d %s\n", (n+1), v[i].c_str());55 g_print("%d %s\n", int(n+1), v[i].c_str());
56 }56 }
5757
58 expected_log.clear();58 expected_log.clear();
5959
=== added file 'tests/sound-player-mock.c'
--- tests/sound-player-mock.c 1970-01-01 00:00:00 +0000
+++ tests/sound-player-mock.c 2016-01-04 20:26:17 +0000
@@ -0,0 +1,94 @@
1/*
2 * Copyright 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 */
19
20#include "sound-player.h"
21#include "sound-player-mock.h"
22
23enum
24{
25 SIGNAL_URI_PLAYED,
26 LAST_SIGNAL
27};
28
29static guint signals[LAST_SIGNAL] = { 0 };
30
31/***
32**** GObject boilerplate
33***/
34
35static void indicator_power_sound_player_interface_init (
36 IndicatorPowerSoundPlayerInterface * iface);
37
38G_DEFINE_TYPE_WITH_CODE (
39 IndicatorPowerSoundPlayerMock,
40 indicator_power_sound_player_mock,
41 G_TYPE_OBJECT,
42 G_IMPLEMENT_INTERFACE (INDICATOR_TYPE_POWER_SOUND_PLAYER,
43 indicator_power_sound_player_interface_init))
44
45/***
46**** IndicatorPowerSoundPlayer virtual functions
47***/
48
49static void
50my_play_uri (IndicatorPowerSoundPlayer * self, const gchar * uri)
51{
52 g_signal_emit (self, signals[SIGNAL_URI_PLAYED], 0, uri, NULL);
53}
54
55/***
56**** Instantiation
57***/
58
59static void
60indicator_power_sound_player_mock_class_init (IndicatorPowerSoundPlayerMockClass * klass G_GNUC_UNUSED)
61{
62 signals[SIGNAL_URI_PLAYED] = g_signal_new (
63 "uri-played",
64 G_TYPE_FROM_CLASS(klass),
65 G_SIGNAL_RUN_LAST,
66 G_STRUCT_OFFSET (IndicatorPowerSoundPlayerMockClass, uri_played),
67 NULL, NULL,
68 g_cclosure_marshal_VOID__STRING,
69 G_TYPE_NONE, 1, G_TYPE_STRING);
70}
71
72static void
73indicator_power_sound_player_interface_init (IndicatorPowerSoundPlayerInterface * iface)
74{
75 iface->play_uri = my_play_uri;
76}
77
78static void
79indicator_power_sound_player_mock_init (IndicatorPowerSoundPlayerMock * self G_GNUC_UNUSED)
80{
81}
82
83/***
84**** Public API
85***/
86
87IndicatorPowerSoundPlayer *
88indicator_power_sound_player_mock_new (void)
89{
90 gpointer o = g_object_new (INDICATOR_TYPE_POWER_SOUND_PLAYER_MOCK, NULL);
91
92 return INDICATOR_POWER_SOUND_PLAYER (o);
93}
94
095
=== added file 'tests/sound-player-mock.h'
--- tests/sound-player-mock.h 1970-01-01 00:00:00 +0000
+++ tests/sound-player-mock.h 2016-01-04 20:26:17 +0000
@@ -0,0 +1,75 @@
1/*
2 * Copyright 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 */
19
20#ifndef __INDICATOR_POWER_SOUND_PLAYER_MOCK__H__
21#define __INDICATOR_POWER_SOUND_PLAYER_MOCK__H__
22
23#include <glib-object.h> /* parent class */
24
25#include "sound-player.h"
26
27G_BEGIN_DECLS
28
29#define INDICATOR_TYPE_POWER_SOUND_PLAYER_MOCK \
30 (indicator_power_sound_player_mock_get_type())
31
32#define INDICATOR_POWER_SOUND_PLAYER_MOCK(o) \
33 (G_TYPE_CHECK_INSTANCE_CAST ((o), \
34 INDICATOR_TYPE_POWER_SOUND_PLAYER_MOCK, \
35 IndicatorPowerSoundPlayerMock))
36
37#define INDICATOR_POWER_SOUND_PLAYER_MOCK_GET_CLASS(o) \
38 (G_TYPE_INSTANCE_GET_CLASS ((o), \
39 INDICATOR_TYPE_POWER_SOUND_PLAYER_MOCK, \
40 IndicatorPowerSoundPlayerMockClass))
41
42#define INDICATOR_IS_POWER_SOUND_PLAYER_MOCK(o) \
43 (G_TYPE_CHECK_INSTANCE_TYPE ((o), \
44 INDICATOR_TYPE_POWER_SOUND_PLAYER_MOCK))
45
46typedef struct _IndicatorPowerSoundPlayerMock
47 IndicatorPowerSoundPlayerMock;
48typedef struct _IndicatorPowerSoundPlayerMockPriv
49 IndicatorPowerSoundPlayerMockPriv;
50typedef struct _IndicatorPowerSoundPlayerMockClass
51 IndicatorPowerSoundPlayerMockClass;
52
53/**
54 * An IndicatorPowerSoundPlayer which gets its devices from Mock.
55 */
56struct _IndicatorPowerSoundPlayerMock
57{
58 GObject parent_instance;
59};
60
61struct _IndicatorPowerSoundPlayerMockClass
62{
63 GObjectClass parent_class;
64
65 /* signals */
66 void (*uri_played) (IndicatorPowerSoundPlayer * self, const gchar* uri);
67};
68
69GType indicator_power_sound_player_mock_get_type (void);
70
71IndicatorPowerSoundPlayer * indicator_power_sound_player_mock_new (void);
72
73G_END_DECLS
74
75#endif /* __INDICATOR_POWER_SOUND_PLAYER_MOCK__H__ */
076
=== modified file 'tests/test-notify.cc'
--- tests/test-notify.cc 2014-09-08 04:56:10 +0000
+++ tests/test-notify.cc 2016-01-04 20:26:17 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright 2014 Canonical Ltd.2 * Copyright 2014-2016 Canonical Ltd.
3 *3 *
4 * This program is free software: you can redistribute it and/or modify it4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published5 * under the terms of the GNU General Public License version 3, as published
@@ -23,6 +23,7 @@
23#include "dbus-shared.h"23#include "dbus-shared.h"
24#include "device.h"24#include "device.h"
25#include "notifier.h"25#include "notifier.h"
26#include "sound-player-mock.h"
2627
27#include <gtest/gtest.h>28#include <gtest/gtest.h>
2829
@@ -77,6 +78,8 @@
77 {78 {
78 super::SetUp();79 super::SetUp();
7980
81 g_setenv ("XDG_DATA_HOME", XDG_DATA_HOME, TRUE);
82
80 // init DBusMock / dbus-test-runner83 // init DBusMock / dbus-test-runner
8184
82 service = dbus_test_service_new(nullptr);85 service = dbus_test_service_new(nullptr);
@@ -273,7 +276,8 @@
273276
274 // set up a notifier and give it the battery so changing the battery's277 // set up a notifier and give it the battery so changing the battery's
275 // charge should show up on the bus.278 // charge should show up on the bus.
276 auto notifier = indicator_power_notifier_new ();279 auto sound_player = indicator_power_sound_player_mock_new ();
280 auto notifier = indicator_power_notifier_new (sound_player);
277 indicator_power_notifier_set_battery (notifier, battery);281 indicator_power_notifier_set_battery (notifier, battery);
278 indicator_power_notifier_set_bus (notifier, bus);282 indicator_power_notifier_set_bus (notifier, bus);
279 wait_msec();283 wait_msec();
@@ -315,14 +319,23 @@
315319
316 // cleanup320 // cleanup
317 g_dbus_connection_signal_unsubscribe (bus, sub_tag);321 g_dbus_connection_signal_unsubscribe (bus, sub_tag);
322 g_object_unref (battery);
318 g_object_unref (notifier);323 g_object_unref (notifier);
319 g_object_unref (battery);324 g_object_unref (sound_player);
320}325}
321326
322/***327/***
323****328****
324***/329***/
325330
331namespace
332{
333 static void on_uri_played(IndicatorPowerSoundPlayer*, const char* uri, gpointer glast_uri)
334 {
335 *static_cast<std::string*>(glast_uri) = uri;
336 }
337}
338
326TEST_F(NotifyFixture, EventsThatChangeNotifications)339TEST_F(NotifyFixture, EventsThatChangeNotifications)
327{340{
328 // GetCapabilities returns an array containing 'actions', so that we'll341 // GetCapabilities returns an array containing 'actions', so that we'll
@@ -343,9 +356,18 @@
343 UP_DEVICE_STATE_DISCHARGING,356 UP_DEVICE_STATE_DISCHARGING,
344 30);357 30);
345358
359 // the file we expect to play on a low battery notification...
360 const char* expected_file = XDG_DATA_HOME "/" GETTEXT_PACKAGE "/sounds/" LOW_BATTERY_SOUND;
361 char* tmp = g_filename_to_uri(expected_file, nullptr, nullptr);
362 const std::string low_power_uri {tmp};
363 g_clear_pointer(&tmp, g_free);
364
346 // set up a notifier and give it the battery so changing the battery's365 // set up a notifier and give it the battery so changing the battery's
347 // charge should show up on the bus.366 // charge should show up on the bus.
348 auto notifier = indicator_power_notifier_new ();367 std::string last_uri;
368 auto sound_player = indicator_power_sound_player_mock_new ();
369 g_signal_connect(sound_player, "uri-played", G_CALLBACK(on_uri_played), &last_uri);
370 auto notifier = indicator_power_notifier_new (sound_player);
349 indicator_power_notifier_set_battery (notifier, battery);371 indicator_power_notifier_set_battery (notifier, battery);
350 indicator_power_notifier_set_bus (notifier, bus);372 indicator_power_notifier_set_bus (notifier, bus);
351 ChangedParams changed_params;373 ChangedParams changed_params;
@@ -363,6 +385,7 @@
363 // test setup case385 // test setup case
364 wait_msec();386 wait_msec();
365 EXPECT_STREQ (POWER_LEVEL_STR_OK, changed_params.power_level.c_str());387 EXPECT_STREQ (POWER_LEVEL_STR_OK, changed_params.power_level.c_str());
388 EXPECT_TRUE(last_uri.empty());
366389
367 // change the percent past the 'low' threshold and confirm that390 // change the percent past the 'low' threshold and confirm that
368 // a) the power level changes391 // a) the power level changes
@@ -373,38 +396,48 @@
373 EXPECT_EQ (FIELD_POWER_LEVEL|FIELD_IS_WARNING, changed_params.fields);396 EXPECT_EQ (FIELD_POWER_LEVEL|FIELD_IS_WARNING, changed_params.fields);
374 EXPECT_EQ (indicator_power_notifier_get_power_level(battery), changed_params.power_level);397 EXPECT_EQ (indicator_power_notifier_get_power_level(battery), changed_params.power_level);
375 EXPECT_TRUE (changed_params.is_warning);398 EXPECT_TRUE (changed_params.is_warning);
399 EXPECT_EQ (low_power_uri, last_uri);
376400
377 // now test that the warning changes if the level goes down even lower...401 // now test that the warning changes if the level goes down even lower...
402 last_uri.clear();
378 changed_params = ChangedParams();403 changed_params = ChangedParams();
379 set_battery_percentage (battery, percent_very_low);404 set_battery_percentage (battery, percent_very_low);
380 wait_msec();405 wait_msec();
381 EXPECT_EQ (FIELD_POWER_LEVEL, changed_params.fields);406 EXPECT_EQ (FIELD_POWER_LEVEL, changed_params.fields);
382 EXPECT_STREQ (POWER_LEVEL_STR_VERY_LOW, changed_params.power_level.c_str());407 EXPECT_STREQ (POWER_LEVEL_STR_VERY_LOW, changed_params.power_level.c_str());
408 EXPECT_EQ (low_power_uri, last_uri);
383409
384 // ...and that the warning is taken down if the battery is plugged back in...410 // ...and that the warning is taken down if the battery is plugged back in...
411 last_uri.clear();
385 changed_params = ChangedParams();412 changed_params = ChangedParams();
386 g_object_set (battery, INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_CHARGING, nullptr);413 g_object_set (battery, INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_CHARGING, nullptr);
387 wait_msec();414 wait_msec();
388 EXPECT_EQ (FIELD_IS_WARNING, changed_params.fields);415 EXPECT_EQ (FIELD_IS_WARNING, changed_params.fields);
389 EXPECT_FALSE (changed_params.is_warning);416 EXPECT_FALSE (changed_params.is_warning);
417 EXPECT_TRUE(last_uri.empty());
390418
391 // ...and that it comes back if we unplug again...419 // ...and that it comes back if we unplug again...
420 last_uri.clear();
392 changed_params = ChangedParams();421 changed_params = ChangedParams();
393 g_object_set (battery, INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_DISCHARGING, nullptr);422 g_object_set (battery, INDICATOR_POWER_DEVICE_STATE, UP_DEVICE_STATE_DISCHARGING, nullptr);
394 wait_msec();423 wait_msec();
395 EXPECT_EQ (FIELD_IS_WARNING, changed_params.fields);424 EXPECT_EQ (FIELD_IS_WARNING, changed_params.fields);
396 EXPECT_TRUE (changed_params.is_warning);425 EXPECT_TRUE (changed_params.is_warning);
426 EXPECT_EQ (low_power_uri, last_uri);
397427
398 // ...and that it's taken down if the power level is OK428 // ...and that it's taken down if the power level is OK
429 last_uri.clear();
399 changed_params = ChangedParams();430 changed_params = ChangedParams();
400 set_battery_percentage (battery, percent_low+1);431 set_battery_percentage (battery, percent_low+1);
401 wait_msec();432 wait_msec();
402 EXPECT_EQ (FIELD_POWER_LEVEL|FIELD_IS_WARNING, changed_params.fields);433 EXPECT_EQ (FIELD_POWER_LEVEL|FIELD_IS_WARNING, changed_params.fields);
403 EXPECT_STREQ (POWER_LEVEL_STR_OK, changed_params.power_level.c_str());434 EXPECT_STREQ (POWER_LEVEL_STR_OK, changed_params.power_level.c_str());
404 EXPECT_FALSE (changed_params.is_warning);435 EXPECT_FALSE (changed_params.is_warning);
436 EXPECT_TRUE(last_uri.empty());
405437
406 // cleanup438 // cleanup
407 g_dbus_connection_signal_unsubscribe (bus, sub_tag);439 g_dbus_connection_signal_unsubscribe (bus, sub_tag);
408 g_object_unref (notifier);440 g_object_unref (notifier);
409 g_object_unref (battery);441 g_object_unref (battery);
442 g_object_unref (sound_player);
410}443}

Subscribers

People subscribed via source and target branches