]> git.ipfire.org Git - thirdparty/shairport-sync.git/commitdiff
Remove timeout on reception of DACP responses to allow for long poll behaviour of...
authorMike Brady <mikebrady@eircom.net>
Fri, 10 Jan 2020 08:31:13 +0000 (08:31 +0000)
committerMike Brady <mikebrady@eircom.net>
Fri, 10 Jan 2020 08:31:13 +0000 (08:31 +0000)
dacp.c
shairport-sync-dbus-test-client.c

diff --git a/dacp.c b/dacp.c
index 7797f7947e3e52692e145ac362599316be7c7b46..a47d1608c99e229e5e6863648ee24c2238abde71 100644 (file)
--- a/dacp.c
+++ b/dacp.c
@@ -150,12 +150,12 @@ void http_cleanup(void *arg) {
 
 int dacp_send_command(const char *command, char **body, ssize_t *bodysize) {
   int result;
-       // debug(1,"dacp_send_command: command is: \"%s\".",command);
-       
-       if (dacp_server.port == 0) {
-         debug(1,"No DACP port specified yet");
-         result = 490; // no port specified
-       } else {
+  // debug(1,"dacp_send_command: command is: \"%s\".",command);
+
+  if (dacp_server.port == 0) {
+    debug(1, "No DACP port specified yet");
+    result = 490; // no port specified
+  } else {
 
     // will malloc space for the body or set it to NULL -- the caller should free it.
 
@@ -213,20 +213,27 @@ int dacp_send_command(const char *command, char **body, ssize_t *bodysize) {
         sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
 
         if (sockfd == -1) {
-          // debug(1, "DACP socket could not be created -- error %d: \"%s\".",errno,strerror(errno));
+          // debug(1, "DACP socket could not be created -- error %d:
+          // \"%s\".",errno,strerror(errno));
           response.code = 497; // Can't establish a socket to the DACP server
         } else {
           pthread_cleanup_push(connect_cleanup, (void *)&sockfd);
           // debug(2, "dacp_send_command: open socket %d.",sockfd);
 
+
+          // This is for limiting the time to be spent waiting for a response.
+
           struct timeval tv;
           tv.tv_sec = 0;
           tv.tv_usec = 500000;
-          if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, sizeof tv) == -1)
-            debug(1, "dacp_send_command: error %d setting receive timeout.", errno);
+          // Don't place a timeout on the receive side of these calls, as some clients may provide
+          // a "long poll" mechanism whereby a reply will not be sent until a change has occurred
+          // if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, sizeof tv) == -1)
+          //   debug(1, "dacp_send_command: error %d setting receive timeout.", errno);
           if (setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (const char *)&tv, sizeof tv) == -1)
             debug(1, "dacp_send_command: error %d setting send timeout.", errno);
 
+
           // connect!
           // debug(1, "DACP socket created.");
           if (connect(sockfd, res->ai_addr, res->ai_addrlen) < 0) {
@@ -240,7 +247,8 @@ int dacp_send_command(const char *command, char **body, ssize_t *bodysize) {
 
             snprintf(message, sizeof(message),
                      "GET /ctrl-int/1/%s HTTP/1.1\r\nHost: %s:%u\r\nActive-Remote: %u\r\n\r\n",
-                     command, dacp_server.ip_string, dacp_server.port, dacp_server.active_remote_id);
+                     command, dacp_server.ip_string, dacp_server.port,
+                     dacp_server.active_remote_id);
 
             // Send command
             debug(3, "dacp_send_command: \"%s\".", command);
@@ -276,8 +284,12 @@ int dacp_send_command(const char *command, char **body, ssize_t *bodysize) {
               memset(buffer, 0, sizeof(buffer));
               while (needmore && !looperror) {
                 const char *data = buffer;
-                if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, sizeof tv) == -1)
-                  debug(1, "dacp_send_command: error %d setting receive timeout.", errno);
+
+                // Don't place a timeout on the receive, as some clients may provide
+                // a "long poll" mechanism whereby a reply will not be sent until a change has occurred
+
+                // if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, sizeof tv) == -1)
+                //  debug(1, "dacp_send_command: error %d setting receive timeout.", errno);
                 ssize_t ndata = recv(sockfd, buffer, sizeof(buffer), 0);
                 // debug(3, "Received %d bytes: \"%s\".", ndata, buffer);
                 if (ndata <= 0) {
@@ -289,10 +301,12 @@ int dacp_send_command(const char *command, char **body, ssize_t *bodysize) {
                     struct linger so_linger;
                     so_linger.l_onoff = 1; // "true"
                     so_linger.l_linger = 0;
-                    int err = setsockopt(sockfd, SOL_SOCKET, SO_LINGER, &so_linger, sizeof so_linger);
+                    int err =
+                        setsockopt(sockfd, SOL_SOCKET, SO_LINGER, &so_linger, sizeof so_linger);
                     if (err)
-                      debug(1,
-                            "Could not set the dacp socket to abort due to a read error on closing.");
+                      debug(
+                          1,
+                          "Could not set the dacp socket to abort due to a read error on closing.");
                   }
 
                   free(response.body);
@@ -487,7 +501,8 @@ void *dacp_monitor_thread_code(__attribute__((unused)) void *na) {
       metadata_store.dacp_server_active = 0;
       metadata_store.advanced_dacp_server_active = 0;
       debug(2,
-            "setting metadata_store.dacp_server_active and metadata_store.advanced_dacp_server_active to 0 with an update "
+            "setting metadata_store.dacp_server_active and "
+            "metadata_store.advanced_dacp_server_active to 0 with an update "
             "flag value of %d",
             ch);
       metadata_hub_modify_epilog(ch);
@@ -499,9 +514,8 @@ void *dacp_monitor_thread_code(__attribute__((unused)) void *na) {
       // so dacp_server.scan_enable will be true at this point
       bad_result_count = 0;
       idle_scan_count = 0;
-      
     }
-    
+
     result = dacp_get_volume(&the_volume); // just want the http code
     pthread_cleanup_pop(1);
 
@@ -514,25 +528,27 @@ void *dacp_monitor_thread_code(__attribute__((unused)) void *na) {
       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 
-    
+    // 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) {    
+
+    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
+    } 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;
     }
@@ -545,14 +561,14 @@ void *dacp_monitor_thread_code(__attribute__((unused)) void *na) {
     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...
@@ -562,7 +578,8 @@ void *dacp_monitor_thread_code(__attribute__((unused)) void *na) {
         update_needed = 1;
       }
     }
-    if (advanced_dacp_server_status_now != -1) { // if advanced_dacp_server_status_now is actually known...
+    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;
@@ -571,286 +588,289 @@ void *dacp_monitor_thread_code(__attribute__((unused)) void *na) {
     }
 
     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);
 
+    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] = "";
+      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) {
-        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] = "";
-        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,"    Serial Number: %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\".");
-                    }
-                    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;
+        // 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,"    Serial Number: %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\".");
                   }
                   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\".");
