aboutsummaryrefslogtreecommitdiffstats
path: root/src/playlist
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2014-01-07 21:39:47 +0100
committerMax Kellermann <max@duempel.org>2014-01-09 09:05:58 +0100
commit322b0616322760dc162447563d8f4da7e024ca90 (patch)
tree2f87cb3ce061556161797aba9f57ee08de5b9e21 /src/playlist
parent43847f2244a34064af24704aac4cfad4a3c76f7d (diff)
downloadmpd-322b0616322760dc162447563d8f4da7e024ca90.tar.gz
mpd-322b0616322760dc162447563d8f4da7e024ca90.tar.xz
mpd-322b0616322760dc162447563d8f4da7e024ca90.zip
DetachedSong: fork of struct Song
From now on, struct Song will be used by the database only, and DetachedSong will be used by everybody else. DetachedSong is easier to use, but Song has lower overhead.
Diffstat (limited to 'src/playlist')
-rw-r--r--src/playlist/AsxPlaylistPlugin.cxx42
-rw-r--r--src/playlist/CuePlaylistPlugin.cxx6
-rw-r--r--src/playlist/DespotifyPlaylistPlugin.cxx16
-rw-r--r--src/playlist/EmbeddedCuePlaylistPlugin.cxx16
-rw-r--r--src/playlist/ExtM3uPlaylistPlugin.cxx13
-rw-r--r--src/playlist/M3uPlaylistPlugin.cxx8
-rw-r--r--src/playlist/PlsPlaylistPlugin.cxx17
-rw-r--r--src/playlist/RssPlaylistPlugin.cxx42
-rw-r--r--src/playlist/SoundCloudPlaylistPlugin.cxx8
-rw-r--r--src/playlist/XspfPlaylistPlugin.cxx37
10 files changed, 69 insertions, 136 deletions
diff --git a/src/playlist/AsxPlaylistPlugin.cxx b/src/playlist/AsxPlaylistPlugin.cxx
index ccd98a711..11bdc93d6 100644
--- a/src/playlist/AsxPlaylistPlugin.cxx
+++ b/src/playlist/AsxPlaylistPlugin.cxx
@@ -43,7 +43,7 @@ struct AsxParser {
* The list of songs (in reverse order because that's faster
* while adding).
*/
- std::forward_list<SongPointer> songs;
+ std::forward_list<DetachedSong> songs;
/**
* The current position in the XML file.
@@ -60,10 +60,9 @@ struct AsxParser {
TagType tag_type;
/**
- * The current song. It is allocated after the "location"
- * element.
+ * The current song URI. It is set by the "ref" element.
*/
- Song *song;
+ std::string location;
TagBuilder tag_builder;
@@ -96,7 +95,7 @@ asx_start_element(gcc_unused GMarkupParseContext *context,
case AsxParser::ROOT:
if (StringEqualsCaseASCII(element_name, "entry")) {
parser->state = AsxParser::ENTRY;
- parser->song = Song::NewRemote("asx:");
+ parser->location.clear();
parser->tag_type = TAG_NUM_OF_ITEM_TYPES;
}
@@ -107,17 +106,8 @@ asx_start_element(gcc_unused GMarkupParseContext *context,
const gchar *href = get_attribute(attribute_names,
attribute_values,
"href");
- if (href != nullptr) {
- /* create new song object; we cannot
- replace the existing song's URI,
- because that attribute is
- immutable */
- Song *song = Song::NewRemote(href);
- if (parser->song != nullptr)
- parser->song->Free();
-
- parser->song = song;
- }
+ if (href != nullptr)
+ parser->location = href;
} else if (StringEqualsCaseASCII(element_name, "author"))
/* is that correct? or should it be COMPOSER
or PERFORMER? */
@@ -142,12 +132,9 @@ asx_end_element(gcc_unused GMarkupParseContext *context,
case AsxParser::ENTRY:
if (StringEqualsCaseASCII(element_name, "entry")) {
- if (strcmp(parser->song->uri, "asx:") != 0) {
- assert(parser->song->tag == nullptr);
- parser->song->tag = parser->tag_builder.CommitNew();
- parser->songs.emplace_front(parser->song);
- } else
- parser->song->Free();
+ if (!parser->location.empty())
+ parser->songs.emplace_front(std::move(parser->location),
+ parser->tag_builder.Commit());
parser->state = AsxParser::ROOT;
} else
@@ -186,15 +173,6 @@ static const GMarkupParser asx_parser = {
nullptr,
};
-static void
-asx_parser_destroy(gpointer data)
-{
- AsxParser *parser = (AsxParser *)data;
-
- if (parser->state >= AsxParser::ENTRY)
- parser->song->Free();
-}
-
/*
* The playlist object
*
@@ -215,7 +193,7 @@ asx_open_stream(InputStream &is)
context = g_markup_parse_context_new(&asx_parser,
G_MARKUP_TREAT_CDATA_AS_TEXT,
- &parser, asx_parser_destroy);
+ &parser, nullptr);
while (true) {
nbytes = is.LockRead(buffer, sizeof(buffer), error2);
diff --git a/src/playlist/CuePlaylistPlugin.cxx b/src/playlist/CuePlaylistPlugin.cxx
index 00aa758b0..1da76d372 100644
--- a/src/playlist/CuePlaylistPlugin.cxx
+++ b/src/playlist/CuePlaylistPlugin.cxx
@@ -36,7 +36,7 @@ class CuePlaylist final : public SongEnumerator {
:is(_is), tis(is) {
}
- virtual Song *NextSong() override;
+ virtual DetachedSong *NextSong() override;
};
static SongEnumerator *
@@ -45,10 +45,10 @@ cue_playlist_open_stream(InputStream &is)
return new CuePlaylist(is);
}
-Song *
+DetachedSong *
CuePlaylist::NextSong()
{
- Song *song = parser.Get();
+ DetachedSong *song = parser.Get();
if (song != nullptr)
return song;
diff --git a/src/playlist/DespotifyPlaylistPlugin.cxx b/src/playlist/DespotifyPlaylistPlugin.cxx
index 67400e20a..d73c7fe72 100644
--- a/src/playlist/DespotifyPlaylistPlugin.cxx
+++ b/src/playlist/DespotifyPlaylistPlugin.cxx
@@ -23,7 +23,7 @@
#include "PlaylistPlugin.hxx"
#include "MemorySongEnumerator.hxx"
#include "tag/Tag.hxx"
-#include "Song.hxx"
+#include "DetachedSong.hxx"
#include "Log.hxx"
extern "C" {
@@ -34,10 +34,9 @@ extern "C" {
#include <stdlib.h>
static void
-add_song(std::forward_list<SongPointer> &songs, ds_track &track)
+add_song(std::forward_list<DetachedSong> &songs, ds_track &track)
{
const char *dsp_scheme = despotify_playlist_plugin.schemes[0];
- Song *song;
char uri[128];
char *ds_uri;
@@ -52,15 +51,12 @@ add_song(std::forward_list<SongPointer> &songs, ds_track &track)
return;
}
- song = Song::NewRemote(uri);
- song->tag = new Tag(mpd_despotify_tag_from_track(track));
-
- songs.emplace_front(song);
+ songs.emplace_front(uri, mpd_despotify_tag_from_track(track));
}
static bool
parse_track(struct despotify_session *session,
- std::forward_list<SongPointer> &songs,
+ std::forward_list<DetachedSong> &songs,
struct ds_link *link)
{
struct ds_track *track = despotify_link_get_track(session, link);
@@ -73,7 +69,7 @@ parse_track(struct despotify_session *session,
static bool
parse_playlist(struct despotify_session *session,
- std::forward_list<SongPointer> &songs,
+ std::forward_list<DetachedSong> &songs,
struct ds_link *link)
{
ds_playlist *playlist = despotify_link_get_playlist(session, link);
@@ -103,7 +99,7 @@ despotify_playlist_open_uri(const char *url,
return nullptr;
}
- std::forward_list<SongPointer> songs;
+ std::forward_list<DetachedSong> songs;
bool parse_result;
switch (link->type) {
diff --git a/src/playlist/EmbeddedCuePlaylistPlugin.cxx b/src/playlist/EmbeddedCuePlaylistPlugin.cxx
index 9dfecbf46..77df51778 100644
--- a/src/playlist/EmbeddedCuePlaylistPlugin.cxx
+++ b/src/playlist/EmbeddedCuePlaylistPlugin.cxx
@@ -30,7 +30,7 @@
#include "tag/TagHandler.hxx"
#include "tag/TagId3.hxx"
#include "tag/ApeTag.hxx"
-#include "Song.hxx"
+#include "DetachedSong.hxx"
#include "TagFile.hxx"
#include "cue/CueParser.hxx"
#include "fs/Traits.hxx"
@@ -69,7 +69,7 @@ public:
delete parser;
}
- virtual Song *NextSong() override;
+ virtual DetachedSong *NextSong() override;
};
static void
@@ -124,10 +124,10 @@ embcue_playlist_open_uri(const char *uri,
return playlist;
}
-Song *
+DetachedSong *
EmbeddedCuePlaylist::NextSong()
{
- Song *song = parser->Get();
+ DetachedSong *song = parser->Get();
if (song != nullptr)
return song;
@@ -145,14 +145,16 @@ EmbeddedCuePlaylist::NextSong()
parser->Feed(line);
song = parser->Get();
- if (song != nullptr)
- return song->ReplaceURI(filename.c_str());
+ if (song != nullptr) {
+ song->SetURI(filename);
+ return song;
+ }
}
parser->Finish();
song = parser->Get();
if (song != nullptr)
- song = song->ReplaceURI(filename.c_str());
+ song->SetURI(filename);
return song;
}
diff --git a/src/playlist/ExtM3uPlaylistPlugin.cxx b/src/playlist/ExtM3uPlaylistPlugin.cxx
index 4f0c111ad..51211988c 100644
--- a/src/playlist/ExtM3uPlaylistPlugin.cxx
+++ b/src/playlist/ExtM3uPlaylistPlugin.cxx
@@ -21,7 +21,7 @@
#include "ExtM3uPlaylistPlugin.hxx"
#include "PlaylistPlugin.hxx"
#include "SongEnumerator.hxx"
-#include "Song.hxx"
+#include "DetachedSong.hxx"
#include "tag/Tag.hxx"
#include "tag/TagBuilder.hxx"
#include "util/StringUtil.hxx"
@@ -44,7 +44,7 @@ public:
strcmp(line.c_str(), "#EXTM3U") == 0;
}
- virtual Song *NextSong() override;
+ virtual DetachedSong *NextSong() override;
};
static SongEnumerator *
@@ -101,20 +101,19 @@ extm3u_parse_tag(const char *line)
return tag.CommitNew();
}
-Song *
+DetachedSong *
ExtM3uPlaylist::NextSong()
{
Tag *tag = NULL;
std::string line;
const char *line_s;
- Song *song;
do {
if (!tis.ReadLine(line)) {
delete tag;
return NULL;
}
-
+
line_s = line.c_str();
if (StringStartsWith(line_s, "#EXTINF:")) {
@@ -126,8 +125,8 @@ ExtM3uPlaylist::NextSong()
line_s = strchug_fast(line_s);
} while (line_s[0] == '#' || *line_s == 0);
- song = Song::NewRemote(line_s);
- song->tag = tag;
+ DetachedSong *song = new DetachedSong(line_s, std::move(*tag));
+ delete tag;
return song;
}
diff --git a/src/playlist/M3uPlaylistPlugin.cxx b/src/playlist/M3uPlaylistPlugin.cxx
index 3f99bdfdf..09f2c91cb 100644
--- a/src/playlist/M3uPlaylistPlugin.cxx
+++ b/src/playlist/M3uPlaylistPlugin.cxx
@@ -21,7 +21,7 @@
#include "M3uPlaylistPlugin.hxx"
#include "PlaylistPlugin.hxx"
#include "SongEnumerator.hxx"
-#include "Song.hxx"
+#include "DetachedSong.hxx"
#include "util/StringUtil.hxx"
#include "TextInputStream.hxx"
@@ -33,7 +33,7 @@ public:
:tis(is) {
}
- virtual Song *NextSong() override;
+ virtual DetachedSong *NextSong() override;
};
static SongEnumerator *
@@ -42,7 +42,7 @@ m3u_open_stream(InputStream &is)
return new M3uPlaylist(is);
}
-Song *
+DetachedSong *
M3uPlaylist::NextSong()
{
std::string line;
@@ -56,7 +56,7 @@ M3uPlaylist::NextSong()
line_s = strchug_fast(line_s);
} while (line_s[0] == '#' || *line_s == 0);
- return Song::NewRemote(line_s);
+ return new DetachedSong(line_s);
}
static const char *const m3u_suffixes[] = {
diff --git a/src/playlist/PlsPlaylistPlugin.cxx b/src/playlist/PlsPlaylistPlugin.cxx
index 3fd420d89..103451dfe 100644
--- a/src/playlist/PlsPlaylistPlugin.cxx
+++ b/src/playlist/PlsPlaylistPlugin.cxx
@@ -22,7 +22,7 @@
#include "PlaylistPlugin.hxx"
#include "MemorySongEnumerator.hxx"
#include "InputStream.hxx"
-#include "Song.hxx"
+#include "DetachedSong.hxx"
#include "tag/TagBuilder.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
@@ -37,7 +37,7 @@
static constexpr Domain pls_domain("pls");
static void
-pls_parser(GKeyFile *keyfile, std::forward_list<SongPointer> &songs)
+pls_parser(GKeyFile *keyfile, std::forward_list<DetachedSong> &songs)
{
gchar *value;
GError *error = nullptr;
@@ -61,8 +61,8 @@ pls_parser(GKeyFile *keyfile, std::forward_list<SongPointer> &songs)
for (; num_entries > 0; --num_entries) {
char key[64];
sprintf(key, "File%u", num_entries);
- value = g_key_file_get_string(keyfile, "playlist", key,
- &error);
+ char *uri = g_key_file_get_string(keyfile, "playlist", key,
+ &error);
if(error) {
FormatError(pls_domain, "Invalid PLS entry %s: '%s'",
key, error->message);
@@ -70,9 +70,6 @@ pls_parser(GKeyFile *keyfile, std::forward_list<SongPointer> &songs)
return;
}
- Song *song = Song::NewRemote(value);
- g_free(value);
-
TagBuilder tag;
sprintf(key, "Title%u", num_entries);
@@ -89,8 +86,8 @@ pls_parser(GKeyFile *keyfile, std::forward_list<SongPointer> &songs)
if (length > 0)
tag.SetTime(length);
- song->tag = tag.CommitNew();
- songs.emplace_front(song);
+ songs.emplace_front(uri, tag.Commit());
+ g_free(uri);
}
}
@@ -135,7 +132,7 @@ pls_open_stream(InputStream &is)
return nullptr;
}
- std::forward_list<SongPointer> songs;
+ std::forward_list<DetachedSong> songs;
pls_parser(keyfile, songs);
g_key_file_free(keyfile);
diff --git a/src/playlist/RssPlaylistPlugin.cxx b/src/playlist/RssPlaylistPlugin.cxx
index c4dd2f8c3..558c74619 100644
--- a/src/playlist/RssPlaylistPlugin.cxx
+++ b/src/playlist/RssPlaylistPlugin.cxx
@@ -43,7 +43,7 @@ struct RssParser {
* The list of songs (in reverse order because that's faster
* while adding).
*/
- std::forward_list<SongPointer> songs;
+ std::forward_list<DetachedSong> songs;
/**
* The current position in the XML file.
@@ -60,10 +60,10 @@ struct RssParser {
TagType tag_type;
/**
- * The current song. It is allocated after the "location"
+ * The current song URI. It is set by the "enclosure"
* element.
*/
- Song *song;
+ std::string location;
TagBuilder tag_builder;
@@ -95,7 +95,7 @@ rss_start_element(gcc_unused GMarkupParseContext *context,
case RssParser::ROOT:
if (StringEqualsCaseASCII(element_name, "item")) {
parser->state = RssParser::ITEM;
- parser->song = Song::NewRemote("rss:");
+ parser->location.clear();
parser->tag_type = TAG_NUM_OF_ITEM_TYPES;
}
@@ -106,18 +106,8 @@ rss_start_element(gcc_unused GMarkupParseContext *context,
const gchar *href = get_attribute(attribute_names,
attribute_values,
"url");
- if (href != nullptr) {
- /* create new song object; we cannot
- replace the existing song's URI,
- because that attribute is
- immutable */
- Song *song = Song::NewRemote(href);
-
- if (parser->song != nullptr)
- parser->song->Free();
-
- parser->song = song;
- }
+ if (href != nullptr)
+ parser->location = href;
} else if (StringEqualsCaseASCII(element_name, "title"))
parser->tag_type = TAG_TITLE;
else if (StringEqualsCaseASCII(element_name, "itunes:author"))
@@ -140,12 +130,9 @@ rss_end_element(gcc_unused GMarkupParseContext *context,
case RssParser::ITEM:
if (StringEqualsCaseASCII(element_name, "item")) {
- if (strcmp(parser->song->uri, "rss:") != 0) {
- assert(parser->song->tag == nullptr);
- parser->song->tag = parser->tag_builder.CommitNew();
- parser->songs.emplace_front(parser->song);
- } else
- parser->song->Free();
+ if (!parser->location.empty())
+ parser->songs.emplace_front(std::move(parser->location),
+ parser->tag_builder.Commit());
parser->state = RssParser::ROOT;
} else
@@ -183,15 +170,6 @@ static const GMarkupParser rss_parser = {
nullptr,
};
-static void
-rss_parser_destroy(gpointer data)
-{
- RssParser *parser = (RssParser *)data;
-
- if (parser->state >= RssParser::ITEM)
- parser->song->Free();
-}
-
/*
* The playlist object
*
@@ -212,7 +190,7 @@ rss_open_stream(InputStream &is)
context = g_markup_parse_context_new(&rss_parser,
G_MARKUP_TREAT_CDATA_AS_TEXT,
- &parser, rss_parser_destroy);
+ &parser, nullptr);
while (true) {
nbytes = is.LockRead(buffer, sizeof(buffer), error2);
diff --git a/src/playlist/SoundCloudPlaylistPlugin.cxx b/src/playlist/SoundCloudPlaylistPlugin.cxx
index cfbd0e8b5..50a9cb214 100644
--- a/src/playlist/SoundCloudPlaylistPlugin.cxx
+++ b/src/playlist/SoundCloudPlaylistPlugin.cxx
@@ -108,7 +108,7 @@ struct parse_data {
char* title;
int got_url; /* nesting level of last stream_url */
- std::forward_list<SongPointer> songs;
+ std::forward_list<DetachedSong> songs;
};
static int
@@ -214,16 +214,14 @@ handle_end_map(void *ctx)
char *u = g_strconcat(data->stream_url, "?client_id=",
soundcloud_config.apikey.c_str(), nullptr);
- Song *s = Song::NewRemote(u);
- g_free(u);
TagBuilder tag;
tag.SetTime(data->duration / 1000);
if (data->title != nullptr)
tag.AddItem(TAG_NAME, data->title);
- s->tag = tag.CommitNew();
- data->songs.emplace_front(s);
+ data->songs.emplace_front(u, tag.Commit());
+ g_free(u);
return 1;
}
diff --git a/src/playlist/XspfPlaylistPlugin.cxx b/src/playlist/XspfPlaylistPlugin.cxx
index 08fe49191..7c20df57d 100644
--- a/src/playlist/XspfPlaylistPlugin.cxx
+++ b/src/playlist/XspfPlaylistPlugin.cxx
@@ -21,6 +21,7 @@
#include "XspfPlaylistPlugin.hxx"
#include "PlaylistPlugin.hxx"
#include "MemorySongEnumerator.hxx"
+#include "DetachedSong.hxx"
#include "InputStream.hxx"
#include "tag/TagBuilder.hxx"
#include "util/Error.hxx"
@@ -41,7 +42,7 @@ struct XspfParser {
* The list of songs (in reverse order because that's faster
* while adding).
*/
- std::forward_list<SongPointer> songs;
+ std::forward_list<DetachedSong> songs;
/**
* The current position in the XML file.
@@ -59,10 +60,9 @@ struct XspfParser {
TagType tag_type;
/**
- * The current song. It is allocated after the "location"
- * element.
+ * The current song URI. It is set by the "location" element.
*/
- Song *song;
+ std::string location;
TagBuilder tag_builder;
@@ -95,7 +95,7 @@ xspf_start_element(gcc_unused GMarkupParseContext *context,
case XspfParser::TRACKLIST:
if (strcmp(element_name, "track") == 0) {
parser->state = XspfParser::TRACK;
- parser->song = nullptr;
+ parser->location.clear();
parser->tag_type = TAG_NUM_OF_ITEM_TYPES;
}
@@ -149,11 +149,9 @@ xspf_end_element(gcc_unused GMarkupParseContext *context,
case XspfParser::TRACK:
if (strcmp(element_name, "track") == 0) {
- if (parser->song != nullptr) {
- assert(parser->song->tag == nullptr);
- parser->song->tag = parser->tag_builder.CommitNew();
- parser->songs.emplace_front(parser->song);
- }
+ if (!parser->location.empty())
+ parser->songs.emplace_front(std::move(parser->location),
+ parser->tag_builder.Commit());
parser->state = XspfParser::TRACKLIST;
} else
@@ -181,7 +179,7 @@ xspf_text(gcc_unused GMarkupParseContext *context,
break;
case XspfParser::TRACK:
- if (parser->song != nullptr &&
+ if (!parser->location.empty() &&
parser->tag_type != TAG_NUM_OF_ITEM_TYPES)
parser->tag_builder.AddItem(parser->tag_type,
text, text_len);
@@ -189,11 +187,7 @@ xspf_text(gcc_unused GMarkupParseContext *context,
break;
case XspfParser::LOCATION:
- if (parser->song == nullptr) {
- char *uri = g_strndup(text, text_len);
- parser->song = Song::NewRemote(uri);
- g_free(uri);
- }
+ parser->location.assign(text, text_len);
break;
}
@@ -207,15 +201,6 @@ static const GMarkupParser xspf_parser = {
nullptr,
};
-static void
-xspf_parser_destroy(gpointer data)
-{
- XspfParser *parser = (XspfParser *)data;
-
- if (parser->state >= XspfParser::TRACK && parser->song != nullptr)
- parser->song->Free();
-}
-
/*
* The playlist object
*
@@ -236,7 +221,7 @@ xspf_open_stream(InputStream &is)
context = g_markup_parse_context_new(&xspf_parser,
G_MARKUP_TREAT_CDATA_AS_TEXT,
- &parser, xspf_parser_destroy);
+ &parser, nullptr);
while (true) {
nbytes = is.LockRead(buffer, sizeof(buffer), error2);