aboutsummaryrefslogtreecommitdiffstats
path: root/src/db/upnp/Directory.cxx
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2014-01-24 16:18:50 +0100
committerMax Kellermann <max@duempel.org>2014-01-24 16:38:44 +0100
commit9d34fc394ce30a28ec0e43f2ad7172b8de8b3be6 (patch)
tree4b58951bc81b17f16140c7f743a163bd837827bf /src/db/upnp/Directory.cxx
parent973c9872f930d73a8ddc98e4802b242aea9f0dba (diff)
downloadmpd-9d34fc394ce30a28ec0e43f2ad7172b8de8b3be6.tar.gz
mpd-9d34fc394ce30a28ec0e43f2ad7172b8de8b3be6.tar.xz
mpd-9d34fc394ce30a28ec0e43f2ad7172b8de8b3be6.zip
Database*: move to db/
Diffstat (limited to 'src/db/upnp/Directory.cxx')
-rw-r--r--src/db/upnp/Directory.cxx262
1 files changed, 0 insertions, 262 deletions
diff --git a/src/db/upnp/Directory.cxx b/src/db/upnp/Directory.cxx
deleted file mode 100644
index adb8b213a..000000000
--- a/src/db/upnp/Directory.cxx
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * 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 "Directory.hxx"
-#include "Util.hxx"
-#include "Expat.hxx"
-#include "Tags.hxx"
-#include "tag/TagBuilder.hxx"
-#include "tag/TagTable.hxx"
-#include "util/NumberParser.hxx"
-
-#include <algorithm>
-#include <string>
-
-#include <string.h>
-
-UPnPDirContent::~UPnPDirContent()
-{
- /* this destructor exists here just so it won't get inlined */
-}
-
-gcc_pure gcc_nonnull_all
-static bool
-CompareStringLiteral(const char *literal, const char *value, size_t length)
-{
- return length == strlen(literal) &&
- memcmp(literal, value, length) == 0;
-}
-
-gcc_pure
-static UPnPDirObject::ItemClass
-ParseItemClass(const char *name, size_t length)
-{
- if (CompareStringLiteral("object.item.audioItem.musicTrack",
- name, length))
- return UPnPDirObject::ItemClass::MUSIC;
- else if (CompareStringLiteral("object.item.playlistItem",
- name, length))
- return UPnPDirObject::ItemClass::PLAYLIST;
- else
- return UPnPDirObject::ItemClass::UNKNOWN;
-}
-
-gcc_pure
-static int
-ParseDuration(const char *duration)
-{
- char *endptr;
-
- unsigned result = ParseUnsigned(duration, &endptr);
- if (endptr == duration || *endptr != ':')
- return 0;
-
- result *= 60;
- duration = endptr + 1;
- result += ParseUnsigned(duration, &endptr);
- if (endptr == duration || *endptr != ':')
- return 0;
-
- result *= 60;
- duration = endptr + 1;
- result += ParseUnsigned(duration, &endptr);
- if (endptr == duration || *endptr != 0)
- return 0;
-
- return result;
-}
-
-/**
- * Transform titles to turn '/' into '_' to make them acceptable path
- * elements. There is a very slight risk of collision in doing
- * this. Twonky returns directory names (titles) like 'Artist/Album'.
- */
-gcc_pure
-static std::string
-titleToPathElt(std::string &&s)
-{
- std::replace(s.begin(), s.end(), '/', '_');
- return s;
-}
-
-/**
- * An XML parser which builds directory contents from DIDL lite input.
- */
-class UPnPDirParser final : public CommonExpatParser {
- UPnPDirContent &m_dir;
-
- enum {
- NONE,
- RES,
- CLASS,
- } state;
-
- /**
- * If not equal to #TAG_NUM_OF_ITEM_TYPES, then we're
- * currently reading an element containing a tag value. The
- * value is being constructed in #value.
- */
- TagType tag_type;
-
- /**
- * The text inside the current element.
- */
- std::string value;
-
- UPnPDirObject m_tobj;
- TagBuilder tag;
-
-public:
- UPnPDirParser(UPnPDirContent& dir)
- :m_dir(dir),
- state(NONE),
- tag_type(TAG_NUM_OF_ITEM_TYPES)
- {
- }
-
-protected:
- virtual void StartElement(const XML_Char *name, const XML_Char **attrs)
- {
- if (m_tobj.type != UPnPDirObject::Type::UNKNOWN &&
- tag_type == TAG_NUM_OF_ITEM_TYPES) {
- tag_type = tag_table_lookup(upnp_tags, name);
- if (tag_type != TAG_NUM_OF_ITEM_TYPES)
- return;
- } else {
- assert(tag_type == TAG_NUM_OF_ITEM_TYPES);
- }
-
- switch (name[0]) {
- case 'c':
- if (!strcmp(name, "container")) {
- m_tobj.clear();
- m_tobj.type = UPnPDirObject::Type::CONTAINER;
-
- const char *id = GetAttribute(attrs, "id");
- if (id != nullptr)
- m_tobj.m_id = id;
-
- const char *pid = GetAttribute(attrs, "parentID");
- if (pid != nullptr)
- m_tobj.m_pid = pid;
- }
- break;
-
- case 'i':
- if (!strcmp(name, "item")) {
- m_tobj.clear();
- m_tobj.type = UPnPDirObject::Type::ITEM;
-
- const char *id = GetAttribute(attrs, "id");
- if (id != nullptr)
- m_tobj.m_id = id;
-
- const char *pid = GetAttribute(attrs, "parentID");
- if (pid != nullptr)
- m_tobj.m_pid = pid;
- }
- break;
-
- case 'r':
- if (!strcmp(name, "res")) {
- // <res protocolInfo="http-get:*:audio/mpeg:*" size="5171496"
- // bitrate="24576" duration="00:03:35" sampleFrequency="44100"
- // nrAudioChannels="2">
-
- const char *duration =
- GetAttribute(attrs, "duration");
- if (duration != nullptr)
- tag.SetTime(ParseDuration(duration));
-
- state = RES;
- }
-
- break;
-
- case 'u':
- if (strcmp(name, "upnp:class") == 0)
- state = CLASS;
- }
- }
-
- bool checkobjok() {
- if (m_tobj.m_id.empty() || m_tobj.m_pid.empty() ||
- m_tobj.name.empty() ||
- (m_tobj.type == UPnPDirObject::Type::ITEM &&
- m_tobj.item_class == UPnPDirObject::ItemClass::UNKNOWN))
- return false;
-
- return true;
- }
-
- virtual void EndElement(const XML_Char *name)
- {
- if (tag_type != TAG_NUM_OF_ITEM_TYPES) {
- assert(m_tobj.type != UPnPDirObject::Type::UNKNOWN);
-
- tag.AddItem(tag_type, value.c_str());
-
- if (tag_type == TAG_TITLE)
- m_tobj.name = titleToPathElt(std::move(value));
-
- value.clear();
- tag_type = TAG_NUM_OF_ITEM_TYPES;
- return;
- }
-
- if ((!strcmp(name, "container") || !strcmp(name, "item")) &&
- checkobjok()) {
- tag.Commit(m_tobj.tag);
- m_dir.objects.emplace_back(std::move(m_tobj));
- }
-
- state = NONE;
- }
-
- virtual void CharacterData(const XML_Char *s, int len)
- {
- if (tag_type != TAG_NUM_OF_ITEM_TYPES) {
- assert(m_tobj.type != UPnPDirObject::Type::UNKNOWN);
-
- value.append(s, len);
- return;
- }
-
- switch (state) {
- case NONE:
- break;
-
- case RES:
- m_tobj.url.assign(s, len);
- break;
-
- case CLASS:
- m_tobj.item_class = ParseItemClass(s, len);
- break;
- }
- }
-};
-
-bool
-UPnPDirContent::parse(const char *input, Error &error)
-{
- UPnPDirParser parser(*this);
- return parser.Parse(input, strlen(input), true, error);
-}