|
|
@ -0,0 +1,436 @@ |
|
|
|
From 61df54155a3cb1846e6bf15e4f007ec8d623de63 Mon Sep 17 00:00:00 2001 |
|
|
|
From: Jean-Francois Dockes <jf@dockes.org> |
|
|
|
Date: Sun, 23 Aug 2020 14:22:21 +0200 |
|
|
|
Subject: [PATCH] Modification to use npupnp instead of pupnp when the upnp |
|
|
|
meson option is set |
|
|
|
|
|
|
|
---
|
|
|
|
meson_options.txt | 5 +- |
|
|
|
.../plugins/upnp/ContentDirectoryService.cxx | 101 ++++++++++++++++++ |
|
|
|
src/lib/upnp/Action.hxx | 2 + |
|
|
|
src/lib/upnp/ClientInit.cxx | 12 +-- |
|
|
|
src/lib/upnp/Compat.hxx | 4 +- |
|
|
|
src/lib/upnp/ContentDirectoryService.cxx | 25 +++++ |
|
|
|
src/lib/upnp/Init.cxx | 4 + |
|
|
|
src/lib/upnp/UniqueIxml.hxx | 2 + |
|
|
|
src/lib/upnp/ixmlwrap.cxx | 4 + |
|
|
|
src/lib/upnp/ixmlwrap.hxx | 2 + |
|
|
|
src/lib/upnp/meson.build | 20 +++- |
|
|
|
11 files changed, 170 insertions(+), 11 deletions(-) |
|
|
|
|
|
|
|
diff --git a/meson_options.txt b/meson_options.txt
|
|
|
|
index d17ac1ca8..da90ccfd8 100644
|
|
|
|
--- a/meson_options.txt
|
|
|
|
+++ b/meson_options.txt
|
|
|
|
@@ -54,7 +54,10 @@ option('dsd', type: 'boolean', value: true, description: 'Support the DSD audio
|
|
|
|
# |
|
|
|
|
|
|
|
option('database', type: 'boolean', value: true, description: 'enable support for the music database') |
|
|
|
-option('upnp', type: 'feature', description: 'UPnP client support')
|
|
|
|
+option('upnp', type: 'combo',
|
|
|
|
+ choices: ['auto', 'pupnp', 'npupnp', 'disabled'],
|
|
|
|
+ value: 'auto',
|
|
|
|
+ description: 'UPnP client support')
|
|
|
|
option('libmpdclient', type: 'feature', description: 'libmpdclient support (for the proxy database plugin)') |
|
|
|
|
|
|
|
# |
|
|
|
diff --git a/src/db/plugins/upnp/ContentDirectoryService.cxx b/src/db/plugins/upnp/ContentDirectoryService.cxx
|
|
|
|
index 99893d89d..29d58ca23 100644
|
|
|
|
--- a/src/db/plugins/upnp/ContentDirectoryService.cxx
|
|
|
|
+++ b/src/db/plugins/upnp/ContentDirectoryService.cxx
|
|
|
|
@@ -18,7 +18,10 @@
|
|
|
|
*/ |
|
|
|
|
|
|
|
#include "lib/upnp/ContentDirectoryService.hxx" |
|
|
|
+#include "config.h"
|
|
|
|
+#ifdef USING_PUPNP
|
|
|
|
#include "lib/upnp/ixmlwrap.hxx" |
|
|
|
+#endif
|
|
|
|
#include "lib/upnp/UniqueIxml.hxx" |
|
|
|
#include "lib/upnp/Action.hxx" |
|
|
|
#include "Directory.hxx" |
|
|
|
@@ -28,8 +31,11 @@
|
|
|
|
#include "util/ScopeExit.hxx" |
|
|
|
#include "util/StringFormat.hxx" |
|
|
|
|
|
|
|
+#include <algorithm>
|
|
|
|
+
|
|
|
|
#include <stdio.h> |
|
|
|
|
|
|
|
+#ifdef USING_PUPNP
|
|
|
|
static void |
|
|
|
ReadResultTag(UPnPDirContent &dirbuf, IXML_Document *response) |
|
|
|
{ |
|
|
|
@@ -39,6 +45,7 @@ ReadResultTag(UPnPDirContent &dirbuf, IXML_Document *response)
|
|
|
|
|
|
|
|
dirbuf.Parse(p); |
|
|
|
} |
|
|
|
+#endif
|
|
|
|
|
|
|
|
inline void |
|
|
|
ContentDirectoryService::readDirSlice(UpnpClient_Handle hdl, |
|
|
|
@@ -47,6 +54,7 @@ ContentDirectoryService::readDirSlice(UpnpClient_Handle hdl,
|
|
|
|
unsigned &didreadp, |
|
|
|
unsigned &totalp) const |
|
|
|
{ |
|
|
|
+#ifdef USING_PUPNP
|
|
|
|
// Some devices require an empty SortCriteria, else bad params |
|
|
|
IXML_Document *request = |
|
|
|
MakeActionHelper("Browse", m_serviceType.c_str(), |
|
|
|
@@ -82,6 +90,37 @@ ContentDirectoryService::readDirSlice(UpnpClient_Handle hdl,
|
|
|
|
totalp = ParseUnsigned(value); |
|
|
|
|
|
|
|
ReadResultTag(dirbuf, response); |
|
|
|
+#else
|
|
|
|
+ std::vector<std::pair<std::string, std::string> > actionParams{
|
|
|
|
+ { "ObjectID", objectId },
|
|
|
|
+ { "BrowseFlag", "BrowseDirectChildren" },
|
|
|
|
+ { "Filter", "*" },
|
|
|
|
+ { "SortCriteria", "" },
|
|
|
|
+ { "StartingIndex", StringFormat<32>("%u", offset).c_str() },
|
|
|
|
+ { "RequestedCount", StringFormat<32>("%u", count).c_str() }
|
|
|
|
+ };
|
|
|
|
+ std::vector<std::pair<std::string, std::string> > responseData;
|
|
|
|
+ int errcode;
|
|
|
|
+ std::string errdesc;
|
|
|
|
+ int code =
|
|
|
|
+ UpnpSendAction(hdl, "", m_actionURL, m_serviceType, "Browse",
|
|
|
|
+ actionParams, responseData, &errcode, errdesc);
|
|
|
|
+ if (code != UPNP_E_SUCCESS)
|
|
|
|
+ throw FormatRuntimeError("UpnpSendAction() failed: %s",
|
|
|
|
+ UpnpGetErrorMessage(code));
|
|
|
|
+ const char *p = "";
|
|
|
|
+ didreadp = 0;
|
|
|
|
+ for (const auto &entry : responseData) {
|
|
|
|
+ if (entry.first == "Result") {
|
|
|
|
+ p = entry.second.c_str();
|
|
|
|
+ } else if (entry.first == "TotalMatches") {
|
|
|
|
+ totalp = ParseUnsigned(entry.second.c_str());
|
|
|
|
+ } else if (entry.first == "NumberReturned") {
|
|
|
|
+ didreadp = ParseUnsigned(entry.second.c_str());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ dirbuf.Parse(p);
|
|
|
|
+#endif
|
|
|
|
} |
|
|
|
|
|
|
|
UPnPDirContent |
|
|
|
@@ -110,6 +149,7 @@ ContentDirectoryService::search(UpnpClient_Handle hdl,
|
|
|
|
unsigned offset = 0, total = -1, count; |
|
|
|
|
|
|
|
do { |
|
|
|
+#ifdef USING_PUPNP
|
|
|
|
UniqueIxmlDocument request(MakeActionHelper("Search", m_serviceType.c_str(), |
|
|
|
"ContainerID", objectId, |
|
|
|
"SearchCriteria", ss, |
|
|
|
@@ -147,6 +187,39 @@ ContentDirectoryService::search(UpnpClient_Handle hdl,
|
|
|
|
total = ParseUnsigned(value); |
|
|
|
|
|
|
|
ReadResultTag(dirbuf, response.get()); |
|
|
|
+#else
|
|
|
|
+ std::vector<std::pair<std::string, std::string> > actionParams{
|
|
|
|
+ { "ContainerID", objectId },
|
|
|
|
+ { "SearchCriteria", ss },
|
|
|
|
+ { "Filter", "*" },
|
|
|
|
+ { "SortCriteria", "" },
|
|
|
|
+ { "StartingIndex",
|
|
|
|
+ StringFormat<32>("%u", offset).c_str() },
|
|
|
|
+ { "RequestedCount", "0" }
|
|
|
|
+ };
|
|
|
|
+ std::vector<std::pair<std::string, std::string> > responseData;
|
|
|
|
+ int errcode;
|
|
|
|
+ std::string errdesc;
|
|
|
|
+ int code = UpnpSendAction(hdl, "", m_actionURL, m_serviceType,
|
|
|
|
+ "Search", actionParams, responseData,
|
|
|
|
+ &errcode, errdesc);
|
|
|
|
+ if (code != UPNP_E_SUCCESS)
|
|
|
|
+ throw FormatRuntimeError("UpnpSendAction() failed: %s",
|
|
|
|
+ UpnpGetErrorMessage(code));
|
|
|
|
+ const char *p = "";
|
|
|
|
+ count = 0;
|
|
|
|
+ for (const auto &entry : responseData) {
|
|
|
|
+ if (entry.first == "Result") {
|
|
|
|
+ p = entry.second.c_str();
|
|
|
|
+ } else if (entry.first == "TotalMatches") {
|
|
|
|
+ total = ParseUnsigned(entry.second.c_str());
|
|
|
|
+ } else if (entry.first == "NumberReturned") {
|
|
|
|
+ count = ParseUnsigned(entry.second.c_str());
|
|
|
|
+ offset += count;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ dirbuf.Parse(p);
|
|
|
|
+#endif
|
|
|
|
} while (count > 0 && offset < total); |
|
|
|
|
|
|
|
return dirbuf; |
|
|
|
@@ -156,6 +229,7 @@ UPnPDirContent
|
|
|
|
ContentDirectoryService::getMetadata(UpnpClient_Handle hdl, |
|
|
|
const char *objectId) const |
|
|
|
{ |
|
|
|
+#ifdef USING_PUPNP
|
|
|
|
// Create request |
|
|
|
UniqueIxmlDocument request(MakeActionHelper("Browse", m_serviceType.c_str(), |
|
|
|
"ObjectID", objectId, |
|
|
|
@@ -179,4 +253,31 @@ ContentDirectoryService::getMetadata(UpnpClient_Handle hdl,
|
|
|
|
UPnPDirContent dirbuf; |
|
|
|
ReadResultTag(dirbuf, response.get()); |
|
|
|
return dirbuf; |
|
|
|
+#else
|
|
|
|
+ std::vector<std::pair<std::string, std::string> > actionParams{
|
|
|
|
+ { "ObjectID", objectId }, { "BrowseFlag", "BrowseMetadata" },
|
|
|
|
+ { "Filter", "*" }, { "SortCriteria", "" },
|
|
|
|
+ { "StartingIndex", "0" }, { "RequestedCount", "1" }
|
|
|
|
+ };
|
|
|
|
+ std::vector<std::pair<std::string, std::string> > responseData;
|
|
|
|
+ int errcode;
|
|
|
|
+ std::string errdesc;
|
|
|
|
+ int code =
|
|
|
|
+ UpnpSendAction(hdl, "", m_actionURL, m_serviceType, "Browse",
|
|
|
|
+ actionParams, responseData, &errcode, errdesc);
|
|
|
|
+ if (code != UPNP_E_SUCCESS)
|
|
|
|
+ throw FormatRuntimeError("UpnpSendAction() failed: %s",
|
|
|
|
+ UpnpGetErrorMessage(code));
|
|
|
|
+ const char *p = "";
|
|
|
|
+ for (const auto &entry : responseData) {
|
|
|
|
+ if (entry.first == "Result") {
|
|
|
|
+ p = entry.second.c_str();
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ UPnPDirContent dirbuf;
|
|
|
|
+ dirbuf.Parse(p);
|
|
|
|
+ return dirbuf;
|
|
|
|
+#endif
|
|
|
|
} |
|
|
|
diff --git a/src/lib/upnp/Action.hxx b/src/lib/upnp/Action.hxx
|
|
|
|
index 49ed75198..4ecf4cb06 100644
|
|
|
|
--- a/src/lib/upnp/Action.hxx
|
|
|
|
+++ b/src/lib/upnp/Action.hxx
|
|
|
|
@@ -38,6 +38,7 @@ CountNameValuePairs(gcc_unused const char *name, gcc_unused const char *value,
|
|
|
|
return 1 + CountNameValuePairs(args...); |
|
|
|
} |
|
|
|
|
|
|
|
+#ifdef USING_PUPNP
|
|
|
|
/** |
|
|
|
* A wrapper for UpnpMakeAction() that counts the number of name/value |
|
|
|
* pairs and adds the nullptr sentinel. |
|
|
|
@@ -52,5 +53,6 @@ MakeActionHelper(const char *action_name, const char *service_type,
|
|
|
|
args..., |
|
|
|
nullptr, nullptr); |
|
|
|
} |
|
|
|
+#endif
|
|
|
|
|
|
|
|
#endif |
|
|
|
diff --git a/src/lib/upnp/ClientInit.cxx b/src/lib/upnp/ClientInit.cxx
|
|
|
|
index 23ba9cade..54b677fa2 100644
|
|
|
|
--- a/src/lib/upnp/ClientInit.cxx
|
|
|
|
+++ b/src/lib/upnp/ClientInit.cxx
|
|
|
|
@@ -31,14 +31,12 @@ static Mutex upnp_client_init_mutex;
|
|
|
|
static unsigned upnp_client_ref; |
|
|
|
static UpnpClient_Handle upnp_client_handle; |
|
|
|
|
|
|
|
-static int
|
|
|
|
-UpnpClientCallback(Upnp_EventType et,
|
|
|
|
-#if UPNP_VERSION >= 10800
|
|
|
|
- const
|
|
|
|
+static int UpnpClientCallback(Upnp_EventType et,
|
|
|
|
+#if 1
|
|
|
|
+ const
|
|
|
|
#endif |
|
|
|
- void *evp,
|
|
|
|
- void *cookie) noexcept
|
|
|
|
-{
|
|
|
|
+ void *evp,
|
|
|
|
+ void *cookie) noexcept {
|
|
|
|
if (cookie == nullptr) |
|
|
|
/* this is the cookie passed to UpnpRegisterClient(); |
|
|
|
but can this ever happen? Will libupnp ever invoke |
|
|
|
diff --git a/src/lib/upnp/Compat.hxx b/src/lib/upnp/Compat.hxx
|
|
|
|
index 7fba1d83b..b9a4d7cf3 100644
|
|
|
|
--- a/src/lib/upnp/Compat.hxx
|
|
|
|
+++ b/src/lib/upnp/Compat.hxx
|
|
|
|
@@ -22,14 +22,14 @@
|
|
|
|
|
|
|
|
#include <upnp.h> |
|
|
|
|
|
|
|
-#if UPNP_VERSION < 10800
|
|
|
|
+#if 0
|
|
|
|
/* emulate the libupnp 1.8 API with older versions */ |
|
|
|
|
|
|
|
using UpnpDiscovery = Upnp_Discovery; |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
-#if UPNP_VERSION < 10624
|
|
|
|
+#if 0
|
|
|
|
#include "util/Compiler.h" |
|
|
|
|
|
|
|
gcc_pure |
|
|
|
diff --git a/src/lib/upnp/ContentDirectoryService.cxx b/src/lib/upnp/ContentDirectoryService.cxx
|
|
|
|
index ae514c717..eed28b41a 100644
|
|
|
|
--- a/src/lib/upnp/ContentDirectoryService.cxx
|
|
|
|
+++ b/src/lib/upnp/ContentDirectoryService.cxx
|
|
|
|
@@ -17,15 +17,21 @@
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
|
|
|
*/ |
|
|
|
|
|
|
|
+#include "config.h"
|
|
|
|
+
|
|
|
|
#include "ContentDirectoryService.hxx" |
|
|
|
#include "UniqueIxml.hxx" |
|
|
|
#include "Device.hxx" |
|
|
|
+#ifdef USING_PUPNP
|
|
|
|
#include "ixmlwrap.hxx" |
|
|
|
+#endif
|
|
|
|
#include "Action.hxx" |
|
|
|
#include "util/UriUtil.hxx" |
|
|
|
#include "util/RuntimeError.hxx" |
|
|
|
#include "util/SplitString.hxx" |
|
|
|
|
|
|
|
+#include <algorithm>
|
|
|
|
+
|
|
|
|
ContentDirectoryService::ContentDirectoryService(const UPnPDevice &device, |
|
|
|
const UPnPService &service) noexcept |
|
|
|
:m_actionURL(uri_apply_base(service.controlURL, device.URLBase)), |
|
|
|
@@ -51,6 +57,7 @@ ContentDirectoryService::~ContentDirectoryService() noexcept
|
|
|
|
std::forward_list<std::string> |
|
|
|
ContentDirectoryService::getSearchCapabilities(UpnpClient_Handle hdl) const |
|
|
|
{ |
|
|
|
+#ifdef USING_PUPNP
|
|
|
|
UniqueIxmlDocument request(UpnpMakeAction("GetSearchCapabilities", m_serviceType.c_str(), |
|
|
|
0, |
|
|
|
nullptr, nullptr)); |
|
|
|
@@ -69,6 +76,24 @@ ContentDirectoryService::getSearchCapabilities(UpnpClient_Handle hdl) const
|
|
|
|
|
|
|
|
const char *s = ixmlwrap::getFirstElementValue(response.get(), |
|
|
|
"SearchCaps"); |
|
|
|
+#else
|
|
|
|
+ std::vector<std::pair<std::string, std::string> > responseData;
|
|
|
|
+ int errcode;
|
|
|
|
+ std::string errdesc;
|
|
|
|
+ auto code = UpnpSendAction(hdl, "", m_actionURL, m_serviceType,
|
|
|
|
+ "GetSearchCapabilities", {}, responseData,
|
|
|
|
+ &errcode, errdesc);
|
|
|
|
+ if (code != UPNP_E_SUCCESS)
|
|
|
|
+ throw FormatRuntimeError("UpnpSendAction() failed: %s",
|
|
|
|
+ UpnpGetErrorMessage(code));
|
|
|
|
+ const char *s{ nullptr };
|
|
|
|
+ for (auto &entry : responseData) {
|
|
|
|
+ if (entry.first == "SearchCaps") {
|
|
|
|
+ s = entry.second.c_str();
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+#endif
|
|
|
|
if (s == nullptr || *s == 0) |
|
|
|
/* we could just "return {}" here, but GCC 5 doesn't |
|
|
|
understand that */ |
|
|
|
diff --git a/src/lib/upnp/Init.cxx b/src/lib/upnp/Init.cxx
|
|
|
|
index 7ad4d565a..10510402a 100644
|
|
|
|
--- a/src/lib/upnp/Init.cxx
|
|
|
|
+++ b/src/lib/upnp/Init.cxx
|
|
|
|
@@ -23,7 +23,9 @@
|
|
|
|
|
|
|
|
#include <upnp.h> |
|
|
|
#include <upnptools.h> |
|
|
|
+#ifdef USING_PUPNP
|
|
|
|
#include <ixml.h> |
|
|
|
+#endif
|
|
|
|
|
|
|
|
#include <assert.h> |
|
|
|
|
|
|
|
@@ -44,8 +46,10 @@ DoInit()
|
|
|
|
|
|
|
|
UpnpSetMaxContentLength(2000*1024); |
|
|
|
|
|
|
|
+#ifdef USING_PUPNP
|
|
|
|
// Servers sometimes make error (e.g.: minidlna returns bad utf-8) |
|
|
|
ixmlRelaxParser(1); |
|
|
|
+#endif
|
|
|
|
} |
|
|
|
|
|
|
|
void |
|
|
|
diff --git a/src/lib/upnp/UniqueIxml.hxx b/src/lib/upnp/UniqueIxml.hxx
|
|
|
|
index 2ff2afa62..8a0ea0a1f 100644
|
|
|
|
--- a/src/lib/upnp/UniqueIxml.hxx
|
|
|
|
+++ b/src/lib/upnp/UniqueIxml.hxx
|
|
|
|
@@ -20,6 +20,7 @@
|
|
|
|
#ifndef MPD_UPNP_UNIQUE_XML_HXX |
|
|
|
#define MPD_UPNP_UNIQUE_XML_HXX |
|
|
|
|
|
|
|
+#ifdef USING_PUPNP
|
|
|
|
#include <ixml.h> |
|
|
|
|
|
|
|
#include <memory> |
|
|
|
@@ -37,4 +38,5 @@ struct UpnpIxmlDeleter {
|
|
|
|
typedef std::unique_ptr<IXML_Document, UpnpIxmlDeleter> UniqueIxmlDocument; |
|
|
|
typedef std::unique_ptr<IXML_NodeList, UpnpIxmlDeleter> UniqueIxmlNodeList; |
|
|
|
|
|
|
|
+#endif /* USING_PUPNP */
|
|
|
|
#endif |
|
|
|
diff --git a/src/lib/upnp/ixmlwrap.cxx b/src/lib/upnp/ixmlwrap.cxx
|
|
|
|
index 4e44f35a6..c7798e557 100644
|
|
|
|
--- a/src/lib/upnp/ixmlwrap.cxx
|
|
|
|
+++ b/src/lib/upnp/ixmlwrap.cxx
|
|
|
|
@@ -15,6 +15,9 @@
|
|
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|
|
|
*/ |
|
|
|
|
|
|
|
+#include "config.h"
|
|
|
|
+
|
|
|
|
+#ifdef USING_PUPNP
|
|
|
|
#include "ixmlwrap.hxx" |
|
|
|
#include "UniqueIxml.hxx" |
|
|
|
|
|
|
|
@@ -39,3 +42,4 @@ getFirstElementValue(IXML_Document *doc, const char *name) noexcept
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
+#endif
|
|
|
|
diff --git a/src/lib/upnp/ixmlwrap.hxx b/src/lib/upnp/ixmlwrap.hxx
|
|
|
|
index 6713d59bd..4b01801f7 100644
|
|
|
|
--- a/src/lib/upnp/ixmlwrap.hxx
|
|
|
|
+++ b/src/lib/upnp/ixmlwrap.hxx
|
|
|
|
@@ -17,6 +17,7 @@
|
|
|
|
#ifndef _IXMLWRAP_H_INCLUDED_ |
|
|
|
#define _IXMLWRAP_H_INCLUDED_ |
|
|
|
|
|
|
|
+#ifdef USING_PUPNP
|
|
|
|
#include <ixml.h> |
|
|
|
|
|
|
|
#include <string> |
|
|
|
@@ -32,4 +33,5 @@ namespace ixmlwrap {
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
+#endif /* USING_PUPNP */
|
|
|
|
#endif /* _IXMLWRAP_H_INCLUDED_ */ |
|
|
|
diff --git a/src/lib/upnp/meson.build b/src/lib/upnp/meson.build
|
|
|
|
index 9e16f7319..bdc248e6c 100644
|
|
|
|
--- a/src/lib/upnp/meson.build
|
|
|
|
+++ b/src/lib/upnp/meson.build
|
|
|
|
@@ -1,4 +1,22 @@
|
|
|
|
-upnp_dep = dependency('libupnp', required: get_option('upnp'))
|
|
|
|
+upnp_option = get_option('upnp')
|
|
|
|
+
|
|
|
|
+if upnp_option == 'auto'
|
|
|
|
+ upnp_dep = dependency('libupnp', version: '>= 1.8', required: false)
|
|
|
|
+ conf.set('USING_PUPNP', upnp_dep.found())
|
|
|
|
+ if not upnp_dep.found()
|
|
|
|
+ upnp_dep = dependency('libnpupnp', version: '>= 1.8', required: false)
|
|
|
|
+ endif
|
|
|
|
+elif upnp_option == 'pupnp'
|
|
|
|
+ upnp_dep = dependency('libupnp', version: '>= 1.8', required: true)
|
|
|
|
+ conf.set('USING_PUPNP', true)
|
|
|
|
+elif upnp_option == 'npupnp'
|
|
|
|
+ upnp_dep = dependency('libnpupnp', required: true)
|
|
|
|
+ conf.set('USING_PUPNP', false)
|
|
|
|
+elif upnp_option == 'disabled'
|
|
|
|
+ upnp_dep = dependency('', required: false)
|
|
|
|
+ subdir_done()
|
|
|
|
+endif
|
|
|
|
+
|
|
|
|
conf.set('ENABLE_UPNP', upnp_dep.found()) |
|
|
|
if not upnp_dep.found() |
|
|
|
subdir_done() |