175
163
player->proxy = NULL;
165
if (G_IS_OBJECT(player->prop_proxy)) {
166
g_object_unref(player->prop_proxy);
168
player->prop_proxy = NULL;
177
170
g_free(player->service_name);
171
g_free(player->exec_name);
178
172
g_free(player->app_name);
179
173
g_free(player->icon_name);
183
DBusGConnection *dbus_player_connect_to_dbus() {
184
// Connect to glib/DBus
185
GError *error = NULL;
188
g_dbus_conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
191
LOG_ERROR("dbus_player_connect_to_dbus: Cannot connect to DBus: %s\n", error ? error->message : "");
202
void dbus_player_disconnect_from_dbus() {
203
// Disconnect from glib/DBus
205
dbus_g_connection_unref(g_dbus_conn);
210
177
MediaPlayerRec *dbus_player_lookup_app_name(gchar *app_name) {
211
178
// Lookup player by its application name (p->app_name).
212
179
// Typical app_names are "Amarok 2.3.2", "RhythmBox 2.3" and "Skype 2.1.0".
302
264
// Clear the old list
303
265
dbus_player_clear_list();
305
// Connect to glib/DBus
306
if (!dbus_player_connect_to_dbus()) {
307
LOG_ERROR("dbus_player_get_players: Error, cannot connect to DBus.\n");
311
267
// Populate the list.
312
// Detect players that follow the MPRIS* standarden, such as Amarok.
313
// Add also non-standard media players like Banshee and RhythmBox.
314
// Add also Skype if it's installed.
315
dbus_player_detect_software();
317
// Add Rhythmbox manually (if installed)
318
add_rhythmbox_player(TRUE);
320
// Add Banshee manually (if installed)
321
add_banshee_player(TRUE);
323
// Add Totem (if installed)
324
add_totem_player(TRUE);
326
// Add Skype (if installed)
268
// Detect players that follow the org.mpris.MediaPlayer2.* standard.
269
mpris2_detect_players();
271
// Make sure the most popular players are in the list.
273
// Add Rhythmbox manually (check if installed)
274
// TODO: Should we translate the app-names?
275
add_player_manually("Rhythmbox", "rhythmbox", "org.mpris.MediaPlayer2.rhythmbox");
277
// Add Banshee manually (check if installed)
278
add_player_manually("Banshee", "banshee", "org.mpris.MediaPlayer2.banshee");
280
// Add Skype manually (check if installed)
329
283
return g_player_list;
332
void add_skype(gboolean find) {
286
void add_player_manually(gchar *app_name, gchar *exec_name, gchar *service_name) {
287
// Add player manually to the list. Check if it's installed.
289
// Already in the list?
290
if (dbus_player_lookup_service_name(service_name)) return;
292
// Find executable /usr/bin/exec_name
293
gchar *path = find_command_path(exec_name);
300
// New MediaPlayer record
301
MediaPlayerRec *player = mpris2_player_new(service_name);
304
player->exec_name = g_strdup(exec_name);
306
// Set application name. This is shown in the listbox
307
player->app_name = g_strdup(app_name);
309
// Function to connect/disconnect event signals for this player
310
player->func_set_signals = mpris2_set_signals;
312
// Function to get track-info (album, track/song name/title, genre, etc.)
313
player->func_get_info = mpris2_get_metadata;
315
// Function to start/run the media player
316
player->func_start_app = mpris2_start_app;
318
// Function to check if this player is running
319
player->func_check_is_running = mpris2_service_is_running;
321
// Function to check if this player is up & running
322
player->active = mpris2_service_is_running_by_name(service_name);
325
player->icon_name = g_strdup_printf("%s.png", exec_name);
327
if (!dbus_player_lookup_app_name(player->app_name)) {
329
GHashTable *player_list = dbus_player_get_list_ref();
330
g_hash_table_insert(player_list, g_strdup(player->service_name), player);
332
// Duplicate or bad record. Free it.
333
dbus_player_delete_item(player);
335
340
gchar *service_name = "com.Skype.API";
379
void add_rhythmbox_player(gboolean find) {
382
gchar *service_name = "org.gnome.Rhythmbox";
384
// Already in the list?
385
if (dbus_player_lookup_service_name(service_name)) return;
388
// Find /usr/bin/rhythmbox
389
gchar *path = find_command_path("rhythmbox");
396
// New MediaPlayer record
397
MediaPlayerRec *player = mpris_player_new(service_name);
399
// Set real application name (player->app_name)
400
// Rhythmbox does not understand the "Identity" message
402
// Set real application name
403
rhythmbox_get_app_name(player);
405
// Function to connect/disconnect event signals for this player
406
player->func_set_signals = rhythmbox_set_signals;
408
// Function to get track-info (album, track/song name/title, genre, etc.)
409
player->func_get_info = rhythmbox_get_info;
411
// Function to start/run the media player
412
player->func_start_app = rhythmbox_start_app;
414
// Function to check if this player is up & running
415
player->active = mpris_service_is_running_by_name(service_name);
418
player->icon_name = g_strdup("rhythmbox.png");
420
if (!dbus_player_lookup_app_name(player->app_name)) {
422
GHashTable *player_list = dbus_player_get_list_ref();
423
g_hash_table_insert(player_list, g_strdup(player->service_name), player);
425
// Duplicate or bad record. Free it.
426
dbus_player_delete_item(player);
430
static void add_banshee_player(gboolean find) {
433
gchar *service_name = "org.bansheeproject.Banshee";
435
// Already in the list?
436
if (dbus_player_lookup_service_name(service_name)) return;
439
// Find /usr/bin/banshee
440
gchar *path = find_command_path("banshee");
447
// New MediaPlayer record
448
MediaPlayerRec *player = mpris_player_new(service_name);
450
// Set real application name (player->app_name)
451
// Banshee does not understand the "Identity" message
452
banshee_get_app_name(player);
454
// Function that can connect/disconnect event signals
455
player->func_set_signals = banshee_set_signals;
457
// Function to get track-info (album, track/song name/title, genre, etc.)
458
player->func_get_info = banshee_get_info;
460
// Function to start/run the media player
461
player->func_start_app = banshee_start_app;
463
// Function to check if this player is up & running
464
player->active = mpris_service_is_running_by_name(service_name);
467
player->icon_name = g_strdup("banshee.png");
469
if (!dbus_player_lookup_app_name(player->app_name)) {
471
GHashTable *player_list = dbus_player_get_list_ref();
472
g_hash_table_insert(player_list, g_strdup(player->service_name), player);
475
// Duplicate or bad record. Free it.
476
dbus_player_delete_item(player);
480
void add_totem_player(gboolean find) {
483
// ******************************
484
// Totem player removed because it does now follow the MPRIS standard well.
485
// ******************************
489
gchar *service_name = "org.mpris.Totem";
491
// Already in the list?
492
if (dbus_player_lookup_service_name(service_name)) return;
495
// Find /usr/bin/totem
496
gchar *path = find_command_path("totem");
503
// New MediaPlayer record
504
MediaPlayerRec *player = mpris_player_new(service_name);
506
// Set real application name
507
mpris_get_app_name(player);
509
// Totem may not understand the "Identity" message!
510
if (!player->app_name) {
511
// Name of the Totem Media Player.
512
player->app_name = g_strdup(_("Totem Media Player"));
515
// Function to connect/disconnect event signals
516
player->func_set_signals = mpris_set_signals;
518
// Function to get track-info (album, track/song name/title, genre, etc.)
519
player->func_get_info = mpris_get_info;
521
// Function to start/run the media player
522
player->func_start_app = mpris_start_app;
524
// Function to check if this player is up & running
525
player->active = mpris_service_is_running_by_name(service_name);
528
player->icon_name = g_strdup("totem.png");
530
if (!dbus_player_lookup_app_name(player->app_name)) {
532
GHashTable *player_list = dbus_player_get_list_ref();
533
g_hash_table_insert(player_list, g_strdup(player->service_name), player);
536
// Duplicate or bad record. Free it.
537
dbus_player_delete_item(player);
541
383
void dbus_player_send_notification(MediaPlayerRec *player, gchar *msg) {
384
// Send notification msg to the recorder/GUI.
542
385
MediaPlayerRec *p = NULL;
546
// Create a "dummy" MediaPlayerRec
547
p = mpris_player_new(NULL);
389
// Create a dummy MediaPlayerRec
390
p = mpris2_player_new(NULL);
550
// Set active so the message goes through
553
393
// Send msg in the track field
554
394
TrackInfo *tr = &p->track;
558
398
tr->status = PLAYER_STATUS_NOTIFY_MSG;
560
// Sends the message via dbus-player.c (as all DBus modules should do!)
400
// Sends the message via dbus-player.c
561
401
dbus_player_process_data(p);
563
// Delete the tmp player
403
// Delete the dummy thing
565
405
dbus_player_delete_item(p);
569
void dbus_player_detect_software() {
570
// Get the list of DBus services (software that i sregistered on the DBus).
571
// Add all MPRIS (org.mpris.*) compliant programs to player list.
573
#define DBUS_MPRIS_NAMESPACE "org.mpris."
575
// Connect to glib/DBus
576
DBusGConnection *dbus_conn = dbus_player_connect_to_dbus();
577
if (!dbus_conn) return;
580
GHashTable *player_list = dbus_player_get_list_ref();
582
// Get service names from the DBus
583
char **name_list = NULL;
585
// Reset error structure
586
GError *error = NULL;
588
// These values come from:
589
// http://dbus.freedesktop.org/doc/api/html/group__DBusShared.html
591
// DBUS_SERVICE_DBUS "org.freedesktop.DBus"
592
// DBUS_PATH_DBUS "/org/freedesktop/DBus"
593
// DBUS_INTERFACE_DBUS "org.freedesktop.DBus"
594
DBusGProxy *proxy = dbus_g_proxy_new_for_name(dbus_conn,
597
DBUS_INTERFACE_DBUS);
599
// Call ListNames method, wait for reply
600
if (!dbus_g_proxy_call(proxy, "ListNames", &error, G_TYPE_INVALID, G_TYPE_STRV, &name_list, G_TYPE_INVALID)) {
601
if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_REMOTE_EXCEPTION)
602
LOG_ERROR("dbus_player_detect_software: Caught remote method exception %s: %s", dbus_g_error_get_name(error), error->message);
604
LOG_ERROR("dbus_player_detect_software: %s\n", error->message);
610
// Loop through gchar *name_list[]
612
for (cptr = name_list; *cptr; cptr++) {
613
// Drop names that start with ":"
614
gchar *service_name = *cptr;
616
if (service_name && service_name[0] == ':') {
620
// MediaPlayer record
621
MediaPlayerRec *player = NULL;
624
// Uncomment this to see all found service names
625
// LOG_PLAYER("DBus service_name:%s\n", service_name);
627
// Non-standard (non-MPRIS) media player
628
if (!strncmp(service_name, "org.gnome.Rhythmbox", strlen("org.gnome.Rhythmbox"))) {
630
add_rhythmbox_player(FALSE);
634
// RhythmBox is MPRIS2 compatible player
635
else if (!strncmp(service_name, "org.mpris.MediaPlayer2.rhythmbox", strlen("org.mpris.MediaPlayer2.rhythmbox"))) {
637
// TODO: Add support for org.mpris.MediaPlayer2.rhythmbox
641
// Non-standard (non-MPRIS) media player
642
else if (!strncmp(service_name, "org.bansheeproject.Banshee", strlen("org.bansheeproject.Banshee"))) {
644
add_banshee_player(FALSE);
648
// Somehow non-standard (non-MPRIS) media player
649
// else if (!strncmp(service_name, "org.gnome.Totem", strlen("org.gnome.Totem"))) {
650
else if (!strncmp(service_name, "org.mpris.Totem", strlen("org.mpris.Totem"))) {
652
add_totem_player(FALSE);
657
else if (!g_strcmp0(service_name, "com.Skype.API")) {
662
// Add all standard following media players (org.mpris.*).
663
// Eg. The Amarok 2.x player implements the MPRIS DBus API well.
664
else if (!strncmp(DBUS_MPRIS_NAMESPACE, service_name, strlen(DBUS_MPRIS_NAMESPACE))) {
666
// New MediaPlayer record
667
player = mpris_player_new(service_name);
669
// Set real application name (player->app_name)
670
mpris_get_app_name(player);
672
// TODO: Check this. Remove hard-coding if possible.
674
if (g_strrstr(player->service_name, "amarok") || g_strrstr(player->service_name, "Amarok")) {
675
player->icon_name = g_strdup("amarok.png");
677
player->icon_name = g_strdup("sound.png");
680
// Function to connect/disconnect event signals for this players
681
player->func_set_signals = mpris_set_signals;
683
// Function to check if this player is running
684
player->func_check_is_running = mpris_service_is_running;
686
// Function to get track-info (album, track/song name/title, genre, etc.)
687
player->func_get_info = mpris_get_info;
689
// Function to start/run the media player
690
player->func_start_app = mpris_start_app;
693
// Has a player record?
694
if (player && player->app_name) {
696
// Is this player running/is active?
697
player->active = mpris_service_is_running_by_name(player->service_name);
699
// Add player to the g_player_list.
701
// Some players send double set of information to the DBus.
702
// Eg. "Amarok 2.3.2" identifies itself as service_name 'org.mpris.amarok' and 'org.mpris.MediaPlayer2.amarok'.
704
// Lookup the record by its app_name (like: "Amarok 2.3.2")
705
if (!dbus_player_lookup_app_name(player->app_name)) {
706
// Add it to the list
707
g_hash_table_insert(player_list, g_strdup(player->service_name), player);
709
// Duplicate or bad record. Free it.
710
dbus_player_delete_item(player);
715
// Free the name_list
716
g_strfreev(name_list);
719
g_object_unref(proxy);