2
* This file is a part of the Cairo-Dock project
4
* Copyright : (C) see the 'copyright' file.
5
* E-mail : see the 'copyright' file.
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU General Public License
9
* as published by the Free Software Foundation; either version 3
10
* of the License, or (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program. If not, see <http://www.gnu.org/licenses/>.
23
#include <glib/gi18n.h>
24
#include <cairo-dock.h>
26
#include "applet-struct.h"
27
#include "applet-musicplayer.h"
28
#include "applet-dbus.h"
29
#include "applet-draw.h"
30
#include "applet-cover.h"
31
#include "applet-mpris.h"
32
#include "applet-rhythmbox.h"
34
/////////////////////////////////
35
// Les Fonctions propres a RB. //
36
/////////////////////////////////
38
/* Teste si Rhythmbox joue de la musique ou non
40
static void _rhythmbox_getPlaying (void)
43
if (cairo_dock_dbus_get_boolean (myData.dbus_proxy_player,"getPlaying"))
44
myData.iPlayingStatus = PLAYER_PLAYING;
46
myData.iPlayingStatus = PLAYER_PAUSED;
49
/* Retourne l'adresse de la musique jouée
51
static void _rhythmbox_getPlayingUri(void)
54
g_free (myData.cPlayingUri);
55
myData.cPlayingUri = cairo_dock_dbus_get_string (myData.dbus_proxy_player, "getPlayingUri");
58
/* Recupere les infos de la chanson courante, y compris le chemin de la couverture (la telecharge au besoin).
60
static void cd_rhythmbox_getSongInfos (gboolean bGetAll)
62
GHashTable *data_list = NULL;
65
if(dbus_g_proxy_call (myData.dbus_proxy_shell, "getSongProperties", NULL,
66
G_TYPE_STRING, myData.cPlayingUri,
68
MP_DBUS_TYPE_SONG_METADATA,
74
g_free (myData.cArtist);
75
value = (GValue *) g_hash_table_lookup(data_list, "artist");
76
if (value != NULL && G_VALUE_HOLDS_STRING(value)) myData.cArtist = g_strdup (g_value_get_string(value));
77
else myData.cArtist = NULL;
78
cd_message (" cArtist <- %s", myData.cArtist);
80
g_free (myData.cAlbum);
81
value = (GValue *) g_hash_table_lookup(data_list, "album");
82
if (value != NULL && G_VALUE_HOLDS_STRING(value)) myData.cAlbum = g_strdup (g_value_get_string(value));
83
else myData.cAlbum = NULL;
84
cd_message (" cAlbum <- %s", myData.cAlbum);
86
g_free (myData.cTitle);
87
value = (GValue *) g_hash_table_lookup(data_list, "title");
88
if (value != NULL && G_VALUE_HOLDS_STRING(value)) myData.cTitle = g_strdup (g_value_get_string(value));
89
else myData.cTitle = NULL;
90
cd_message (" cTitle <- %s", myData.cTitle);
92
value = (GValue *) g_hash_table_lookup(data_list, "track-number");
93
if (value != NULL && G_VALUE_HOLDS_UINT(value)) myData.iTrackNumber = g_value_get_uint(value);
94
else myData.iTrackNumber = 0;
95
cd_message (" iTrackNumber <- %d", myData.iTrackNumber);
97
value = (GValue *) g_hash_table_lookup(data_list, "duration");
98
if (value != NULL && G_VALUE_HOLDS_UINT(value)) myData.iSongLength = g_value_get_uint(value);
99
else myData.iSongLength = 0;
100
cd_message (" iSongLength <- %ds", myData.iSongLength);
103
const gchar *cString = NULL;
104
value = (GValue *) g_hash_table_lookup(data_list, "rb:coverArt-uri");
105
if (value != NULL && G_VALUE_HOLDS_STRING(value)) // RB nous donne une adresse, eventuellement distante.
106
cString = g_value_get_string(value);
107
cd_musicplayer_set_cover_path (cString);
108
cd_debug ("MP : cCoverPath <- %s", myData.cCoverPath);
110
g_hash_table_destroy (data_list);
114
cd_debug (" can't get song properties");
115
g_free (myData.cPlayingUri);
116
myData.cPlayingUri = NULL;
117
g_free (myData.cTitle);
118
myData.cTitle = NULL;
119
g_free (myData.cAlbum);
120
myData.cAlbum = NULL;
121
g_free (myData.cCoverPath);
122
myData.cCoverPath = NULL;
127
/////////////////////////////////////
128
// Les callbacks des signaux DBus. //
129
/////////////////////////////////////
131
/* Fonction executee a chaque changement de musique.
133
static void onChangeSong(DBusGProxy *player_proxy,const gchar *uri, gpointer data)
136
cd_message ("MP : %s (%s)",__func__,uri);
138
g_free (myData.cPlayingUri);
139
if(uri != NULL && *uri != '\0')
141
myData.cPlayingUri = g_strdup (uri);
142
cd_rhythmbox_getSongInfos (TRUE); // TRUE <=> get all
146
myData.cPlayingUri = NULL;
147
myData.cover_exist = FALSE;
149
g_free (myData.cArtist);
150
myData.cArtist = NULL;
151
g_free (myData.cAlbum);
152
myData.cAlbum = NULL;
153
g_free (myData.cTitle);
154
myData.cTitle = NULL;
155
g_free (myData.cCoverPath);
156
myData.cCoverPath = NULL;
157
myData.iSongLength = 0;
158
myData.iTrackNumber = 0;
160
cd_musicplayer_update_icon ();
164
/* Fonction executee a chaque changement play/pause
166
static void onChangePlaying(DBusGProxy *player_proxy, gboolean playing, gpointer data)
170
myData.iPlayingStatus = PLAYER_PLAYING;
172
myData.iPlayingStatus = PLAYER_PAUSED;
173
if(! myData.cover_exist && myData.cPlayingUri != NULL)
175
cd_message (" cPlayingUri : %s", myData.cPlayingUri);
176
cd_musicplayer_apply_status_surface (myData.iPlayingStatus);
180
CD_APPLET_REDRAW_MY_ICON;
186
/* Fonction executee a chaque changement de temps joué
188
static void onElapsedChanged (DBusGProxy *player_proxy, int elapsed, gpointer data)
191
myData.iCurrentTime = elapsed;
194
cd_debug ("%s (%ds/%ds)", __func__, elapsed, myData.iSongLength);
195
if(myConfig.iQuickInfoType == MY_APPLET_TIME_ELAPSED)
197
CD_APPLET_SET_MINUTES_SECONDES_AS_QUICK_INFO (elapsed);
198
CD_APPLET_REDRAW_MY_ICON;
200
else if(myConfig.iQuickInfoType == MY_APPLET_TIME_LEFT) // avec un '-' devant.
202
CD_APPLET_SET_MINUTES_SECONDES_AS_QUICK_INFO (elapsed - myData.iSongLength);
203
CD_APPLET_REDRAW_MY_ICON;
205
else if(myConfig.iQuickInfoType == MY_APPLET_PERCENTAGE)
207
CD_APPLET_SET_QUICK_INFO_ON_MY_ICON_PRINTF ("%d%%", (int) (100.*elapsed/myData.iSongLength));
208
CD_APPLET_REDRAW_MY_ICON;
215
/*static void onSongPropertyChanged (DBusGProxy *player_proxy, const gchar *a, const gchar *cProperty, GValue *c, GValue *d, gpointer data)
218
cd_debug ("\n%s (%s)\n\n",__func__,cImageURI);
219
g_free (myData.cCoverPath);
220
myData.cCoverPath = g_strdup (cImageURI);
222
CD_APPLET_SET_IMAGE_ON_MY_ICON (myData.cCoverPath);
223
CD_APPLET_REDRAW_MY_ICON;
224
myData.cover_exist = TRUE;
225
if (myData.iSidCheckCover != 0)
227
g_source_remove (myData.iSidCheckCover);
228
myData.iSidCheckCover = 0;
234
////////////////////////////
235
// Definition du backend. //
236
////////////////////////////
238
/* Controle du lecteur (permet d'effectuer les actions de bases sur le lecteur)
240
void cd_rhythmbox_control (MyPlayerControl pControl, const char* song)
243
const gchar *cCommand = NULL;
246
case PLAYER_PREVIOUS :
247
cCommand = "previous"; // ou bien rhythmbox-client --previous
250
case PLAYER_PLAY_PAUSE :
251
cCommand = "playPause"; // ou bien rhythmbox-client --pause/--play
255
cCommand = "next"; // ou bien rhythmbox-client --next
258
case PLAYER_ENQUEUE :
260
gchar *cCommand2 = g_strdup_printf ("rhythmbox-client --enqueue %s", song);
261
g_spawn_command_line_async (cCommand2, NULL);
271
if (pControl == PLAYER_PLAY_PAUSE) // Cas special pour RB qui necessite un argument pour le PlayPause
273
gboolean bStartPlaying = (myData.iPlayingStatus != PLAYER_PLAYING);
274
dbus_g_proxy_call_no_reply (myData.dbus_proxy_player, cCommand,
275
G_TYPE_BOOLEAN, bStartPlaying,
279
else if (cCommand != NULL)
281
cd_debug ("MP : Handler rhythmbox : will use '%s'", cCommand);
282
cairo_dock_dbus_call (myData.dbus_proxy_player, cCommand);
286
void cd_rhythmbox_get_cover_path (void)
288
cd_rhythmbox_getSongInfos (FALSE); // FALSE <=> on ne recupere que la couverture.
291
/* Initialise le backend de RB.
293
static void cd_rhythmbox_start (void)
295
// register to the signals
296
dbus_g_proxy_add_signal(myData.dbus_proxy_player, "playingChanged",
299
dbus_g_proxy_connect_signal(myData.dbus_proxy_player, "playingChanged",
300
G_CALLBACK(onChangePlaying), NULL, NULL);
302
dbus_g_proxy_add_signal(myData.dbus_proxy_player, "playingUriChanged",
305
dbus_g_proxy_connect_signal(myData.dbus_proxy_player, "playingUriChanged",
306
G_CALLBACK(onChangeSong), NULL, NULL);
308
dbus_g_proxy_add_signal(myData.dbus_proxy_player, "elapsedChanged",
311
dbus_g_proxy_connect_signal(myData.dbus_proxy_player, "elapsedChanged",
312
G_CALLBACK(onElapsedChanged), NULL, NULL);
314
/*TODO (or maybe not, if they included MPRIS2)
315
dbus_g_proxy_add_signal(myData.dbus_proxy_player, "playingSongPropertyChanged",
321
dbus_g_proxy_connect_signal(myData.dbus_proxy_player, "playingSongPropertyChanged",
322
G_CALLBACK(onSongPropertyChanged), NULL, NULL);*/
324
// get the current state.
325
_rhythmbox_getPlaying();
326
_rhythmbox_getPlayingUri();
327
cd_rhythmbox_getSongInfos (TRUE); // TRUE <=> get all
328
cd_musicplayer_update_icon ();
331
/* On enregistre notre lecteur.
333
void cd_musicplayer_register_rhythmbox_handler (void)
335
cd_debug ("MP - Used RB DBus methods");
336
MusicPlayerHandler *pHandler = g_new0 (MusicPlayerHandler, 1);
337
pHandler->name = "Rhythmbox";
338
pHandler->get_data = NULL; // rien a faire vu que l'echange de donnees se fait entierement avec les proxys DBus.
339
pHandler->stop = NULL; // signals are disconnected when the proxy is destroyed.
340
pHandler->start = cd_rhythmbox_start; // renseigne les proprietes DBus et se connecte au bus.
341
pHandler->control = cd_rhythmbox_control;
342
pHandler->get_cover = cd_rhythmbox_get_cover_path;
344
pHandler->appclass = "rhythmbox";
345
pHandler->launch = "rhythmbox";
346
pHandler->cMprisService = "org.gnome.Rhythmbox"; // they used MPRIS from version 2.90.1~20110908 with org.mpris.MediaPlayer2.rhythmbox, but we don't care as they quickly switched to MPRIS2 in version 2.90.1~20111126
347
pHandler->cMpris2Service = "org.mpris.MediaPlayer2.rhythmbox"; // after 2.90.1~20111126 (on a previous development version, they used rhythmbox3...)
348
pHandler->path = "/org/gnome/Rhythmbox/Player"; // <= 0.13
349
pHandler->interface = "org.gnome.Rhythmbox.Player";
350
pHandler->path2 = "/org/gnome/Rhythmbox/Shell";
351
pHandler->interface2 = "org.gnome.Rhythmbox.Shell";
353
pHandler->cCoverDir = g_strdup_printf ("%s/.cache/rhythmbox/covers", g_getenv ("HOME"));
354
pHandler->bSeparateAcquisition = FALSE;
355
pHandler->iPlayerControls = PLAYER_PREVIOUS | PLAYER_PLAY_PAUSE | PLAYER_NEXT | PLAYER_ENQUEUE;
356
pHandler->iLevel = PLAYER_EXCELLENT;
358
cd_musicplayer_register_my_handler(pHandler);