]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
osx: introduce bonjour support 411/head
authorDamjan Marion <damjan.marion@gmail.com>
Fri, 30 May 2014 22:47:17 +0000 (00:47 +0200)
committerDamjan Marion <damjan.marion@gmail.com>
Sun, 1 Jun 2014 14:21:25 +0000 (16:21 +0200)
Makefile
configure
src/bonjour.c [new file with mode: 0644]
src/bonjour.h [new file with mode: 0644]
src/main.c

index adfaa409dab76e492ac456972a2474380a551155..2d7cee8335e942a19225de27e86bd73b4d32937c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -36,7 +36,9 @@ LDFLAGS += -ldl -lpthread -lm
 ifeq ($(CONFIG_LIBICONV),yes)
 LDFLAGS += -liconv
 endif
-ifneq ($(PLATFORM), darwin)
+ifeq ($(PLATFORM), darwin)
+LDFLAGS += -framework CoreServices
+else
 LDFLAGS += -lrt
 endif
 
@@ -261,6 +263,9 @@ SRCS-${CONFIG_INOTIFY} += \
 # Avahi
 SRCS-$(CONFIG_AVAHI) += src/avahi.c
 
+# Bonjour
+SRCS-$(CONFIG_BONJOUR) += src/bonjour.c
+
 # libav
 SRCS-$(CONFIG_LIBAV) += src/libav.c \
        src/muxer/muxer_libav.c \
index a637379f1c6c3ce97a172b8b84b13d063df13cbd..e125992d8e0f90f1826eff1a799cf3d4767c3de2 100755 (executable)
--- a/configure
+++ b/configure
@@ -172,6 +172,8 @@ fi
 #
 if [ ${PLATFORM} = "darwin" ]; then
   disable linuxdvb
+  disable avahi
+  enable bonjour
 fi
 
 #
diff --git a/src/bonjour.c b/src/bonjour.c
new file mode 100644 (file)
index 0000000..b9e0205
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ *  Bonjour service publisher
+ *  Copyright (C) 2014 Damjan Marion
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "tvheadend.h"
+#include "bonjour.h"
+
+#include <CoreServices/CoreServices.h>
+
+typedef struct {
+  char *key;
+  char *value;
+} txt_rec_t;
+
+pthread_t bonjour_tid;
+CFNetServiceRef svc_http, svc_htsp;
+
+static void
+bonjour_callback(CFNetServiceRef theService, CFStreamError* error, void* info)
+{  
+  if (error->error) {
+    tvhlog(LOG_ERR, "bonjour", "callback error (domain = %ld, error =%d)",
+           error->domain, error->error);   
+  } 
+}
+
+static void
+bonjour_start_service(CFNetServiceRef *svc, char *service_type,
+                      uint32_t port, txt_rec_t *txt)
+{
+  CFStringRef str;
+  CFStreamError error = {0};
+  CFNetServiceClientContext context = {0, NULL, NULL, NULL, NULL};
+  
+  str = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, service_type,
+                                        kCFStringEncodingASCII,
+                                        kCFAllocatorNull);
+
+  *svc = CFNetServiceCreate(NULL, CFSTR(""), str, CFSTR("Tvheadend"), port);
+  if (!*svc) {
+    tvhlog(LOG_ERR, "bonjour", "service creation failed"); 
+    return;
+  }
+
+  CFNetServiceSetClient(*svc, bonjour_callback, &context);
+  CFNetServiceScheduleWithRunLoop(*svc, CFRunLoopGetCurrent(),
+                                  kCFRunLoopCommonModes);
+
+  if (txt) {
+    CFDataRef data = NULL;
+    CFMutableDictionaryRef dict;
+    dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks,
+                                     &kCFTypeDictionaryValueCallBacks);
+    
+    while(txt->key) {
+      str = CFStringCreateWithCString (NULL, txt->key, kCFStringEncodingASCII);
+      data = CFDataCreate (NULL, (uint8_t *) txt->value, strlen(txt->value));
+      CFDictionaryAddValue(dict, str, data);
+      txt++;
+    }
+    
+    data = CFNetServiceCreateTXTDataWithDictionary(NULL, dict);
+    CFNetServiceSetTXTData(*svc, data);
+    CFRelease(data);
+    CFRelease(dict);
+  }
+
+  if (!CFNetServiceRegisterWithOptions(*svc, 0, &error))
+    tvhlog(LOG_ERR, "bonjour", "registration failed (service type = %s, "
+           "domain = %ld, error =%d)", service_type, error.domain, error.error); 
+  else
+    tvhlog(LOG_INFO, "bonjour", "service '%s' successfully established",
+           service_type);
+}
+
+static void
+bonjour_stop_service(CFNetServiceRef *svc)
+{
+  CFNetServiceUnscheduleFromRunLoop(*svc, CFRunLoopGetCurrent(), 
+                                    kCFRunLoopCommonModes);
+  CFNetServiceSetClient(*svc, NULL, NULL);  
+  CFRelease(*svc);
+}
+
+void
+bonjour_init(void)
+{
+  txt_rec_t txt_rec_http[] = {
+    { "path", "/" },
+    { .key = NULL }
+  };
+  
+  bonjour_start_service(&svc_http, "_http._tcp", 9981, txt_rec_http);
+  bonjour_start_service(&svc_htsp, "_htsp._tcp", 9982, NULL);
+}
+
+void
+bonjour_done(void)
+{
+  bonjour_stop_service(&svc_http);
+  bonjour_stop_service(&svc_htsp);
+}
diff --git a/src/bonjour.h b/src/bonjour.h
new file mode 100644 (file)
index 0000000..0e20c5f
--- /dev/null
@@ -0,0 +1,7 @@
+#ifdef CONFIG_BONJOUR
+void bonjour_init(void);
+void bonjour_done(void);
+#else
+static inline void bonjour_init(void) { }
+static inline void bonjour_done(void) { }
+#endif
index 0eda2218f2c78159f32e43b51b244f744cf61589..1f32b88d76c7ceb951e4623e1e25cedff43f5206 100644 (file)
@@ -51,6 +51,7 @@
 #include "dvr/dvr.h"
 #include "htsp_server.h"
 #include "avahi.h"
+#include "bonjour.h"
 #include "input.h"
 #include "service.h"
 #include "trap.h"
@@ -812,6 +813,7 @@ main(int argc, char **argv)
     subscription_dummy_join(opt_subscribe, 1);
 
   avahi_init();
+  bonjour_init();
 
   epg_updated(); // cleanup now all prev ref's should have been created
 
@@ -874,6 +876,7 @@ main(int argc, char **argv)
   tvhftrace("main", access_done);
   tvhftrace("main", epg_done);
   tvhftrace("main", avahi_done);
+  tvhftrace("main", bonjour_done);
   tvhftrace("main", imagecache_done);
   tvhftrace("main", idnode_done);
   tvhftrace("main", lang_code_done);