]> git.ipfire.org Git - thirdparty/shairport-sync.git/commitdiff
hooking up a dacp scanner
authorMike Brady <mikebrady@eircom.net>
Sat, 2 Dec 2017 19:52:39 +0000 (19:52 +0000)
committerMike Brady <mikebrady@eircom.net>
Sat, 2 Dec 2017 19:52:39 +0000 (19:52 +0000)
common.h
dacp.c
dacp.h
definitions.h [new file with mode: 0644]
mdns_avahi.c
player.h
shairport.c

index 719ff702c80e1369dd9d41fcc9c56c200785e106..82ff60f707b9af98fd34dc1530eb007cccaaba75 100644 (file)
--- a/common.h
+++ b/common.h
@@ -8,6 +8,7 @@
 
 #include "audio.h"
 #include "config.h"
+#include "definitions.h"
 #include "mdns.h"
 
 #if defined(__APPLE__) && defined(__MACH__)
diff --git a/dacp.c b/dacp.c
index 9a916ce9740b4bab569e00cf923b62fd85ebcc84..2dcd5fdf46c0496063397c2affd00fbdd570d727 100644 (file)
--- a/dacp.c
+++ b/dacp.c
 #include <time.h>
 #include <unistd.h>
 
-uint16_t dacp_port;
+typedef struct  {
+  uint16_t port;
+  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
+} dacp_server_record;
+
 pthread_t dacp_monitor_thread;
+dacp_server_record dacp_server;
 
 static pthread_mutex_t dacp_conversation_lock = PTHREAD_MUTEX_INITIALIZER;
 static pthread_mutex_t dacp_server_information_lock = PTHREAD_MUTEX_INITIALIZER;
 static pthread_cond_t dacp_server_information_cv = PTHREAD_COND_INITIALIZER;
 
 // this will be running on the thread of its caller, not of the conversation thread...
-void set_dacp_port(
-    uint16_t port) { // tell the DACP conversation thread that the port has been set or changed
-  pthread_mutex_lock(&dacp_server_information_lock);
-  dacp_port = port;
-  pthread_cond_signal(&dacp_server_information_cv);
-  pthread_mutex_unlock(&dacp_server_information_lock);
-}
-
-// this will be running on the thread of its caller, not of the conversation thread...
-void unset_dacp_port() { // tell the DACP conversation thread that that port has gone offline.
+void set_dacp_server_information(rtsp_conn_info* conn) { // tell the DACP conversation thread that the port has been set or changed
   pthread_mutex_lock(&dacp_server_information_lock);
-  dacp_port = 0;
+  
+  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;
+  
   pthread_cond_signal(&dacp_server_information_cv);
   pthread_mutex_unlock(&dacp_server_information_lock);
 }
 
 void *dacp_monitor_thread_code(void *na) {
+  int scan_index = 0;
+  debug(1, "DACP monitor thread started.");
   // wait until we get a valid port number to begin monitoring it
   while (1) {
     pthread_mutex_lock(&dacp_server_information_lock);
-    while (dacp_port == 0)
+    while (dacp_server.port == 0) {
+      debug(1,"Wait for a valid DACP port");
       pthread_cond_wait(&dacp_server_information_cv, &dacp_server_information_lock);
+    }
     pthread_mutex_unlock(&dacp_server_information_lock);
-    debug(1, "DACP Monitor Thread active now.");
+    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++);
     sleep(3);
   }
+  debug(1, "DACP monitor thread exiting.");
   pthread_exit(NULL);
 }
 
 void dacp_monitor_start() {
+  memset(&dacp_server,0,sizeof(dacp_server_record));
   pthread_create(&dacp_monitor_thread, NULL, dacp_monitor_thread_code, NULL);
 }
 
diff --git a/dacp.h b/dacp.h
index a7bdebe2d1c676fc9d92f51ab6ab949844a8b2a8..493a6932a58a383875fa07588ddbf166727a9fd8 100644 (file)
--- a/dacp.h
+++ b/dacp.h
@@ -17,6 +17,8 @@ typedef struct dacp_speaker_stuff {
   char *name; // this is really just for debugging
 } dacp_spkr_stuff;
 
+void dacp_monitor_start();
+
 uint32_t dacp_tlv_crawl(
     char **p,
     int32_t *length); // return the code of the next TLV entity and advance the pointer beyond it.
