|
Packit |
9ca0cf |
/*
|
|
Packit |
9ca0cf |
* Copyright © 2013 Intel Corporation.
|
|
Packit |
9ca0cf |
*
|
|
Packit |
9ca0cf |
* This program is free software; you can redistribute it and/or modify it
|
|
Packit |
9ca0cf |
* under the terms and conditions of the GNU Lesser General Public License,
|
|
Packit |
9ca0cf |
* version 2.1, as published by the Free Software Foundation.
|
|
Packit |
9ca0cf |
*
|
|
Packit |
9ca0cf |
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
|
Packit |
9ca0cf |
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
Packit |
9ca0cf |
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
Packit |
9ca0cf |
* details.
|
|
Packit |
9ca0cf |
*
|
|
Packit |
9ca0cf |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit |
9ca0cf |
* along with this program; if not, see <http://www.gnu.org/licenses>
|
|
Packit |
9ca0cf |
*
|
|
Packit |
9ca0cf |
* Author: Michael Wood <michael.g.wood@intel.com>
|
|
Packit |
9ca0cf |
*/
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
#include "mpris-controller.h"
|
|
Packit |
9ca0cf |
#include "bus-watch-namespace.h"
|
|
Packit |
9ca0cf |
#include <gio/gio.h>
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
G_DEFINE_TYPE (MprisController, mpris_controller, G_TYPE_OBJECT)
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
#define CONTROLLER_PRIVATE(o) \
|
|
Packit |
9ca0cf |
(G_TYPE_INSTANCE_GET_PRIVATE ((o), MPRIS_TYPE_CONTROLLER, MprisControllerPrivate))
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
enum {
|
|
Packit |
9ca0cf |
PROP_0,
|
|
Packit |
9ca0cf |
PROP_HAS_ACTIVE_PLAYER
|
|
Packit |
9ca0cf |
};
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
struct _MprisControllerPrivate
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
GCancellable *cancellable;
|
|
Packit |
9ca0cf |
GDBusProxy *mpris_client_proxy;
|
|
Packit |
9ca0cf |
guint namespace_watcher_id;
|
|
Packit |
9ca0cf |
GSList *other_players;
|
|
Packit |
9ca0cf |
gboolean connecting;
|
|
Packit |
9ca0cf |
};
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
mpris_controller_dispose (GObject *object)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
MprisControllerPrivate *priv = MPRIS_CONTROLLER (object)->priv;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_clear_object (&priv->cancellable);
|
|
Packit |
9ca0cf |
g_clear_object (&priv->mpris_client_proxy);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (priv->namespace_watcher_id)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
bus_unwatch_namespace (priv->namespace_watcher_id);
|
|
Packit |
9ca0cf |
priv->namespace_watcher_id = 0;
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (priv->other_players)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
g_slist_free_full (priv->other_players, g_free);
|
|
Packit |
9ca0cf |
priv->other_players = NULL;
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
G_OBJECT_CLASS (mpris_controller_parent_class)->dispose (object);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
mpris_proxy_call_done (GObject *object,
|
|
Packit |
9ca0cf |
GAsyncResult *res,
|
|
Packit |
9ca0cf |
gpointer user_data)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
GError *error = NULL;
|
|
Packit |
9ca0cf |
GVariant *ret;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (!(ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (object), res, &error)))
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
Packit |
9ca0cf |
g_warning ("Error calling method %s", error->message);
|
|
Packit |
9ca0cf |
g_clear_error (&error);
|
|
Packit |
9ca0cf |
return;
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
g_variant_unref (ret);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
gboolean
|
|
Packit |
9ca0cf |
mpris_controller_key (MprisController *self, const gchar *key)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
MprisControllerPrivate *priv = MPRIS_CONTROLLER (self)->priv;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (!priv->mpris_client_proxy)
|
|
Packit |
9ca0cf |
return FALSE;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (g_strcmp0 (key, "Play") == 0)
|
|
Packit |
9ca0cf |
key = "PlayPause";
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_debug ("calling %s over dbus to mpris client %s",
|
|
Packit |
9ca0cf |
key, g_dbus_proxy_get_name (priv->mpris_client_proxy));
|
|
Packit |
9ca0cf |
g_dbus_proxy_call (priv->mpris_client_proxy,
|
|
Packit |
9ca0cf |
key, NULL, 0, -1, priv->cancellable,
|
|
Packit |
9ca0cf |
mpris_proxy_call_done,
|
|
Packit |
9ca0cf |
NULL);
|
|
Packit |
9ca0cf |
return TRUE;
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
mpris_proxy_ready_cb (GObject *object,
|
|
Packit |
9ca0cf |
GAsyncResult *res,
|
|
Packit |
9ca0cf |
gpointer user_data)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
MprisControllerPrivate *priv;
|
|
Packit |
9ca0cf |
GError *error = NULL;
|
|
Packit |
9ca0cf |
GDBusProxy *proxy;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (!proxy)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
Packit |
9ca0cf |
g_warning ("Error connecting to mpris interface %s", error->message);
|
|
Packit |
9ca0cf |
g_clear_error (&error);
|
|
Packit |
9ca0cf |
return;
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
priv = MPRIS_CONTROLLER (user_data)->priv;
|
|
Packit |
9ca0cf |
priv->mpris_client_proxy = proxy;
|
|
Packit |
9ca0cf |
priv->connecting = FALSE;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_object_notify (user_data, "has-active-player");
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
start_mpris_proxy (MprisController *self, const gchar *name)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
MprisControllerPrivate *priv = MPRIS_CONTROLLER (self)->priv;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_debug ("Creating proxy for for %s", name);
|
|
Packit |
9ca0cf |
g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
|
|
Packit |
9ca0cf |
0,
|
|
Packit |
9ca0cf |
NULL,
|
|
Packit |
9ca0cf |
name,
|
|
Packit |
9ca0cf |
"/org/mpris/MediaPlayer2",
|
|
Packit |
9ca0cf |
"org.mpris.MediaPlayer2.Player",
|
|
Packit |
9ca0cf |
priv->cancellable,
|
|
Packit |
9ca0cf |
mpris_proxy_ready_cb,
|
|
Packit |
9ca0cf |
self);
|
|
Packit |
9ca0cf |
priv->connecting = TRUE;
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
mpris_player_appeared (GDBusConnection *connection,
|
|
Packit |
9ca0cf |
const gchar *name,
|
|
Packit |
9ca0cf |
const gchar *name_owner,
|
|
Packit |
9ca0cf |
gpointer user_data)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
MprisController *self = user_data;
|
|
Packit |
9ca0cf |
MprisControllerPrivate *priv = MPRIS_CONTROLLER (self)->priv;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (priv->mpris_client_proxy == NULL && !priv->connecting)
|
|
Packit |
9ca0cf |
start_mpris_proxy (self, name);
|
|
Packit |
9ca0cf |
else
|
|
Packit |
9ca0cf |
self->priv->other_players = g_slist_prepend (self->priv->other_players, g_strdup (name));
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
mpris_player_vanished (GDBusConnection *connection,
|
|
Packit |
9ca0cf |
const gchar *name,
|
|
Packit |
9ca0cf |
gpointer user_data)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
MprisController *self = user_data;
|
|
Packit |
9ca0cf |
MprisControllerPrivate *priv = MPRIS_CONTROLLER (self)->priv;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
if (priv->mpris_client_proxy &&
|
|
Packit |
9ca0cf |
g_strcmp0 (name, g_dbus_proxy_get_name (priv->mpris_client_proxy)) == 0)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
g_clear_object (&priv->mpris_client_proxy);
|
|
Packit |
9ca0cf |
g_object_notify (user_data, "has-active-player");
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
/* take the next one if there's one */
|
|
Packit |
9ca0cf |
if (self->priv->other_players && !priv->connecting)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
GSList *first;
|
|
Packit |
9ca0cf |
gchar *name;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
first = self->priv->other_players;
|
|
Packit |
9ca0cf |
name = first->data;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
start_mpris_proxy (self, name);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
self->priv->other_players = self->priv->other_players->next;
|
|
Packit |
9ca0cf |
g_free (name);
|
|
Packit |
9ca0cf |
g_slist_free_1 (first);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
mpris_controller_constructed (GObject *object)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
MprisControllerPrivate *priv = MPRIS_CONTROLLER (object)->priv;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
priv->namespace_watcher_id = bus_watch_namespace (G_BUS_TYPE_SESSION,
|
|
Packit |
9ca0cf |
"org.mpris.MediaPlayer2",
|
|
Packit |
9ca0cf |
mpris_player_appeared,
|
|
Packit |
9ca0cf |
mpris_player_vanished,
|
|
Packit |
9ca0cf |
MPRIS_CONTROLLER (object),
|
|
Packit |
9ca0cf |
NULL);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
mpris_controller_get_property (GObject *object,
|
|
Packit |
9ca0cf |
guint prop_id,
|
|
Packit |
9ca0cf |
GValue *value,
|
|
Packit |
9ca0cf |
GParamSpec *pspec)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
MprisController *self = MPRIS_CONTROLLER (object);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
switch (prop_id) {
|
|
Packit |
9ca0cf |
case PROP_HAS_ACTIVE_PLAYER:
|
|
Packit |
9ca0cf |
g_value_set_boolean (value,
|
|
Packit |
9ca0cf |
mpris_controller_get_has_active_player (self));
|
|
Packit |
9ca0cf |
break;
|
|
Packit |
9ca0cf |
default:
|
|
Packit |
9ca0cf |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
Packit |
9ca0cf |
break;
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
mpris_controller_class_init (MprisControllerClass *klass)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_type_class_add_private (klass, sizeof (MprisControllerPrivate));
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
object_class->constructed = mpris_controller_constructed;
|
|
Packit |
9ca0cf |
object_class->dispose = mpris_controller_dispose;
|
|
Packit |
9ca0cf |
object_class->get_property = mpris_controller_get_property;
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
g_object_class_install_property (object_class,
|
|
Packit |
9ca0cf |
PROP_HAS_ACTIVE_PLAYER,
|
|
Packit |
9ca0cf |
g_param_spec_boolean ("has-active-player",
|
|
Packit |
9ca0cf |
NULL,
|
|
Packit |
9ca0cf |
NULL,
|
|
Packit |
9ca0cf |
FALSE,
|
|
Packit |
9ca0cf |
G_PARAM_READABLE));
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
static void
|
|
Packit |
9ca0cf |
mpris_controller_init (MprisController *self)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
self->priv = CONTROLLER_PRIVATE (self);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
gboolean
|
|
Packit |
9ca0cf |
mpris_controller_get_has_active_player (MprisController *controller)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
g_return_val_if_fail (MPRIS_IS_CONTROLLER (controller), FALSE);
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
return (controller->priv->mpris_client_proxy != NULL);
|
|
Packit |
9ca0cf |
}
|
|
Packit |
9ca0cf |
|
|
Packit |
9ca0cf |
MprisController *
|
|
Packit |
9ca0cf |
mpris_controller_new (void)
|
|
Packit |
9ca0cf |
{
|
|
Packit |
9ca0cf |
return g_object_new (MPRIS_TYPE_CONTROLLER, NULL);
|
|
Packit |
9ca0cf |
}
|