4
Copyright 2011 Jiří Janoušek <janousek.jiri@gmail.com>
6
This program is free software: you can redistribute it and/or modify it
7
under the terms of the GNU General Public License version 3, as published
8
by the Free Software Foundation.
10
This program is distributed in the hope that it will be useful, but
11
WITHOUT ANY WARRANTY; without even the implied warranties of
12
MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
13
PURPOSE. See the GNU General Public License for more details.
15
You should have received a copy of the GNU General Public License along
16
with this program. If not, see <http://www.gnu.org/licenses/>.
19
/* http://www.mpris.org/2.1/spec/Player_Node.html */
20
[DBus(name = "org.mpris.MediaPlayer2.Player")]
21
public class GMF.Player : GLib.Object{
23
private DBusConnection conn;
24
private HashTable<string,Variant> song_info;
26
public Player(Application app, DBusConnection conn){
27
this.frame = app.frame;
29
this.song_info = new HashTable<string,Variant>(null, null);
30
this.notify.connect(this.send_property_change);
31
this.frame.song_changed.connect(this.on_song_changed);
32
this.frame.playback_state_changed.connect(this.on_playback_state_changed);
35
private void send_property_change (ParamSpec p) {
36
var builder = new VariantBuilder (VariantType.ARRAY);
37
var invalid_builder = new VariantBuilder (new VariantType ("as"));
38
debug("send changed %s", p.name);
43
builder.add ("{sv}", "Metadata", i);
45
case "can-go-previous":
46
i = this.can_go_previous;
47
builder.add ("{sv}", "CanGoPrevious", i);
51
builder.add ("{sv}", "CanGoNext", i);
55
builder.add ("{sv}", "CanPlay", i);
59
builder.add ("{sv}", "CanPause", i);
61
case "playback-status":
62
i = this.playback_status;
63
builder.add ("{sv}", "PlaybackStatus", i);
66
warning("Unhandled property: %s", p.name);
70
var v = new Variant("(sa{sv}as)", "org.mpris.MediaPlayer2.Player",
71
builder, invalid_builder);
73
conn.emit_signal ("org.mpris.MediaPlayer2.googlemusicframe",
74
"/org/mpris/MediaPlayer2",
75
"org.freedesktop.DBus.Properties",
76
"PropertiesChanged", v );
79
stderr.printf ("%s\n", e.message);
83
private void on_song_changed(string? art, string? artist, string? song){
84
var info = new HashTable<string,Variant>(null, null);
85
string[] artistArray = {};
86
if(artist != null) artistArray += artist;
87
info.insert("xesam:artist", artistArray);
88
if(song != null) info.insert("xesam:title", song);
89
if(art != null) info.insert("mpris:artUrl", art);
93
private void on_playback_state_changed(string state, bool can_prev, bool can_next){
94
this.playback_status = state == "none" ? "Stopped"
95
: (state == "paused" ? "Paused" : "Playing");
97
this.can_go_previous = can_prev;
98
this.can_go_next = can_next;
99
this.can_pause = this.can_play = state != "none";
102
/* Properties: http://www.mpris.org/2.1/spec/Player_Node.html#properties */
104
[Description(nick = "The current playback status.", blurb = "The current playback status. May be 'Playing', 'Paused' or 'Stopped'.")]
105
public string playback_status { owned get; private set; default = "Stopped";}
107
[Description(nick = "The current loop / repeat status", blurb = "May be: 'None' if the playback will stop when there are no more tracks to play. 'Track' if the current track will start again from the begining once it has finished playing. 'Playlist' if the playback loops through a list of tracks.")]
108
public string LoopStatus{
128
//~ [Description(nick = "The current playback rate.", blurb = "The current playback rate.")]
129
//~ public double Rate{
131
//~ return (double)1.0;
137
//~ [Description(nick = "Minimum playback rate.", blurb = "Minimum playback rate.")]
138
//~ public double MinimumRate{
140
//~ return (double)1.0;
144
//~ [Description(nick = "Maximum playback rate.", blurb = "Maximum playback rate.")]
145
//~ public double MaximumRate{
147
//~ return (double)1.0;
151
[Description(nick = "Shuffle state", blurb = "A value of false indicates that playback is progressing linearly through a playlist, while true means playback is progressing through a playlist in some other order.")]
165
[Description(nick = "The metadata of the current element.", blurb = "The metadata of the current element.")]
166
public HashTable<string,Variant>? Metadata{
168
Variant variant = "1";
169
this.song_info.insert("mpris:trackid", variant);
170
return this.song_info;
173
this.song_info = value;
177
//~ [Description(nick = "The volume level.", blurb = "The volume level.")]
178
//~ public double Volume{
180
//~ return (double)1.0;
187
[Description(nick = "The current track position in microseconds.", blurb = "The current track position in microseconds.")]
188
public int64 Position{
194
[Description(nick = "Next song action availability", blurb = "Whether the client can call the Next method on this interface and expect the current track to change.")]
195
public bool can_go_next{ get; private set; default = false; }
197
[Description(nick = "Previous song action availability", blurb = "Whether the client can call the Previous method on this interface and expect the current track to change.")]
198
public bool can_go_previous{ get; private set; default = false; }
200
[Description(nick = "Play action availability", blurb = "Whether playback can be started using Play or PlayPause.")]
201
public bool can_play{ get; private set; default = false; }
203
[Description(nick = "Pause action availability", blurb = "Whether playback can be paused using Pause or PlayPause.")]
204
public bool can_pause{ get; private set; default = false; }
206
[Description(nick = "Seek action availability", blurb = "Whether the client can control the playback position using Seek and SetPosition. This may be different for different tracks.")]
213
[Description(nick = "Whether the media player may be controlled.", blurb = "Whether the media player may be controlled over this interface.")]
214
public bool CanControl{
220
/* Signals: http://www.mpris.org/2.1/spec/Player_Node.html#signals */
222
* Indicates that the track position has changed in a way that is inconsistant with the current playing state.
223
* @param Position The new position, in microseconds.
225
public signal void Seeked(int64 Position);
227
/* Methods: http://www.mpris.org/2.1/spec/Player_Node.html#methods */
230
* Skips to the next track in the tracklist.
232
* If there is no next track (and endless playback and track repeat are both off),
233
* playback will be stopped. If playback is paused or stopped, it remains that way.
236
this.frame.command("nextSong");
240
* Skips to the previous track in the tracklist.
242
* If there is no previous track (and endless playback and track repeat are both off),
243
* playback will be stopped. If playback is paused or stopped, it remains that way.
245
public void previous(){
246
/* sometimes it's neede to send this command twice :-/ */
247
this.frame.command("prevSong");
253
* If playback is already paused, this has no effect. Calling Play after this should
254
* cause playback to start again from the same position.
257
this.frame.command("pauseSong");
262
* If playback is already paused, resumes playback.
263
* If playback is stopped, starts playback.
265
public void play_pause(){
266
this.frame.command("playPause");
272
* If playback is already stopped, this has no effect. Calling Play after this should
273
* cause playback to start again from the beginning of the track.
276
this.frame.command("pauseSong");
280
* Starts or resumes playback.
282
* If already playing, this has no effect.
283
* If there is no track to play, this has no effect.
286
this.frame.command("playPause ");
290
* Seeks forward in the current track by the specified number of microseconds.
292
* A negative value seeks back. If this would mean seeking back further than the start
293
* of the track, the position is set to 0. If the value passed in would mean seeking
294
* beyond the end of the track, acts like a call to Next. If the CanSeek property
295
* is false, this has no effect.
297
* @param Offset The number of microseconds to seek forward.
299
public void seek(int64 Offset) {
304
* Sets the current track position in microseconds.
306
* If the Position argument is less than 0, does nothing.
307
* If the Position argument is greater than the track length, does nothing.
308
* If the CanSeek property is false, this has no effect.
310
* @param TrackId The currently playing track's identifier. If this does not match
311
* the id of the currently-playing track, the call is ignored as "stale".
312
* @param Position Track position in microseconds.This must be between 0 and <track_length>.
314
public void SetPosition(string dobj, int64 Position) {
319
* @param Uri Uri of the track to load.
321
public void OpenUri(string Uri) {