@@ -27,5 +29,5 @@ int dacp_set_include_speaker_volume(rtsp_conn_info *conn, int64_t machine_number
 int dacp_set_speaker_volume(rtsp_conn_info *conn, int64_t machine_number, int32_t vo);
 int dacp_get_speaker_list(rtsp_conn_info *conn, dacp_spkr_stuff *speaker_array,
                           int max_size_of_array);
-void set_dacp_port(uint16_t port); // tell the DACP conversation thread that the port has been set or changed
-void unset_dacp_port(); // tell the DACP conversation thread that that port has gone offline.
+void set_dacp_server_information(rtsp_conn_info* conn); // tell the DACP conversation thread that the dacp server information has been set or changed
+
diff --git a/definitions.h b/definitions.h
new file mode 100644 (file)
index 0000000..5fe42b4
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef _DEFINITIONS_H
+#define _DEFINITIONS_H
+
+//#include <libconfig.h>
+//#include <signal.h>
+//#include <stdint.h>
+#include <sys/socket.h>
+
+//#include "audio.h"
+#include "config.h"
+//#include "mdns.h"
+
+#if defined(__APPLE__) && defined(__MACH__)
+/* Apple OSX and iOS (Darwin). ------------------------------ */
+#include <TargetConditionals.h>
+#if TARGET_OS_MAC == 1
+/* OSX */
+#define COMPILE_FOR_OSX 1
+#endif
+#endif
+
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__CYGWIN__)
+/* Linux and FreeBSD */
+#define COMPILE_FOR_LINUX_AND_FREEBSD_AND_CYGWIN 1
+#endif
+
+// struct sockaddr_in6 is bigger than struct sockaddr. derp
+#ifdef AF_INET6
+#define SOCKADDR struct sockaddr_storage
+#define SAFAMILY ss_family
+#else
+#define SOCKADDR struct sockaddr
+#define SAFAMILY sa_family
+#endif
+
+
+#endif // _DEFINITIONS_H
index cb99f462c496e4e99f50155a01c364f01d1d23bc..a506d4918cb7f8128c20cb8a17b77e6f6ff1fe7f 100644 (file)
@@ -49,8 +49,6 @@ typedef struct {
   AvahiThreadedPoll *service_poll;
   AvahiClient *service_client;
   AvahiServiceBrowser *service_browser;
-  char *dacp_id;
-  uint16_t *dacp_port;
 } dacp_browser_struct;
 
 // static AvahiServiceBrowser *sb = NULL;