-                    }
-                    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;
+                case 3:
+                  if (metadata_store.play_status != PS_PAUSED) {
+                    metadata_store.play_status = PS_PAUSED;
+                    debug(2, "Play status is \"paused\".");
                   }
                   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\".");
-                    }
-                    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;
+                case 4:
+                  if (metadata_store.play_status != PS_PLAYING) {
+                    metadata_store.play_status = PS_PLAYING;
+                    debug(2, "Play status changed to \"playing\".");
                   }
                   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);
-                  }
+                default:
+                  debug(1, "Unrecognised play status %d received.", r);
                   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 '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 '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);
+                case 1:
+                  if (metadata_store.shuffle_status != SS_ON) {
+                    metadata_store.shuffle_status = SS_ON;
+                    debug(2, "Shuffle status is \"on\".");
                   }
                   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);
+                default:
+                  debug(1, "Unrecognised shuffle status %d received.", r);
+                  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\".");
                   }
                   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;
+                case 1:
+                  if (metadata_store.repeat_status != RS_ONE) {
+                    metadata_store.repeat_status = RS_ONE;
+                    debug(2, "Repeat status is \"one\".");
                   }
                   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);
+                case 2:
+                  if (metadata_store.repeat_status != RS_ALL) {
+                    metadata_store.repeat_status = RS_ALL;
+                    debug(2, "Repeat status is \"all\".");
                   }
                   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++;
-                    }
-                   */
+                  debug(1, "Unrecognised repeat status %d received.", r);
                   break;
                 }
-                // printf("\n");
+                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;
               }
-
-              // 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");
+              // 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
           } else {
-            debug(1, "Can't find any content in playerstatusupdate request");
+            debug(1, "Status Update not found.\n");
           }
-        } /* 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,"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));
+        } else {
+          debug(1, "Can't find any content in playerstatusupdate request");
+        }
+      } /* else {
+        if (result != 403)
+          debug(1, "Unexpected response %d to playerstatusupdate request", result);
+      } */
       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);
