From: Andreas Öman Date: Mon, 10 Aug 2009 19:06:16 +0000 (+0000) Subject: The HTSP service is now announced via AVAHI (mDNS service discovery) X-Git-Tag: 2.12~540 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a099c4862710ff1688048ebf6ca5c528e2baab83;p=thirdparty%2Ftvheadend.git The HTSP service is now announced via AVAHI (mDNS service discovery) --- diff --git a/Makefile b/Makefile index ea114915e..b099119dc 100644 --- a/Makefile +++ b/Makefile @@ -99,6 +99,15 @@ SRCS += src/webui/webui.c \ src/webui/extjs.c \ src/webui/simpleui.c \ +# +# AVAHI interface +# + +SRCS-$(CONFIG_AVAHI) += src/avahi.c + +${BUILDDIR}/src/avahi.o : CFLAGS = \ + $(shell pkg-config --cflags avahi-client) -Wall -Werror + # Various transformations SRCS += $(SRCS-yes) DLIBS += $(DLIBS-yes) diff --git a/configure b/configure index 54d80aae3..2c6cbfedf 100755 --- a/configure +++ b/configure @@ -35,6 +35,7 @@ show_help(){ } enable cwc +enable avahi for opt do optval="${opt#*=}" @@ -91,6 +92,21 @@ fi echo >>${CONFIG_MAK} $CC_CONFIG_MAK +# +# AVAHI +# +if enabled avahi; then + if pkg-config avahi-client; then + # CFLAGS are included by Makefile + echo >>${CONFIG_MAK} "LDFLAGS_cfg += " `pkg-config --libs avahi-client` + echo "Using AVAHI client: `pkg-config --modversion avahi-client`" + else + echo "avahi-client not found. Unable to build with AVAHI support." + echo "To compile without it, configure with: --disable-avahi" + die + fi +fi + # # configure ffmpeg # diff --git a/debian/changelog b/debian/changelog index eac361dd8..92fd9260f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -6,6 +6,8 @@ hts-tvheadend (2.5) hts; urgency=low * If XMLTV grabbing was disabled tvheadend would spin in a 100% CPU loop. This is now fixed. + * The HTSP service is now announced via AVAHI (mDNS service discovery) + hts-tvheadend (2.4) hts; urgency=low * Due to a bug, the polarisation of DVB-S muxes was not correctly diff --git a/src/avahi.c b/src/avahi.c new file mode 100644 index 000000000..6faad2636 --- /dev/null +++ b/src/avahi.c @@ -0,0 +1,256 @@ +/* + * AVAHI service publisher + * Copyright (C) 2009 Andreas Öman + * + * 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 . + */ + +/*** + This file is part of avahi. + + avahi is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + avahi 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 Lesser General + Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with avahi; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "tvhead.h" +#include "avahi.h" + +static AvahiEntryGroup *group = NULL; +static char *name = NULL; + +static void create_services(AvahiClient *c); + +static void +entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, + void *userdata) +{ + assert(g == group || group == NULL); + group = g; + + /* Called whenever the entry group state changes */ + + switch (state) { + case AVAHI_ENTRY_GROUP_ESTABLISHED : + /* The entry group has been established successfully */ + tvhlog(LOG_INFO, "AVAHI", + "Service '%s' successfully established.", name); + break; + + case AVAHI_ENTRY_GROUP_COLLISION : { + char *n; + + /* A service name collision with a remote service + * happened. Let's pick a new name */ + n = avahi_alternative_service_name(name); + avahi_free(name); + name = n; + + tvhlog(LOG_ERR, "AVAHI", + "Service name collision, renaming service to '%s'", name); + + /* And recreate the services */ + create_services(avahi_entry_group_get_client(g)); + break; + } + + case AVAHI_ENTRY_GROUP_FAILURE : + tvhlog(LOG_ERR, "AVAHI", + "Entry group failure: %s", + avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(g)))); + break; + + case AVAHI_ENTRY_GROUP_UNCOMMITED: + case AVAHI_ENTRY_GROUP_REGISTERING: + ; + } +} + + +/** + * + */ +static void +create_services(AvahiClient *c) +{ + char *n; + int ret; + assert(c); + + /* If this is the first time we're called, let's create a new + * entry group if necessary */ + + if (!group) + if (!(group = avahi_entry_group_new(c, entry_group_callback, NULL))) { + tvhlog(LOG_ERR, "AVAHI", + "avahi_enty_group_new() failed: %s", + avahi_strerror(avahi_client_errno(c))); + goto fail; + } + + /* If the group is empty (either because it was just created, or + * because it was reset previously, add our entries. */ + + if (avahi_entry_group_is_empty(group)) { + tvhlog(LOG_DEBUG, "AVAHI", "Adding service '%s'", name); + + /* Add the service for IPP */ + if ((ret = avahi_entry_group_add_service(group, AVAHI_IF_UNSPEC, + AVAHI_PROTO_UNSPEC, 0, name, + "_htsp._tcp", NULL, NULL, 9982, + NULL)) < 0) { + + if (ret == AVAHI_ERR_COLLISION) + goto collision; + + tvhlog(LOG_ERR, "AVAHI", + "Failed to add _htsp._tcp service: %s", + avahi_strerror(ret)); + goto fail; + } + + /* Tell the server to register the service */ + if ((ret = avahi_entry_group_commit(group)) < 0) { + tvhlog(LOG_ERR, "AVAHI", + "Failed to commit entry group: %s", + avahi_strerror(ret)); + goto fail; + } + } + + return; + + collision: + + /* A service name collision with a local service happened. Let's + * pick a new name */ + n = avahi_alternative_service_name(name); + avahi_free(name); + name = n; + + tvhlog(LOG_ERR, "AVAHI", + "Service name collision, renaming service to '%s'", name); + + avahi_entry_group_reset(group); + + create_services(c); + return; + + fail: + return; +} + + +/** + * + */ +static void +client_callback(AvahiClient *c, AvahiClientState state, void *userdata) +{ + assert(c); + + /* Called whenever the client or server state changes */ + + switch (state) { + case AVAHI_CLIENT_S_RUNNING: + + /* The server has startup successfully and registered its host + * name on the network, so it's time to create our services */ + create_services(c); + break; + + case AVAHI_CLIENT_FAILURE: + tvhlog(LOG_ERR, "AVAHI", "Client failure: %s", + avahi_strerror(avahi_client_errno(c))); + break; + + case AVAHI_CLIENT_S_COLLISION: + + /* Let's drop our registered services. When the server is back + * in AVAHI_SERVER_RUNNING state we will register them + * again with the new host name. */ + + case AVAHI_CLIENT_S_REGISTERING: + + /* The server records are now being established. This + * might be caused by a host name change. We need to wait + * for our own records to register until the host name is + * properly esatblished. */ + + if(group) + avahi_entry_group_reset(group); + + break; + + case AVAHI_CLIENT_CONNECTING: + ; + } +} + + +/** + * + */ +static void * +avahi_thread(void *aux) +{ + AvahiSimplePoll *asp = avahi_simple_poll_new(); + const AvahiPoll *ap = avahi_simple_poll_get(asp); + + name = avahi_strdup("Tvheadend"); + + avahi_client_new(ap, AVAHI_CLIENT_NO_FAIL, client_callback, NULL, NULL); + + while((avahi_simple_poll_iterate(asp, -1)) != -1) {} + + return NULL; + + +} + +/** + * + */ +void +avahi_init(void) +{ + pthread_t tid; + + pthread_create(&tid, NULL, avahi_thread, NULL); +} diff --git a/src/avahi.h b/src/avahi.h new file mode 100644 index 000000000..891820cdf --- /dev/null +++ b/src/avahi.h @@ -0,0 +1 @@ +void avahi_init(void); diff --git a/src/main.c b/src/main.c index 251f22e96..c62298b21 100644 --- a/src/main.c +++ b/src/main.c @@ -51,6 +51,7 @@ #include "dvr/dvr.h" #include "htsp.h" #include "rawtsinput.h" +#include "avahi.h" #include "parachute.h" #include "settings.h" @@ -354,6 +355,10 @@ main(int argc, char **argv) if(join_transport != NULL) subscription_dummy_join(join_transport); +#ifdef CONFIG_AVAHI + avahi_init(); +#endif + pthread_mutex_unlock(&global_lock); diff --git a/support/configure.inc b/support/configure.inc index 4f74edf8b..f7671b1c5 100644 --- a/support/configure.inc +++ b/support/configure.inc @@ -21,6 +21,7 @@ RELEASENAME=`head -n1 ${TOPDIR}/ChangeLog | awk '{print $2}' | sed s/\(// | sed CONFIG_LIST=" cwc + avahi " die() {