diff options
author | Eric Wong <normalperson@yhbt.net> | 2008-06-16 02:48:07 +0000 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2008-06-16 02:48:07 +0000 |
commit | 2444f5d41a3ccefdf14f5336430ef46baf976626 (patch) | |
tree | ee147c111fea3c7f808fd2f27a4dc55500d7d013 | |
parent | ac74ef1fde5859aabcffe6ec6c57100cb680d89f (diff) | |
download | mpd-2444f5d41a3ccefdf14f5336430ef46baf976626.tar.gz mpd-2444f5d41a3ccefdf14f5336430ef46baf976626.tar.xz mpd-2444f5d41a3ccefdf14f5336430ef46baf976626.zip |
Backport Bonjour support from trunk
Thanks to Qball, pat, and jat :)
------------------------------------------------------------------------
r6477 | jat | 2007-06-04 19:41:18 +0200 (Mo, 04 Jun 2007) | 4 lines
Don't initialize zeroconf until after we've daemonized and log output has
been redirected. This prevents zeroconf from blocking daemonization, and
makes sure any errors get sent to the logs and not stdout.
------------------------------------------------------------------------
r6474 | jat | 2007-06-03 22:09:12 +0200 (So, 03 Jun 2007) | 3 lines
Adding ChangeLog entry for zeroconf_enabled, adding Zeroconf section to
mpdconf.example, and updating the zeroconf_* docs.
------------------------------------------------------------------------
r6471 | jat | 2007-06-03 21:44:19 +0200 (So, 03 Jun 2007) | 4 lines
Define HAVE_ZEROCONF if Avahi or Bonjour support is enabled, so that we can
silence a warning about an unused variable without using stupid checks for
HAVE_AVAHI || HAVE_BONJOUR.
------------------------------------------------------------------------
r6467 | pat | 2007-06-03 20:08:51 +0200 (So, 03 Jun 2007) | 2 lines
allow zeroconf to be disabled.
------------------------------------------------------------------------
r6464 | jat | 2007-06-03 02:03:20 +0200 (So, 03 Jun 2007) | 2 lines
Cleaning up zeroconf configure magic.
------------------------------------------------------------------------
r6463 | jat | 2007-06-03 00:58:51 +0200 (So, 03 Jun 2007) | 2 lines
Check if we need -ldns_sd for Bonjour.
------------------------------------------------------------------------
r6462 | jat | 2007-06-03 00:52:53 +0200 (So, 03 Jun 2007) | 2 lines
Adding a missing include.
------------------------------------------------------------------------
r6453 | pat | 2007-06-02 19:06:08 +0200 (Sa, 02 Jun 2007) | 3 lines
Added Bonjour zeroconf support. This works now natively on
MacOS X. I couldn't test mDNSResponder support on Linux, as
Debian doesn't include it - but should work as well.
git-svn-id: https://svn.musicpd.org/mpd/branches/branch-0.13.0-fixes@7381 09075e82-0dd4-0310-85a5-a0d7c8717e4f
-rw-r--r-- | configure.ac | 34 | ||||
-rw-r--r-- | doc/mpd.conf.5 | 10 | ||||
-rw-r--r-- | doc/mpdconf.example | 14 | ||||
-rw-r--r-- | src/conf.c | 1 | ||||
-rw-r--r-- | src/conf.h | 1 | ||||
-rw-r--r-- | src/main.c | 5 | ||||
-rw-r--r-- | src/zeroconf.c | 128 |
7 files changed, 163 insertions, 30 deletions
diff --git a/configure.ac b/configure.ac index 1206b296f..562264362 100644 --- a/configure.ac +++ b/configure.ac @@ -583,26 +583,38 @@ no|avahi|bonjour) esac if test x$with_zeroconf != xno; then - if test x$with_zeroconf = xauto; then + if test x$with_zeroconf = xavahi || test x$with_zeroconf = xauto; then PKG_CHECK_MODULES([AVAHI], [avahi-client], - [with_zeroconf=avahi;AC_DEFINE([HAVE_AVAHI], 1, [Define to enable Avahi Zeroconf support])] MPD_LIBS="$MPD_LIBS $AVAHI_LIBS" MPD_CFLAGS="$MPD_CFLAGS $AVAHI_CFLAGS", - [with_zeroconf=auto]) + [found_avahi=1;AC_DEFINE([HAVE_AVAHI], 1, [Define to enable Avahi Zeroconf support])] + MPD_LIBS="$MPD_LIBS $AVAHI_LIBS" MPD_CFLAGS="$MPD_CFLAGS $AVAHI_CFLAGS", + [found_avahi=0]) + fi + + if test x$found_avahi = x1; then + with_zeroconf=avahi elif test x$with_zeroconf = xavahi; then - PKG_CHECK_MODULES([AVAHI], [avahi-client], - [with_zeroconf=avahi;AC_DEFINE([HAVE_AVAHI], 1, [Define to enable Avahi Zeroconf support])] MPD_LIBS="$MPD_LIBS $AVAHI_LIBS" MPD_CFLAGS="$MPD_CFLAGS $AVAHI_CFLAGS") + with_zeroconf=no fi - # In the future, should add bonjour support (for OSX) and check at autodetect - # time - #if test x$with_zeroconf = xbonjour -o x$with_zeroconf = xauto; then - if test x$with_zeroconf = xbonjour; then - AC_MSG_WARN([Bonjour support has not been implemented yet, disabling Zeroconf]) + if test x$with_zeroconf = xbonjour || test x$with_zeroconf = xauto; then + AC_CHECK_HEADER(dns_sd.h, + [found_bonjour=1;AC_DEFINE([HAVE_BONJOUR], 1, [Define to enable Bonjour Zeroconf support])], + [found_bonjour=0]) + AC_CHECK_LIB(dns_sd, DNSServiceRegister, + MPD_LIBS="$MPD_LIBS -ldns_sd") + fi + + if test x$found_bonjour = x1; then + with_zeroconf=bonjour + elif test x$with_zeroconf = xbonjour; then with_zeroconf=no fi - if test x$with_zeroconf = xauto; then + if test x$with_zeroconf = xauto || test x$with_zeroconf = xno; then AC_MSG_WARN([No supported Zeroconf backend found, disabling Zeroconf]) with_zeroconf=no + else + AC_DEFINE([HAVE_ZEROCONF], 1, [Define to enable Zeroconf support]) fi fi diff --git a/doc/mpd.conf.5 b/doc/mpd.conf.5 index efe95167d..d52f07200 100644 --- a/doc/mpd.conf.5 +++ b/doc/mpd.conf.5 @@ -71,10 +71,14 @@ reports from what address a connection is opened, and when it is closed, and "verbose" records excessive amounts of information for debugging purposes. The default is "default". .TP +.B zeroconf_enabled <yes or no> +If yes, and MPD has been compiled with support for Avahi or Bonjour, service +information will be published with Zeroconf. The default is yes. +.TP .B zeroconf_name <name> -If Zerconf is compiled into MPD, this is the service name to publish. This -should be unique to your local network, but name collisions will be properly -dealt with. +If Zeroconf is enabled, this is the service name to publish. This name should +be unique to your local network, but name collisions will be properly dealt +with. The default is "Music Player". .TP .B password <password@permissions> This specifies a password for access to mpd. The format is diff --git a/doc/mpdconf.example b/doc/mpdconf.example index 8cd367541..aff3db430 100644 --- a/doc/mpdconf.example +++ b/doc/mpdconf.example @@ -45,9 +45,17 @@ error_file "~/.mpd/mpd.error" # #log_level "default" # -# If Zeroconf is configured, the service name to publish. This -# should be unique on your local network, but name collisions -# will be taken care of for you. +################################################################ + + +########################### ZEROCONF ########################### +# +# If yes, service information will be published with Zeroconf. +# +#zeroconf_enabled "yes" +# +# The service name to publish. This name should be unique on +# your local network. # #zeroconf_name "Music Player" # diff --git a/src/conf.c b/src/conf.c index 15d95a78b..307d85dfd 100644 --- a/src/conf.c +++ b/src/conf.c @@ -145,6 +145,7 @@ void initConf(void) registerConfigParam(CONF_PORT, 0, 0); registerConfigParam(CONF_LOG_LEVEL, 0, 0); registerConfigParam(CONF_ZEROCONF_NAME, 0, 0); + registerConfigParam(CONF_ZEROCONF_ENABLED, 0, 0); registerConfigParam(CONF_PASSWORD, 1, 0); registerConfigParam(CONF_DEFAULT_PERMS, 0, 0); registerConfigParam(CONF_AUDIO_OUTPUT, 1, 1); diff --git a/src/conf.h b/src/conf.h index 7059eaa90..f5ef07525 100644 --- a/src/conf.h +++ b/src/conf.h @@ -33,6 +33,7 @@ #define CONF_PORT "port" #define CONF_LOG_LEVEL "log_level" #define CONF_ZEROCONF_NAME "zeroconf_name" +#define CONF_ZEROCONF_ENABLED "zeroconf_enabled" #define CONF_PASSWORD "password" #define CONF_DEFAULT_PERMS "default_permissions" #define CONF_AUDIO_OUTPUT "audio_output" diff --git a/src/main.c b/src/main.c index 4c537eb1d..ddfe508b6 100644 --- a/src/main.c +++ b/src/main.c @@ -429,7 +429,6 @@ int main(int argc, char *argv[]) initAudioDriver(); initVolume(); initInterfaces(); - initZeroconf(); initReplayGainState(); initNormalization(); initInputStream(); @@ -438,10 +437,10 @@ int main(int argc, char *argv[]) setup_log_output(options.stdOutput); - - initSigHandlers(); + initZeroconf(); + openVolumeDevice(); read_state_file(); diff --git a/src/zeroconf.c b/src/zeroconf.c index 0b0163218..6ded363bf 100644 --- a/src/zeroconf.c +++ b/src/zeroconf.c @@ -19,6 +19,7 @@ #include <stdlib.h> #include <assert.h> #include <string.h> +#include <arpa/inet.h> #include "zeroconf.h" #include "conf.h" @@ -35,6 +36,17 @@ */ #define SERVICE_NAME "Music Player" +#ifdef HAVE_ZEROCONF +static struct ioOps zeroConfIo = { +}; +#endif + +#ifdef HAVE_BONJOUR +#include <dns_sd.h> + +static DNSServiceRef dnsReference; +#endif + /* Here is the implementation for Avahi (http://avahi.org) Zeroconf support */ #ifdef HAVE_AVAHI @@ -55,10 +67,6 @@ static int avahiRunning; static int avahiFdset( fd_set* rfds, fd_set* wfds, fd_set* efds ); static int avahiFdconsume( int fdCount, fd_set* rfds, fd_set* wfds, fd_set* efds ); -static struct ioOps avahiIo = { - .fdset = avahiFdset, - .consume = avahiFdconsume, -}; /* Forward Declaration */ static void avahiRegisterService(AvahiClient *c); @@ -453,36 +461,127 @@ static void init_avahi(const char *serviceName) goto fail; } - avahiIo.fdset = avahiFdset; - avahiIo.consume = avahiFdconsume; - registerIO( &avahiIo ); + zeroConfIo.fdset = avahiFdset; + zeroConfIo.consume = avahiFdconsume; + registerIO( &zeroConfIo ); return; fail: finishZeroconf(); } -#else /* !HAVE_AVAHI */ -static void init_avahi(const char *serviceName) { } #endif /* HAVE_AVAHI */ +#ifdef HAVE_BONJOUR +static int dnsRegisterFdset(fd_set* rfds, fd_set* wfds, fd_set* efds) +{ + int fd; + + if (dnsReference == NULL) + return -1; + + fd = DNSServiceRefSockFD(dnsReference); + if (fd == -1) + return -1; + + FD_SET(fd, rfds); + + return fd; +} + +static int dnsRegisterFdconsume(int fdCount, fd_set* rfds, fd_set* wfds, + fd_set* efds) +{ + int fd; + + if (dnsReference == NULL) + return -1; + + fd = DNSServiceRefSockFD(dnsReference); + if (fd == -1) + return -1; + + if (FD_ISSET(fd, rfds)) { + FD_CLR(fd, rfds); + + DNSServiceProcessResult(dnsReference); + + return fdCount - 1; + } + + return fdCount; +} + +static void dnsRegisterCallback (DNSServiceRef sdRef, DNSServiceFlags flags, + DNSServiceErrorType errorCode, const char *name, + const char *regtype, const char *domain, void *context) +{ + if (errorCode != kDNSServiceErr_NoError) { + ERROR("Failed to register zeroconf service.\n"); + + DNSServiceRefDeallocate(dnsReference); + dnsReference = NULL; + deregisterIO( &zeroConfIo ); + } else { + DEBUG("Registered zeroconf service with name '%s'\n", name); + } +} + +static void init_zeroconf_osx(const char *serviceName) +{ + DNSServiceErrorType error = DNSServiceRegister(&dnsReference, + 0, 0, serviceName, SERVICE_TYPE, NULL, NULL, htons(getBoundPort()), 0, + NULL, dnsRegisterCallback, NULL); + + if (error != kDNSServiceErr_NoError) { + ERROR("Failed to register zeroconf service.\n"); + + if (dnsReference) { + DNSServiceRefDeallocate(dnsReference); + dnsReference = NULL; + } + return; + } + + zeroConfIo.fdset = dnsRegisterFdset; + zeroConfIo.consume = dnsRegisterFdconsume; + registerIO( &zeroConfIo ); +} +#endif + void initZeroconf(void) { const char* serviceName = SERVICE_NAME; ConfigParam *param; + int enabled = getBoolConfigParam(CONF_ZEROCONF_ENABLED); + + if (enabled != -1 && enabled != 1) + return; param = getConfigParam(CONF_ZEROCONF_NAME); if (param && strlen(param->value) > 0) serviceName = param->value; + +#ifdef HAVE_AVAHI init_avahi(serviceName); +#endif + +#ifdef HAVE_BONJOUR + init_zeroconf_osx(serviceName); +#endif } void finishZeroconf(void) { + int enabled = getBoolConfigParam(CONF_ZEROCONF_ENABLED); + + if (enabled != -1 && enabled != 1) + return; + #ifdef HAVE_AVAHI DEBUG( "Avahi: Shutting down interface\n" ); - deregisterIO( &avahiIo ); + deregisterIO( &zeroConfIo ); if( avahiGroup ) { avahi_entry_group_free( avahiGroup ); @@ -497,4 +596,13 @@ void finishZeroconf(void) avahi_free( avahiName ); avahiName = NULL; #endif /* HAVE_AVAHI */ + +#ifdef HAVE_BONJOUR + deregisterIO( &zeroConfIo ); + if (dnsReference != NULL) { + DNSServiceRefDeallocate(dnsReference); + dnsReference = NULL; + DEBUG("Deregistered Zeroconf service.\n"); + } +#endif } |