@@ -69,8 +67,9 @@ static void resolve_callback(AvahiServiceResolver *r, AVAHI_GCC_UNUSED AvahiIfIn
                              const char *host_name, const AvahiAddress *address, uint16_t port,
                              AvahiStringList *txt, AvahiLookupResultFlags flags, void *userdata) {
   assert(r);
-
-  dacp_browser_struct *dbs = (dacp_browser_struct *)userdata;
+  
+  rtsp_conn_info *conn = (rtsp_conn_info *)userdata;
+  dacp_browser_struct *dbs = (dacp_browser_struct *)conn->mdns_private_pointer;
 
   /* Called whenever a service has been resolved successfully or timed out */
   switch (event) {
@@ -84,12 +83,13 @@ 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, dbs->dacp_id) == 0) {
-        uint16_t *p = dbs->dacp_port;
-        if (*p != port) {
+      if (strcmp(dacpid, conn->dacp_id) == 0) {
+        if (conn->dacp_port != port) {
           debug(1, "Client's DACP port: %u.", port);
-          *p = port;
-          set_dacp_port(port);
+          conn->dacp_port = port;
+#if defined(HAVE_DBUS) || defined(HAVE_MPRIS)
+          set_dacp_server_information(conn);
+#endif
 #ifdef CONFIG_METADATA
           char portstring[20];
           memset(portstring, 0, sizeof(portstring));
@@ -109,7 +109,8 @@ 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) {
-  dacp_browser_struct *dbs = (dacp_browser_struct *)userdata;
+  rtsp_conn_info *conn = (rtsp_conn_info *)userdata;
+  dacp_browser_struct *dbs = (dacp_browser_struct *)conn->mdns_private_pointer;
   assert(b);
   /* Called whenever a new services becomes available on the LAN or is removed from the LAN */
   switch (event) {
@@ -134,12 +135,13 @@ static void browse_callback(AvahiServiceBrowser *b, AvahiIfIndex interface, Avah
     char *dacpid = strstr(name, "iTunes_Ctrl_");
     if (dacpid) {
       dacpid += strlen("iTunes_Ctrl_");
-      if (strcmp(dacpid, dbs->dacp_id) == 0) {
-        uint16_t *p = dbs->dacp_port;
-        if (*p != 0) {
+      if (strcmp(dacpid, conn->dacp_id) == 0) {
+        if (conn->dacp_id != 0) {
           debug(1, "Client's DACP status withdrawn.");
-          *p = 0;
-          unset_dacp_port();
+          conn->dacp_id = 0;
+#if defined(HAVE_DBUS) || defined(HAVE_MPRIS)          
+          set_dacp_server_information(conn); // this will have the effect of telling the scanner that the DACP server is no longer working
+#endif
         }
       }
     } else {
@@ -297,7 +299,8 @@ static void client_callback(AvahiClient *c, AvahiClientState state,
 static void service_client_callback(AvahiClient *c, AvahiClientState state, void *userdata) {
   int err;
 
-  dacp_browser_struct *dbs = (dacp_browser_struct *)userdata;
+  rtsp_conn_info *conn = (rtsp_conn_info *)userdata;
+  dacp_browser_struct *dbs = (dacp_browser_struct *)conn->mdns_private_pointer;
 
   switch (state) {
   case AVAHI_CLIENT_S_REGISTERING:
@@ -380,12 +383,12 @@ static void avahi_unregister(void) {
 int avahi_dacp_monitor(rtsp_conn_info *conn) {
 
   dacp_browser_struct *dbs = (dacp_browser_struct *)malloc(sizeof(dacp_browser_struct));
+  
 
   if (dbs == NULL)
     die("can not allocate a dacp_browser_struct.");
-
-  dbs->dacp_id = dacp_id;
-  dbs->dacp_port = port;
+    
+  conn->mdns_private_pointer = (void *)dbs;
 
   // create the threaded poll code
   int err;
@@ -394,25 +397,27 @@ int avahi_dacp_monitor(rtsp_conn_info *conn) {
     if (dbs) {
       free((char *)dbs);
     }
+    conn->mdns_private_pointer = NULL;
     return -1;
   }
 
   // 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 *)dbs, &err))) {
+                             service_client_callback, (void *)conn, &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;
   }
 
   /* 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 *)dbs))) {
+                                      "_dacp._tcp", NULL, 0, browse_callback, (void *)conn))) {
     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
@@ -420,6 +425,7 @@ int avahi_dacp_monitor(rtsp_conn_info *conn) {
       avahi_threaded_poll_free(dbs->service_poll);
       free((char *)dbs);
     }
+    conn->mdns_private_pointer = NULL;
     return -1;
   }
   // start the polling thread
@@ -431,9 +437,9 @@ int avahi_dacp_monitor(rtsp_conn_info *conn) {
       avahi_threaded_poll_free(dbs->service_poll);
       free((char *)dbs);
     }
+    conn->mdns_private_pointer = NULL;
     return -1;
   }
-  conn->mdns_private_pointer = (void *)dbs;
   return 0;
 }
 
index b0e923eaf71452878a156d90ffc4f6f68d5b0347..6ee4f4d0565fa97c01d627ae95c83b0082e30556 100644 (file)
--- a/player.h
+++ b/player.h
@@ -5,6 +5,7 @@
 #include <pthread.h>
 
 #include "config.h"
+#include "definitions.h"
 
 #ifdef HAVE_LIBMBEDTLS
 #include <mbedtls/aes.h>
@@ -183,7 +184,7 @@ typedef struct {
   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 *dacp_private;          // private storage (just a pointer) for the dacp_port resolver
+  void *mdns_private_pointer;  // private storage (just a pointer) for the dacp_port resolver
 
 } rtsp_conn_info;
 
index b2a94649616db951764a13aaface71fb0e0fe7d9..1d3602e7d6a7b7053773373395fec27a75c58729 100644 (file)
 #include <glib.h>
 #endif
 
+#if defined(HAVE_DBUS) || defined(HAVE_MPRIS)
+#include "dacp.h"
+#endif
+
 #ifdef HAVE_DBUS
 #include "dbus-service.h"
 #endif
@@ -1065,7 +1069,7 @@ const char *pid_file_proc(void) {
 }
 
 void exit_function() {
-  debug(1, "exit function called...");
+  // debug(1, "exit function called...");
   if (config.cfg)
     config_destroy(config.cfg);
   if (config.appName)
@@ -1534,6 +1538,11 @@ int main(int argc, char **argv) {
   metadata_init(); // create the metadata pipe if necessary
 #endif
 
+#if defined(HAVE_DBUS) || defined(HAVE_MPRIS)
+  debug(1,"Requesting DACP Monitor");
+  dacp_monitor_start();
+#endif
+
 #if defined(HAVE_DBUS) || defined(HAVE_MPRIS)
   // Start up DBUS services after initial settings are all made
   debug(1, "Starting up D-Bus services");