song: convert header to C++
This commit is contained in:
parent
43f613d9be
commit
ba161ec572
|
@ -81,7 +81,6 @@ mpd_headers = \
|
||||||
src/replay_gain_info.h \
|
src/replay_gain_info.h \
|
||||||
src/replay_gain_ape.h \
|
src/replay_gain_ape.h \
|
||||||
src/TimePrint.cxx src/TimePrint.hxx \
|
src/TimePrint.cxx src/TimePrint.hxx \
|
||||||
src/song.h \
|
|
||||||
src/stats.h \
|
src/stats.h \
|
||||||
src/tag.h \
|
src/tag.h \
|
||||||
src/tag_internal.h \
|
src/tag_internal.h \
|
||||||
|
@ -217,7 +216,7 @@ src_mpd_SOURCES = \
|
||||||
src/ReplayGainConfig.cxx \
|
src/ReplayGainConfig.cxx \
|
||||||
src/ReplayGainInfo.cxx \
|
src/ReplayGainInfo.cxx \
|
||||||
src/SignalHandlers.cxx src/SignalHandlers.hxx \
|
src/SignalHandlers.cxx src/SignalHandlers.hxx \
|
||||||
src/Song.cxx \
|
src/Song.cxx src/Song.hxx \
|
||||||
src/SongUpdate.cxx \
|
src/SongUpdate.cxx \
|
||||||
src/SongPrint.cxx src/SongPrint.hxx \
|
src/SongPrint.cxx src/SongPrint.hxx \
|
||||||
src/SongSave.cxx src/SongSave.hxx \
|
src/SongSave.cxx src/SongSave.hxx \
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
#include "DatabaseHelpers.hxx"
|
#include "DatabaseHelpers.hxx"
|
||||||
#include "DatabasePlugin.hxx"
|
#include "DatabasePlugin.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
@ -37,7 +37,7 @@ struct StringLess {
|
||||||
typedef std::set<const char *, StringLess> StringSet;
|
typedef std::set<const char *, StringLess> StringSet;
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
CollectTags(StringSet &set, enum tag_type tag_type, song &song)
|
CollectTags(StringSet &set, enum tag_type tag_type, Song &song)
|
||||||
{
|
{
|
||||||
struct tag *tag = song.tag;
|
struct tag *tag = song.tag;
|
||||||
if (tag == nullptr)
|
if (tag == nullptr)
|
||||||
|
@ -104,7 +104,7 @@ StatsVisitTag(DatabaseStats &stats, StringSet &artists, StringSet &albums,
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
StatsVisitSong(DatabaseStats &stats, StringSet &artists, StringSet &albums,
|
StatsVisitSong(DatabaseStats &stats, StringSet &artists, StringSet &albums,
|
||||||
song &song)
|
Song &song)
|
||||||
{
|
{
|
||||||
++stats.song_count;
|
++stats.song_count;
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
AddSong(const char *playlist_path_utf8,
|
AddSong(const char *playlist_path_utf8,
|
||||||
song &song, GError **error_r)
|
Song &song, GError **error_r)
|
||||||
{
|
{
|
||||||
return spl_append_song(playlist_path_utf8, &song, error_r);
|
return spl_append_song(playlist_path_utf8, &song, error_r);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ extern "C" {
|
||||||
struct config_param;
|
struct config_param;
|
||||||
struct DatabaseSelection;
|
struct DatabaseSelection;
|
||||||
struct db_visitor;
|
struct db_visitor;
|
||||||
|
struct Song;
|
||||||
|
|
||||||
struct DatabaseStats {
|
struct DatabaseStats {
|
||||||
/**
|
/**
|
||||||
|
@ -91,14 +92,14 @@ public:
|
||||||
* @param uri_utf8 the URI of the song within the music
|
* @param uri_utf8 the URI of the song within the music
|
||||||
* directory (UTF-8)
|
* directory (UTF-8)
|
||||||
*/
|
*/
|
||||||
virtual struct song *GetSong(const char *uri_utf8,
|
virtual Song *GetSong(const char *uri_utf8,
|
||||||
GError **error_r) const = 0;
|
GError **error_r) const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mark the song object as "unused". Call this on objects
|
* Mark the song object as "unused". Call this on objects
|
||||||
* returned by GetSong().
|
* returned by GetSong().
|
||||||
*/
|
*/
|
||||||
virtual void ReturnSong(struct song *song) const = 0;
|
virtual void ReturnSong(Song *song) const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visit the selected entities.
|
* Visit the selected entities.
|
||||||
|
|
|
@ -27,11 +27,7 @@
|
||||||
#include "Directory.hxx"
|
#include "Directory.hxx"
|
||||||
#include "Client.hxx"
|
#include "Client.hxx"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
|
#include "Song.hxx"
|
||||||
extern "C" {
|
|
||||||
#include "song.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "DatabaseGlue.hxx"
|
#include "DatabaseGlue.hxx"
|
||||||
#include "DatabasePlugin.hxx"
|
#include "DatabasePlugin.hxx"
|
||||||
|
|
||||||
|
@ -59,7 +55,7 @@ print_playlist_in_directory(Client *client,
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
PrintSongBrief(Client *client, song &song)
|
PrintSongBrief(Client *client, Song &song)
|
||||||
{
|
{
|
||||||
assert(song.parent != NULL);
|
assert(song.parent != NULL);
|
||||||
|
|
||||||
|
@ -73,7 +69,7 @@ PrintSongBrief(Client *client, song &song)
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
PrintSongFull(Client *client, song &song)
|
PrintSongFull(Client *client, Song &song)
|
||||||
{
|
{
|
||||||
assert(song.parent != NULL);
|
assert(song.parent != NULL);
|
||||||
|
|
||||||
|
@ -142,10 +138,10 @@ static void printSearchStats(Client *client, SearchStats *stats)
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
stats_visitor_song(SearchStats &stats, song &song)
|
stats_visitor_song(SearchStats &stats, Song &song)
|
||||||
{
|
{
|
||||||
stats.numberOfSongs++;
|
stats.numberOfSongs++;
|
||||||
stats.playTime += song_get_duration(&song);
|
stats.playTime += song.GetDuration();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -191,7 +187,7 @@ printInfoForAllIn(Client *client, const char *uri_utf8,
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
PrintSongURIVisitor(Client *client, song &song)
|
PrintSongURIVisitor(Client *client, Song &song)
|
||||||
{
|
{
|
||||||
song_print_uri(client, &song);
|
song_print_uri(client, &song);
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
AddToQueue(Partition &partition, song &song, GError **error_r)
|
AddToQueue(Partition &partition, Song &song, GError **error_r)
|
||||||
{
|
{
|
||||||
enum playlist_result result =
|
enum playlist_result result =
|
||||||
partition.playlist.AppendSong(partition.pc, &song, NULL);
|
partition.playlist.AppendSong(partition.pc, &song, NULL);
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include "DatabaseLock.hxx"
|
#include "DatabaseLock.hxx"
|
||||||
#include "Directory.hxx"
|
#include "Directory.hxx"
|
||||||
#include "DirectorySave.hxx"
|
#include "DirectorySave.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "TextFile.hxx"
|
#include "TextFile.hxx"
|
||||||
#include "TagInternal.hxx"
|
#include "TagInternal.hxx"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include "SongFilter.hxx"
|
#include "SongFilter.hxx"
|
||||||
|
|
||||||
bool
|
bool
|
||||||
DatabaseSelection::Match(const song &song) const
|
DatabaseSelection::Match(const Song &song) const
|
||||||
{
|
{
|
||||||
return filter == nullptr || filter->Match(song);
|
return filter == nullptr || filter->Match(song);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
class SongFilter;
|
class SongFilter;
|
||||||
struct song;
|
struct Song;
|
||||||
|
|
||||||
struct DatabaseSelection {
|
struct DatabaseSelection {
|
||||||
/**
|
/**
|
||||||
|
@ -50,7 +50,7 @@ struct DatabaseSelection {
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool Match(const song &song) const;
|
bool Match(const Song &song) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -25,11 +25,11 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
struct Directory;
|
struct Directory;
|
||||||
struct song;
|
struct Song;
|
||||||
struct PlaylistInfo;
|
struct PlaylistInfo;
|
||||||
|
|
||||||
typedef std::function<bool(const Directory &, GError **)> VisitDirectory;
|
typedef std::function<bool(const Directory &, GError **)> VisitDirectory;
|
||||||
typedef std::function<bool(struct song &, GError **)> VisitSong;
|
typedef std::function<bool(struct Song &, GError **)> VisitSong;
|
||||||
typedef std::function<bool(const PlaylistInfo &, const Directory &,
|
typedef std::function<bool(const PlaylistInfo &, const Directory &,
|
||||||
GError **)> VisitPlaylist;
|
GError **)> VisitPlaylist;
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#include "MusicPipe.hxx"
|
#include "MusicPipe.hxx"
|
||||||
#include "DecoderControl.hxx"
|
#include "DecoderControl.hxx"
|
||||||
#include "DecoderInternal.hxx"
|
#include "DecoderInternal.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "InputStream.hxx"
|
#include "InputStream.hxx"
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "DecoderControl.hxx"
|
#include "DecoderControl.hxx"
|
||||||
#include "MusicPipe.hxx"
|
#include "MusicPipe.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ decoder_control::~decoder_control()
|
||||||
ClearError();
|
ClearError();
|
||||||
|
|
||||||
if (song != NULL)
|
if (song != NULL)
|
||||||
song_free(song);
|
song->Free();
|
||||||
|
|
||||||
g_free(mixramp_start);
|
g_free(mixramp_start);
|
||||||
g_free(mixramp_end);
|
g_free(mixramp_end);
|
||||||
|
@ -84,7 +84,7 @@ dc_command_async(struct decoder_control *dc, enum decoder_command cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
decoder_control::IsCurrentSong(const struct song *_song) const
|
decoder_control::IsCurrentSong(const Song *_song) const
|
||||||
{
|
{
|
||||||
assert(_song != NULL);
|
assert(_song != NULL);
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ decoder_control::IsCurrentSong(const struct song *_song) const
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
decoder_control::Start(struct song *_song,
|
decoder_control::Start(Song *_song,
|
||||||
unsigned _start_ms, unsigned _end_ms,
|
unsigned _start_ms, unsigned _end_ms,
|
||||||
music_buffer *_buffer, music_pipe *_pipe)
|
music_buffer *_buffer, music_pipe *_pipe)
|
||||||
{
|
{
|
||||||
|
@ -113,7 +113,7 @@ decoder_control::Start(struct song *_song,
|
||||||
assert(music_pipe_empty(_pipe));
|
assert(music_pipe_empty(_pipe));
|
||||||
|
|
||||||
if (song != nullptr)
|
if (song != nullptr)
|
||||||
song_free(song);
|
song->Free();
|
||||||
|
|
||||||
song = _song;
|
song = _song;
|
||||||
start_ms = _start_ms;
|
start_ms = _start_ms;
|
||||||
|
|
|
@ -29,6 +29,8 @@
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
struct Song;
|
||||||
|
|
||||||
enum decoder_state {
|
enum decoder_state {
|
||||||
DECODE_STATE_STOP = 0,
|
DECODE_STATE_STOP = 0,
|
||||||
DECODE_STATE_START,
|
DECODE_STATE_START,
|
||||||
|
@ -96,7 +98,7 @@ struct decoder_control {
|
||||||
* This is a duplicate, and must be freed when this attribute
|
* This is a duplicate, and must be freed when this attribute
|
||||||
* is cleared.
|
* is cleared.
|
||||||
*/
|
*/
|
||||||
struct song *song;
|
Song *song;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The initial seek position (in milliseconds), e.g. to the
|
* The initial seek position (in milliseconds), e.g. to the
|
||||||
|
@ -260,10 +262,10 @@ struct decoder_control {
|
||||||
* Caller must lock the object.
|
* Caller must lock the object.
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool IsCurrentSong(const struct song *_song) const;
|
bool IsCurrentSong(const Song *_song) const;
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool LockIsCurrentSong(const struct song *_song) const {
|
bool LockIsCurrentSong(const Song *_song) const {
|
||||||
Lock();
|
Lock();
|
||||||
const bool result = IsCurrentSong(_song);
|
const bool result = IsCurrentSong(_song);
|
||||||
Unlock();
|
Unlock();
|
||||||
|
@ -280,7 +282,7 @@ struct decoder_control {
|
||||||
* @param pipe the pipe which receives the decoded chunks (owned by
|
* @param pipe the pipe which receives the decoded chunks (owned by
|
||||||
* the caller)
|
* the caller)
|
||||||
*/
|
*/
|
||||||
void Start(struct song *song, unsigned start_ms, unsigned end_ms,
|
void Start(Song *song, unsigned start_ms, unsigned end_ms,
|
||||||
music_buffer *buffer, music_pipe *pipe);
|
music_buffer *buffer, music_pipe *pipe);
|
||||||
|
|
||||||
void Stop();
|
void Stop();
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
#include "DecoderInternal.hxx"
|
#include "DecoderInternal.hxx"
|
||||||
#include "DecoderError.hxx"
|
#include "DecoderError.hxx"
|
||||||
#include "DecoderPlugin.hxx"
|
#include "DecoderPlugin.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "mpd_error.h"
|
#include "mpd_error.h"
|
||||||
#include "Mapper.hxx"
|
#include "Mapper.hxx"
|
||||||
#include "fs/Path.hxx"
|
#include "fs/Path.hxx"
|
||||||
|
@ -380,10 +380,10 @@ decoder_run_file(struct decoder *decoder, const char *path_fs)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
decoder_run_song(struct decoder_control *dc,
|
decoder_run_song(struct decoder_control *dc,
|
||||||
const struct song *song, const char *uri)
|
const Song *song, const char *uri)
|
||||||
{
|
{
|
||||||
decoder decoder(dc, dc->start_ms > 0,
|
decoder decoder(dc, dc->start_ms > 0,
|
||||||
song->tag != NULL && song_is_file(song)
|
song->tag != NULL && song->IsFile()
|
||||||
? tag_dup(song->tag) : nullptr);
|
? tag_dup(song->tag) : nullptr);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -391,7 +391,7 @@ decoder_run_song(struct decoder_control *dc,
|
||||||
|
|
||||||
decoder_command_finished_locked(dc);
|
decoder_command_finished_locked(dc);
|
||||||
|
|
||||||
ret = song_is_file(song)
|
ret = song->IsFile()
|
||||||
? decoder_run_file(&decoder, uri)
|
? decoder_run_file(&decoder, uri)
|
||||||
: decoder_run_stream(&decoder, uri);
|
: decoder_run_stream(&decoder, uri);
|
||||||
|
|
||||||
|
@ -427,15 +427,15 @@ decoder_run(struct decoder_control *dc)
|
||||||
{
|
{
|
||||||
dc->ClearError();
|
dc->ClearError();
|
||||||
|
|
||||||
const struct song *song = dc->song;
|
const Song *song = dc->song;
|
||||||
char *uri;
|
char *uri;
|
||||||
|
|
||||||
assert(song != NULL);
|
assert(song != NULL);
|
||||||
|
|
||||||
if (song_is_file(song))
|
if (song->IsFile())
|
||||||
uri = map_song_fs(song).Steal();
|
uri = map_song_fs(song).Steal();
|
||||||
else
|
else
|
||||||
uri = song_get_uri(song);
|
uri = song->GetURI();
|
||||||
|
|
||||||
if (uri == NULL) {
|
if (uri == NULL) {
|
||||||
dc->state = DECODE_STATE_ERROR;
|
dc->state = DECODE_STATE_ERROR;
|
||||||
|
|
|
@ -23,9 +23,9 @@
|
||||||
#include "PlaylistVector.hxx"
|
#include "PlaylistVector.hxx"
|
||||||
#include "DatabaseLock.hxx"
|
#include "DatabaseLock.hxx"
|
||||||
#include "SongSort.hxx"
|
#include "SongSort.hxx"
|
||||||
|
#include "Song.hxx"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "song.h"
|
|
||||||
#include "util/list_sort.h"
|
#include "util/list_sort.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,9 +68,9 @@ Directory::Directory(const char *_path)
|
||||||
|
|
||||||
Directory::~Directory()
|
Directory::~Directory()
|
||||||
{
|
{
|
||||||
struct song *song, *ns;
|
Song *song, *ns;
|
||||||
directory_for_each_song_safe(song, ns, this)
|
directory_for_each_song_safe(song, ns, this)
|
||||||
song_free(song);
|
song->Free();
|
||||||
|
|
||||||
Directory *child, *n;
|
Directory *child, *n;
|
||||||
directory_for_each_child_safe(child, n, this)
|
directory_for_each_child_safe(child, n, this)
|
||||||
|
@ -208,7 +208,7 @@ Directory::LookupDirectory(const char *uri)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Directory::AddSong(struct song *song)
|
Directory::AddSong(Song *song)
|
||||||
{
|
{
|
||||||
assert(holding_db_lock());
|
assert(holding_db_lock());
|
||||||
assert(song != NULL);
|
assert(song != NULL);
|
||||||
|
@ -218,7 +218,7 @@ Directory::AddSong(struct song *song)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Directory::RemoveSong(struct song *song)
|
Directory::RemoveSong(Song *song)
|
||||||
{
|
{
|
||||||
assert(holding_db_lock());
|
assert(holding_db_lock());
|
||||||
assert(song != NULL);
|
assert(song != NULL);
|
||||||
|
@ -227,13 +227,13 @@ Directory::RemoveSong(struct song *song)
|
||||||
list_del(&song->siblings);
|
list_del(&song->siblings);
|
||||||
}
|
}
|
||||||
|
|
||||||
const song *
|
const Song *
|
||||||
Directory::FindSong(const char *name_utf8) const
|
Directory::FindSong(const char *name_utf8) const
|
||||||
{
|
{
|
||||||
assert(holding_db_lock());
|
assert(holding_db_lock());
|
||||||
assert(name_utf8 != NULL);
|
assert(name_utf8 != NULL);
|
||||||
|
|
||||||
struct song *song;
|
Song *song;
|
||||||
directory_for_each_song(song, this) {
|
directory_for_each_song(song, this) {
|
||||||
assert(song->parent == this);
|
assert(song->parent == this);
|
||||||
|
|
||||||
|
@ -244,7 +244,7 @@ Directory::FindSong(const char *name_utf8) const
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct song *
|
Song *
|
||||||
Directory::LookupSong(const char *uri)
|
Directory::LookupSong(const char *uri)
|
||||||
{
|
{
|
||||||
char *duplicated, *base;
|
char *duplicated, *base;
|
||||||
|
@ -266,7 +266,7 @@ Directory::LookupSong(const char *uri)
|
||||||
} else
|
} else
|
||||||
base = duplicated;
|
base = duplicated;
|
||||||
|
|
||||||
struct song *song = d->FindSong(base);
|
Song *song = d->FindSong(base);
|
||||||
assert(song == NULL || song->parent == d);
|
assert(song == NULL || song->parent == d);
|
||||||
|
|
||||||
g_free(duplicated);
|
g_free(duplicated);
|
||||||
|
@ -305,7 +305,7 @@ Directory::Walk(bool recursive, const SongFilter *filter,
|
||||||
assert(error_r == NULL || *error_r == NULL);
|
assert(error_r == NULL || *error_r == NULL);
|
||||||
|
|
||||||
if (visit_song) {
|
if (visit_song) {
|
||||||
struct song *song;
|
Song *song;
|
||||||
directory_for_each_song(song, this)
|
directory_for_each_song(song, this)
|
||||||
if ((filter == nullptr || filter->Match(*song)) &&
|
if ((filter == nullptr || filter->Match(*song)) &&
|
||||||
!visit_song(*song, error_r))
|
!visit_song(*song, error_r))
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
#define directory_for_each_song_safe(pos, n, directory) \
|
#define directory_for_each_song_safe(pos, n, directory) \
|
||||||
list_for_each_entry_safe(pos, n, &directory->songs, siblings)
|
list_for_each_entry_safe(pos, n, &directory->songs, siblings)
|
||||||
|
|
||||||
struct song;
|
struct Song;
|
||||||
struct db_visitor;
|
struct db_visitor;
|
||||||
class SongFilter;
|
class SongFilter;
|
||||||
|
|
||||||
|
@ -202,12 +202,12 @@ public:
|
||||||
* Caller must lock the #db_mutex.
|
* Caller must lock the #db_mutex.
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
const song *FindSong(const char *name_utf8) const;
|
const Song *FindSong(const char *name_utf8) const;
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
song *FindSong(const char *name_utf8) {
|
Song *FindSong(const char *name_utf8) {
|
||||||
const Directory *cthis = this;
|
const Directory *cthis = this;
|
||||||
return const_cast<song *>(cthis->FindSong(name_utf8));
|
return const_cast<Song *>(cthis->FindSong(name_utf8));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -219,20 +219,20 @@ public:
|
||||||
* @return the song, or NULL if none was found
|
* @return the song, or NULL if none was found
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
song *LookupSong(const char *uri);
|
Song *LookupSong(const char *uri);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a song object to this directory. Its "parent" attribute must
|
* Add a song object to this directory. Its "parent" attribute must
|
||||||
* be set already.
|
* be set already.
|
||||||
*/
|
*/
|
||||||
void AddSong(song *song);
|
void AddSong(Song *song);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a song object from this directory (which effectively
|
* Remove a song object from this directory (which effectively
|
||||||
* invalidates the song object, because the "parent" attribute becomes
|
* invalidates the song object, because the "parent" attribute becomes
|
||||||
* stale), but does not free it.
|
* stale), but does not free it.
|
||||||
*/
|
*/
|
||||||
void RemoveSong(song *song);
|
void RemoveSong(Song *song);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Caller must lock the #db_mutex.
|
* Caller must lock the #db_mutex.
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "DirectorySave.hxx"
|
#include "DirectorySave.hxx"
|
||||||
#include "Directory.hxx"
|
#include "Directory.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "SongSave.hxx"
|
#include "SongSave.hxx"
|
||||||
#include "PlaylistDatabase.hxx"
|
#include "PlaylistDatabase.hxx"
|
||||||
#include "TextFile.hxx"
|
#include "TextFile.hxx"
|
||||||
|
@ -65,7 +65,7 @@ directory_save(FILE *fp, const Directory *directory)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct song *song;
|
Song *song;
|
||||||
directory_for_each_song(song, directory)
|
directory_for_each_song(song, directory)
|
||||||
song_save(fp, song);
|
song_save(fp, song);
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ directory_load(TextFile &file, Directory *directory, GError **error)
|
||||||
return false;
|
return false;
|
||||||
} else if (g_str_has_prefix(line, SONG_BEGIN)) {
|
} else if (g_str_has_prefix(line, SONG_BEGIN)) {
|
||||||
const char *name = line + sizeof(SONG_BEGIN) - 1;
|
const char *name = line + sizeof(SONG_BEGIN) - 1;
|
||||||
struct song *song;
|
Song *song;
|
||||||
|
|
||||||
if (directory->FindSong(name) != nullptr) {
|
if (directory->FindSong(name) != nullptr) {
|
||||||
g_set_error(error, directory_quark(), 0,
|
g_set_error(error, directory_quark(), 0,
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
#include "Idle.hxx"
|
#include "Idle.hxx"
|
||||||
|
|
||||||
void
|
void
|
||||||
Instance::DeleteSong(const song &song)
|
Instance::DeleteSong(const Song &song)
|
||||||
{
|
{
|
||||||
partition->DeleteSong(song);
|
partition->DeleteSong(song);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,14 +24,14 @@
|
||||||
|
|
||||||
class ClientList;
|
class ClientList;
|
||||||
struct Partition;
|
struct Partition;
|
||||||
struct song;
|
struct Song;
|
||||||
|
|
||||||
struct Instance {
|
struct Instance {
|
||||||
ClientList *client_list;
|
ClientList *client_list;
|
||||||
|
|
||||||
Partition *partition;
|
Partition *partition;
|
||||||
|
|
||||||
void DeleteSong(const song &song);
|
void DeleteSong(const Song &song);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The database has been modified. Propagate the change to
|
* The database has been modified. Propagate the change to
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "Mapper.hxx"
|
#include "Mapper.hxx"
|
||||||
#include "Directory.hxx"
|
#include "Directory.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "fs/Path.hxx"
|
#include "fs/Path.hxx"
|
||||||
#include "fs/FileSystem.hxx"
|
#include "fs/FileSystem.hxx"
|
||||||
#include "fs/DirectoryReader.hxx"
|
#include "fs/DirectoryReader.hxx"
|
||||||
|
@ -246,12 +246,12 @@ map_detached_song_fs(const char *uri_utf8)
|
||||||
}
|
}
|
||||||
|
|
||||||
Path
|
Path
|
||||||
map_song_fs(const struct song *song)
|
map_song_fs(const Song *song)
|
||||||
{
|
{
|
||||||
assert(song_is_file(song));
|
assert(song->IsFile());
|
||||||
|
|
||||||
if (song_in_database(song))
|
if (song->IsInDatabase())
|
||||||
return song_is_detached(song)
|
return song->IsDetached()
|
||||||
? map_detached_song_fs(song->uri)
|
? map_detached_song_fs(song->uri)
|
||||||
: map_directory_child_fs(song->parent, song->uri);
|
: map_directory_child_fs(song->parent, song->uri);
|
||||||
else
|
else
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
|
|
||||||
class Path;
|
class Path;
|
||||||
struct Directory;
|
struct Directory;
|
||||||
struct song;
|
struct Song;
|
||||||
|
|
||||||
bool mapper_init(const char *_music_dir, const char *_playlist_dir,
|
bool mapper_init(const char *_music_dir, const char *_playlist_dir,
|
||||||
GError **error_r);
|
GError **error_r);
|
||||||
|
@ -112,7 +112,7 @@ map_directory_child_fs(const Directory *directory, const char *name);
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
Path
|
Path
|
||||||
map_song_fs(const struct song *song);
|
map_song_fs(const Song *song);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps a file system path (relative to the music directory or
|
* Maps a file system path (relative to the music directory or
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
#include "CommandError.hxx"
|
#include "CommandError.hxx"
|
||||||
#include "UpdateGlue.hxx"
|
#include "UpdateGlue.hxx"
|
||||||
#include "Directory.hxx"
|
#include "Directory.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "SongPrint.hxx"
|
#include "SongPrint.hxx"
|
||||||
#include "TagPrint.hxx"
|
#include "TagPrint.hxx"
|
||||||
#include "TimePrint.hxx"
|
#include "TimePrint.hxx"
|
||||||
|
@ -130,7 +130,7 @@ handle_lsinfo(Client *client, int argc, char *argv[])
|
||||||
if (!client_allow_file(client, path_fs, &error))
|
if (!client_allow_file(client, path_fs, &error))
|
||||||
return print_error(client, error);
|
return print_error(client, error);
|
||||||
|
|
||||||
struct song *song = song_file_load(path_utf8, NULL);
|
Song *song = Song::LoadFile(path_utf8, nullptr);
|
||||||
if (song == NULL) {
|
if (song == NULL) {
|
||||||
command_error(client, ACK_ERROR_NO_EXIST,
|
command_error(client, ACK_ERROR_NO_EXIST,
|
||||||
"No such file");
|
"No such file");
|
||||||
|
@ -138,7 +138,7 @@ handle_lsinfo(Client *client, int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
song_print_info(client, song);
|
song_print_info(client, song);
|
||||||
song_free(song);
|
song->Free();
|
||||||
return COMMAND_RETURN_OK;
|
return COMMAND_RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@ struct Partition {
|
||||||
return playlist.DeleteRange(pc, start, end);
|
return playlist.DeleteRange(pc, start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeleteSong(const song &song) {
|
void DeleteSong(const Song &song) {
|
||||||
playlist.DeleteSong(pc, song);
|
playlist.DeleteSong(pc, song);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "PlayerControl.hxx"
|
#include "PlayerControl.hxx"
|
||||||
#include "Idle.hxx"
|
#include "Idle.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "DecoderControl.hxx"
|
#include "DecoderControl.hxx"
|
||||||
#include "Main.hxx"
|
#include "Main.hxx"
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pc_enqueue_song_locked(struct player_control *pc, struct song *song);
|
pc_enqueue_song_locked(struct player_control *pc, Song *song);
|
||||||
|
|
||||||
player_control::player_control(unsigned _buffer_chunks,
|
player_control::player_control(unsigned _buffer_chunks,
|
||||||
unsigned _buffered_before_play)
|
unsigned _buffered_before_play)
|
||||||
|
@ -59,7 +59,7 @@ player_control::player_control(unsigned _buffer_chunks,
|
||||||
player_control::~player_control()
|
player_control::~player_control()
|
||||||
{
|
{
|
||||||
if (next_song != nullptr)
|
if (next_song != nullptr)
|
||||||
song_free(next_song);
|
next_song->Free();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -88,7 +88,7 @@ player_command(struct player_control *pc, enum player_command cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
player_control::Play(struct song *song)
|
player_control::Play(Song *song)
|
||||||
{
|
{
|
||||||
assert(song != NULL);
|
assert(song != NULL);
|
||||||
|
|
||||||
|
@ -253,7 +253,7 @@ player_control::GetErrorMessage() const
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pc_enqueue_song_locked(struct player_control *pc, struct song *song)
|
pc_enqueue_song_locked(struct player_control *pc, Song *song)
|
||||||
{
|
{
|
||||||
assert(song != NULL);
|
assert(song != NULL);
|
||||||
assert(pc->next_song == NULL);
|
assert(pc->next_song == NULL);
|
||||||
|
@ -263,7 +263,7 @@ pc_enqueue_song_locked(struct player_control *pc, struct song *song)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
player_control::EnqueueSong(struct song *song)
|
player_control::EnqueueSong(Song *song)
|
||||||
{
|
{
|
||||||
assert(song != NULL);
|
assert(song != NULL);
|
||||||
|
|
||||||
|
@ -273,14 +273,14 @@ player_control::EnqueueSong(struct song *song)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
player_control::Seek(struct song *song, float seek_time)
|
player_control::Seek(Song *song, float seek_time)
|
||||||
{
|
{
|
||||||
assert(song != NULL);
|
assert(song != NULL);
|
||||||
|
|
||||||
Lock();
|
Lock();
|
||||||
|
|
||||||
if (next_song != nullptr)
|
if (next_song != nullptr)
|
||||||
song_free(next_song);
|
next_song->Free();
|
||||||
|
|
||||||
next_song = song;
|
next_song = song;
|
||||||
seek_where = seek_time;
|
seek_where = seek_time;
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
struct decoder_control;
|
struct decoder_control;
|
||||||
|
struct Song;
|
||||||
|
|
||||||
enum player_state {
|
enum player_state {
|
||||||
PLAYER_STATE_STOP = 0,
|
PLAYER_STATE_STOP = 0,
|
||||||
|
@ -139,7 +140,7 @@ struct player_control {
|
||||||
* This is a duplicate, and must be freed when this attribute
|
* This is a duplicate, and must be freed when this attribute
|
||||||
* is cleared.
|
* is cleared.
|
||||||
*/
|
*/
|
||||||
struct song *next_song;
|
Song *next_song;
|
||||||
|
|
||||||
double seek_where;
|
double seek_where;
|
||||||
float cross_fade_seconds;
|
float cross_fade_seconds;
|
||||||
|
@ -230,7 +231,7 @@ struct player_control {
|
||||||
* @param song the song to be queued; the given instance will
|
* @param song the song to be queued; the given instance will
|
||||||
* be owned and freed by the player
|
* be owned and freed by the player
|
||||||
*/
|
*/
|
||||||
void Play(struct song *song);
|
void Play(Song *song);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* see PLAYER_COMMAND_CANCEL
|
* see PLAYER_COMMAND_CANCEL
|
||||||
|
@ -287,7 +288,7 @@ struct player_control {
|
||||||
* @param song the song to be queued; the given instance will be owned
|
* @param song the song to be queued; the given instance will be owned
|
||||||
* and freed by the player
|
* and freed by the player
|
||||||
*/
|
*/
|
||||||
void EnqueueSong(struct song *song);
|
void EnqueueSong(Song *song);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes the player thread seek the specified song to a position.
|
* Makes the player thread seek the specified song to a position.
|
||||||
|
@ -297,7 +298,7 @@ struct player_control {
|
||||||
* @return true on success, false on failure (e.g. if MPD isn't
|
* @return true on success, false on failure (e.g. if MPD isn't
|
||||||
* playing currently)
|
* playing currently)
|
||||||
*/
|
*/
|
||||||
bool Seek(struct song *song, float seek_time);
|
bool Seek(Song *song, float seek_time);
|
||||||
|
|
||||||
void SetCrossFade(float cross_fade_seconds);
|
void SetCrossFade(float cross_fade_seconds);
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
#include "MusicPipe.hxx"
|
#include "MusicPipe.hxx"
|
||||||
#include "MusicBuffer.hxx"
|
#include "MusicBuffer.hxx"
|
||||||
#include "MusicChunk.hxx"
|
#include "MusicChunk.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "Main.hxx"
|
#include "Main.hxx"
|
||||||
#include "mpd_error.h"
|
#include "mpd_error.h"
|
||||||
#include "CrossFade.hxx"
|
#include "CrossFade.hxx"
|
||||||
|
@ -86,7 +86,7 @@ struct player {
|
||||||
/**
|
/**
|
||||||
* the song currently being played
|
* the song currently being played
|
||||||
*/
|
*/
|
||||||
struct song *song;
|
Song *song;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* is cross fading enabled?
|
* is cross fading enabled?
|
||||||
|
@ -176,7 +176,7 @@ player_dc_start(struct player *player, struct music_pipe *pipe)
|
||||||
if (pc->command == PLAYER_COMMAND_SEEK)
|
if (pc->command == PLAYER_COMMAND_SEEK)
|
||||||
start_ms += (unsigned)(pc->seek_where * 1000);
|
start_ms += (unsigned)(pc->seek_where * 1000);
|
||||||
|
|
||||||
dc->Start(song_dup_detached(pc->next_song),
|
dc->Start(pc->next_song->DupDetached(),
|
||||||
start_ms, pc->next_song->end_ms,
|
start_ms, pc->next_song->end_ms,
|
||||||
player_buffer, pipe);
|
player_buffer, pipe);
|
||||||
}
|
}
|
||||||
|
@ -254,7 +254,7 @@ player_wait_for_decoder(struct player *player)
|
||||||
pc->Lock();
|
pc->Lock();
|
||||||
pc->SetError(PLAYER_ERROR_DECODER, error);
|
pc->SetError(PLAYER_ERROR_DECODER, error);
|
||||||
|
|
||||||
song_free(pc->next_song);
|
pc->next_song->Free();
|
||||||
pc->next_song = NULL;
|
pc->next_song = NULL;
|
||||||
|
|
||||||
pc->Unlock();
|
pc->Unlock();
|
||||||
|
@ -263,7 +263,7 @@ player_wait_for_decoder(struct player *player)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player->song != NULL)
|
if (player->song != NULL)
|
||||||
song_free(player->song);
|
player->song->Free();
|
||||||
|
|
||||||
player->song = pc->next_song;
|
player->song = pc->next_song;
|
||||||
player->elapsed_time = 0.0;
|
player->elapsed_time = 0.0;
|
||||||
|
@ -275,7 +275,7 @@ player_wait_for_decoder(struct player *player)
|
||||||
pc->Lock();
|
pc->Lock();
|
||||||
|
|
||||||
/* update player_control's song information */
|
/* update player_control's song information */
|
||||||
pc->total_time = song_get_duration(pc->next_song);
|
pc->total_time = pc->next_song->GetDuration();
|
||||||
pc->bit_rate = 0;
|
pc->bit_rate = 0;
|
||||||
audio_format_clear(&pc->audio_format);
|
audio_format_clear(&pc->audio_format);
|
||||||
|
|
||||||
|
@ -295,14 +295,14 @@ player_wait_for_decoder(struct player *player)
|
||||||
* indicated by the decoder plugin.
|
* indicated by the decoder plugin.
|
||||||
*/
|
*/
|
||||||
static double
|
static double
|
||||||
real_song_duration(const struct song *song, double decoder_duration)
|
real_song_duration(const Song *song, double decoder_duration)
|
||||||
{
|
{
|
||||||
assert(song != NULL);
|
assert(song != NULL);
|
||||||
|
|
||||||
if (decoder_duration <= 0.0)
|
if (decoder_duration <= 0.0)
|
||||||
/* the decoder plugin didn't provide information; fall
|
/* the decoder plugin didn't provide information; fall
|
||||||
back to song_get_duration() */
|
back to Song::GetDuration() */
|
||||||
return song_get_duration(song);
|
return song->GetDuration();
|
||||||
|
|
||||||
if (song->end_ms > 0 && song->end_ms / 1000.0 < decoder_duration)
|
if (song->end_ms > 0 && song->end_ms / 1000.0 < decoder_duration)
|
||||||
return (song->end_ms - song->start_ms) / 1000.0;
|
return (song->end_ms - song->start_ms) / 1000.0;
|
||||||
|
@ -407,7 +407,7 @@ player_check_decoder_startup(struct player *player)
|
||||||
player->decoder_starting = false;
|
player->decoder_starting = false;
|
||||||
|
|
||||||
if (!player->paused && !player_open_output(player)) {
|
if (!player->paused && !player_open_output(player)) {
|
||||||
char *uri = song_get_uri(dc->song);
|
char *uri = dc->song->GetURI();
|
||||||
g_warning("problems opening audio device "
|
g_warning("problems opening audio device "
|
||||||
"while playing \"%s\"", uri);
|
"while playing \"%s\"", uri);
|
||||||
g_free(uri);
|
g_free(uri);
|
||||||
|
@ -479,7 +479,7 @@ player_send_silence(struct player *player)
|
||||||
static bool player_seek_decoder(struct player *player)
|
static bool player_seek_decoder(struct player *player)
|
||||||
{
|
{
|
||||||
struct player_control *pc = player->pc;
|
struct player_control *pc = player->pc;
|
||||||
struct song *song = pc->next_song;
|
Song *song = pc->next_song;
|
||||||
struct decoder_control *dc = player->dc;
|
struct decoder_control *dc = player->dc;
|
||||||
|
|
||||||
assert(pc->next_song != NULL);
|
assert(pc->next_song != NULL);
|
||||||
|
@ -512,7 +512,7 @@ static bool player_seek_decoder(struct player *player)
|
||||||
player->pipe = dc->pipe;
|
player->pipe = dc->pipe;
|
||||||
}
|
}
|
||||||
|
|
||||||
song_free(pc->next_song);
|
pc->next_song->Free();
|
||||||
pc->next_song = NULL;
|
pc->next_song = NULL;
|
||||||
player->queued = false;
|
player->queued = false;
|
||||||
}
|
}
|
||||||
|
@ -633,7 +633,7 @@ static void player_process_command(struct player *player)
|
||||||
pc->Lock();
|
pc->Lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
song_free(pc->next_song);
|
pc->next_song->Free();
|
||||||
pc->next_song = NULL;
|
pc->next_song = NULL;
|
||||||
player->queued = false;
|
player->queued = false;
|
||||||
player_command_finished_locked(pc);
|
player_command_finished_locked(pc);
|
||||||
|
@ -656,9 +656,9 @@ static void player_process_command(struct player *player)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
update_song_tag(struct song *song, const struct tag *new_tag)
|
update_song_tag(Song *song, const struct tag *new_tag)
|
||||||
{
|
{
|
||||||
if (song_is_file(song))
|
if (song->IsFile())
|
||||||
/* don't update tags of local files, only remote
|
/* don't update tags of local files, only remote
|
||||||
streams may change tags dynamically */
|
streams may change tags dynamically */
|
||||||
return;
|
return;
|
||||||
|
@ -687,7 +687,7 @@ update_song_tag(struct song *song, const struct tag *new_tag)
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
play_chunk(struct player_control *pc,
|
play_chunk(struct player_control *pc,
|
||||||
struct song *song, struct music_chunk *chunk,
|
Song *song, struct music_chunk *chunk,
|
||||||
const struct audio_format *format,
|
const struct audio_format *format,
|
||||||
GError **error_r)
|
GError **error_r)
|
||||||
{
|
{
|
||||||
|
@ -872,7 +872,7 @@ player_song_border(struct player *player)
|
||||||
{
|
{
|
||||||
player->xfade = XFADE_UNKNOWN;
|
player->xfade = XFADE_UNKNOWN;
|
||||||
|
|
||||||
char *uri = song_get_uri(player->song);
|
char *uri = player->song->GetURI();
|
||||||
g_message("played \"%s\"", uri);
|
g_message("played \"%s\"", uri);
|
||||||
g_free(uri);
|
g_free(uri);
|
||||||
|
|
||||||
|
@ -1084,13 +1084,13 @@ static void do_play(struct player_control *pc, struct decoder_control *dc)
|
||||||
tag_free(player.cross_fade_tag);
|
tag_free(player.cross_fade_tag);
|
||||||
|
|
||||||
if (player.song != NULL)
|
if (player.song != NULL)
|
||||||
song_free(player.song);
|
player.song->Free();
|
||||||
|
|
||||||
pc->Lock();
|
pc->Lock();
|
||||||
|
|
||||||
if (player.queued) {
|
if (player.queued) {
|
||||||
assert(pc->next_song != NULL);
|
assert(pc->next_song != NULL);
|
||||||
song_free(pc->next_song);
|
pc->next_song->Free();
|
||||||
pc->next_song = NULL;
|
pc->next_song = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1133,7 +1133,7 @@ player_task(gpointer arg)
|
||||||
|
|
||||||
case PLAYER_COMMAND_PAUSE:
|
case PLAYER_COMMAND_PAUSE:
|
||||||
if (pc->next_song != NULL) {
|
if (pc->next_song != NULL) {
|
||||||
song_free(pc->next_song);
|
pc->next_song->Free();
|
||||||
pc->next_song = NULL;
|
pc->next_song = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1178,7 +1178,7 @@ player_task(gpointer arg)
|
||||||
|
|
||||||
case PLAYER_COMMAND_CANCEL:
|
case PLAYER_COMMAND_CANCEL:
|
||||||
if (pc->next_song != NULL) {
|
if (pc->next_song != NULL) {
|
||||||
song_free(pc->next_song);
|
pc->next_song->Free();
|
||||||
pc->next_song = NULL;
|
pc->next_song = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "Playlist.hxx"
|
#include "Playlist.hxx"
|
||||||
#include "PlayerControl.hxx"
|
#include "PlayerControl.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "Idle.hxx"
|
#include "Idle.hxx"
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
@ -62,10 +62,9 @@ playlist_queue_song_order(struct playlist *playlist, struct player_control *pc,
|
||||||
|
|
||||||
playlist->queued = order;
|
playlist->queued = order;
|
||||||
|
|
||||||
struct song *song =
|
Song *song = playlist->queue.GetOrder(order)->DupDetached();
|
||||||
song_dup_detached(playlist->queue.GetOrder(order));
|
|
||||||
|
|
||||||
uri = song_get_uri(song);
|
uri = song->GetURI();
|
||||||
g_debug("queue song %i:\"%s\"", playlist->queued, uri);
|
g_debug("queue song %i:\"%s\"", playlist->queued, uri);
|
||||||
g_free(uri);
|
g_free(uri);
|
||||||
|
|
||||||
|
@ -94,7 +93,7 @@ playlist_song_started(struct playlist *playlist, struct player_control *pc)
|
||||||
idle_add(IDLE_PLAYER);
|
idle_add(IDLE_PLAYER);
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct song *
|
const Song *
|
||||||
playlist::GetQueuedSong() const
|
playlist::GetQueuedSong() const
|
||||||
{
|
{
|
||||||
return playing && queued >= 0
|
return playing && queued >= 0
|
||||||
|
@ -103,7 +102,7 @@ playlist::GetQueuedSong() const
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
playlist::UpdateQueuedSong(player_control &pc, const song *prev)
|
playlist::UpdateQueuedSong(player_control &pc, const Song *prev)
|
||||||
{
|
{
|
||||||
if (!playing)
|
if (!playing)
|
||||||
return;
|
return;
|
||||||
|
@ -130,7 +129,7 @@ playlist::UpdateQueuedSong(player_control &pc, const song *prev)
|
||||||
current = queue.PositionToOrder(current_position);
|
current = queue.PositionToOrder(current_position);
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct song *const next_song = next_order >= 0
|
const Song *const next_song = next_order >= 0
|
||||||
? queue.GetOrder(next_order)
|
? queue.GetOrder(next_order)
|
||||||
: nullptr;
|
: nullptr;
|
||||||
|
|
||||||
|
@ -154,9 +153,9 @@ playlist::PlayOrder(player_control &pc, int order)
|
||||||
playing = true;
|
playing = true;
|
||||||
queued = -1;
|
queued = -1;
|
||||||
|
|
||||||
struct song *song = song_dup_detached(queue.GetOrder(order));
|
Song *song = queue.GetOrder(order)->DupDetached();
|
||||||
|
|
||||||
char *uri = song_get_uri(song);
|
char *uri = song->GetURI();
|
||||||
g_debug("play %i:\"%s\"", order, uri);
|
g_debug("play %i:\"%s\"", order, uri);
|
||||||
g_free(uri);
|
g_free(uri);
|
||||||
|
|
||||||
|
@ -177,7 +176,7 @@ playlist::SyncWithPlayer(player_control &pc)
|
||||||
|
|
||||||
pc.Lock();
|
pc.Lock();
|
||||||
const player_state pc_state = pc.GetState();
|
const player_state pc_state = pc.GetState();
|
||||||
const song *pc_next_song = pc.next_song;
|
const Song *pc_next_song = pc.next_song;
|
||||||
pc.Unlock();
|
pc.Unlock();
|
||||||
|
|
||||||
if (pc_state == PLAYER_STATE_STOP)
|
if (pc_state == PLAYER_STATE_STOP)
|
||||||
|
@ -290,7 +289,7 @@ playlist::SetRandom(player_control &pc, bool status)
|
||||||
if (status == queue.random)
|
if (status == queue.random)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const struct song *const queued_song = GetQueuedSong();
|
const Song *const queued_song = GetQueuedSong();
|
||||||
|
|
||||||
queue.random = status;
|
queue.random = status;
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
struct player_control;
|
struct player_control;
|
||||||
|
struct Song;
|
||||||
|
|
||||||
struct playlist {
|
struct playlist {
|
||||||
/**
|
/**
|
||||||
|
@ -99,7 +100,7 @@ struct playlist {
|
||||||
* none if there is none (yet?) or if MPD isn't playing.
|
* none if there is none (yet?) or if MPD isn't playing.
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
const struct song *GetQueuedSong() const;
|
const Song *GetQueuedSong() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the "PLAYLIST" event handler. It is invoked by the
|
* This is the "PLAYLIST" event handler. It is invoked by the
|
||||||
|
@ -124,7 +125,7 @@ protected:
|
||||||
* @param prev the song which was previously queued, as
|
* @param prev the song which was previously queued, as
|
||||||
* determined by playlist_get_queued_song()
|
* determined by playlist_get_queued_song()
|
||||||
*/
|
*/
|
||||||
void UpdateQueuedSong(player_control &pc, const song *prev);
|
void UpdateQueuedSong(player_control &pc, const Song *prev);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Clear(player_control &pc);
|
void Clear(player_control &pc);
|
||||||
|
@ -134,7 +135,7 @@ public:
|
||||||
void FullIncrementVersions();
|
void FullIncrementVersions();
|
||||||
|
|
||||||
enum playlist_result AppendSong(player_control &pc,
|
enum playlist_result AppendSong(player_control &pc,
|
||||||
struct song *song,
|
Song *song,
|
||||||
unsigned *added_id=nullptr);
|
unsigned *added_id=nullptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -153,7 +154,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void DeleteInternal(player_control &pc,
|
void DeleteInternal(player_control &pc,
|
||||||
unsigned song, const struct song **queued_p);
|
unsigned song, const Song **queued_p);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum playlist_result DeletePosition(player_control &pc,
|
enum playlist_result DeletePosition(player_control &pc,
|
||||||
|
@ -175,7 +176,7 @@ public:
|
||||||
enum playlist_result DeleteRange(player_control &pc,
|
enum playlist_result DeleteRange(player_control &pc,
|
||||||
unsigned start, unsigned end);
|
unsigned start, unsigned end);
|
||||||
|
|
||||||
void DeleteSong(player_control &pc, const song &song);
|
void DeleteSong(player_control &pc, const Song &song);
|
||||||
|
|
||||||
void Shuffle(player_control &pc, unsigned start, unsigned end);
|
void Shuffle(player_control &pc, unsigned start, unsigned end);
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "Playlist.hxx"
|
#include "Playlist.hxx"
|
||||||
#include "PlayerControl.hxx"
|
#include "PlayerControl.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
|
@ -198,7 +198,7 @@ playlist::SeekSongPosition(player_control &pc, unsigned song, float seek_time)
|
||||||
if (!queue.IsValidPosition(song))
|
if (!queue.IsValidPosition(song))
|
||||||
return PLAYLIST_RESULT_BAD_RANGE;
|
return PLAYLIST_RESULT_BAD_RANGE;
|
||||||
|
|
||||||
const struct song *queued_song = GetQueuedSong();
|
const Song *queued_song = GetQueuedSong();
|
||||||
|
|
||||||
unsigned i = queue.random
|
unsigned i = queue.random
|
||||||
? queue.PositionToOrder(song)
|
? queue.PositionToOrder(song)
|
||||||
|
@ -218,7 +218,7 @@ playlist::SeekSongPosition(player_control &pc, unsigned song, float seek_time)
|
||||||
queued_song = nullptr;
|
queued_song = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct song *the_song = song_dup_detached(queue.GetOrder(i));
|
Song *the_song = queue.GetOrder(i)->DupDetached();
|
||||||
if (!pc.Seek(the_song, seek_time)) {
|
if (!pc.Seek(the_song, seek_time)) {
|
||||||
UpdateQueuedSong(pc, queued_song);
|
UpdateQueuedSong(pc, queued_song);
|
||||||
|
|
||||||
|
|
|
@ -27,11 +27,7 @@
|
||||||
#include "Playlist.hxx"
|
#include "Playlist.hxx"
|
||||||
#include "PlayerControl.hxx"
|
#include "PlayerControl.hxx"
|
||||||
#include "util/UriUtil.hxx"
|
#include "util/UriUtil.hxx"
|
||||||
|
#include "Song.hxx"
|
||||||
extern "C" {
|
|
||||||
#include "song.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "Idle.hxx"
|
#include "Idle.hxx"
|
||||||
#include "DatabaseGlue.hxx"
|
#include "DatabaseGlue.hxx"
|
||||||
#include "DatabasePlugin.hxx"
|
#include "DatabasePlugin.hxx"
|
||||||
|
@ -61,7 +57,7 @@ enum playlist_result
|
||||||
playlist::AppendFile(struct player_control &pc,
|
playlist::AppendFile(struct player_control &pc,
|
||||||
const char *path_utf8, unsigned *added_id)
|
const char *path_utf8, unsigned *added_id)
|
||||||
{
|
{
|
||||||
struct song *song = song_file_load(path_utf8, NULL);
|
Song *song = Song::LoadFile(path_utf8, nullptr);
|
||||||
if (song == NULL)
|
if (song == NULL)
|
||||||
return PLAYLIST_RESULT_NO_SUCH_SONG;
|
return PLAYLIST_RESULT_NO_SUCH_SONG;
|
||||||
|
|
||||||
|
@ -70,14 +66,14 @@ playlist::AppendFile(struct player_control &pc,
|
||||||
|
|
||||||
enum playlist_result
|
enum playlist_result
|
||||||
playlist::AppendSong(struct player_control &pc,
|
playlist::AppendSong(struct player_control &pc,
|
||||||
struct song *song, unsigned *added_id)
|
Song *song, unsigned *added_id)
|
||||||
{
|
{
|
||||||
unsigned id;
|
unsigned id;
|
||||||
|
|
||||||
if (queue.IsFull())
|
if (queue.IsFull())
|
||||||
return PLAYLIST_RESULT_TOO_LARGE;
|
return PLAYLIST_RESULT_TOO_LARGE;
|
||||||
|
|
||||||
const struct song *const queued_song = GetQueuedSong();
|
const Song *const queued_song = GetQueuedSong();
|
||||||
|
|
||||||
id = queue.Append(song, 0);
|
id = queue.Append(song, 0);
|
||||||
|
|
||||||
|
@ -110,9 +106,9 @@ playlist::AppendURI(struct player_control &pc,
|
||||||
g_debug("add to playlist: %s", uri);
|
g_debug("add to playlist: %s", uri);
|
||||||
|
|
||||||
const Database *db = nullptr;
|
const Database *db = nullptr;
|
||||||
struct song *song;
|
Song *song;
|
||||||
if (uri_has_scheme(uri)) {
|
if (uri_has_scheme(uri)) {
|
||||||
song = song_remote_new(uri);
|
song = Song::NewRemote(uri);
|
||||||
} else {
|
} else {
|
||||||
db = GetDatabase(nullptr);
|
db = GetDatabase(nullptr);
|
||||||
if (db == nullptr)
|
if (db == nullptr)
|
||||||
|
@ -136,7 +132,7 @@ playlist::SwapPositions(player_control &pc, unsigned song1, unsigned song2)
|
||||||
if (!queue.IsValidPosition(song1) || !queue.IsValidPosition(song2))
|
if (!queue.IsValidPosition(song1) || !queue.IsValidPosition(song2))
|
||||||
return PLAYLIST_RESULT_BAD_RANGE;
|
return PLAYLIST_RESULT_BAD_RANGE;
|
||||||
|
|
||||||
const struct song *const queued_song = GetQueuedSong();
|
const Song *const queued_song = GetQueuedSong();
|
||||||
|
|
||||||
queue.SwapPositions(song1, song2);
|
queue.SwapPositions(song1, song2);
|
||||||
|
|
||||||
|
@ -190,7 +186,7 @@ playlist::SetPriorityRange(player_control &pc,
|
||||||
/* remember "current" and "queued" */
|
/* remember "current" and "queued" */
|
||||||
|
|
||||||
const int current_position = GetCurrentPosition();
|
const int current_position = GetCurrentPosition();
|
||||||
const struct song *const queued_song = GetQueuedSong();
|
const Song *const queued_song = GetQueuedSong();
|
||||||
|
|
||||||
/* apply the priority changes */
|
/* apply the priority changes */
|
||||||
|
|
||||||
|
@ -222,7 +218,7 @@ playlist::SetPriorityId(struct player_control &pc,
|
||||||
|
|
||||||
void
|
void
|
||||||
playlist::DeleteInternal(player_control &pc,
|
playlist::DeleteInternal(player_control &pc,
|
||||||
unsigned song, const struct song **queued_p)
|
unsigned song, const Song **queued_p)
|
||||||
{
|
{
|
||||||
assert(song < GetLength());
|
assert(song < GetLength());
|
||||||
|
|
||||||
|
@ -272,7 +268,7 @@ playlist::DeletePosition(struct player_control &pc, unsigned song)
|
||||||
if (song >= queue.GetLength())
|
if (song >= queue.GetLength())
|
||||||
return PLAYLIST_RESULT_BAD_RANGE;
|
return PLAYLIST_RESULT_BAD_RANGE;
|
||||||
|
|
||||||
const struct song *queued_song = GetQueuedSong();
|
const Song *queued_song = GetQueuedSong();
|
||||||
|
|
||||||
DeleteInternal(pc, song, &queued_song);
|
DeleteInternal(pc, song, &queued_song);
|
||||||
|
|
||||||
|
@ -294,7 +290,7 @@ playlist::DeleteRange(struct player_control &pc, unsigned start, unsigned end)
|
||||||
if (start >= end)
|
if (start >= end)
|
||||||
return PLAYLIST_RESULT_SUCCESS;
|
return PLAYLIST_RESULT_SUCCESS;
|
||||||
|
|
||||||
const struct song *queued_song = GetQueuedSong();
|
const Song *queued_song = GetQueuedSong();
|
||||||
|
|
||||||
do {
|
do {
|
||||||
DeleteInternal(pc, --end, &queued_song);
|
DeleteInternal(pc, --end, &queued_song);
|
||||||
|
@ -317,7 +313,7 @@ playlist::DeleteId(struct player_control &pc, unsigned id)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
playlist::DeleteSong(struct player_control &pc, const struct song &song)
|
playlist::DeleteSong(struct player_control &pc, const struct Song &song)
|
||||||
{
|
{
|
||||||
for (int i = queue.GetLength() - 1; i >= 0; --i)
|
for (int i = queue.GetLength() - 1; i >= 0; --i)
|
||||||
// TODO: compare URI instead of pointer
|
// TODO: compare URI instead of pointer
|
||||||
|
@ -339,7 +335,7 @@ playlist::MoveRange(player_control &pc, unsigned start, unsigned end, int to)
|
||||||
/* nothing happens */
|
/* nothing happens */
|
||||||
return PLAYLIST_RESULT_SUCCESS;
|
return PLAYLIST_RESULT_SUCCESS;
|
||||||
|
|
||||||
const struct song *const queued_song = GetQueuedSong();
|
const Song *const queued_song = GetQueuedSong();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (to < 0) => move to offset from current song
|
* (to < 0) => move to offset from current song
|
||||||
|
@ -394,7 +390,7 @@ playlist::Shuffle(player_control &pc, unsigned start, unsigned end)
|
||||||
/* needs at least two entries. */
|
/* needs at least two entries. */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const struct song *const queued_song = GetQueuedSong();
|
const Song *const queued_song = GetQueuedSong();
|
||||||
if (playing && current >= 0) {
|
if (playing && current >= 0) {
|
||||||
unsigned current_position = queue.OrderToPosition(current);
|
unsigned current_position = queue.OrderToPosition(current);
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
#include "PlaylistVector.hxx"
|
#include "PlaylistVector.hxx"
|
||||||
#include "DatabasePlugin.hxx"
|
#include "DatabasePlugin.hxx"
|
||||||
#include "DatabaseGlue.hxx"
|
#include "DatabaseGlue.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "io_error.h"
|
#include "io_error.h"
|
||||||
#include "Mapper.hxx"
|
#include "Mapper.hxx"
|
||||||
#include "TextFile.hxx"
|
#include "TextFile.hxx"
|
||||||
|
@ -360,7 +360,7 @@ spl_remove_index(const char *utf8path, unsigned pos, GError **error_r)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
spl_append_song(const char *utf8path, struct song *song, GError **error_r)
|
spl_append_song(const char *utf8path, Song *song, GError **error_r)
|
||||||
{
|
{
|
||||||
if (spl_map(error_r).IsNull())
|
if (spl_map(error_r).IsNull())
|
||||||
return false;
|
return false;
|
||||||
|
@ -402,16 +402,16 @@ bool
|
||||||
spl_append_uri(const char *url, const char *utf8file, GError **error_r)
|
spl_append_uri(const char *url, const char *utf8file, GError **error_r)
|
||||||
{
|
{
|
||||||
if (uri_has_scheme(url)) {
|
if (uri_has_scheme(url)) {
|
||||||
struct song *song = song_remote_new(url);
|
Song *song = Song::NewRemote(url);
|
||||||
bool success = spl_append_song(utf8file, song, error_r);
|
bool success = spl_append_song(utf8file, song, error_r);
|
||||||
song_free(song);
|
song->Free();
|
||||||
return success;
|
return success;
|
||||||
} else {
|
} else {
|
||||||
const Database *db = GetDatabase(error_r);
|
const Database *db = GetDatabase(error_r);
|
||||||
if (db == nullptr)
|
if (db == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
song *song = db->GetSong(url, error_r);
|
Song *song = db->GetSong(url, error_r);
|
||||||
if (song == nullptr)
|
if (song == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
struct song;
|
struct Song;
|
||||||
struct PlaylistInfo;
|
struct PlaylistInfo;
|
||||||
class PlaylistVector;
|
class PlaylistVector;
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ bool
|
||||||
spl_remove_index(const char *utf8path, unsigned pos, GError **error_r);
|
spl_remove_index(const char *utf8path, unsigned pos, GError **error_r);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
spl_append_song(const char *utf8path, struct song *song, GError **error_r);
|
spl_append_song(const char *utf8path, Song *song, GError **error_r);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
spl_append_uri(const char *file, const char *utf8file, GError **error_r);
|
spl_append_uri(const char *file, const char *utf8file, GError **error_r);
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
struct config_param;
|
struct config_param;
|
||||||
struct input_stream;
|
struct input_stream;
|
||||||
struct tag;
|
struct tag;
|
||||||
|
struct Song;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An object which provides the contents of a playlist.
|
* An object which provides the contents of a playlist.
|
||||||
|
@ -78,7 +79,7 @@ struct playlist_plugin {
|
||||||
|
|
||||||
void (*close)(struct playlist_provider *playlist);
|
void (*close)(struct playlist_provider *playlist);
|
||||||
|
|
||||||
struct song *(*read)(struct playlist_provider *playlist);
|
Song *(*read)(struct playlist_provider *playlist);
|
||||||
|
|
||||||
const char *const*schemes;
|
const char *const*schemes;
|
||||||
const char *const*suffixes;
|
const char *const*suffixes;
|
||||||
|
@ -132,7 +133,7 @@ playlist_plugin_close(struct playlist_provider *playlist)
|
||||||
playlist->plugin->close(playlist);
|
playlist->plugin->close(playlist);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct song *
|
static inline Song *
|
||||||
playlist_plugin_read(struct playlist_provider *playlist)
|
playlist_plugin_read(struct playlist_provider *playlist)
|
||||||
{
|
{
|
||||||
return playlist->plugin->read(playlist);
|
return playlist->plugin->read(playlist);
|
||||||
|
|
|
@ -31,10 +31,7 @@
|
||||||
#include "DatabasePlugin.hxx"
|
#include "DatabasePlugin.hxx"
|
||||||
#include "Client.hxx"
|
#include "Client.hxx"
|
||||||
#include "input_stream.h"
|
#include "input_stream.h"
|
||||||
|
#include "Song.hxx"
|
||||||
extern "C" {
|
|
||||||
#include "song.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
playlist_print_uris(Client *client, const struct playlist *playlist)
|
playlist_print_uris(Client *client, const struct playlist *playlist)
|
||||||
|
@ -119,7 +116,7 @@ PrintSongDetails(Client *client, const char *uri_utf8)
|
||||||
if (db == nullptr)
|
if (db == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
song *song = db->GetSong(uri_utf8, nullptr);
|
Song *song = db->GetSong(uri_utf8, nullptr);
|
||||||
if (song == nullptr)
|
if (song == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -152,7 +149,7 @@ static void
|
||||||
playlist_provider_print(Client *client, const char *uri,
|
playlist_provider_print(Client *client, const char *uri,
|
||||||
struct playlist_provider *playlist, bool detail)
|
struct playlist_provider *playlist, bool detail)
|
||||||
{
|
{
|
||||||
struct song *song;
|
Song *song;
|
||||||
char *base_uri = uri != NULL ? g_path_get_dirname(uri) : NULL;
|
char *base_uri = uri != NULL ? g_path_get_dirname(uri) : NULL;
|
||||||
|
|
||||||
while ((song = playlist_plugin_read(playlist)) != NULL) {
|
while ((song = playlist_plugin_read(playlist)) != NULL) {
|
||||||
|
@ -165,7 +162,7 @@ playlist_provider_print(Client *client, const char *uri,
|
||||||
else
|
else
|
||||||
song_print_uri(client, song);
|
song_print_uri(client, song);
|
||||||
|
|
||||||
song_free(song);
|
song->Free();
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free(base_uri);
|
g_free(base_uri);
|
||||||
|
|
|
@ -24,10 +24,7 @@
|
||||||
#include "PlaylistSong.hxx"
|
#include "PlaylistSong.hxx"
|
||||||
#include "Playlist.hxx"
|
#include "Playlist.hxx"
|
||||||
#include "input_stream.h"
|
#include "input_stream.h"
|
||||||
|
#include "Song.hxx"
|
||||||
extern "C" {
|
|
||||||
#include "song.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
enum playlist_result
|
enum playlist_result
|
||||||
playlist_load_into_queue(const char *uri, struct playlist_provider *source,
|
playlist_load_into_queue(const char *uri, struct playlist_provider *source,
|
||||||
|
@ -36,7 +33,7 @@ playlist_load_into_queue(const char *uri, struct playlist_provider *source,
|
||||||
bool secure)
|
bool secure)
|
||||||
{
|
{
|
||||||
enum playlist_result result;
|
enum playlist_result result;
|
||||||
struct song *song;
|
Song *song;
|
||||||
char *base_uri = uri != NULL ? g_path_get_dirname(uri) : NULL;
|
char *base_uri = uri != NULL ? g_path_get_dirname(uri) : NULL;
|
||||||
|
|
||||||
for (unsigned i = 0;
|
for (unsigned i = 0;
|
||||||
|
@ -44,7 +41,7 @@ playlist_load_into_queue(const char *uri, struct playlist_provider *source,
|
||||||
++i) {
|
++i) {
|
||||||
if (i < start_index) {
|
if (i < start_index) {
|
||||||
/* skip songs before the start index */
|
/* skip songs before the start index */
|
||||||
song_free(song);
|
song->Free();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +50,7 @@ playlist_load_into_queue(const char *uri, struct playlist_provider *source,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
result = dest->AppendSong(*pc, song);
|
result = dest->AppendSong(*pc, song);
|
||||||
song_free(song);
|
song->Free();
|
||||||
if (result != PLAYLIST_RESULT_SUCCESS) {
|
if (result != PLAYLIST_RESULT_SUCCESS) {
|
||||||
g_free(base_uri);
|
g_free(base_uri);
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include "PlaylistSave.hxx"
|
#include "PlaylistSave.hxx"
|
||||||
#include "PlaylistFile.hxx"
|
#include "PlaylistFile.hxx"
|
||||||
#include "Playlist.hxx"
|
#include "Playlist.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "Mapper.hxx"
|
#include "Mapper.hxx"
|
||||||
#include "Idle.hxx"
|
#include "Idle.hxx"
|
||||||
#include "fs/Path.hxx"
|
#include "fs/Path.hxx"
|
||||||
|
@ -31,14 +31,14 @@
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
void
|
void
|
||||||
playlist_print_song(FILE *file, const struct song *song)
|
playlist_print_song(FILE *file, const Song *song)
|
||||||
{
|
{
|
||||||
if (playlist_saveAbsolutePaths && song_in_database(song)) {
|
if (playlist_saveAbsolutePaths && song->IsInDatabase()) {
|
||||||
const Path path = map_song_fs(song);
|
const Path path = map_song_fs(song);
|
||||||
if (!path.IsNull())
|
if (!path.IsNull())
|
||||||
fprintf(file, "%s\n", path.c_str());
|
fprintf(file, "%s\n", path.c_str());
|
||||||
} else {
|
} else {
|
||||||
char *uri = song_get_uri(song);
|
char *uri = song->GetURI();
|
||||||
const Path uri_fs = Path::FromUTF8(uri);
|
const Path uri_fs = Path::FromUTF8(uri);
|
||||||
g_free(uri);
|
g_free(uri);
|
||||||
|
|
||||||
|
|
|
@ -24,13 +24,13 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
struct song;
|
struct Song;
|
||||||
struct queue;
|
struct queue;
|
||||||
struct playlist;
|
struct playlist;
|
||||||
struct player_control;
|
struct player_control;
|
||||||
|
|
||||||
void
|
void
|
||||||
playlist_print_song(FILE *fp, const struct song *song);
|
playlist_print_song(FILE *fp, const Song *song);
|
||||||
|
|
||||||
void
|
void
|
||||||
playlist_print_uri(FILE *fp, const char *uri);
|
playlist_print_uri(FILE *fp, const char *uri);
|
||||||
|
|
|
@ -26,10 +26,7 @@
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
#include "fs/Path.hxx"
|
#include "fs/Path.hxx"
|
||||||
#include "util/UriUtil.hxx"
|
#include "util/UriUtil.hxx"
|
||||||
|
#include "Song.hxx"
|
||||||
extern "C" {
|
|
||||||
#include "song.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
|
@ -37,8 +34,8 @@ extern "C" {
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
static void
|
static void
|
||||||
merge_song_metadata(struct song *dest, const struct song *base,
|
merge_song_metadata(Song *dest, const Song *base,
|
||||||
const struct song *add)
|
const Song *add)
|
||||||
{
|
{
|
||||||
dest->tag = base->tag != NULL
|
dest->tag = base->tag != NULL
|
||||||
? (add->tag != NULL
|
? (add->tag != NULL
|
||||||
|
@ -53,10 +50,10 @@ merge_song_metadata(struct song *dest, const struct song *base,
|
||||||
dest->end_ms = add->end_ms;
|
dest->end_ms = add->end_ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct song *
|
static Song *
|
||||||
apply_song_metadata(struct song *dest, const struct song *src)
|
apply_song_metadata(Song *dest, const Song *src)
|
||||||
{
|
{
|
||||||
struct song *tmp;
|
Song *tmp;
|
||||||
|
|
||||||
assert(dest != NULL);
|
assert(dest != NULL);
|
||||||
assert(src != NULL);
|
assert(src != NULL);
|
||||||
|
@ -64,7 +61,7 @@ apply_song_metadata(struct song *dest, const struct song *src)
|
||||||
if (src->tag == NULL && src->start_ms == 0 && src->end_ms == 0)
|
if (src->tag == NULL && src->start_ms == 0 && src->end_ms == 0)
|
||||||
return dest;
|
return dest;
|
||||||
|
|
||||||
if (song_in_database(dest)) {
|
if (dest->IsInDatabase()) {
|
||||||
const Path &path_fs = map_song_fs(dest);
|
const Path &path_fs = map_song_fs(dest);
|
||||||
if (path_fs.IsNull())
|
if (path_fs.IsNull())
|
||||||
return dest;
|
return dest;
|
||||||
|
@ -73,11 +70,11 @@ apply_song_metadata(struct song *dest, const struct song *src)
|
||||||
if (path_utf8.empty())
|
if (path_utf8.empty())
|
||||||
path_utf8 = path_fs.c_str();
|
path_utf8 = path_fs.c_str();
|
||||||
|
|
||||||
tmp = song_file_new(path_utf8.c_str(), NULL);
|
tmp = Song::NewFile(path_utf8.c_str(), NULL);
|
||||||
|
|
||||||
merge_song_metadata(tmp, dest, src);
|
merge_song_metadata(tmp, dest, src);
|
||||||
} else {
|
} else {
|
||||||
tmp = song_file_new(dest->uri, NULL);
|
tmp = Song::NewFile(dest->uri, NULL);
|
||||||
merge_song_metadata(tmp, dest, src);
|
merge_song_metadata(tmp, dest, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,19 +86,19 @@ apply_song_metadata(struct song *dest, const struct song *src)
|
||||||
(e.g. last track on a CUE file); fix it up here */
|
(e.g. last track on a CUE file); fix it up here */
|
||||||
tmp->tag->time = dest->tag->time - src->start_ms / 1000;
|
tmp->tag->time = dest->tag->time - src->start_ms / 1000;
|
||||||
|
|
||||||
song_free(dest);
|
dest->Free();
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct song *
|
static Song *
|
||||||
playlist_check_load_song(const struct song *song, const char *uri, bool secure)
|
playlist_check_load_song(const Song *song, const char *uri, bool secure)
|
||||||
{
|
{
|
||||||
struct song *dest;
|
Song *dest;
|
||||||
|
|
||||||
if (uri_has_scheme(uri)) {
|
if (uri_has_scheme(uri)) {
|
||||||
dest = song_remote_new(uri);
|
dest = Song::NewRemote(uri);
|
||||||
} else if (g_path_is_absolute(uri) && secure) {
|
} else if (g_path_is_absolute(uri) && secure) {
|
||||||
dest = song_file_load(uri, NULL);
|
dest = Song::LoadFile(uri, nullptr);
|
||||||
if (dest == NULL)
|
if (dest == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
} else {
|
} else {
|
||||||
|
@ -109,23 +106,23 @@ playlist_check_load_song(const struct song *song, const char *uri, bool secure)
|
||||||
if (db == nullptr)
|
if (db == nullptr)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
struct song *tmp = db->GetSong(uri, nullptr);
|
Song *tmp = db->GetSong(uri, nullptr);
|
||||||
if (tmp == NULL)
|
if (tmp == NULL)
|
||||||
/* not found in database */
|
/* not found in database */
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
dest = song_dup_detached(tmp);
|
dest = tmp->DupDetached();
|
||||||
db->ReturnSong(tmp);
|
db->ReturnSong(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
return apply_song_metadata(dest, song);
|
return apply_song_metadata(dest, song);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct song *
|
Song *
|
||||||
playlist_check_translate_song(struct song *song, const char *base_uri,
|
playlist_check_translate_song(Song *song, const char *base_uri,
|
||||||
bool secure)
|
bool secure)
|
||||||
{
|
{
|
||||||
if (song_in_database(song))
|
if (song->IsInDatabase())
|
||||||
/* already ok */
|
/* already ok */
|
||||||
return song;
|
return song;
|
||||||
|
|
||||||
|
@ -137,7 +134,7 @@ playlist_check_translate_song(struct song *song, const char *base_uri,
|
||||||
return song;
|
return song;
|
||||||
else {
|
else {
|
||||||
/* unsupported remote song */
|
/* unsupported remote song */
|
||||||
song_free(song);
|
song->Free();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,7 +156,7 @@ playlist_check_translate_song(struct song *song, const char *base_uri,
|
||||||
else if (!secure) {
|
else if (!secure) {
|
||||||
/* local files must be relative to the music
|
/* local files must be relative to the music
|
||||||
directory when "secure" is enabled */
|
directory when "secure" is enabled */
|
||||||
song_free(song);
|
song->Free();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,8 +167,8 @@ playlist_check_translate_song(struct song *song, const char *base_uri,
|
||||||
if (base_uri != NULL)
|
if (base_uri != NULL)
|
||||||
uri = allocated = g_build_filename(base_uri, uri, NULL);
|
uri = allocated = g_build_filename(base_uri, uri, NULL);
|
||||||
|
|
||||||
struct song *dest = playlist_check_load_song(song, uri, secure);
|
Song *dest = playlist_check_load_song(song, uri, secure);
|
||||||
song_free(song);
|
song->Free();
|
||||||
g_free(allocated);
|
g_free(allocated);
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
#ifndef MPD_PLAYLIST_SONG_HXX
|
#ifndef MPD_PLAYLIST_SONG_HXX
|
||||||
#define MPD_PLAYLIST_SONG_HXX
|
#define MPD_PLAYLIST_SONG_HXX
|
||||||
|
|
||||||
|
struct Song;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verifies the song, returns NULL if it is unsafe. Translate the
|
* Verifies the song, returns NULL if it is unsafe. Translate the
|
||||||
* song to a new song object within the database, if it is a local
|
* song to a new song object within the database, if it is a local
|
||||||
|
@ -28,8 +30,8 @@
|
||||||
* @param secure if true, then local files are only allowed if they
|
* @param secure if true, then local files are only allowed if they
|
||||||
* are relative to base_uri
|
* are relative to base_uri
|
||||||
*/
|
*/
|
||||||
struct song *
|
Song *
|
||||||
playlist_check_translate_song(struct song *song, const char *base_uri,
|
playlist_check_translate_song(Song *song, const char *base_uri,
|
||||||
bool secure);
|
bool secure);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "Queue.hxx"
|
#include "Queue.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ queue::ModifyAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
queue::Append(struct song *song, uint8_t priority)
|
queue::Append(Song *song, uint8_t priority)
|
||||||
{
|
{
|
||||||
assert(!IsFull());
|
assert(!IsFull());
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ queue::Append(struct song *song, uint8_t priority)
|
||||||
const unsigned id = id_table.Insert(position);
|
const unsigned id = id_table.Insert(position);
|
||||||
|
|
||||||
auto &item = items[position];
|
auto &item = items[position];
|
||||||
item.song = song_dup_detached(song);
|
item.song = song->DupDetached();
|
||||||
item.id = id;
|
item.id = id;
|
||||||
item.version = version;
|
item.version = version;
|
||||||
item.priority = priority;
|
item.priority = priority;
|
||||||
|
@ -232,9 +232,9 @@ queue::DeletePosition(unsigned position)
|
||||||
{
|
{
|
||||||
assert(position < length);
|
assert(position < length);
|
||||||
|
|
||||||
struct song *song = Get(position);
|
Song *song = Get(position);
|
||||||
assert(!song_in_database(song) || song_is_detached(song));
|
assert(!song->IsInDatabase() || song->IsDetached());
|
||||||
song_free(song);
|
song->Free();
|
||||||
|
|
||||||
const unsigned id = PositionToId(position);
|
const unsigned id = PositionToId(position);
|
||||||
const unsigned _order = PositionToOrder(position);
|
const unsigned _order = PositionToOrder(position);
|
||||||
|
@ -268,9 +268,9 @@ queue::Clear()
|
||||||
for (unsigned i = 0; i < length; i++) {
|
for (unsigned i = 0; i < length; i++) {
|
||||||
Item *item = &items[i];
|
Item *item = &items[i];
|
||||||
|
|
||||||
assert(!song_in_database(item->song) ||
|
assert(!item->song->IsInDatabase() ||
|
||||||
song_is_detached(item->song));
|
item->song->IsDetached());
|
||||||
song_free(item->song);
|
item->song->Free();
|
||||||
|
|
||||||
id_table.Erase(item->id);
|
id_table.Erase(item->id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,8 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct Song;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A queue of songs. This is the backend of the playlist: it contains
|
* A queue of songs. This is the backend of the playlist: it contains
|
||||||
* an ordered list of songs.
|
* an ordered list of songs.
|
||||||
|
@ -51,7 +53,7 @@ struct queue {
|
||||||
* information attached.
|
* information attached.
|
||||||
*/
|
*/
|
||||||
struct Item {
|
struct Item {
|
||||||
struct song *song;
|
Song *song;
|
||||||
|
|
||||||
/** the unique id of this item in the queue */
|
/** the unique id of this item in the queue */
|
||||||
unsigned id;
|
unsigned id;
|
||||||
|
@ -198,7 +200,7 @@ struct queue {
|
||||||
/**
|
/**
|
||||||
* Returns the song at the specified position.
|
* Returns the song at the specified position.
|
||||||
*/
|
*/
|
||||||
struct song *Get(unsigned position) const {
|
Song *Get(unsigned position) const {
|
||||||
assert(position < length);
|
assert(position < length);
|
||||||
|
|
||||||
return items[position].song;
|
return items[position].song;
|
||||||
|
@ -207,7 +209,7 @@ struct queue {
|
||||||
/**
|
/**
|
||||||
* Returns the song at the specified order number.
|
* Returns the song at the specified order number.
|
||||||
*/
|
*/
|
||||||
struct song *GetOrder(unsigned _order) const {
|
Song *GetOrder(unsigned _order) const {
|
||||||
return Get(OrderToPosition(_order));
|
return Get(OrderToPosition(_order));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,11 +256,12 @@ struct queue {
|
||||||
* that, the caller must check if the queue is already full.
|
* that, the caller must check if the queue is already full.
|
||||||
*
|
*
|
||||||
* If a song is not in the database (determined by
|
* If a song is not in the database (determined by
|
||||||
* song_in_database()), it is freed when removed from the queue.
|
* Song::IsInDatabase()), it is freed when removed from the
|
||||||
|
* queue.
|
||||||
*
|
*
|
||||||
* @param priority the priority of this new queue item
|
* @param priority the priority of this new queue item
|
||||||
*/
|
*/
|
||||||
unsigned Append(struct song *song, uint8_t priority);
|
unsigned Append(Song *song, uint8_t priority);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Swaps two songs, addressed by their position.
|
* Swaps two songs, addressed by their position.
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#include "Client.hxx"
|
#include "Client.hxx"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -99,7 +99,7 @@ queue_find(Client *client, const struct queue *queue,
|
||||||
const SongFilter &filter)
|
const SongFilter &filter)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < queue->GetLength(); i++) {
|
for (unsigned i = 0; i < queue->GetLength(); i++) {
|
||||||
const struct song *song = queue->Get(i);
|
const Song *song = queue->Get(i);
|
||||||
|
|
||||||
if (filter.Match(*song))
|
if (filter.Match(*song))
|
||||||
queue_print_song_info(client, queue, i);
|
queue_print_song_info(client, queue, i);
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "QueueSave.hxx"
|
#include "QueueSave.hxx"
|
||||||
#include "Playlist.hxx"
|
#include "Playlist.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "SongSave.hxx"
|
#include "SongSave.hxx"
|
||||||
#include "DatabasePlugin.hxx"
|
#include "DatabasePlugin.hxx"
|
||||||
#include "DatabaseGlue.hxx"
|
#include "DatabaseGlue.hxx"
|
||||||
|
@ -32,24 +32,24 @@
|
||||||
#define PRIO_LABEL "Prio: "
|
#define PRIO_LABEL "Prio: "
|
||||||
|
|
||||||
static void
|
static void
|
||||||
queue_save_database_song(FILE *fp, int idx, const struct song *song)
|
queue_save_database_song(FILE *fp, int idx, const Song *song)
|
||||||
{
|
{
|
||||||
char *uri = song_get_uri(song);
|
char *uri = song->GetURI();
|
||||||
|
|
||||||
fprintf(fp, "%i:%s\n", idx, uri);
|
fprintf(fp, "%i:%s\n", idx, uri);
|
||||||
g_free(uri);
|
g_free(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
queue_save_full_song(FILE *fp, const struct song *song)
|
queue_save_full_song(FILE *fp, const Song *song)
|
||||||
{
|
{
|
||||||
song_save(fp, song);
|
song_save(fp, song);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
queue_save_song(FILE *fp, int idx, const struct song *song)
|
queue_save_song(FILE *fp, int idx, const Song *song)
|
||||||
{
|
{
|
||||||
if (song_in_database(song))
|
if (song->IsInDatabase())
|
||||||
queue_save_database_song(fp, idx, song);
|
queue_save_database_song(fp, idx, song);
|
||||||
else
|
else
|
||||||
queue_save_full_song(fp, song);
|
queue_save_full_song(fp, song);
|
||||||
|
@ -83,7 +83,7 @@ queue_load_song(TextFile &file, const char *line, queue *queue)
|
||||||
}
|
}
|
||||||
|
|
||||||
const Database *db = nullptr;
|
const Database *db = nullptr;
|
||||||
struct song *song;
|
Song *song;
|
||||||
|
|
||||||
if (g_str_has_prefix(line, SONG_BEGIN)) {
|
if (g_str_has_prefix(line, SONG_BEGIN)) {
|
||||||
const char *uri = line + sizeof(SONG_BEGIN) - 1;
|
const char *uri = line + sizeof(SONG_BEGIN) - 1;
|
||||||
|
@ -108,7 +108,7 @@ queue_load_song(TextFile &file, const char *line, queue *queue)
|
||||||
const char *uri = endptr + 1;
|
const char *uri = endptr + 1;
|
||||||
|
|
||||||
if (uri_has_scheme(uri)) {
|
if (uri_has_scheme(uri)) {
|
||||||
song = song_remote_new(uri);
|
song = Song::NewRemote(uri);
|
||||||
} else {
|
} else {
|
||||||
db = GetDatabase(nullptr);
|
db = GetDatabase(nullptr);
|
||||||
if (db == nullptr)
|
if (db == nullptr)
|
||||||
|
|
97
src/Song.cxx
97
src/Song.cxx
|
@ -18,7 +18,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "Directory.hxx"
|
#include "Directory.hxx"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
Directory detached_root;
|
Directory detached_root;
|
||||||
|
|
||||||
static struct song *
|
static Song *
|
||||||
song_alloc(const char *uri, Directory *parent)
|
song_alloc(const char *uri, Directory *parent)
|
||||||
{
|
{
|
||||||
size_t uri_length;
|
size_t uri_length;
|
||||||
|
@ -37,7 +37,7 @@ song_alloc(const char *uri, Directory *parent)
|
||||||
uri_length = strlen(uri);
|
uri_length = strlen(uri);
|
||||||
assert(uri_length);
|
assert(uri_length);
|
||||||
|
|
||||||
struct song *song = (struct song *)
|
Song *song = (Song *)
|
||||||
g_malloc(sizeof(*song) - sizeof(song->uri) + uri_length + 1);
|
g_malloc(sizeof(*song) - sizeof(song->uri) + uri_length + 1);
|
||||||
|
|
||||||
song->tag = nullptr;
|
song->tag = nullptr;
|
||||||
|
@ -49,67 +49,65 @@ song_alloc(const char *uri, Directory *parent)
|
||||||
return song;
|
return song;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct song *
|
Song *
|
||||||
song_remote_new(const char *uri)
|
Song::NewRemote(const char *uri)
|
||||||
{
|
{
|
||||||
return song_alloc(uri, nullptr);
|
return song_alloc(uri, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct song *
|
Song *
|
||||||
song_file_new(const char *path, Directory *parent)
|
Song::NewFile(const char *path, Directory *parent)
|
||||||
{
|
{
|
||||||
assert((parent == nullptr) == (*path == '/'));
|
assert((parent == nullptr) == (*path == '/'));
|
||||||
|
|
||||||
return song_alloc(path, parent);
|
return song_alloc(path, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct song *
|
Song *
|
||||||
song_replace_uri(struct song *old_song, const char *uri)
|
Song::ReplaceURI(const char *new_uri)
|
||||||
{
|
{
|
||||||
struct song *new_song = song_alloc(uri, old_song->parent);
|
Song *new_song = song_alloc(new_uri, parent);
|
||||||
new_song->tag = old_song->tag;
|
new_song->tag = tag;
|
||||||
new_song->mtime = old_song->mtime;
|
new_song->mtime = mtime;
|
||||||
new_song->start_ms = old_song->start_ms;
|
new_song->start_ms = start_ms;
|
||||||
new_song->end_ms = old_song->end_ms;
|
new_song->end_ms = end_ms;
|
||||||
g_free(old_song);
|
g_free(this);
|
||||||
return new_song;
|
return new_song;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct song *
|
Song *
|
||||||
song_detached_new(const char *uri)
|
Song::NewDetached(const char *uri)
|
||||||
{
|
{
|
||||||
assert(uri != nullptr);
|
assert(uri != nullptr);
|
||||||
|
|
||||||
return song_alloc(uri, &detached_root);
|
return song_alloc(uri, &detached_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct song *
|
Song *
|
||||||
song_dup_detached(const struct song *src)
|
Song::DupDetached() const
|
||||||
{
|
{
|
||||||
assert(src != nullptr);
|
Song *song;
|
||||||
|
if (IsInDatabase()) {
|
||||||
struct song *song;
|
char *new_uri = GetURI();
|
||||||
if (song_in_database(src)) {
|
song = NewDetached(new_uri);
|
||||||
char *uri = song_get_uri(src);
|
g_free(new_uri);
|
||||||
song = song_detached_new(uri);
|
|
||||||
g_free(uri);
|
|
||||||
} else
|
} else
|
||||||
song = song_alloc(src->uri, nullptr);
|
song = song_alloc(uri, nullptr);
|
||||||
|
|
||||||
song->tag = tag_dup(src->tag);
|
song->tag = tag_dup(tag);
|
||||||
song->mtime = src->mtime;
|
song->mtime = mtime;
|
||||||
song->start_ms = src->start_ms;
|
song->start_ms = start_ms;
|
||||||
song->end_ms = src->end_ms;
|
song->end_ms = end_ms;
|
||||||
|
|
||||||
return song;
|
return song;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
song_free(struct song *song)
|
Song::Free()
|
||||||
{
|
{
|
||||||
if (song->tag)
|
if (tag != nullptr)
|
||||||
tag_free(song->tag);
|
tag_free(tag);
|
||||||
g_free(song);
|
g_free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
|
@ -130,7 +128,7 @@ directory_is_same(const Directory *a, const Directory *b)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
song_equals(const struct song *a, const struct song *b)
|
song_equals(const Song *a, const Song *b)
|
||||||
{
|
{
|
||||||
assert(a != nullptr);
|
assert(a != nullptr);
|
||||||
assert(b != nullptr);
|
assert(b != nullptr);
|
||||||
|
@ -140,8 +138,8 @@ song_equals(const struct song *a, const struct song *b)
|
||||||
(a->parent == &detached_root || b->parent == &detached_root)) {
|
(a->parent == &detached_root || b->parent == &detached_root)) {
|
||||||
/* must compare the full URI if one of the objects is
|
/* must compare the full URI if one of the objects is
|
||||||
"detached" */
|
"detached" */
|
||||||
char *au = song_get_uri(a);
|
char *au = a->GetURI();
|
||||||
char *bu = song_get_uri(b);
|
char *bu = b->GetURI();
|
||||||
const bool result = strcmp(au, bu) == 0;
|
const bool result = strcmp(au, bu) == 0;
|
||||||
g_free(bu);
|
g_free(bu);
|
||||||
g_free(au);
|
g_free(au);
|
||||||
|
@ -153,26 +151,25 @@ song_equals(const struct song *a, const struct song *b)
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
song_get_uri(const struct song *song)
|
Song::GetURI() const
|
||||||
{
|
{
|
||||||
assert(song != nullptr);
|
assert(*uri);
|
||||||
assert(*song->uri);
|
|
||||||
|
|
||||||
if (!song_in_database(song) || song->parent->IsRoot())
|
if (!IsInDatabase() || parent->IsRoot())
|
||||||
return g_strdup(song->uri);
|
return g_strdup(uri);
|
||||||
else
|
else
|
||||||
return g_strconcat(song->parent->GetPath(),
|
return g_strconcat(parent->GetPath(),
|
||||||
"/", song->uri, nullptr);
|
"/", uri, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
double
|
double
|
||||||
song_get_duration(const struct song *song)
|
Song::GetDuration() const
|
||||||
{
|
{
|
||||||
if (song->end_ms > 0)
|
if (end_ms > 0)
|
||||||
return (song->end_ms - song->start_ms) / 1000.0;
|
return (end_ms - start_ms) / 1000.0;
|
||||||
|
|
||||||
if (song->tag == nullptr)
|
if (tag == nullptr)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return song->tag->time - song->start_ms / 1000.0;
|
return tag->time - start_ms / 1000.0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,147 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-2013 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_SONG_HXX
|
||||||
|
#define MPD_SONG_HXX
|
||||||
|
|
||||||
|
#include "util/list.h"
|
||||||
|
#include "gcc.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#define SONG_FILE "file: "
|
||||||
|
#define SONG_TIME "Time: "
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A dummy #directory instance that is used for "detached" song
|
||||||
|
* copies.
|
||||||
|
*/
|
||||||
|
extern struct Directory detached_root;
|
||||||
|
|
||||||
|
struct Song {
|
||||||
|
/**
|
||||||
|
* Pointers to the siblings of this directory within the
|
||||||
|
* parent directory. It is unused (undefined) if this song is
|
||||||
|
* not in the database.
|
||||||
|
*
|
||||||
|
* This attribute is protected with the global #db_mutex.
|
||||||
|
* Read access in the update thread does not need protection.
|
||||||
|
*/
|
||||||
|
struct list_head siblings;
|
||||||
|
|
||||||
|
struct tag *tag;
|
||||||
|
Directory *parent;
|
||||||
|
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;
|
||||||
|
|
||||||
|
char uri[sizeof(int)];
|
||||||
|
|
||||||
|
/** allocate a new song with a remote URL */
|
||||||
|
gcc_malloc
|
||||||
|
static Song *NewRemote(const char *uri);
|
||||||
|
|
||||||
|
/** allocate a new song with a local file name */
|
||||||
|
gcc_malloc
|
||||||
|
static Song *NewFile(const char *path_utf8, Directory *parent);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* allocate a new song structure with a local file name and attempt to
|
||||||
|
* load its metadata. If all decoder plugin fail to read its meta
|
||||||
|
* data, nullptr is returned.
|
||||||
|
*/
|
||||||
|
gcc_malloc
|
||||||
|
static Song *LoadFile(const char *path_utf8, Directory *parent);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces the URI of a song object. The given song object
|
||||||
|
* is destroyed, and a newly allocated one is returned. It
|
||||||
|
* does not update the reference within the parent directory;
|
||||||
|
* the caller is responsible for doing that.
|
||||||
|
*/
|
||||||
|
gcc_malloc
|
||||||
|
Song *ReplaceURI(const char *uri);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a "detached" song object.
|
||||||
|
*/
|
||||||
|
gcc_malloc
|
||||||
|
static Song *NewDetached(const char *uri);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a duplicate of the song object. If the object is
|
||||||
|
* in the database, it creates a "detached" copy of this song,
|
||||||
|
* see Song::IsDetached().
|
||||||
|
*/
|
||||||
|
gcc_malloc
|
||||||
|
Song *DupDetached() const;
|
||||||
|
|
||||||
|
void Free();
|
||||||
|
|
||||||
|
bool IsInDatabase() const {
|
||||||
|
return parent != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsFile() const {
|
||||||
|
return IsInDatabase() || uri[0] == '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsDetached() const {
|
||||||
|
assert(IsInDatabase());
|
||||||
|
|
||||||
|
return parent == &detached_root;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UpdateFile();
|
||||||
|
bool UpdateFileInArchive();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the URI of the song in UTF-8 encoding, including its
|
||||||
|
* location within the music directory.
|
||||||
|
*
|
||||||
|
* The return value is allocated on the heap, and must be freed by the
|
||||||
|
* caller.
|
||||||
|
*/
|
||||||
|
gcc_malloc
|
||||||
|
char *GetURI() const;
|
||||||
|
|
||||||
|
gcc_pure
|
||||||
|
double GetDuration() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if both objects refer to the same physical song.
|
||||||
|
*/
|
||||||
|
gcc_pure
|
||||||
|
bool
|
||||||
|
song_equals(const Song *a, const Song *b);
|
||||||
|
|
||||||
|
#endif
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "SongFilter.hxx"
|
#include "SongFilter.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
@ -107,10 +107,10 @@ SongFilter::Item::Match(const struct tag &_tag) const
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SongFilter::Item::Match(const song &song) const
|
SongFilter::Item::Match(const Song &song) const
|
||||||
{
|
{
|
||||||
if (tag == LOCATE_TAG_FILE_TYPE || tag == LOCATE_TAG_ANY_TYPE) {
|
if (tag == LOCATE_TAG_FILE_TYPE || tag == LOCATE_TAG_ANY_TYPE) {
|
||||||
char *uri = song_get_uri(&song);
|
char *uri = song.GetURI();
|
||||||
const bool result = StringMatch(uri);
|
const bool result = StringMatch(uri);
|
||||||
g_free(uri);
|
g_free(uri);
|
||||||
|
|
||||||
|
@ -156,7 +156,7 @@ SongFilter::Parse(unsigned argc, char *argv[], bool fold_case)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SongFilter::Match(const song &song) const
|
SongFilter::Match(const Song &song) const
|
||||||
{
|
{
|
||||||
for (const auto &i : items)
|
for (const auto &i : items)
|
||||||
if (!i.Match(song))
|
if (!i.Match(song))
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
|
|
||||||
struct tag;
|
struct tag;
|
||||||
struct tag_item;
|
struct tag_item;
|
||||||
struct song;
|
struct Song;
|
||||||
|
|
||||||
class SongFilter {
|
class SongFilter {
|
||||||
class Item {
|
class Item {
|
||||||
|
@ -71,7 +71,7 @@ class SongFilter {
|
||||||
bool Match(const struct tag &tag) const;
|
bool Match(const struct tag &tag) const;
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool Match(const song &song) const;
|
bool Match(const Song &song) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::list<Item> items;
|
std::list<Item> items;
|
||||||
|
@ -94,7 +94,7 @@ public:
|
||||||
bool Match(const tag &tag) const;
|
bool Match(const tag &tag) const;
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool Match(const song &song) const;
|
bool Match(const Song &song) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -20,15 +20,15 @@
|
||||||
#ifndef MPD_SONG_POINTER_HXX
|
#ifndef MPD_SONG_POINTER_HXX
|
||||||
#define MPD_SONG_POINTER_HXX
|
#define MPD_SONG_POINTER_HXX
|
||||||
|
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
class SongPointer {
|
class SongPointer {
|
||||||
struct song *song;
|
Song *song;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit SongPointer(struct song *_song)
|
explicit SongPointer(Song *_song)
|
||||||
:song(_song) {}
|
:song(_song) {}
|
||||||
|
|
||||||
SongPointer(const SongPointer &) = delete;
|
SongPointer(const SongPointer &) = delete;
|
||||||
|
@ -39,7 +39,7 @@ public:
|
||||||
|
|
||||||
~SongPointer() {
|
~SongPointer() {
|
||||||
if (song != nullptr)
|
if (song != nullptr)
|
||||||
song_free(song);
|
song->Free();
|
||||||
}
|
}
|
||||||
|
|
||||||
SongPointer &operator=(const SongPointer &) = delete;
|
SongPointer &operator=(const SongPointer &) = delete;
|
||||||
|
@ -49,11 +49,11 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator const struct song *() const {
|
operator const Song *() const {
|
||||||
return song;
|
return song;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct song *Steal() {
|
Song *Steal() {
|
||||||
auto result = song;
|
auto result = song;
|
||||||
song = nullptr;
|
song = nullptr;
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "SongPrint.hxx"
|
#include "SongPrint.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "Directory.hxx"
|
#include "Directory.hxx"
|
||||||
#include "TimePrint.hxx"
|
#include "TimePrint.hxx"
|
||||||
#include "TagPrint.hxx"
|
#include "TagPrint.hxx"
|
||||||
|
@ -30,9 +30,9 @@
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
void
|
void
|
||||||
song_print_uri(Client *client, struct song *song)
|
song_print_uri(Client *client, Song *song)
|
||||||
{
|
{
|
||||||
if (song_in_database(song) && !song->parent->IsRoot()) {
|
if (song->IsInDatabase() && !song->parent->IsRoot()) {
|
||||||
client_printf(client, "%s%s/%s\n", SONG_FILE,
|
client_printf(client, "%s%s/%s\n", SONG_FILE,
|
||||||
song->parent->GetPath(), song->uri);
|
song->parent->GetPath(), song->uri);
|
||||||
} else {
|
} else {
|
||||||
|
@ -51,7 +51,7 @@ song_print_uri(Client *client, struct song *song)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
song_print_info(Client *client, struct song *song)
|
song_print_info(Client *client, Song *song)
|
||||||
{
|
{
|
||||||
song_print_uri(client, song);
|
song_print_uri(client, song);
|
||||||
|
|
||||||
|
|
|
@ -20,13 +20,13 @@
|
||||||
#ifndef MPD_SONG_PRINT_HXX
|
#ifndef MPD_SONG_PRINT_HXX
|
||||||
#define MPD_SONG_PRINT_HXX
|
#define MPD_SONG_PRINT_HXX
|
||||||
|
|
||||||
struct song;
|
struct Song;
|
||||||
class Client;
|
class Client;
|
||||||
|
|
||||||
void
|
void
|
||||||
song_print_info(Client *client, struct song *song);
|
song_print_info(Client *client, Song *song);
|
||||||
|
|
||||||
void
|
void
|
||||||
song_print_uri(Client *client, struct song *song);
|
song_print_uri(Client *client, Song *song);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "SongSave.hxx"
|
#include "SongSave.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "TagSave.hxx"
|
#include "TagSave.hxx"
|
||||||
#include "Directory.hxx"
|
#include "Directory.hxx"
|
||||||
#include "TextFile.hxx"
|
#include "TextFile.hxx"
|
||||||
|
@ -43,7 +43,7 @@ song_save_quark(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
song_save(FILE *fp, const struct song *song)
|
song_save(FILE *fp, const Song *song)
|
||||||
{
|
{
|
||||||
fprintf(fp, SONG_BEGIN "%s\n", song->uri);
|
fprintf(fp, SONG_BEGIN "%s\n", song->uri);
|
||||||
|
|
||||||
|
@ -59,13 +59,13 @@ song_save(FILE *fp, const struct song *song)
|
||||||
fprintf(fp, SONG_END "\n");
|
fprintf(fp, SONG_END "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
struct song *
|
Song *
|
||||||
song_load(TextFile &file, Directory *parent, const char *uri,
|
song_load(TextFile &file, Directory *parent, const char *uri,
|
||||||
GError **error_r)
|
GError **error_r)
|
||||||
{
|
{
|
||||||
struct song *song = parent != NULL
|
Song *song = parent != NULL
|
||||||
? song_file_new(uri, parent)
|
? Song::NewFile(uri, parent)
|
||||||
: song_remote_new(uri);
|
: Song::NewRemote(uri);
|
||||||
char *line, *colon;
|
char *line, *colon;
|
||||||
enum tag_type type;
|
enum tag_type type;
|
||||||
const char *value;
|
const char *value;
|
||||||
|
@ -76,7 +76,7 @@ song_load(TextFile &file, Directory *parent, const char *uri,
|
||||||
if (colon == NULL || colon == line) {
|
if (colon == NULL || colon == line) {
|
||||||
if (song->tag != NULL)
|
if (song->tag != NULL)
|
||||||
tag_end_add(song->tag);
|
tag_end_add(song->tag);
|
||||||
song_free(song);
|
song->Free();
|
||||||
|
|
||||||
g_set_error(error_r, song_save_quark(), 0,
|
g_set_error(error_r, song_save_quark(), 0,
|
||||||
"unknown line in db: %s", line);
|
"unknown line in db: %s", line);
|
||||||
|
@ -118,7 +118,7 @@ song_load(TextFile &file, Directory *parent, const char *uri,
|
||||||
} else {
|
} else {
|
||||||
if (song->tag != NULL)
|
if (song->tag != NULL)
|
||||||
tag_end_add(song->tag);
|
tag_end_add(song->tag);
|
||||||
song_free(song);
|
song->Free();
|
||||||
|
|
||||||
g_set_error(error_r, song_save_quark(), 0,
|
g_set_error(error_r, song_save_quark(), 0,
|
||||||
"unknown line in db: %s", line);
|
"unknown line in db: %s", line);
|
||||||
|
|
|
@ -26,12 +26,12 @@
|
||||||
|
|
||||||
#define SONG_BEGIN "song_begin: "
|
#define SONG_BEGIN "song_begin: "
|
||||||
|
|
||||||
struct song;
|
struct Song;
|
||||||
struct Directory;
|
struct Directory;
|
||||||
class TextFile;
|
class TextFile;
|
||||||
|
|
||||||
void
|
void
|
||||||
song_save(FILE *fp, const struct song *song);
|
song_save(FILE *fp, const Song *song);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads a song from the input file. Reading stops after the
|
* Loads a song from the input file. Reading stops after the
|
||||||
|
@ -41,7 +41,7 @@ song_save(FILE *fp, const struct song *song);
|
||||||
* ignore errors
|
* ignore errors
|
||||||
* @return true on success, false on error
|
* @return true on success, false on error
|
||||||
*/
|
*/
|
||||||
struct song *
|
Song *
|
||||||
song_load(TextFile &file, Directory *parent, const char *uri,
|
song_load(TextFile &file, Directory *parent, const char *uri,
|
||||||
GError **error_r);
|
GError **error_r);
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "SongSort.hxx"
|
#include "SongSort.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "util/list.h"
|
#include "util/list.h"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
|
|
||||||
|
@ -94,8 +94,8 @@ compare_tag_item(const struct tag *a, const struct tag *b, enum tag_type type)
|
||||||
static int
|
static int
|
||||||
song_cmp(G_GNUC_UNUSED void *priv, struct list_head *_a, struct list_head *_b)
|
song_cmp(G_GNUC_UNUSED void *priv, struct list_head *_a, struct list_head *_b)
|
||||||
{
|
{
|
||||||
const struct song *a = (const struct song *)_a;
|
const Song *a = (const Song *)_a;
|
||||||
const struct song *b = (const struct song *)_b;
|
const Song *b = (const Song *)_b;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* first sort by album */
|
/* first sort by album */
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "SongSticker.hxx"
|
#include "SongSticker.hxx"
|
||||||
#include "StickerDatabase.hxx"
|
#include "StickerDatabase.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "Directory.hxx"
|
#include "Directory.hxx"
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
@ -29,80 +29,66 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
char *
|
char *
|
||||||
sticker_song_get_value(const struct song *song, const char *name)
|
sticker_song_get_value(const Song *song, const char *name)
|
||||||
{
|
{
|
||||||
char *uri, *value;
|
|
||||||
|
|
||||||
assert(song != NULL);
|
assert(song != NULL);
|
||||||
assert(song_in_database(song));
|
assert(song->IsInDatabase());
|
||||||
|
|
||||||
uri = song_get_uri(song);
|
char *uri = song->GetURI();
|
||||||
value = sticker_load_value("song", uri, name);
|
char *value = sticker_load_value("song", uri, name);
|
||||||
g_free(uri);
|
g_free(uri);
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
sticker_song_set_value(const struct song *song,
|
sticker_song_set_value(const Song *song,
|
||||||
const char *name, const char *value)
|
const char *name, const char *value)
|
||||||
{
|
{
|
||||||
char *uri;
|
|
||||||
bool ret;
|
|
||||||
|
|
||||||
assert(song != NULL);
|
assert(song != NULL);
|
||||||
assert(song_in_database(song));
|
assert(song->IsInDatabase());
|
||||||
|
|
||||||
uri = song_get_uri(song);
|
char *uri = song->GetURI();
|
||||||
ret = sticker_store_value("song", uri, name, value);
|
bool ret = sticker_store_value("song", uri, name, value);
|
||||||
g_free(uri);
|
g_free(uri);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
sticker_song_delete(const struct song *song)
|
sticker_song_delete(const Song *song)
|
||||||
{
|
{
|
||||||
char *uri;
|
|
||||||
bool ret;
|
|
||||||
|
|
||||||
assert(song != NULL);
|
assert(song != NULL);
|
||||||
assert(song_in_database(song));
|
assert(song->IsInDatabase());
|
||||||
|
|
||||||
uri = song_get_uri(song);
|
char *uri = song->GetURI();
|
||||||
ret = sticker_delete("song", uri);
|
bool ret = sticker_delete("song", uri);
|
||||||
g_free(uri);
|
g_free(uri);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
sticker_song_delete_value(const struct song *song, const char *name)
|
sticker_song_delete_value(const Song *song, const char *name)
|
||||||
{
|
{
|
||||||
char *uri;
|
|
||||||
bool success;
|
|
||||||
|
|
||||||
assert(song != NULL);
|
assert(song != NULL);
|
||||||
assert(song_in_database(song));
|
assert(song->IsInDatabase());
|
||||||
|
|
||||||
uri = song_get_uri(song);
|
char *uri = song->GetURI();
|
||||||
success = sticker_delete_value("song", uri, name);
|
bool success = sticker_delete_value("song", uri, name);
|
||||||
g_free(uri);
|
g_free(uri);
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sticker *
|
struct sticker *
|
||||||
sticker_song_get(const struct song *song)
|
sticker_song_get(const Song *song)
|
||||||
{
|
{
|
||||||
char *uri;
|
|
||||||
struct sticker *sticker;
|
|
||||||
|
|
||||||
assert(song != NULL);
|
assert(song != NULL);
|
||||||
assert(song_in_database(song));
|
assert(song->IsInDatabase());
|
||||||
|
|
||||||
uri = song_get_uri(song);
|
char *uri = song->GetURI();
|
||||||
sticker = sticker_load("song", uri);
|
struct sticker *sticker = sticker_load("song", uri);
|
||||||
g_free(uri);
|
g_free(uri);
|
||||||
|
|
||||||
return sticker;
|
return sticker;
|
||||||
|
@ -113,7 +99,7 @@ struct sticker_song_find_data {
|
||||||
const char *base_uri;
|
const char *base_uri;
|
||||||
size_t base_uri_length;
|
size_t base_uri_length;
|
||||||
|
|
||||||
void (*func)(struct song *song, const char *value,
|
void (*func)(Song *song, const char *value,
|
||||||
void *user_data);
|
void *user_data);
|
||||||
void *user_data;
|
void *user_data;
|
||||||
};
|
};
|
||||||
|
@ -128,14 +114,14 @@ sticker_song_find_cb(const char *uri, const char *value, void *user_data)
|
||||||
/* should not happen, ignore silently */
|
/* should not happen, ignore silently */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
song *song = data->directory->LookupSong(uri + data->base_uri_length);
|
Song *song = data->directory->LookupSong(uri + data->base_uri_length);
|
||||||
if (song != NULL)
|
if (song != NULL)
|
||||||
data->func(song, value, data->user_data);
|
data->func(song, value, data->user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
sticker_song_find(Directory *directory, const char *name,
|
sticker_song_find(Directory *directory, const char *name,
|
||||||
void (*func)(struct song *song, const char *value,
|
void (*func)(Song *song, const char *value,
|
||||||
void *user_data),
|
void *user_data),
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
#include "gerror.h"
|
#include "gerror.h"
|
||||||
|
|
||||||
struct song;
|
struct Song;
|
||||||
struct Directory;
|
struct Directory;
|
||||||
struct sticker;
|
struct sticker;
|
||||||
|
|
||||||
|
@ -31,28 +31,28 @@ struct sticker;
|
||||||
* free the return value with g_free().
|
* free the return value with g_free().
|
||||||
*/
|
*/
|
||||||
char *
|
char *
|
||||||
sticker_song_get_value(const struct song *song, const char *name);
|
sticker_song_get_value(const Song *song, const char *name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a sticker value in the specified song. Overwrites existing
|
* Sets a sticker value in the specified song. Overwrites existing
|
||||||
* values.
|
* values.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
sticker_song_set_value(const struct song *song,
|
sticker_song_set_value(const Song *song,
|
||||||
const char *name, const char *value);
|
const char *name, const char *value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes a sticker from the database. All values are deleted.
|
* Deletes a sticker from the database. All values are deleted.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
sticker_song_delete(const struct song *song);
|
sticker_song_delete(const Song *song);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes a sticker value. Does nothing if the sticker did not
|
* Deletes a sticker value. Does nothing if the sticker did not
|
||||||
* exist.
|
* exist.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
sticker_song_delete_value(const struct song *song, const char *name);
|
sticker_song_delete_value(const Song *song, const char *name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the sticker for the specified song.
|
* Loads the sticker for the specified song.
|
||||||
|
@ -61,7 +61,7 @@ sticker_song_delete_value(const struct song *song, const char *name);
|
||||||
* @return a sticker object, or NULL on error or if there is no sticker
|
* @return a sticker object, or NULL on error or if there is no sticker
|
||||||
*/
|
*/
|
||||||
struct sticker *
|
struct sticker *
|
||||||
sticker_song_get(const struct song *song);
|
sticker_song_get(const Song *song);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds stickers with the specified name below the specified
|
* Finds stickers with the specified name below the specified
|
||||||
|
@ -76,7 +76,7 @@ sticker_song_get(const struct song *song);
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
sticker_song_find(Directory *directory, const char *name,
|
sticker_song_find(Directory *directory, const char *name,
|
||||||
void (*func)(struct song *song, const char *value,
|
void (*func)(Song *song, const char *value,
|
||||||
void *user_data),
|
void *user_data),
|
||||||
void *user_data);
|
void *user_data);
|
||||||
|
|
||||||
|
|
|
@ -18,11 +18,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h" /* must be first for large file support */
|
#include "config.h" /* must be first for large file support */
|
||||||
|
#include "Song.hxx"
|
||||||
extern "C" {
|
|
||||||
#include "song.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "util/UriUtil.hxx"
|
#include "util/UriUtil.hxx"
|
||||||
#include "Directory.hxx"
|
#include "Directory.hxx"
|
||||||
#include "Mapper.hxx"
|
#include "Mapper.hxx"
|
||||||
|
@ -46,26 +42,26 @@ extern "C" {
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
struct song *
|
Song *
|
||||||
song_file_load(const char *path_utf8, Directory *parent)
|
Song::LoadFile(const char *path_utf8, Directory *parent)
|
||||||
{
|
{
|
||||||
struct song *song;
|
Song *song;
|
||||||
bool ret;
|
bool ret;
|
||||||
|
|
||||||
assert((parent == NULL) == g_path_is_absolute(path_utf8));
|
assert((parent == NULL) == g_path_is_absolute(path_utf8));
|
||||||
assert(!uri_has_scheme(path_utf8));
|
assert(!uri_has_scheme(path_utf8));
|
||||||
assert(strchr(path_utf8, '\n') == NULL);
|
assert(strchr(path_utf8, '\n') == NULL);
|
||||||
|
|
||||||
song = song_file_new(path_utf8, parent);
|
song = NewFile(path_utf8, parent);
|
||||||
|
|
||||||
//in archive ?
|
//in archive ?
|
||||||
if (parent != NULL && parent->device == DEVICE_INARCHIVE) {
|
if (parent != NULL && parent->device == DEVICE_INARCHIVE) {
|
||||||
ret = song_file_update_inarchive(song);
|
ret = song->UpdateFileInArchive();
|
||||||
} else {
|
} else {
|
||||||
ret = song_file_update(song);
|
ret = song->UpdateFile();
|
||||||
}
|
}
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
song_free(song);
|
song->Free();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,18 +80,18 @@ tag_scan_fallback(const char *path,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
song_file_update(struct song *song)
|
Song::UpdateFile()
|
||||||
{
|
{
|
||||||
const char *suffix;
|
const char *suffix;
|
||||||
const struct decoder_plugin *plugin;
|
const struct decoder_plugin *plugin;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
struct input_stream *is = NULL;
|
struct input_stream *is = NULL;
|
||||||
|
|
||||||
assert(song_is_file(song));
|
assert(IsFile());
|
||||||
|
|
||||||
/* check if there's a suffix and a plugin */
|
/* check if there's a suffix and a plugin */
|
||||||
|
|
||||||
suffix = uri_get_suffix(song->uri);
|
suffix = uri_get_suffix(uri);
|
||||||
if (suffix == NULL)
|
if (suffix == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -103,33 +99,33 @@ song_file_update(struct song *song)
|
||||||
if (plugin == NULL)
|
if (plugin == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const Path path_fs = map_song_fs(song);
|
const Path path_fs = map_song_fs(this);
|
||||||
if (path_fs.IsNull())
|
if (path_fs.IsNull())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (song->tag != NULL) {
|
if (tag != NULL) {
|
||||||
tag_free(song->tag);
|
tag_free(tag);
|
||||||
song->tag = NULL;
|
tag = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!StatFile(path_fs, st) || !S_ISREG(st.st_mode)) {
|
if (!StatFile(path_fs, st) || !S_ISREG(st.st_mode)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
song->mtime = st.st_mtime;
|
mtime = st.st_mtime;
|
||||||
|
|
||||||
Mutex mutex;
|
Mutex mutex;
|
||||||
Cond cond;
|
Cond cond;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
/* load file tag */
|
/* load file tag */
|
||||||
song->tag = tag_new();
|
tag = tag_new();
|
||||||
if (decoder_plugin_scan_file(plugin, path_fs.c_str(),
|
if (decoder_plugin_scan_file(plugin, path_fs.c_str(),
|
||||||
&full_tag_handler, song->tag))
|
&full_tag_handler, tag))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
tag_free(song->tag);
|
tag_free(tag);
|
||||||
song->tag = NULL;
|
tag = nullptr;
|
||||||
|
|
||||||
/* fall back to stream tag */
|
/* fall back to stream tag */
|
||||||
if (plugin->scan_stream != NULL) {
|
if (plugin->scan_stream != NULL) {
|
||||||
|
@ -143,14 +139,14 @@ song_file_update(struct song *song)
|
||||||
|
|
||||||
/* now try the stream_tag() method */
|
/* now try the stream_tag() method */
|
||||||
if (is != NULL) {
|
if (is != NULL) {
|
||||||
song->tag = tag_new();
|
tag = tag_new();
|
||||||
if (decoder_plugin_scan_stream(plugin, is,
|
if (decoder_plugin_scan_stream(plugin, is,
|
||||||
&full_tag_handler,
|
&full_tag_handler,
|
||||||
song->tag))
|
tag))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
tag_free(song->tag);
|
tag_free(tag);
|
||||||
song->tag = NULL;
|
tag = nullptr;
|
||||||
|
|
||||||
input_stream_lock_seek(is, 0, SEEK_SET, NULL);
|
input_stream_lock_seek(is, 0, SEEK_SET, NULL);
|
||||||
}
|
}
|
||||||
|
@ -162,24 +158,23 @@ song_file_update(struct song *song)
|
||||||
if (is != NULL)
|
if (is != NULL)
|
||||||
input_stream_close(is);
|
input_stream_close(is);
|
||||||
|
|
||||||
if (song->tag != NULL && tag_is_empty(song->tag))
|
if (tag != nullptr && tag_is_empty(tag))
|
||||||
tag_scan_fallback(path_fs.c_str(), &full_tag_handler,
|
tag_scan_fallback(path_fs.c_str(), &full_tag_handler, tag);
|
||||||
song->tag);
|
|
||||||
|
|
||||||
return song->tag != NULL;
|
return tag != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
song_file_update_inarchive(struct song *song)
|
Song::UpdateFileInArchive()
|
||||||
{
|
{
|
||||||
const char *suffix;
|
const char *suffix;
|
||||||
const struct decoder_plugin *plugin;
|
const struct decoder_plugin *plugin;
|
||||||
|
|
||||||
assert(song_is_file(song));
|
assert(IsFile());
|
||||||
|
|
||||||
/* check if there's a suffix and a plugin */
|
/* check if there's a suffix and a plugin */
|
||||||
|
|
||||||
suffix = uri_get_suffix(song->uri);
|
suffix = uri_get_suffix(uri);
|
||||||
if (suffix == NULL)
|
if (suffix == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -187,13 +182,13 @@ song_file_update_inarchive(struct song *song)
|
||||||
if (plugin == NULL)
|
if (plugin == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (song->tag != NULL)
|
if (tag != nullptr)
|
||||||
tag_free(song->tag);
|
tag_free(tag);
|
||||||
|
|
||||||
//accept every file that has music suffix
|
//accept every file that has music suffix
|
||||||
//because we don't support tag reading through
|
//because we don't support tag reading through
|
||||||
//input streams
|
//input streams
|
||||||
song->tag = tag_new();
|
tag = tag_new();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ struct sticker_song_find_data {
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sticker_song_find_print_cb(struct song *song, const char *value,
|
sticker_song_find_print_cb(Song *song, const char *value,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
struct sticker_song_find_data *data =
|
struct sticker_song_find_data *data =
|
||||||
|
@ -58,7 +58,7 @@ handle_sticker_song(Client *client, int argc, char *argv[])
|
||||||
|
|
||||||
/* get song song_id key */
|
/* get song song_id key */
|
||||||
if (argc == 5 && strcmp(argv[1], "get") == 0) {
|
if (argc == 5 && strcmp(argv[1], "get") == 0) {
|
||||||
song *song = db->GetSong(argv[3], &error);
|
Song *song = db->GetSong(argv[3], &error);
|
||||||
if (song == nullptr)
|
if (song == nullptr)
|
||||||
return print_error(client, error);
|
return print_error(client, error);
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ handle_sticker_song(Client *client, int argc, char *argv[])
|
||||||
return COMMAND_RETURN_OK;
|
return COMMAND_RETURN_OK;
|
||||||
/* list song song_id */
|
/* list song song_id */
|
||||||
} else if (argc == 4 && strcmp(argv[1], "list") == 0) {
|
} else if (argc == 4 && strcmp(argv[1], "list") == 0) {
|
||||||
song *song = db->GetSong(argv[3], &error);
|
Song *song = db->GetSong(argv[3], &error);
|
||||||
if (song == nullptr)
|
if (song == nullptr)
|
||||||
return print_error(client, error);
|
return print_error(client, error);
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ handle_sticker_song(Client *client, int argc, char *argv[])
|
||||||
return COMMAND_RETURN_OK;
|
return COMMAND_RETURN_OK;
|
||||||
/* set song song_id id key */
|
/* set song song_id id key */
|
||||||
} else if (argc == 6 && strcmp(argv[1], "set") == 0) {
|
} else if (argc == 6 && strcmp(argv[1], "set") == 0) {
|
||||||
song *song = db->GetSong(argv[3], &error);
|
Song *song = db->GetSong(argv[3], &error);
|
||||||
if (song == nullptr)
|
if (song == nullptr)
|
||||||
return print_error(client, error);
|
return print_error(client, error);
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ handle_sticker_song(Client *client, int argc, char *argv[])
|
||||||
/* delete song song_id [key] */
|
/* delete song song_id [key] */
|
||||||
} else if ((argc == 4 || argc == 5) &&
|
} else if ((argc == 4 || argc == 5) &&
|
||||||
strcmp(argv[1], "delete") == 0) {
|
strcmp(argv[1], "delete") == 0) {
|
||||||
song *song = db->GetSong(argv[3], &error);
|
Song *song = db->GetSong(argv[3], &error);
|
||||||
if (song == nullptr)
|
if (song == nullptr)
|
||||||
return print_error(client, error);
|
return print_error(client, error);
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include "TagInternal.hxx"
|
#include "TagInternal.hxx"
|
||||||
#include "TagPool.hxx"
|
#include "TagPool.hxx"
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "mpd_error.h"
|
#include "mpd_error.h"
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include "TagPrint.hxx"
|
#include "TagPrint.hxx"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
#include "TagInternal.hxx"
|
#include "TagInternal.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "Client.hxx"
|
#include "Client.hxx"
|
||||||
|
|
||||||
void tag_print_types(Client *client)
|
void tag_print_types(Client *client)
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include "TagSave.hxx"
|
#include "TagSave.hxx"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
#include "TagInternal.hxx"
|
#include "TagInternal.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
|
|
||||||
void tag_save(FILE *file, const struct tag *tag)
|
void tag_save(FILE *file, const struct tag *tag)
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include "UpdateInternal.hxx"
|
#include "UpdateInternal.hxx"
|
||||||
#include "DatabaseLock.hxx"
|
#include "DatabaseLock.hxx"
|
||||||
#include "Directory.hxx"
|
#include "Directory.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "Mapper.hxx"
|
#include "Mapper.hxx"
|
||||||
#include "fs/Path.hxx"
|
#include "fs/Path.hxx"
|
||||||
#include "ArchiveList.hxx"
|
#include "ArchiveList.hxx"
|
||||||
|
@ -58,10 +58,10 @@ update_archive_tree(Directory *directory, const char *name)
|
||||||
|
|
||||||
//add file
|
//add file
|
||||||
db_lock();
|
db_lock();
|
||||||
struct song *song = directory->FindSong(name);
|
Song *song = directory->FindSong(name);
|
||||||
db_unlock();
|
db_unlock();
|
||||||
if (song == NULL) {
|
if (song == NULL) {
|
||||||
song = song_file_load(name, directory);
|
song = Song::LoadFile(name, directory);
|
||||||
if (song != NULL) {
|
if (song != NULL) {
|
||||||
db_lock();
|
db_lock();
|
||||||
directory->AddSong(song);
|
directory->AddSong(song);
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
#include "UpdateDatabase.hxx"
|
#include "UpdateDatabase.hxx"
|
||||||
#include "DatabaseLock.hxx"
|
#include "DatabaseLock.hxx"
|
||||||
#include "Directory.hxx"
|
#include "Directory.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "DecoderPlugin.hxx"
|
#include "DecoderPlugin.hxx"
|
||||||
#include "Mapper.hxx"
|
#include "Mapper.hxx"
|
||||||
#include "fs/Path.hxx"
|
#include "fs/Path.hxx"
|
||||||
|
@ -89,7 +89,7 @@ update_container_file(Directory *directory,
|
||||||
char *vtrack;
|
char *vtrack;
|
||||||
unsigned int tnum = 0;
|
unsigned int tnum = 0;
|
||||||
while ((vtrack = plugin->container_scan(pathname.c_str(), ++tnum)) != NULL) {
|
while ((vtrack = plugin->container_scan(pathname.c_str(), ++tnum)) != NULL) {
|
||||||
struct song *song = song_file_new(vtrack, contdir);
|
Song *song = Song::NewFile(vtrack, contdir);
|
||||||
|
|
||||||
// shouldn't be necessary but it's there..
|
// shouldn't be necessary but it's there..
|
||||||
song->mtime = st->st_mtime;
|
song->mtime = st->st_mtime;
|
||||||
|
|
|
@ -22,14 +22,14 @@
|
||||||
#include "UpdateRemove.hxx"
|
#include "UpdateRemove.hxx"
|
||||||
#include "PlaylistVector.hxx"
|
#include "PlaylistVector.hxx"
|
||||||
#include "Directory.hxx"
|
#include "Directory.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "DatabaseLock.hxx"
|
#include "DatabaseLock.hxx"
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
void
|
void
|
||||||
delete_song(Directory *dir, struct song *del)
|
delete_song(Directory *dir, Song *del)
|
||||||
{
|
{
|
||||||
assert(del->parent == dir);
|
assert(del->parent == dir);
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ delete_song(Directory *dir, struct song *del)
|
||||||
update_remove_song(del);
|
update_remove_song(del);
|
||||||
|
|
||||||
/* finally, all possible references gone, free it */
|
/* finally, all possible references gone, free it */
|
||||||
song_free(del);
|
del->Free();
|
||||||
|
|
||||||
db_lock();
|
db_lock();
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ clear_directory(Directory *directory)
|
||||||
directory_for_each_child_safe(child, n, directory)
|
directory_for_each_child_safe(child, n, directory)
|
||||||
delete_directory(child);
|
delete_directory(child);
|
||||||
|
|
||||||
struct song *song, *ns;
|
Song *song, *ns;
|
||||||
directory_for_each_song_safe(song, ns, directory) {
|
directory_for_each_song_safe(song, ns, directory) {
|
||||||
assert(song->parent == directory);
|
assert(song->parent == directory);
|
||||||
delete_song(directory, song);
|
delete_song(directory, song);
|
||||||
|
@ -90,7 +90,7 @@ delete_name_in(Directory *parent, const char *name)
|
||||||
modified = true;
|
modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct song *song = parent->FindSong(name);
|
Song *song = parent->FindSong(name);
|
||||||
if (song != NULL) {
|
if (song != NULL) {
|
||||||
delete_song(parent, song);
|
delete_song(parent, song);
|
||||||
modified = true;
|
modified = true;
|
||||||
|
|
|
@ -23,13 +23,13 @@
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
|
|
||||||
struct Directory;
|
struct Directory;
|
||||||
struct song;
|
struct Song;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Caller must lock the #db_mutex.
|
* Caller must lock the #db_mutex.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
delete_song(Directory *parent, struct song *song);
|
delete_song(Directory *parent, Song *song);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively free a directory and all its contents.
|
* Recursively free a directory and all its contents.
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
#include "thread/Mutex.hxx"
|
#include "thread/Mutex.hxx"
|
||||||
#include "thread/Cond.hxx"
|
#include "thread/Cond.hxx"
|
||||||
|
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "Main.hxx"
|
#include "Main.hxx"
|
||||||
#include "Instance.hxx"
|
#include "Instance.hxx"
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
static const struct song *removed_song;
|
static const Song *removed_song;
|
||||||
|
|
||||||
static Mutex remove_mutex;
|
static Mutex remove_mutex;
|
||||||
static Cond remove_cond;
|
static Cond remove_cond;
|
||||||
|
@ -53,7 +53,7 @@ song_remove_event(void)
|
||||||
|
|
||||||
assert(removed_song != NULL);
|
assert(removed_song != NULL);
|
||||||
|
|
||||||
uri = song_get_uri(removed_song);
|
uri = removed_song->GetURI();
|
||||||
g_message("removing %s", uri);
|
g_message("removing %s", uri);
|
||||||
g_free(uri);
|
g_free(uri);
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ update_remove_global_init(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
update_remove_song(const struct song *song)
|
update_remove_song(const Song *song)
|
||||||
{
|
{
|
||||||
assert(removed_song == NULL);
|
assert(removed_song == NULL);
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
|
|
||||||
struct song;
|
struct Song;
|
||||||
|
|
||||||
void
|
void
|
||||||
update_remove_global_init(void);
|
update_remove_global_init(void);
|
||||||
|
@ -33,6 +33,6 @@ update_remove_global_init(void);
|
||||||
* serialized access is implemented to avoid excessive locking.
|
* serialized access is implemented to avoid excessive locking.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
update_remove_song(const struct song *song);
|
update_remove_song(const Song *song);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
#include "UpdateContainer.hxx"
|
#include "UpdateContainer.hxx"
|
||||||
#include "DatabaseLock.hxx"
|
#include "DatabaseLock.hxx"
|
||||||
#include "Directory.hxx"
|
#include "Directory.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "DecoderPlugin.hxx"
|
#include "DecoderPlugin.hxx"
|
||||||
#include "DecoderList.hxx"
|
#include "DecoderList.hxx"
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ update_song_file2(Directory *directory,
|
||||||
const struct decoder_plugin *plugin)
|
const struct decoder_plugin *plugin)
|
||||||
{
|
{
|
||||||
db_lock();
|
db_lock();
|
||||||
struct song *song = directory->FindSong(name);
|
Song *song = directory->FindSong(name);
|
||||||
db_unlock();
|
db_unlock();
|
||||||
|
|
||||||
if (!directory_child_access(directory, name, R_OK)) {
|
if (!directory_child_access(directory, name, R_OK)) {
|
||||||
|
@ -68,7 +68,7 @@ update_song_file2(Directory *directory,
|
||||||
|
|
||||||
if (song == NULL) {
|
if (song == NULL) {
|
||||||
g_debug("reading %s/%s", directory->GetPath(), name);
|
g_debug("reading %s/%s", directory->GetPath(), name);
|
||||||
song = song_file_load(name, directory);
|
song = Song::LoadFile(name, directory);
|
||||||
if (song == NULL) {
|
if (song == NULL) {
|
||||||
g_debug("ignoring unrecognized file %s/%s",
|
g_debug("ignoring unrecognized file %s/%s",
|
||||||
directory->GetPath(), name);
|
directory->GetPath(), name);
|
||||||
|
@ -85,7 +85,7 @@ update_song_file2(Directory *directory,
|
||||||
} else if (st->st_mtime != song->mtime || walk_discard) {
|
} else if (st->st_mtime != song->mtime || walk_discard) {
|
||||||
g_message("updating %s/%s",
|
g_message("updating %s/%s",
|
||||||
directory->GetPath(), name);
|
directory->GetPath(), name);
|
||||||
if (!song_file_update(song)) {
|
if (!song->UpdateFile()) {
|
||||||
g_debug("deleting unrecognized file %s/%s",
|
g_debug("deleting unrecognized file %s/%s",
|
||||||
directory->GetPath(), name);
|
directory->GetPath(), name);
|
||||||
db_lock();
|
db_lock();
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#include "DatabaseLock.hxx"
|
#include "DatabaseLock.hxx"
|
||||||
#include "DatabaseSimple.hxx"
|
#include "DatabaseSimple.hxx"
|
||||||
#include "Directory.hxx"
|
#include "Directory.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "PlaylistVector.hxx"
|
#include "PlaylistVector.hxx"
|
||||||
#include "PlaylistRegistry.hxx"
|
#include "PlaylistRegistry.hxx"
|
||||||
#include "Mapper.hxx"
|
#include "Mapper.hxx"
|
||||||
|
@ -109,7 +109,7 @@ remove_excluded_from_directory(Directory *directory,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct song *song, *ns;
|
Song *song, *ns;
|
||||||
directory_for_each_song_safe(song, ns, directory) {
|
directory_for_each_song_safe(song, ns, directory) {
|
||||||
assert(song->parent == directory);
|
assert(song->parent == directory);
|
||||||
|
|
||||||
|
@ -138,7 +138,7 @@ purge_deleted_from_directory(Directory *directory)
|
||||||
modified = true;
|
modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct song *song, *ns;
|
Song *song, *ns;
|
||||||
directory_for_each_song_safe(song, ns, directory) {
|
directory_for_each_song_safe(song, ns, directory) {
|
||||||
const Path path = map_song_fs(song);
|
const Path path = map_song_fs(song);
|
||||||
if (path.IsNull() || !FileExists(path)) {
|
if (path.IsNull() || !FileExists(path)) {
|
||||||
|
@ -414,7 +414,7 @@ directory_make_child_checked(Directory *parent, const char *name_utf8)
|
||||||
/* if we're adding directory paths, make sure to delete filenames
|
/* if we're adding directory paths, make sure to delete filenames
|
||||||
with potentially the same name */
|
with potentially the same name */
|
||||||
db_lock();
|
db_lock();
|
||||||
struct song *conflicting = parent->FindSong(name_utf8);
|
Song *conflicting = parent->FindSong(name_utf8);
|
||||||
if (conflicting)
|
if (conflicting)
|
||||||
delete_song(parent, conflicting);
|
delete_song(parent, conflicting);
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "CueParser.hxx"
|
#include "CueParser.hxx"
|
||||||
#include "util/StringUtil.hxx"
|
#include "util/StringUtil.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
@ -42,13 +42,13 @@ CueParser::~CueParser()
|
||||||
g_free(filename);
|
g_free(filename);
|
||||||
|
|
||||||
if (current != nullptr)
|
if (current != nullptr)
|
||||||
song_free(current);
|
current->Free();
|
||||||
|
|
||||||
if (previous != nullptr)
|
if (previous != nullptr)
|
||||||
song_free(previous);
|
previous->Free();
|
||||||
|
|
||||||
if (finished != nullptr)
|
if (finished != nullptr)
|
||||||
song_free(finished);
|
finished->Free();
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
|
@ -250,7 +250,7 @@ CueParser::Feed2(char *p)
|
||||||
}
|
}
|
||||||
|
|
||||||
state = TRACK;
|
state = TRACK;
|
||||||
current = song_remote_new(filename);
|
current = Song::NewRemote(filename);
|
||||||
assert(current->tag == nullptr);
|
assert(current->tag == nullptr);
|
||||||
current->tag = tag_dup(tag);
|
current->tag = tag_dup(tag);
|
||||||
tag_add_item(current->tag, TAG_TRACK, nr);
|
tag_add_item(current->tag, TAG_TRACK, nr);
|
||||||
|
@ -304,7 +304,7 @@ CueParser::Finish()
|
||||||
end = true;
|
end = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct song *
|
Song *
|
||||||
CueParser::Get()
|
CueParser::Get()
|
||||||
{
|
{
|
||||||
if (finished == nullptr && end) {
|
if (finished == nullptr && end) {
|
||||||
|
@ -316,7 +316,7 @@ CueParser::Get()
|
||||||
previous = nullptr;
|
previous = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct song *song = finished;
|
Song *song = finished;
|
||||||
finished = nullptr;
|
finished = nullptr;
|
||||||
return song;
|
return song;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
#include "gcc.h"
|
#include "gcc.h"
|
||||||
|
|
||||||
|
struct Song;
|
||||||
|
|
||||||
class CueParser {
|
class CueParser {
|
||||||
enum {
|
enum {
|
||||||
/**
|
/**
|
||||||
|
@ -58,19 +60,19 @@ class CueParser {
|
||||||
/**
|
/**
|
||||||
* The song currently being edited.
|
* The song currently being edited.
|
||||||
*/
|
*/
|
||||||
struct song *current;
|
Song *current;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The previous song. It is remembered because its end_time
|
* The previous song. It is remembered because its end_time
|
||||||
* will be set to the current song's start time.
|
* will be set to the current song's start time.
|
||||||
*/
|
*/
|
||||||
struct song *previous;
|
Song *previous;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A song that is completely finished and can be returned to
|
* A song that is completely finished and can be returned to
|
||||||
* the caller via cue_parser_get().
|
* the caller via cue_parser_get().
|
||||||
*/
|
*/
|
||||||
struct song *finished;
|
Song *finished;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set to true after previous.end_time has been updated to the
|
* Set to true after previous.end_time has been updated to the
|
||||||
|
@ -109,7 +111,7 @@ public:
|
||||||
* @return a song object that must be freed by the caller, or NULL if
|
* @return a song object that must be freed by the caller, or NULL if
|
||||||
* no song was finished at this time
|
* no song was finished at this time
|
||||||
*/
|
*/
|
||||||
struct song *Get();
|
Song *Get();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
gcc_pure
|
gcc_pure
|
||||||
|
|
|
@ -23,12 +23,12 @@
|
||||||
#include "DatabaseSelection.hxx"
|
#include "DatabaseSelection.hxx"
|
||||||
#include "PlaylistVector.hxx"
|
#include "PlaylistVector.hxx"
|
||||||
#include "Directory.hxx"
|
#include "Directory.hxx"
|
||||||
|
#include "Song.hxx"
|
||||||
#include "gcc.h"
|
#include "gcc.h"
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "db_error.h"
|
#include "db_error.h"
|
||||||
#include "song.h"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef MPD_DIRECTORY_H
|
#undef MPD_DIRECTORY_H
|
||||||
|
@ -52,9 +52,9 @@ public:
|
||||||
|
|
||||||
virtual bool Open(GError **error_r) override;
|
virtual bool Open(GError **error_r) override;
|
||||||
virtual void Close() override;
|
virtual void Close() override;
|
||||||
virtual struct song *GetSong(const char *uri_utf8,
|
virtual Song *GetSong(const char *uri_utf8,
|
||||||
GError **error_r) const override;
|
GError **error_r) const override;
|
||||||
virtual void ReturnSong(struct song *song) const;
|
virtual void ReturnSong(Song *song) const;
|
||||||
|
|
||||||
virtual bool Visit(const DatabaseSelection &selection,
|
virtual bool Visit(const DatabaseSelection &selection,
|
||||||
VisitDirectory visit_directory,
|
VisitDirectory visit_directory,
|
||||||
|
@ -181,10 +181,10 @@ ProxyDatabase::Close()
|
||||||
mpd_connection_free(connection);
|
mpd_connection_free(connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
static song *
|
static Song *
|
||||||
Convert(const struct mpd_song *song);
|
Convert(const struct mpd_song *song);
|
||||||
|
|
||||||
struct song *
|
Song *
|
||||||
ProxyDatabase::GetSong(const char *uri, GError **error_r) const
|
ProxyDatabase::GetSong(const char *uri, GError **error_r) const
|
||||||
{
|
{
|
||||||
// TODO: implement
|
// TODO: implement
|
||||||
|
@ -196,13 +196,13 @@ ProxyDatabase::GetSong(const char *uri, GError **error_r) const
|
||||||
}
|
}
|
||||||
|
|
||||||
struct mpd_song *song = mpd_recv_song(connection);
|
struct mpd_song *song = mpd_recv_song(connection);
|
||||||
struct song *song2 = song != nullptr
|
Song *song2 = song != nullptr
|
||||||
? Convert(song)
|
? Convert(song)
|
||||||
: nullptr;
|
: nullptr;
|
||||||
mpd_song_free(song);
|
mpd_song_free(song);
|
||||||
if (!mpd_response_finish(connection)) {
|
if (!mpd_response_finish(connection)) {
|
||||||
if (song2 != nullptr)
|
if (song2 != nullptr)
|
||||||
song_free(song2);
|
song2->Free();
|
||||||
|
|
||||||
CheckError(connection, error_r);
|
CheckError(connection, error_r);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -216,13 +216,13 @@ ProxyDatabase::GetSong(const char *uri, GError **error_r) const
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ProxyDatabase::ReturnSong(struct song *song) const
|
ProxyDatabase::ReturnSong(Song *song) const
|
||||||
{
|
{
|
||||||
assert(song != nullptr);
|
assert(song != nullptr);
|
||||||
assert(song_in_database(song));
|
assert(song->IsInDatabase());
|
||||||
assert(song_is_detached(song));
|
assert(song->IsDetached());
|
||||||
|
|
||||||
song_free(song);
|
song->Free();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -268,10 +268,10 @@ Copy(struct tag *tag, enum tag_type d_tag,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static song *
|
static Song *
|
||||||
Convert(const struct mpd_song *song)
|
Convert(const struct mpd_song *song)
|
||||||
{
|
{
|
||||||
struct song *s = song_detached_new(mpd_song_get_uri(song));
|
Song *s = Song::NewDetached(mpd_song_get_uri(song));
|
||||||
|
|
||||||
s->mtime = mpd_song_get_last_modified(song);
|
s->mtime = mpd_song_get_last_modified(song);
|
||||||
s->start_ms = mpd_song_get_start(song) * 1000;
|
s->start_ms = mpd_song_get_start(song) * 1000;
|
||||||
|
@ -297,9 +297,9 @@ Visit(const struct mpd_song *song,
|
||||||
if (!visit_song)
|
if (!visit_song)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
struct song *s = Convert(song);
|
Song *s = Convert(song);
|
||||||
bool success = visit_song(*s, error_r);
|
bool success = visit_song(*s, error_r);
|
||||||
song_free(s);
|
s->Free();
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
|
@ -211,13 +211,13 @@ SimpleDatabase::Close()
|
||||||
root->Free();
|
root->Free();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct song *
|
Song *
|
||||||
SimpleDatabase::GetSong(const char *uri, GError **error_r) const
|
SimpleDatabase::GetSong(const char *uri, GError **error_r) const
|
||||||
{
|
{
|
||||||
assert(root != NULL);
|
assert(root != NULL);
|
||||||
|
|
||||||
db_lock();
|
db_lock();
|
||||||
song *song = root->LookupSong(uri);
|
Song *song = root->LookupSong(uri);
|
||||||
db_unlock();
|
db_unlock();
|
||||||
if (song == NULL)
|
if (song == NULL)
|
||||||
g_set_error(error_r, db_quark(), DB_NOT_FOUND,
|
g_set_error(error_r, db_quark(), DB_NOT_FOUND,
|
||||||
|
@ -231,7 +231,7 @@ SimpleDatabase::GetSong(const char *uri, GError **error_r) const
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SimpleDatabase::ReturnSong(gcc_unused struct song *song) const
|
SimpleDatabase::ReturnSong(gcc_unused Song *song) const
|
||||||
{
|
{
|
||||||
assert(song != nullptr);
|
assert(song != nullptr);
|
||||||
|
|
||||||
|
@ -264,7 +264,7 @@ SimpleDatabase::Visit(const DatabaseSelection &selection,
|
||||||
const Directory *directory = root->LookupDirectory(selection.uri);
|
const Directory *directory = root->LookupDirectory(selection.uri);
|
||||||
if (directory == NULL) {
|
if (directory == NULL) {
|
||||||
if (visit_song) {
|
if (visit_song) {
|
||||||
song *song = root->LookupSong(selection.uri);
|
Song *song = root->LookupSong(selection.uri);
|
||||||
if (song != nullptr)
|
if (song != nullptr)
|
||||||
return !selection.Match(*song) ||
|
return !selection.Match(*song) ||
|
||||||
visit_song(*song, error_r);
|
visit_song(*song, error_r);
|
||||||
|
|
|
@ -66,9 +66,9 @@ public:
|
||||||
virtual bool Open(GError **error_r) override;
|
virtual bool Open(GError **error_r) override;
|
||||||
virtual void Close() override;
|
virtual void Close() override;
|
||||||
|
|
||||||
virtual struct song *GetSong(const char *uri_utf8,
|
virtual Song *GetSong(const char *uri_utf8,
|
||||||
GError **error_r) const override;
|
GError **error_r) const override;
|
||||||
virtual void ReturnSong(struct song *song) const;
|
virtual void ReturnSong(Song *song) const;
|
||||||
|
|
||||||
virtual bool Visit(const DatabaseSelection &selection,
|
virtual bool Visit(const DatabaseSelection &selection,
|
||||||
VisitDirectory visit_directory,
|
VisitDirectory visit_directory,
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include "AsxPlaylistPlugin.hxx"
|
#include "AsxPlaylistPlugin.hxx"
|
||||||
#include "MemoryPlaylistProvider.hxx"
|
#include "MemoryPlaylistProvider.hxx"
|
||||||
#include "input_stream.h"
|
#include "input_stream.h"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
@ -60,7 +60,7 @@ struct AsxParser {
|
||||||
* The current song. It is allocated after the "location"
|
* The current song. It is allocated after the "location"
|
||||||
* element.
|
* element.
|
||||||
*/
|
*/
|
||||||
struct song *song;
|
Song *song;
|
||||||
|
|
||||||
AsxParser()
|
AsxParser()
|
||||||
:state(ROOT) {}
|
:state(ROOT) {}
|
||||||
|
@ -91,7 +91,7 @@ asx_start_element(G_GNUC_UNUSED GMarkupParseContext *context,
|
||||||
case AsxParser::ROOT:
|
case AsxParser::ROOT:
|
||||||
if (g_ascii_strcasecmp(element_name, "entry") == 0) {
|
if (g_ascii_strcasecmp(element_name, "entry") == 0) {
|
||||||
parser->state = AsxParser::ENTRY;
|
parser->state = AsxParser::ENTRY;
|
||||||
parser->song = song_remote_new("asx:");
|
parser->song = Song::NewRemote("asx:");
|
||||||
parser->tag = TAG_NUM_OF_ITEM_TYPES;
|
parser->tag = TAG_NUM_OF_ITEM_TYPES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,12 +108,12 @@ asx_start_element(G_GNUC_UNUSED GMarkupParseContext *context,
|
||||||
replace the existing song's URI,
|
replace the existing song's URI,
|
||||||
because that attribute is
|
because that attribute is
|
||||||
immutable */
|
immutable */
|
||||||
struct song *song = song_remote_new(href);
|
Song *song = Song::NewRemote(href);
|
||||||
|
|
||||||
if (parser->song != NULL) {
|
if (parser->song != NULL) {
|
||||||
song->tag = parser->song->tag;
|
song->tag = parser->song->tag;
|
||||||
parser->song->tag = NULL;
|
parser->song->tag = NULL;
|
||||||
song_free(parser->song);
|
parser->song->Free();
|
||||||
}
|
}
|
||||||
|
|
||||||
parser->song = song;
|
parser->song = song;
|
||||||
|
@ -145,7 +145,7 @@ asx_end_element(G_GNUC_UNUSED GMarkupParseContext *context,
|
||||||
if (strcmp(parser->song->uri, "asx:") != 0)
|
if (strcmp(parser->song->uri, "asx:") != 0)
|
||||||
parser->songs.emplace_front(parser->song);
|
parser->songs.emplace_front(parser->song);
|
||||||
else
|
else
|
||||||
song_free(parser->song);
|
parser->song->Free();
|
||||||
|
|
||||||
parser->state = AsxParser::ROOT;
|
parser->state = AsxParser::ROOT;
|
||||||
} else
|
} else
|
||||||
|
@ -192,7 +192,7 @@ asx_parser_destroy(gpointer data)
|
||||||
AsxParser *parser = (AsxParser *)data;
|
AsxParser *parser = (AsxParser *)data;
|
||||||
|
|
||||||
if (parser->state >= AsxParser::ENTRY)
|
if (parser->state >= AsxParser::ENTRY)
|
||||||
song_free(parser->song);
|
parser->song->Free();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include "CuePlaylistPlugin.hxx"
|
#include "CuePlaylistPlugin.hxx"
|
||||||
#include "PlaylistPlugin.hxx"
|
#include "PlaylistPlugin.hxx"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "input_stream.h"
|
#include "input_stream.h"
|
||||||
#include "cue/CueParser.hxx"
|
#include "cue/CueParser.hxx"
|
||||||
#include "TextInputStream.hxx"
|
#include "TextInputStream.hxx"
|
||||||
|
@ -63,12 +63,12 @@ cue_playlist_close(struct playlist_provider *_playlist)
|
||||||
delete playlist;
|
delete playlist;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct song *
|
static Song *
|
||||||
cue_playlist_read(struct playlist_provider *_playlist)
|
cue_playlist_read(struct playlist_provider *_playlist)
|
||||||
{
|
{
|
||||||
CuePlaylist *playlist = (CuePlaylist *)_playlist;
|
CuePlaylist *playlist = (CuePlaylist *)_playlist;
|
||||||
|
|
||||||
struct song *song = playlist->parser.Get();
|
Song *song = playlist->parser.Get();
|
||||||
if (song != NULL)
|
if (song != NULL)
|
||||||
return song;
|
return song;
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include "DespotifyUtils.hxx"
|
#include "DespotifyUtils.hxx"
|
||||||
#include "MemoryPlaylistProvider.hxx"
|
#include "MemoryPlaylistProvider.hxx"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <despotify.h>
|
#include <despotify.h>
|
||||||
|
@ -37,7 +37,7 @@ static void
|
||||||
add_song(std::forward_list<SongPointer> &songs, struct ds_track *track)
|
add_song(std::forward_list<SongPointer> &songs, struct ds_track *track)
|
||||||
{
|
{
|
||||||
const char *dsp_scheme = despotify_playlist_plugin.schemes[0];
|
const char *dsp_scheme = despotify_playlist_plugin.schemes[0];
|
||||||
struct song *song;
|
Song *song;
|
||||||
char uri[128];
|
char uri[128];
|
||||||
char *ds_uri;
|
char *ds_uri;
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ add_song(std::forward_list<SongPointer> &songs, struct ds_track *track)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
song = song_remote_new(uri);
|
song = Song::NewRemote(uri);
|
||||||
song->tag = mpd_despotify_tag_from_track(track);
|
song->tag = mpd_despotify_tag_from_track(track);
|
||||||
|
|
||||||
songs.emplace_front(song);
|
songs.emplace_front(song);
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
#include "PlaylistPlugin.hxx"
|
#include "PlaylistPlugin.hxx"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
#include "tag_handler.h"
|
#include "tag_handler.h"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "TagFile.hxx"
|
#include "TagFile.hxx"
|
||||||
#include "cue/CueParser.hxx"
|
#include "cue/CueParser.hxx"
|
||||||
|
|
||||||
|
@ -128,12 +128,12 @@ embcue_playlist_close(struct playlist_provider *_playlist)
|
||||||
g_free(playlist);
|
g_free(playlist);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct song *
|
static Song *
|
||||||
embcue_playlist_read(struct playlist_provider *_playlist)
|
embcue_playlist_read(struct playlist_provider *_playlist)
|
||||||
{
|
{
|
||||||
struct embcue_playlist *playlist = (struct embcue_playlist *)_playlist;
|
struct embcue_playlist *playlist = (struct embcue_playlist *)_playlist;
|
||||||
|
|
||||||
struct song *song = playlist->parser->Get();
|
Song *song = playlist->parser->Get();
|
||||||
if (song != NULL)
|
if (song != NULL)
|
||||||
return song;
|
return song;
|
||||||
|
|
||||||
|
@ -152,13 +152,13 @@ embcue_playlist_read(struct playlist_provider *_playlist)
|
||||||
playlist->parser->Feed(line);
|
playlist->parser->Feed(line);
|
||||||
song = playlist->parser->Get();
|
song = playlist->parser->Get();
|
||||||
if (song != NULL)
|
if (song != NULL)
|
||||||
return song_replace_uri(song, playlist->filename);
|
return song->ReplaceURI(playlist->filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
playlist->parser->Finish();
|
playlist->parser->Finish();
|
||||||
song = playlist->parser->Get();
|
song = playlist->parser->Get();
|
||||||
if (song != NULL)
|
if (song != NULL)
|
||||||
song = song_replace_uri(song, playlist->filename);
|
song = song->ReplaceURI(playlist->filename);
|
||||||
return song;
|
return song;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "ExtM3uPlaylistPlugin.hxx"
|
#include "ExtM3uPlaylistPlugin.hxx"
|
||||||
#include "PlaylistPlugin.hxx"
|
#include "PlaylistPlugin.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
#include "util/StringUtil.hxx"
|
#include "util/StringUtil.hxx"
|
||||||
#include "TextInputStream.hxx"
|
#include "TextInputStream.hxx"
|
||||||
|
@ -105,14 +105,14 @@ extm3u_parse_tag(const char *line)
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct song *
|
static Song *
|
||||||
extm3u_read(struct playlist_provider *_playlist)
|
extm3u_read(struct playlist_provider *_playlist)
|
||||||
{
|
{
|
||||||
ExtM3uPlaylist *playlist = (ExtM3uPlaylist *)_playlist;
|
ExtM3uPlaylist *playlist = (ExtM3uPlaylist *)_playlist;
|
||||||
struct tag *tag = NULL;
|
struct tag *tag = NULL;
|
||||||
std::string line;
|
std::string line;
|
||||||
const char *line_s;
|
const char *line_s;
|
||||||
struct song *song;
|
Song *song;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (!playlist->tis->ReadLine(line)) {
|
if (!playlist->tis->ReadLine(line)) {
|
||||||
|
@ -134,7 +134,7 @@ extm3u_read(struct playlist_provider *_playlist)
|
||||||
++line_s;
|
++line_s;
|
||||||
} while (line_s[0] == '#' || *line_s == 0);
|
} while (line_s[0] == '#' || *line_s == 0);
|
||||||
|
|
||||||
song = song_remote_new(line_s);
|
song = Song::NewRemote(line_s);
|
||||||
song->tag = tag;
|
song->tag = tag;
|
||||||
return song;
|
return song;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include "PlaylistPlugin.hxx"
|
#include "PlaylistPlugin.hxx"
|
||||||
#include "PlaylistRegistry.hxx"
|
#include "PlaylistRegistry.hxx"
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "input_stream.h"
|
#include "input_stream.h"
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
@ -268,7 +268,7 @@ lastfm_close(struct playlist_provider *_playlist)
|
||||||
g_free(playlist);
|
g_free(playlist);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct song *
|
static Song *
|
||||||
lastfm_read(struct playlist_provider *_playlist)
|
lastfm_read(struct playlist_provider *_playlist)
|
||||||
{
|
{
|
||||||
struct lastfm_playlist *playlist = (struct lastfm_playlist *)_playlist;
|
struct lastfm_playlist *playlist = (struct lastfm_playlist *)_playlist;
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "M3uPlaylistPlugin.hxx"
|
#include "M3uPlaylistPlugin.hxx"
|
||||||
#include "PlaylistPlugin.hxx"
|
#include "PlaylistPlugin.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "TextInputStream.hxx"
|
#include "TextInputStream.hxx"
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
@ -51,7 +51,7 @@ m3u_close(struct playlist_provider *_playlist)
|
||||||
g_free(playlist);
|
g_free(playlist);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct song *
|
static Song *
|
||||||
m3u_read(struct playlist_provider *_playlist)
|
m3u_read(struct playlist_provider *_playlist)
|
||||||
{
|
{
|
||||||
M3uPlaylist *playlist = (M3uPlaylist *)_playlist;
|
M3uPlaylist *playlist = (M3uPlaylist *)_playlist;
|
||||||
|
@ -68,7 +68,7 @@ m3u_read(struct playlist_provider *_playlist)
|
||||||
++line_s;
|
++line_s;
|
||||||
} while (line_s[0] == '#' || *line_s == 0);
|
} while (line_s[0] == '#' || *line_s == 0);
|
||||||
|
|
||||||
return song_remote_new(line_s);
|
return Song::NewRemote(line_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *const m3u_suffixes[] = {
|
static const char *const m3u_suffixes[] = {
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "MemoryPlaylistProvider.hxx"
|
#include "MemoryPlaylistProvider.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
memory_playlist_close(struct playlist_provider *_playlist)
|
memory_playlist_close(struct playlist_provider *_playlist)
|
||||||
|
@ -29,7 +29,7 @@ memory_playlist_close(struct playlist_provider *_playlist)
|
||||||
delete playlist;
|
delete playlist;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct song *
|
static Song *
|
||||||
memory_playlist_read(struct playlist_provider *_playlist)
|
memory_playlist_read(struct playlist_provider *_playlist)
|
||||||
{
|
{
|
||||||
MemoryPlaylistProvider *playlist = (MemoryPlaylistProvider *)_playlist;
|
MemoryPlaylistProvider *playlist = (MemoryPlaylistProvider *)_playlist;
|
||||||
|
@ -57,7 +57,7 @@ MemoryPlaylistProvider::MemoryPlaylistProvider(std::forward_list<SongPointer> &&
|
||||||
playlist_provider_init(this, &memory_playlist_plugin);
|
playlist_provider_init(this, &memory_playlist_plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline song *
|
inline Song *
|
||||||
MemoryPlaylistProvider::Read()
|
MemoryPlaylistProvider::Read()
|
||||||
{
|
{
|
||||||
if (songs.empty())
|
if (songs.empty())
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
#include <forward_list>
|
#include <forward_list>
|
||||||
|
|
||||||
struct song;
|
struct Song;
|
||||||
|
|
||||||
class MemoryPlaylistProvider : public playlist_provider {
|
class MemoryPlaylistProvider : public playlist_provider {
|
||||||
std::forward_list<SongPointer> songs;
|
std::forward_list<SongPointer> songs;
|
||||||
|
@ -33,7 +33,7 @@ class MemoryPlaylistProvider : public playlist_provider {
|
||||||
public:
|
public:
|
||||||
MemoryPlaylistProvider(std::forward_list<SongPointer> &&_songs);
|
MemoryPlaylistProvider(std::forward_list<SongPointer> &&_songs);
|
||||||
|
|
||||||
song *Read();
|
Song *Read();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include "PlsPlaylistPlugin.hxx"
|
#include "PlsPlaylistPlugin.hxx"
|
||||||
#include "MemoryPlaylistProvider.hxx"
|
#include "MemoryPlaylistProvider.hxx"
|
||||||
#include "input_stream.h"
|
#include "input_stream.h"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
@ -50,7 +50,7 @@ pls_parser(GKeyFile *keyfile, std::forward_list<SongPointer> &songs)
|
||||||
}
|
}
|
||||||
|
|
||||||
while (num_entries > 0) {
|
while (num_entries > 0) {
|
||||||
struct song *song;
|
Song *song;
|
||||||
key = g_strdup_printf("File%i", num_entries);
|
key = g_strdup_printf("File%i", num_entries);
|
||||||
value = g_key_file_get_string(keyfile, "playlist", key,
|
value = g_key_file_get_string(keyfile, "playlist", key,
|
||||||
&error);
|
&error);
|
||||||
|
@ -62,7 +62,7 @@ pls_parser(GKeyFile *keyfile, std::forward_list<SongPointer> &songs)
|
||||||
}
|
}
|
||||||
g_free(key);
|
g_free(key);
|
||||||
|
|
||||||
song = song_remote_new(value);
|
song = Song::NewRemote(value);
|
||||||
g_free(value);
|
g_free(value);
|
||||||
|
|
||||||
key = g_strdup_printf("Title%i", num_entries);
|
key = g_strdup_printf("Title%i", num_entries);
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include "RssPlaylistPlugin.hxx"
|
#include "RssPlaylistPlugin.hxx"
|
||||||
#include "MemoryPlaylistProvider.hxx"
|
#include "MemoryPlaylistProvider.hxx"
|
||||||
#include "input_stream.h"
|
#include "input_stream.h"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
@ -60,7 +60,7 @@ struct RssParser {
|
||||||
* The current song. It is allocated after the "location"
|
* The current song. It is allocated after the "location"
|
||||||
* element.
|
* element.
|
||||||
*/
|
*/
|
||||||
struct song *song;
|
Song *song;
|
||||||
|
|
||||||
RssParser()
|
RssParser()
|
||||||
:state(ROOT) {}
|
:state(ROOT) {}
|
||||||
|
@ -90,7 +90,7 @@ rss_start_element(G_GNUC_UNUSED GMarkupParseContext *context,
|
||||||
case RssParser::ROOT:
|
case RssParser::ROOT:
|
||||||
if (g_ascii_strcasecmp(element_name, "item") == 0) {
|
if (g_ascii_strcasecmp(element_name, "item") == 0) {
|
||||||
parser->state = RssParser::ITEM;
|
parser->state = RssParser::ITEM;
|
||||||
parser->song = song_remote_new("rss:");
|
parser->song = Song::NewRemote("rss:");
|
||||||
parser->tag = TAG_NUM_OF_ITEM_TYPES;
|
parser->tag = TAG_NUM_OF_ITEM_TYPES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,12 +107,12 @@ rss_start_element(G_GNUC_UNUSED GMarkupParseContext *context,
|
||||||
replace the existing song's URI,
|
replace the existing song's URI,
|
||||||
because that attribute is
|
because that attribute is
|
||||||
immutable */
|
immutable */
|
||||||
struct song *song = song_remote_new(href);
|
Song *song = Song::NewRemote(href);
|
||||||
|
|
||||||
if (parser->song != NULL) {
|
if (parser->song != NULL) {
|
||||||
song->tag = parser->song->tag;
|
song->tag = parser->song->tag;
|
||||||
parser->song->tag = NULL;
|
parser->song->tag = NULL;
|
||||||
song_free(parser->song);
|
parser->song->Free();
|
||||||
}
|
}
|
||||||
|
|
||||||
parser->song = song;
|
parser->song = song;
|
||||||
|
@ -142,7 +142,7 @@ rss_end_element(G_GNUC_UNUSED GMarkupParseContext *context,
|
||||||
if (strcmp(parser->song->uri, "rss:") != 0)
|
if (strcmp(parser->song->uri, "rss:") != 0)
|
||||||
parser->songs.emplace_front(parser->song);
|
parser->songs.emplace_front(parser->song);
|
||||||
else
|
else
|
||||||
song_free(parser->song);
|
parser->song->Free();
|
||||||
|
|
||||||
parser->state = RssParser::ROOT;
|
parser->state = RssParser::ROOT;
|
||||||
} else
|
} else
|
||||||
|
@ -189,7 +189,7 @@ rss_parser_destroy(gpointer data)
|
||||||
RssParser *parser = (RssParser *)data;
|
RssParser *parser = (RssParser *)data;
|
||||||
|
|
||||||
if (parser->state >= RssParser::ITEM)
|
if (parser->state >= RssParser::ITEM)
|
||||||
song_free(parser->song);
|
parser->song->Free();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include "MemoryPlaylistProvider.hxx"
|
#include "MemoryPlaylistProvider.hxx"
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include "input_stream.h"
|
#include "input_stream.h"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
@ -203,12 +203,12 @@ static int handle_end_map(void *ctx)
|
||||||
/* got_url == 1, track finished, make it into a song */
|
/* got_url == 1, track finished, make it into a song */
|
||||||
data->got_url = 0;
|
data->got_url = 0;
|
||||||
|
|
||||||
struct song *s;
|
Song *s;
|
||||||
struct tag *t;
|
struct tag *t;
|
||||||
char *u;
|
char *u;
|
||||||
|
|
||||||
u = g_strconcat(data->stream_url, "?client_id=", soundcloud_config.apikey, NULL);
|
u = g_strconcat(data->stream_url, "?client_id=", soundcloud_config.apikey, NULL);
|
||||||
s = song_remote_new(u);
|
s = Song::NewRemote(u);
|
||||||
g_free(u);
|
g_free(u);
|
||||||
t = tag_new();
|
t = tag_new();
|
||||||
t->time = data->duration / 1000;
|
t->time = data->duration / 1000;
|
||||||
|
|
|
@ -60,7 +60,7 @@ struct XspfParser {
|
||||||
* The current song. It is allocated after the "location"
|
* The current song. It is allocated after the "location"
|
||||||
* element.
|
* element.
|
||||||
*/
|
*/
|
||||||
struct song *song;
|
Song *song;
|
||||||
|
|
||||||
XspfParser()
|
XspfParser()
|
||||||
:state(ROOT) {}
|
:state(ROOT) {}
|
||||||
|
@ -187,7 +187,7 @@ xspf_text(G_GNUC_UNUSED GMarkupParseContext *context,
|
||||||
case XspfParser::LOCATION:
|
case XspfParser::LOCATION:
|
||||||
if (parser->song == NULL) {
|
if (parser->song == NULL) {
|
||||||
char *uri = g_strndup(text, text_len);
|
char *uri = g_strndup(text, text_len);
|
||||||
parser->song = song_remote_new(uri);
|
parser->song = Song::NewRemote(uri);
|
||||||
g_free(uri);
|
g_free(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,7 +209,7 @@ xspf_parser_destroy(gpointer data)
|
||||||
XspfParser *parser = (XspfParser *)data;
|
XspfParser *parser = (XspfParser *)data;
|
||||||
|
|
||||||
if (parser->state >= XspfParser::TRACK && parser->song != NULL)
|
if (parser->state >= XspfParser::TRACK && parser->song != NULL)
|
||||||
song_free(parser->song);
|
parser->song->Free();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
167
src/song.h
167
src/song.h
|
@ -1,167 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2003-2011 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_SONG_H
|
|
||||||
#define MPD_SONG_H
|
|
||||||
|
|
||||||
#include "util/list.h"
|
|
||||||
#include "gcc.h"
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
|
|
||||||
#define SONG_FILE "file: "
|
|
||||||
#define SONG_TIME "Time: "
|
|
||||||
|
|
||||||
struct song {
|
|
||||||
/**
|
|
||||||
* Pointers to the siblings of this directory within the
|
|
||||||
* parent directory. It is unused (undefined) if this song is
|
|
||||||
* not in the database.
|
|
||||||
*
|
|
||||||
* This attribute is protected with the global #db_mutex.
|
|
||||||
* Read access in the update thread does not need protection.
|
|
||||||
*/
|
|
||||||
struct list_head siblings;
|
|
||||||
|
|
||||||
struct tag *tag;
|
|
||||||
struct Directory *parent;
|
|
||||||
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;
|
|
||||||
|
|
||||||
char uri[sizeof(int)];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A dummy #directory instance that is used for "detached" song
|
|
||||||
* copies.
|
|
||||||
*/
|
|
||||||
extern struct Directory detached_root;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** allocate a new song with a remote URL */
|
|
||||||
struct song *
|
|
||||||
song_remote_new(const char *uri);
|
|
||||||
|
|
||||||
/** allocate a new song with a local file name */
|
|
||||||
struct song *
|
|
||||||
song_file_new(const char *path_utf8, struct Directory *parent);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* allocate a new song structure with a local file name and attempt to
|
|
||||||
* load its metadata. If all decoder plugin fail to read its meta
|
|
||||||
* data, NULL is returned.
|
|
||||||
*/
|
|
||||||
struct song *
|
|
||||||
song_file_load(const char *path_utf8, struct Directory *parent);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replaces the URI of a song object. The given song object is
|
|
||||||
* destroyed, and a newly allocated one is returned. It does not
|
|
||||||
* update the reference within the parent directory; the caller is
|
|
||||||
* responsible for doing that.
|
|
||||||
*/
|
|
||||||
struct song *
|
|
||||||
song_replace_uri(struct song *song, const char *uri);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a "detached" song object.
|
|
||||||
*/
|
|
||||||
struct song *
|
|
||||||
song_detached_new(const char *uri);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a duplicate of the song object. If the object is in the
|
|
||||||
* database, it creates a "detached" copy of this song, see
|
|
||||||
* song_is_detached().
|
|
||||||
*/
|
|
||||||
gcc_malloc
|
|
||||||
struct song *
|
|
||||||
song_dup_detached(const struct song *src);
|
|
||||||
|
|
||||||
void
|
|
||||||
song_free(struct song *song);
|
|
||||||
|
|
||||||
static inline bool
|
|
||||||
song_in_database(const struct song *song)
|
|
||||||
{
|
|
||||||
return song->parent != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool
|
|
||||||
song_is_file(const struct song *song)
|
|
||||||
{
|
|
||||||
return song_in_database(song) || song->uri[0] == '/';
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool
|
|
||||||
song_is_detached(const struct song *song)
|
|
||||||
{
|
|
||||||
assert(song != NULL);
|
|
||||||
assert(song_in_database(song));
|
|
||||||
|
|
||||||
return song->parent == &detached_root;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if both objects refer to the same physical song.
|
|
||||||
*/
|
|
||||||
gcc_pure
|
|
||||||
bool
|
|
||||||
song_equals(const struct song *a, const struct song *b);
|
|
||||||
|
|
||||||
bool
|
|
||||||
song_file_update(struct song *song);
|
|
||||||
|
|
||||||
bool
|
|
||||||
song_file_update_inarchive(struct song *song);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the URI of the song in UTF-8 encoding, including its
|
|
||||||
* location within the music directory.
|
|
||||||
*
|
|
||||||
* The return value is allocated on the heap, and must be freed by the
|
|
||||||
* caller.
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
song_get_uri(const struct song *song);
|
|
||||||
|
|
||||||
double
|
|
||||||
song_get_duration(const struct song *song);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include "DatabasePlugin.hxx"
|
#include "DatabasePlugin.hxx"
|
||||||
#include "DatabaseSelection.hxx"
|
#include "DatabaseSelection.hxx"
|
||||||
#include "Directory.hxx"
|
#include "Directory.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "PlaylistVector.hxx"
|
#include "PlaylistVector.hxx"
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
|
@ -53,7 +53,7 @@ DumpDirectory(const Directory &directory, GError **)
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
DumpSong(song &song, GError **)
|
DumpSong(Song &song, GError **)
|
||||||
{
|
{
|
||||||
cout << "S " << song.parent->path << "/" << song.uri << endl;
|
cout << "S " << song.parent->path << "/" << song.uri << endl;
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "directory.h"
|
#include "directory.h"
|
||||||
#include "gcc.h"
|
#include "gcc.h"
|
||||||
|
|
||||||
|
@ -26,8 +26,8 @@
|
||||||
|
|
||||||
struct directory detached_root;
|
struct directory detached_root;
|
||||||
|
|
||||||
struct song *
|
Song *
|
||||||
song_dup_detached(gcc_unused const struct song *src)
|
song_dup_detached(gcc_unused const Song *src)
|
||||||
{
|
{
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "TagSave.hxx"
|
#include "TagSave.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "Directory.hxx"
|
#include "Directory.hxx"
|
||||||
#include "input_stream.h"
|
#include "input_stream.h"
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
|
@ -141,7 +141,7 @@ int main(int argc, char **argv)
|
||||||
struct input_stream *is = NULL;
|
struct input_stream *is = NULL;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
struct playlist_provider *playlist;
|
struct playlist_provider *playlist;
|
||||||
struct song *song;
|
Song *song;
|
||||||
|
|
||||||
if (argc != 3) {
|
if (argc != 3) {
|
||||||
g_printerr("Usage: dump_playlist CONFIG URI\n");
|
g_printerr("Usage: dump_playlist CONFIG URI\n");
|
||||||
|
@ -234,7 +234,7 @@ int main(int argc, char **argv)
|
||||||
if (song->tag != NULL)
|
if (song->tag != NULL)
|
||||||
tag_save(stdout, song->tag);
|
tag_save(stdout, song->tag);
|
||||||
|
|
||||||
song_free(song);
|
song->Free();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* deinitialize everything */
|
/* deinitialize everything */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "Queue.hxx"
|
#include "Queue.hxx"
|
||||||
#include "song.h"
|
#include "Song.hxx"
|
||||||
#include "Directory.hxx"
|
#include "Directory.hxx"
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
@ -10,14 +10,14 @@ Directory detached_root;
|
||||||
Directory::Directory() {}
|
Directory::Directory() {}
|
||||||
Directory::~Directory() {}
|
Directory::~Directory() {}
|
||||||
|
|
||||||
struct song *
|
Song *
|
||||||
song_dup_detached(const struct song *src)
|
Song::DupDetached() const
|
||||||
{
|
{
|
||||||
return const_cast<song *>(src);
|
return const_cast<Song *>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
song_free(gcc_unused struct song *song)
|
Song::Free()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ check_descending_priority(const struct queue *queue,
|
||||||
int
|
int
|
||||||
main(gcc_unused int argc, gcc_unused char **argv)
|
main(gcc_unused int argc, gcc_unused char **argv)
|
||||||
{
|
{
|
||||||
static struct song songs[16];
|
static Song songs[16];
|
||||||
|
|
||||||
struct queue queue(32);
|
struct queue queue(32);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue