~ubuntu-branches/ubuntu/vivid/indicator-sound/vivid-proposed

« back to all changes in this revision

Viewing changes to src/service.vala

  • Committer: Package Import Robot
  • Author(s): Ubuntu daily release, Ted Gould
  • Date: 2015-01-29 17:32:11 UTC
  • mfrom: (28.220.44)
  • Revision ID: package-import@ubuntu.com-20150129173211-5a3q1dx398s6k0if
Tags: 12.10.2+15.04.20150129.1-0ubuntu1
[ Ted Gould ]
* Move notification code out of volume control object
* Build a rudimentary Pulse Audio mock for testing.
* Disconnect the right function from the 'closed' signal (LP:
  #1307021)
* Ensure that the active port is not null before looking at its value
  (LP: #1399862)

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
 
20
20
public class IndicatorSound.Service: Object {
21
21
        public Service (MediaPlayerList playerlist) {
 
22
                sync_notification = new Notify.Notification(_("Volume"), "", "audio-volume-muted");
 
23
                this.notification_server_watch = GLib.Bus.watch_name(GLib.BusType.SESSION,
 
24
                        "org.freedesktop.Notifications",
 
25
                        GLib.BusNameWatcherFlags.NONE,
 
26
                        () => { check_sync_notification = false; },
 
27
                        () => { check_sync_notification = false; });
 
28
 
22
29
                this.settings = new Settings ("com.canonical.indicator.sound");
23
30
                this.sharedsettings = new Settings ("com.ubuntu.sound");
24
31
 
49
56
                this.actions.add_action (this.create_mute_action ());
50
57
                this.actions.add_action (this.create_volume_action ());
51
58
                this.actions.add_action (this.create_mic_volume_action ());
52
 
                this.actions.add_action (this.create_high_volume_actions ());
 
59
                this.actions.add_action (this.create_high_volume_action ());
53
60
 
54
61
                this.menus = new HashTable<string, SoundMenu> (str_hash, str_equal);
55
62
                this.menus.insert ("desktop_greeter", new SoundMenu (null, SoundMenu.DisplayFlags.SHOW_MUTE | SoundMenu.DisplayFlags.HIDE_PLAYERS | SoundMenu.DisplayFlags.GREETER_PLAYERS));
70
77
                        this.sync_preferred_players ();
71
78
                });
72
79
 
73
 
                if (settings.get_boolean ("show-notify-osd-on-scroll")) {
74
 
                        List<string> caps = Notify.get_server_caps ();
75
 
                        if (caps.find_custom ("x-canonical-private-synchronous", strcmp) != null) {
76
 
                                this.notification = new Notify.Notification ("indicator-sound", "", "");
77
 
                                this.notification.set_hint ("x-canonical-private-synchronous", "indicator-sound");
78
 
                        }
79
 
                }
80
 
 
81
80
                sharedsettings.bind ("allow-amplified-volume", this, "allow-amplified-volume", SettingsBindFlags.GET);
 
81
 
 
82
                /* Hide the notification when the menu is shown */
 
83
                var shown_action = actions.lookup_action ("indicator-shown") as SimpleAction;
 
84
                shown_action.change_state.connect ((state) => {
 
85
                        if (state.get_boolean()) {
 
86
                                try {
 
87
                                        sync_notification.close();
 
88
                                } catch (Error e) {
 
89
                                        warning("Unable to close synchronous volume notification: %s", e.message);
 
90
                                }
 
91
                        }
 
92
                });
82
93
        }
83
94
 
84
95
        ~Service() {
86
97
                        Source.remove (this.sound_was_blocked_timeout_id);
87
98
                        this.sound_was_blocked_timeout_id = 0;
88
99
                }
 
100
 
 
101
                if (this.notification_server_watch != 0) {
 
102
                        GLib.Bus.unwatch_name(this.notification_server_watch);
 
103
                        this.notification_server_watch = 0;
 
104
                }
89
105
        }
90
106
 
91
107
        bool greeter_show_track () {
143
159
                        }
144
160
 
145
161
                        /* Normalize volume, because the volume action's state is [0.0, 1.0], see create_volume_action() */
146
 
                        this.actions.change_action_state ("volume", this.volume_control.get_volume () / this.max_volume);
 
162
                        this.actions.change_action_state ("volume", this.volume_control.volume / this.max_volume);
147
163
                }
148
164
        }
149
165
 
152
168
                { "scroll", activate_scroll_action, "i", null, null },
153
169
                { "desktop-settings", activate_desktop_settings, null, null, null },
154
170
                { "phone-settings", activate_phone_settings, null, null, null },
 
171
                { "indicator-shown", null, null, "@b false", null },
155
172
        };
156
173
 
157
174
        MainLoop loop;
164
181
        uint player_action_update_id;
165
182
        bool mute_blocks_sound;
