/*
* DACP protocol handler. This file is part of Shairport Sync.
- * Copyright (c) Mike Brady 2017 -- 2019
+ * Copyright (c) Mike Brady 2017 -- 2020
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
typedef struct {
int players_connection_thread_index; // the connection thread index when a player thread is
// associated with this, zero otherwise
- int scan_enable; // set to 1 if if sacanning should be considered
+ int scan_enable; // set to 1 if scanning should be considered
char dacp_id[256]; // the DACP ID string
uint16_t port; // zero if no port discovered
short connection_family; // AF_INET6 or AF_INET
// static pthread_mutex_t dacp_server_information_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t dacp_conversation_lock;
static pthread_mutex_t dacp_server_information_lock;
-static pthread_cond_t dacp_server_information_cv = PTHREAD_COND_INITIALIZER;
+static pthread_cond_t dacp_server_information_cv;
void addrinfo_cleanup(void *arg) {
// debug(1, "addrinfo cleanup called.");
// debug(1,"dacp_send_command: command is: \"%s\".",command);
if (dacp_server.port == 0) {
- debug(1, "No DACP port specified yet");
+ debug(2, "No DACP port specified yet");
result = 490; // no port specified
} else {
// 493 Client failed to send a message
// 492 Argument out of range
// 491 Client refused connection
+ // 490 No port specified
struct addrinfo hints, *res;
int sockfd;
dacp_server.always_use_revision_number_1 = 1;
}
-
- mdns_dacp_monitor_set_id(dacp_server.dacp_id);
-
metadata_hub_modify_prolog();
int ch = metadata_store.dacp_server_active != dacp_server.scan_enable;
metadata_store.dacp_server_active = dacp_server.scan_enable;
"flag value of %d",
ch);
metadata_hub_modify_epilog(ch);
- while (dacp_server.scan_enable == 0) {
- // debug(1, "dacp_monitor_thread_code wait for an event to possible enable scan");
- pthread_cond_wait(&dacp_server_information_cv, &dacp_server_information_lock);
- // debug(1,"dacp_monitor_thread_code wake up.");
+
+ uint64_t time_to_wait_for_wakeup_ns = (uint64_t)(1000000000 * config.missing_port_dacp_scan_interval_seconds);
+
+#ifdef COMPILE_FOR_LINUX_AND_FREEBSD_AND_CYGWIN_AND_OPENBSD
+ uint64_t time_of_wakeup_ns = get_absolute_time_in_ns() + time_to_wait_for_wakeup_ns;
+ uint64_t sec = time_of_wakeup_ns / 1000000000;
+ uint64_t nsec = time_of_wakeup_ns % 1000000000;
+#endif
+#ifdef COMPILE_FOR_OSX
+ uint64_t sec = time_to_wait_for_wakeup_ns / 1000000000;
+ uint64_t nsec = time_to_wait_for_wakeup_ns % 1000000000;
+#endif
+
+ struct timespec time_to_wait;
+ time_to_wait.tv_sec = sec;
+ time_to_wait.tv_nsec = nsec;
+
+ while ((dacp_server.scan_enable == 0) && (result != ETIMEDOUT)) {
+ // debug(1, "dacp_monitor_thread_code wait for an event to possibly enable scan");
+
+#ifdef COMPILE_FOR_LINUX_AND_FREEBSD_AND_CYGWIN_AND_OPENBSD
+ result = pthread_cond_timedwait(&dacp_server_information_cv, &dacp_server_information_lock,
+ &time_to_wait); // this is a pthread cancellation point
+ // debug(1, "result is %d, dacp_server.scan_enable is %d, time_to_wait_for_wakeup_ns is %" PRId64 ".", result, dacp_server.scan_enable, time_to_wait_for_wakeup_ns);
+
+#endif
+#ifdef COMPILE_FOR_OSX
+ result = pthread_cond_timedwait_relative_np(&dacp_server_information_cv, &dacp_server_information_lock, &time_to_wait);
+#endif
+ }
+ if (dacp_server.scan_enable == 1) {
+ bad_result_count = 0;
+ idle_scan_count = 0;
}
- // so dacp_server.scan_enable will be true at this point
- bad_result_count = 0;
- idle_scan_count = 0;
}
always_use_revision_number_1 = dacp_server.always_use_revision_number_1; // set this while access is locked
result = dacp_get_volume(&the_volume); // just want the http code
pthread_cleanup_pop(1);
- scan_index++;
- // debug(1,"DACP Scan Result: %d.", result);
-
- if ((result == 200) || (result == 400)) {
- bad_result_count = 0;
+ if (result == 490) { // 490 means no port was specified
+ if ((dacp_server.dacp_id != NULL) && (strlen(dacp_server.dacp_id) != 0)) {
+ // debug(1,"mdns_dacp_monitor_set_id");
+ mdns_dacp_monitor_set_id(dacp_server.dacp_id);
+ }
} else {
- if (bad_result_count < config.scan_max_bad_response_count) // limit to some reasonable value
- bad_result_count++;
- }
-
- // here, do the debouncing calculations to see
- // if the dacp server and the
- // advanced dacp server are available
+ scan_index++;
+ // debug(1,"DACP Scan Result: %d.", result);
- // -1 means we don't know because some bad statuses have been reported
- // 0 means definitely no
- // +1 means definitely yes
-
- int dacp_server_status_now = -1;
- int advanced_dacp_server_status_now = -1;
+ if ((result == 200) || (result == 400)) {
+ bad_result_count = 0;
+ } else {
+ if (bad_result_count < config.scan_max_bad_response_count) // limit to some reasonable value
+ bad_result_count++;
+ }
- if (bad_result_count == 0) {
- dacp_server_status_now = 1;
- if (result == 200)
- advanced_dacp_server_status_now = 1;
- else if (result == 400)
+ // here, do the debouncing calculations to see
+ // if the dacp server and the
+ // advanced dacp server are available
+
+ // -1 means we don't know because some bad statuses have been reported
+ // 0 means definitely no
+ // +1 means definitely yes
+
+ int dacp_server_status_now = -1;
+ int advanced_dacp_server_status_now = -1;
+
+ if (bad_result_count == 0) {
+ dacp_server_status_now = 1;
+ if (result == 200)
+ advanced_dacp_server_status_now = 1;
+ else if (result == 400)
+ advanced_dacp_server_status_now = 0;
+ } else if (bad_result_count ==
+ config.scan_max_bad_response_count) { // if a sequence of bad return codes occurs,
+ // then it's gone
+ dacp_server_status_now = 0;
advanced_dacp_server_status_now = 0;
- } else if (bad_result_count ==
- config.scan_max_bad_response_count) { // if a sequence of bad return codes occurs,
- // then it's gone
- dacp_server_status_now = 0;
- advanced_dacp_server_status_now = 0;
- }
+ }
- if (metadata_store.player_thread_active == 0)
- idle_scan_count++;
- else
- idle_scan_count = 0;
+ if (metadata_store.player_thread_active == 0)
+ idle_scan_count++;
+ else
+ idle_scan_count = 0;
- debug(3, "Scan Result: %d, Bad Scan Count: %d, Idle Scan Count: %d.", result, bad_result_count,
- idle_scan_count);
+ debug(3, "Scan Result: %d, Bad Scan Count: %d, Idle Scan Count: %d.", result, bad_result_count,
+ idle_scan_count);
- /* not used
- // decide if idle for too long
- if (idle_scan_count == config.scan_max_inactive_count) {
- debug(2, "DACP server status scanning stopped.");
- dacp_server.scan_enable = 0;
- }
- */
+ /* not used
+ // decide if idle for too long
+ if (idle_scan_count == config.scan_max_inactive_count) {
+ debug(2, "DACP server status scanning stopped.");
+ dacp_server.scan_enable = 0;
+ }
+ */
- int update_needed = 0;
- metadata_hub_modify_prolog();
- if (dacp_server_status_now != -1) { // if dacp_server_status_now is actually known...
- if (metadata_store.dacp_server_active != dacp_server_status_now) {
- debug(2, "metadata_store.dacp_server_active set to %d.", dacp_server_status_now);
- metadata_store.dacp_server_active = dacp_server_status_now;
- update_needed = 1;
+ int update_needed = 0;
+ metadata_hub_modify_prolog();
+ if (dacp_server_status_now != -1) { // if dacp_server_status_now is actually known...
+ if (metadata_store.dacp_server_active != dacp_server_status_now) {
+ debug(2, "metadata_store.dacp_server_active set to %d.", dacp_server_status_now);
+ metadata_store.dacp_server_active = dacp_server_status_now;
+ update_needed = 1;
+ }
}
- }
- if (advanced_dacp_server_status_now !=
- -1) { // if advanced_dacp_server_status_now is actually known...
- if (metadata_store.advanced_dacp_server_active != advanced_dacp_server_status_now) {
- debug(2, "metadata_store.advanced_dacp_server_active set to %d.", dacp_server_status_now);
- metadata_store.advanced_dacp_server_active = advanced_dacp_server_status_now;
- update_needed = 1;
+ if (advanced_dacp_server_status_now !=
+ -1) { // if advanced_dacp_server_status_now is actually known...
+ if (metadata_store.advanced_dacp_server_active != advanced_dacp_server_status_now) {
+ debug(2, "metadata_store.advanced_dacp_server_active set to %d.", dacp_server_status_now);
+ metadata_store.advanced_dacp_server_active = advanced_dacp_server_status_now;
+ update_needed = 1;
+ }
}
- }
- metadata_hub_modify_epilog(update_needed);
+ metadata_hub_modify_epilog(update_needed);
- // pthread_mutex_unlock(&dacp_server_information_lock);
- // debug(1, "DACP Server ID \"%u\" at \"%s:%u\", scan %d.", dacp_server.active_remote_id,
- // dacp_server.ip_string, dacp_server.port, scan_index);
+ // pthread_mutex_unlock(&dacp_server_information_lock);
+ // debug(1, "DACP Server ID \"%u\" at \"%s:%u\", scan %d.", dacp_server.active_remote_id,
+ // dacp_server.ip_string, dacp_server.port, scan_index);
- if (result == 200) {
- metadata_hub_modify_prolog();
- int diff = metadata_store.speaker_volume != the_volume;
- if (diff)
- metadata_store.speaker_volume = the_volume;
- metadata_hub_modify_epilog(diff);
-
- ssize_t le;
- char *response = NULL;
- int32_t item_size;
- char command[1024] = "";
- if (always_use_revision_number_1 != 0) // for forked-daapd
- revision_number = 1;
- snprintf(command, sizeof(command) - 1, "playstatusupdate?revision-number=%d",
- revision_number);
- // debug(1,"dacp_monitor_thread_code: command: \"%s\"",command);
- result = dacp_send_command(command, &response, &le);
- // debug(1,"Response to \"%s\" is %d.",command,result);
- // remember: unless the revision_number you pass in is 1,
- // response will be 200 only if there's something new to report.
if (result == 200) {
- // if (0) {
- char *sp = response;
- if (le >= 8) {
- // here start looking for the contents of the status update
- if (dacp_tlv_crawl(&sp, &item_size) == 'cmst') { // status
- // here, we know that we are receiving playerstatusupdates, so set a flag
- metadata_hub_modify_prolog();
- // debug(1, "playstatusupdate release track metadata");
- // metadata_hub_reset_track_metadata();
- // metadata_store.playerstatusupdates_are_received = 1;
- sp -= item_size; // drop down into the array -- don't skip over it
- le -= 8;
- // char typestring[5];
- // we need to acquire the metadata data structure and possibly update it
- while (le >= 8) {
- uint32_t type = dacp_tlv_crawl(&sp, &item_size);
- le -= item_size + 8;
- char *t;
- // char u;
- // char *st;
- int32_t r;
- uint32_t ui;
- // uint64_t v;
- // int i;
-
- switch (type) {
- case 'cmsr': // revision number
- t = sp - item_size;
- revision_number = ntohl(*(uint32_t *)(t));
- // debug(1,"New revision number received: %d", revision_number);
- break;
- case 'caps': // play status
- t = sp - item_size;
- r = *(unsigned char *)(t);
- switch (r) {
- case 2:
- if (metadata_store.play_status != PS_STOPPED) {
- metadata_store.play_status = PS_STOPPED;
- debug(2, "Play status is \"stopped\".");
- }
+ metadata_hub_modify_prolog();
+ int diff = metadata_store.speaker_volume != the_volume;
+ if (diff)
+ metadata_store.speaker_volume = the_volume;
+ metadata_hub_modify_epilog(diff);
+
+ ssize_t le;
+ char *response = NULL;
+ int32_t item_size;
+ char command[1024] = "";
+ if (always_use_revision_number_1 != 0) // for forked-daapd
+ revision_number = 1;
+ snprintf(command, sizeof(command) - 1, "playstatusupdate?revision-number=%d",
+ revision_number);
+ // debug(1,"dacp_monitor_thread_code: command: \"%s\"",command);
+ result = dacp_send_command(command, &response, &le);
+ // debug(1,"Response to \"%s\" is %d.",command,result);
+ // remember: unless the revision_number you pass in is 1,
+ // response will be 200 only if there's something new to report.
+ if (result == 200) {
+ // if (0) {
+ char *sp = response;
+ if (le >= 8) {
+ // here start looking for the contents of the status update
+ if (dacp_tlv_crawl(&sp, &item_size) == 'cmst') { // status
+ // here, we know that we are receiving playerstatusupdates, so set a flag
+ metadata_hub_modify_prolog();
+ // debug(1, "playstatusupdate release track metadata");
+ // metadata_hub_reset_track_metadata();
+ // metadata_store.playerstatusupdates_are_received = 1;
+ sp -= item_size; // drop down into the array -- don't skip over it
+ le -= 8;
+ // char typestring[5];
+ // we need to acquire the metadata data structure and possibly update it
+ while (le >= 8) {
+ uint32_t type = dacp_tlv_crawl(&sp, &item_size);
+ le -= item_size + 8;
+ char *t;
+ // char u;
+ // char *st;
+ int32_t r;
+ uint32_t ui;
+ // uint64_t v;
+ // int i;
+
+ switch (type) {
+ case 'cmsr': // revision number
+ t = sp - item_size;
+ revision_number = ntohl(*(uint32_t *)(t));
+ // debug(1,"New revision number received: %d", revision_number);
break;
- case 3:
- if (metadata_store.play_status != PS_PAUSED) {
- metadata_store.play_status = PS_PAUSED;
- debug(2, "Play status is \"paused\".");
+ case 'caps': // play status
+ t = sp - item_size;
+ r = *(unsigned char *)(t);
+ switch (r) {
+ case 2:
+ if (metadata_store.play_status != PS_STOPPED) {
+ metadata_store.play_status = PS_STOPPED;
+ debug(2, "Play status is \"stopped\".");
+ }
+ break;
+ case 3:
+ if (metadata_store.play_status != PS_PAUSED) {
+ metadata_store.play_status = PS_PAUSED;
+ debug(2, "Play status is \"paused\".");
+ }
+ break;
+ case 4:
+ if (metadata_store.play_status != PS_PLAYING) {
+ metadata_store.play_status = PS_PLAYING;
+ debug(2, "Play status changed to \"playing\".");
+ }
+ break;
+ default:
+ debug(1, "Unrecognised play status %d received.", r);
+ break;
}
break;
- case 4:
- if (metadata_store.play_status != PS_PLAYING) {
- metadata_store.play_status = PS_PLAYING;
- debug(2, "Play status changed to \"playing\".");
+ case 'cash': // shuffle status
+ t = sp - item_size;
+ r = *(unsigned char *)(t);
+ switch (r) {
+ case 0:
+ if (metadata_store.shuffle_status != SS_OFF) {
+ metadata_store.shuffle_status = SS_OFF;
+ debug(2, "Shuffle status is \"off\".");
+ }
+ break;
+ case 1:
+ if (metadata_store.shuffle_status != SS_ON) {
+ metadata_store.shuffle_status = SS_ON;
+ debug(2, "Shuffle status is \"on\".");
+ }
+ break;
+ default:
+ debug(1, "Unrecognised shuffle status %d received.", r);
+ break;
}
break;
- default:
- debug(1, "Unrecognised play status %d received.", r);
+ case 'carp': // repeat status
+ t = sp - item_size;
+ r = *(unsigned char *)(t);
+ switch (r) {
+ case 0:
+ if (metadata_store.repeat_status != RS_OFF) {
+ metadata_store.repeat_status = RS_OFF;
+ debug(2, "Repeat status is \"none\".");
+ }
+ break;
+ case 1:
+ if (metadata_store.repeat_status != RS_ONE) {
+ metadata_store.repeat_status = RS_ONE;
+ debug(2, "Repeat status is \"one\".");
+ }
+ break;
+ case 2:
+ if (metadata_store.repeat_status != RS_ALL) {
+ metadata_store.repeat_status = RS_ALL;
+ debug(2, "Repeat status is \"all\".");
+ }
+ break;
+ default:
+ debug(1, "Unrecognised repeat status %d received.", r);
+ break;
+ }
break;
- }
- break;
- case 'cash': // shuffle status
- t = sp - item_size;
- r = *(unsigned char *)(t);
- switch (r) {
- case 0:
- if (metadata_store.shuffle_status != SS_OFF) {
- metadata_store.shuffle_status = SS_OFF;
- debug(2, "Shuffle status is \"off\".");
+ case 'cann': // track name
+ 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 1:
- if (metadata_store.shuffle_status != SS_ON) {
- metadata_store.shuffle_status = SS_ON;
- debug(2, "Shuffle status is \"on\".");
+ case 'cana': // artist name
+ 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;
- default:
- debug(1, "Unrecognised shuffle status %d received.", r);
+ case 'canl': // album name
+ 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;
- }
- break;
- case 'carp': // repeat status
- t = sp - item_size;
- r = *(unsigned char *)(t);
- switch (r) {
- case 0:
- if (metadata_store.repeat_status != RS_OFF) {
- metadata_store.repeat_status = RS_OFF;
- debug(2, "Repeat status is \"none\".");
+ case 'cang': // genre
+ 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 1:
- if (metadata_store.repeat_status != RS_ONE) {
- metadata_store.repeat_status = RS_ONE;
- debug(2, "Repeat status is \"one\".");
+ case 'canp': // nowplaying 4 ids: dbid, plid, playlistItem, itemid (from mellowware
+ // see reference above)
+ 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, sp - item_size,
+ sizeof(metadata_store.item_composite_id));
+ char st[33];
+ char *pt = st;
+ int it;
+ for (it = 0; it < 16; it++) {
+ snprintf(pt, 3, "%02X", metadata_store.item_composite_id[it]);
+ pt += 2;
+ }
+ *pt = 0;
+ debug(2, "Item composite ID changed to 0x%s.", st);
+ metadata_store.item_composite_id_changed = 1;
}
break;
- case 2:
- if (metadata_store.repeat_status != RS_ALL) {
- metadata_store.repeat_status = RS_ALL;
- debug(2, "Repeat status is \"all\".");
+ case 'astm':
+ t = sp - item_size;
+ 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;
+
+ /*
+ case 'mstt':
+ case 'cant':
+ case 'cast':
+ case 'cmmk':
+ case 'caas':
+ case 'caar':
+ t = sp - item_size;
+ r = ntohl(*(uint32_t *)(t));
+ printf(" %d", r);
+ printf(" (0x");
+ t = sp - item_size;
+ for (i = 0; i < item_size; i++) {
+ printf("%02x", *t & 0xff);
+ t++;
+ }
+ printf(")");
+ break;
+ case 'asai':
+ t = sp - item_size;
+ s = ntohl(*(uint32_t *)(t));
+ s = s << 32;
+ t += 4;
+ v = (ntohl(*(uint32_t *)(t))) & 0xffffffff;
+ s += v;
+ printf(" %lu", s);
+ printf(" (0x");
+ t = sp - item_size;
+ for (i = 0; i < item_size; i++) {
+ printf("%02x", *t & 0xff);
+ t++;
+ }
+ printf(")");
+ break;
+ */
default:
- debug(1, "Unrecognised repeat status %d received.", r);
+ /*
+ printf(" 0x");
+ t = sp - item_size;
+ for (i = 0; i < item_size; i++) {
+ printf("%02x", *t & 0xff);
+ t++;
+ }
+ */
break;
}
- break;
- case 'cann': // track name
- 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
- 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
- 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
- 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)
- 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, sp - item_size,
- sizeof(metadata_store.item_composite_id));
- char st[33];
- char *pt = st;
- int it;
- for (it = 0; it < 16; it++) {
- snprintf(pt, 3, "%02X", metadata_store.item_composite_id[it]);
- pt += 2;
- }
- *pt = 0;
- debug(2, "Item composite ID changed to 0x%s.", st);
- metadata_store.item_composite_id_changed = 1;
- }
- break;
- case 'astm':
- t = sp - item_size;
- 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;
-
- /*
- case 'mstt':
- case 'cant':
- case 'cast':
- case 'cmmk':
- case 'caas':
- case 'caar':
- t = sp - item_size;
- r = ntohl(*(uint32_t *)(t));
- printf(" %d", r);
- printf(" (0x");
- t = sp - item_size;
- for (i = 0; i < item_size; i++) {
- printf("%02x", *t & 0xff);
- t++;
- }
- printf(")");
- break;
- case 'asai':
- t = sp - item_size;
- s = ntohl(*(uint32_t *)(t));
- s = s << 32;
- t += 4;
- v = (ntohl(*(uint32_t *)(t))) & 0xffffffff;
- s += v;
- printf(" %lu", s);
- printf(" (0x");
- t = sp - item_size;
- for (i = 0; i < item_size; i++) {
- printf("%02x", *t & 0xff);
- t++;
- }
- printf(")");
- break;
- */
- default:
- /*
- printf(" 0x");
- t = sp - item_size;
- for (i = 0; i < item_size; i++) {
- printf("%02x", *t & 0xff);
- t++;
- }
- */
- break;
+ // printf("\n");
}
- // printf("\n");
- }
- // finished possibly writing to the metadata hub
- metadata_hub_modify_epilog(
- 1); // should really see if this can be made responsive to changes
+ // finished possibly writing to the metadata hub
+ metadata_hub_modify_epilog(
+ 1); // should really see if this can be made responsive to changes
+ } else {
+ debug(1, "Status Update not found.\n");
+ }
} else {
- debug(1, "Status Update not found.\n");
+ debug(1, "Can't find any content in playerstatusupdate request");
}
- } else {
- debug(1, "Can't find any content in playerstatusupdate request");
- }
- } /* else {
- if (result != 403)
- debug(1, "Unexpected response %d to playerstatusupdate request", result);
- } */
+ } /* else {
+ if (result != 403)
+ debug(1, "Unexpected response %d to playerstatusupdate request", result);
+ } */
+ if (response) {
+ free(response);
+ response = NULL;
+ };
+ };
+ /*
+ strcpy(command,"nowplayingartwork?mw=320&mh=320");
+ debug(1,"Command: \"%s\", result is %d",command, dacp_send_command(command, &response, &le));
if (response) {
free(response);
response = NULL;
- };
- };
- /*
- strcpy(command,"nowplayingartwork?mw=320&mh=320");
- debug(1,"Command: \"%s\", result is %d",command, dacp_send_command(command, &response, &le));
- if (response) {
- free(response);
- response = NULL;
- }
- strcpy(command,"getproperty?properties=dmcp.volume");
- debug(1,"Command: \"%s\", result is %d",command, dacp_send_command(command, &response, &le));
- if (response) {
- free(response);
- response = NULL;
- }
- strcpy(command,"setproperty?dmcp.volume=100.000000");
- debug(1,"Command: \"%s\", result is %d",command, dacp_send_command(command, &response, &le));
- if (response) {
- free(response);
- response = NULL;
+ }
+ strcpy(command,"getproperty?properties=dmcp.volume");
+ debug(1,"Command: \"%s\", result is %d",command, dacp_send_command(command, &response, &le));
+ if (response) {
+ free(response);
+ response = NULL;
+ }
+ strcpy(command,"setproperty?dmcp.volume=100.000000");
+ debug(1,"Command: \"%s\", result is %d",command, dacp_send_command(command, &response, &le));
+ if (response) {
+ free(response);
+ response = NULL;
+ }
+ */
+ if (metadata_store.player_thread_active)
+ sleep(config.scan_interval_when_active);
+ else
+ sleep(config.scan_interval_when_inactive);
}
- */
- if (metadata_store.player_thread_active)
- sleep(config.scan_interval_when_active);
- else
- sleep(config.scan_interval_when_inactive);
}
debug(1, "DACP monitor thread exiting -- should never happen.");
pthread_exit(NULL);
void dacp_monitor_start() {
int rc;
+
+#ifdef COMPILE_FOR_LINUX_AND_FREEBSD_AND_CYGWIN_AND_OPENBSD
+ pthread_condattr_t attr;
+ pthread_condattr_init(&attr);
+ pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); // can't do this in OS X, and don't need it.
+ rc = pthread_cond_init(&dacp_server_information_cv, &attr);
+ if (rc)
+ debug(1, "Error initialising the DACP Server Information Condition Variable");
+ pthread_condattr_destroy(&attr);
+#endif
+#ifdef COMPILE_FOR_OSX
+ rc = pthread_cond_init(&dacp_server_information_cv, NULL);
+#endif
+
+
+
pthread_mutexattr_t mta;
rc = pthread_mutexattr_init(&mta);
pthread_mutex_destroy(&dacp_server_information_lock);
debug(3, "DACP Conversation Lock Mutex Destroyed");
pthread_mutex_destroy(&dacp_conversation_lock);
+ pthread_cond_destroy(&dacp_server_information_cv);
+ debug(1, "DACP Server Information Condition Variable destroyed.");
}
}