osx: introduce bonjour support
This commit is contained in:
parent
0ebca1b3db
commit
9b0388c844
5 changed files with 138 additions and 1 deletions
7
Makefile
7
Makefile
|
@ -36,7 +36,9 @@ LDFLAGS += -ldl -lpthread -lm
|
||||||
ifeq ($(CONFIG_LIBICONV),yes)
|
ifeq ($(CONFIG_LIBICONV),yes)
|
||||||
LDFLAGS += -liconv
|
LDFLAGS += -liconv
|
||||||
endif
|
endif
|
||||||
ifneq ($(PLATFORM), darwin)
|
ifeq ($(PLATFORM), darwin)
|
||||||
|
LDFLAGS += -framework CoreServices
|
||||||
|
else
|
||||||
LDFLAGS += -lrt
|
LDFLAGS += -lrt
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -261,6 +263,9 @@ SRCS-${CONFIG_INOTIFY} += \
|
||||||
# Avahi
|
# Avahi
|
||||||
SRCS-$(CONFIG_AVAHI) += src/avahi.c
|
SRCS-$(CONFIG_AVAHI) += src/avahi.c
|
||||||
|
|
||||||
|
# Bonjour
|
||||||
|
SRCS-$(CONFIG_BONJOUR) += src/bonjour.c
|
||||||
|
|
||||||
# libav
|
# libav
|
||||||
SRCS-$(CONFIG_LIBAV) += src/libav.c \
|
SRCS-$(CONFIG_LIBAV) += src/libav.c \
|
||||||
src/muxer/muxer_libav.c \
|
src/muxer/muxer_libav.c \
|
||||||
|
|
2
configure
vendored
2
configure
vendored
|
@ -172,6 +172,8 @@ fi
|
||||||
#
|
#
|
||||||
if [ ${PLATFORM} = "darwin" ]; then
|
if [ ${PLATFORM} = "darwin" ]; then
|
||||||
disable linuxdvb
|
disable linuxdvb
|
||||||
|
disable avahi
|
||||||
|
enable bonjour
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
120
src/bonjour.c
Normal file
120
src/bonjour.c
Normal file
|
@ -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);
|
||||||
|
}
|
7
src/bonjour.h
Normal file
7
src/bonjour.h
Normal file
|
@ -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
|
|
@ -51,6 +51,7 @@
|
||||||
#include "dvr/dvr.h"
|
#include "dvr/dvr.h"
|
||||||
#include "htsp_server.h"
|
#include "htsp_server.h"
|
||||||
#include "avahi.h"
|
#include "avahi.h"
|
||||||
|
#include "bonjour.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "service.h"
|
#include "service.h"
|
||||||
#include "trap.h"
|
#include "trap.h"
|
||||||
|
@ -812,6 +813,7 @@ main(int argc, char **argv)
|
||||||
subscription_dummy_join(opt_subscribe, 1);
|
subscription_dummy_join(opt_subscribe, 1);
|
||||||
|
|
||||||
avahi_init();
|
avahi_init();
|
||||||
|
bonjour_init();
|
||||||
|
|
||||||
epg_updated(); // cleanup now all prev ref's should have been created
|
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", access_done);
|
||||||
tvhftrace("main", epg_done);
|
tvhftrace("main", epg_done);
|
||||||
tvhftrace("main", avahi_done);
|
tvhftrace("main", avahi_done);
|
||||||
|
tvhftrace("main", bonjour_done);
|
||||||
tvhftrace("main", imagecache_done);
|
tvhftrace("main", imagecache_done);
|
||||||
tvhftrace("main", idnode_done);
|
tvhftrace("main", idnode_done);
|
||||||
tvhftrace("main", lang_code_done);
|
tvhftrace("main", lang_code_done);
|
||||||
|
|
Loading…
Add table
Reference in a new issue