diff --git a/audio/control.c b/audio/control.c
index cb9dd76..7fe4af5 100644
--- a/audio/control.c
+++ b/audio/control.c
};
struct media_info {
+ char *title;
+ char *artist;
+ char *album;
+ char *genre;
+ uint32_t ntracks;
+ uint32_t track;
+ uint32_t track_len;
uint32_t elapsed;
};
mp->settings[attr] = val;
}
+static void mp_set_media_attributes(struct control *control,
+ struct media_info *mi)
+{
+ struct media_player *mp = control->mp;
+
+ g_free(mp->mi.title);
+ mp->mi.title = g_strdup(mi->title);
+
+ g_free(mp->mi.artist);
+ mp->mi.artist = g_strdup(mi->artist);
+
+ g_free(mp->mi.album);
+ mp->mi.album = g_strdup(mi->album);
+
+ g_free(mp->mi.genre);
+ mp->mi.genre = g_strdup(mi->genre);
+
+ mp->mi.ntracks = mi->ntracks;
+ mp->mi.track = mi->track;
+ mp->mi.track_len = mi->track_len;
+
+ /*
+ * elapsed is special. Whenever the track changes, we reset it to 0,
+ * so client doesn't have to make another call to change_playback
+ */
+ mp->mi.elapsed = 0;
+ g_timer_start(mp->timer);
+
+ DBG("Track changed:\n\ttitle: %s\n\tartist: %s\n\talbum: %s\n"
+ "\tgenre: %s\n\tNumber of tracks: %u\n"
+ "\tTrack number: %u\n\tTrack duration: %u",
+ mi->title, mi->artist, mi->album, mi->genre,
+ mi->ntracks, mi->track, mi->track_len);
+}
+
/* handle vendordep pdu inside an avctp packet */
static int handle_vendordep_pdu(struct control *control,
struct avrcp_header *avrcp,
DBG("AVRCP: uinput initialized for %s", address);
}
+static void media_info_init(struct media_info *mi)
+{
+ memset(mi, 0, sizeof(*mi));
+
+ /*
+ * As per section 5.4.1 of AVRCP 1.3 spec, return 0xFFFFFFFF if TG
+ * does not support these attributes (i.e. they were never set via
+ * D-Bus)
+ */
+ mi->track_len = 0xFFFFFFFF;
+ mi->elapsed = 0xFFFFFFFF;
+}
+
static void avctp_connect_cb(GIOChannel *chan, GError *err, gpointer data)
{
struct control *control = data;
return dbus_message_new_method_return(msg);
}
+static gboolean media_info_parse(DBusMessageIter *iter, struct media_info *mi)
+{
+ DBusMessageIter dict;
+ DBusMessageIter var;
+ int ctype;
+
+ ctype = dbus_message_iter_get_arg_type(iter);
+ if (ctype != DBUS_TYPE_ARRAY)
+ return FALSE;
+
+ media_info_init(mi);
+ dbus_message_iter_recurse(iter, &dict);
+
+ while ((ctype = dbus_message_iter_get_arg_type(&dict)) !=
+ DBUS_TYPE_INVALID) {
+ DBusMessageIter entry;
+ const char *key;
+
+ if (ctype != DBUS_TYPE_DICT_ENTRY)
+ return FALSE;
+
+ dbus_message_iter_recurse(&dict, &entry);
+ if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
+ return FALSE;
+
+ dbus_message_iter_get_basic(&entry, &key);
+ dbus_message_iter_next(&entry);
+
+ if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
+ return FALSE;
+
+ dbus_message_iter_recurse(&entry, &var);
+
+ if (!strcmp(key, "Title")) {
+ if (dbus_message_iter_get_arg_type(&var) !=
+ DBUS_TYPE_STRING)
+ return FALSE;
+
+ dbus_message_iter_get_basic(&var, &mi->title);
+ } else if (!strcmp(key, "Artist")) {
+ if (dbus_message_iter_get_arg_type(&var) !=
+ DBUS_TYPE_STRING)
+ return FALSE;
+
+ dbus_message_iter_get_basic(&var, &mi->artist);
+ } else if (!strcmp(key, "Album")) {
+ if (dbus_message_iter_get_arg_type(&var) !=
+ DBUS_TYPE_STRING)
+ return FALSE;
+
+ dbus_message_iter_get_basic(&var, &mi->album);
+ } else if (!strcmp(key, "Genre")) {
+ if (dbus_message_iter_get_arg_type(&var) !=
+ DBUS_TYPE_STRING)
+ return FALSE;
+
+ dbus_message_iter_get_basic(&var, &mi->genre);
+ } else if (!strcmp(key, "NumberOfTracks")) {
+ if (dbus_message_iter_get_arg_type(&var) !=
+ DBUS_TYPE_UINT32)
+ return FALSE;
+
+ dbus_message_iter_get_basic(&var, &mi->ntracks);
+ } else if (!strcmp(key, "TrackNumber")) {
+ if (dbus_message_iter_get_arg_type(&var) !=
+ DBUS_TYPE_UINT32)
+ return FALSE;
+
+ dbus_message_iter_get_basic(&var, &mi->track);
+ } else if (!strcmp(key, "TrackDuration")) {
+ if (dbus_message_iter_get_arg_type(&var) !=
+ DBUS_TYPE_UINT32)
+ return FALSE;
+
+ dbus_message_iter_get_basic(&var, &mi->track_len);
+ } else {
+ return FALSE;
+ }
+
+ dbus_message_iter_next(&dict);
+ }
+
+ if (mi->title == NULL)
+ return FALSE;
+
+ return TRUE;
+}
+
+static DBusMessage *mp_change_track(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
+ struct audio_device *device = data;
+ struct control *control = device->control;
+ DBusMessageIter iter;
+ struct media_info mi;
+
+
+ dbus_message_iter_init(msg, &iter);
+ if (!media_info_parse(&iter, &mi))
+ return btd_error_invalid_args(msg);
+
+ mp_set_media_attributes(control, &mi);
+
+ return dbus_message_new_method_return(msg);
+}
+
static GDBusMethodTable mp_methods[] = {
{ "SetProperty", "sv", "", mp_set_property },
{ "ChangePlayback", "su", "", mp_change_playback },
+ { "ChangeTrack", "a{sv}", "", mp_change_track },
{ }
};
MEDIA_PLAYER_INTERFACE, dev->path);
mp->timer = g_timer_new();
+ media_info_init(&mp->mi);
control->mp = mp;
}