/* * vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab * * $LastChangedDate$ * $Revision$ * $LastChangedBy$ * $URL$ * * Copyright 2009-2011 Eric Connell * * This file is part of Mangler. * * Mangler is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Mangler is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Mangler. If not, see . */ // MPRIS INTERFACE: http://wiki.xmms2.xmms.se/wiki/MPRIS #include "manglerintegration.h" #include "config.h" #include using namespace std; bool ManglerIntegration::update(bool forceUpdate, const gchar *data) { switch (client) { #ifdef HAVE_LIBMPDCLIENT case MusicClient_MPD: { // Get out of idle mode mpd_idle idle_status = mpd_run_noidle (mpd_connection); // If there was no change of song, return false, and go back in idle mode if (idle_status != MPD_IDLE_PLAYER && !forceUpdate) { mpd_send_idle (mpd_connection); return false; } // Retrieve the status object struct mpd_status *status = mpd_run_status (mpd_connection); // Playback is stopped, or unknown mpd_state current_state = mpd_status_get_state (status); if (current_state == MPD_STATE_STOP || current_state == MPD_STATE_UNKNOWN) { current_status = 0; } if (current_state == MPD_STATE_PAUSE) { current_status = 1; } if (current_state == MPD_STATE_PLAY) { current_status = 2; } // Get the currrent song int current_song_pos = mpd_status_get_song_pos (status); if (current_song_pos == -1) { return false; } struct mpd_song *current_song = mpd_run_get_queue_song_pos (mpd_connection, current_song_pos); if (current_song == NULL) { return false; } // Fill the strings artist = mpd_song_get_tag (current_song, MPD_TAG_ARTIST, 0); title = mpd_song_get_tag (current_song, MPD_TAG_TITLE, 0); album= mpd_song_get_tag (current_song, MPD_TAG_ALBUM, 0); // Free the memory for the status and song objects, and go back in idle mode mpd_status_free (status); mpd_song_free (current_song); mpd_send_idle (mpd_connection); return true; } break; #endif default: break; } return false; } ManglerIntegration::ManglerIntegration () { #ifdef HAVE_LIBMPDCLIENT mpd_connection = NULL; #endif } void ManglerIntegration::setClient (MusicClient _client) { client = _client; switch (client) { case MusicClient_None: break; #ifdef HAVE_LIBMPDCLIENT case MusicClient_MPD: { mode = 0; const char *hostname = "localhost"; int port = 6600; int timeout = -1; mpd_connection = mpd_connection_new (hostname, port, timeout); mpd_send_idle (mpd_connection); } break; #endif #ifdef HAVE_DBUS case MusicClient_Rhythmbox: { mode = 1; dbus_namespace = "org.gnome.Rhythmbox"; dbus_player = "org.gnome.Rhythmbox.Player"; dbus_player_path = "/org/gnome/Rhythmbox/Player"; dbus_shell = "org.gnome.Rhythmbox.Shell"; dbus_shell_path = "/org/gnome/Rhythmbox/Shell"; dbus_uri_changed = "playingUriChanged"; dbus_playing_changed = "playingChanged"; dbus_get_current_song = "getPlayingUri"; dbus_get_song_properties = "getSongProperties"; bus = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); player = dbus_g_proxy_new_for_name (bus, dbus_namespace.c_str(), dbus_player_path.c_str(), dbus_player.c_str()); shell = dbus_g_proxy_new_for_name (bus, dbus_namespace.c_str(), dbus_shell_path.c_str(), dbus_shell.c_str()); dbus_g_proxy_add_signal (player, dbus_uri_changed.c_str(), G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal (player, dbus_uri_changed.c_str(), G_CALLBACK (dbus_uri_signal_callback), this, NULL); dbus_g_proxy_add_signal (player, dbus_playing_changed.c_str(), G_TYPE_BOOLEAN, G_TYPE_INVALID); dbus_g_proxy_connect_signal (player, dbus_playing_changed.c_str(), G_CALLBACK(dbus_playing_changed_callback), this, NULL); dbus_playing_changed_callback(NULL, FALSE, this); } break; case MusicClient_Amarok: mode = 1; dbus_namespace = "org.kde.amarok"; dbus_player = dbus_shell = "org.gnome.Amarok.Player"; dbus_player_path = dbus_shell_path = "/Player"; dbus_uri_changed = "TrackChange"; dbus_playing_changed = "StatusChange"; dbus_get_current_song = dbus_get_song_properties = "GetMetadata"; bus = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); player = dbus_g_proxy_new_for_name (bus, dbus_namespace.c_str(), dbus_player_path.c_str(), dbus_player.c_str()); shell = dbus_g_proxy_new_for_name (bus, dbus_namespace.c_str(), dbus_shell_path.c_str(), dbus_shell.c_str()); dbus_g_proxy_add_signal (player, dbus_uri_changed.c_str(), G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal (player, dbus_uri_changed.c_str(), G_CALLBACK (dbus_uri_signal_callback), this, NULL); dbus_g_proxy_add_signal (player, dbus_playing_changed.c_str(), G_TYPE_BOOLEAN, G_TYPE_INVALID); dbus_g_proxy_connect_signal (player, dbus_playing_changed.c_str(), G_CALLBACK(dbus_playing_changed_callback), this, NULL); dbus_playing_changed_callback(NULL, FALSE, this); break; #endif default: break; } first_sent = false; } #ifdef HAVE_DBUS gchar * ManglerIntegration::get_current_uri_dbus () { DBusConnection *conn; DBusMessage *msg, *reply; DBusMessageIter iter; gchar *uri; msg = dbus_message_new_method_call (dbus_namespace.c_str(), dbus_player_path.c_str(), dbus_player.c_str(), dbus_get_current_song.c_str()); if (!msg) { return NULL; } dbus_message_set_auto_start (msg, FALSE); conn = (DBusConnection *) dbus_g_connection_get_connection (bus); reply = dbus_connection_send_with_reply_and_block(conn, msg, 5000, NULL); dbus_message_unref (msg); if (!reply) { return NULL; } if (dbus_message_get_type(reply) != DBUS_MESSAGE_TYPE_METHOD_RETURN) { dbus_message_unref (reply); return NULL; } dbus_message_iter_init(reply, &iter); if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) { dbus_message_unref(reply); return NULL; } dbus_message_iter_get_basic(&iter, &uri); dbus_message_unref(reply); return uri; } void dbus_playing_changed_callback (DBusGProxy *proxy, gboolean playing, gpointer data) { ManglerIntegration *integration = (ManglerIntegration *) data; gchar *uri; if (!playing) { uri = integration->get_current_uri_dbus(); if (uri && strlen(uri) != 0) { integration->set_current_status (1); dbus_uri_signal_callback(NULL, uri, integration); } } else { integration->set_current_status (2); } } void dbus_uri_signal_callback (DBusGProxy *proxy, const gchar *uri, gpointer data) { ManglerIntegration *integration = (ManglerIntegration *) data; GValue *value; GHashTable *table = NULL; g_return_if_fail (uri != NULL); if (!dbus_g_proxy_call(integration->get_shell(), integration->dbus_get_song_properties.c_str(), NULL, G_TYPE_STRING, uri, G_TYPE_INVALID, dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), &table, G_TYPE_INVALID)) { return; } value = (GValue *) g_hash_table_lookup(table, "artist"); if (value != NULL && G_VALUE_HOLDS_STRING(value)) { integration->artist = g_value_get_string(value); } value = (GValue *) g_hash_table_lookup(table, "album"); if (value != NULL && G_VALUE_HOLDS_STRING(value)) { integration->album = g_value_get_string(value); } value = (GValue *) g_hash_table_lookup(table, "title"); if (value != NULL && G_VALUE_HOLDS_STRING(value)) { integration->title = g_value_get_string(value); } g_hash_table_destroy(table); return; } #endif Glib::ustring ManglerIntegration::format () const { std::ostringstream os; int _state = (int) current_status; Glib::ustring formatted_text (""); if (_state == 0 || _state == 1) { return formatted_text; } // os << "Stopped" << ": "; // if (_state == 1) // os << "Paused" << ": "; os << artist << " - " << title; formatted_text = os.str(); return formatted_text; } ManglerIntegration::~ManglerIntegration() { #ifdef HAVE_LIBMPDCLIENT if (mpd_connection != NULL) { mpd_connection_free (mpd_connection); } #endif } bool ManglerIntegration::first () { if (!first_sent) { first_sent = true; return false; } return true; }