Merge lp:~mr-fiorotto/wingpanel-indicator-sound/trying-to-fix-1591392 into lp:~wingpanel-devs/wingpanel-indicator-sound/trunk
- trying-to-fix-1591392
- Merge into trunk
Status: | Rejected | ||||
---|---|---|---|---|---|
Rejected by: | Danielle Foré | ||||
Proposed branch: | lp:~mr-fiorotto/wingpanel-indicator-sound/trying-to-fix-1591392 | ||||
Merge into: | lp:~wingpanel-devs/wingpanel-indicator-sound/trunk | ||||
Diff against target: |
1305 lines (+671/-180) 15 files modified
po/sound-indicator.pot (+8/-8) src/CMakeLists.txt (+4/-0) src/Indicator.vala (+16/-16) src/Services/Adapter.vala (+38/-0) src/Services/Device.vala (+43/-0) src/Services/Manager.vala (+260/-0) src/Services/MediaPlayer.vala (+33/-0) src/Services/MprisClient.vala (+10/-16) src/Services/Settings.vala (+16/-16) src/Services/Volume-control.vala (+4/-3) src/Widgets/DisplayWidget.vala (+5/-3) src/Widgets/MaxWidthLabel.vala (+17/-17) src/Widgets/MprisGui.vala (+134/-56) src/Widgets/MprisWidget.vala (+67/-29) src/Widgets/Scale.vala (+16/-16) |
||||
To merge this branch: | bzr merge lp:~mr-fiorotto/wingpanel-indicator-sound/trying-to-fix-1591392 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Giuliano Fiorotto (community) | Needs Resubmitting | ||
Danielle Foré | code | Needs Fixing | |
Fabio Zaramella (community) | Needs Information | ||
Review via email: mp+316123@code.launchpad.net |
Commit message
Description of the change
Danielle Foré (danrabbit) wrote : | # |
Oh hey I disconnected and re-paired my phone and now the controls are working. Neat :)
Fabio Zaramella (fabiozaramella) wrote : | # |
Daniel, we have already tried to discriminate between device types in order to display the correct icon but unfortunately the possible values are:"Audio", "Video", "Audio Broadcasting" and "Video Broadcasting". I don't think that showing a phone icon is a good idea because it could also be a tablet, or any other bluetooth media player, but i agree that bluetooth icon also looks a bit out of place. It would be nice to have a proper icon, for example a speaker with a little bluetooth icon overlay or something like this. ;)
- 146. By Giuliano Fiorotto
-
Updated all copyright headers
Danielle Foré (danrabbit) wrote : | # |
If you look on the Bluez interface it actually gives you the direct value of the icon name for a device. I'll ping you about this on Slack :)
Danielle Foré (danrabbit) wrote : | # |
Please make sure you don't *change* any licenses. It looks like you've re-licensed several files from LGPL to GPL. Only *add* a license header to your *new* files please :)
- 147. By Giuliano Fiorotto
-
Display device icon and name
- 148. By Giuliano Fiorotto
-
fix conflicts
Fabio Zaramella (fabiozaramella) wrote : | # |
Can you check licenses are ok now?
Danielle Foré (danrabbit) wrote : | # |
When in doubt check the diff. You diff should only contain changes that fall within the scope of solving the issue. In general, please don't change lines that you don't need to. Smaller diffs are easier to review:
* Indicator.vala, Settings.vala, DisplayWidget.vala, MaxWidthLabel.vala, Scale.vala, and Volume-control.vala seem to have been touched unnecessarily. There's no actual change to the code in these files. Please `bzr revert` them.
* MprisClient.vala also looks like you've completely re-written the file. I'm having a tough time seeing what your actual changes are here.
As far as the functionality of the branch, it seems to work as intended. The correct device icon shows and the controls work as expected :)
Giuliano Fiorotto (mr-fiorotto) wrote : | # |
I reverted all the files that seem to have been touched unnecessarily but i can't understand the problem of MprisClient.vala because i reverted it 2 times and it didn't change.
Giuliano Fiorotto (mr-fiorotto) wrote : | # |
I reverted all the files that seem to have been touched unnecessarily to version 143 as suggested by @danrabbit
Danielle Foré (danrabbit) wrote : | # |
Marking as rejected since Fabio superseded it with another branch
Unmerged revisions
- 151. By Giuliano Fiorotto
-
revert version 143
- 150. By Giuliano Fiorotto
-
revert again mprisclient.vala
- 149. By Giuliano Fiorotto
-
revert
- 148. By Giuliano Fiorotto
-
fix conflicts
- 147. By Giuliano Fiorotto
-
Display device icon and name
- 146. By Giuliano Fiorotto
-
Updated all copyright headers
- 145. By Giuliano Fiorotto
-
Implement controls for connected Bluetooth media players, code styling
- 144. By Giuliano Fiorotto
-
Working on bug #1591392
Preview Diff
1 | === modified file 'po/sound-indicator.pot' |
2 | --- po/sound-indicator.pot 2015-08-20 09:56:18 +0000 |
3 | +++ po/sound-indicator.pot 2017-02-23 11:44:20 +0000 |
4 | @@ -8,7 +8,7 @@ |
5 | msgstr "" |
6 | "Project-Id-Version: PACKAGE VERSION\n" |
7 | "Report-Msgid-Bugs-To: \n" |
8 | -"POT-Creation-Date: 2015-08-20 04:54-0500\n" |
9 | +"POT-Creation-Date: 2017-02-01 15:26+0100\n" |
10 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" |
11 | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" |
12 | "Language-Team: LANGUAGE <LL@li.org>\n" |
13 | @@ -17,30 +17,30 @@ |
14 | "Content-Type: text/plain; charset=UTF-8\n" |
15 | "Content-Transfer-Encoding: 8bit\n" |
16 | |
17 | -#: ../src//Indicator.vala:53 |
18 | +#: ../src/Indicator.vala:41 |
19 | msgid "Indicator Sound" |
20 | msgstr "" |
21 | |
22 | -#: ../src//Indicator.vala:54 |
23 | +#: ../src/Indicator.vala:42 |
24 | msgid "The sound indicator" |
25 | msgstr "" |
26 | |
27 | -#: ../src//Indicator.vala:361 |
28 | +#: ../src/Indicator.vala:327 |
29 | msgid "Sound Settings…" |
30 | msgstr "" |
31 | |
32 | -#: ../src//Widgets/MprisGui.vala:24 |
33 | +#: ../src/Widgets/MprisGui.vala:24 |
34 | msgid "Not currently playing" |
35 | msgstr "" |
36 | |
37 | -#: ../src//Widgets/MprisGui.vala:40 |
38 | +#: ../src/Widgets/MprisGui.vala:40 |
39 | msgid "Music player" |
40 | msgstr "" |
41 | |
42 | -#: ../src//Widgets/MprisGui.vala:390 |
43 | +#: ../src/Widgets/MprisGui.vala:523 |
44 | msgid "by " |
45 | msgstr "" |
46 | |
47 | -#: ../src//Widgets/MprisGui.vala:393 |
48 | +#: ../src/Widgets/MprisGui.vala:526 |
49 | msgid "Unknown Title" |
50 | msgstr "" |
51 | |
52 | === modified file 'src/CMakeLists.txt' |
53 | --- src/CMakeLists.txt 2016-12-22 19:28:43 +0000 |
54 | +++ src/CMakeLists.txt 2017-02-23 11:44:20 +0000 |
55 | @@ -22,6 +22,10 @@ |
56 | Services/MprisClient.vala |
57 | Services/Settings.vala |
58 | Services/Volume-control.vala |
59 | + Services/Manager.vala |
60 | + Services/Adapter.vala |
61 | + Services/Device.vala |
62 | + Services/MediaPlayer.vala |
63 | ${CMAKE_CURRENT_BINARY_DIR}/config.vala |
64 | PACKAGES |
65 | wingpanel-2.0 |
66 | |
67 | === modified file 'src/Indicator.vala' |
68 | --- src/Indicator.vala 2017-02-03 20:19:16 +0000 |
69 | +++ src/Indicator.vala 2017-02-23 11:44:20 +0000 |
70 | @@ -1,19 +1,19 @@ |
71 | -/* |
72 | -* Copyright (c) 2015-2017 elementary LLC. (http://launchpad.net/wingpanel-indicator-sound) |
73 | -* |
74 | -* This program is free software; you can redistribute it and/or |
75 | -* modify it under the terms of the GNU General Public |
76 | -* License as published by the Free Software Foundation; either |
77 | -* version 2 of the License, or (at your option) any later version. |
78 | -* |
79 | -* This program is distributed in the hope that it will be useful, |
80 | -* but WITHOUT ANY WARRANTY; without even the implied warranty of |
81 | -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
82 | -* General Public License for more details. |
83 | -* |
84 | -* You should have received a copy of the GNU General Public License |
85 | -* along with this program. If not, see <http://www.gnu.org/licenses/>. |
86 | -*/ |
87 | +/*- |
88 | + * Copyright (c) 2015 Wingpanel Developers (http://launchpad.net/wingpanel) |
89 | + * |
90 | + * This program is free software: you can redistribute it and/or modify |
91 | + * it under the terms of the GNU Library General Public License as published by |
92 | + * the Free Software Foundation, either version 2.1 of the License, or |
93 | + * (at your option) any later version. |
94 | + * |
95 | + * This program is distributed in the hope that it will be useful, |
96 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
97 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
98 | + * GNU Library General Public License for more details. |
99 | + * |
100 | + * You should have received a copy of the GNU Library General Public License |
101 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
102 | + */ |
103 | |
104 | public class Sound.Indicator : Wingpanel.Indicator { |
105 | private DisplayWidget display_widget; |
106 | |
107 | === added file 'src/Services/Adapter.vala' |
108 | --- src/Services/Adapter.vala 1970-01-01 00:00:00 +0000 |
109 | +++ src/Services/Adapter.vala 2017-02-23 11:44:20 +0000 |
110 | @@ -0,0 +1,38 @@ |
111 | +/* |
112 | + * Copyright (c) 2015-2017 elementary LLC. (http://launchpad.net/wingpanel-indicator-sound) |
113 | + * |
114 | + * This program is free software; you can redistribute it and/or |
115 | + * modify it under the terms of the GNU General Public |
116 | + * License as published by the Free Software Foundation; either |
117 | + * version 2 of the License, or (at your option) any later version. |
118 | + * |
119 | + * This program is distributed in the hope that it will be useful, |
120 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
121 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
122 | + * General Public License for more details. |
123 | + * |
124 | + * You should have received a copy of the GNU General Public |
125 | + * License along with this program; If not, see <http://www.gnu.org/licenses/>. |
126 | + * |
127 | + */ |
128 | + |
129 | +[DBus (name = "org.bluez.Adapter1")] |
130 | +public interface Sound.Services.Adapter : Object { |
131 | + public abstract void remove_device (ObjectPath device) throws IOError; |
132 | + public abstract void set_discovery_filter (HashTable<string, Variant> properties) throws IOError; |
133 | + public abstract void start_discovery () throws IOError; |
134 | + public abstract void stop_discovery () throws IOError; |
135 | + |
136 | + public abstract string[] UUIDs { public owned get; private set; } |
137 | + public abstract bool discoverable { public get; public set; } |
138 | + public abstract bool discovering { public get; private set; } |
139 | + public abstract bool pairable { public get; public set; } |
140 | + public abstract bool powered { public get; public set; } |
141 | + public abstract string address { public owned get; private set; } |
142 | + public abstract string alias { public owned get; public set; } |
143 | + public abstract string modalias { public owned get; private set; } |
144 | + public abstract string name { public owned get; private set; } |
145 | + public abstract uint @class { public get; private set; } |
146 | + public abstract uint discoverable_timeout { public get; private set; } |
147 | + public abstract uint pairable_timeout { public get; private set; } |
148 | +} |
149 | |
150 | === added file 'src/Services/Device.vala' |
151 | --- src/Services/Device.vala 1970-01-01 00:00:00 +0000 |
152 | +++ src/Services/Device.vala 2017-02-23 11:44:20 +0000 |
153 | @@ -0,0 +1,43 @@ |
154 | +/* |
155 | + * Copyright (c) 2015-2017 elementary LLC. (http://launchpad.net/wingpanel-indicator-sound) |
156 | + * |
157 | + * This program is free software; you can redistribute it and/or |
158 | + * modify it under the terms of the GNU General Public |
159 | + * License as published by the Free Software Foundation; either |
160 | + * version 2 of the License, or (at your option) any later version. |
161 | + * |
162 | + * This program is distributed in the hope that it will be useful, |
163 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
164 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
165 | + * General Public License for more details. |
166 | + * |
167 | + * You should have received a copy of the GNU General Public |
168 | + * License along with this program; If not, see <http://www.gnu.org/licenses/>. |
169 | + * |
170 | + */ |
171 | + |
172 | +[DBus (name = "org.bluez.Device1")] |
173 | +public interface Sound.Services.Device : Object { |
174 | + public abstract void cancel_pairing () throws IOError; |
175 | + public abstract void connect () throws IOError; |
176 | + public abstract void connect_profile (string UUID) throws IOError; |
177 | + public abstract void disconnect () throws IOError; |
178 | + public abstract void disconnect_profile (string UUID) throws IOError; |
179 | + public abstract void pair () throws IOError; |
180 | + |
181 | + public abstract string[] UUIDs { public owned get; private set; } |
182 | + public abstract bool blocked { public owned get; public set; } |
183 | + public abstract bool connected { public owned get; private set; } |
184 | + public abstract bool legacy_pairing { public owned get; private set; } |
185 | + public abstract bool paired { public owned get; private set; } |
186 | + public abstract bool trusted { public owned get; public set; } |
187 | + public abstract int16 RSSI { public owned get; private set; } |
188 | + public abstract ObjectPath adapter { public owned get; private set; } |
189 | + public abstract string address { public owned get; private set; } |
190 | + public abstract string alias { public owned get; public set; } |
191 | + public abstract string icon { public owned get; private set; } |
192 | + public abstract string modalias { public owned get; private set; } |
193 | + public abstract string name { public owned get; private set; } |
194 | + public abstract uint16 appearance { public owned get; private set; } |
195 | + public abstract uint32 @class { public owned get; private set; } |
196 | +} |
197 | |
198 | === added file 'src/Services/Manager.vala' |
199 | --- src/Services/Manager.vala 1970-01-01 00:00:00 +0000 |
200 | +++ src/Services/Manager.vala 2017-02-23 11:44:20 +0000 |
201 | @@ -0,0 +1,260 @@ |
202 | +/* |
203 | + * Copyright (c) 2015-2017 elementary LLC. (http://launchpad.net/wingpanel-indicator-sound) |
204 | + * |
205 | + * This program is free software; you can redistribute it and/or |
206 | + * modify it under the terms of the GNU General Public |
207 | + * License as published by the Free Software Foundation; either |
208 | + * version 2 of the License, or (at your option) any later version. |
209 | + * |
210 | + * This program is distributed in the hope that it will be useful, |
211 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
212 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
213 | + * General Public License for more details. |
214 | + * |
215 | + * You should have received a copy of the GNU General Public |
216 | + * License along with this program; If not, see <http://www.gnu.org/licenses/>. |
217 | + * |
218 | + */ |
219 | + |
220 | +[DBus (name = "org.freedesktop.DBus.ObjectManager")] |
221 | +public interface Sound.Services.DBusInterface : Object { |
222 | + public signal void interfaces_added (ObjectPath object_path, HashTable<string, HashTable<string, Variant>> param); |
223 | + public signal void interfaces_removed (ObjectPath object_path, string[] string_array); |
224 | + |
225 | + public abstract HashTable<ObjectPath, HashTable<string, HashTable<string, Variant>>> get_managed_objects () throws IOError; |
226 | +} |
227 | + |
228 | +public class Sound.Services.ObjectManager : Object { |
229 | + public signal void global_state_changed (bool enabled, bool connected); |
230 | + public signal void adapter_added (Services.Adapter adapter); |
231 | + public signal void adapter_removed (Services.Adapter adapter); |
232 | + public signal void device_added (Services.Device adapter); |
233 | + public signal void device_removed (Services.Device adapter); |
234 | + public signal void media_player_added (Services.MediaPlayer media_player, string name, string icon); |
235 | + public signal void media_player_removed (Services.MediaPlayer media_player); |
236 | + public signal void media_player_status_changed (string status, string title, string album); |
237 | + |
238 | + public bool has_object { get; private set; default = false; } |
239 | + public string media_player_status { get; private set; default = "stopped";} |
240 | + public string current_track_title { get; private set; default = "Not playing";} |
241 | + public string current_track_artist { get; private set;} |
242 | + |
243 | + private Services.DBusInterface object_interface; |
244 | + private Gee.HashMap<string, Services.Adapter> adapters; |
245 | + private Gee.HashMap<string, Services.Device> devices; |
246 | + private Gee.HashMap<string, Services.MediaPlayer> media_players; |
247 | + |
248 | + public ObjectManager () { |
249 | + |
250 | + } |
251 | + |
252 | + construct { |
253 | + adapters = new Gee.HashMap<string, Services.Adapter> (null, null); |
254 | + devices = new Gee.HashMap<string, Services.Device> (null, null); |
255 | + media_players = new Gee.HashMap<string, Services.MediaPlayer> (null, null); |
256 | + |
257 | + Bus.get_proxy.begin<Services.DBusInterface> (BusType.SYSTEM, "org.bluez", "/", DBusProxyFlags.NONE, null, (obj, res) => { |
258 | + try { |
259 | + object_interface = Bus.get_proxy.end (res); |
260 | + object_interface.get_managed_objects ().foreach (add_path); |
261 | + object_interface.interfaces_added.connect (add_path); |
262 | + object_interface.interfaces_removed.connect (remove_path); |
263 | + } catch (Error e) { |
264 | + critical (e.message); |
265 | + } |
266 | + }); |
267 | + } |
268 | + |
269 | + [CCode (instance_pos = -1)] |
270 | + private void add_path (ObjectPath path, HashTable<string, HashTable<string, Variant>> param) { |
271 | + if ("org.bluez.Adapter1" in param) { |
272 | + try { |
273 | + Services.Adapter adapter = Bus.get_proxy_sync (BusType.SYSTEM, "org.bluez", path, DBusProxyFlags.GET_INVALIDATED_PROPERTIES); |
274 | + lock (adapters) { |
275 | + adapters.set (path, adapter); |
276 | + } |
277 | + has_object = true; |
278 | + |
279 | + adapter_added (adapter); |
280 | + (adapter as DBusProxy).g_properties_changed.connect ((changed, invalid) => { |
281 | + var powered = changed.lookup_value ("Powered", new VariantType ("b")); |
282 | + if (powered != null) { |
283 | + check_global_state (); |
284 | + } |
285 | + }); |
286 | + } catch (Error e) { |
287 | + warning ("Connecting to bluetooth adapter failed: %s", e.message); |
288 | + } |
289 | + } else if ("org.bluez.Device1" in param) { |
290 | + try { |
291 | + Services.Device device = Bus.get_proxy_sync (BusType.SYSTEM, "org.bluez", path, DBusProxyFlags.GET_INVALIDATED_PROPERTIES); |
292 | + if (device.paired) { |
293 | + lock (devices) { |
294 | + devices.set (path, device); |
295 | + } |
296 | + |
297 | + device_added (device); |
298 | + } |
299 | + |
300 | + (device as DBusProxy).g_properties_changed.connect ((changed, invalid) => { |
301 | + var connected = changed.lookup_value ("Connected", new VariantType ("b")); |
302 | + if (connected != null) { |
303 | + check_global_state (); |
304 | + } |
305 | + |
306 | + var paired = changed.lookup_value ("Paired", new VariantType ("b")); |
307 | + if (paired != null) { |
308 | + if (device.paired) { |
309 | + lock (devices) { |
310 | + devices.set (path, device); |
311 | + } |
312 | + |
313 | + device_added (device); |
314 | + } else { |
315 | + lock (devices) { |
316 | + devices.unset (path); |
317 | + } |
318 | + |
319 | + device_removed (device); |
320 | + } |
321 | + } |
322 | + }); |
323 | + } catch (Error e) { |
324 | + warning ("Connecting to bluetooth device failed: %s", e.message); |
325 | + } |
326 | + } else if ("org.bluez.MediaPlayer1" in param) { |
327 | + try { |
328 | + Services.MediaPlayer media_player = Bus.get_proxy_sync (BusType.SYSTEM, "org.bluez", path, DBusProxyFlags.GET_INVALIDATED_PROPERTIES); |
329 | + lock (media_players) { |
330 | + media_players.set (path, media_player); |
331 | + |
332 | + } |
333 | + string device_name = path.substring (0, path.last_index_of("/")); |
334 | + Services.Device cur_device = Bus.get_proxy_sync (BusType.SYSTEM, "org.bluez", device_name, DBusProxyFlags.GET_INVALIDATED_PROPERTIES); |
335 | + media_player_status = media_player.track.lookup ("Title").get_string (null); |
336 | + media_player_added (media_player, cur_device.name, cur_device.icon); |
337 | + |
338 | + (media_player as DBusProxy).g_properties_changed.connect ((changed, invalid) => { |
339 | + if (changed.print (true).contains ("Track")) { |
340 | + Variant tmp = changed.lookup_value ("Track", VariantType.DICTIONARY); |
341 | + string title = tmp.lookup_value ("Title", VariantType.STRING).get_string (null); |
342 | + string artist = tmp.lookup_value ("Artist", VariantType.STRING).get_string (null); |
343 | + current_track_title = title; |
344 | + current_track_artist = artist; |
345 | + media_player_status_changed ("", title, artist); |
346 | + } else if (changed.lookup("Status", "s")) { |
347 | + string status = changed.lookup_value ("Status", VariantType.STRING).get_string (null); |
348 | + media_player_status = status; |
349 | + media_player_status_changed (status, "", ""); |
350 | + } |
351 | + }); |
352 | + } catch (Error e) { |
353 | + warning ("Connecting to bluetooth media player failed: %s", e.message); |
354 | + } |
355 | + } |
356 | + } |
357 | + |
358 | + [CCode (instance_pos = -1)] |
359 | + public void remove_path (ObjectPath path) { |
360 | + lock (adapters) { |
361 | + var adapter = adapters.get (path); |
362 | + if (adapter != null) { |
363 | + adapters.unset (path); |
364 | + has_object = !adapters.is_empty; |
365 | + |
366 | + adapter_removed (adapter); |
367 | + return; |
368 | + } |
369 | + } |
370 | + |
371 | + lock (devices) { |
372 | + var device = devices.get (path); |
373 | + if (device != null) { |
374 | + devices.unset (path); |
375 | + device_removed (device); |
376 | + } |
377 | + } |
378 | + |
379 | + lock (media_players) { |
380 | + var media_player = media_players.get (path); |
381 | + if (media_player != null) { |
382 | + media_players.unset (path); |
383 | + media_player_removed (media_player); |
384 | + } |
385 | + } |
386 | + } |
387 | + |
388 | + public Gee.Collection<Services.Adapter> get_adapters () { |
389 | + lock (adapters) { |
390 | + return adapters.values; |
391 | + } |
392 | + } |
393 | + |
394 | + public Gee.Collection<Services.Device> get_devices () { |
395 | + lock (devices) { |
396 | + return devices.values; |
397 | + } |
398 | + } |
399 | + |
400 | + public Services.Adapter? get_adapter_from_path (string path) { |
401 | + lock (adapters) { |
402 | + return adapters.get (path); |
403 | + } |
404 | + } |
405 | + |
406 | + private void check_global_state () { |
407 | + global_state_changed (get_global_state (), get_connected ()); |
408 | + } |
409 | + |
410 | + public bool get_connected () { |
411 | + lock (devices) { |
412 | + foreach (var device in devices.values) { |
413 | + if (device.connected) { |
414 | + return true; |
415 | + } |
416 | + } |
417 | + } |
418 | + |
419 | + return false; |
420 | + } |
421 | + |
422 | + public bool get_global_state () { |
423 | + lock (adapters) { |
424 | + foreach (var adapter in adapters.values) { |
425 | + if (adapter.powered) { |
426 | + return true; |
427 | + } |
428 | + } |
429 | + } |
430 | + |
431 | + return false; |
432 | + } |
433 | + |
434 | + public void set_global_state (bool state) { |
435 | + new Thread<void*> (null, () => { |
436 | + lock (devices) { |
437 | + foreach (var device in devices.values) { |
438 | + if (device.connected) { |
439 | + try { |
440 | + device.disconnect (); |
441 | + } catch (Error e) { |
442 | + critical (e.message); |
443 | + } |
444 | + } |
445 | + } |
446 | + } |
447 | + |
448 | + lock (adapters) { |
449 | + foreach (var adapter in adapters.values) { |
450 | + adapter.powered = state; |
451 | + } |
452 | + } |
453 | + |
454 | + return null; |
455 | + }); |
456 | + } |
457 | + |
458 | + public void set_last_state () { |
459 | + check_global_state(); |
460 | + } |
461 | +} |
462 | |
463 | === added file 'src/Services/MediaPlayer.vala' |
464 | --- src/Services/MediaPlayer.vala 1970-01-01 00:00:00 +0000 |
465 | +++ src/Services/MediaPlayer.vala 2017-02-23 11:44:20 +0000 |
466 | @@ -0,0 +1,33 @@ |
467 | +/* |
468 | + * Copyright (c) 2017 elementary LLC. (http://launchpad.net/wingpanel-indicator-sound) |
469 | + * |
470 | + * This program is free software; you can redistribute it and/or |
471 | + * modify it under the terms of the GNU General Public |
472 | + * License as published by the Free Software Foundation; either |
473 | + * version 2 of the License, or (at your option) any later version. |
474 | + * |
475 | + * This program is distributed in the hope that it will be useful, |
476 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
477 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
478 | + * General Public License for more details. |
479 | + * |
480 | + * You should have received a copy of the GNU General Public |
481 | + * License along with this program; If not, see <http://www.gnu.org/licenses/>. |
482 | + * |
483 | + * Authored by: Fiorotto Giuliano <mr.fiorotto@gmail.com> |
484 | + * Fabio Zaramella <ffabio.96.x@gmail.com> |
485 | + */ |
486 | + |
487 | +[DBus (name = "org.bluez.MediaPlayer1")] |
488 | +public interface Sound.Services.MediaPlayer : Object { |
489 | + public abstract void play () throws IOError; |
490 | + public abstract void pause () throws IOError; |
491 | + public abstract void stop () throws IOError; |
492 | + public abstract void next () throws IOError; |
493 | + public abstract void previous () throws IOError; |
494 | + public abstract void fast_forward () throws IOError; |
495 | + public abstract void rewind () throws IOError; |
496 | + public abstract string name { public owned get; } |
497 | + public abstract string status { public owned get; } |
498 | + public abstract HashTable<string,Variant> track { public owned get; } |
499 | +} |
500 | |
501 | === modified file 'src/Services/MprisClient.vala' |
502 | --- src/Services/MprisClient.vala 2017-02-03 20:19:16 +0000 |
503 | +++ src/Services/MprisClient.vala 2017-02-23 11:44:20 +0000 |
504 | @@ -1,19 +1,13 @@ |
505 | /* |
506 | -* Copyright (c) 2014 Ikey Doherty <ikey.doherty@gmail.com> |
507 | -* |
508 | -* This program is free software; you can redistribute it and/or |
509 | -* modify it under the terms of the GNU General Public |
510 | -* License as published by the Free Software Foundation; either |
511 | -* version 2 of the License, or (at your option) any later version. |
512 | -* |
513 | -* This program is distributed in the hope that it will be useful, |
514 | -* but WITHOUT ANY WARRANTY; without even the implied warranty of |
515 | -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
516 | -* General Public License for more details. |
517 | -* |
518 | -* You should have received a copy of the GNU General Public License |
519 | -* along with this program. If not, see <http://www.gnu.org/licenses/>. |
520 | -*/ |
521 | + * MprisClient.vala |
522 | + * |
523 | + * Copyright 2014 Ikey Doherty <ikey.doherty@gmail.com> |
524 | + * |
525 | + * This program is free software; you can redistribute it and/or modify |
526 | + * it under the terms of the GNU General Public License as published by |
527 | + * the Free Software Foundation; either version 2 of the License, or |
528 | + * (at your option) any later version. |
529 | + */ |
530 | |
531 | namespace Sound.Services { |
532 | |
533 | @@ -111,4 +105,4 @@ |
534 | |
535 | } |
536 | |
537 | -} |
538 | +} |
539 | \ No newline at end of file |
540 | |
541 | === modified file 'src/Services/Settings.vala' |
542 | --- src/Services/Settings.vala 2017-02-03 20:19:16 +0000 |
543 | +++ src/Services/Settings.vala 2017-02-23 11:44:20 +0000 |
544 | @@ -1,19 +1,19 @@ |
545 | -/* |
546 | -* Copyright (c) 2015-2017 elementary LLC. (http://launchpad.net/wingpanel-indicator-sound) |
547 | -* |
548 | -* This program is free software; you can redistribute it and/or |
549 | -* modify it under the terms of the GNU General Public |
550 | -* License as published by the Free Software Foundation; either |
551 | -* version 2 of the License, or (at your option) any later version. |
552 | -* |
553 | -* This program is distributed in the hope that it will be useful, |
554 | -* but WITHOUT ANY WARRANTY; without even the implied warranty of |
555 | -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
556 | -* General Public License for more details. |
557 | -* |
558 | -* You should have received a copy of the GNU General Public License |
559 | -* along with this program. If not, see <http://www.gnu.org/licenses/>. |
560 | -*/ |
561 | +/*- |
562 | + * Copyright (c) 2015 Wingpanel Developers (http://launchpad.net/wingpanel) |
563 | + * |
564 | + * This program is free software: you can redistribute it and/or modify |
565 | + * it under the terms of the GNU Library General Public License as published by |
566 | + * the Free Software Foundation, either version 2.1 of the License, or |
567 | + * (at your option) any later version. |
568 | + * |
569 | + * This program is distributed in the hope that it will be useful, |
570 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
571 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
572 | + * GNU Library General Public License for more details. |
573 | + * |
574 | + * You should have received a copy of the GNU Library General Public License |
575 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
576 | + */ |
577 | |
578 | public class Sound.Services.Settings : Granite.Services.Settings { |
579 | |
580 | |
581 | === modified file 'src/Services/Volume-control.vala' |
582 | --- src/Services/Volume-control.vala 2017-01-27 21:44:31 +0000 |
583 | +++ src/Services/Volume-control.vala 2017-02-23 11:44:20 +0000 |
584 | @@ -1,7 +1,8 @@ |
585 | /* |
586 | * -*- Mode:Vala; indent-tabs-mode:t; tab-width:4; encoding:utf8 -*- |
587 | - * Copyright (c) 2013 Canonical Ltd. |
588 | - * 2015-2017 elementary LLC. (http://launchpad.net/wingpanel) |
589 | + * Copyright |
590 | + * 2013 Canonical Ltd. |
591 | + * 2015 Wingpanel Developers |
592 | * |
593 | * This program is free software; you can redistribute it and/or modify |
594 | * it under the terms of the GNU General Public License as published by |
595 | @@ -832,4 +833,4 @@ |
596 | } |
597 | return false; // G_SOURCE_REMOVE |
598 | } |
599 | -} |
600 | +} |
601 | \ No newline at end of file |
602 | |
603 | === modified file 'src/Widgets/DisplayWidget.vala' |
604 | --- src/Widgets/DisplayWidget.vala 2017-02-03 20:19:16 +0000 |
605 | +++ src/Widgets/DisplayWidget.vala 2017-02-23 11:44:20 +0000 |
606 | @@ -1,5 +1,5 @@ |
607 | /* |
608 | -* Copyright (c) 2016-2017 elementary LLC. (http://launchpad.net/wingpanel-indicator-sound) |
609 | +* Copyright (c) 2016 elementary LLC. (http://launchpad.net/wingpanel-indicator-sound) |
610 | * |
611 | * This program is free software; you can redistribute it and/or |
612 | * modify it under the terms of the GNU General Public |
613 | @@ -11,8 +11,10 @@ |
614 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
615 | * General Public License for more details. |
616 | * |
617 | -* You should have received a copy of the GNU General Public License |
618 | -* along with this program. If not, see <http://www.gnu.org/licenses/>. |
619 | +* You should have received a copy of the GNU General Public |
620 | +* License along with this program; if not, write to the |
621 | +* Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
622 | +* Boston, MA 02111-1307, USA. |
623 | */ |
624 | |
625 | public class DisplayWidget : Gtk.Grid { |
626 | |
627 | === modified file 'src/Widgets/MaxWidthLabel.vala' |
628 | --- src/Widgets/MaxWidthLabel.vala 2017-02-03 20:19:16 +0000 |
629 | +++ src/Widgets/MaxWidthLabel.vala 2017-02-23 11:44:20 +0000 |
630 | @@ -1,19 +1,19 @@ |
631 | -/* |
632 | -* Copyright (c) 2015-2017 elementary LLC. (http://launchpad.net/wingpanel-indicator-sound) |
633 | -* |
634 | -* This program is free software; you can redistribute it and/or |
635 | -* modify it under the terms of the GNU General Public |
636 | -* License as published by the Free Software Foundation; either |
637 | -* version 2 of the License, or (at your option) any later version. |
638 | -* |
639 | -* This program is distributed in the hope that it will be useful, |
640 | -* but WITHOUT ANY WARRANTY; without even the implied warranty of |
641 | -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
642 | -* General Public License for more details. |
643 | -* |
644 | -* You should have received a copy of the GNU General Public License |
645 | -* along with this program. If not, see <http://www.gnu.org/licenses/>. |
646 | -*/ |
647 | +/*- |
648 | + * Copyright (c) 2015 Wingpanel Developers (http://launchpad.net/wingpanel) |
649 | + * |
650 | + * This program is free software: you can redistribute it and/or modify |
651 | + * it under the terms of the GNU Library General Public License as published by |
652 | + * the Free Software Foundation, either version 2.1 of the License, or |
653 | + * (at your option) any later version. |
654 | + * |
655 | + * This program is distributed in the hope that it will be useful, |
656 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
657 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
658 | + * GNU Library General Public License for more details. |
659 | + * |
660 | + * You should have received a copy of the GNU Library General Public License |
661 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
662 | + */ |
663 | |
664 | public class MaxWidthLabel : Gtk.Label { |
665 | private int max_width; |
666 | @@ -34,4 +34,4 @@ |
667 | } |
668 | } |
669 | |
670 | -} |
671 | +} |
672 | \ No newline at end of file |
673 | |
674 | === modified file 'src/Widgets/MprisGui.vala' |
675 | --- src/Widgets/MprisGui.vala 2017-02-03 20:19:16 +0000 |
676 | +++ src/Widgets/MprisGui.vala 2017-02-23 11:44:20 +0000 |
677 | @@ -14,6 +14,7 @@ |
678 | * |
679 | * You should have received a copy of the GNU General Public License |
680 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
681 | + * |
682 | */ |
683 | |
684 | const int ICON_SIZE = 48; |
685 | @@ -71,6 +72,7 @@ |
686 | } |
687 | |
688 | private Services.MprisClient? client_ = null; |
689 | + private Services.MediaPlayer? mp_client = null; |
690 | |
691 | public Services.MprisClient? client { |
692 | get { |
693 | @@ -118,6 +120,22 @@ |
694 | public ClientWidget (Services.MprisClient mpris_client) { |
695 | Object (orientation: Gtk.Orientation.VERTICAL, spacing: 0, client: mpris_client); |
696 | } |
697 | + |
698 | + /** |
699 | + * Create a new ClientWidget for bluetooth controls |
700 | + * |
701 | + * @param client The underlying MediaPlayer instance to use |
702 | + */ |
703 | + public ClientWidget.bluetooth (Services.MediaPlayer media_player_client, string name, string icon){ |
704 | + mp_client = media_player_client; |
705 | + |
706 | + app_icon = new ThemedIcon (icon); |
707 | + background.set_from_gicon (app_icon, Gtk.IconSize.DIALOG); |
708 | + title_label.set_markup ("<b>%s</b>".printf (Markup.escape_text (name))); |
709 | + artist_label.set_text (NOT_PLAYING); |
710 | + |
711 | + update_controls (); |
712 | + } |
713 | |
714 | /** |
715 | * Create a new ClientWidget for the default player |
716 | @@ -194,25 +212,33 @@ |
717 | prev_btn = btn; |
718 | btn.clicked.connect (()=> { |
719 | Idle.add (()=> { |
720 | - if (client.player.can_go_previous) { |
721 | - if(!Thread.supported ()) { |
722 | - warning ("Threading is not supported. DBus timeout could be blocking UI"); |
723 | + if (!Thread.supported ()) { |
724 | + warning ("Threading is not supported. DBus timeout could be blocking UI"); |
725 | + try { |
726 | + if (mp_client == null && client.player.can_go_previous) { |
727 | + client.player.previous (); |
728 | + } else if (mp_client != null) { |
729 | + mp_client.previous (); |
730 | + } |
731 | + } catch (Error e) { |
732 | + warning ("Going to previous track probably failed (faulty MPRIS interface): %s", e.message); |
733 | + } |
734 | + } else { |
735 | + new Thread <void*> ("wingpanel_indicator_sound_dbus_backward_thread", () => { |
736 | try { |
737 | - client.player.previous(); |
738 | - } catch (Error e) { |
739 | + if (mp_client == null) { |
740 | + client.player.previous (); |
741 | + } else if(mp_client != null) { |
742 | + mp_client.previous (); |
743 | + } |
744 | + } catch (Error e) { |
745 | warning ("Going to previous track probably failed (faulty MPRIS interface): %s", e.message); |
746 | } |
747 | - } else { |
748 | - new Thread <void*> ("wingpanel_indicator_sound_dbus_backward_thread", () => { |
749 | - try { |
750 | - client.player.previous(); |
751 | - } catch (Error e) { |
752 | - warning ("Going to previous track probably failed (faulty MPRIS interface): %s", e.message); |
753 | - } |
754 | - return null; |
755 | - }); |
756 | - } |
757 | + |
758 | + return null; |
759 | + }); |
760 | } |
761 | + |
762 | return false; |
763 | }); |
764 | }); |
765 | @@ -224,23 +250,43 @@ |
766 | play_btn = btn; |
767 | btn.clicked.connect (()=> { |
768 | Idle.add (()=> { |
769 | - if(!Thread.supported ()) { |
770 | + if (!Thread.supported ()) { |
771 | warning ("Threading is not supported. DBus timeout could be blocking UI"); |
772 | try { |
773 | - client.player.play_pause(); |
774 | - } catch (Error e) { |
775 | + if (mp_client == null) { |
776 | + client.player.play_pause (); |
777 | + } else if (mp_client != null) { |
778 | + if (mp_client.status == "playing") { |
779 | + mp_client.pause (); |
780 | + } else { |
781 | + mp_client.play (); |
782 | + } |
783 | + update_play_status (); |
784 | + } |
785 | + } catch (Error e) { |
786 | warning ("Playing/Pausing probably failed (faulty MPRIS interface): %s", e.message); |
787 | } |
788 | } else { |
789 | new Thread <void*> ("wingpanel_indicator_sound_dbus_backward_thread", () => { |
790 | try { |
791 | - client.player.play_pause(); |
792 | + if (mp_client == null) { |
793 | + client.player.play_pause (); |
794 | + } else if (mp_client != null) { |
795 | + if (mp_client.status == "playing") { |
796 | + mp_client.pause (); |
797 | + } else { |
798 | + mp_client.play (); |
799 | + } |
800 | + update_play_status (); |
801 | + } |
802 | } catch (Error e) { |
803 | warning ("Playing/Pausing probably failed (faulty MPRIS interface): %s", e.message); |
804 | } |
805 | + |
806 | return null; |
807 | }); |
808 | } |
809 | + |
810 | return false; |
811 | }); |
812 | }); |
813 | @@ -251,25 +297,33 @@ |
814 | next_btn = btn; |
815 | btn.clicked.connect (()=> { |
816 | Idle.add (()=> { |
817 | - if (client.player.can_go_next) { |
818 | - if(!Thread.supported ()) { |
819 | - warning ("Threading is not supported. DBus timeout could be blocking UI"); |
820 | + if(!Thread.supported ()) { |
821 | + warning ("Threading is not supported. DBus timeout could be blocking UI"); |
822 | + try { |
823 | + if (mp_client == null && client.player.can_go_next) { |
824 | + client.player.next (); |
825 | + } else if (mp_client != null) { |
826 | + mp_client.next (); |
827 | + } |
828 | + } catch (Error e) { |
829 | + warning ("Going to next track probably failed (faulty MPRIS interface): %s", e.message); |
830 | + } |
831 | + } else { |
832 | + new Thread <void*> ("wingpanel_indicator_sound_dbus_forward_thread", () => { |
833 | try { |
834 | - client.player.next(); |
835 | - } catch (Error e) { |
836 | + if (mp_client == null) { |
837 | + client.player.next (); |
838 | + } else if (mp_client != null) { |
839 | + mp_client.next (); |
840 | + } |
841 | + } catch (Error e) { |
842 | warning ("Going to next track probably failed (faulty MPRIS interface): %s", e.message); |
843 | } |
844 | - } else { |
845 | - new Thread <void*> ("wingpanel_indicator_sound_dbus_forward_thread", () => { |
846 | - try { |
847 | - client.player.next(); |
848 | - } catch (Error e) { |
849 | - warning ("Going to next track probably failed (faulty MPRIS interface): %s", e.message); |
850 | - } |
851 | - return null; |
852 | - }); |
853 | - } |
854 | + |
855 | + return null; |
856 | + }); |
857 | } |
858 | + |
859 | return false; |
860 | }); |
861 | }); |
862 | @@ -295,7 +349,7 @@ |
863 | |
864 | private void connect_to_client () { |
865 | client.prop.properties_changed.connect ((i,p,inv)=> { |
866 | - if (i == "org.mpris.MediaPlayer2.Player") { |
867 | + if (i == "org.mpris.MediaPlayer2.Player") { |
868 | /* Handle mediaplayer2 iface */ |
869 | p.foreach ((k,v)=> { |
870 | if (k == "Metadata") { |
871 | @@ -323,17 +377,17 @@ |
872 | try { |
873 | close (); |
874 | if (client != null && client.player.can_raise) { |
875 | - if(!Thread.supported ()) { |
876 | + if( !Thread.supported ()) { |
877 | warning ("Threading is not supported. DBus timeout could be blocking UI"); |
878 | try { |
879 | - client.player.raise(); |
880 | - } catch (Error e) { |
881 | + client.player.raise (); |
882 | + } catch (Error e) { |
883 | warning ("Raising the player probably failed (faulty MPRIS interface): %s", e.message); |
884 | } |
885 | } else { |
886 | new Thread <void*> ("wingpanel_indicator_sound_dbus_backward_thread", () => { |
887 | try { |
888 | - client.player.raise(); |
889 | + client.player.raise (); |
890 | } catch (Error e) { |
891 | warning ("Raising the player probably failed (faulty MPRIS interface): %s", e.message); |
892 | } |
893 | @@ -343,7 +397,7 @@ |
894 | } else if (app_info != null) { |
895 | app_info.launch (null, null); |
896 | } |
897 | - } catch (Error e) { |
898 | + } catch (Error e) { |
899 | warning ("Could not launch player"); |
900 | } |
901 | |
902 | @@ -367,20 +421,21 @@ |
903 | |
904 | return Gdk.EVENT_STOP; |
905 | }); |
906 | + |
907 | return btn; |
908 | } |
909 | |
910 | /** |
911 | - * Update play status based on player requirements |
912 | + * Update play status based on player requirements |
913 | */ |
914 | private void update_play_status () { |
915 | - switch (client.player.playback_status) { |
916 | + switch (client.player.playback_status) { |
917 | case "Playing": |
918 | - (play_btn.get_image () as Gtk.Image).set_from_icon_name ("media-playback-pause-symbolic", Gtk.IconSize.LARGE_TOOLBAR); |
919 | + (play_btn.get_image () as Gtk.Image).set_from_icon_name ("media-playback-pause-symbolic", Gtk.IconSize.LARGE_TOOLBAR); |
920 | break; |
921 | default: |
922 | /* Stopped, Paused */ |
923 | - (play_btn.get_image () as Gtk.Image).set_from_icon_name ("media-playback-start-symbolic", Gtk.IconSize.LARGE_TOOLBAR); |
924 | + (play_btn.get_image () as Gtk.Image).set_from_icon_name ("media-playback-start-symbolic", Gtk.IconSize.LARGE_TOOLBAR); |
925 | break; |
926 | } |
927 | } |
928 | @@ -389,28 +444,33 @@ |
929 | * Update prev/next sensitivity based on player requirements |
930 | */ |
931 | private void update_controls () { |
932 | - prev_btn.set_sensitive (client.player.can_go_previous); |
933 | - next_btn.set_sensitive (client.player.can_go_next); |
934 | + if (mp_client == null) { |
935 | + prev_btn.set_sensitive (client.player.can_go_previous); |
936 | + next_btn.set_sensitive (client.player.can_go_next); |
937 | + } else { |
938 | + prev_btn.set_sensitive (true); |
939 | + next_btn.set_sensitive (true); |
940 | + } |
941 | } |
942 | |
943 | /** |
944 | * Utility, handle updating the album art |
945 | */ |
946 | private void update_art (string uri) { |
947 | - if (!uri.has_prefix ("file://") && !uri.has_prefix ("http")) { |
948 | + if (!uri.has_prefix ("file://") && !uri.has_prefix ("http")) { |
949 | background.set_from_gicon (app_icon, Gtk.IconSize.DIALOG); |
950 | mask.no_show_all = true; |
951 | mask.hide (); |
952 | return; |
953 | } |
954 | - if (uri.has_prefix ("file://")) { |
955 | + if (uri.has_prefix ("file://")) { |
956 | string fname = uri.split ("file://")[1]; |
957 | try { |
958 | var pbuf = new Gdk.Pixbuf.from_file_at_size (fname, ICON_SIZE, ICON_SIZE); |
959 | background.set_from_pixbuf (mask_pixbuf (pbuf)); |
960 | mask.no_show_all = false; |
961 | mask.show (); |
962 | - } catch (Error e) { |
963 | + } catch (Error e) { |
964 | //background.set_from_gicon (app_icon, Gtk.IconSize.DIALOG); |
965 | } |
966 | } else { |
967 | @@ -430,7 +490,7 @@ |
968 | mask.no_show_all = false; |
969 | mask.show (); |
970 | } |
971 | - } catch (Error e) { |
972 | + } catch (Error e) { |
973 | background.set_from_gicon (app_icon, Gtk.IconSize.DIALOG); |
974 | mask.no_show_all = true; |
975 | mask.hide (); |
976 | @@ -442,7 +502,7 @@ |
977 | */ |
978 | protected void update_from_meta () { |
979 | var metadata = client.player.metadata; |
980 | - if ("mpris:artUrl" in metadata) { |
981 | + if ("mpris:artUrl" in metadata) { |
982 | var url = metadata["mpris:artUrl"].get_string (); |
983 | last_artUrl = url; |
984 | update_art (url); |
985 | @@ -455,7 +515,7 @@ |
986 | } |
987 | |
988 | string title; |
989 | - if ("xesam:title" in metadata && metadata["xesam:title"].is_of_type (VariantType.STRING) |
990 | + if ("xesam:title" in metadata && metadata["xesam:title"].is_of_type (VariantType.STRING) |
991 | && metadata["xesam:title"].get_string () != "") { |
992 | title = metadata["xesam:title"].get_string (); |
993 | } else { |
994 | @@ -464,11 +524,11 @@ |
995 | |
996 | title_label.set_markup ("<b>%s</b>".printf (Markup.escape_text (title))); |
997 | |
998 | - if ("xesam:artist" in metadata && metadata["xesam:artist"].is_of_type (VariantType.STRING_ARRAY)) { |
999 | + if ("xesam:artist" in metadata && metadata["xesam:artist"].is_of_type (VariantType.STRING_ARRAY)) { |
1000 | (unowned string)[] artists = metadata["xesam:artist"].get_strv (); |
1001 | artist_label.set_text (_("by ")+string.joinv (", ", artists)); |
1002 | } else { |
1003 | - if (client.player.playback_status == "Playing") { |
1004 | + if (client.player.playback_status == "Playing") { |
1005 | artist_label.set_text (_("Unknown Title")); |
1006 | } else { |
1007 | artist_label.set_text (NOT_PLAYING); |
1008 | @@ -489,8 +549,7 @@ |
1009 | var surface = new Cairo.ImageSurface (Cairo.Format.ARGB32, mask_size, mask_size); |
1010 | var cr = new Cairo.Context (surface); |
1011 | |
1012 | - Granite.Drawing.Utilities.cairo_rounded_rectangle (cr, |
1013 | - offset_x, offset_y, size, size, 4); |
1014 | + Granite.Drawing.Utilities.cairo_rounded_rectangle (cr, offset_x, offset_y, size, size, 4); |
1015 | cr.clip (); |
1016 | |
1017 | Gdk.cairo_set_source_pixbuf (cr, input, offset_x, offset_y); |
1018 | @@ -498,4 +557,23 @@ |
1019 | |
1020 | return Gdk.pixbuf_get_from_surface (surface, 0, 0, mask_size, mask_size); |
1021 | } |
1022 | + |
1023 | + public void update_play (string playing, string title, string artist) { |
1024 | + if (playing != "") { |
1025 | + switch (playing) { |
1026 | + case "playing": |
1027 | + (play_btn.get_image () as Gtk.Image).set_from_icon_name ("media-playback-pause-symbolic", Gtk.IconSize.LARGE_TOOLBAR); |
1028 | + break; |
1029 | + default: |
1030 | + /* Stopped, Paused */ |
1031 | + (play_btn.get_image () as Gtk.Image).set_from_icon_name ("media-playback-start-symbolic", Gtk.IconSize.LARGE_TOOLBAR); |
1032 | + break; |
1033 | + } |
1034 | + } |
1035 | + |
1036 | + if (title != "" && artist != "") { |
1037 | + title_label.set_markup ("<b>%s</b>".printf (Markup.escape_text (title))); |
1038 | + artist_label.set_text (artist); |
1039 | + } |
1040 | + } |
1041 | } |
1042 | |
1043 | === modified file 'src/Widgets/MprisWidget.vala' |
1044 | --- src/Widgets/MprisWidget.vala 2017-02-03 20:19:16 +0000 |
1045 | +++ src/Widgets/MprisWidget.vala 2017-02-23 11:44:20 +0000 |
1046 | @@ -14,6 +14,7 @@ |
1047 | * |
1048 | * You should have received a copy of the GNU General Public License |
1049 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1050 | + * |
1051 | */ |
1052 | |
1053 | public class Sound.Widgets.MprisWidget : Gtk.Box { |
1054 | @@ -21,15 +22,18 @@ |
1055 | |
1056 | AppInfo? default_music; |
1057 | ClientWidget default_widget; |
1058 | + ClientWidget bluetooth_widget; |
1059 | HashTable<string,ClientWidget> ifaces; |
1060 | public signal void close (); |
1061 | |
1062 | - public MprisWidget() { |
1063 | + public Sound.Services.ObjectManager object_manager; |
1064 | + |
1065 | + public MprisWidget () { |
1066 | Object (orientation: Gtk.Orientation.VERTICAL, spacing: 1); |
1067 | |
1068 | - ifaces = new HashTable<string,ClientWidget>(str_hash, str_equal); |
1069 | + ifaces = new HashTable<string,ClientWidget> (str_hash, str_equal); |
1070 | |
1071 | - Idle.add(()=> { |
1072 | + Idle.add (()=> { |
1073 | setup_dbus(); |
1074 | return false; |
1075 | }); |
1076 | @@ -42,18 +46,51 @@ |
1077 | close (); |
1078 | }); |
1079 | |
1080 | - default_widget.show_all(); |
1081 | + default_widget.show_all (); |
1082 | pack_start(default_widget, false, false, 0); |
1083 | } |
1084 | |
1085 | - show_all(); |
1086 | + object_manager = new Services.ObjectManager (); |
1087 | + object_manager.bind_property ("has-object", this, "visible", GLib.BindingFlags.SYNC_CREATE); |
1088 | + |
1089 | + if (object_manager.has_object) { |
1090 | + object_manager.set_last_state (); |
1091 | + } |
1092 | + |
1093 | + object_manager.media_player_added.connect ((media_player, name, icon) => { |
1094 | + try { |
1095 | + bluetooth_widget = new ClientWidget.bluetooth (media_player, name, icon); |
1096 | + bluetooth_widget.close.connect (() => { |
1097 | + close (); |
1098 | + }); |
1099 | + |
1100 | + bluetooth_widget.show_all (); |
1101 | + pack_start (bluetooth_widget, false, false, 0); |
1102 | + } catch (Error e) { |
1103 | + warning ("Connecting to bluetooth device failed: %s", e.message); |
1104 | + } |
1105 | + }); |
1106 | + |
1107 | + object_manager.media_player_removed.connect ((media_player) => { |
1108 | + debug ("Media player %s removed", media_player.name); |
1109 | + bluetooth_widget.destroy (); |
1110 | + }); |
1111 | + |
1112 | + object_manager.media_player_status_changed.connect ((status, title, artist) => { |
1113 | + bluetooth_widget.update_play (status, title, artist); |
1114 | + if (status == "playing" && default_widget.client.player.playback_status == "Playing") { |
1115 | + default_widget.client.player.play_pause (); |
1116 | + } |
1117 | + }); |
1118 | + |
1119 | + show_all (); |
1120 | } |
1121 | |
1122 | public void pause_all () { |
1123 | foreach (var cw in ifaces.get_values ()) { |
1124 | try { |
1125 | cw.client.player.pause (); |
1126 | - } catch (Error e) { |
1127 | + } catch (Error e) { |
1128 | warning ("Could not pause: %s", e.message); |
1129 | } |
1130 | } |
1131 | @@ -69,7 +106,7 @@ |
1132 | if (iface.player.desktop_entry == default_music.get_id ().replace (".desktop","")) { |
1133 | default_widget.mpris_name = name; |
1134 | default_widget.client = iface; |
1135 | - ifaces.insert(name, default_widget); |
1136 | + ifaces.insert (name, default_widget); |
1137 | default_widget.no_show_all = false; |
1138 | default_widget.visible = true; |
1139 | } else { |
1140 | @@ -82,9 +119,9 @@ |
1141 | widg.close.connect (() => { |
1142 | close (); |
1143 | }); |
1144 | - widg.show_all(); |
1145 | - pack_start(widg, false, false, 0); |
1146 | - ifaces.insert(name, widg); |
1147 | + widg.show_all (); |
1148 | + pack_start (widg, false, false, 0); |
1149 | + ifaces.insert (name, widg); |
1150 | } |
1151 | } |
1152 | |
1153 | @@ -93,17 +130,17 @@ |
1154 | * |
1155 | * @param name DBUS name to remove handler for |
1156 | */ |
1157 | - void destroy_iface(string name) { |
1158 | + void destroy_iface (string name) { |
1159 | if (default_widget.mpris_name == name) { |
1160 | default_widget.client = null; |
1161 | } else { |
1162 | var widg = ifaces[name]; |
1163 | - if (widg != null) { |
1164 | - remove(widg); |
1165 | + if (widg != null) { |
1166 | + remove (widg); |
1167 | } |
1168 | } |
1169 | |
1170 | - ifaces.remove(name); |
1171 | + ifaces.remove (name); |
1172 | |
1173 | if (ifaces.length != 0 && default_widget.mpris_name == "") { |
1174 | default_widget.no_show_all = true; |
1175 | @@ -118,14 +155,14 @@ |
1176 | /** |
1177 | * Do basic dbus initialisation |
1178 | */ |
1179 | - public void setup_dbus() { |
1180 | + public void setup_dbus () { |
1181 | try { |
1182 | impl = Bus.get_proxy_sync(BusType.SESSION, "org.freedesktop.DBus", "/org/freedesktop/DBus"); |
1183 | var names = impl.list_names(); |
1184 | |
1185 | /* Search for existing players (launched prior to our start) */ |
1186 | foreach (var name in names) { |
1187 | - if (name.has_prefix("org.mpris.MediaPlayer2.")) { |
1188 | + if (name.has_prefix ("org.mpris.MediaPlayer2.")) { |
1189 | bool add = true; |
1190 | foreach (string name2 in ifaces.get_keys ()) { |
1191 | // skip if already a interface is present. |
1192 | @@ -135,18 +172,18 @@ |
1193 | } |
1194 | } |
1195 | if (add) { |
1196 | - var iface = new_iface(name); |
1197 | + var iface = new_iface (name); |
1198 | if (iface != null) { |
1199 | - add_iface(name, iface); |
1200 | + add_iface (name, iface); |
1201 | } |
1202 | } |
1203 | } |
1204 | } |
1205 | |
1206 | /* Also check for new mpris clients coming up while we're up */ |
1207 | - impl.name_owner_changed.connect((n,o,ne)=> { |
1208 | + impl.name_owner_changed.connect ((n,o,ne)=> { |
1209 | /* Separate.. */ |
1210 | - if (n.has_prefix("org.mpris.MediaPlayer2.")) { |
1211 | + if (n.has_prefix ("org.mpris.MediaPlayer2.")) { |
1212 | if (o == "") { |
1213 | // delay the sync because otherwise the dbus properties are not yet intialized! |
1214 | Timeout.add (100, () => { |
1215 | @@ -157,15 +194,15 @@ |
1216 | return false; |
1217 | } |
1218 | } |
1219 | - var iface = new_iface(n); |
1220 | + var iface = new_iface (n); |
1221 | if (iface != null) { |
1222 | - add_iface(n,iface); |
1223 | + add_iface (n,iface); |
1224 | } |
1225 | return false; |
1226 | }); |
1227 | } else { |
1228 | Idle.add(()=> { |
1229 | - destroy_iface(n); |
1230 | + destroy_iface (n); |
1231 | return false; |
1232 | }); |
1233 | } |
1234 | @@ -183,24 +220,25 @@ |
1235 | * @param busname The busname to instaniate ifaces from |
1236 | * @return a new MprisClient, or null if errors occurred. |
1237 | */ |
1238 | - public Services.MprisClient? new_iface(string busname) { |
1239 | + public Services.MprisClient? new_iface (string busname) { |
1240 | Services.PlayerIface? play = null; |
1241 | Services.MprisClient? cl = null; |
1242 | Services.DbusPropIface? prop = null; |
1243 | |
1244 | try { |
1245 | - play = Bus.get_proxy_sync(BusType.SESSION, busname, "/org/mpris/MediaPlayer2"); |
1246 | + play = Bus.get_proxy_sync (BusType.SESSION, busname, "/org/mpris/MediaPlayer2"); |
1247 | } catch (Error e) { |
1248 | - message(e.message); |
1249 | + message (e.message); |
1250 | return null; |
1251 | } |
1252 | + |
1253 | try { |
1254 | - prop = Bus.get_proxy_sync(BusType.SESSION, busname, "/org/mpris/MediaPlayer2"); |
1255 | + prop = Bus.get_proxy_sync (BusType.SESSION, busname, "/org/mpris/MediaPlayer2"); |
1256 | } catch (Error e) { |
1257 | - message(e.message); |
1258 | + message (e.message); |
1259 | return null; |
1260 | } |
1261 | - cl = new Services.MprisClient(play, prop); |
1262 | + cl = new Services.MprisClient (play, prop); |
1263 | |
1264 | return cl; |
1265 | } |
1266 | |
1267 | === modified file 'src/Widgets/Scale.vala' |
1268 | --- src/Widgets/Scale.vala 2017-02-03 20:19:16 +0000 |
1269 | +++ src/Widgets/Scale.vala 2017-02-23 11:44:20 +0000 |
1270 | @@ -1,19 +1,19 @@ |
1271 | -/* |
1272 | -* Copyright (c) 2015-2017 elementary LLC. (http://launchpad.net/wingpanel-indicator-sound) |
1273 | -* |
1274 | -* This program is free software; you can redistribute it and/or |
1275 | -* modify it under the terms of the GNU General Public |
1276 | -* License as published by the Free Software Foundation; either |
1277 | -* version 2 of the License, or (at your option) any later version. |
1278 | -* |
1279 | -* This program is distributed in the hope that it will be useful, |
1280 | -* but WITHOUT ANY WARRANTY; without even the implied warranty of |
1281 | -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1282 | -* General Public License for more details. |
1283 | -* |
1284 | -* You should have received a copy of the GNU General Public License |
1285 | -* along with this program. If not, see <http://www.gnu.org/licenses/>. |
1286 | -*/ |
1287 | +/*- |
1288 | + * Copyright (c) 2015 Wingpanel Developers (http://launchpad.net/wingpanel) |
1289 | + * |
1290 | + * This program is free software: you can redistribute it and/or modify |
1291 | + * it under the terms of the GNU Library General Public License as published by |
1292 | + * the Free Software Foundation, either version 2.1 of the License, or |
1293 | + * (at your option) any later version. |
1294 | + * |
1295 | + * This program is distributed in the hope that it will be useful, |
1296 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1297 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1298 | + * GNU Library General Public License for more details. |
1299 | + * |
1300 | + * You should have received a copy of the GNU Library General Public License |
1301 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1302 | + */ |
1303 | |
1304 | public class Sound.Widgets.Scale : Gtk.Grid { |
1305 | private Gtk.Image image; |
Please make sure to add a copyright header for new files, specifically MediaPlayer.vala
I can confirm that my phone shows up as a new media player and the track information displays.
I can't confirm that the player controls work here (iPhone running iOS 10)
Can we get the device icon instead of using the bluetooth icon?