+      };
+    };
+    /*
+    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;
+    }
+    */
+    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);
index 6b8f122c498f0ea1a932196e7c1c4bfd326e6534..111002346e4a95399d047828efd8045f1f0cbc10 100644 (file)
@@ -65,8 +65,7 @@ void on_properties_changed(__attribute__((unused)) GDBusProxy *proxy, GVariant *
   }
 }
 
-void notify_loudness_callback(ShairportSync *proxy,
-                                            __attribute__((unused)) gpointer user_data) {
+void notify_loudness_callback(ShairportSync *proxy, __attribute__((unused)) gpointer user_data) {
   //  printf("\"notify_loudness_callback\" called with a gpointer of
   //  %lx.\n",(int64_t)user_data);
   gboolean ebl = shairport_sync_get_loudness(proxy);
@@ -187,28 +186,44 @@ int main(int argc, char *argv[]) {
   g_signal_connect(proxy4, "notify::volume", G_CALLBACK(notify_volume_callback),
                    "ShairportSync.AdvancedRemoteControl");
 
+
+
   g_print("Starting test...\n");
 
+  g_print("Using the RemoteControl interface, set airplay volume to -30, -20, -10, 0 and -15 for two seconds each...\n");
+  shairport_sync_remote_control_call_set_airplay_volume(SHAIRPORT_SYNC_REMOTE_CONTROL(proxy3), -30, NULL, NULL, 0);
+  sleep(2);
+  shairport_sync_remote_control_call_set_airplay_volume(SHAIRPORT_SYNC_REMOTE_CONTROL(proxy3), -20, NULL, NULL, 0);
+  sleep(2);
+  shairport_sync_remote_control_call_set_airplay_volume(SHAIRPORT_SYNC_REMOTE_CONTROL(proxy3), -10, NULL, NULL, 0);
+  sleep(2);
+  shairport_sync_remote_control_call_set_airplay_volume(SHAIRPORT_SYNC_REMOTE_CONTROL(proxy3), 0, NULL, NULL, 0);
+  sleep(2);
+  shairport_sync_remote_control_call_set_airplay_volume(SHAIRPORT_SYNC_REMOTE_CONTROL(proxy3), -15, NULL, NULL, 0);
+  sleep(2);
+
+  g_print("Using the AdvancedRemoteControl interface, set airplay volume to 20%%, 100%%, 40%% and 60%% for two seconds each...\n");
   shairport_sync_advanced_remote_control_call_set_volume(
       SHAIRPORT_SYNC_ADVANCED_REMOTE_CONTROL(proxy4), 20, NULL, NULL, 0);
-  sleep(5);
+  sleep(2);
   shairport_sync_advanced_remote_control_call_set_volume(
       SHAIRPORT_SYNC_ADVANCED_REMOTE_CONTROL(proxy4), 100, NULL, NULL, 0);
-  sleep(5);
+  sleep(2);
   shairport_sync_advanced_remote_control_call_set_volume(
       SHAIRPORT_SYNC_ADVANCED_REMOTE_CONTROL(proxy4), 40, NULL, NULL, 0);
-  sleep(5);
+  sleep(2);
   shairport_sync_advanced_remote_control_call_set_volume(
       SHAIRPORT_SYNC_ADVANCED_REMOTE_CONTROL(proxy4), 60, NULL, NULL, 0);
-        
-  sleep(5);
-  g_print("Volume up for five seconds...\n");
-  shairport_sync_remote_control_call_volume_up(SHAIRPORT_SYNC_REMOTE_CONTROL(proxy3), NULL, NULL, NULL);
 
+  sleep(2);
+  g_print("Using the RemoteControl interface, increase volume for five seconds...\n");
+  shairport_sync_remote_control_call_volume_up(SHAIRPORT_SYNC_REMOTE_CONTROL(proxy3), NULL, NULL,
+                                               NULL);
   sleep(5);
-  g_print("Volume down\n");
-  shairport_sync_remote_control_call_volume_down(SHAIRPORT_SYNC_REMOTE_CONTROL(proxy3), NULL, NULL, NULL);
-  
+  g_print("Using the RemoteControl interface, decrease volume...\n");
+  shairport_sync_remote_control_call_volume_down(SHAIRPORT_SYNC_REMOTE_CONTROL(proxy3), NULL, NULL,
+                                                 NULL);
+
   /*
   // sleep(1);
     shairport_sync_set_loudness_filter_active(SHAIRPORT_SYNC(proxy), TRUE);