aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configure.ac34
-rw-r--r--doc/mpd.conf.510
-rw-r--r--doc/mpdconf.example14
-rw-r--r--src/conf.c1
-rw-r--r--src/conf.h1
-rw-r--r--src/main.c5
-rw-r--r--src/zeroconf.c128
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
}