166
183
        uint sound_was_blocked_timeout_id;
167
 
        Notify.Notification notification;
168
184
        bool syncing_preferred_players = false;
169
185
        AccountsServiceUser? accounts_service = null;
170
186
        bool export_to_accounts_service = false;
 
187
        private Notify.Notification sync_notification;
 
188
        private uint notification_server_watch;
171
189
 
172
190
        /* Maximum volume as a scaling factor between the volume action's state and the value in
173
191
         * this.volume_control. See create_volume_action().
179
197
        void activate_scroll_action (SimpleAction action, Variant? param) {
180
198
                int delta = param.get_int32(); /* positive for up, negative for down */
181
199
 
182
 
                double v = this.volume_control.get_volume () + volume_step_percentage * delta;
183
 
                this.volume_control.set_volume (v.clamp (0.0, this.max_volume));
184
 
 
185
 
                /* TODO: Don't want to mess up the desktop today, but we should remove this
186
 
                   scrolling change and merge that into volume control's notification */
187
 
                if (this.notification != null) {
188
 
                        string icon;
189
 
                        if (v <= 0.0)
190
 
                                icon = "notification-audio-volume-off";
191
 
                        else if (v <= 0.3)
192
 
                                icon = "notification-audio-volume-low";
193
 
                        else if (v <= 0.7)
194
 
                                icon = "notification-audio-volume-medium";
195
 
                        else
196
 
                                icon = "notification-audio-volume-high";
197
 
 
198
 
                        this.notification.update ("indicator-sound", "", icon);
199
 
                        this.notification.set_hint ("value", ((int32) (100 * v / this.max_volume)).clamp (-1, 101));
200
 
                        try {
201
 
                                this.notification.show ();
202
 
                        }
203
 
                        catch (Error e) {
204
 
                                warning ("unable to show notification: %s", e.message);
205
 
                        }
206
 
                }
 
200
                double v = this.volume_control.volume + volume_step_percentage * delta;
 
201
                this.volume_control.volume = v.clamp (0.0, this.max_volume);
207
202
        }
208
203
 
209
204
        void activate_desktop_settings (SimpleAction action, Variant? param) {
238
233
        }
239
234
 
240
235
        void update_root_icon () {
241
 
                double volume = this.volume_control.get_volume ();
 
236
                double volume = this.volume_control.volume;
242
237
                string icon;
243
238
                if (this.volume_control.mute)
244
239
                        icon = this.mute_blocks_sound ? "audio-volume-muted-blocking-panel" : "audio-volume-muted-panel";
273
268
                root_action.set_state (builder.end());
274
269
        }
275
270
 
 
271
        private bool check_sync_notification = false;
 
272
        private bool support_sync_notification = false;
 
273
 
 
274
        void update_sync_notification () {
 
275
                if (!check_sync_notification) {
 
276
                        List<string> caps = Notify.get_server_caps ();
 
277
                        if (caps.find_custom ("x-canonical-private-synchronous", strcmp) != null) {
 
278
                                support_sync_notification = true;
 
279
                        }
 
280
                        check_sync_notification = true;
 
281
                }
 
282
 
 
283
                if (!support_sync_notification)
 
284
                        return;
 
285
 
 
286
                var shown_action = actions.lookup_action ("indicator-shown") as SimpleAction;
 
287
                if (shown_action != null && shown_action.get_state().get_boolean())
 
288
                        return;
 
289
 
 
290
                /* Determine Label */
 
291
                string volume_label = "";
 
292
                if (volume_control.high_volume)
 
293
                        volume_label = _("High volume");
 
294
 
 
295
                /* Choose an icon */
 
296
                string icon = "audio-volume-muted";
 
297
                if (volume_control.volume <= 0.0)
 
298
                        icon = "audio-volume-muted";
 
299
                else if (volume_control.volume <= 0.3)
 
300
                        icon = "audio-volume-low";
 
301
                else if (volume_control.volume <= 0.7)
 
302
                        icon = "audio-volume-medium";
 
303
                else
 
304
                        icon = "audio-volume-high";
 
305
 
 
306
                /* Check tint */
 
307
                string tint = "false";
 
308
                if (volume_control.high_volume)
 
309
                        tint = "true";
 
310
 
 
311
                /* Put it all into the notification */
 
312
                sync_notification.clear_hints ();
 
313
                sync_notification.update (_("Volume"), volume_label, icon);
 
314
                sync_notification.set_hint ("value", (int32)(volume_control.volume * 100.0));
 
315
                sync_notification.set_hint ("x-canonical-value-bar-tint", tint);
 
316
                sync_notification.set_hint ("x-canonical-private-synchronous", "true");
 
317
                sync_notification.set_hint ("x-canonical-non-shaped-icon", "true");
 
318
 
 
319
                /* Show it */
 
320
                try {
 
321
                        sync_notification.show ();                      
 
322
                } catch (GLib.Error e) {
 
323
                        warning("Unable to send volume change notification: %s", e.message);
 
324
                }
 
325
        }
 
