db/upnp/Object: add attribute "tag"

Replaces "m_title" and "m_props".  More bloat removed.
This commit is contained in:
Max Kellermann 2014-01-14 21:25:43 +01:00
parent 4bcaf5d306
commit 676d8bb624
3 changed files with 26 additions and 83 deletions

View File

@ -210,21 +210,7 @@ upnpItemToSong(const UPnPDirObject &dirent, const char *uri)
uri = dirent.url.c_str(); uri = dirent.url.c_str();
Song *s = Song::NewFile(uri, nullptr); Song *s = Song::NewFile(uri, nullptr);
s->tag = new Tag(dirent.tag);
TagBuilder tag;
if (dirent.duration > 0)
tag.SetTime(dirent.duration);
tag.AddItem(TAG_TITLE, dirent.m_title.c_str());
for (auto i = upnp_tags; i->name != nullptr; ++i) {
const char *value = dirent.getprop(i->name);
if (value != nullptr)
tag.AddItem(i->type, value);
}
s->tag = tag.CommitNew();
return s; return s;
} }
@ -267,27 +253,6 @@ UpnpDatabase::GetSong(const char *uri, Error &error) const
return song; return song;
} }
/**
* Retrieve the value for an MPD tag from an object entry.
*/
gcc_pure
static const char *
getTagValue(const UPnPDirObject &dirent, TagType tag)
{
if (tag == TAG_TITLE) {
if (!dirent.m_title.empty())
return dirent.m_title.c_str();
return nullptr;
}
const char *name = tag_table_lookup(upnp_tags, tag);
if (name == nullptr)
return nullptr;
return dirent.getprop(name);
}
/** /**
* Double-quote a string, adding internal backslash escaping. * Double-quote a string, adding internal backslash escaping.
*/ */
@ -801,7 +766,7 @@ UpnpDatabase::VisitUniqueTags(const DatabaseSelection &selection,
dirent.item_class != UPnPDirObject::ItemClass::MUSIC) dirent.item_class != UPnPDirObject::ItemClass::MUSIC)
continue; continue;
const char *value = getTagValue(dirent, tag); const char *value = dirent.tag.GetValue(tag);
if (value != nullptr) { if (value != nullptr) {
#if defined(__clang__) || GCC_CHECK_VERSION(4,8) #if defined(__clang__) || GCC_CHECK_VERSION(4,8)
values.emplace(value); values.emplace(value);

View File

@ -21,6 +21,9 @@
#include "Directory.hxx" #include "Directory.hxx"
#include "Util.hxx" #include "Util.hxx"
#include "Expat.hxx" #include "Expat.hxx"
#include "Tags.hxx"
#include "tag/TagBuilder.hxx"
#include "tag/TagTable.hxx"
#include <algorithm> #include <algorithm>
#include <string> #include <string>
@ -28,14 +31,6 @@
#include <string.h> #include <string.h>
static const char *const upnptags[] = {
"upnp:artist",
"upnp:album",
"upnp:genre",
"upnp:originalTrackNumber",
nullptr,
};
gcc_pure gcc_pure
static UPnPDirObject::ItemClass static UPnPDirObject::ItemClass
ParseItemClass(const char *name) ParseItemClass(const char *name)
@ -77,6 +72,7 @@ titleToPathElt(std::string &&s)
class UPnPDirParser final : public CommonExpatParser { class UPnPDirParser final : public CommonExpatParser {
std::vector<std::string> m_path; std::vector<std::string> m_path;
UPnPDirObject m_tobj; UPnPDirObject m_tobj;
TagBuilder tag;
public: public:
UPnPDirParser(UPnPDirContent& dir) UPnPDirParser(UPnPDirContent& dir)
@ -130,7 +126,7 @@ protected:
const char *duration = const char *duration =
GetAttribute(attrs, "duration"); GetAttribute(attrs, "duration");
if (duration != nullptr) if (duration != nullptr)
m_tobj.duration = ParseDuration(duration); tag.SetTime(ParseDuration(duration));
} }
break; break;
@ -150,8 +146,10 @@ protected:
virtual void EndElement(const XML_Char *name) virtual void EndElement(const XML_Char *name)
{ {
if ((!strcmp(name, "container") || !strcmp(name, "item")) && if ((!strcmp(name, "container") || !strcmp(name, "item")) &&
checkobjok()) checkobjok()) {
tag.Commit(m_tobj.tag);
m_dir.objects.push_back(std::move(m_tobj)); m_dir.objects.push_back(std::move(m_tobj));
}
m_path.pop_back(); m_path.pop_back();
} }
@ -160,14 +158,19 @@ protected:
{ {
std::string str(s, len); std::string str(s, len);
trimstring(str); trimstring(str);
switch (m_path.back()[0]) {
case 'd':
if (!m_path.back().compare("dc:title")) {
m_tobj.m_title = str;
m_tobj.name = titleToPathElt(std::move(str));
}
break; TagType type = tag_table_lookup(upnp_tags,
m_path.back().c_str());
if (type != TAG_NUM_OF_ITEM_TYPES) {
tag.AddItem(type, str.c_str());
if (type == TAG_TITLE)
m_tobj.name = titleToPathElt(std::move(str));
return;
}
switch (m_path.back()[0]) {
case 'r': case 'r':
if (!m_path.back().compare("res")) { if (!m_path.back().compare("res")) {
m_tobj.url = str; m_tobj.url = str;
@ -178,10 +181,6 @@ protected:
m_tobj.item_class = ParseItemClass(str.c_str()); m_tobj.item_class = ParseItemClass(str.c_str());
break; break;
} }
for (auto i = upnptags; *i != nullptr; ++i)
if (!m_path.back().compare(*i))
m_tobj.m_props[*i] += str;
break; break;
} }
} }

View File

@ -20,8 +20,9 @@
#ifndef MPD_UPNP_OBJECT_HXX #ifndef MPD_UPNP_OBJECT_HXX
#define MPD_UPNP_OBJECT_HXX #define MPD_UPNP_OBJECT_HXX
#include "tag/Tag.hxx"
#include <string> #include <string>
#include <map>
/** /**
* UpnP Media Server directory entry, converted from XML data. * UpnP Media Server directory entry, converted from XML data.
@ -61,43 +62,21 @@ public:
std::string m_title; // dc:title. Directory name for a container. std::string m_title; // dc:title. Directory name for a container.
Type type; Type type;
ItemClass item_class; ItemClass item_class;
// Properties as gathered from the XML document (url, artist, etc.)
// The map keys are the XML tag or attribute names.
std::map<std::string, std::string> m_props;
/** Tag tag;
* Song duration in seconds. 0 if unknown.
*/
int duration;
UPnPDirObject() = default; UPnPDirObject() = default;
UPnPDirObject(UPnPDirObject &&) = default; UPnPDirObject(UPnPDirObject &&) = default;
UPnPDirObject &operator=(UPnPDirObject &&) = default; UPnPDirObject &operator=(UPnPDirObject &&) = default;
/** Get named property
* @param property name (e.g. upnp:artist, upnp:album,
* upnp:originalTrackNumber, upnp:genre). Use m_title instead
* for dc:title.
* @param[out] value
* @return true if found.
*/
const char *getprop(const char *_name) const {
auto it = m_props.find(_name);
if (it == m_props.end())
return nullptr;
return it->second.c_str();
}
void clear() void clear()
{ {
m_id.clear(); m_id.clear();
m_pid.clear(); m_pid.clear();
url.clear(); url.clear();
m_title.clear();
type = Type::UNKNOWN; type = Type::UNKNOWN;
item_class = ItemClass::UNKNOWN; item_class = ItemClass::UNKNOWN;
m_props.clear(); tag.Clear();
duration = -1;
} }
}; };