From 9b0388c8444868f714daa5a0406fc89209ac0164 Mon Sep 17 00:00:00 2001 From: Damjan Marion Date: Sat, 31 May 2014 00:47:17 +0200 Subject: [PATCH] osx: introduce bonjour support --- Makefile | 7 ++- configure | 2 + src/bonjour.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/bonjour.h | 7 +++ src/main.c | 3 ++ 5 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 src/bonjour.c create mode 100644 src/bonjour.h diff --git a/Makefile b/Makefile index adfaa409..2d7cee83 100644 --- 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 \ diff --git a/configure b/configure index a637379f..e125992d 100755 --- 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 index 00000000..b9e0205d --- /dev/null +++ b/src/bonjour.c @@ -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 . + */ + +#include +#include +#include + +#include "tvheadend.h" +#include "bonjour.h" + +#include + +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 index 00000000..0e20c5f1 --- /dev/null +++ b/src/bonjour.h @@ -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 diff --git a/src/main.c b/src/main.c index 0eda2218..1f32b88d 100644 --- a/src/main.c +++ b/src/main.c @@ -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);