Skip to content

Commit

Permalink
mpris2: Implement volume control.
Browse files Browse the repository at this point in the history
  • Loading branch information
jlindgren90 committed May 3, 2012
1 parent 7c7710d commit ae1f9c2
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 27 deletions.
2 changes: 1 addition & 1 deletion src/mpris2/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR}

CPPFLAGS += -I../.. ${GLIB_CFLAGS} ${GIO_UNIX_CFLAGS}
CFLAGS += ${PLUGIN_CFLAGS}
LIBS += ${GLIB_LIBS} ${GIO_UNIX_LIBS}
LIBS += -lm ${GLIB_LIBS} ${GIO_UNIX_LIBS}
1 change: 1 addition & 0 deletions src/mpris2/mpris2-player.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<property name="Metadata" type="a{sv}" access="read"/>
<property name="PlaybackStatus" type="s" access="read"/>
<property name="Position" type="x" access="read"/>
<property name="Volume" type="d" access="readwrite"/>
<method name="Next"/>
<method name="Pause"/>
<method name="Play"/>
Expand Down
97 changes: 91 additions & 6 deletions src/mpris2/object-player.c
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,19 @@ static const _ExtendedGDBusPropertyInfo _mpris_media_player2_player_property_inf
FALSE
};

static const _ExtendedGDBusPropertyInfo _mpris_media_player2_player_property_info_volume =
{
{
-1,
"Volume",
"d",
G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE,
NULL
},
"volume",
FALSE
};

static const _ExtendedGDBusPropertyInfo * const _mpris_media_player2_player_property_info_pointers[] =
{
&_mpris_media_player2_player_property_info_can_control,
Expand All @@ -482,6 +495,7 @@ static const _ExtendedGDBusPropertyInfo * const _mpris_media_player2_player_prop
&_mpris_media_player2_player_property_info_metadata,
&_mpris_media_player2_player_property_info_playback_status,
&_mpris_media_player2_player_property_info_position,
&_mpris_media_player2_player_property_info_volume,
NULL
};

Expand Down Expand Up @@ -534,6 +548,7 @@ mpris_media_player2_player_override_properties (GObjectClass *klass, guint prope
g_object_class_override_property (klass, property_id_begin++, "metadata");
g_object_class_override_property (klass, property_id_begin++, "playback-status");
g_object_class_override_property (klass, property_id_begin++, "position");
g_object_class_override_property (klass, property_id_begin++, "volume");
return property_id_begin - 1;
}

