break;
case 'cang': // genre
t = sp - item_size;
- if ((metadata_store.genre == NULL) || (strncmp(metadata_store.genre, t, item_size) != 0)) {
+ if ((metadata_store.genre == NULL) ||
+ (strncmp(metadata_store.genre, t, item_size) != 0)) {
if (metadata_store.genre)
free(metadata_store.genre);
metadata_store.genre = strndup(t, item_size);
case 'canp': // nowplaying 4 ids: dbid, plid, playlistItem, itemid (from mellowware --
// see reference above)
t = sp - item_size;
- if (memcmp(metadata_store.item_composite_id, t, sizeof(metadata_store.item_composite_id)) != 0) {
- memcpy(metadata_store.item_composite_id, t, sizeof(metadata_store.item_composite_id));
+ if (memcmp(metadata_store.item_composite_id, t,
+ sizeof(metadata_store.item_composite_id)) != 0) {
+ memcpy(metadata_store.item_composite_id, t,
+ sizeof(metadata_store.item_composite_id));
char st[33];
char *pt = st;
metadata_store.changed = 1;
}
break;
+ case 'astm':
+ t = sp - item_size;
+ r = ntohl(*(int32_t *)(t));
+ metadata_store.songtime_in_milliseconds = ntohl(*(uint32_t *)(t));
+ break;
+
/*
case 'mstt':
case 'cant':
case 'cmmk':
case 'caas':
case 'caar':
- case 'astm':
t = sp - item_size;
r = ntohl(*(int32_t *)(t));
printf(" %d", r);
}
// printf("\n");
}
+
// now, if the metadata is changed, send a signal
+ run_metadata_watchers();
} else {
printf("Status Update not found.\n");
response = NULL;
}
*/
- sleep(2);
+ sleep(2);
}
debug(1, "DACP monitor thread exiting.");
pthread_exit(NULL);
* Basically, if you need to store metadata
* (e.g. for use with the dbus interfaces),
* then you need a metadata hub,
- * where everything is stored
+ * where everything is stored
* This file is part of Shairport Sync.
* Copyright (c) Mike Brady 2017
* All rights reserved.
debug(1, "Metadata bundle initialisation.");
memset(&metadata_store, 0, sizeof(metadata_store));
}
+
+void add_metadata_watcher(metadata_watcher fn, void *userdata) {
+ int i;
+ for (i = 0; i < number_of_watchers; i++) {
+ if (metadata_store.watchers[i] == NULL) {
+ metadata_store.watchers[i] = fn;
+ metadata_store.watchers_data[i] = userdata;
+ debug(1, "Added a metadata watcher into slot %d", i);
+ break;
+ }
+ }
+}
+
+void run_metadata_watchers(void) {
+ int i;
+ for (i = 0; i < number_of_watchers; i++) {
+ if (metadata_store.watchers[i]) {
+ metadata_store.watchers[i](&metadata_store, metadata_store.watchers_data[i]);
+ }
+ }
+}
#include "dacp.h"
+#include "metadata_hub.h"
#include "mpris-service.h"
+void mpris_metadata_watcher(struct metadata_bundle *argc, void *userdata) {
+ debug(1, "MPRIS metadata watcher called");
+ char response[100];
+ switch (argc->repeat_status) {
+ case RS_NONE:
+ strcpy(response, "None");
+ break;
+ case RS_SINGLE:
+ strcpy(response, "Track");
+ break;
+ case RS_ALL:
+ strcpy(response, "Playlist");
+ break;
+ }
+
+ // debug(1,"Set loop status to \"%s\"",response);
+ media_player2_player_set_loop_status(mprisPlayerPlayerSkeleton, response);
+
+ GVariantBuilder *dict_builder, *aa;
+ GVariant *trackname, *albumname, *trackid, *tracklength;
+
+ // Build the Track ID from the 16-byte item_composite_id in hex prefixed by
+ // /org/gnome/ShairportSync
+
+ char st[33];
+ char *pt = st;
+ int it;
+ for (it = 0; it < 16; it++) {
+ sprintf(pt, "%02X", argc->item_composite_id[it]);
+ pt += 2;
+ }
+ *pt = 0;
+ debug(1, "Item composite ID set to 0x%s.", st);
+
+ char trackidstring[1024];
+ sprintf(trackidstring, "/org/gnome/ShairportSync/%s", st);
+
+ trackid = g_variant_new("o", trackidstring);
+
+ // Make up the track name and album name
+ trackname = g_variant_new("s", argc->track_name);
+ albumname = g_variant_new("s", argc->album_name);
+
+ // Make up the track length in microseconds as an int64
+
+ uint64_t track_length_in_microseconds = argc->songtime_in_milliseconds;
+
+ track_length_in_microseconds *= 1000; // to micorseconds in 64-bit precision
+
+ // Make up the track name and album name
+ tracklength = g_variant_new("x", track_length_in_microseconds);
+
+ /* Build the artists array */
+ // debug(1,"Build artists");
+ aa = g_variant_builder_new(G_VARIANT_TYPE("as"));
+ g_variant_builder_add(aa, "s", argc->artist_name);
+ GVariant *artists = g_variant_builder_end(aa);
+ g_variant_builder_unref(aa);
+
+ /* Build the genre array */
+ // debug(1,"Build genre");
+ aa = g_variant_builder_new(G_VARIANT_TYPE("as"));
+ g_variant_builder_add(aa, "s", argc->genre);
+ GVariant *genres = g_variant_builder_end(aa);
+ g_variant_builder_unref(aa);
+
+ /* Build the metadata array */
+ // debug(1,"Build metadata");
+ dict_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+ g_variant_builder_add(dict_builder, "{sv}", "xesam:title", trackname);
+ g_variant_builder_add(dict_builder, "{sv}", "xesam:album", albumname);
+ g_variant_builder_add(dict_builder, "{sv}", "xesam:artist", artists);
+ g_variant_builder_add(dict_builder, "{sv}", "xesam:genre", genres);
+ g_variant_builder_add(dict_builder, "{sv}", "xesam:trackid", trackid);
+ g_variant_builder_add(dict_builder, "{sv}", "xesam:length", tracklength);
+ GVariant *dict = g_variant_builder_end(dict_builder);
+ g_variant_builder_unref(dict_builder);
+
+ media_player2_player_set_metadata(mprisPlayerPlayerSkeleton, dict);
+}
+
static gboolean on_handle_next(MediaPlayer2Player *skeleton, GDBusMethodInvocation *invocation,
gpointer user_data) {
send_simple_dacp_command("nextitem");
media_player2_set_supported_uri_schemes(mprisPlayerSkeleton, empty_string_array);
media_player2_set_supported_mime_types(mprisPlayerSkeleton, empty_string_array);
- media_player2_player_set_playback_status(mprisPlayerPlayerSkeleton, "stop");
- media_player2_player_set_loop_status(mprisPlayerPlayerSkeleton, "off");
+ media_player2_player_set_playback_status(mprisPlayerPlayerSkeleton, "Stopped");
+ media_player2_player_set_loop_status(mprisPlayerPlayerSkeleton, "None");
media_player2_player_set_volume(mprisPlayerPlayerSkeleton, 0.5);
media_player2_player_set_minimum_rate(mprisPlayerPlayerSkeleton, 1.0);
media_player2_player_set_maximum_rate(mprisPlayerPlayerSkeleton, 1.0);
g_signal_connect(mprisPlayerPlayerSkeleton, "handle-previous", G_CALLBACK(on_handle_previous),
NULL);
+ add_metadata_watcher(mpris_metadata_watcher, NULL);
+
debug(1, "Shairport Sync D-BUS service started on interface \"%s\".", name);
debug(1, "MPRIS service started on interface \"%s\".", name);