]> git.ipfire.org Git - thirdparty/shairport-sync.git/commitdiff
Make scanning for DACP port part of the dacp handler. Only emit 'clip' and 'svip...
authorMike Brady <mikebrady@eircom.net>
Sat, 31 Mar 2018 16:34:59 +0000 (17:34 +0100)
committerMike Brady <mikebrady@eircom.net>
Sat, 31 Mar 2018 16:34:59 +0000 (17:34 +0100)
audio_alsa.c
dacp.c
dacp.h
mdns.c
mdns.h
mdns_avahi.c
metadata_hub.c
player.c
player.h
rtp.c
rtsp.c

index 7a60db22ae0b452a2b49472dd0baa40e93daf4f0..beb8158cf9fffa42aa00684242cfe55142af8eda 100644 (file)
@@ -503,14 +503,14 @@ int open_alsa_device(void) {
       (snd_pcm_hw_params_set_access(alsa_handle, alsa_params, SND_PCM_ACCESS_MMAP_INTERLEAVED) >=
        0)) {
     if (output_method_signalled == 0) {
-      debug(1, "Output written using MMAP");
+      debug(3, "Output written using MMAP");
       output_method_signalled = 1;
     }
     access = SND_PCM_ACCESS_MMAP_INTERLEAVED;
     alsa_pcm_write = snd_pcm_mmap_writei;
   } else {
     if (output_method_signalled == 0) {
-      debug(1, "Output written with RW");
+      debug(3, "Output written with RW");
       output_method_signalled = 1;
     }
     access = SND_PCM_ACCESS_RW_INTERLEAVED;
diff --git a/dacp.c b/dacp.c
index cb6581ca2deed5fb303465245cc53c1ee7f372da..b6ad72ee7aed80b60b923659de8f8eb875328d2f 100644 (file)
--- a/dacp.c
+++ b/dacp.c
@@ -49,11 +49,13 @@ 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
+  char dacp_id[256];                   // the DACP ID string
   uint16_t port;                       // zero if no port discovered
   short connection_family;             // AF_INET6 or AF_INET
   uint32_t scope_id;                   // if it's an ipv6 connection, this will be its scope id
   char ip_string[INET6_ADDRSTRLEN];    // the ip string pointing to the client
   uint32_t active_remote_id;           // send this when you want to send remote control commands
+  void *port_monitor_private_storage;
 } dacp_server_record;
 
 pthread_t dacp_monitor_thread;
@@ -175,8 +177,8 @@ int dacp_send_command(const char *command, char **body, ssize_t *bodysize) {
         response.code = 497; // Can't establish a socket to the DACP server
       } else {
         struct timeval tv;
-        tv.tv_sec = 0;
-        tv.tv_usec = 250000;
+        tv.tv_sec = 1;
+        tv.tv_usec = 0;
         if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, sizeof tv) == -1)
           debug(1, "Error %d setting receive timeout for DACP service.", errno);
         if (setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (const char *)&tv, sizeof tv) == -1)
@@ -294,43 +296,69 @@ void relinquish_dacp_server_information(rtsp_conn_info *conn) {
 }
 
 // this will be running on the thread of its caller, not of the conversation thread...
