Skip to content

Commit

Permalink
Squashed commit of the following:
Browse files Browse the repository at this point in the history
    Fix Issue #890 -- #890
    Recognise situation where a track has no artwork properly.
    Less likely to drop the 'availabile' property.
    Always output the full metadata whenever any part of it has changed.
    Metadata coming from dacp is now incorporated,
  • Loading branch information
mikebrady committed Aug 29, 2019
1 parent d846bc5 commit 86b6d7b
Show file tree
Hide file tree
Showing 7 changed files with 429 additions and 433 deletions.
36 changes: 36 additions & 0 deletions common.c
Original file line number Diff line number Diff line change
Expand Up @@ -1519,3 +1519,39 @@ int64_t generate_zero_frames(char *outp, size_t number_of_frames, enum sps_forma
}
return previous_random_number;
}

// This will check the incoming string "s" of length "len" with the existing NUL-terminated string "str" and update "flag" accordingly.

// Note: if the incoming string length is zero, then the a NULL is used; i.e. no zero-length strings are stored.

// If the strings are different, the str is free'd and replaced by a pointer
// to a newly strdup'd string and the flag is set
// If they are the same, the flag is cleared

int string_update_with_size(char **str, int *flag, char *s, size_t len) {
if (*str) {
if ((s) && (len)) {
if (strncmp(*str, s, len) != 0) {
free(*str);
*str = strndup(s, len);
*flag = 1;
} else {
*flag = 0;
}
} else {
// old string is non-NULL, new string is NULL or length 0
free(*str);
*str = NULL;
*flag = 1;
}
} else { // old string is NULL
if ((s) && (len)) {
*str = strndup(s, len);
*flag = 1;
} else {
// old string is NULL and new string is NULL or length 0
*flag = 0; // so no change
}
}
return *flag;
}
2 changes: 2 additions & 0 deletions common.h
Original file line number Diff line number Diff line change
Expand Up @@ -393,4 +393,6 @@ int64_t generate_zero_frames(char *outp, size_t number_of_frames, enum sps_forma

void malloc_cleanup(void *arg);

int string_update_with_size(char **str, int *flag, char *s, size_t len);

#endif // _COMMON_H
113 changes: 50 additions & 63 deletions dacp.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,10 @@ static void response_code(void *opaque, int code) {
}

static const struct http_funcs responseFuncs = {
response_realloc, response_body, response_header, response_code,
response_realloc,
response_body,
response_header,
response_code,
};

// static pthread_mutex_t dacp_conversation_lock = PTHREAD_MUTEX_INITIALIZER;
Expand Down Expand Up @@ -320,9 +323,10 @@ int dacp_send_command(const char *command, char **body, ssize_t *bodysize) {
// debug(1,"Sent command\"%s\" with a response body of size %d.",command,response.size);
// debug(1,"dacp_conversation_lock released.");
} else {
debug(3, "dacp_send_command: could not acquire a lock on the dacp transmit/receive section "
"when attempting to "
"send the command \"%s\". Possible timeout?",
debug(3,
"dacp_send_command: could not acquire a lock on the dacp transmit/receive section "
"when attempting to "
"send the command \"%s\". Possible timeout?",
command);
response.code = 494; // This client is already busy
}
Expand Down Expand Up @@ -419,8 +423,9 @@ void set_dacp_server_information(rtsp_conn_info *conn) {

void dacp_monitor_port_update_callback(char *dacp_id, uint16_t port) {
debug_mutex_lock(&dacp_server_information_lock, 500000, 2);
debug(3, "dacp_monitor_port_update_callback with Remote ID \"%s\", target ID \"%s\" and port "
"number %d.",
debug(3,
"dacp_monitor_port_update_callback with Remote ID \"%s\", target ID \"%s\" and port "
"number %d.",
dacp_id, dacp_server.dacp_id, port);
if (strcmp(dacp_id, dacp_server.dacp_id) == 0) {
dacp_server.port = port;
Expand Down Expand Up @@ -468,8 +473,9 @@ void *dacp_monitor_thread_code(__attribute__((unused)) void *na) {
(metadata_store.advanced_dacp_server_active != 0);
metadata_store.dacp_server_active = 0;
metadata_store.advanced_dacp_server_active = 0;
debug(2, "setting dacp_server_active and advanced_dacp_server_active to 0 with an update "
"flag value of %d",
debug(2,
"setting dacp_server_active and advanced_dacp_server_active to 0 with an update "
"flag value of %d",
ch);
metadata_hub_modify_epilog(ch);
while (dacp_server.scan_enable == 0) {
Expand All @@ -483,7 +489,7 @@ void *dacp_monitor_thread_code(__attribute__((unused)) void *na) {
scan_index++;
result = dacp_get_volume(&the_volume); // just want the http code

if ((result == 496) || (result == 403) || (result == 501)) {
if ((result == 403) || (result == 501)) {
bad_result_count++;
// debug(1,"Bad Scan : %d.",result);
} else
Expand Down Expand Up @@ -511,8 +517,8 @@ void *dacp_monitor_thread_code(__attribute__((unused)) void *na) {
if (dacp_server.scan_enable ==
1) { // if it hasn't been turned off, continue looking for information.
int transient_problem =
(result == 494) ||
(result == 495); // this just means that it couldn't send the query because something
(result == 494) || (result == 495) ||
(result == 496); // this just means that it couldn't send the query because something
// else
// was sending a command or something
if ((!transient_problem) && (bad_result_count == 0) && (idle_scan_count == 0) &&
Expand All @@ -525,12 +531,12 @@ void *dacp_monitor_thread_code(__attribute__((unused)) void *na) {
int inactive = metadata_store.dacp_server_active == 0;
if (inactive) {
metadata_store.dacp_server_active = 1;
debug(2, "Setting dacp_server_active to active because of a response of %d.", result);
debug(1, "Setting dacp_server_active to active because of a response of %d.", result);
}
int same = metadata_store.advanced_dacp_server_active == (result == 200);
if (!same) {
metadata_store.advanced_dacp_server_active = (result == 200);
debug(2, "Setting dacp_advanced_server_active to %d because of a response of %d.",
debug(1, "Setting dacp_advanced_server_active to %d because of a response of %d.",
(result == 200), result);
}
metadata_hub_modify_epilog(inactive + (!same));
Expand Down Expand Up @@ -574,6 +580,7 @@ void *dacp_monitor_thread_code(__attribute__((unused)) void *na) {
// char u;
// char *st;
int32_t r;
uint32_t ui;
// uint64_t v;
// int i;

Expand Down Expand Up @@ -658,64 +665,42 @@ void *dacp_monitor_thread_code(__attribute__((unused)) void *na) {
break;
}
break;
/*
case 'cann': // track name
t = sp - item_size;
if ((metadata_store.track_name == NULL) ||
(strncmp(metadata_store.track_name, t, item_size) != 0)) {
if (metadata_store.track_name)
free(metadata_store.track_name);
metadata_store.track_name = strndup(t, item_size);
debug(1, "Track name changed to: \"%s\"", metadata_store.track_name);
metadata_store.track_name_changed = 1;
metadata_store.changed = 1;
debug(2, "DACP Track Name seen");
if (string_update_with_size(&metadata_store.track_name, &metadata_store.track_name_changed,
sp - item_size, item_size)) {
debug(2, "DACP Track Name set to: \"%s\"", metadata_store.track_name);
}
break;
case 'cana': // artist name
t = sp - item_size;
if ((metadata_store.artist_name == NULL) ||
(strncmp(metadata_store.artist_name, t, item_size) != 0)) {
if (metadata_store.artist_name)
free(metadata_store.artist_name);
metadata_store.artist_name = strndup(t, item_size);
debug(1, "Artist name changed to: \"%s\"", metadata_store.artist_name);
metadata_store.artist_name_changed = 1;
metadata_store.changed = 1;
debug(2, "DACP Artist Name seen");
if (string_update_with_size(&metadata_store.artist_name,
&metadata_store.artist_name_changed, sp - item_size,
item_size)) {
debug(2, "DACP Artist Name set to: \"%s\"", metadata_store.artist_name);
}
break;
case 'canl': // album name
t = sp - item_size;
if ((metadata_store.album_name == NULL) ||
(strncmp(metadata_store.album_name, t, item_size) != 0)) {
if (metadata_store.album_name)
free(metadata_store.album_name);
metadata_store.album_name = strndup(t, item_size);
debug(1, "Album name changed to: \"%s\"", metadata_store.album_name);
metadata_store.album_name_changed = 1;
metadata_store.changed = 1;
debug(2, "DACP Album Name seen");
if (string_update_with_size(&metadata_store.album_name, &metadata_store.album_name_changed,
sp - item_size, item_size)) {
debug(2, "DACP Album Name set to: \"%s\"", metadata_store.album_name);
}
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)
free(metadata_store.genre);
metadata_store.genre = strndup(t, item_size);
debug(1, "Genre changed to: \"%s\"", metadata_store.genre);
metadata_store.genre_changed = 1;
metadata_store.changed = 1;
debug(2, "DACP Genre seen");
if (string_update_with_size(&metadata_store.genre, &metadata_store.genre_changed,
sp - item_size, item_size)) {
debug(2, "DACP Genre set to: \"%s\"", metadata_store.genre);
}
break;
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,
debug(2, "DACP Composite ID seen");
if (memcmp(metadata_store.item_composite_id, sp - item_size,
sizeof(metadata_store.item_composite_id)) != 0) {
memcpy(metadata_store.item_composite_id, t,
memcpy(metadata_store.item_composite_id, sp - item_size,
sizeof(metadata_store.item_composite_id));
char st[33];
char *pt = st;
int it;
Expand All @@ -724,18 +709,20 @@ void *dacp_monitor_thread_code(__attribute__((unused)) void *na) {
pt += 2;
}
*pt = 0;
// debug(1, "Item composite ID set to 0x%s.", st);
metadata_store.item_id_changed = 1;
metadata_store.changed = 1;
debug(2, "Item composite ID changed to 0x%s.", st);
metadata_store.item_composite_id_changed = 1;
}
break;
*/
case 'astm':
t = sp - item_size;
r = ntohl(*(uint32_t *)(t));
if (metadata_store.track_metadata)
metadata_store.track_metadata->songtime_in_milliseconds =
ntohl(*(uint32_t *)(t));
ui = ntohl(*(uint32_t *)(t));
debug(2, "DACP Song Time seen: \"%u\" of length %u.", ui, item_size);
if (ui != metadata_store.songtime_in_milliseconds) {
metadata_store.songtime_in_milliseconds = ui;
metadata_store.songtime_in_milliseconds_changed = 1;
debug(2, "DACP Song Time set to: \"%u\"",
metadata_store.songtime_in_milliseconds);
}
break;

/*
Expand Down
82 changes: 39 additions & 43 deletions dbus-service.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,77 +146,73 @@ void dbus_metadata_watcher(struct metadata_bundle *argc, __attribute__((unused))
debug(1, "This should never happen.");
}

GVariantBuilder *dict_builder, *aa;
// Build the metadata array
debug(2, "Build metadata");
GVariantBuilder *dict_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));

/* Build the metadata array */
// debug(1,"Build metadata");
dict_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));

// Make up the artwork URI if we have one
// Add in the artwork URI if it exists.
if (argc->cover_art_pathname) {
char artURIstring[1024];
snprintf(artURIstring, sizeof(artURIstring), "file://%s", argc->cover_art_pathname);
// debug(1,"artURI String: \"%s\".",artURIstring);
GVariant *artUrl = g_variant_new("s", artURIstring);
GVariant *artUrl = g_variant_new("s", argc->cover_art_pathname);
g_variant_builder_add(dict_builder, "{sv}", "mpris:artUrl", artUrl);
}

// Add the TrackID if we have one
if ((argc->track_metadata) && (argc->track_metadata->item_id)) {
// Add in the Track ID based on the 'mper' metadata if it is non-zero
if (argc->item_id != 0) {
char trackidstring[128];
// debug(1, "Set ID using mper ID: \"%u\".",argc->item_id);
snprintf(trackidstring, sizeof(trackidstring), "/org/gnome/ShairportSync/mper_%u",
argc->track_metadata->item_id);
argc->item_id);
GVariant *trackid = g_variant_new("o", trackidstring);
g_variant_builder_add(dict_builder, "{sv}", "mpris:trackid", trackid);
}

// Add the track name if there is one
if ((argc->track_metadata) && (argc->track_metadata->track_name)) {
// debug(1, "Track name set to \"%s\".", argc->track_name);
GVariant *trackname = g_variant_new("s", argc->track_metadata->track_name);
g_variant_builder_add(dict_builder, "{sv}", "xesam:title", trackname);
// Add the track name if it exists
if (argc->track_name) {
GVariant *track_name = g_variant_new("s", argc->track_name);
g_variant_builder_add(dict_builder, "{sv}", "xesam:title", track_name);
}

// Add the album name if there is one
if ((argc->track_metadata) && (argc->track_metadata->album_name)) {
// debug(1, "Album name set to \"%s\".", argc->album_name);
GVariant *albumname = g_variant_new("s", argc->track_metadata->album_name);
g_variant_builder_add(dict_builder, "{sv}", "xesam:album", albumname);
// Add the album name if it exists
if (argc->album_name) {
GVariant *album_name = g_variant_new("s", argc->album_name);
g_variant_builder_add(dict_builder, "{sv}", "xesam:album", album_name);
}

// Add the artists if there are any (actually there will be at most one, but put it in an array)
if ((argc->track_metadata) && (argc->track_metadata->artist_name)) {
/* Build the artists array */
// debug(1,"Build artist array");
aa = g_variant_builder_new(G_VARIANT_TYPE("as"));
g_variant_builder_add(aa, "s", argc->track_metadata->artist_name);
GVariant *artists = g_variant_builder_end(aa);
g_variant_builder_unref(aa);
// Add the artist name if it exists
if (argc->artist_name) {
GVariantBuilder *artist_as = g_variant_builder_new(G_VARIANT_TYPE("as"));
g_variant_builder_add(artist_as, "s", argc->artist_name);
GVariant *artists = g_variant_builder_end(artist_as);
g_variant_builder_unref(artist_as);
g_variant_builder_add(dict_builder, "{sv}", "xesam:artist", artists);
}

// Add the genres if there are any (actually there will be at most one, but put it in an array)
if ((argc->track_metadata) && (argc->track_metadata->genre)) {
// debug(1,"Build genre");
aa = g_variant_builder_new(G_VARIANT_TYPE("as"));
g_variant_builder_add(aa, "s", argc->track_metadata->genre);
GVariant *genres = g_variant_builder_end(aa);
g_variant_builder_unref(aa);
g_variant_builder_add(dict_builder, "{sv}", "xesam:genre", genres);
// Add the genre if it exists
if (argc->genre) {
GVariantBuilder *genre_as = g_variant_builder_new(G_VARIANT_TYPE("as"));
g_variant_builder_add(genre_as, "s", argc->genre);
GVariant *genre = g_variant_builder_end(genre_as);
g_variant_builder_unref(genre_as);
g_variant_builder_add(dict_builder, "{sv}", "xesam:genre", genre);
}

if (argc->songtime_in_milliseconds) {
uint64_t track_length_in_microseconds = argc->songtime_in_milliseconds;
track_length_in_microseconds *= 1000; // to microseconds in 64-bit precision
// Make up the track name and album name
// debug(1, "Set tracklength to %lu.", track_length_in_microseconds);
GVariant *tracklength = g_variant_new("x", track_length_in_microseconds);
g_variant_builder_add(dict_builder, "{sv}", "mpris:length", tracklength);
}

GVariant *dict = g_variant_builder_end(dict_builder);
g_variant_builder_unref(dict_builder);

// debug(1,"Set metadata");
shairport_sync_remote_control_set_metadata(shairportSyncRemoteControlSkeleton, dict);
}

static gboolean on_handle_set_volume(ShairportSyncAdvancedRemoteControl *skeleton,
GDBusMethodInvocation *invocation, const gint volume,
__attribute__((unused)) gpointer user_data) {
debug(1, "Set volume to %d.", volume);
debug(2, "Set volume to %d.", volume);
dacp_set_volume(volume);
shairport_sync_advanced_remote_control_complete_set_volume(skeleton, invocation);
return TRUE;
Expand Down
Loading

0 comments on commit 86b6d7b

Please sign in to comment.