Codebase list gnome-shell-extension-mediaplayer / 837d011
Merge tag 'upstream/0_git20160830' into debian/master Upstream version 0~git20160830 Simon McVittie 7 years ago
5 changed file(s) with 106 addition(s) and 52 deletion(s). Raw diff Collapse all Expand all
0 commit 17091aca40ad003cbd28ad88ed9a914aea6dc0f4
1 Merge: fb5da1b 38a396f
2 Author: Jean-Philippe Braun <eon@patapon.info>
3 Date: 2016-08-30 12:16:25 +0200
4
5 Merge pull request #250 from fenryxo/nuvola-rating
6
7 Add support for Nuvola Player's MPRIS rating API
8
9 commit fb5da1bb7f55442d695b7abcb34b1690ed9dc86c
10 Author: Jean-Philippe Braun <eon@patapon.info>
11 Date: 2016-08-27 10:55:46 +0200
12
13 vlc is sending stop on track change
14
15 commit 50741a8d3654a612840181da83b8fbfa3c16438c
16 Author: Jean-Philippe Braun <eon@patapon.info>
17 Date: 2016-08-27 10:46:31 +0200
18
19 Simplify cover management
20
21 Fixes http cover updates with Spotify
22
23 Refs #260
24 Refs #271
25
026 commit c5f9d905fd39dfc978d8416d2c1cb0f6694e0f09
127 Author: Jean-Philippe Braun <jean-philippe.braun@cloudwatt.com>
228 Date: 2016-05-09 20:44:30 +0200
3157 Do not disable already disabled extension
3258
3359 Causes 'manager is null' js error
60
61 commit 38a396fd4e449de282484423625c4f6ead74218f
62 Author: Jiří Janoušek <janousek.jiri@gmail.com>
63 Date: 2016-03-06 10:07:57 +0100
64
65 Add support for Nuvola Player's MPRIS rating API
66
67 The Nuvola Player's MPRIS interface provides following non-standard
68 vendor-prefixed rating API:
69
70 * the Player.NuvolaCanRate Boolean property, which is true when rating
71 is possible
72 * the Player.NuvolaSetRating(Double rating) method to set rating with
73 the double value having the same meaning as xesam:userRating in
74 Metadata property.
75
76 Upstream Issue: tiliado/nuvolaplayer#204
77
78 Signed-off-by: Jiří Janoušek <janousek.jiri@gmail.com>
3479
3580 commit 040807fce94f952364c0b1a253b1031e44d5ca26
3681 Merge: e14b8fe 6393aa8
28292874 Merge branch 'playlists' into devel
28302875
28312876 Conflicts:
2832 po/pl.po
2877 po/pl.po
28332878
28342879 commit ffd0424b2e782b1d8f1bb0d736d5fbff9fe64c17
28352880 Merge: 42a666e 02fe361
6262 trackArtist: null,
6363 trackUrl: null,
6464 trackCoverUrl: null,
65 trackCoverPath: null,
6665 trackLength: null,
6766 trackObj: null,
6867 trackRating: null,
111110 this._currentPlaylist = "";
112111 this._trackTime = 0;
113112 this._wantedSeekValue = 0;
114 this._trackCoverFileTmp = null;
115113
116114 this._timerId = 0;
117115 this._statusId = 0;
143141 }));
144142
145143 this.connect("player-update", Lang.bind(this, function(player, state) {
144 //global.log(JSON.stringify(state));
146145 this.state.update(state);
147146 if (state.status)
148147 this._onStatusChange();
360359 state.trackLength = metadata["mpris:length"] ? metadata["mpris:length"].unpack() / 1000000 : 0;
361360 state.trackObj = metadata["mpris:trackid"] ? metadata["mpris:trackid"].unpack() : "";
362361 state.trackCoverUrl = metadata["mpris:artUrl"] ? metadata["mpris:artUrl"].unpack() : "";
363 state.isRadio = false;
364
365 if (state.trackCoverUrl !== this.state.trackCoverUrl) {
366 if (state.trackCoverUrl) {
367 let cover_path = "";
368 // Distant cover
369 if (state.trackCoverUrl.match(/^http/)) {
370 // Copy the cover to a tmp local file
371 let cover = Gio.file_new_for_uri(decodeURIComponent(state.trackCoverUrl));
372 // Don't create multiple tmp files
373 if (!this._trackCoverFileTmp)
374 this._trackCoverFileTmp = Gio.file_new_tmp('XXXXXX.mediaplayer-cover')[0];
375 // asynchronous copy
376 cover.read_async(null, null, Lang.bind(this, this._onReadCover));
377 }
378 // Local cover
379 else if (state.trackCoverUrl.match(/^file/)) {
380 state.trackCoverPath = decodeURIComponent(state.trackCoverUrl.substr(7));
381 }
382 }
383 else {
384 state.trackCoverPath = '';
385 }
386 }
387362
388363 if (state.trackCoverUrl === '' && metadata["xesam:genre"]) {
389364 let genres = metadata["xesam:genre"].deep_unpack();
408383 if (metadata.rating)
409384 rating = metadata.rating.deep_unpack();
410385 state.trackRating = parseInt(rating);
411 },
412
413 _onReadCover: function(cover, result) {
414 let inStream = cover.read_finish(result);
415 let outStream = this._trackCoverFileTmp.replace(null, false,
416 Gio.FileCreateFlags.REPLACE_DESTINATION,
417 null, null);
418 outStream.splice_async(inStream, Gio.OutputStreamSpliceFlags.CLOSE_TARGET,
419 0, null, Lang.bind(this, function(outStream, result) {
420 outStream.splice_finish(result, null);
421 this.emit('player-update',
422 new PlayerState({trackCoverPath: this._trackCoverFileTmp.get_path()}));
423 }));
424386 },
425387
426388 _refreshProperties: function() {
5656
5757 const SEND_STOP_ON_CHANGE = [
5858 "org.mpris.MediaPlayer2.banshee",
59 "org.mpris.MediaPlayer2.vlc",
5960 "org.mpris.MediaPlayer2.pragha"
6061 ];
6162
130130
131131 this.activePlaylist = null;
132132
133 this.trackCoverUrl = false;
134 this.trackCoverFileTmp = false;
135133 this.trackCover = new St.Button({style_class: 'track-cover-container',
136134 x_align: St.Align.START,
137135 y_align: St.Align.START,
334332 this.setActivePlaylist(newState.playlist);
335333 }
336334
337 if (newState.trackCoverPath !== null || newState.isRadio !== null) {
335 if (newState.trackCoverUrl !== null || newState.isRadio !== null) {
338336 this.hideCover();
339337 this.showCover(newState);
340338 }
372370 icon_size: this.trackCover.child.icon_size});
373371 this.trackCover.child = coverIcon;
374372 }
375 else if (! state.trackCoverPath || ! GLib.file_test(state.trackCoverPath, GLib.FileTest.EXISTS)) {
373 else if (state.trackCoverUrl) {
374 let file = Gio.File.new_for_uri(state.trackCoverUrl);
375 let gicon = new Gio.FileIcon({file: file});
376 let coverIcon = new St.Icon({gicon: gicon, style_class: "track-cover",
377 icon_size: this.trackCover.child.icon_size});
378 this.trackCover.child = coverIcon;
379 }
380 else {
376381 let coverIcon = new St.Icon({icon_name: "media-optical-cd-audio",
377382 icon_size: this.trackCover.child.icon_size});
378383 this.trackCover.child = coverIcon;
379384 }
380 else {
381 let gicon = new Gio.FileIcon({file: Gio.File.new_for_path(state.trackCoverPath)});
382 let coverIcon = new St.Icon({gicon: gicon, style_class: "track-cover",
383 icon_size: this.trackCover.child.icon_size});
384 this.trackCover.child = coverIcon;
385 }
385
386386 // Show the new cover
387387 Tweener.addTween(this.trackCover, {
388388 opacity: 255,
254254 this._player = player;
255255 // Current value
256256 this._value = value;
257 // Supported players
257 // Supported players (except for Nuvola Player)
258258 this._supported = {
259259 "org.mpris.MediaPlayer2.banshee": this.applyBansheeRating,
260260 "org.mpris.MediaPlayer2.rhythmbox": this.applyRhythmbox3Rating,
289289 },
290290
291291 newRating: function(button) {
292 if (this._supported[this._player.busName]) {
292 if (this._supported[this._player.busName] || this.nuvolaRatingSupported()) {
293293 if (button.hover)
294294 this.hoverRating(button._rateValue);
295295 else
336336 let applyFunc = Lang.bind(this, this._supported[this._player.busName]);
337337 applied = applyFunc(rateValue);
338338 }
339 else if (this.getNuvolaRatingProxy()) {
340 applied = this.applyNuvolaRating(rateValue);
341 }
339342 if (applied) {
340343 this.setRating(rateValue);
341344 }
377380 return false;
378381 },
379382
383 getNuvolaRatingProxy: function() {
384 if (this._nuvolaRatingProxy === false) {
385 return false;
386 }
387 if (this._nuvolaRatingProxy) {
388 return this._nuvolaRatingProxy;
389 }
390 /* Web apps running in the Nuvola Player runtime are named "org.mpris.MediaPlayer2.NuvolaAppFooBarBaz" */
391 if (this._player.busName.indexOf("org.mpris.MediaPlayer2.NuvolaApp") !== 0) {
392 this._nuvolaRatingProxy = false;
393 return false;
394 }
395 const NuvolaRatingIface = '<node>\
396 <interface name="org.mpris.MediaPlayer2.Player">\
397 <method name="NuvolaSetRating">\
398 <arg type="d" direction="in" />\
399 </method>\
400 <property name="NuvolaCanRate" type="b" access="read" />\
401 </interface>\
402 </node>';
403 const NuvolaRatingProxy = Gio.DBusProxy.makeProxyWrapper(NuvolaRatingIface);
404 this._nuvolaRatingProxy = new NuvolaRatingProxy(Gio.DBus.session, this._player.busName,
405 "/org/mpris/MediaPlayer2");
406 return this._nuvolaRatingProxy;
407 },
408
409 nuvolaRatingSupported: function() {
410 let proxy = this.getNuvolaRatingProxy();
411 if (proxy) {
412 return proxy.NuvolaCanRate;
413 }
414 return false;
415 },
416
417 applyNuvolaRating: function(value) {
418 let proxy = this.getNuvolaRatingProxy();
419 if (proxy && proxy.NuvolaCanRate) {
420 proxy.NuvolaSetRatingRemote(value / 5.0);
421 return true;
422 }
423 return false;
424 },
425
380426 destroy: function() {
381427 this.actor.destroy();
382428 },