-void set_dacp_server_information(rtsp_conn_info *conn) { // tell the DACP conversation thread that
-                                                         // the port has been set or changed
+// tell the DACP conversation thread what DACP server we are listening to
+// if the active_remote_id is the same we don't change anything apart from
+// the conversation number
+// Thus, we can keep the DACP port that might have previously been discovered
+void set_dacp_server_information(rtsp_conn_info *conn) {
   sps_pthread_mutex_timedlock(
       &dacp_server_information_lock, 500000,
       "set_dacp_server_information couldn't get DACP server information lock in 0.5 second!.", 1);
   dacp_server.players_connection_thread_index = conn->connection_number;
-  dacp_server.port = conn->dacp_port;
-  dacp_server.connection_family = conn->connection_ip_family;
-  dacp_server.scope_id = conn->self_scope_id;
-  strncpy(dacp_server.ip_string, conn->client_ip_string, INET6_ADDRSTRLEN);
-  dacp_server.active_remote_id = conn->dacp_active_remote;
-  if (dacp_server.port)
-    dacp_server.scan_enable = 1;
-  else {
-    debug(1, "DACP server port has been set to zero.");
+  if (strcmp(conn->dacp_id, dacp_server.dacp_id) != 0) {
+    strncpy(dacp_server.dacp_id, conn->dacp_id, sizeof(dacp_server.dacp_id));
+    dacp_server.port = 0;
     dacp_server.scan_enable = 0;
+    dacp_server.connection_family = conn->connection_ip_family;
+    dacp_server.scope_id = conn->self_scope_id;
+    strncpy(dacp_server.ip_string, conn->client_ip_string, INET6_ADDRSTRLEN);
+    dacp_server.active_remote_id = conn->dacp_active_remote;
+
+    if (dacp_server.port_monitor_private_storage) // if there's is a monitor already active...
+      mdns_dacp_dont_monitor(dacp_server.port_monitor_private_storage); // let it go.
+    dacp_server.port_monitor_private_storage =
+        mdns_dacp_monitor(dacp_server.dacp_id); // create a new one for us
+
+    metadata_hub_modify_prolog();
+    int ch = metadata_store.dacp_server_active != dacp_server.scan_enable;
+    metadata_store.dacp_server_active = dacp_server.scan_enable;
+    if ((metadata_store.client_ip == NULL) ||
+        (strncmp(metadata_store.client_ip, conn->client_ip_string, INET6_ADDRSTRLEN) != 0)) {
+      if (metadata_store.client_ip)
+        free(metadata_store.client_ip);
+      metadata_store.client_ip = strndup(conn->client_ip_string, INET6_ADDRSTRLEN);
+      debug(3, "MH Client IP set to: \"%s\"", metadata_store.client_ip);
+      ch = 1;
+    }
+    metadata_hub_modify_epilog(ch);
   }
-  metadata_hub_modify_prolog();
-  int ch = metadata_store.dacp_server_active != dacp_server.scan_enable;
-  metadata_store.dacp_server_active = dacp_server.scan_enable;
-
-  if ((metadata_store.client_ip == NULL) ||
-      (strncmp(metadata_store.client_ip, conn->client_ip_string, INET6_ADDRSTRLEN) != 0)) {
-    if (metadata_store.client_ip)
-      free(metadata_store.client_ip);
-    metadata_store.client_ip = strndup(conn->client_ip_string, INET6_ADDRSTRLEN);
-    debug(1, "MH Client IP set to: \"%s\"", metadata_store.client_ip);
-    metadata_store.client_ip_changed = 1;
-    metadata_store.changed = 1;
-    ch = 1;
-  }
-  metadata_hub_modify_epilog(ch);
-
   pthread_cond_signal(&dacp_server_information_cv);
   pthread_mutex_unlock(&dacp_server_information_lock);
 }
 
+void dacp_monitor_port_update_callback(char *dacp_id, uint16_t port) {
+  debug(3, "dacp_monitor_port_update_callback with Remote ID \"%s\" and port number %d.", dacp_id,
+        port);
+  sps_pthread_mutex_timedlock(
+      &dacp_server_information_lock, 500000,
+      "dacp_monitor_port_update_callback couldn't get DACP server information lock in 0.5 second!.",
+      1);
+  if (strcmp(dacp_id, dacp_server.dacp_id) == 0) {
+    dacp_server.port = port;
+    if (port == 0)
+      dacp_server.scan_enable = 0;
+    else
+      dacp_server.scan_enable = 1;
+    metadata_hub_modify_prolog();
+    int ch = metadata_store.dacp_server_active != dacp_server.scan_enable;
+    metadata_store.dacp_server_active = dacp_server.scan_enable;
+    metadata_hub_modify_epilog(ch);
+    pthread_cond_signal(&dacp_server_information_cv);
+  } else {
+    debug(1, "dacp port monitor reporting on and out-of-use remote.");
+  }
+  pthread_mutex_unlock(&dacp_server_information_lock);
+}
 void *dacp_monitor_thread_code(__attribute__((unused)) void *na) {
   int scan_index = 0;
   // char server_reply[10000];
@@ -361,8 +389,10 @@ void *dacp_monitor_thread_code(__attribute__((unused)) void *na) {
     // 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 != 494) { // this just means that it couldn't send the query because something else
-                         // was sending a command
+    int transient_problem = (result == 494) || (result == 495);
+    if (!transient_problem) { // this just means that it couldn't send the query because something
+                              // else
+                              // was sending a command or something
       int adv = (result == 200);
       // a result of 200 means the advanced features of, e.g., iTunes, are available
       // so, turn the advanced_dacp_server flag on or off and flag if it's changed.
diff --git a/dacp.h b/dacp.h
index 1a04e01660c7a92c8d6718b6a73ea9171e3858f6..09dd477dbd93cba289b87aa567e9dbf8eae3513e 100644 (file)
--- a/dacp.h
+++ b/dacp.h
@@ -26,6 +26,8 @@ int dacp_get_speaker_list(dacp_spkr_stuff *speaker_array, int max_size_of_array,
 void set_dacp_server_information(rtsp_conn_info *conn); // tell the DACP conversation thread that
                                                         // the dacp server information has been set
                                                         // or changed
+void dacp_monitor_port_update_callback(
+    char *dacp_id, uint16_t port); // a callback to say the port is no longer in use
 int send_simple_dacp_command(const char *command);
 
 int dacp_set_include_speaker_volume(int64_t machine_number, int32_t vo);
diff --git a/mdns.c b/mdns.c
index 0651cdcfe6512c15dc429f99a3a0f5a6376993a2..6634d1d02e544b61063e79f08ea8b707154d1063 100644 (file)
--- a/mdns.c
+++ b/mdns.c
@@ -104,21 +104,23 @@ void mdns_unregister(void) {
   }
 }
 
-void mdns_dacp_monitor(rtsp_conn_info *conn) {
+void *mdns_dacp_monitor(char *dacp_id) {
+  void *reply = NULL;
   if ((config.mdns) && (config.mdns->mdns_dacp_monitor)) {
-    int error = config.mdns->mdns_dacp_monitor(conn);
-    if (error) {
+    reply = config.mdns->mdns_dacp_monitor(dacp_id);
+    if (reply == NULL) {
       debug(1, "Error starting a DACP monitor.");
     }
   } else
-    debug(1, "Can't start a DACP monitor.");
+    debug(1, "Can't start a DACP monitor -- none registered.");
+  return reply;
 }
 
-void mdns_dacp_dont_monitor(rtsp_conn_info *conn) {
+void mdns_dacp_dont_monitor(void *userdata) {
   if ((config.mdns) && (config.mdns->mdns_dacp_dont_monitor)) {
-    config.mdns->mdns_dacp_dont_monitor(conn);
+    config.mdns->mdns_dacp_dont_monitor(userdata);
   } else
-    debug(1, "Can't stop a DACP monitor.");
+    debug(1, "Can't stop a DACP monitor -- none registered.");
 }
 void mdns_ls_backends(void) {
   mdns_backend **b = NULL;
diff --git a/mdns.h b/mdns.h
index e5360e260813f7fb511344aab543eb3ca5ae45bf..9f96a9f7225d34aa2cea7570aa0e676f92132f99 100644 (file)
--- a/mdns.h
+++ b/mdns.h
@@ -9,8 +9,8 @@ extern int mdns_pid;
 
 void mdns_unregister(void);
 void mdns_register(void);
-void mdns_dacp_monitor(rtsp_conn_info *conn);
-void mdns_dacp_dont_monitor(rtsp_conn_info *conn);
+void *mdns_dacp_monitor(char *dacp_id);
+void mdns_dacp_dont_monitor(void *userdata);
 
 void mdns_ls_backends(void);
 
@@ -18,8 +18,8 @@ typedef struct {
   char *name;
   int (*mdns_register)(char *apname, int port);
   void (*mdns_unregister)(void);
-  int (*mdns_dacp_monitor)(rtsp_conn_info *conn);
-  void (*mdns_dacp_dont_monitor)(rtsp_conn_info *conn);
+  void *(*mdns_dacp_monitor)(char *);
+  void (*mdns_dacp_dont_monitor)(void *);
 } mdns_backend;
 
 #ifdef CONFIG_METADATA
index 05bbbe3db3308b0bf2e3f320f37985e4d5c9a5a6..b1f8c31b97dc7d33468940a76a4ce7d88cd9a587 100644 (file)
@@ -51,6 +51,7 @@ typedef struct {
   AvahiThreadedPoll *service_poll;
   AvahiClient *service_client;
   AvahiServiceBrowser *service_browser;
+  char *dacp_id;
 } dacp_browser_struct;
 
 // static AvahiServiceBrowser *sb = NULL;
@@ -72,8 +73,7 @@ static void resolve_callback(AvahiServiceResolver *r, AVAHI_GCC_UNUSED AvahiIfIn
                              __attribute__((unused)) AvahiLookupResultFlags flags, void *userdata) {
   assert(r);
 
-  rtsp_conn_info *conn = (rtsp_conn_info *)userdata;
-  //  dacp_browser_struct *dbs = (dacp_browser_struct *)conn->mdns_private_pointer;
+  dacp_browser_struct *dbs = (dacp_browser_struct *)userdata;
 
   /* Called whenever a service has been resolved successfully or timed out */
   switch (event) {
@@ -87,20 +87,17 @@ static void resolve_callback(AvahiServiceResolver *r, AVAHI_GCC_UNUSED AvahiIfIn
     char *dacpid = strstr(name, "iTunes_Ctrl_");
     if (dacpid) {
       dacpid += strlen("iTunes_Ctrl_");
-      if (strcmp(dacpid, conn->dacp_id) == 0) {
-        if (conn->dacp_port != port) {
-          debug(2, "Client's DACP port: %u.", port);
-          conn->dacp_port = port;
+      if (strcmp(dacpid, dbs->dacp_id) == 0) {
+        debug(3, "Client's DACP port: %u.", port);
 #ifdef HAVE_DACP_CLIENT
-          set_dacp_server_information(conn);
+        dacp_monitor_port_update_callback(dacpid, port);
 #endif
 #ifdef CONFIG_METADATA
-          char portstring[20];
-          memset(portstring, 0, sizeof(portstring));
-          sprintf(portstring, "%u", port);
-          send_ssnc_metadata('dapo', strdup(portstring), strlen(portstring), 0);
+        char portstring[20];
+        memset(portstring, 0, sizeof(portstring));
+        sprintf(portstring, "%u", port);
+        send_ssnc_metadata('dapo', strdup(portstring), strlen(portstring), 0);
 #endif
-        }
       }
     } else {
       debug(1, "Resolve callback: Can't see a DACP string in a DACP Record!");
@@ -113,8 +110,7 @@ static void browse_callback(AvahiServiceBrowser *b, AvahiIfIndex interface, Avah
                             AvahiBrowserEvent event, const char *name, const char *type,
                             const char *domain, AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
                             void *userdata) {
-  rtsp_conn_info *conn = (rtsp_conn_info *)userdata;
-  dacp_browser_struct *dbs = (dacp_browser_struct *)conn->mdns_private_pointer;
+  dacp_browser_struct *dbs = (dacp_browser_struct *)userdata;
   assert(b);
   /* Called whenever a new services becomes available on the LAN or is removed from the LAN */
   switch (event) {
@@ -135,29 +131,17 @@ static void browse_callback(AvahiServiceBrowser *b, AvahiIfIndex interface, Avah
             avahi_strerror(avahi_client_errno(dbs->service_client)));
     break;
   case AVAHI_BROWSER_REMOVE:
-    debug(3, "(Browser) REMOVE: service '%s' of type '%s' in domain '%s'.", name, type, domain);
+    debug(1, "(Browser) REMOVE: service '%s' of type '%s' in domain '%s'.", name, type, domain);
+#ifdef HAVE_DACP_CLIENT
     char *dacpid = strstr(name, "iTunes_Ctrl_");
     if (dacpid) {
       dacpid += strlen("iTunes_Ctrl_");
-      if (strcmp(dacpid, conn->dacp_id) == 0) {
-        if (conn->dacp_id != 0) {
-          debug(3, "Client's DACP status withdrawn.");
-          conn->dacp_port = 0;
-          /*
-          #ifdef HAVE_DACP_CLIENT
-          // this might be in a race condition with another connection that could come into effect
-          before this one has terminated.
-                    set_dacp_server_information(conn); // this will have the effect of telling the
-          scanner
-                                                       // that the DACP server is no longer working
-          #endif
-          */
-        }
-      }
+      if (strcmp(dacpid, dbs->dacp_id) == 0)
+        dacp_monitor_port_update_callback(dbs->dacp_id, 0); // say the port is withdrawn
     } else {
       debug(1, "Browse callback: Can't see a DACP string in a DACP Record!");
     }
-
+#endif
     break;
   case AVAHI_BROWSER_ALL_FOR_NOW:
   case AVAHI_BROWSER_CACHE_EXHAUSTED:
@@ -309,8 +293,7 @@ static void client_callback(AvahiClient *c, AvahiClientState state,
 static void service_client_callback(AvahiClient *c, AvahiClientState state, void *userdata) {
   int err;
 
-  rtsp_conn_info *conn = (rtsp_conn_info *)userdata;
-  dacp_browser_struct *dbs = (dacp_browser_struct *)conn->mdns_private_pointer;
+  dacp_browser_struct *dbs = (dacp_browser_struct *)userdata;
 
   switch (state) {
   case AVAHI_CLIENT_S_REGISTERING:
@@ -390,71 +373,68 @@ static void avahi_unregister(void) {
   service_name = NULL;
 }
 
-int avahi_dacp_monitor(rtsp_conn_info *conn) {
-
+void *avahi_dacp_monitor(char *dacp_id) {
   dacp_browser_struct *dbs = (dacp_browser_struct *)malloc(sizeof(dacp_browser_struct));
 
   if (dbs == NULL)
     die("can not allocate a dacp_browser_struct.");
 
-  conn->mdns_private_pointer = (void *)dbs;
+  char *t = strdup(dacp_id);
+  if (t)
+    dbs->dacp_id = t;
+  else {
+    die("can not allocate a dacp_id string in dacp_browser_struct.");
+  }
 
   // create the threaded poll code
   int err;
   if (!(dbs->service_poll = avahi_threaded_poll_new())) {
     warn("couldn't create avahi threaded service_poll!");
-    if (dbs) {
-      free((char *)dbs);
-    }
-    conn->mdns_private_pointer = NULL;
-    return -1;
+    free(dbs->dacp_id);
+    free((char *)dbs);
+    return NULL;
   }
 
   // create the service client
   if (!(dbs->service_client =
             avahi_client_new(avahi_threaded_poll_get(dbs->service_poll), AVAHI_CLIENT_NO_FAIL,
-                             service_client_callback, (void *)conn, &err))) {
+                             service_client_callback, (void *)dbs, &err))) {
     warn("couldn't create avahi service client: %s!", avahi_strerror(err));
-    if (dbs) { // should free the threaded poll code
-      avahi_threaded_poll_free(dbs->service_poll);
-      free((char *)dbs);
-    }
-    conn->mdns_private_pointer = NULL;
-    return -1;
+    avahi_threaded_poll_free(dbs->service_poll);
+    free(dbs->dacp_id);
+    free((char *)dbs);
+    return NULL;
   }
 
   /* Create the service browser */
   if (!(dbs->service_browser =
             avahi_service_browser_new(dbs->service_client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
-                                      "_dacp._tcp", NULL, 0, browse_callback, (void *)conn))) {
+                                      "_dacp._tcp", NULL, 0, browse_callback, (void *)dbs))) {
     warn("Failed to create service browser: %s\n",
          avahi_strerror(avahi_client_errno(dbs->service_client)));
-    if (dbs) { // should free the threaded poll code and the service client
-      avahi_client_free(dbs->service_client);
-      avahi_threaded_poll_free(dbs->service_poll);
-      free((char *)dbs);
-    }
-    conn->mdns_private_pointer = NULL;
-    return -1;
+    avahi_client_free(dbs->service_client);
+    avahi_threaded_poll_free(dbs->service_poll);
+    free(dbs->dacp_id);
+    free((char *)dbs);
+    return NULL;
   }
   // start the polling thread
   if (avahi_threaded_poll_start(dbs->service_poll) < 0) {
     warn("couldn't start avahi service_poll thread");
-    if (dbs) { // should free the threaded poll code and the service client and the service browser
-      avahi_service_browser_free(dbs->service_browser);
-      avahi_client_free(dbs->service_client);
-      avahi_threaded_poll_free(dbs->service_poll);
-      free((char *)dbs);
-    }
-    conn->mdns_private_pointer = NULL;
-    return -1;
+    avahi_service_browser_free(dbs->service_browser);
+    avahi_client_free(dbs->service_client);
+    avahi_threaded_poll_free(dbs->service_poll);
+    free(dbs->dacp_id);
+    free((char *)dbs);
+    return NULL;
   }
-  return 0;
+  debug(3, "DACP monitor successfully started");
+  return (void *)dbs;
 }
 
-void avahi_dacp_dont_monitor(rtsp_conn_info *conn) {
-  dacp_browser_struct *dbs = (dacp_browser_struct *)conn->mdns_private_pointer;
-  if (dbs) {
+void avahi_dacp_dont_monitor(void *userdata) {
+  if (userdata) {
+    dacp_browser_struct *dbs = (dacp_browser_struct *)userdata;
     // stop and dispose of everything
     if ((dbs)->service_poll)
       avahi_threaded_poll_stop((dbs)->service_poll);
@@ -464,8 +444,9 @@ void avahi_dacp_dont_monitor(rtsp_conn_info *conn) {
       avahi_client_free((dbs)->service_client);
     if ((dbs)->service_poll)
       avahi_threaded_poll_free((dbs)->service_poll);
+    free(dbs->dacp_id);
     free((char *)(dbs));
-    conn->mdns_private_pointer = NULL;
+    debug(3, "DACP monitor successfully stopped");
   } else {
     debug(1, "DHCP Monitor is not running.");
   }
index 3f912cf0c864bda935155201091a84a73b15e690..049ec0fa4bdd1d210efa2174635ca539b31dc514 100644 (file)
@@ -87,9 +87,9 @@ void metadata_hub_modify_prolog(void) {
   // always run this before changing an entry or a sequence of entries in the metadata_hub
   // debug(1, "locking metadata hub for writing");
   if (pthread_rwlock_trywrlock(&metadata_hub_re_lock) != 0) {
-    debug(1, "Metadata_hub write lock is already taken -- must wait.");
+    debug(2, "Metadata_hub write lock is already taken -- must wait.");
     pthread_rwlock_wrlock(&metadata_hub_re_lock);
-    debug(1, "Okay -- acquired the metadata_hub write lock.");
+    debug(2, "Okay -- acquired the metadata_hub write lock.");
   }
 }
 
index 3e36940d71d94ab4f8d205b8c5832dfacbf57723..6e3f533d81b4a8269e63e2764be3268bd1459e4e 100644 (file)
--- a/player.c
+++ b/player.c
@@ -277,7 +277,7 @@ static int alac_decode(short *dest, int *destlen, uint8_t *buf, int len, rtsp_co
 #ifdef HAVE_APPLE_ALAC
     if (config.use_apple_decoder) {
       if (conn->decoder_in_use != 1 << decoder_apple_alac) {
-        debug(1, "Apple ALAC Decoder used on encrypted audio.");
+        debug(2, "Apple ALAC Decoder used on encrypted audio.");
         conn->decoder_in_use = 1 << decoder_apple_alac;
       }
       apple_alac_decode_frame(packet, len, (unsigned char *)dest, &outsize);
@@ -286,7 +286,7 @@ static int alac_decode(short *dest, int *destlen, uint8_t *buf, int len, rtsp_co
 #endif
     {
       if (conn->decoder_in_use != 1 << decoder_hammerton) {
-        debug(1, "Hammerton Decoder used on encrypted audio.");
+        debug(2, "Hammerton Decoder used on encrypted audio.");
         conn->decoder_in_use = 1 << decoder_hammerton;
       }
       alac_decode_frame(conn->decoder_info, packet, (unsigned char *)dest, &outsize);
@@ -296,7 +296,7 @@ static int alac_decode(short *dest, int *destlen, uint8_t *buf, int len, rtsp_co
 #ifdef HAVE_APPLE_ALAC
     if (config.use_apple_decoder) {
       if (conn->decoder_in_use != 1 << decoder_apple_alac) {
-        debug(1, "Apple ALAC Decoder used on unencrypted audio.");
+        debug(2, "Apple ALAC Decoder used on unencrypted audio.");
         conn->decoder_in_use = 1 << decoder_apple_alac;
       }
       apple_alac_decode_frame(buf, len, (unsigned char *)dest, &outsize);
@@ -305,7 +305,7 @@ static int alac_decode(short *dest, int *destlen, uint8_t *buf, int len, rtsp_co
 #endif
     {
       if (conn->decoder_in_use != 1 << decoder_hammerton) {
-        debug(1, "Hammerton Decoder used on unencrypted audio.");
+        debug(2, "Hammerton Decoder used on unencrypted audio.");
         conn->decoder_in_use = 1 << decoder_hammerton;
       }
       alac_decode_frame(conn->decoder_info, buf, dest, &outsize);
@@ -824,13 +824,7 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
           reference_timestamp *= conn->output_sample_ratio;
           if (conn->first_packet_timestamp == 0) { // if this is the very first packet
                                                    // debug(1,"First frame seen, time %u, with %d
-// frames...",curframe->timestamp,seq_diff(ab_read, ab_write));
-
-// say we have started playing here
-#ifdef CONFIG_METADATA
-            send_ssnc_metadata('pffr', NULL, 0,
-                               0); // "first frame received", but don't wait if the queue is locked
-#endif
+            // frames...",curframe->timestamp,seq_diff(ab_read, ab_write));
 
             if (reference_timestamp) { // if we have a reference time
               // debug(1,"First frame seen with timestamp...");
@@ -839,6 +833,13 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
                                        // supposed to start playing this
               have_sent_prefiller_silence = 0;
 
+// say we have started playing here
+#ifdef CONFIG_METADATA
+              debug(1, "pffr");
+              send_ssnc_metadata(
+                  'pffr', NULL, 0,
+                  0); // "first frame received", but don't wait if the queue is locked
+#endif
               // Here, calculate when we should start playing. We need to know when to allow the
               // packets to be sent to the player.
               // We will send packets of silence from now until that time and then we will send the
@@ -1059,6 +1060,7 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
                                           &conn->play_segment_reference_frame_remote_time, conn);
             conn->play_segment_reference_frame *= conn->output_sample_ratio;
 #ifdef CONFIG_METADATA
+            debug(1, "prsm");
             send_ssnc_metadata('prsm', NULL, 0,
                                0); // "resume", but don't wait if the queue is locked
 #endif
@@ -1384,9 +1386,9 @@ static void *player_thread_func(void *arg) {
   conn->fix_volume = 0x10000;
 
   if (conn->latency == 0) {
-    debug(1,
-          "No latency has (yet) been specified. Setting 99225 (2.25 seconds) frames as a default.");
-    conn->latency = 99225;
+    debug(3, "No latency has (yet) been specified. Setting 99,226 (2.25 seconds + 1 frame) frames "
+             "as a default.");
+    conn->latency = 99226;
   }
 
   int rc = pthread_mutex_init(&conn->ab_mutex, NULL);
@@ -1463,7 +1465,7 @@ static void *player_thread_func(void *arg) {
     conn->output_bytes_per_frame = 4;
   }
 
-  debug(1, "Output frame bytes is %d.", conn->output_bytes_per_frame);
+  debug(3, "Output frame bytes is %d.", conn->output_bytes_per_frame);
 
   // create and start the timing, control and audio receiver threads
   pthread_t rtp_audio_thread, rtp_control_thread, rtp_timing_thread;
@@ -1548,7 +1550,7 @@ static void *player_thread_func(void *arg) {
     die("Unknown format choosing output bit depth");
   }
 
-  debug(1, "Output bit depth is %d.", output_bit_depth);
+  debug(3, "Output bit depth is %d.", output_bit_depth);
 
   if (conn->input_bit_depth > output_bit_depth) {
     debug(1, "Dithering will be enabled because the input bit depth is greater than the output bit "
@@ -1601,11 +1603,12 @@ static void *player_thread_func(void *arg) {
 #ifdef HAVE_DACP_CLIENT
   set_dacp_server_information(conn); // this will start scanning when a port is registered by the
                                      // code initiated by the mdns_dacp_monitor
-#endif
+#else
+  // this is only used for compatability, if dacp stuff isn't enabled.
   // start an mdns/zeroconf thread to look for DACP messages containing our DACP_ID and getting the
   // port number
-  // mdns_dacp_monitor(conn->dacp_id, &conn->dacp_port, &conn->dacp_private);
-  mdns_dacp_monitor(conn);
+  conn->dapo_private_storage = mdns_dacp_monitor(conn->dacp_id);
+#endif
 
   conn->framesProcessedInThisEpoch = 0;
   conn->framesGeneratedInThisEpoch = 0;
@@ -2223,10 +2226,11 @@ static void *player_thread_func(void *arg) {
            elapsedSec);
   }
 
+#ifndef HAVE_DACP_CLIENT
   // stop watching for DACP port number stuff
-  mdns_dacp_dont_monitor(conn); // begin looking out for information about the client
-                                // as a remote control. Specifically we might need
-                                // the port number
+  // this is only used for compatability, if dacp stuff isn't enabled.
+  mdns_dacp_dont_monitor(conn->dapo_private_storage);
+#endif
 
   if (config.output->stop)
     config.output->stop();
@@ -2525,7 +2529,12 @@ void player_flush(int64_t timestamp, rtsp_conn_info *conn) {
   conn->play_segment_reference_frame = 0;
   conn->play_number_after_flush = 0;
 #ifdef CONFIG_METADATA
-  send_ssnc_metadata('pfls', NULL, 0, 1);
+  // only send a flush metadata message if the first packet has been seen -- it's a bogus message
+  // otherwise
+  if (conn->first_packet_timestamp) {
+    debug(1, "pfls");
+    send_ssnc_metadata('pfls', NULL, 0, 1);
+  }
 #endif
 }
 
@@ -2538,6 +2547,7 @@ int player_play(rtsp_conn_info *conn) {
         BUFFER_FRAMES);
   command_start();
 #ifdef CONFIG_METADATA
+  debug(1, "pbeg");
   send_ssnc_metadata('pbeg', NULL, 0, 1);
 #endif
   pthread_t *pt = malloc(sizeof(pthread_t));
@@ -2562,6 +2572,7 @@ void player_stop(rtsp_conn_info *conn) {
     pthread_kill(*conn->player_thread, SIGUSR1);
     pthread_join(*conn->player_thread, NULL);
 #ifdef CONFIG_METADATA
+    debug(1, "pend");
     send_ssnc_metadata('pend', NULL, 0, 1);
 #endif
     command_stop();
index a4dcfe4a5d2212b40a7d00cd53bea89850946bc4..a6deb7c8014eddc7c0a483fb0e2dba7ce10d6fdd 100644 (file)
--- a/player.h
+++ b/player.h
@@ -173,11 +173,11 @@ typedef struct {
   // mdns to find it.
   // at present, only avahi can do this
 
-  char *dacp_id;               // id of the client -- used to find the port to be used
-  uint16_t dacp_port;          // port on the client to send remote control messages to, else zero
+  char *dacp_id; // id of the client -- used to find the port to be used
+  //  uint16_t dacp_port;          // port on the client to send remote control messages to, else
+  //  zero
   uint32_t dacp_active_remote; // key to send to the remote controller
-  void *mdns_private_pointer;  // private storage (just a pointer) for the dacp_port resolver
-
+  void *dapo_private_storage;  // this is used for compatibility, if dacp stuff isn't enabled.
 } rtsp_conn_info;
 
 int player_play(rtsp_conn_info *conn);
diff --git a/rtp.c b/rtp.c
index ec3f2fc8cf75a1e9695d2b6c9f5e02ba0cdfe654..03002fa727c85609d376c0c83bf7fc27f80f8d77 100644 (file)
--- a/rtp.c
+++ b/rtp.c
@@ -42,6 +42,7 @@
 #include "common.h"
 #include "player.h"
 #include "rtp.h"
+#include "rtsp.h"
 
 uint64_t local_to_remote_time_jitters;
 uint64_t local_to_remote_time_jitters_count;
@@ -246,10 +247,10 @@ void *rtp_control_receiver(void *arg) {
 
           if (la != conn->latency) {
             conn->latency = la;
-            debug(1, "New latency: %lld, sync latency: %lld, minimum latency: %lld, maximum "
-                     "latency: %lld, fixed offset: %lld.",
-                  la, sync_rtp_timestamp - rtp_timestamp_less_latency, conn->minimum_latency,
-                  conn->maximum_latency, config.fixedLatencyOffset);
+            // debug(1, "New latency: %lld, sync latency: %lld, minimum latency: %lld, maximum "
+            //         "latency: %lld, fixed offset: %lld.",
+            //      la, sync_rtp_timestamp - rtp_timestamp_less_latency, conn->minimum_latency,
+            //      conn->maximum_latency, config.fixedLatencyOffset);
           }
         }
 
@@ -799,6 +800,11 @@ void rtp_setup(SOCKADDR *local, SOCKADDR *remote, int cport, int tport, int *lsp
 
   conn->request_sent = 0;
   conn->rtp_running = 1;
+
+#ifdef CONFIG_METADATA
+  send_ssnc_metadata('clip', strdup(conn->client_ip_string), strlen(conn->client_ip_string), 1);
+  send_ssnc_metadata('svip', strdup(conn->self_ip_string), strlen(conn->self_ip_string), 1);
+#endif
 }
 
 void get_reference_timestamp_stuff(int64_t *timestamp, uint64_t *timestamp_time,
diff --git a/rtsp.c b/rtsp.c
index 530fdbfa47a90a99ac9ae35f762b02d4f2060b60..ca6e48d410d7b5e3e70f30d55ac6dd8e12265318 100644 (file)
--- a/rtsp.c
+++ b/rtsp.c
@@ -768,7 +768,7 @@ static void handle_setup(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *
 
   char *ar = msg_get_header(req, "Active-Remote");
   if (ar) {
-    debug(1, "Active-Remote string seen: \"%s\".", ar);
+    debug(2, "Active-Remote string seen: \"%s\".", ar);
     // get the active remote
     char *p;
     conn->dacp_active_remote = strtoul(ar, &p, 10);
@@ -779,7 +779,7 @@ static void handle_setup(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *
 
   ar = msg_get_header(req, "DACP-ID");
   if (ar) {
-    debug(1, "DACP-ID string seen: \"%s\".", ar);
+    debug(2, "DACP-ID string seen: \"%s\".", ar);
     conn->dacp_id = strdup(ar);
 #ifdef CONFIG_METADATA
     send_metadata('ssnc', 'daid', ar, strlen(ar), req, 1);
@@ -915,7 +915,7 @@ static void handle_set_parameter_parameter(rtsp_conn_info *conn, rtsp_message *r
 //    'pfls' -- play stream flush. No arguments
 //    'prsm' -- play stream resume. No arguments
 //             `pffr` -- the first frame of a play session has been received and has been validly
-//timed.
+// timed.
 //    'pvol' -- play volume. The volume is sent as a string --
 //    "airplay_volume,volume,lowest_volume,highest_volume"
 //              volume, lowest_volume and highest_volume are given in dB.
@@ -1579,7 +1579,7 @@ static void handle_announce(rtsp_conn_info *conn, rtsp_message *req, rtsp_messag
     }
     hdr = msg_get_header(req, "User-Agent");
     if (hdr) {
-      debug(1, "Play connection from user agent \"%s\" on RTSP conversation thread %d.", hdr,
+      debug(2, "Play connection from user agent \"%s\" on RTSP conversation thread %d.", hdr,
             conn->connection_number);
 #ifdef CONFIG_METADATA
       send_metadata('ssnc', 'snua', hdr, strlen(hdr), req, 1);
@@ -2118,11 +2118,7 @@ void rtsp_listen_loop(void) {
           sa = (struct sockaddr_in *)&conn->remote;
           inet_ntop(AF_INET, &(sa->sin_addr), remote_ip4, INET_ADDRSTRLEN);
           unsigned short int rport = ntohs(sa->sin_port);
-#ifdef CONFIG_METADATA
-          send_ssnc_metadata('clip', strdup(remote_ip4), strlen(remote_ip4), 1);
-          send_ssnc_metadata('svip', strdup(ip4), strlen(ip4), 1);
-#endif
-          debug(1, "New RTSP connection from %s:%u to self at %s:%u on conversation thread %d.",
+          debug(2, "New RTSP connection from %s:%u to self at %s:%u on conversation thread %d.",
                 remote_ip4, rport, ip4, tport, conn->connection_number);
         }
 #ifdef AF_INET6
@@ -2139,11 +2135,7 @@ void rtsp_listen_loop(void) {
           sa6 = (struct sockaddr_in6 *)&conn->remote; // pretend this is loaded with something
           inet_ntop(AF_INET6, &(sa6->sin6_addr), remote_ip6, INET6_ADDRSTRLEN);
           u_int16_t rport = ntohs(sa6->sin6_port);
-#ifdef CONFIG_METADATA
-          send_ssnc_metadata('clip', strdup(remote_ip6), strlen(remote_ip6), 1);
-          send_ssnc_metadata('svip', strdup(ip6), strlen(ip6), 1);
-#endif
-          debug(1, "New RTSP connection from [%s]:%u to self at [%s]:%u on conversation thread %d.",
+          debug(2, "New RTSP connection from [%s]:%u to self at [%s]:%u on conversation thread %d.",
                 remote_ip6, rport, ip6, tport, conn->connection_number);
         }
 #endif