aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2014-01-26 11:19:17 +0100
committerMax Kellermann <max@duempel.org>2014-01-26 15:51:33 +0100
commit0b3fbdba87e9ecbfaefab9f71203a1c35f1a8b00 (patch)
tree4e103fbcbea5dd504054f0d60dbc84e83ceed52b
parent3dad837ca692df4eecee9c16fd9155b4ca23e289 (diff)
downloadmpd-0b3fbdba87e9ecbfaefab9f71203a1c35f1a8b00.tar.gz
mpd-0b3fbdba87e9ecbfaefab9f71203a1c35f1a8b00.tar.xz
mpd-0b3fbdba87e9ecbfaefab9f71203a1c35f1a8b00.zip
neighbor/upnp: UPnP media server discovery
-rw-r--r--Makefile.am23
-rw-r--r--configure.ac3
-rw-r--r--src/lib/upnp/ContentDirectoryService.hxx5
-rw-r--r--src/neighbor/Registry.cxx4
-rw-r--r--src/neighbor/plugins/UpnpNeighborPlugin.cxx139
-rw-r--r--src/neighbor/plugins/UpnpNeighborPlugin.hxx27
6 files changed, 201 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am
index 0acca6b31..8a648e45b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -436,6 +436,15 @@ NEIGHBOR_LIBS = \
$(SMBCLIENT_LIBS) \
libneighbor.a
+if HAVE_LIBUPNP
+libneighbor_a_SOURCES += \
+ $(UPNP_SOURCES) \
+ src/neighbor/plugins/UpnpNeighborPlugin.cxx src/neighbor/plugins/UpnpNeighborPlugin.hxx
+NEIGHBOR_LIBS += \
+ $(EXPAT_LIBS) \
+ $(UPNP_LIBS)
+endif
+
endif
# database plugins
@@ -1323,10 +1332,14 @@ if ENABLE_NEIGHBOR_PLUGINS
test_run_neighbor_explorer_SOURCES = \
src/Log.cxx src/LogBackend.cxx \
+ src/IOThread.cxx \
test/run_neighbor_explorer.cxx
test_run_neighbor_explorer_LDADD = \
$(GLIB_LIBS) \
$(NEIGHBOR_LIBS) \
+ $(INPUT_LIBS) \
+ $(ARCHIVE_LIBS) \
+ libtag.a \
libconf.a \
libevent.a \
libfs.a \
@@ -1334,6 +1347,16 @@ test_run_neighbor_explorer_LDADD = \
libthread.a \
libutil.a
+if HAVE_LIBUPNP
+test_run_neighbor_explorer_SOURCES += src/lib/expat/ExpatParser.cxx
+endif
+
+if ENABLE_DESPOTIFY
+test_run_neighbor_explorer_SOURCES += \
+ src/lib/despotify/DespotifyUtils.cxx \
+ src/lib/despotify/DespotifyUtils.hxx
+endif
+
endif
if ENABLE_ARCHIVE
diff --git a/configure.ac b/configure.ac
index 19ead794b..d65839a40 100644
--- a/configure.ac
+++ b/configure.ac
@@ -897,6 +897,9 @@ if test x$enable_neighbor_plugins = xauto; then
if test x$enable_smbclient = xyes; then
enable_neighbor_plugins=yes
fi
+ if test x$enable_upnp = xyes; then
+ enable_neighbor_plugins=yes
+ fi
fi
if test x$enable_neighbor_plugins = xyes; then
diff --git a/src/lib/upnp/ContentDirectoryService.hxx b/src/lib/upnp/ContentDirectoryService.hxx
index 3c4497be1..0b03df2e7 100644
--- a/src/lib/upnp/ContentDirectoryService.hxx
+++ b/src/lib/upnp/ContentDirectoryService.hxx
@@ -121,6 +121,11 @@ public:
std::list<std::string> &result,
Error &error) const;
+ gcc_pure
+ std::string GetURI() const {
+ return "upnp://" + m_deviceId + "/" + m_serviceType;
+ }
+
/** Retrieve the "friendly name" for this server, useful for display. */
const char *getFriendlyName() const {
return m_friendlyName.c_str();
diff --git a/src/neighbor/Registry.cxx b/src/neighbor/Registry.cxx
index fc9d05ecf..f6d1f97b3 100644
--- a/src/neighbor/Registry.cxx
+++ b/src/neighbor/Registry.cxx
@@ -21,6 +21,7 @@
#include "Registry.hxx"
#include "NeighborPlugin.hxx"
#include "plugins/SmbclientNeighborPlugin.hxx"
+#include "plugins/UpnpNeighborPlugin.hxx"
#include <string.h>
@@ -28,6 +29,9 @@ const NeighborPlugin *const neighbor_plugins[] = {
#ifdef ENABLE_SMBCLIENT
&smbclient_neighbor_plugin,
#endif
+#ifdef HAVE_LIBUPNP
+ &upnp_neighbor_plugin,
+#endif
nullptr
};
diff --git a/src/neighbor/plugins/UpnpNeighborPlugin.cxx b/src/neighbor/plugins/UpnpNeighborPlugin.cxx
new file mode 100644
index 000000000..253e4c13b
--- /dev/null
+++ b/src/neighbor/plugins/UpnpNeighborPlugin.cxx
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * 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 2 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+#include "UpnpNeighborPlugin.hxx"
+#include "lib/upnp/Domain.hxx"
+#include "lib/upnp/ClientInit.hxx"
+#include "lib/upnp/Discovery.hxx"
+#include "lib/upnp/ContentDirectoryService.hxx"
+#include "neighbor/NeighborPlugin.hxx"
+#include "neighbor/Explorer.hxx"
+#include "neighbor/Listener.hxx"
+#include "neighbor/Info.hxx"
+#include "Log.hxx"
+
+class UpnpNeighborExplorer final
+ : public NeighborExplorer, UPnPDiscoveryListener {
+ struct Server {
+ std::string name, comment;
+
+ bool alive;
+
+ Server(std::string &&_name, std::string &&_comment)
+ :name(std::move(_name)), comment(std::move(_comment)),
+ alive(true) {}
+ Server(const Server &) = delete;
+
+ gcc_pure
+ bool operator==(const Server &other) const {
+ return name == other.name;
+ }
+
+ gcc_pure
+ NeighborInfo Export() const {
+ return { "smb://" + name + "/", comment };
+ }
+ };
+
+ UPnPDeviceDirectory *discovery;
+
+public:
+ UpnpNeighborExplorer(NeighborListener &_listener)
+ :NeighborExplorer(_listener) {}
+
+ /* virtual methods from class NeighborExplorer */
+ virtual bool Open(Error &error) override;
+ virtual void Close() override;
+ virtual List GetList() const override;
+
+private:
+ /* virtual methods from class UPnPDiscoveryListener */
+ virtual void FoundUPnP(const ContentDirectoryService &service) override;
+ virtual void LostUPnP(const ContentDirectoryService &service) override;
+};
+
+bool
+UpnpNeighborExplorer::Open(Error &error)
+{
+ UpnpClient_Handle handle;
+ if (!UpnpClientGlobalInit(handle, error))
+ return false;
+
+ discovery = new UPnPDeviceDirectory(handle, this);
+ if (!discovery->Start(error)) {
+ delete discovery;
+ UpnpClientGlobalFinish();
+ return false;
+ }
+
+ return true;
+}
+
+void
+UpnpNeighborExplorer::Close()
+{
+ delete discovery;
+ UpnpClientGlobalFinish();
+}
+
+NeighborExplorer::List
+UpnpNeighborExplorer::GetList() const
+{
+ std::vector<ContentDirectoryService> tmp;
+
+ {
+ Error error;
+ if (!discovery->getDirServices(tmp, error))
+ LogError(error);
+ }
+
+ List result;
+ for (const auto &i : tmp)
+ result.emplace_front(i.GetURI(), i.getFriendlyName());
+ return result;
+}
+
+void
+UpnpNeighborExplorer::FoundUPnP(const ContentDirectoryService &service)
+{
+ const NeighborInfo n(service.GetURI(), service.getFriendlyName());
+ listener.FoundNeighbor(n);
+}
+
+void
+UpnpNeighborExplorer::LostUPnP(const ContentDirectoryService &service)
+{
+ const NeighborInfo n(service.GetURI(), service.getFriendlyName());
+ listener.LostNeighbor(n);
+}
+
+static NeighborExplorer *
+upnp_neighbor_create(gcc_unused EventLoop &loop,
+ NeighborListener &listener,
+ gcc_unused const config_param &param,
+ gcc_unused Error &error)
+{
+ return new UpnpNeighborExplorer(listener);
+}
+
+const NeighborPlugin upnp_neighbor_plugin = {
+ "upnp",
+ upnp_neighbor_create,
+};
diff --git a/src/neighbor/plugins/UpnpNeighborPlugin.hxx b/src/neighbor/plugins/UpnpNeighborPlugin.hxx
new file mode 100644
index 000000000..78e4ccf13
--- /dev/null
+++ b/src/neighbor/plugins/UpnpNeighborPlugin.hxx
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * 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 2 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPD_NEIGHBOR_UPNP_HXX
+#define MPD_NEIGHBOR_UPNP_HXX
+
+struct NeighborPlugin;
+
+extern const NeighborPlugin upnp_neighbor_plugin;
+
+#endif