326
 
276
327
        Action create_silent_mode_action () {
277
328
                bool silentNow = false;
278
329
                if (this.accounts_service != null) {
347
398
                return mute_action;
348
399
        }
349
400
 
350
 
        void volume_changed (double volume) {
351
 
                var volume_action = this.actions.lookup_action ("volume") as SimpleAction;
352
 
 
353
 
                /* Normalize volume, because the volume action's state is [0.0, 1.0], see create_volume_action() */
354
 
                volume_action.set_state (new Variant.double (volume / this.max_volume));
355
 
 
356
 
                this.update_root_icon ();
357
 
        }
358
 
 
359
401
        Action create_volume_action () {
360
402
                /* The action's state is between be in [0.0, 1.0] instead of [0.0,
361
403
                 * max_volume], so that we don't need to update the slider menu item
364
406
                 * volume_control.set_volume().
365
407
                 */
366
408
 
367
 
                double volume = this.volume_control.get_volume () / this.max_volume;
 
409
                double volume = this.volume_control.volume / this.max_volume;
368
410
 
369
411
                var volume_action = new SimpleAction.stateful ("volume", VariantType.INT32, new Variant.double (volume));
370
412
 
371
413
                volume_action.change_state.connect ( (action, val) => {
372
414
                        double v = val.get_double () * this.max_volume;
373
 
                        volume_control.set_volume (v.clamp (0.0, this.max_volume));
 
415
                        volume_control.volume = v.clamp (0.0, this.max_volume);
374
416
                });
375
417
 
376
418
                /* activating this action changes the volume by the amount given in the parameter */
377
419
                volume_action.activate.connect ( (action, param) => {
378
420
                        int delta = param.get_int32 ();
379
 
                        double v = volume_control.get_volume () + volume_step_percentage * delta;
380
 
                        volume_control.set_volume (v.clamp (0.0, this.max_volume));
381
 
                });
382
 
 
383
 
                this.volume_control.volume_changed.connect (volume_changed);
 
421
                        double v = volume_control.volume + volume_step_percentage * delta;
 
422
                        volume_control.volume = v.clamp (0.0, this.max_volume);
 
423
                });
 
424
 
 
425
                this.volume_control.notify["volume"].connect (() => {
 
426
                        var vol_action = this.actions.lookup_action ("volume") as SimpleAction;
 
427
 
 
428
                        /* Normalize volume, because the volume action's state is [0.0, 1.0], see create_volume_action() */
 
429
                        vol_action.set_state (new Variant.double (this.volume_control.volume / this.max_volume));
 
430
 
 
431
                        this.update_root_icon ();
 
432
                        this.update_sync_notification ();
 
433
                });
384
434
 
385
435
                this.volume_control.bind_property ("ready", volume_action, "enabled", BindingFlags.SYNC_CREATE);
386
436
 
388
438
        }
389
439
 
390
440
        Action create_mic_volume_action () {
391
 
                var volume_action = new SimpleAction.stateful ("mic-volume", null, new Variant.double (this.volume_control.get_mic_volume ()));
 
441
                var volume_action = new SimpleAction.stateful ("mic-volume", null, new Variant.double (this.volume_control.mic_volume));
392
442
 
393
443
                volume_action.change_state.connect ( (action, val) => {
394
 
                        volume_control.set_mic_volume (val.get_double ());
 
444
                        volume_control.mic_volume = val.get_double ();
395
445
                });
396
446
 
397
 
                this.volume_control.mic_volume_changed.connect ( (volume) => {
398
 
                        volume_action.set_state (new Variant.double (volume));
 
447
                this.volume_control.notify["mic-volume"].connect ( () => {
 
448
                        volume_action.set_state (new Variant.double (this.volume_control.mic_volume));
399
449
                });
400
450
 
401
451
                this.volume_control.bind_property ("ready", volume_action, "enabled", BindingFlags.SYNC_CREATE);
403
453
                return volume_action;
404
454
        }
405
455
 
406
 
        Action create_high_volume_actions () {
 
456
        Action create_high_volume_action () {
407
457
                var high_volume_action = new SimpleAction.stateful("high-volume", null, new Variant.boolean (this.volume_control.high_volume));
408
458
 
409
 
                this.volume_control.notify["high-volume"].connect( () =>
410
 
                        high_volume_action.set_state(new Variant.boolean (this.volume_control.high_volume)));
 
459
                this.volume_control.notify["high-volume"].connect( () => {
 
460
                        high_volume_action.set_state(new Variant.boolean (this.volume_control.high_volume));
 
461
                        update_sync_notification();
 
462
                });
411
463
 
412
464
                return high_volume_action;
413
465
        }