db/upnp: move the LibUPnP instance to class UpnpDatabase

Delete the object when closing the database.
This commit is contained in:
Max Kellermann 2014-01-16 09:06:01 +01:00
parent 02769929b3
commit a35c7bc81a
7 changed files with 49 additions and 77 deletions

View File

@ -159,14 +159,18 @@ UpnpDatabase::Configure(const config_param &, Error &)
bool bool
UpnpDatabase::Open(Error &error) UpnpDatabase::Open(Error &error)
{ {
m_lib = LibUPnP::getLibUPnP(error); m_lib = new LibUPnP();
if (!m_lib) if (!m_lib->ok()) {
error.Set(m_lib->GetInitError());
delete m_lib;
return false; return false;
}
m_superdir = new UPnPDeviceDirectory(); m_superdir = new UPnPDeviceDirectory(m_lib);
if (!m_superdir->ok()) { if (!m_superdir->ok()) {
error.Set(m_superdir->GetError()); error.Set(m_superdir->GetError());
delete m_superdir; delete m_superdir;
delete m_lib;
return false; return false;
} }
@ -182,7 +186,7 @@ UpnpDatabase::Close()
{ {
delete m_root; delete m_root;
delete m_superdir; delete m_superdir;
// TBD decide what we do with the lib object delete m_lib;
} }
void void
@ -285,7 +289,7 @@ UpnpDatabase::SearchSongs(ContentDirectoryService* server,
return true; return true;
std::set<std::string> searchcaps; std::set<std::string> searchcaps;
if (!server->getSearchCapabilities(searchcaps, error)) if (!server->getSearchCapabilities(m_lib->getclh(), searchcaps, error))
return false; return false;
if (searchcaps.empty()) if (searchcaps.empty())
@ -352,7 +356,9 @@ UpnpDatabase::SearchSongs(ContentDirectoryService* server,
} }
} }
return server->search(objid, cond.c_str(), dirbuf, error); return server->search(m_lib->getclh(),
objid, cond.c_str(), dirbuf,
error);
} }
static bool static bool
@ -433,7 +439,7 @@ UpnpDatabase::ReadNode(ContentDirectoryService *server,
Error &error) const Error &error) const
{ {
UPnPDirContent dirbuf; UPnPDirContent dirbuf;
if (!server->getMetadata(objid, dirbuf, error)) if (!server->getMetadata(m_lib->getclh(), objid, dirbuf, error))
return false; return false;
if (dirbuf.objects.size() == 1) { if (dirbuf.objects.size() == 1) {
@ -484,10 +490,12 @@ UpnpDatabase::Namei(ContentDirectoryService* server,
return true; return true;
} }
const UpnpClient_Handle handle = m_lib->getclh();
// Walk the path elements, read each directory and try to find the next one // Walk the path elements, read each directory and try to find the next one
for (unsigned int i = 0; i < vpath.size(); i++) { for (unsigned int i = 0; i < vpath.size(); i++) {
UPnPDirContent dirbuf; UPnPDirContent dirbuf;
if (!server->readDir(objid.c_str(), dirbuf, error)) if (!server->readDir(handle, objid.c_str(), dirbuf, error))
return false; return false;
// Look for the name in the sub-container list // Look for the name in the sub-container list
@ -611,7 +619,7 @@ UpnpDatabase::VisitServer(ContentDirectoryService* server,
and loop here, but it's not useful as mpd will only return and loop here, but it's not useful as mpd will only return
data to the client when we're done anyway. */ data to the client when we're done anyway. */
UPnPDirContent dirbuf; UPnPDirContent dirbuf;
if (!server->readDir(objid.c_str(), dirbuf, error)) if (!server->readDir(m_lib->getclh(), objid.c_str(), dirbuf, error))
return false; return false;
for (const auto &dirent : dirbuf.objects) { for (const auto &dirent : dirbuf.objects) {

View File

@ -24,12 +24,10 @@
#include "ixmlwrap.hxx" #include "ixmlwrap.hxx"
#include "Directory.hxx" #include "Directory.hxx"
#include "Util.hxx" #include "Util.hxx"
#include "upnpplib.hxx"
#include "util/Error.hxx" #include "util/Error.hxx"
#include <stdio.h> #include <stdio.h>
#include <upnp/upnp.h>
#include <upnp/upnptools.h> #include <upnp/upnptools.h>
ContentDirectoryService::ContentDirectoryService(const UPnPDevice &device, ContentDirectoryService::ContentDirectoryService(const UPnPDevice &device,
@ -64,17 +62,12 @@ public:
}; };
bool bool
ContentDirectoryService::readDirSlice(const char *objectId, int offset, ContentDirectoryService::readDirSlice(UpnpClient_Handle hdl,
const char *objectId, int offset,
int count, UPnPDirContent &dirbuf, int count, UPnPDirContent &dirbuf,
int *didreadp, int *totalp, int *didreadp, int *totalp,
Error &error) Error &error)
{ {
LibUPnP *lib = LibUPnP::getLibUPnP(error);
if (lib == nullptr)
return false;
UpnpClient_Handle hdl = lib->getclh();
IXML_Document *request(0); IXML_Document *request(0);
IXML_Document *response(0); IXML_Document *response(0);
DirBResFree cleaner(&request, &response); DirBResFree cleaner(&request, &response);
@ -132,7 +125,8 @@ ContentDirectoryService::readDirSlice(const char *objectId, int offset,
} }
bool bool
ContentDirectoryService::readDir(const char *objectId, ContentDirectoryService::readDir(UpnpClient_Handle handle,
const char *objectId,
UPnPDirContent &dirbuf, UPnPDirContent &dirbuf,
Error &error) Error &error)
{ {
@ -141,7 +135,7 @@ ContentDirectoryService::readDir(const char *objectId,
while (offset < total) { while (offset < total) {
int count; int count;
if (!readDirSlice(objectId, offset, m_rdreqcnt, dirbuf, if (!readDirSlice(handle, objectId, offset, m_rdreqcnt, dirbuf,
&count, &total, error)) &count, &total, error))
return false; return false;
@ -152,17 +146,12 @@ ContentDirectoryService::readDir(const char *objectId,
} }
bool bool
ContentDirectoryService::search(const char *objectId, ContentDirectoryService::search(UpnpClient_Handle hdl,
const char *objectId,
const char *ss, const char *ss,
UPnPDirContent &dirbuf, UPnPDirContent &dirbuf,
Error &error) Error &error)
{ {
LibUPnP *lib = LibUPnP::getLibUPnP(error);
if (lib == nullptr)
return false;
UpnpClient_Handle hdl = lib->getclh();
IXML_Document *request(0); IXML_Document *request(0);
IXML_Document *response(0); IXML_Document *response(0);
@ -226,15 +215,10 @@ ContentDirectoryService::search(const char *objectId,
} }
bool bool
ContentDirectoryService::getSearchCapabilities(std::set<std::string> &result, ContentDirectoryService::getSearchCapabilities(UpnpClient_Handle hdl,
std::set<std::string> &result,
Error &error) Error &error)
{ {
LibUPnP *lib = LibUPnP::getLibUPnP(error);
if (lib == nullptr)
return false;
UpnpClient_Handle hdl = lib->getclh();
IXML_Document *request(0); IXML_Document *request(0);
IXML_Document *response(0); IXML_Document *response(0);
@ -272,16 +256,11 @@ ContentDirectoryService::getSearchCapabilities(std::set<std::string> &result,
} }
bool bool
ContentDirectoryService::getMetadata(const char *objectId, ContentDirectoryService::getMetadata(UpnpClient_Handle hdl,
const char *objectId,
UPnPDirContent &dirbuf, UPnPDirContent &dirbuf,
Error &error) Error &error)
{ {
LibUPnP *lib = LibUPnP::getLibUPnP(error);
if (lib == nullptr)
return false;
UpnpClient_Handle hdl = lib->getclh();
IXML_Document *response(0); IXML_Document *response(0);
// Create request // Create request

View File

@ -20,6 +20,8 @@
#ifndef _UPNPDIR_HXX_INCLUDED_ #ifndef _UPNPDIR_HXX_INCLUDED_
#define _UPNPDIR_HXX_INCLUDED_ #define _UPNPDIR_HXX_INCLUDED_
#include <upnp/upnp.h>
#include <string> #include <string>
#include <set> #include <set>
@ -71,10 +73,12 @@ public:
* @param objectId the UPnP object Id for the container. Root has Id "0" * @param objectId the UPnP object Id for the container. Root has Id "0"
* @param[out] dirbuf stores the entries we read. * @param[out] dirbuf stores the entries we read.
*/ */
bool readDir(const char *objectId, UPnPDirContent &dirbuf, bool readDir(UpnpClient_Handle handle,
const char *objectId, UPnPDirContent &dirbuf,
Error &error); Error &error);
bool readDirSlice(const char *objectId, int offset, bool readDirSlice(UpnpClient_Handle handle,
const char *objectId, int offset,
int count, UPnPDirContent& dirbuf, int count, UPnPDirContent& dirbuf,
int *didread, int *total, int *didread, int *total,
Error &error); Error &error);
@ -89,7 +93,8 @@ public:
* section 2.5.5. Maybe we'll provide an easier way some day... * section 2.5.5. Maybe we'll provide an easier way some day...
* @param[out] dirbuf stores the entries we read. * @param[out] dirbuf stores the entries we read.
*/ */
bool search(const char *objectId, const char *searchstring, bool search(UpnpClient_Handle handle,
const char *objectId, const char *searchstring,
UPnPDirContent &dirbuf, UPnPDirContent &dirbuf,
Error &error); Error &error);
@ -99,7 +104,8 @@ public:
* @param[out] dirbuf stores the entries we read. At most one entry will be * @param[out] dirbuf stores the entries we read. At most one entry will be
* returned. * returned.
*/ */
bool getMetadata(const char *objectId, UPnPDirContent &dirbuf, bool getMetadata(UpnpClient_Handle handle,
const char *objectId, UPnPDirContent &dirbuf,
Error &error); Error &error);
/** Retrieve search capabilities /** Retrieve search capabilities
@ -107,7 +113,8 @@ public:
* @param[out] result an empty vector: no search, or a single '*' element: * @param[out] result an empty vector: no search, or a single '*' element:
* any tag can be used in a search, or a list of usable tag names. * any tag can be used in a search, or a list of usable tag names.
*/ */
bool getSearchCapabilities(std::set<std::string> &result, bool getSearchCapabilities(UpnpClient_Handle handle,
std::set<std::string> &result,
Error &error); Error &error);
/** Retrieve the "friendly name" for this server, useful for display. */ /** Retrieve the "friendly name" for this server, useful for display. */

View File

@ -216,18 +216,14 @@ UPnPDeviceDirectory::expireDevices()
search(); search();
} }
UPnPDeviceDirectory::UPnPDeviceDirectory() UPnPDeviceDirectory::UPnPDeviceDirectory(LibUPnP *_lib)
:m_searchTimeout(2), m_lastSearch(0) :lib(_lib), m_searchTimeout(2), m_lastSearch(0)
{ {
if (!discoveredQueue.start(1, discoExplorer, 0)) { if (!discoveredQueue.start(1, discoExplorer, 0)) {
error.Set(upnp_domain, "Discover work queue start failed"); error.Set(upnp_domain, "Discover work queue start failed");
return; return;
} }
LibUPnP *lib = LibUPnP::getLibUPnP(error);
if (lib == nullptr)
return;
lib->SetHandler([](Upnp_EventType type, void *event){ lib->SetHandler([](Upnp_EventType type, void *event){
cluCallBack(type, event); cluCallBack(type, event);
}); });
@ -243,10 +239,6 @@ UPnPDeviceDirectory::search()
return true; return true;
m_lastSearch = now; m_lastSearch = now;
LibUPnP *lib = LibUPnP::getLibUPnP(error);
if (lib == nullptr)
return false;
// We search both for device and service just in case. // We search both for device and service just in case.
int code = UpnpSearchAsync(lib->getclh(), m_searchTimeout, int code = UpnpSearchAsync(lib->getclh(), m_searchTimeout,
ContentDirectorySType, lib); ContentDirectorySType, lib);

View File

@ -26,6 +26,7 @@
#include <time.h> #include <time.h>
class LibUPnP;
class ContentDirectoryService; class ContentDirectoryService;
/** /**
@ -35,6 +36,8 @@ class ContentDirectoryService;
* for now, but this could be made more general, by removing the filtering. * for now, but this could be made more general, by removing the filtering.
*/ */
class UPnPDeviceDirectory { class UPnPDeviceDirectory {
LibUPnP *const lib;
Error error; Error error;
/** /**
@ -47,7 +50,7 @@ class UPnPDeviceDirectory {
time_t m_lastSearch; time_t m_lastSearch;
public: public:
UPnPDeviceDirectory(); UPnPDeviceDirectory(LibUPnP *_lib);
UPnPDeviceDirectory(const UPnPDeviceDirectory &) = delete; UPnPDeviceDirectory(const UPnPDeviceDirectory &) = delete;
UPnPDeviceDirectory& operator=(const UPnPDeviceDirectory &) = delete; UPnPDeviceDirectory& operator=(const UPnPDeviceDirectory &) = delete;

View File

@ -27,20 +27,6 @@
static LibUPnP *theLib; static LibUPnP *theLib;
LibUPnP *
LibUPnP::getLibUPnP(Error &error)
{
if (theLib == nullptr)
theLib = new LibUPnP;
if (!theLib->ok()) {
error.Set(theLib->GetInitError());
return nullptr;
}
return theLib;
}
LibUPnP::LibUPnP() LibUPnP::LibUPnP()
{ {
auto code = UpnpInit(0, 0); auto code = UpnpInit(0, 0);

View File

@ -35,19 +35,16 @@ class LibUPnP {
Handler handler; Handler handler;
static int o_callback(Upnp_EventType, void *, void *);
public:
LibUPnP(); LibUPnP();
LibUPnP(const LibUPnP &) = delete; LibUPnP(const LibUPnP &) = delete;
LibUPnP &operator=(const LibUPnP &) = delete; LibUPnP &operator=(const LibUPnP &) = delete;
static int o_callback(Upnp_EventType, void *, void *);
public:
~LibUPnP(); ~LibUPnP();
/** Retrieve the singleton LibUPnP object */
static LibUPnP *getLibUPnP(Error &error);
/** Check state after initialization */ /** Check state after initialization */
bool ok() const bool ok() const
{ {