aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2014-01-19 10:51:34 +0100
committerMax Kellermann <max@duempel.org>2014-01-19 17:04:51 +0100
commitf5ae1ce00b85699291a7cdf9782574e70a8c28f5 (patch)
tree9cb95dd1d98b1b0cd522ee27d7e8a374a3c8eb4a /src
parent738d6f10409037fbf8aa30cec5aceb121e21e230 (diff)
downloadmpd-f5ae1ce00b85699291a7cdf9782574e70a8c28f5.tar.gz
mpd-f5ae1ce00b85699291a7cdf9782574e70a8c28f5.tar.xz
mpd-f5ae1ce00b85699291a7cdf9782574e70a8c28f5.zip
LightSong: new class to be used by DatabasePlugin callbacks
Detach the Song class completely from the public API, only to be used by SimpleDatabase and the update thread.
Diffstat (limited to '')
-rw-r--r--src/DatabaseHelpers.cxx10
-rw-r--r--src/DatabasePlaylist.cxx2
-rw-r--r--src/DatabasePlugin.hxx8
-rw-r--r--src/DatabasePrint.cxx29
-rw-r--r--src/DatabaseQueue.cxx2
-rw-r--r--src/DatabaseSelection.cxx2
-rw-r--r--src/DatabaseSelection.hxx4
-rw-r--r--src/DatabaseSong.cxx2
-rw-r--r--src/DatabaseVisitor.hxx4
-rw-r--r--src/DetachedSong.cxx6
-rw-r--r--src/DetachedSong.hxx6
-rw-r--r--src/Directory.cxx23
-rw-r--r--src/LightSong.cxx (renamed from test/FakeSong.cxx)20
-rw-r--r--src/LightSong.hxx82
-rw-r--r--src/Mapper.cxx2
-rw-r--r--src/Mapper.hxx3
-rw-r--r--src/PlaylistEdit.cxx1
-rw-r--r--src/PlaylistPrint.cxx6
-rw-r--r--src/PlaylistSave.cxx1
-rw-r--r--src/PlaylistSong.cxx1
-rw-r--r--src/PlaylistUpdate.cxx6
-rw-r--r--src/Song.cxx21
-rw-r--r--src/Song.hxx6
-rw-r--r--src/SongFilter.cxx33
-rw-r--r--src/SongFilter.hxx9
-rw-r--r--src/SongPrint.cxx14
-rw-r--r--src/SongPrint.hxx6
-rw-r--r--src/SongSticker.cxx17
-rw-r--r--src/SongSticker.hxx14
-rw-r--r--src/TagPrint.cxx3
-rw-r--r--src/TagSave.cxx3
-rw-r--r--src/UpdateRemove.cxx3
-rw-r--r--src/command/StickerCommands.cxx10
-rw-r--r--src/db/LazyDatabase.cxx4
-rw-r--r--src/db/LazyDatabase.hxx6
-rw-r--r--src/db/ProxyDatabasePlugin.cxx129
-rw-r--r--src/db/SimpleDatabasePlugin.cxx30
-rw-r--r--src/db/SimpleDatabasePlugin.hxx12
-rw-r--r--src/db/UpnpDatabasePlugin.cxx71
-rw-r--r--src/playlist/AsxPlaylistPlugin.cxx1
-rw-r--r--src/playlist/RssPlaylistPlugin.cxx1
-rw-r--r--src/playlist/SoundCloudPlaylistPlugin.cxx1
42 files changed, 381 insertions, 233 deletions
diff --git a/src/DatabaseHelpers.cxx b/src/DatabaseHelpers.cxx
index e7bd006f0..58e7aaa3b 100644
--- a/src/DatabaseHelpers.cxx
+++ b/src/DatabaseHelpers.cxx
@@ -19,7 +19,7 @@
#include "DatabaseHelpers.hxx"
#include "DatabasePlugin.hxx"
-#include "Song.hxx"
+#include "LightSong.hxx"
#include "tag/Tag.hxx"
#include <functional>
@@ -37,9 +37,9 @@ struct StringLess {
typedef std::set<const char *, StringLess> StringSet;
static bool
-CollectTags(StringSet &set, TagType tag_type, Song &song)
+CollectTags(StringSet &set, TagType tag_type, const LightSong &song)
{
- const Tag *tag = &song.tag;
+ const Tag *tag = song.tag;
bool found = false;
for (unsigned i = 0; i < tag->num_items; ++i) {
@@ -102,11 +102,11 @@ StatsVisitTag(DatabaseStats &stats, StringSet &artists, StringSet &albums,
static bool
StatsVisitSong(DatabaseStats &stats, StringSet &artists, StringSet &albums,
- Song &song)
+ const LightSong &song)
{
++stats.song_count;
- StatsVisitTag(stats, artists, albums, song.tag);
+ StatsVisitTag(stats, artists, albums, *song.tag);
return true;
}
diff --git a/src/DatabasePlaylist.cxx b/src/DatabasePlaylist.cxx
index 5f7c85a78..58742ca64 100644
--- a/src/DatabasePlaylist.cxx
+++ b/src/DatabasePlaylist.cxx
@@ -30,7 +30,7 @@
static bool
AddSong(const char *playlist_path_utf8,
- Song &song, Error &error)
+ const LightSong &song, Error &error)
{
return spl_append_song(playlist_path_utf8, map_song_detach(song),
error);
diff --git a/src/DatabasePlugin.hxx b/src/DatabasePlugin.hxx
index 3af44d7dd..2ded7f736 100644
--- a/src/DatabasePlugin.hxx
+++ b/src/DatabasePlugin.hxx
@@ -35,7 +35,7 @@
struct config_param;
struct DatabaseSelection;
struct db_visitor;
-struct Song;
+struct LightSong;
class Error;
class EventLoop;
class DatabaseListener;
@@ -94,14 +94,14 @@ public:
* @param uri_utf8 the URI of the song within the music
* directory (UTF-8)
*/
- virtual Song *GetSong(const char *uri_utf8,
- Error &error) const = 0;
+ virtual const LightSong *GetSong(const char *uri_utf8,
+ Error &error) const = 0;
/**
* Mark the song object as "unused". Call this on objects
* returned by GetSong().
*/
- virtual void ReturnSong(Song *song) const = 0;
+ virtual void ReturnSong(const LightSong *song) const = 0;
/**
* Visit the selected entities.
diff --git a/src/DatabasePrint.cxx b/src/DatabasePrint.cxx
index 514cf3f7b..7b5975275 100644
--- a/src/DatabasePrint.cxx
+++ b/src/DatabasePrint.cxx
@@ -26,7 +26,7 @@
#include "Directory.hxx"
#include "Client.hxx"
#include "tag/Tag.hxx"
-#include "Song.hxx"
+#include "LightSong.hxx"
#include "DatabaseGlue.hxx"
#include "DatabasePlugin.hxx"
@@ -52,6 +52,17 @@ PrintDirectoryFull(Client &client, const Directory &directory)
return true;
}
+static void
+print_playlist_in_directory(Client &client,
+ const char *directory,
+ const char *name_utf8)
+{
+ if (directory == nullptr)
+ client_printf(client, "playlist: %s\n", name_utf8);
+ else
+ client_printf(client, "playlist: %s/%s\n",
+ directory, name_utf8);
+}
static void
print_playlist_in_directory(Client &client,
@@ -66,25 +77,25 @@ print_playlist_in_directory(Client &client,
}
static bool
-PrintSongBrief(Client &client, const Song &song)
+PrintSongBrief(Client &client, const LightSong &song)
{
song_print_uri(client, song);
- if (song.tag.has_playlist)
+ if (song.tag->has_playlist)
/* this song file has an embedded CUE sheet */
- print_playlist_in_directory(client, song.parent, song.uri);
+ print_playlist_in_directory(client, song.directory, song.uri);
return true;
}
static bool
-PrintSongFull(Client &client, const Song &song)
+PrintSongFull(Client &client, const LightSong &song)
{
song_print_info(client, song);
- if (song.tag.has_playlist)
+ if (song.tag->has_playlist)
/* this song file has an embedded CUE sheet */
- print_playlist_in_directory(client, song.parent, song.uri);
+ print_playlist_in_directory(client, song.directory, song.uri);
return true;
}
@@ -146,7 +157,7 @@ static void printSearchStats(Client &client, SearchStats *stats)
}
static bool
-stats_visitor_song(SearchStats &stats, Song &song)
+stats_visitor_song(SearchStats &stats, const LightSong &song)
{
stats.numberOfSongs++;
stats.playTime += song.GetDuration();
@@ -195,7 +206,7 @@ printInfoForAllIn(Client &client, const char *uri_utf8,
}
static bool
-PrintSongURIVisitor(Client &client, Song &song)
+PrintSongURIVisitor(Client &client, const LightSong &song)
{
song_print_uri(client, song);
diff --git a/src/DatabaseQueue.cxx b/src/DatabaseQueue.cxx
index 0ed073285..ee1dbd57c 100644
--- a/src/DatabaseQueue.cxx
+++ b/src/DatabaseQueue.cxx
@@ -29,7 +29,7 @@
#include <functional>
static bool
-AddToQueue(Partition &partition, const Song &song, Error &error)
+AddToQueue(Partition &partition, const LightSong &song, Error &error)
{
PlaylistResult result =
partition.playlist.AppendSong(partition.pc,
diff --git a/src/DatabaseSelection.cxx b/src/DatabaseSelection.cxx
index 1dedafec0..035321252 100644
--- a/src/DatabaseSelection.cxx
+++ b/src/DatabaseSelection.cxx
@@ -31,7 +31,7 @@ DatabaseSelection::DatabaseSelection(const char *_uri, bool _recursive,
}
bool
-DatabaseSelection::Match(const Song &song) const
+DatabaseSelection::Match(const LightSong &song) const
{
return filter == nullptr || filter->Match(song);
}
diff --git a/src/DatabaseSelection.hxx b/src/DatabaseSelection.hxx
index 3447b5eee..a39ce7afe 100644
--- a/src/DatabaseSelection.hxx
+++ b/src/DatabaseSelection.hxx
@@ -25,7 +25,7 @@
#include <string>
class SongFilter;
-struct Song;
+struct LightSong;
struct DatabaseSelection {
/**
@@ -45,7 +45,7 @@ struct DatabaseSelection {
const SongFilter *_filter=nullptr);
gcc_pure
- bool Match(const Song &song) const;
+ bool Match(const LightSong &song) const;
};
#endif
diff --git a/src/DatabaseSong.cxx b/src/DatabaseSong.cxx
index a8f2188cc..592d38b85 100644
--- a/src/DatabaseSong.cxx
+++ b/src/DatabaseSong.cxx
@@ -31,7 +31,7 @@ DatabaseDetachSong(const char *uri, Error &error)
if (db == nullptr)
return nullptr;
- Song *tmp = db->GetSong(uri, error);
+ const LightSong *tmp = db->GetSong(uri, error);
if (tmp == nullptr)
return nullptr;
diff --git a/src/DatabaseVisitor.hxx b/src/DatabaseVisitor.hxx
index 6f7ff3deb..486407765 100644
--- a/src/DatabaseVisitor.hxx
+++ b/src/DatabaseVisitor.hxx
@@ -23,12 +23,12 @@
#include <functional>
struct Directory;
-struct Song;
+struct LightSong;
struct PlaylistInfo;
class Error;
typedef std::function<bool(const Directory &, Error &)> VisitDirectory;
-typedef std::function<bool(struct Song &, Error &)> VisitSong;
+typedef std::function<bool(const LightSong &, Error &)> VisitSong;
typedef std::function<bool(const PlaylistInfo &, const Directory &,
Error &)> VisitPlaylist;
diff --git a/src/DetachedSong.cxx b/src/DetachedSong.cxx
index e8b75f618..4e52afb0c 100644
--- a/src/DetachedSong.cxx
+++ b/src/DetachedSong.cxx
@@ -19,13 +19,13 @@
#include "config.h"
#include "DetachedSong.hxx"
-#include "Song.hxx"
+#include "LightSong.hxx"
#include "util/UriUtil.hxx"
#include "fs/Traits.hxx"
-DetachedSong::DetachedSong(const Song &other)
+DetachedSong::DetachedSong(const LightSong &other)
:uri(other.GetURI().c_str()),
- tag(other.tag),
+ tag(*other.tag),
mtime(other.mtime),
start_ms(other.start_ms), end_ms(other.end_ms) {}
diff --git a/src/DetachedSong.hxx b/src/DetachedSong.hxx
index 7d841a4c2..2ef3cdf3e 100644
--- a/src/DetachedSong.hxx
+++ b/src/DetachedSong.hxx
@@ -29,10 +29,10 @@
#include <time.h>
-struct Song;
+struct LightSong;
class DetachedSong {
- friend DetachedSong map_song_detach(const Song &song);
+ friend DetachedSong map_song_detach(const LightSong &song);
/**
* An UTF-8-encoded URI referring to the song file. This can
@@ -62,7 +62,7 @@ class DetachedSong {
*/
unsigned end_ms;
- explicit DetachedSong(const Song &other);
+ explicit DetachedSong(const LightSong &other);
public:
explicit DetachedSong(const DetachedSong &other)
diff --git a/src/Directory.cxx b/src/Directory.cxx
index ff2c00b05..210d7cb67 100644
--- a/src/Directory.cxx
+++ b/src/Directory.cxx
@@ -24,6 +24,7 @@
#include "DatabaseLock.hxx"
#include "SongSort.hxx"
#include "Song.hxx"
+#include "LightSong.hxx"
#include "fs/Traits.hxx"
#include "util/Alloc.hxx"
#include "util/Error.hxx"
@@ -251,6 +252,20 @@ Directory::Sort()
child->Sort();
}
+static LightSong
+ExportSong(const Song &src)
+{
+ LightSong dest;
+ dest.directory = src.parent->IsRoot()
+ ? nullptr : src.parent->GetPath();
+ dest.uri = src.uri;
+ dest.tag = &src.tag;
+ dest.mtime = src.mtime;
+ dest.start_ms = src.start_ms;
+ dest.end_ms = src.end_ms;
+ return dest;
+}
+
bool
Directory::Walk(bool recursive, const SongFilter *filter,
VisitDirectory visit_directory, VisitSong visit_song,
@@ -261,10 +276,12 @@ Directory::Walk(bool recursive, const SongFilter *filter,
if (visit_song) {
Song *song;
- directory_for_each_song(song, *this)
- if ((filter == nullptr || filter->Match(*song)) &&
- !visit_song(*song, error))
+ directory_for_each_song(song, *this) {
+ const LightSong song2 = ExportSong(*song);
+ if ((filter == nullptr || filter->Match(song2)) &&
+ !visit_song(song2, error))
return false;
+ }
}
if (visit_playlist) {
diff --git a/test/FakeSong.cxx b/src/LightSong.cxx
index e2fae4d6e..af1e801f8 100644
--- a/test/FakeSong.cxx
+++ b/src/LightSong.cxx
@@ -17,17 +17,17 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include "config.h"
-#include "Song.hxx"
-#include "directory.h"
-#include "Compiler.h"
+#include "LightSong.hxx"
+#include "tag/Tag.hxx"
-#include <stdlib.h>
+double
+LightSong::GetDuration() const
+{
+ if (end_ms > 0)
+ return (end_ms - start_ms) / 1000.0;
-struct directory detached_root;
+ if (tag->time <= 0)
+ return 0;
-Song *
-song_dup_detached(gcc_unused const Song *src)
-{
- abort();
+ return tag->time - start_ms / 1000.0;
}
diff --git a/src/LightSong.hxx b/src/LightSong.hxx
new file mode 100644
index 000000000..b93d5876c
--- /dev/null
+++ b/src/LightSong.hxx
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+#ifndef MPD_LIGHT_SONG_HXX
+#define MPD_LIGHT_SONG_HXX
+
+#include "Compiler.h"
+
+#include <string>
+
+#include <time.h>
+
+struct Tag;
+
+/**
+ * A reference to a song file. Unlike the other "Song" classes in the
+ * MPD code base, this one consists only of pointers. It is supposed
+ * to be as light as possible while still providing all the
+ * information MPD has about a song file. This class does not manage
+ * any memory, and the pointers become invalid quickly. Only to be
+ * used to pass around during well-defined situations.
+ */
+struct LightSong {
+ /**
+ * If this is not nullptr, then it denotes a prefix for the
+ * #uri. To build the full URI, join directory and uri with a
+ * slash.
+ */
+ const char *directory;
+
+ const char *uri;
+
+ /**
+ * Must not be nullptr.
+ */
+ const Tag *tag;
+
+ time_t mtime;
+
+ /**
+ * Start of this sub-song within the file in milliseconds.
+ */
+ unsigned start_ms;
+
+ /**
+ * End of this sub-song within the file in milliseconds.
+ * Unused if zero.
+ */
+ unsigned end_ms;
+
+ gcc_pure
+ std::string GetURI() const {
+ if (directory == nullptr)
+ return std::string(uri);
+
+ std::string result(directory);
+ result.push_back('/');
+ result.append(uri);
+ return result;
+ }
+
+ gcc_pure
+ double GetDuration() const;
+};
+
+#endif
diff --git a/src/Mapper.cxx b/src/Mapper.cxx
index d41fba957..8fafce12d 100644
--- a/src/Mapper.cxx
+++ b/src/Mapper.cxx
@@ -218,7 +218,7 @@ map_detached_song_fs(const char *uri_utf8)
}
DetachedSong
-map_song_detach(const Song &song)
+map_song_detach(const LightSong &song)
{
return DetachedSong(song);
}
diff --git a/src/Mapper.hxx b/src/Mapper.hxx
index 18a5ca3fe..5c01a9aff 100644
--- a/src/Mapper.hxx
+++ b/src/Mapper.hxx
@@ -33,6 +33,7 @@
class AllocatedPath;
struct Directory;
struct Song;
+struct LightSong;
class DetachedSong;
void
@@ -112,7 +113,7 @@ map_directory_child_fs(const Directory &directory, const char *name);
*/
gcc_pure
DetachedSong
-map_song_detach(const Song &song);
+map_song_detach(const LightSong &song);
/**
* Determines the file system path of a song. This must not be a
diff --git a/src/PlaylistEdit.cxx b/src/PlaylistEdit.cxx
index 0eea62e18..cbae02fef 100644
--- a/src/PlaylistEdit.cxx
+++ b/src/PlaylistEdit.cxx
@@ -29,7 +29,6 @@
#include "PlayerControl.hxx"
#include "util/UriUtil.hxx"
#include "util/Error.hxx"
-#include "Song.hxx"
#include "DetachedSong.hxx"
#include "Mapper.hxx"
#include "Idle.hxx"
diff --git a/src/PlaylistPrint.cxx b/src/PlaylistPrint.cxx
index dcd0953d6..34143d8a8 100644
--- a/src/PlaylistPrint.cxx
+++ b/src/PlaylistPrint.cxx
@@ -30,12 +30,14 @@
#include "DatabasePlugin.hxx"
#include "Client.hxx"
#include "InputStream.hxx"
-#include "Song.hxx"
#include "DetachedSong.hxx"
#include "fs/Traits.hxx"
#include "util/Error.hxx"
#include "thread/Cond.hxx"
+#define SONG_FILE "file: "
+#define SONG_TIME "Time: "
+
void
playlist_print_uris(Client &client, const playlist &playlist)
{
@@ -118,7 +120,7 @@ PrintSongDetails(Client &client, const char *uri_utf8)
if (db == nullptr)
return false;
- Song *song = db->GetSong(uri_utf8, IgnoreError());
+ auto *song = db->GetSong(uri_utf8, IgnoreError());
if (song == nullptr)
return false;
diff --git a/src/PlaylistSave.cxx b/src/PlaylistSave.cxx
index 6d9b41b62..9a01aa954 100644
--- a/src/PlaylistSave.cxx
+++ b/src/PlaylistSave.cxx
@@ -22,7 +22,6 @@
#include "PlaylistFile.hxx"
#include "PlaylistError.hxx"
#include "Playlist.hxx"
-#include "Song.hxx"
#include "DetachedSong.hxx"
#include "Mapper.hxx"
#include "Idle.hxx"
diff --git a/src/PlaylistSong.cxx b/src/PlaylistSong.cxx
index 5d61c7f71..5d3011988 100644
--- a/src/PlaylistSong.cxx
+++ b/src/PlaylistSong.cxx
@@ -29,7 +29,6 @@
#include "util/UriUtil.hxx"
#include "util/Error.hxx"
#include "DetachedSong.hxx"
-#include "Song.hxx"
#include <assert.h>
#include <string.h>
diff --git a/src/PlaylistUpdate.cxx b/src/PlaylistUpdate.cxx
index 55b2e9f0a..755589786 100644
--- a/src/PlaylistUpdate.cxx
+++ b/src/PlaylistUpdate.cxx
@@ -21,7 +21,7 @@
#include "Playlist.hxx"
#include "DatabaseGlue.hxx"
#include "DatabasePlugin.hxx"
-#include "Song.hxx"
+#include "LightSong.hxx"
#include "DetachedSong.hxx"
#include "tag/Tag.hxx"
#include "Idle.hxx"
@@ -35,7 +35,7 @@ UpdatePlaylistSong(const Database &db, DetachedSong &song)
from the Database */
return false;
- Song *original = db.GetSong(song.GetURI(), IgnoreError());
+ const LightSong *original = db.GetSong(song.GetURI(), IgnoreError());
if (original == nullptr)
/* not found - shouldn't happen, because the update
thread should ensure that all stale Song instances
@@ -49,7 +49,7 @@ UpdatePlaylistSong(const Database &db, DetachedSong &song)
}
song.SetLastModified(original->mtime);
- song.SetTag(original->tag);
+ song.SetTag(*original->tag);
db.ReturnSong(original);
return true;
diff --git a/src/Song.cxx b/src/Song.cxx
index 384307642..565b9af98 100644
--- a/src/Song.cxx
+++ b/src/Song.cxx
@@ -23,6 +23,7 @@
#include "tag/Tag.hxx"
#include "util/VarSize.hxx"
#include "DetachedSong.hxx"
+#include "LightSong.hxx"
#include <assert.h>
#include <string.h>
@@ -94,14 +95,16 @@ Song::GetURI() const
}
}
-double
-Song::GetDuration() const
+LightSong
+Song::Export() const
{
- if (end_ms > 0)
- return (end_ms - start_ms) / 1000.0;
-
- if (tag.time <= 0)
- return 0;
-
- return tag.time - start_ms / 1000.0;
+ LightSong dest;
+ dest.directory = parent->IsRoot()
+ ? nullptr : parent->GetPath();
+ dest.uri = uri;
+ dest.tag = &tag;
+ dest.mtime = mtime;
+ dest.start_ms = start_ms;
+ dest.end_ms = end_ms;
+ return dest;
}
diff --git a/src/Song.hxx b/src/Song.hxx
index 81f9f0c90..824fb429c 100644
--- a/src/Song.hxx
+++ b/src/Song.hxx
@@ -29,9 +29,7 @@
#include <assert.h>
#include <time.h>
-#define SONG_FILE "file: "
-#define SONG_TIME "Time: "
-
+struct LightSong;
struct Directory;
class DetachedSong;
@@ -112,7 +110,7 @@ struct Song {
std::string GetURI() const;
gcc_pure
- double GetDuration() const;
+ LightSong Export() const;
};
#endif
diff --git a/src/SongFilter.cxx b/src/SongFilter.cxx
index dccbab925..594ac3abc 100644
--- a/src/SongFilter.cxx
+++ b/src/SongFilter.cxx
@@ -20,6 +20,7 @@
#include "config.h"
#include "SongFilter.hxx"
#include "Song.hxx"
+#include "LightSong.hxx"
#include "DetachedSong.hxx"
#include "tag/Tag.hxx"
#include "util/ASCII.hxx"
@@ -137,7 +138,19 @@ SongFilter::Item::Match(const Tag &_tag) const
}
bool
-SongFilter::Item::Match(const Song &song) const
+SongFilter::Item::Match(const DetachedSong &song) const
+{
+ if (tag == LOCATE_TAG_BASE_TYPE)
+ return uri_is_child_or_same(value.c_str(), song.GetURI());
+
+ if (tag == LOCATE_TAG_FILE_TYPE)
+ return StringMatch(song.GetURI());
+
+ return Match(song.GetTag());
+}
+
+bool
+SongFilter::Item::Match(const LightSong &song) const
{
if (tag == LOCATE_TAG_BASE_TYPE) {
const auto uri = song.GetURI();
@@ -149,19 +162,7 @@ SongFilter::Item::Match(const Song &song) const
return StringMatch(uri.c_str());
}
- return Match(song.tag);
-}
-
-bool
-SongFilter::Item::Match(const DetachedSong &song) const
-{
- if (tag == LOCATE_TAG_BASE_TYPE)
- return uri_is_child_or_same(value.c_str(), song.GetURI());
-
- if (tag == LOCATE_TAG_FILE_TYPE)
- return StringMatch(song.GetURI());
-
- return Match(song.GetTag());
+ return Match(*song.tag);
}
SongFilter::SongFilter(unsigned tag, const char *value, bool fold_case)
@@ -207,7 +208,7 @@ SongFilter::Parse(unsigned argc, char *argv[], bool fold_case)
}
bool
-SongFilter::Match(const Song &song) const
+SongFilter::Match(const DetachedSong &song) const
{
for (const auto &i : items)
if (!i.Match(song))
@@ -217,7 +218,7 @@ SongFilter::Match(const Song &song) const
}
bool
-SongFilter::Match(const DetachedSong &song) const
+SongFilter::Match(const LightSong &song) const
{
for (const auto &i : items)
if (!i.Match(song))
diff --git a/src/SongFilter.hxx b/src/SongFilter.hxx
index d53c98357..74d7187c9 100644
--- a/src/SongFilter.hxx
+++ b/src/SongFilter.hxx
@@ -38,6 +38,7 @@
struct Tag;
struct TagItem;
struct Song;
+struct LightSong;
class DetachedSong;
class SongFilter {
@@ -80,10 +81,10 @@ public:
bool Match(const Tag &tag) const;
gcc_pure
- bool Match(const Song &song) const;
+ bool Match(const DetachedSong &song) const;
gcc_pure
- bool Match(const DetachedSong &song) const;
+ bool Match(const LightSong &song) const;
};
private:
@@ -107,10 +108,10 @@ public:
bool Match(const Tag &tag) const;
gcc_pure
- bool Match(const Song &song) const;
+ bool Match(const DetachedSong &song) const;
gcc_pure
- bool Match(const DetachedSong &song) const;
+ bool Match(const LightSong &song) const;
const std::list<Item> &GetItems() const {
return items;
diff --git a/src/SongPrint.cxx b/src/SongPrint.cxx
index 67b622356..810518c21 100644
--- a/src/SongPrint.cxx
+++ b/src/SongPrint.cxx
@@ -19,7 +19,7 @@
#include "config.h"
#include "SongPrint.hxx"
-#include "Song.hxx"
+#include "LightSong.hxx"
#include "DetachedSong.hxx"
#include "Directory.hxx"
#include "TimePrint.hxx"
@@ -28,6 +28,8 @@
#include "Client.hxx"
#include "util/UriUtil.hxx"
+#define SONG_FILE "file: "
+
static void
song_print_uri(Client &client, const char *uri)
{
@@ -40,11 +42,11 @@ song_print_uri(Client &client, const char *uri)
}
void
-song_print_uri(Client &client, const Song &song)
+song_print_uri(Client &client, const LightSong &song)
{
- if (song.parent != nullptr && !song.parent->IsRoot()) {
+ if (song.directory != nullptr) {
client_printf(client, "%s%s/%s\n", SONG_FILE,
- song.parent->GetPath(), song.uri);
+ song.directory, song.uri);
} else
song_print_uri(client, song.uri);
}
@@ -56,7 +58,7 @@ song_print_uri(Client &client, const DetachedSong &song)
}
void
-song_print_info(Client &client, const Song &song)
+song_print_info(Client &client, const LightSong &song)
{
song_print_uri(client, song);
@@ -74,7 +76,7 @@ song_print_info(Client &client, const Song &song)
if (song.mtime > 0)
time_print(client, "Last-Modified", song.mtime);
- tag_print(client, song.tag);
+ tag_print(client, *song.tag);
}
void
diff --git a/src/SongPrint.hxx b/src/SongPrint.hxx
index 7bbf6e19c..16a9ee6ff 100644
--- a/src/SongPrint.hxx
+++ b/src/SongPrint.hxx
@@ -20,7 +20,7 @@
#ifndef MPD_SONG_PRINT_HXX
#define MPD_SONG_PRINT_HXX
-struct Song;
+struct LightSong;
class DetachedSong;
class Client;
@@ -28,10 +28,10 @@ void
song_print_info(Client &client, const DetachedSong &song);
void
-song_print_info(Client &client, const Song &song);
+song_print_info(Client &client, const LightSong &song);
void
-song_print_uri(Client &client, const Song &song);
+song_print_uri(Client &client, const LightSong &song);
void
song_print_uri(Client &client, const DetachedSong &song);
diff --git a/src/SongSticker.cxx b/src/SongSticker.cxx
index 8c5499bc2..55143d278 100644
--- a/src/SongSticker.cxx
+++ b/src/SongSticker.cxx
@@ -20,6 +20,7 @@
#include "config.h"
#include "SongSticker.hxx"
#include "StickerDatabase.hxx"
+#include "LightSong.hxx"
#include "Song.hxx"
#include "Directory.hxx"
@@ -29,14 +30,14 @@
#include <string.h>
std::string
-sticker_song_get_value(const Song &song, const char *name)
+sticker_song_get_value(const LightSong &song, const char *name)
{
const auto uri = song.GetURI();
return sticker_load_value("song", uri.c_str(), name);
}
bool
-sticker_song_set_value(const Song &song,
+sticker_song_set_value(const LightSong &song,
const char *name, const char *value)
{
const auto uri = song.GetURI();
@@ -44,21 +45,21 @@ sticker_song_set_value(const Song &song,
}
bool
-sticker_song_delete(const Song &song)
+sticker_song_delete(const LightSong &song)
{
const auto uri = song.GetURI();
return sticker_delete("song", uri.c_str());
}
bool
-sticker_song_delete_value(const Song &song, const char *name)
+sticker_song_delete_value(const LightSong &song, const char *name)
{
const auto uri = song.GetURI();
return sticker_delete_value("song", uri.c_str(), name);
}
struct sticker *
-sticker_song_get(const Song &song)
+sticker_song_get(const LightSong &song)
{
const auto uri = song.GetURI();
return sticker_load("song", uri.c_str());
@@ -69,7 +70,7 @@ struct sticker_song_find_data {
const char *base_uri;
size_t base_uri_length;
- void (*func)(Song &song, const char *value,
+ void (*func)(const LightSong &song, const char *value,
void *user_data);
void *user_data;
};
@@ -86,12 +87,12 @@ sticker_song_find_cb(const char *uri, const char *value, void *user_data)
Song *song = data->directory->LookupSong(uri + data->base_uri_length);
if (song != nullptr)
- data->func(*song, value, data->user_data);
+ data->func(song->Export(), value, data->user_data);
}
bool
sticker_song_find(Directory &directory, const char *name,
- void (*func)(Song &song, const char *value,
+ void (*func)(const LightSong &song, const char *value,
void *user_data),
void *user_data)
{
diff --git a/src/SongSticker.hxx b/src/SongSticker.hxx
index b626e63e3..2f977bd21 100644
--- a/src/SongSticker.hxx
+++ b/src/SongSticker.hxx
@@ -24,7 +24,7 @@
#include <string>
-struct Song;
+struct LightSong;
struct Directory;
struct sticker;
@@ -34,28 +34,28 @@ struct sticker;
*/
gcc_pure
std::string
-sticker_song_get_value(const Song &song, const char *name);
+sticker_song_get_value(const LightSong &song, const char *name);
/**
* Sets a sticker value in the specified song. Overwrites existing
* values.
*/
bool
-sticker_song_set_value(const Song &song,
+sticker_song_set_value(const LightSong &song,
const char *name, const char *value);
/**
* Deletes a sticker from the database. All values are deleted.
*/
bool
-sticker_song_delete(const Song &song);
+sticker_song_delete(const LightSong &song);
/**
* Deletes a sticker value. Does nothing if the sticker did not
* exist.
*/
bool
-sticker_song_delete_value(const Song &song, const char *name);
+sticker_song_delete_value(const LightSong &song, const char *name);
/**
* Loads the sticker for the specified song.
@@ -64,7 +64,7 @@ sticker_song_delete_value(const Song &song, const char *name);
* @return a sticker object, or NULL on error or if there is no sticker
*/
sticker *
-sticker_song_get(const Song &song);
+sticker_song_get(const LightSong &song);
/**
* Finds stickers with the specified name below the specified
@@ -79,7 +79,7 @@ sticker_song_get(const Song &song);
*/
bool
sticker_song_find(Directory &directory, const char *name,
- void (*func)(Song &song, const char *value,
+ void (*func)(const LightSong &song, const char *value,
void *user_data),
void *user_data);
diff --git a/src/TagPrint.cxx b/src/TagPrint.cxx
index 14d3abcf0..4f5ea8be3 100644
--- a/src/TagPrint.cxx
+++ b/src/TagPrint.cxx
@@ -21,9 +21,10 @@
#include "TagPrint.hxx"
#include "tag/Tag.hxx"
#include "tag/TagSettings.h"
-#include "Song.hxx"
#include "Client.hxx"
+#define SONG_TIME "Time: "
+
void tag_print_types(Client &client)
{
int i;
diff --git a/src/TagSave.cxx b/src/TagSave.cxx
index 24058906e..3a291e115 100644
--- a/src/TagSave.cxx
+++ b/src/TagSave.cxx
@@ -20,7 +20,8 @@
#include "config.h"
#include "TagSave.hxx"
#include "tag/Tag.hxx"
-#include "Song.hxx"
+
+#define SONG_TIME "Time: "
void
tag_save(FILE *file, const Tag &tag)
diff --git a/src/UpdateRemove.cxx b/src/UpdateRemove.cxx
index cc57fbe94..bed7a92ab 100644
--- a/src/UpdateRemove.cxx
+++ b/src/UpdateRemove.cxx
@@ -24,6 +24,7 @@
#include "thread/Mutex.hxx"
#include "thread/Cond.hxx"
#include "Song.hxx"
+#include "LightSong.hxx"
#include "Main.hxx"
#include "Instance.hxx"
#include "Log.hxx"
@@ -57,7 +58,7 @@ song_remove_event(void)
#ifdef ENABLE_SQLITE
/* if the song has a sticker, remove it */
if (sticker_enabled())
- sticker_song_delete(*removed_song);
+ sticker_song_delete(removed_song->Export());
#endif
{
diff --git a/src/command/StickerCommands.cxx b/src/command/StickerCommands.cxx
index 93a13140b..4272dee69 100644
--- a/src/command/StickerCommands.cxx
+++ b/src/command/StickerCommands.cxx
@@ -39,7 +39,7 @@ struct sticker_song_find_data {
};
static void
-sticker_song_find_print_cb(Song &song, const char *value,
+sticker_song_find_print_cb(const LightSong &song, const char *value,
void *user_data)
{
struct sticker_song_find_data *data =
@@ -59,7 +59,7 @@ handle_sticker_song(Client &client, int argc, char *argv[])
/* get song song_id key */
if (argc == 5 && strcmp(argv[1], "get") == 0) {
- Song *song = db->GetSong(argv[3], error);
+ const LightSong *song = db->GetSong(argv[3], error);
if (song == nullptr)
return print_error(client, error);
@@ -76,7 +76,7 @@ handle_sticker_song(Client &client, int argc, char *argv[])
return CommandResult::OK;
/* list song song_id */
} else if (argc == 4 && strcmp(argv[1], "list") == 0) {
- Song *song = db->GetSong(argv[3], error);
+ const LightSong *song = db->GetSong(argv[3], error);
if (song == nullptr)
return print_error(client, error);
@@ -90,7 +90,7 @@ handle_sticker_song(Client &client, int argc, char *argv[])
return CommandResult::OK;
/* set song song_id id key */
} else if (argc == 6 && strcmp(argv[1], "set") == 0) {
- Song *song = db->GetSong(argv[3], error);
+ const LightSong *song = db->GetSong(argv[3], error);
if (song == nullptr)
return print_error(client, error);
@@ -106,7 +106,7 @@ handle_sticker_song(Client &client, int argc, char *argv[])
/* delete song song_id [key] */
} else if ((argc == 4 || argc == 5) &&
strcmp(argv[1], "delete") == 0) {
- Song *song = db->GetSong(argv[3], error);
+ const LightSong *song = db->GetSong(argv[3], error);
if (song == nullptr)
return print_error(client, error);
diff --git a/src/db/LazyDatabase.cxx b/src/db/LazyDatabase.cxx
index 0718c3dcd..6a01ffb82 100644
--- a/src/db/LazyDatabase.cxx
+++ b/src/db/LazyDatabase.cxx
@@ -51,7 +51,7 @@ LazyDatabase::Close()
}
}
-Song *
+const LightSong *
LazyDatabase::GetSong(const char *uri, Error &error) const
{
return EnsureOpen(error)
@@ -60,7 +60,7 @@ LazyDatabase::GetSong(const char *uri, Error &error) const
}
void
-LazyDatabase::ReturnSong(Song *song) const
+LazyDatabase::ReturnSong(const LightSong *song) const
{
assert(open);
diff --git a/src/db/LazyDatabase.hxx b/src/db/LazyDatabase.hxx
index 7f97aa40d..f718ecb3f 100644
--- a/src/db/LazyDatabase.hxx
+++ b/src/db/LazyDatabase.hxx
@@ -41,9 +41,9 @@ public:
virtual void Close() override;
- virtual Song *GetSong(const char *uri_utf8,
- Error &error) const override;
- virtual void ReturnSong(Song *song) const;
+ virtual const LightSong *GetSong(const char *uri_utf8,
+ Error &error) const override;
+ virtual void ReturnSong(const LightSong *song) const;
virtual bool Visit(const DatabaseSelection &selection,
VisitDirectory visit_directory,
diff --git a/src/db/ProxyDatabasePlugin.cxx b/src/db/ProxyDatabasePlugin.cxx
index e5e9ac76f..f65e4f3d0 100644
--- a/src/db/ProxyDatabasePlugin.cxx
+++ b/src/db/ProxyDatabasePlugin.cxx
@@ -24,11 +24,12 @@
#include "DatabaseSelection.hxx"
#include "DatabaseError.hxx"
#include "Directory.hxx"
-#include "Song.hxx"
+#include "LightSong.hxx"
#include "SongFilter.hxx"
#include "Compiler.h"
#include "ConfigData.hxx"
#include "tag/TagBuilder.hxx"
+#include "tag/Tag.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "protocol/Ack.hxx"
@@ -44,6 +45,25 @@
#include <string>
#include <list>
+class ProxySong : public LightSong {
+ Tag tag2;
+
+public:
+ explicit ProxySong(const mpd_song *song);
+};
+
+class AllocatedProxySong : public ProxySong {
+ mpd_song *const song;
+
+public:
+ explicit AllocatedProxySong(mpd_song *_song)
+ :ProxySong(_song), song(_song) {}
+
+ ~AllocatedProxySong() {
+ mpd_song_free(song);
+ }
+};
+
class ProxyDatabase final : public Database, SocketMonitor, IdleMonitor {
DatabaseListener &listener;
@@ -79,9 +99,9 @@ public:
virtual bool Open(Error &error) override;
virtual void Close() override;
- virtual Song *GetSong(const char *uri_utf8,
+ virtual const LightSong *GetSong(const char *uri_utf8,
Error &error) const override;
- virtual void ReturnSong(Song *song) const;
+ virtual void ReturnSong(const LightSong *song) const;
virtual bool Visit(const DatabaseSelection &selection,
VisitDirectory visit_directory,
@@ -144,6 +164,38 @@ static constexpr struct {
{ TAG_NUM_OF_ITEM_TYPES, MPD_TAG_COUNT }
};
+static void
+Copy(TagBuilder &tag, TagType d_tag,
+ const struct mpd_song *song, enum mpd_tag_type s_tag)
+{
+
+ for (unsigned i = 0;; ++i) {
+ const char *value = mpd_song_get_tag(song, s_tag, i);
+ if (value == nullptr)
+ break;
+
+ tag.AddItem(d_tag, value);
+ }
+}
+
+ProxySong::ProxySong(const mpd_song *song)
+{
+ directory = nullptr;
+ uri = mpd_song_get_uri(song);
+ tag = &tag2;
+ mtime = mpd_song_get_last_modified(song);
+ start_ms = mpd_song_get_start(song) * 1000;
+ end_ms = mpd_song_get_end(song) * 1000;
+
+ TagBuilder tag_builder;
+ tag_builder.SetTime(mpd_song_get_duration(song));
+
+ for (const auto *i = &tag_table[0]; i->d != TAG_NUM_OF_ITEM_TYPES; ++i)
+ Copy(tag_builder, i->d, song, i->s);
+
+ tag_builder.Commit(tag2);
+}
+
gcc_const
static enum mpd_tag_type
Convert(TagType tag_type)
@@ -424,10 +476,7 @@ ProxyDatabase::OnIdle()
SocketMonitor::ScheduleRead();
}
-static Song *
-Convert(const struct mpd_song *song);
-
-Song *
+const LightSong *
ProxyDatabase::GetSong(const char *uri, Error &error) const
{
// TODO: eliminate the const_cast
@@ -452,18 +501,17 @@ ProxyDatabase::GetSong(const char *uri, Error &error) const
return nullptr;
}
- Song *song2 = Convert(song);
- mpd_song_free(song);
- return song2;
+ return new AllocatedProxySong(song);
}
void
-ProxyDatabase::ReturnSong(Song *song) const
+ProxyDatabase::ReturnSong(const LightSong *_song) const
{
- assert(song != nullptr);
- assert(song->parent == nullptr);
+ assert(_song != nullptr);
- song->Free();
+ AllocatedProxySong *song = (AllocatedProxySong *)
+ const_cast<LightSong *>(_song);
+ delete song;
}
static bool
@@ -493,60 +541,23 @@ Visit(struct mpd_connection *connection, Directory &root,
return true;
}
-static void
-Copy(TagBuilder &tag, TagType d_tag,
- const struct mpd_song *song, enum mpd_tag_type s_tag)
-{
-
- for (unsigned i = 0;; ++i) {
- const char *value = mpd_song_get_tag(song, s_tag, i);
- if (value == nullptr)
- break;
-
- tag.AddItem(d_tag, value);
- }
-}
-
-static Song *
-Convert(const struct mpd_song *song)
-{
- Song *s = Song::NewFile(mpd_song_get_uri(song), nullptr);
-
- s->mtime = mpd_song_get_last_modified(song);
- s->start_ms = mpd_song_get_start(song) * 1000;
- s->end_ms = mpd_song_get_end(song) * 1000;
-
- TagBuilder tag;
- tag.SetTime(mpd_song_get_duration(song));
-
- for (const auto *i = &tag_table[0]; i->d != TAG_NUM_OF_ITEM_TYPES; ++i)
- Copy(tag, i->d, song, i->s);
-
- tag.Commit(s->tag);
-
- return s;
-}
-
gcc_pure
static bool
-Match(const SongFilter *filter, const Song &song)
+Match(const SongFilter *filter, const LightSong &song)
{
return filter == nullptr || filter->Match(song);
}
static bool
Visit(const SongFilter *filter,
- const struct mpd_song *song,
+ const mpd_song *_song,
VisitSong visit_song, Error &error)
{
if (!visit_song)
return true;
- Song *s = Convert(song);
- bool success = !Match(filter, *s) || visit_song(*s, error);
- s->Free();
-
- return success;
+ const ProxySong song(_song);
+ return !Match(filter, song) || visit_song(song, error);
}
static bool
@@ -664,12 +675,10 @@ SearchSongs(struct mpd_connection *connection,
bool result = true;
struct mpd_song *song;
while (result && (song = mpd_recv_song(connection)) != nullptr) {
- Song *song2 = Convert(song);
- mpd_song_free(song);
+ AllocatedProxySong song2(song);
- result = !Match(selection.filter, *song2) ||
- visit_song(*song2, error);
- song2->Free();
+ result = !Match(selection.filter, song2) ||
+ visit_song(song2, error);
}
mpd_response_finish(connection);
diff --git a/src/db/SimpleDatabasePlugin.cxx b/src/db/SimpleDatabasePlugin.cxx
index c33db3831..3d947c042 100644
--- a/src/db/SimpleDatabasePlugin.cxx
+++ b/src/db/SimpleDatabasePlugin.cxx
@@ -22,6 +22,7 @@
#include "DatabaseSelection.hxx"
#include "DatabaseHelpers.hxx"
#include "Directory.hxx"
+#include "Song.hxx"
#include "SongFilter.hxx"
#include "DatabaseSave.hxx"
#include "DatabaseLock.hxx"
@@ -193,29 +194,34 @@ SimpleDatabase::Close()
delete root;
}
-Song *
+const LightSong *
SimpleDatabase::GetSong(const char *uri, Error &error) const
{
assert(root != nullptr);
+ assert(borrowed_song_count == 0);
db_lock();
- Song *song = root->LookupSong(uri);
+ const Song *song = root->LookupSong(uri);
db_unlock();
- if (song == nullptr)
+ if (song == nullptr) {
error.Format(db_domain, DB_NOT_FOUND,
"No such song: %s", uri);
+ return nullptr;
+ }
+
+ light_song = song->Export();
+
#ifndef NDEBUG
- else
- ++borrowed_song_count;
+ ++borrowed_song_count;
#endif
- return song;
+ return &light_song;
}
void
-SimpleDatabase::ReturnSong(gcc_unused Song *song) const
+SimpleDatabase::ReturnSong(gcc_unused const LightSong *song) const
{
- assert(song != nullptr);
+ assert(song == &light_song);
#ifndef NDEBUG
assert(borrowed_song_count > 0);
@@ -247,9 +253,11 @@ SimpleDatabase::Visit(const DatabaseSelection &selection,
if (directory == nullptr) {
if (visit_song) {
Song *song = root->LookupSong(selection.uri.c_str());
- if (song != nullptr)
- return !selection.Match(*song) ||
- visit_song(*song, error);
+ if (song != nullptr) {
+ const LightSong song2 = song->Export();
+ return !selection.Match(song2) ||
+ visit_song(song2, error);
+ }
}
error.Set(db_domain, DB_NOT_FOUND, "No such directory");
diff --git a/src/db/SimpleDatabasePlugin.hxx b/src/db/SimpleDatabasePlugin.hxx
index d51174194..509b91e4e 100644
--- a/src/db/SimpleDatabasePlugin.hxx
+++ b/src/db/SimpleDatabasePlugin.hxx
@@ -22,6 +22,7 @@
#include "DatabasePlugin.hxx"
#include "fs/AllocatedPath.hxx"
+#include "LightSong.hxx"
#include "Compiler.h"
#include <cassert>
@@ -36,6 +37,11 @@ class SimpleDatabase : public Database {
time_t mtime;
+ /**
+ * A buffer for GetSong().
+ */
+ mutable LightSong light_song;
+
#ifndef NDEBUG
mutable unsigned borrowed_song_count;
#endif
@@ -60,9 +66,9 @@ public:
virtual bool Open(Error &error) override;
virtual void Close() override;
- virtual Song *GetSong(const char *uri_utf8,
- Error &error) const override;
- virtual void ReturnSong(Song *song) const;
+ virtual const LightSong *GetSong(const char *uri_utf8,
+ Error &error) const override;
+ virtual void ReturnSong(const LightSong *song) const;
virtual bool Visit(const DatabaseSelection &selection,
VisitDirectory visit_directory,
diff --git a/src/db/UpnpDatabasePlugin.cxx b/src/db/UpnpDatabasePlugin.cxx
index dbf04f818..0768488a3 100644
--- a/src/db/UpnpDatabasePlugin.cxx
+++ b/src/db/UpnpDatabasePlugin.cxx
@@ -31,7 +31,7 @@
#include "DatabaseError.hxx"
#include "PlaylistVector.hxx"
#include "Directory.hxx"
-#include "Song.hxx"
+#include "LightSong.hxx"
#include "ConfigData.hxx"
#include "tag/TagBuilder.hxx"
#include "tag/TagTable.hxx"
@@ -49,6 +49,31 @@
static const char *const rootid = "0";
+class UpnpSong : public LightSong {
+ std::string uri2;
+
+ Tag tag2;
+
+public:
+ explicit UpnpSong(UPnPDirObject &&object)
+ :uri2(std::move(object.url)), tag2(std::move(object.tag)) {
+ directory = nullptr;
+ uri = uri2.c_str();
+ tag = &tag2;
+ mtime = 0;
+ start_ms = end_ms = 0;
+ }
+
+ UpnpSong(UPnPDirObject &&object, const char *_uri)
+ :uri2(_uri), tag2(std::move(object.tag)) {
+ directory = nullptr;
+ uri = uri2.c_str();
+ tag = &tag2;
+ mtime = 0;
+ start_ms = end_ms = 0;
+ }
+};
+
class UpnpDatabase : public Database {
LibUPnP *m_lib;
UPnPDeviceDirectory *m_superdir;
@@ -61,9 +86,9 @@ public:
virtual bool Open(Error &error) override;
virtual void Close() override;
- virtual Song *GetSong(const char *uri_utf8,
- Error &error) const override;
- virtual void ReturnSong(Song *song) const;
+ virtual const LightSong *GetSong(const char *uri_utf8,
+ Error &error) const override;
+ virtual void ReturnSong(const LightSong *song) const;
virtual bool Visit(const DatabaseSelection &selection,
VisitDirectory visit_directory,
@@ -187,34 +212,20 @@ UpnpDatabase::Close()
}
void
-UpnpDatabase::ReturnSong(Song *song) const
-{
- assert(song != nullptr);
-
- song->Free();
-}
-
-// If uri is empty, we use the object's url instead. This happens
-// when the target of a Visit() is a song, which only happens when
-// "add"ing AFAIK. Visit() calls us with a null uri so that the url
-// appropriate for fetching is used instead.
-static Song *
-upnpItemToSong(UPnPDirObject &&dirent, const char *uri)
+UpnpDatabase::ReturnSong(const LightSong *_song) const
{
- if (*uri == 0)
- uri = dirent.url.c_str();
+ assert(_song != nullptr);
- Song *s = Song::NewFile(uri, nullptr);
- s->tag = std::move(dirent.tag);
- return s;
+ UpnpSong *song = (UpnpSong *)const_cast<LightSong *>(_song);
+ delete song;
}
// Get song info by path. We can receive either the id path, or the titles
// one
-Song *
+const LightSong *
UpnpDatabase::GetSong(const char *uri, Error &error) const
{
- Song *song = nullptr;
+ UpnpSong *song = nullptr;
auto vpath = stringToTokens(uri, "/", true);
if (vpath.size() >= 2) {
ContentDirectoryService server;
@@ -232,7 +243,8 @@ UpnpDatabase::GetSong(const char *uri, Error &error) const
error))
return nullptr;
}
- song = upnpItemToSong(std::move(dirent), "");
+
+ song = new UpnpSong(std::move(dirent));
}
if (song == nullptr)
error.Format(db_domain, DB_NOT_FOUND, "No such song: %s", uri);
@@ -357,12 +369,9 @@ visitSong(UPnPDirObject &&meta, const char *path,
{
if (!visit_song)
return true;
- Song *s = upnpItemToSong(std::move(meta), path);
- if (!selection.Match(*s))
- return true;
- bool success = visit_song(*s, error);
- s->Free();
- return success;
+
+ const UpnpSong song(std::move(meta), path);
+ return !selection.Match(song) || visit_song(song, error);
}
/**
diff --git a/src/playlist/AsxPlaylistPlugin.cxx b/src/playlist/AsxPlaylistPlugin.cxx
index 7c988a539..24eb26077 100644
--- a/src/playlist/AsxPlaylistPlugin.cxx
+++ b/src/playlist/AsxPlaylistPlugin.cxx
@@ -21,7 +21,6 @@
#include "AsxPlaylistPlugin.hxx"
#include "PlaylistPlugin.hxx"
#include "MemorySongEnumerator.hxx"
-#include "Song.hxx"
#include "tag/TagBuilder.hxx"
#include "util/ASCII.hxx"
#include "util/Error.hxx"
diff --git a/src/playlist/RssPlaylistPlugin.cxx b/src/playlist/RssPlaylistPlugin.cxx
index 253ff7ad2..550a4630e 100644
--- a/src/playlist/RssPlaylistPlugin.cxx
+++ b/src/playlist/RssPlaylistPlugin.cxx
@@ -21,7 +21,6 @@
#include "RssPlaylistPlugin.hxx"
#include "PlaylistPlugin.hxx"
#include "MemorySongEnumerator.hxx"
-#include "Song.hxx"
#include "tag/TagBuilder.hxx"
#include "util/ASCII.hxx"
#include "util/Error.hxx"
diff --git a/src/playlist/SoundCloudPlaylistPlugin.cxx b/src/playlist/SoundCloudPlaylistPlugin.cxx
index b0282b5da..bf68acd3b 100644
--- a/src/playlist/SoundCloudPlaylistPlugin.cxx
+++ b/src/playlist/SoundCloudPlaylistPlugin.cxx
@@ -23,7 +23,6 @@
#include "MemorySongEnumerator.hxx"
#include "ConfigData.hxx"
#include "InputStream.hxx"
-#include "Song.hxx"
#include "tag/TagBuilder.hxx"
#include "util/StringUtil.hxx"
#include "util/Error.hxx"