Expand Down Expand Up @@ -565,6 +580,7 @@ mpris_media_player2_player_override_properties (GObjectClass *klass, guint prope
* @get_metadata: Getter for the #MprisMediaPlayer2Player:metadata property.
* @get_playback_status: Getter for the #MprisMediaPlayer2Player:playback-status property.
* @get_position: Getter for the #MprisMediaPlayer2Player:position property.
* @get_volume: Getter for the #MprisMediaPlayer2Player:volume property.
* @seeked: Handler for the #MprisMediaPlayer2Player::seeked signal.
*
* Virtual table for the D-Bus interface <link linkend="gdbus-interface-org-mpris-MediaPlayer2-Player.top_of_page">org.mpris.MediaPlayer2.Player</link>.
Expand Down Expand Up @@ -855,6 +871,15 @@ mpris_media_player2_player_default_init (MprisMediaPlayer2PlayerIface *iface)
*/
g_object_interface_install_property (iface,
g_param_spec_int64 ("position", "Position", "Position", G_MININT64, G_MAXINT64, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
* MprisMediaPlayer2Player:volume:
*
* Represents the D-Bus property <link linkend="gdbus-property-org-mpris-MediaPlayer2-Player.Volume">"Volume"</link>.
*
* Since the D-Bus property for this #GObject property is both readable and writable, it is meaningful to both read from it and write to it on both the service- and client-side.
*/
g_object_interface_install_property (iface,
g_param_spec_double ("volume", "Volume", "Volume", -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}

typedef MprisMediaPlayer2PlayerIface MprisMediaPlayer2PlayerInterface;
Expand Down Expand Up @@ -1179,6 +1204,37 @@ mpris_media_player2_player_set_position (MprisMediaPlayer2Player *object, gint64
g_object_set (G_OBJECT (object), "position", value, NULL);
}

/**
* mpris_media_player2_player_get_volume: (skip)
* @object: A #MprisMediaPlayer2Player.
*
* Gets the value of the <link linkend="gdbus-property-org-mpris-MediaPlayer2-Player.Volume">"Volume"</link> D-Bus property.
*
* Since this D-Bus property is both readable and writable, it is meaningful to use this function on both the client- and service-side.
*
* Returns: The property value.
*/
gdouble
mpris_media_player2_player_get_volume (MprisMediaPlayer2Player *object)
{
return MPRIS_MEDIA_PLAYER2_PLAYER_GET_IFACE (object)->get_volume (object);
}

/**
* mpris_media_player2_player_set_volume: (skip)
* @object: A #MprisMediaPlayer2Player.
* @value: The value to set.
*
* Sets the <link linkend="gdbus-property-org-mpris-MediaPlayer2-Player.Volume">"Volume"</link> D-Bus property to @value.
*
* Since this D-Bus property is both readable and writable, it is meaningful to use this function on both the client- and service-side.
*/
void
mpris_media_player2_player_set_volume (MprisMediaPlayer2Player *object, gdouble value)
{
g_object_set (G_OBJECT (object), "volume", value, NULL);
}

/**
* mpris_media_player2_player_emit_seeked:
* @object: A #MprisMediaPlayer2Player.
Expand Down Expand Up @@ -2133,7 +2189,7 @@ mpris_media_player2_player_proxy_get_property (GObject *object,
{
const _ExtendedGDBusPropertyInfo *info;
GVariant *variant;
g_assert (prop_id != 0 && prop_id - 1 < 9);
g_assert (prop_id != 0 && prop_id - 1 < 10);
info = _mpris_media_player2_player_property_info_pointers[prop_id - 1];
variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (object), info->parent_struct.name);
if (info->use_gvariant)
Expand Down Expand Up @@ -2174,7 +2230,7 @@ mpris_media_player2_player_proxy_set_property (GObject *object,
{
const _ExtendedGDBusPropertyInfo *info;
GVariant *variant;
g_assert (prop_id != 0 && prop_id - 1 < 9);
g_assert (prop_id != 0 && prop_id - 1 < 10);
info = _mpris_media_player2_player_property_info_pointers[prop_id - 1];
variant = g_dbus_gvalue_to_gvariant (value, G_VARIANT_TYPE (info->parent_struct.signature));
g_dbus_proxy_call (G_DBUS_PROXY (object),
Expand Down Expand Up @@ -2389,6 +2445,21 @@ mpris_media_player2_player_proxy_get_position (MprisMediaPlayer2Player *object)
return value;
}

static gdouble
mpris_media_player2_player_proxy_get_volume (MprisMediaPlayer2Player *object)
{
MprisMediaPlayer2PlayerProxy *proxy = MPRIS_MEDIA_PLAYER2_PLAYER_PROXY (object);
GVariant *variant;
gdouble value = 0;
variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Volume");
if (variant != NULL)
{
value = g_variant_get_double (variant);
g_variant_unref (variant);
}
return value;
}

static void
mpris_media_player2_player_proxy_init (MprisMediaPlayer2PlayerProxy *proxy)
{
Expand Down Expand Up @@ -2429,6 +2500,7 @@ mpris_media_player2_player_proxy_iface_init (MprisMediaPlayer2PlayerIface *iface
iface->get_metadata = mpris_media_player2_player_proxy_get_metadata;
iface->get_playback_status = mpris_media_player2_player_proxy_get_playback_status;
iface->get_position = mpris_media_player2_player_proxy_get_position;
iface->get_volume = mpris_media_player2_player_proxy_get_volume;
}

/**
Expand Down Expand Up @@ -2871,7 +2943,7 @@ mpris_media_player2_player_skeleton_finalize (GObject *object)
{
MprisMediaPlayer2PlayerSkeleton *skeleton = MPRIS_MEDIA_PLAYER2_PLAYER_SKELETON (object);
guint n;
for (n = 0; n < 9; n++)
for (n = 0; n < 10; n++)
g_value_unset (&skeleton->priv->properties[n]);
g_free (skeleton->priv->properties);
g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free);
Expand All @@ -2889,7 +2961,7 @@ mpris_media_player2_player_skeleton_get_property (GObject *object,
GParamSpec *pspec)
{
MprisMediaPlayer2PlayerSkeleton *skeleton = MPRIS_MEDIA_PLAYER2_PLAYER_SKELETON (object);
g_assert (prop_id != 0 && prop_id - 1 < 9);
g_assert (prop_id != 0 && prop_id - 1 < 10);
g_mutex_lock (&skeleton->priv->lock);
g_value_copy (&skeleton->priv->properties[prop_id - 1], value);
g_mutex_unlock (&skeleton->priv->lock);
Expand Down Expand Up @@ -3006,7 +3078,7 @@ mpris_media_player2_player_skeleton_set_property (GObject *object,
GParamSpec *pspec)
{
MprisMediaPlayer2PlayerSkeleton *skeleton = MPRIS_MEDIA_PLAYER2_PLAYER_SKELETON (object);
g_assert (prop_id != 0 && prop_id - 1 < 9);
g_assert (prop_id != 0 && prop_id - 1 < 10);
g_mutex_lock (&skeleton->priv->lock);
g_object_freeze_notify (object);
if (!_g_value_equal (value, &skeleton->priv->properties[prop_id - 1]))
Expand All @@ -3026,7 +3098,7 @@ mpris_media_player2_player_skeleton_init (MprisMediaPlayer2PlayerSkeleton *skele
skeleton->priv = G_TYPE_INSTANCE_GET_PRIVATE (skeleton, MPRIS_TYPE_MEDIA_PLAYER2_PLAYER_SKELETON, MprisMediaPlayer2PlayerSkeletonPrivate);
g_mutex_init (&skeleton->priv->lock);
skeleton->priv->context = g_main_context_ref_thread_default ();
skeleton->priv->properties = g_new0 (GValue, 9);
skeleton->priv->properties = g_new0 (GValue, 10);
g_value_init (&skeleton->priv->properties[0], G_TYPE_BOOLEAN);
g_value_init (&skeleton->priv->properties[1], G_TYPE_BOOLEAN);
g_value_init (&skeleton->priv->properties[2], G_TYPE_BOOLEAN);
Expand All @@ -3036,6 +3108,7 @@ mpris_media_player2_player_skeleton_init (MprisMediaPlayer2PlayerSkeleton *skele
g_value_init (&skeleton->priv->properties[6], G_TYPE_VARIANT);
g_value_init (&skeleton->priv->properties[7], G_TYPE_STRING);
g_value_init (&skeleton->priv->properties[8], G_TYPE_INT64);
g_value_init (&skeleton->priv->properties[9], G_TYPE_DOUBLE);
}

static gboolean
Expand Down Expand Up @@ -3137,6 +3210,17 @@ mpris_media_player2_player_skeleton_get_position (MprisMediaPlayer2Player *objec
return value;
}

static gdouble
mpris_media_player2_player_skeleton_get_volume (MprisMediaPlayer2Player *object)
{
MprisMediaPlayer2PlayerSkeleton *skeleton = MPRIS_MEDIA_PLAYER2_PLAYER_SKELETON (object);
gdouble value;
g_mutex_lock (&skeleton->priv->lock);
value = g_value_get_double (&(skeleton->priv->properties[9]));
g_mutex_unlock (&skeleton->priv->lock);
return value;
}

static void
mpris_media_player2_player_skeleton_class_init (MprisMediaPlayer2PlayerSkeletonClass *klass)
{
Expand Down Expand Up @@ -3174,6 +3258,7 @@ mpris_media_player2_player_skeleton_iface_init (MprisMediaPlayer2PlayerIface *if
iface->get_metadata = mpris_media_player2_player_skeleton_get_metadata;
iface->get_playback_status = mpris_media_player2_player_skeleton_get_playback_status;
iface->get_position = mpris_media_player2_player_skeleton_get_position;
iface->get_volume = mpris_media_player2_player_skeleton_get_volume;
}

/**
Expand Down
5 changes: 5 additions & 0 deletions src/mpris2/object-player.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ struct _MprisMediaPlayer2PlayerIface

gint64 (*get_position) (MprisMediaPlayer2Player *object);

gdouble (*get_volume) (MprisMediaPlayer2Player *object);

void (*seeked) (
MprisMediaPlayer2Player *object,
gint64 arg_Position);
Expand Down Expand Up @@ -304,6 +306,9 @@ void mpris_media_player2_player_set_playback_status (MprisMediaPlayer2Player *ob
gint64 mpris_media_player2_player_get_position (MprisMediaPlayer2Player *object);
void mpris_media_player2_player_set_position (MprisMediaPlayer2Player *object, gint64 value);

gdouble mpris_media_player2_player_get_volume (MprisMediaPlayer2Player *object);
void mpris_media_player2_player_set_volume (MprisMediaPlayer2Player *object, gdouble value);


/* ---- */

Expand Down
43 changes: 23 additions & 20 deletions src/mpris2/plugin.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* the use of this software.
*/

#include <math.h>
#include <stdint.h>
#include <stdio.h>

Expand All @@ -35,7 +36,7 @@ static char * last_title, * last_artist, * last_album, * last_file;
static int last_length;
static const char * image_file;
static GVariantType * metadata_type;
static int update_position_source;
static int update_timer;

static bool_t quit_cb (MprisMediaPlayer2 * object, GDBusMethodInvocation * call,
void * unused)
Expand Down Expand Up @@ -151,14 +152,26 @@ static void update_metadata (void * data, GObject * object)
g_object_set (object, "metadata", array, NULL);
}

static bool_t update_position (GObject * object)
static void volume_changed (GObject * object)
{
double vol;
g_object_get (object, "volume", & vol, NULL);
aud_drct_set_volume_main (round (vol * 100));
}

static bool_t update (GObject * object)
{
int64_t pos = 0;
int vol = 0;

if (aud_drct_get_playing () && aud_drct_get_ready ())
pos = (int64_t) aud_drct_get_time () * 1000;

g_object_set (object, "position", pos, NULL);
aud_drct_get_volume_main (& vol);

g_signal_handlers_block_by_func (object, (void *) volume_changed, NULL);
g_object_set (object, "position", pos, "volume", (double) vol / 100, NULL);
g_signal_handlers_unblock_by_func (object, (void *) volume_changed, NULL);
return TRUE;
}

Expand All @@ -167,25 +180,12 @@ static void update_playback_status (void * data, GObject * object)
const char * status;

if (aud_drct_get_playing ())
{
status = aud_drct_get_paused () ? "Paused" : "Playing";

if (! update_position_source)
update_position_source = g_timeout_add (250, (GSourceFunc) update_position, object);
}
else
{
status = "Stopped";

if (update_position_source)
{
g_source_remove (update_position_source);
update_position_source = 0;
}
}

g_object_set (object, "playback-status", status, NULL);
update_position (object);
update (object);
}

static void emit_seek (void * data, GObject * object)
Expand Down Expand Up @@ -285,10 +285,10 @@ void mpris2_cleanup (void)
hook_dissociate ("playback ready", (HookFunction) emit_seek);
hook_dissociate ("playback seek", (HookFunction) emit_seek);

if (update_position_source)
if (update_timer)
{
g_source_remove (update_position_source);
update_position_source = 0;
g_source_remove (update_timer);
update_timer = 0;
}

g_dbus_connection_close_sync (bus, NULL, NULL);
Expand Down Expand Up @@ -353,6 +353,7 @@ bool_t mpris2_init (void)
"can-seek", TRUE,
NULL);

update_timer = g_timeout_add (250, (GSourceFunc) update, object_player);
update_playback_status (NULL, object_player);

if (aud_drct_get_playing () && aud_drct_get_ready ())
Expand All @@ -379,6 +380,8 @@ bool_t mpris2_init (void)
g_signal_connect (object_player, "handle-set-position", (GCallback) set_position_cb, NULL);
g_signal_connect (object_player, "handle-stop", (GCallback) stop_cb, NULL);

g_signal_connect (object_player, "notify::volume", (GCallback) volume_changed, NULL);

if (! g_dbus_interface_skeleton_export ((GDBusInterfaceSkeleton *)
object_core, bus, "/org/mpris/MediaPlayer2", & error) ||
! g_dbus_interface_skeleton_export ((GDBusInterfaceSkeleton *)
Expand Down

0 comments on commit ae1f9c2

Please sign in to comment.