diff options
-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 } |