song: convert header to C++

This commit is contained in:
Max Kellermann 2013-07-28 13:25:12 +02:00
parent 43f613d9be
commit ba161ec572
91 changed files with 643 additions and 691 deletions

View File

@ -81,7 +81,6 @@ mpd_headers = \
src/replay_gain_info.h \
src/replay_gain_ape.h \
src/TimePrint.cxx src/TimePrint.hxx \
src/song.h \
src/stats.h \
src/tag.h \
src/tag_internal.h \
@ -217,7 +216,7 @@ src_mpd_SOURCES = \
src/ReplayGainConfig.cxx \
src/ReplayGainInfo.cxx \
src/SignalHandlers.cxx src/SignalHandlers.hxx \
src/Song.cxx \
src/Song.cxx src/Song.hxx \
src/SongUpdate.cxx \
src/SongPrint.cxx src/SongPrint.hxx \
src/SongSave.cxx src/SongSave.hxx \

View File

@ -19,7 +19,7 @@
#include "DatabaseHelpers.hxx"
#include "DatabasePlugin.hxx"
#include "song.h"
#include "Song.hxx"
#include "tag.h"
#include <functional>
@ -37,7 +37,7 @@ struct StringLess {
typedef std::set<const char *, StringLess> StringSet;
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;
if (tag == nullptr)
@ -104,7 +104,7 @@ StatsVisitTag(DatabaseStats &stats, StringSet &artists, StringSet &albums,
static bool
StatsVisitSong(DatabaseStats &stats, StringSet &artists, StringSet &albums,
song &song)
Song &song)
{
++stats.song_count;

View File

@ -28,7 +28,7 @@
static bool
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);
}

View File

@ -36,6 +36,7 @@ extern "C" {
struct config_param;
struct DatabaseSelection;
struct db_visitor;
struct Song;
struct DatabaseStats {
/**
@ -91,14 +92,14 @@ public:
* @param uri_utf8 the URI of the song within the music
* directory (UTF-8)
*/
virtual struct song *GetSong(const char *uri_utf8,
GError **error_r) const = 0;
virtual Song *GetSong(const char *uri_utf8,
GError **error_r) const = 0;
/**
* Mark the song object as "unused". Call this on objects
* returned by GetSong().
*/
virtual void ReturnSong(struct song *song) const = 0;
virtual void ReturnSong(Song *song) const = 0;
/**
* Visit the selected entities.

View File

@ -27,11 +27,7 @@
#include "Directory.hxx"
#include "Client.hxx"
#include "tag.h"
extern "C" {
#include "song.h"
}
#include "Song.hxx"
#include "DatabaseGlue.hxx"
#include "DatabasePlugin.hxx"
@ -59,7 +55,7 @@ print_playlist_in_directory(Client *client,
}
static bool
PrintSongBrief(Client *client, song &song)
PrintSongBrief(Client *client, Song &song)
{
assert(song.parent != NULL);
@ -73,7 +69,7 @@ PrintSongBrief(Client *client, song &song)
}
static bool
PrintSongFull(Client *client, song &song)
PrintSongFull(Client *client, Song &song)
{
assert(song.parent != NULL);
@ -142,10 +138,10 @@ static void printSearchStats(Client *client, SearchStats *stats)
}
static bool
stats_visitor_song(SearchStats &stats, song &song)
stats_visitor_song(SearchStats &stats, Song &song)
{
stats.numberOfSongs++;
stats.playTime += song_get_duration(&song);
stats.playTime += song.GetDuration();
return true;
}
@ -191,7 +187,7 @@ printInfoForAllIn(Client *client, const char *uri_utf8,
}
static bool
PrintSongURIVisitor(Client *client, song &song)
PrintSongURIVisitor(Client *client, Song &song)
{
song_print_uri(client, &song);

View File

@ -27,7 +27,7 @@
#include <functional>
static bool
AddToQueue(Partition &partition, song &song, GError **error_r)
AddToQueue(Partition &partition, Song &song, GError **error_r)
{
enum playlist_result result =
partition.playlist.AppendSong(partition.pc, &song, NULL);

View File

@ -22,7 +22,7 @@
#include "DatabaseLock.hxx"
#include "Directory.hxx"
#include "DirectorySave.hxx"
#include "song.h"
#include "Song.hxx"
#include "TextFile.hxx"
#include "TagInternal.hxx"
#include "tag.h"

View File

@ -21,7 +21,7 @@
#include "SongFilter.hxx"
bool
DatabaseSelection::Match(const song &song) const
DatabaseSelection::Match(const Song &song) const
{
return filter == nullptr || filter->Match(song);
}

View File

@ -26,7 +26,7 @@
#include <stddef.h>
class SongFilter;
struct song;
struct Song;
struct DatabaseSelection {
/**
@ -50,7 +50,7 @@ struct DatabaseSelection {
}
gcc_pure
bool Match(const song &song) const;
bool Match(const Song &song) const;
};
#endif

View File

@ -25,11 +25,11 @@
#include <functional>
struct Directory;
struct song;
struct Song;
struct PlaylistInfo;
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 &,
GError **)> VisitPlaylist;

View File

@ -26,7 +26,7 @@
#include "MusicPipe.hxx"
#include "DecoderControl.hxx"
#include "DecoderInternal.hxx"
#include "song.h"
#include "Song.hxx"
#include "InputStream.hxx"
#include <glib.h>

View File

@ -20,7 +20,7 @@
#include "config.h"
#include "DecoderControl.hxx"
#include "MusicPipe.hxx"
#include "song.h"
#include "Song.hxx"
#include <assert.h>
@ -41,7 +41,7 @@ decoder_control::~decoder_control()
ClearError();
if (song != NULL)
song_free(song);
song->Free();
g_free(mixramp_start);
g_free(mixramp_end);
@ -84,7 +84,7 @@ dc_command_async(struct decoder_control *dc, enum decoder_command cmd)
}
bool
decoder_control::IsCurrentSong(const struct song *_song) const
decoder_control::IsCurrentSong(const Song *_song) const
{
assert(_song != NULL);
@ -103,7 +103,7 @@ decoder_control::IsCurrentSong(const struct song *_song) const
}
void
decoder_control::Start(struct song *_song,
decoder_control::Start(Song *_song,
unsigned _start_ms, unsigned _end_ms,
music_buffer *_buffer, music_pipe *_pipe)
{
@ -113,7 +113,7 @@ decoder_control::Start(struct song *_song,
assert(music_pipe_empty(_pipe));
if (song != nullptr)
song_free(song);
song->Free();
song = _song;
start_ms = _start_ms;

View File

@ -29,6 +29,8 @@
#include <assert.h>
struct Song;
enum decoder_state {
DECODE_STATE_STOP = 0,
DECODE_STATE_START,
@ -96,7 +98,7 @@ struct decoder_control {
* This is a duplicate, and must be freed when this attribute
* is cleared.
*/
struct song *song;
Song *song;
/**
* The initial seek position (in milliseconds), e.g. to the
@ -260,10 +262,10 @@ struct decoder_control {
* Caller must lock the object.
*/
gcc_pure
bool IsCurrentSong(const struct song *_song) const;
bool IsCurrentSong(const Song *_song) const;
gcc_pure
bool LockIsCurrentSong(const struct song *_song) const {
bool LockIsCurrentSong(const Song *_song) const {
Lock();
const bool result = IsCurrentSong(_song);
Unlock();
@ -280,7 +282,7 @@ struct decoder_control {
* @param pipe the pipe which receives the decoded chunks (owned by
* 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);
void Stop();

View File

@ -23,7 +23,7 @@
#include "DecoderInternal.hxx"
#include "DecoderError.hxx"
#include "DecoderPlugin.hxx"
#include "song.h"
#include "Song.hxx"
#include "mpd_error.h"
#include "Mapper.hxx"
#include "fs/Path.hxx"
@ -380,10 +380,10 @@ decoder_run_file(struct decoder *decoder, const char *path_fs)
static void
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,
song->tag != NULL && song_is_file(song)
song->tag != NULL && song->IsFile()
? tag_dup(song->tag) : nullptr);
int ret;
@ -391,7 +391,7 @@ decoder_run_song(struct decoder_control *dc,
decoder_command_finished_locked(dc);
ret = song_is_file(song)
ret = song->IsFile()
? decoder_run_file(&decoder, uri)
: decoder_run_stream(&decoder, uri);
@ -427,15 +427,15 @@ decoder_run(struct decoder_control *dc)
{
dc->ClearError();
const struct song *song = dc->song;
const Song *song = dc->song;
char *uri;
assert(song != NULL);
if (song_is_file(song))
if (song->IsFile())
uri = map_song_fs(song).Steal();
else
uri = song_get_uri(song);
uri = song->GetURI();
if (uri == NULL) {
dc->state = DECODE_STATE_ERROR;

View File

@ -23,9 +23,9 @@
#include "PlaylistVector.hxx"
#include "DatabaseLock.hxx"
#include "SongSort.hxx"
#include "Song.hxx"
extern "C" {
#include "song.h"
#include "util/list_sort.h"
}
@ -68,9 +68,9 @@ Directory::Directory(const char *_path)
Directory::~Directory()
{
struct song *song, *ns;
Song *song, *ns;
directory_for_each_song_safe(song, ns, this)
song_free(song);
song->Free();
Directory *child, *n;
directory_for_each_child_safe(child, n, this)
@ -208,7 +208,7 @@ Directory::LookupDirectory(const char *uri)
}
void
Directory::AddSong(struct song *song)
Directory::AddSong(Song *song)
{
assert(holding_db_lock());
assert(song != NULL);
@ -218,7 +218,7 @@ Directory::AddSong(struct song *song)
}
void
Directory::RemoveSong(struct song *song)
Directory::RemoveSong(Song *song)
{
assert(holding_db_lock());
assert(song != NULL);
@ -227,13 +227,13 @@ Directory::RemoveSong(struct song *song)
list_del(&song->siblings);
}
const song *
const Song *
Directory::FindSong(const char *name_utf8) const
{
assert(holding_db_lock());
assert(name_utf8 != NULL);
struct song *song;
Song *song;
directory_for_each_song(song, this) {
assert(song->parent == this);
@ -244,7 +244,7 @@ Directory::FindSong(const char *name_utf8) const
return NULL;
}
struct song *
Song *
Directory::LookupSong(const char *uri)
{
char *duplicated, *base;
@ -266,7 +266,7 @@ Directory::LookupSong(const char *uri)
} else
base = duplicated;
struct song *song = d->FindSong(base);
Song *song = d->FindSong(base);
assert(song == NULL || song->parent == d);
g_free(duplicated);
@ -305,7 +305,7 @@ Directory::Walk(bool recursive, const SongFilter *filter,
assert(error_r == NULL || *error_r == NULL);
if (visit_song) {
struct song *song;
Song *song;
directory_for_each_song(song, this)
if ((filter == nullptr || filter->Match(*song)) &&
!visit_song(*song, error_r))

View File

@ -45,7 +45,7 @@
#define directory_for_each_song_safe(pos, n, directory) \
list_for_each_entry_safe(pos, n, &directory->songs, siblings)
struct song;
struct Song;
struct db_visitor;
class SongFilter;
@ -202,12 +202,12 @@ public:
* Caller must lock the #db_mutex.
*/
gcc_pure
const song *FindSong(const char *name_utf8) const;
const Song *FindSong(const char *name_utf8) const;
gcc_pure
song *FindSong(const char *name_utf8) {
Song *FindSong(const char *name_utf8) {
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
*/
gcc_pure
song *LookupSong(const char *uri);
Song *LookupSong(const char *uri);
/**
* Add a song object to this directory. Its "parent" attribute must
* be set already.
*/
void AddSong(song *song);
void AddSong(Song *song);
/**
* Remove a song object from this directory (which effectively
* invalidates the song object, because the "parent" attribute becomes
* stale), but does not free it.
*/
void RemoveSong(song *song);
void RemoveSong(Song *song);
/**
* Caller must lock the #db_mutex.

View File

@ -20,7 +20,7 @@
#include "config.h"
#include "DirectorySave.hxx"
#include "Directory.hxx"
#include "song.h"
#include "Song.hxx"
#include "SongSave.hxx"
#include "PlaylistDatabase.hxx"
#include "TextFile.hxx"
@ -65,7 +65,7 @@ directory_save(FILE *fp, const Directory *directory)
return;
}
struct song *song;
Song *song;
directory_for_each_song(song, directory)
song_save(fp, song);
@ -143,7 +143,7 @@ directory_load(TextFile &file, Directory *directory, GError **error)
return false;
} else if (g_str_has_prefix(line, SONG_BEGIN)) {
const char *name = line + sizeof(SONG_BEGIN) - 1;
struct song *song;
Song *song;
if (directory->FindSong(name) != nullptr) {
g_set_error(error, directory_quark(), 0,

View File

@ -23,7 +23,7 @@
#include "Idle.hxx"
void
Instance::DeleteSong(const song &song)
Instance::DeleteSong(const Song &song)
{
partition->DeleteSong(song);
}

View File

@ -24,14 +24,14 @@
class ClientList;
struct Partition;
struct song;
struct Song;
struct Instance {
ClientList *client_list;
Partition *partition;
void DeleteSong(const song &song);
void DeleteSong(const Song &song);
/**
* The database has been modified. Propagate the change to

View File

@ -24,7 +24,7 @@
#include "config.h"
#include "Mapper.hxx"
#include "Directory.hxx"
#include "song.h"
#include "Song.hxx"
#include "fs/Path.hxx"
#include "fs/FileSystem.hxx"
#include "fs/DirectoryReader.hxx"
@ -246,12 +246,12 @@ map_detached_song_fs(const char *uri_utf8)
}
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))
return song_is_detached(song)
if (song->IsInDatabase())
return song->IsDetached()
? map_detached_song_fs(song->uri)
: map_directory_child_fs(song->parent, song->uri);
else

View File

@ -31,7 +31,7 @@
class Path;
struct Directory;
struct song;
struct Song;
bool mapper_init(const char *_music_dir, const char *_playlist_dir,
GError **error_r);
@ -112,7 +112,7 @@ map_directory_child_fs(const Directory *directory, const char *name);
*/
gcc_pure
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

View File

@ -23,7 +23,7 @@
#include "CommandError.hxx"
#include "UpdateGlue.hxx"
#include "Directory.hxx"
#include "song.h"
#include "Song.hxx"
#include "SongPrint.hxx"
#include "TagPrint.hxx"
#include "TimePrint.hxx"
@ -130,7 +130,7 @@ handle_lsinfo(Client *client, int argc, char *argv[])
if (!client_allow_file(client, path_fs, &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) {
command_error(client, ACK_ERROR_NO_EXIST,
"No such file");
@ -138,7 +138,7 @@ handle_lsinfo(Client *client, int argc, char *argv[])
}
song_print_info(client, song);
song_free(song);
song->Free();
return COMMAND_RETURN_OK;
}

View File

@ -76,7 +76,7 @@ struct Partition {
return playlist.DeleteRange(pc, start, end);
}
void DeleteSong(const song &song) {
void DeleteSong(const Song &song) {
playlist.DeleteSong(pc, song);
}

View File

@ -20,7 +20,7 @@
#include "config.h"
#include "PlayerControl.hxx"
#include "Idle.hxx"
#include "song.h"
#include "Song.hxx"
#include "DecoderControl.hxx"
#include "Main.hxx"
@ -30,7 +30,7 @@
#include <stdio.h>
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,
unsigned _buffered_before_play)
@ -59,7 +59,7 @@ player_control::player_control(unsigned _buffer_chunks,
player_control::~player_control()
{
if (next_song != nullptr)
song_free(next_song);
next_song->Free();
}
static void
@ -88,7 +88,7 @@ player_command(struct player_control *pc, enum player_command cmd)
}
void
player_control::Play(struct song *song)
player_control::Play(Song *song)
{
assert(song != NULL);
@ -253,7 +253,7 @@ player_control::GetErrorMessage() const
}
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(pc->next_song == NULL);
@ -263,7 +263,7 @@ pc_enqueue_song_locked(struct player_control *pc, struct song *song)
}
void
player_control::EnqueueSong(struct song *song)
player_control::EnqueueSong(Song *song)
{
assert(song != NULL);
@ -273,14 +273,14 @@ player_control::EnqueueSong(struct song *song)
}
bool
player_control::Seek(struct song *song, float seek_time)
player_control::Seek(Song *song, float seek_time)
{
assert(song != NULL);
Lock();
if (next_song != nullptr)
song_free(next_song);
next_song->Free();
next_song = song;
seek_where = seek_time;

View File

@ -29,6 +29,7 @@
#include <stdint.h>
struct decoder_control;
struct Song;
enum player_state {
PLAYER_STATE_STOP = 0,
@ -139,7 +140,7 @@ struct player_control {
* This is a duplicate, and must be freed when this attribute
* is cleared.
*/
struct song *next_song;
Song *next_song;
double seek_where;
float cross_fade_seconds;
@ -230,7 +231,7 @@ struct player_control {
* @param song the song to be queued; the given instance will
* be owned and freed by the player
*/
void Play(struct song *song);
void Play(Song *song);
/**
* see PLAYER_COMMAND_CANCEL
@ -287,7 +288,7 @@ struct player_control {
* @param song the song to be queued; the given instance will be owned
* 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.
@ -297,7 +298,7 @@ struct player_control {
* @return true on success, false on failure (e.g. if MPD isn't
* playing currently)
*/
bool Seek(struct song *song, float seek_time);
bool Seek(Song *song, float seek_time);
void SetCrossFade(float cross_fade_seconds);

View File

@ -24,7 +24,7 @@
#include "MusicPipe.hxx"
#include "MusicBuffer.hxx"
#include "MusicChunk.hxx"
#include "song.h"
#include "Song.hxx"
#include "Main.hxx"
#include "mpd_error.h"
#include "CrossFade.hxx"
@ -86,7 +86,7 @@ struct player {
/**
* the song currently being played
*/
struct song *song;
Song *song;
/**
* is cross fading enabled?
@ -176,7 +176,7 @@ player_dc_start(struct player *player, struct music_pipe *pipe)
if (pc->command == PLAYER_COMMAND_SEEK)
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,
player_buffer, pipe);
}
@ -254,7 +254,7 @@ player_wait_for_decoder(struct player *player)
pc->Lock();
pc->SetError(PLAYER_ERROR_DECODER, error);
song_free(pc->next_song);
pc->next_song->Free();
pc->next_song = NULL;
pc->Unlock();
@ -263,7 +263,7 @@ player_wait_for_decoder(struct player *player)
}
if (player->song != NULL)
song_free(player->song);
player->song->Free();
player->song = pc->next_song;
player->elapsed_time = 0.0;
@ -275,7 +275,7 @@ player_wait_for_decoder(struct player *player)
pc->Lock();
/* 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;
audio_format_clear(&pc->audio_format);
@ -295,14 +295,14 @@ player_wait_for_decoder(struct player *player)
* indicated by the decoder plugin.
*/
static double
real_song_duration(const struct song *song, double decoder_duration)
real_song_duration(const Song *song, double decoder_duration)
{
assert(song != NULL);
if (decoder_duration <= 0.0)
/* the decoder plugin didn't provide information; fall
back to song_get_duration() */
return song_get_duration(song);
back to Song::GetDuration() */
return song->GetDuration();
if (song->end_ms > 0 && song->end_ms / 1000.0 < decoder_duration)
return (song->end_ms - song->start_ms) / 1000.0;
@ -407,7 +407,7 @@ player_check_decoder_startup(struct player *player)
player->decoder_starting = false;
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 "
"while playing \"%s\"", uri);
g_free(uri);
@ -479,7 +479,7 @@ player_send_silence(struct player *player)
static bool player_seek_decoder(struct player *player)
{
struct player_control *pc = player->pc;
struct song *song = pc->next_song;
Song *song = pc->next_song;
struct decoder_control *dc = player->dc;
assert(pc->next_song != NULL);
@ -512,7 +512,7 @@ static bool player_seek_decoder(struct player *player)
player->pipe = dc->pipe;
}
song_free(pc->next_song);
pc->next_song->Free();
pc->next_song = NULL;
player->queued = false;
}
@ -633,7 +633,7 @@ static void player_process_command(struct player *player)
pc->Lock();
}
song_free(pc->next_song);
pc->next_song->Free();
pc->next_song = NULL;
player->queued = false;
player_command_finished_locked(pc);
@ -656,9 +656,9 @@ static void player_process_command(struct player *player)
}
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
streams may change tags dynamically */
return;
@ -687,7 +687,7 @@ update_song_tag(struct song *song, const struct tag *new_tag)
*/
static bool
play_chunk(struct player_control *pc,
struct song *song, struct music_chunk *chunk,
Song *song, struct music_chunk *chunk,
const struct audio_format *format,
GError **error_r)
{
@ -872,7 +872,7 @@ player_song_border(struct player *player)
{
player->xfade = XFADE_UNKNOWN;
char *uri = song_get_uri(player->song);
char *uri = player->song->GetURI();
g_message("played \"%s\"", 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);
if (player.song != NULL)
song_free(player.song);
player.song->Free();
pc->Lock();
if (player.queued) {
assert(pc->next_song != NULL);
song_free(pc->next_song);
pc->next_song->Free();
pc->next_song = NULL;
}
@ -1133,7 +1133,7 @@ player_task(gpointer arg)
case PLAYER_COMMAND_PAUSE:
if (pc->next_song != NULL) {
song_free(pc->next_song);
pc->next_song->Free();
pc->next_song = NULL;
}
@ -1178,7 +1178,7 @@ player_task(gpointer arg)
case PLAYER_COMMAND_CANCEL:
if (pc->next_song != NULL) {
song_free(pc->next_song);
pc->next_song->Free();
pc->next_song = NULL;
}

View File

@ -20,7 +20,7 @@
#include "config.h"
#include "Playlist.hxx"
#include "PlayerControl.hxx"
#include "song.h"
#include "Song.hxx"
#include "Idle.hxx"
#include <glib.h>
@ -62,10 +62,9 @@ playlist_queue_song_order(struct playlist *playlist, struct player_control *pc,
playlist->queued = order;
struct song *song =
song_dup_detached(playlist->queue.GetOrder(order));
Song *song = playlist->queue.GetOrder(order)->DupDetached();
uri = song_get_uri(song);
uri = song->GetURI();
g_debug("queue song %i:\"%s\"", playlist->queued, uri);
g_free(uri);
@ -94,7 +93,7 @@ playlist_song_started(struct playlist *playlist, struct player_control *pc)
idle_add(IDLE_PLAYER);
}
const struct song *
const Song *
playlist::GetQueuedSong() const
{
return playing && queued >= 0
@ -103,7 +102,7 @@ playlist::GetQueuedSong() const
}
void
playlist::UpdateQueuedSong(player_control &pc, const song *prev)
playlist::UpdateQueuedSong(player_control &pc, const Song *prev)
{
if (!playing)
return;
@ -130,7 +129,7 @@ playlist::UpdateQueuedSong(player_control &pc, const song *prev)
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)
: nullptr;
@ -154,9 +153,9 @@ playlist::PlayOrder(player_control &pc, int order)
playing = true;
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_free(uri);
@ -177,7 +176,7 @@ playlist::SyncWithPlayer(player_control &pc)
pc.Lock();
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();
if (pc_state == PLAYER_STATE_STOP)
@ -290,7 +289,7 @@ playlist::SetRandom(player_control &pc, bool status)
if (status == queue.random)
return;
const struct song *const queued_song = GetQueuedSong();
const Song *const queued_song = GetQueuedSong();
queue.random = status;

View File

@ -26,6 +26,7 @@
#include <stdbool.h>
struct player_control;
struct Song;
struct playlist {
/**
@ -99,7 +100,7 @@ struct playlist {
* none if there is none (yet?) or if MPD isn't playing.
*/
gcc_pure
const struct song *GetQueuedSong() const;
const Song *GetQueuedSong() const;
/**
* 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
* determined by playlist_get_queued_song()
*/
void UpdateQueuedSong(player_control &pc, const song *prev);
void UpdateQueuedSong(player_control &pc, const Song *prev);
public:
void Clear(player_control &pc);
@ -134,7 +135,7 @@ public:
void FullIncrementVersions();
enum playlist_result AppendSong(player_control &pc,
struct song *song,
Song *song,
unsigned *added_id=nullptr);
/**
@ -153,7 +154,7 @@ public:
protected:
void DeleteInternal(player_control &pc,
unsigned song, const struct song **queued_p);
unsigned song, const Song **queued_p);
public:
enum playlist_result DeletePosition(player_control &pc,
@ -175,7 +176,7 @@ public:
enum playlist_result DeleteRange(player_control &pc,
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);

View File

@ -25,7 +25,7 @@
#include "config.h"
#include "Playlist.hxx"
#include "PlayerControl.hxx"
#include "song.h"
#include "Song.hxx"
#include <glib.h>
@ -198,7 +198,7 @@ playlist::SeekSongPosition(player_control &pc, unsigned song, float seek_time)
if (!queue.IsValidPosition(song))
return PLAYLIST_RESULT_BAD_RANGE;
const struct song *queued_song = GetQueuedSong();
const Song *queued_song = GetQueuedSong();
unsigned i = queue.random
? queue.PositionToOrder(song)
@ -218,7 +218,7 @@ playlist::SeekSongPosition(player_control &pc, unsigned song, float seek_time)
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)) {
UpdateQueuedSong(pc, queued_song);

View File

@ -27,11 +27,7 @@
#include "Playlist.hxx"
#include "PlayerControl.hxx"
#include "util/UriUtil.hxx"
extern "C" {
#include "song.h"
}
#include "Song.hxx"
#include "Idle.hxx"
#include "DatabaseGlue.hxx"
#include "DatabasePlugin.hxx"
@ -61,7 +57,7 @@ enum playlist_result
playlist::AppendFile(struct player_control &pc,
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)
return PLAYLIST_RESULT_NO_SUCH_SONG;
@ -70,14 +66,14 @@ playlist::AppendFile(struct player_control &pc,
enum playlist_result
playlist::AppendSong(struct player_control &pc,
struct song *song, unsigned *added_id)
Song *song, unsigned *added_id)
{
unsigned id;
if (queue.IsFull())
return PLAYLIST_RESULT_TOO_LARGE;
const struct song *const queued_song = GetQueuedSong();
const Song *const queued_song = GetQueuedSong();
id = queue.Append(song, 0);
@ -110,9 +106,9 @@ playlist::AppendURI(struct player_control &pc,
g_debug("add to playlist: %s", uri);
const Database *db = nullptr;
struct song *song;
Song *song;
if (uri_has_scheme(uri)) {
song = song_remote_new(uri);
song = Song::NewRemote(uri);
} else {
db = GetDatabase(nullptr);
if (db == nullptr)
@ -136,7 +132,7 @@ playlist::SwapPositions(player_control &pc, unsigned song1, unsigned song2)
if (!queue.IsValidPosition(song1) || !queue.IsValidPosition(song2))
return PLAYLIST_RESULT_BAD_RANGE;
const struct song *const queued_song = GetQueuedSong();
const Song *const queued_song = GetQueuedSong();
queue.SwapPositions(song1, song2);
@ -190,7 +186,7 @@ playlist::SetPriorityRange(player_control &pc,
/* remember "current" and "queued" */
const int current_position = GetCurrentPosition();
const struct song *const queued_song = GetQueuedSong();
const Song *const queued_song = GetQueuedSong();
/* apply the priority changes */
@ -222,7 +218,7 @@ playlist::SetPriorityId(struct player_control &pc,
void
playlist::DeleteInternal(player_control &pc,
unsigned song, const struct song **queued_p)
unsigned song, const Song **queued_p)
{
assert(song < GetLength());
@ -272,7 +268,7 @@ playlist::DeletePosition(struct player_control &pc, unsigned song)
if (song >= queue.GetLength())
return PLAYLIST_RESULT_BAD_RANGE;
const struct song *queued_song = GetQueuedSong();
const Song *queued_song = GetQueuedSong();
DeleteInternal(pc, song, &queued_song);
@ -294,7 +290,7 @@ playlist::DeleteRange(struct player_control &pc, unsigned start, unsigned end)
if (start >= end)
return PLAYLIST_RESULT_SUCCESS;
const struct song *queued_song = GetQueuedSong();
const Song *queued_song = GetQueuedSong();
do {
DeleteInternal(pc, --end, &queued_song);
@ -317,7 +313,7 @@ playlist::DeleteId(struct player_control &pc, unsigned id)
}
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)
// TODO: compare URI instead of pointer
@ -339,7 +335,7 @@ playlist::MoveRange(player_control &pc, unsigned start, unsigned end, int to)
/* nothing happens */
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
@ -394,7 +390,7 @@ playlist::Shuffle(player_control &pc, unsigned start, unsigned end)
/* needs at least two entries. */
return;
const struct song *const queued_song = GetQueuedSong();
const Song *const queued_song = GetQueuedSong();
if (playing && current >= 0) {
unsigned current_position = queue.OrderToPosition(current);

View File

@ -24,7 +24,7 @@
#include "PlaylistVector.hxx"
#include "DatabasePlugin.hxx"
#include "DatabaseGlue.hxx"
#include "song.h"
#include "Song.hxx"
#include "io_error.h"
#include "Mapper.hxx"
#include "TextFile.hxx"
@ -360,7 +360,7 @@ spl_remove_index(const char *utf8path, unsigned pos, GError **error_r)
}
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())
return false;
@ -402,16 +402,16 @@ bool
spl_append_uri(const char *url, const char *utf8file, GError **error_r)
{
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);
song_free(song);
song->Free();
return success;
} else {
const Database *db = GetDatabase(error_r);
if (db == nullptr)
return false;
song *song = db->GetSong(url, error_r);
Song *song = db->GetSong(url, error_r);
if (song == nullptr)
return false;

View File

@ -25,7 +25,7 @@
#include <vector>
#include <string>
struct song;
struct Song;
struct PlaylistInfo;
class PlaylistVector;
@ -72,7 +72,7 @@ bool
spl_remove_index(const char *utf8path, unsigned pos, GError **error_r);
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
spl_append_uri(const char *file, const char *utf8file, GError **error_r);

View File

@ -28,6 +28,7 @@
struct config_param;
struct input_stream;
struct tag;
struct Song;
/**
* An object which provides the contents of a playlist.
@ -78,7 +79,7 @@ struct playlist_plugin {
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*suffixes;
@ -132,7 +133,7 @@ playlist_plugin_close(struct playlist_provider *playlist)
playlist->plugin->close(playlist);
}
static inline struct song *
static inline Song *
playlist_plugin_read(struct playlist_provider *playlist)
{
return playlist->plugin->read(playlist);

View File

@ -31,10 +31,7 @@
#include "DatabasePlugin.hxx"
#include "Client.hxx"
#include "input_stream.h"
extern "C" {
#include "song.h"
}
#include "Song.hxx"
void
playlist_print_uris(Client *client, const struct playlist *playlist)
@ -119,7 +116,7 @@ PrintSongDetails(Client *client, const char *uri_utf8)
if (db == nullptr)
return false;
song *song = db->GetSong(uri_utf8, nullptr);
Song *song = db->GetSong(uri_utf8, nullptr);
if (song == nullptr)
return false;
@ -152,7 +149,7 @@ static void
playlist_provider_print(Client *client, const char *uri,
struct playlist_provider *playlist, bool detail)
{
struct song *song;
Song *song;
char *base_uri = uri != NULL ? g_path_get_dirname(uri) : NULL;
while ((song = playlist_plugin_read(playlist)) != NULL) {
@ -165,7 +162,7 @@ playlist_provider_print(Client *client, const char *uri,
else
song_print_uri(client, song);
song_free(song);
song->Free();
}
g_free(base_uri);

View File

@ -24,10 +24,7 @@
#include "PlaylistSong.hxx"
#include "Playlist.hxx"
#include "input_stream.h"
extern "C" {
#include "song.h"
}
#include "Song.hxx"
enum playlist_result
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)
{
enum playlist_result result;
struct song *song;
Song *song;
char *base_uri = uri != NULL ? g_path_get_dirname(uri) : NULL;
for (unsigned i = 0;
@ -44,7 +41,7 @@ playlist_load_into_queue(const char *uri, struct playlist_provider *source,
++i) {
if (i < start_index) {
/* skip songs before the start index */
song_free(song);
song->Free();
continue;
}
@ -53,7 +50,7 @@ playlist_load_into_queue(const char *uri, struct playlist_provider *source,
continue;
result = dest->AppendSong(*pc, song);
song_free(song);
song->Free();
if (result != PLAYLIST_RESULT_SUCCESS) {
g_free(base_uri);
return result;

View File

@ -21,7 +21,7 @@
#include "PlaylistSave.hxx"
#include "PlaylistFile.hxx"
#include "Playlist.hxx"
#include "song.h"
#include "Song.hxx"
#include "Mapper.hxx"
#include "Idle.hxx"
#include "fs/Path.hxx"
@ -31,14 +31,14 @@
#include <glib.h>
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);
if (!path.IsNull())
fprintf(file, "%s\n", path.c_str());
} else {
char *uri = song_get_uri(song);
char *uri = song->GetURI();
const Path uri_fs = Path::FromUTF8(uri);
g_free(uri);

View File

@ -24,13 +24,13 @@
#include <stdio.h>
struct song;
struct Song;
struct queue;
struct playlist;
struct player_control;
void
playlist_print_song(FILE *fp, const struct song *song);
playlist_print_song(FILE *fp, const Song *song);
void
playlist_print_uri(FILE *fp, const char *uri);

View File

@ -26,10 +26,7 @@
#include "tag.h"
#include "fs/Path.hxx"
#include "util/UriUtil.hxx"
extern "C" {
#include "song.h"
}
#include "Song.hxx"
#include <glib.h>
@ -37,8 +34,8 @@ extern "C" {
#include <string.h>
static void
merge_song_metadata(struct song *dest, const struct song *base,
const struct song *add)
merge_song_metadata(Song *dest, const Song *base,
const Song *add)
{
dest->tag = base->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;
}
static struct song *
apply_song_metadata(struct song *dest, const struct song *src)
static Song *
apply_song_metadata(Song *dest, const Song *src)
{
struct song *tmp;
Song *tmp;
assert(dest != 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)
return dest;
if (song_in_database(dest)) {
if (dest->IsInDatabase()) {
const Path &path_fs = map_song_fs(dest);
if (path_fs.IsNull())
return dest;
@ -73,11 +70,11 @@ apply_song_metadata(struct song *dest, const struct song *src)
if (path_utf8.empty())
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);
} else {
tmp = song_file_new(dest->uri, NULL);
tmp = Song::NewFile(dest->uri, NULL);
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 */
tmp->tag->time = dest->tag->time - src->start_ms / 1000;
song_free(dest);
dest->Free();
return tmp;
}
static struct song *
playlist_check_load_song(const struct song *song, const char *uri, bool secure)
static Song *
playlist_check_load_song(const Song *song, const char *uri, bool secure)
{
struct song *dest;
Song *dest;
if (uri_has_scheme(uri)) {
dest = song_remote_new(uri);
dest = Song::NewRemote(uri);
} else if (g_path_is_absolute(uri) && secure) {
dest = song_file_load(uri, NULL);
dest = Song::LoadFile(uri, nullptr);
if (dest == NULL)
return NULL;
} else {
@ -109,23 +106,23 @@ playlist_check_load_song(const struct song *song, const char *uri, bool secure)
if (db == nullptr)
return nullptr;
struct song *tmp = db->GetSong(uri, nullptr);
Song *tmp = db->GetSong(uri, nullptr);
if (tmp == NULL)
/* not found in database */
return NULL;
dest = song_dup_detached(tmp);
dest = tmp->DupDetached();
db->ReturnSong(tmp);
}
return apply_song_metadata(dest, song);
}
struct song *
playlist_check_translate_song(struct song *song, const char *base_uri,
Song *
playlist_check_translate_song(Song *song, const char *base_uri,
bool secure)
{
if (song_in_database(song))
if (song->IsInDatabase())
/* already ok */
return song;
@ -137,7 +134,7 @@ playlist_check_translate_song(struct song *song, const char *base_uri,
return song;
else {
/* unsupported remote song */
song_free(song);
song->Free();
return NULL;
}
}
@ -159,7 +156,7 @@ playlist_check_translate_song(struct song *song, const char *base_uri,
else if (!secure) {
/* local files must be relative to the music
directory when "secure" is enabled */
song_free(song);
song->Free();
return NULL;
}
@ -170,8 +167,8 @@ playlist_check_translate_song(struct song *song, const char *base_uri,
if (base_uri != NULL)
uri = allocated = g_build_filename(base_uri, uri, NULL);
struct song *dest = playlist_check_load_song(song, uri, secure);
song_free(song);
Song *dest = playlist_check_load_song(song, uri, secure);
song->Free();
g_free(allocated);
return dest;
}

View File

@ -20,6 +20,8 @@
#ifndef MPD_PLAYLIST_SONG_HXX
#define MPD_PLAYLIST_SONG_HXX
struct Song;
/**
* 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
@ -28,8 +30,8 @@
* @param secure if true, then local files are only allowed if they
* are relative to base_uri
*/
struct song *
playlist_check_translate_song(struct song *song, const char *base_uri,
Song *
playlist_check_translate_song(Song *song, const char *base_uri,
bool secure);
#endif

View File

@ -19,7 +19,7 @@
#include "config.h"
#include "Queue.hxx"
#include "song.h"
#include "Song.hxx"
#include <stdlib.h>
@ -97,7 +97,7 @@ queue::ModifyAll()
}
unsigned
queue::Append(struct song *song, uint8_t priority)
queue::Append(Song *song, uint8_t priority)
{
assert(!IsFull());
@ -105,7 +105,7 @@ queue::Append(struct song *song, uint8_t priority)
const unsigned id = id_table.Insert(position);
auto &item = items[position];
item.song = song_dup_detached(song);
item.song = song->DupDetached();
item.id = id;
item.version = version;
item.priority = priority;
@ -232,9 +232,9 @@ queue::DeletePosition(unsigned position)
{
assert(position < length);
struct song *song = Get(position);
assert(!song_in_database(song) || song_is_detached(song));
song_free(song);
Song *song = Get(position);
assert(!song->IsInDatabase() || song->IsDetached());
song->Free();
const unsigned id = PositionToId(position);
const unsigned _order = PositionToOrder(position);
@ -268,9 +268,9 @@ queue::Clear()
for (unsigned i = 0; i < length; i++) {
Item *item = &items[i];
assert(!song_in_database(item->song) ||
song_is_detached(item->song));
song_free(item->song);
assert(!item->song->IsInDatabase() ||
item->song->IsDetached());
item->song->Free();
id_table.Erase(item->id);
}

View File

@ -29,6 +29,8 @@
#include <assert.h>
#include <stdint.h>
struct Song;
/**
* A queue of songs. This is the backend of the playlist: it contains
* an ordered list of songs.
@ -51,7 +53,7 @@ struct queue {
* information attached.
*/
struct Item {
struct song *song;
Song *song;
/** the unique id of this item in the queue */
unsigned id;
@ -198,7 +200,7 @@ struct queue {
/**
* Returns the song at the specified position.
*/
struct song *Get(unsigned position) const {
Song *Get(unsigned position) const {
assert(position < length);
return items[position].song;
@ -207,7 +209,7 @@ struct queue {
/**
* Returns the song at the specified order number.
*/
struct song *GetOrder(unsigned _order) const {
Song *GetOrder(unsigned _order) const {
return Get(OrderToPosition(_order));
}
@ -254,11 +256,12 @@ struct queue {
* that, the caller must check if the queue is already full.
*
* 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
*/
unsigned Append(struct song *song, uint8_t priority);
unsigned Append(Song *song, uint8_t priority);
/**
* Swaps two songs, addressed by their position.

View File

@ -26,7 +26,7 @@
#include "Client.hxx"
extern "C" {
#include "song.h"
#include "Song.hxx"
}
/**
@ -99,7 +99,7 @@ queue_find(Client *client, const struct queue *queue,
const SongFilter &filter)
{
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))
queue_print_song_info(client, queue, i);

View File

@ -20,7 +20,7 @@
#include "config.h"
#include "QueueSave.hxx"
#include "Playlist.hxx"
#include "song.h"
#include "Song.hxx"
#include "SongSave.hxx"
#include "DatabasePlugin.hxx"
#include "DatabaseGlue.hxx"
@ -32,24 +32,24 @@
#define PRIO_LABEL "Prio: "
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);
g_free(uri);
}
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);
}
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);
else
queue_save_full_song(fp, song);
@ -83,7 +83,7 @@ queue_load_song(TextFile &file, const char *line, queue *queue)
}
const Database *db = nullptr;
struct song *song;
Song *song;
if (g_str_has_prefix(line, SONG_BEGIN)) {
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;
if (uri_has_scheme(uri)) {
song = song_remote_new(uri);
song = Song::NewRemote(uri);
} else {
db = GetDatabase(nullptr);
if (db == nullptr)

View File

@ -18,7 +18,7 @@
*/
#include "config.h"
#include "song.h"
#include "Song.hxx"
#include "Directory.hxx"
#include "tag.h"
@ -28,7 +28,7 @@
Directory detached_root;
static struct song *
static Song *
song_alloc(const char *uri, Directory *parent)
{
size_t uri_length;
@ -37,7 +37,7 @@ song_alloc(const char *uri, Directory *parent)
uri_length = strlen(uri);
assert(uri_length);
struct song *song = (struct song *)
Song *song = (Song *)
g_malloc(sizeof(*song) - sizeof(song->uri) + uri_length + 1);
song->tag = nullptr;
@ -49,67 +49,65 @@ song_alloc(const char *uri, Directory *parent)
return song;
}
struct song *
song_remote_new(const char *uri)
Song *
Song::NewRemote(const char *uri)
{
return song_alloc(uri, nullptr);
}
struct song *
song_file_new(const char *path, Directory *parent)
Song *
Song::NewFile(const char *path, Directory *parent)
{
assert((parent == nullptr) == (*path == '/'));
return song_alloc(path, parent);
}
struct song *
song_replace_uri(struct song *old_song, const char *uri)
Song *
Song::ReplaceURI(const char *new_uri)
{
struct song *new_song = song_alloc(uri, old_song->parent);
new_song->tag = old_song->tag;
new_song->mtime = old_song->mtime;
new_song->start_ms = old_song->start_ms;
new_song->end_ms = old_song->end_ms;
g_free(old_song);
Song *new_song = song_alloc(new_uri, parent);
new_song->tag = tag;
new_song->mtime = mtime;
new_song->start_ms = start_ms;
new_song->end_ms = end_ms;
g_free(this);
return new_song;
}
struct song *
song_detached_new(const char *uri)
Song *
Song::NewDetached(const char *uri)
{
assert(uri != nullptr);
return song_alloc(uri, &detached_root);
}
struct song *
song_dup_detached(const struct song *src)
Song *
Song::DupDetached() const
{
assert(src != nullptr);
struct song *song;
if (song_in_database(src)) {
char *uri = song_get_uri(src);
song = song_detached_new(uri);
g_free(uri);
Song *song;
if (IsInDatabase()) {
char *new_uri = GetURI();
song = NewDetached(new_uri);
g_free(new_uri);
} else
song = song_alloc(src->uri, nullptr);
song = song_alloc(uri, nullptr);
song->tag = tag_dup(src->tag);
song->mtime = src->mtime;
song->start_ms = src->start_ms;
song->end_ms = src->end_ms;
song->tag = tag_dup(tag);
song->mtime = mtime;
song->start_ms = start_ms;
song->end_ms = end_ms;
return song;
}
void
song_free(struct song *song)
Song::Free()
{
if (song->tag)
tag_free(song->tag);
g_free(song);
if (tag != nullptr)
tag_free(tag);
g_free(this);
}
gcc_pure
@ -130,7 +128,7 @@ directory_is_same(const Directory *a, const Directory *b)
}
bool
song_equals(const struct song *a, const struct song *b)
song_equals(const Song *a, const Song *b)
{
assert(a != 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)) {
/* must compare the full URI if one of the objects is
"detached" */
char *au = song_get_uri(a);
char *bu = song_get_uri(b);
char *au = a->GetURI();
char *bu = b->GetURI();
const bool result = strcmp(au, bu) == 0;
g_free(bu);
g_free(au);
@ -153,26 +151,25 @@ song_equals(const struct song *a, const struct song *b)
}
char *
song_get_uri(const struct song *song)
Song::GetURI() const
{
assert(song != nullptr);
assert(*song->uri);
assert(*uri);
if (!song_in_database(song) || song->parent->IsRoot())
return g_strdup(song->uri);
if (!IsInDatabase() || parent->IsRoot())
return g_strdup(uri);
else
return g_strconcat(song->parent->GetPath(),
"/", song->uri, nullptr);
return g_strconcat(parent->GetPath(),
"/", uri, nullptr);
}
double
song_get_duration(const struct song *song)
Song::GetDuration() const
{
if (song->end_ms > 0)
return (song->end_ms - song->start_ms) / 1000.0;
if (end_ms > 0)
return (end_ms - start_ms) / 1000.0;
if (song->tag == nullptr)
if (tag == nullptr)
return 0;
return song->tag->time - song->start_ms / 1000.0;
return tag->time - start_ms / 1000.0;
}

147
src/Song.hxx Normal file
View File

@ -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

View File

@ -19,7 +19,7 @@
#include "config.h"
#include "SongFilter.hxx"
#include "song.h"
#include "Song.hxx"
#include "tag.h"
#include <glib.h>
@ -107,10 +107,10 @@ SongFilter::Item::Match(const struct tag &_tag) const
}
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) {
char *uri = song_get_uri(&song);
char *uri = song.GetURI();
const bool result = StringMatch(uri);
g_free(uri);
@ -156,7 +156,7 @@ SongFilter::Parse(unsigned argc, char *argv[], bool fold_case)
}
bool
SongFilter::Match(const song &song) const
SongFilter::Match(const Song &song) const
{
for (const auto &i : items)
if (!i.Match(song))

View File

@ -31,7 +31,7 @@
struct tag;
struct tag_item;
struct song;
struct Song;
class SongFilter {
class Item {
@ -71,7 +71,7 @@ class SongFilter {
bool Match(const struct tag &tag) const;
gcc_pure
bool Match(const song &song) const;
bool Match(const Song &song) const;
};
std::list<Item> items;
@ -94,7 +94,7 @@ public:
bool Match(const tag &tag) const;
gcc_pure
bool Match(const song &song) const;
bool Match(const Song &song) const;
};
/**

View File

@ -20,15 +20,15 @@
#ifndef MPD_SONG_POINTER_HXX
#define MPD_SONG_POINTER_HXX
#include "song.h"
#include "Song.hxx"
#include <utility>
class SongPointer {
struct song *song;
Song *song;
public:
explicit SongPointer(struct song *_song)
explicit SongPointer(Song *_song)
:song(_song) {}
SongPointer(const SongPointer &) = delete;
@ -39,7 +39,7 @@ public:
~SongPointer() {
if (song != nullptr)
song_free(song);
song->Free();
}
SongPointer &operator=(const SongPointer &) = delete;
@ -49,11 +49,11 @@ public:
return *this;
}
operator const struct song *() const {
operator const Song *() const {
return song;
}
struct song *Steal() {
Song *Steal() {
auto result = song;
song = nullptr;
return result;

View File

@ -19,7 +19,7 @@
#include "config.h"
#include "SongPrint.hxx"
#include "song.h"
#include "Song.hxx"
#include "Directory.hxx"
#include "TimePrint.hxx"
#include "TagPrint.hxx"
@ -30,9 +30,9 @@
#include <glib.h>
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,
song->parent->GetPath(), song->uri);
} else {
@ -51,7 +51,7 @@ song_print_uri(Client *client, struct song *song)
}
void
song_print_info(Client *client, struct song *song)
song_print_info(Client *client, Song *song)
{
song_print_uri(client, song);

View File

@ -20,13 +20,13 @@
#ifndef MPD_SONG_PRINT_HXX
#define MPD_SONG_PRINT_HXX
struct song;
struct Song;
class Client;
void
song_print_info(Client *client, struct song *song);
song_print_info(Client *client, Song *song);
void
song_print_uri(Client *client, struct song *song);
song_print_uri(Client *client, Song *song);
#endif

View File

@ -19,7 +19,7 @@
#include "config.h"
#include "SongSave.hxx"
#include "song.h"
#include "Song.hxx"
#include "TagSave.hxx"
#include "Directory.hxx"
#include "TextFile.hxx"
@ -43,7 +43,7 @@ song_save_quark(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);
@ -59,13 +59,13 @@ song_save(FILE *fp, const struct song *song)
fprintf(fp, SONG_END "\n");
}
struct song *
Song *
song_load(TextFile &file, Directory *parent, const char *uri,
GError **error_r)
{
struct song *song = parent != NULL
? song_file_new(uri, parent)
: song_remote_new(uri);
Song *song = parent != NULL
? Song::NewFile(uri, parent)
: Song::NewRemote(uri);
char *line, *colon;
enum tag_type type;
const char *value;
@ -76,7 +76,7 @@ song_load(TextFile &file, Directory *parent, const char *uri,
if (colon == NULL || colon == line) {
if (song->tag != NULL)
tag_end_add(song->tag);
song_free(song);
song->Free();
g_set_error(error_r, song_save_quark(), 0,
"unknown line in db: %s", line);
@ -118,7 +118,7 @@ song_load(TextFile &file, Directory *parent, const char *uri,
} else {
if (song->tag != NULL)
tag_end_add(song->tag);
song_free(song);
song->Free();
g_set_error(error_r, song_save_quark(), 0,
"unknown line in db: %s", line);

View File

@ -26,12 +26,12 @@
#define SONG_BEGIN "song_begin: "
struct song;
struct Song;
struct Directory;
class TextFile;
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
@ -41,7 +41,7 @@ song_save(FILE *fp, const struct song *song);
* ignore errors
* @return true on success, false on error
*/
struct song *
Song *
song_load(TextFile &file, Directory *parent, const char *uri,
GError **error_r);

View File

@ -19,7 +19,7 @@
#include "config.h"
#include "SongSort.hxx"
#include "song.h"
#include "Song.hxx"
#include "util/list.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
song_cmp(G_GNUC_UNUSED void *priv, struct list_head *_a, struct list_head *_b)
{
const struct song *a = (const struct song *)_a;
const struct song *b = (const struct song *)_b;
const Song *a = (const Song *)_a;
const Song *b = (const Song *)_b;
int ret;
/* first sort by album */

View File

@ -20,7 +20,7 @@
#include "config.h"
#include "SongSticker.hxx"
#include "StickerDatabase.hxx"
#include "song.h"
#include "Song.hxx"
#include "Directory.hxx"
#include <glib.h>
@ -29,80 +29,66 @@
#include <string.h>
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_in_database(song));
assert(song->IsInDatabase());
uri = song_get_uri(song);
value = sticker_load_value("song", uri, name);
char *uri = song->GetURI();
char *value = sticker_load_value("song", uri, name);
g_free(uri);
return value;
}
bool
sticker_song_set_value(const struct song *song,
sticker_song_set_value(const Song *song,
const char *name, const char *value)
{
char *uri;
bool ret;
assert(song != NULL);
assert(song_in_database(song));
assert(song->IsInDatabase());
uri = song_get_uri(song);
ret = sticker_store_value("song", uri, name, value);
char *uri = song->GetURI();
bool ret = sticker_store_value("song", uri, name, value);
g_free(uri);
return ret;
}
bool
sticker_song_delete(const struct song *song)
sticker_song_delete(const Song *song)
{
char *uri;
bool ret;
assert(song != NULL);
assert(song_in_database(song));
assert(song->IsInDatabase());
uri = song_get_uri(song);
ret = sticker_delete("song", uri);
char *uri = song->GetURI();
bool ret = sticker_delete("song", uri);
g_free(uri);
return ret;
}
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_in_database(song));
assert(song->IsInDatabase());
uri = song_get_uri(song);
success = sticker_delete_value("song", uri, name);
char *uri = song->GetURI();
bool success = sticker_delete_value("song", uri, name);
g_free(uri);
return success;
}
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_in_database(song));
assert(song->IsInDatabase());
uri = song_get_uri(song);
sticker = sticker_load("song", uri);
char *uri = song->GetURI();
struct sticker *sticker = sticker_load("song", uri);
g_free(uri);
return sticker;
@ -113,7 +99,7 @@ struct sticker_song_find_data {
const char *base_uri;
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;
};
@ -128,14 +114,14 @@ sticker_song_find_cb(const char *uri, const char *value, void *user_data)
/* should not happen, ignore silently */
return;
song *song = data->directory->LookupSong(uri + data->base_uri_length);
Song *song = data->directory->LookupSong(uri + data->base_uri_length);
if (song != NULL)
data->func(song, value, data->user_data);
}
bool
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)
{

View File

@ -22,7 +22,7 @@
#include "gerror.h"
struct song;
struct Song;
struct Directory;
struct sticker;
@ -31,28 +31,28 @@ struct sticker;
* free the return value with g_free().
*/
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
* values.
*/
bool
sticker_song_set_value(const struct song *song,
sticker_song_set_value(const Song *song,
const char *name, const char *value);
/**
* Deletes a sticker from the database. All values are deleted.
*/
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
* exist.
*/
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.
@ -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
*/
struct sticker *
sticker_song_get(const struct song *song);
sticker_song_get(const Song *song);
/**
* Finds stickers with the specified name below the specified
@ -76,7 +76,7 @@ sticker_song_get(const struct song *song);
*/
bool
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);

View File

@ -18,11 +18,7 @@
*/
#include "config.h" /* must be first for large file support */
extern "C" {
#include "song.h"
}
#include "Song.hxx"
#include "util/UriUtil.hxx"
#include "Directory.hxx"
#include "Mapper.hxx"
@ -46,26 +42,26 @@ extern "C" {
#include <sys/stat.h>
#include <stdio.h>
struct song *
song_file_load(const char *path_utf8, Directory *parent)
Song *
Song::LoadFile(const char *path_utf8, Directory *parent)
{
struct song *song;
Song *song;
bool ret;
assert((parent == NULL) == g_path_is_absolute(path_utf8));
assert(!uri_has_scheme(path_utf8));
assert(strchr(path_utf8, '\n') == NULL);
song = song_file_new(path_utf8, parent);
song = NewFile(path_utf8, parent);
//in archive ?
if (parent != NULL && parent->device == DEVICE_INARCHIVE) {
ret = song_file_update_inarchive(song);
ret = song->UpdateFileInArchive();
} else {
ret = song_file_update(song);
ret = song->UpdateFile();
}
if (!ret) {
song_free(song);
song->Free();
return NULL;
}
@ -84,18 +80,18 @@ tag_scan_fallback(const char *path,
}
bool
song_file_update(struct song *song)
Song::UpdateFile()
{
const char *suffix;
const struct decoder_plugin *plugin;
struct stat st;
struct input_stream *is = NULL;
assert(song_is_file(song));
assert(IsFile());
/* check if there's a suffix and a plugin */
suffix = uri_get_suffix(song->uri);
suffix = uri_get_suffix(uri);
if (suffix == NULL)
return false;
@ -103,33 +99,33 @@ song_file_update(struct song *song)
if (plugin == NULL)
return false;
const Path path_fs = map_song_fs(song);
const Path path_fs = map_song_fs(this);
if (path_fs.IsNull())
return false;
if (song->tag != NULL) {
tag_free(song->tag);
song->tag = NULL;
if (tag != NULL) {
tag_free(tag);
tag = NULL;
}
if (!StatFile(path_fs, st) || !S_ISREG(st.st_mode)) {
return false;
}
song->mtime = st.st_mtime;
mtime = st.st_mtime;
Mutex mutex;
Cond cond;
do {
/* load file tag */
song->tag = tag_new();
tag = tag_new();
if (decoder_plugin_scan_file(plugin, path_fs.c_str(),
&full_tag_handler, song->tag))
&full_tag_handler, tag))
break;
tag_free(song->tag);
song->tag = NULL;
tag_free(tag);
tag = nullptr;
/* fall back to stream tag */
if (plugin->scan_stream != NULL) {
@ -143,14 +139,14 @@ song_file_update(struct song *song)
/* now try the stream_tag() method */
if (is != NULL) {
song->tag = tag_new();
tag = tag_new();
if (decoder_plugin_scan_stream(plugin, is,
&full_tag_handler,
song->tag))
tag))
break;
tag_free(song->tag);
song->tag = NULL;
tag_free(tag);
tag = nullptr;
input_stream_lock_seek(is, 0, SEEK_SET, NULL);
}
@ -162,24 +158,23 @@ song_file_update(struct song *song)
if (is != NULL)
input_stream_close(is);
if (song->tag != NULL && tag_is_empty(song->tag))
tag_scan_fallback(path_fs.c_str(), &full_tag_handler,
song->tag);
if (tag != nullptr && tag_is_empty(tag))
tag_scan_fallback(path_fs.c_str(), &full_tag_handler, tag);
return song->tag != NULL;
return tag != nullptr;
}
bool
song_file_update_inarchive(struct song *song)
Song::UpdateFileInArchive()
{
const char *suffix;
const struct decoder_plugin *plugin;
assert(song_is_file(song));
assert(IsFile());
/* check if there's a suffix and a plugin */
suffix = uri_get_suffix(song->uri);
suffix = uri_get_suffix(uri);
if (suffix == NULL)
return false;
@ -187,13 +182,13 @@ song_file_update_inarchive(struct song *song)
if (plugin == NULL)
return false;
if (song->tag != NULL)
tag_free(song->tag);
if (tag != nullptr)
tag_free(tag);
//accept every file that has music suffix
//because we don't support tag reading through
//input streams
song->tag = tag_new();
tag = tag_new();
return true;
}

View File

@ -38,7 +38,7 @@ struct sticker_song_find_data {
};
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)
{
struct sticker_song_find_data *data =
@ -58,7 +58,7 @@ handle_sticker_song(Client *client, int argc, char *argv[])
/* get song song_id key */
if (argc == 5 && strcmp(argv[1], "get") == 0) {
song *song = db->GetSong(argv[3], &error);
Song *song = db->GetSong(argv[3], &error);
if (song == nullptr)
return print_error(client, error);
@ -76,7 +76,7 @@ handle_sticker_song(Client *client, int argc, char *argv[])
return COMMAND_RETURN_OK;
/* list song song_id */
} 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)
return print_error(client, error);
@ -90,7 +90,7 @@ handle_sticker_song(Client *client, int argc, char *argv[])
return COMMAND_RETURN_OK;
/* set song song_id id key */
} 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)
return print_error(client, error);
@ -106,7 +106,7 @@ handle_sticker_song(Client *client, int argc, char *argv[])
/* delete song song_id [key] */
} else if ((argc == 4 || argc == 5) &&
strcmp(argv[1], "delete") == 0) {
song *song = db->GetSong(argv[3], &error);
Song *song = db->GetSong(argv[3], &error);
if (song == nullptr)
return print_error(client, error);

View File

@ -22,7 +22,7 @@
#include "TagInternal.hxx"
#include "TagPool.hxx"
#include "conf.h"
#include "song.h"
#include "Song.hxx"
#include "mpd_error.h"
#include <glib.h>

View File

@ -21,7 +21,7 @@
#include "TagPrint.hxx"
#include "tag.h"
#include "TagInternal.hxx"
#include "song.h"
#include "Song.hxx"
#include "Client.hxx"
void tag_print_types(Client *client)

View File

@ -21,7 +21,7 @@
#include "TagSave.hxx"
#include "tag.h"
#include "TagInternal.hxx"
#include "song.h"
#include "Song.hxx"
void tag_save(FILE *file, const struct tag *tag)
{

View File

@ -22,7 +22,7 @@
#include "UpdateInternal.hxx"
#include "DatabaseLock.hxx"
#include "Directory.hxx"
#include "song.h"
#include "Song.hxx"
#include "Mapper.hxx"
#include "fs/Path.hxx"
#include "ArchiveList.hxx"
@ -58,10 +58,10 @@ update_archive_tree(Directory *directory, const char *name)
//add file
db_lock();
struct song *song = directory->FindSong(name);
Song *song = directory->FindSong(name);
db_unlock();
if (song == NULL) {
song = song_file_load(name, directory);
song = Song::LoadFile(name, directory);
if (song != NULL) {
db_lock();
directory->AddSong(song);

View File

@ -23,7 +23,7 @@
#include "UpdateDatabase.hxx"
#include "DatabaseLock.hxx"
#include "Directory.hxx"
#include "song.h"
#include "Song.hxx"
#include "DecoderPlugin.hxx"
#include "Mapper.hxx"
#include "fs/Path.hxx"
@ -89,7 +89,7 @@ update_container_file(Directory *directory,
char *vtrack;
unsigned int tnum = 0;
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..
song->mtime = st->st_mtime;

View File

@ -22,14 +22,14 @@
#include "UpdateRemove.hxx"
#include "PlaylistVector.hxx"
#include "Directory.hxx"
#include "song.h"
#include "Song.hxx"
#include "DatabaseLock.hxx"
#include <glib.h>
#include <assert.h>
void
delete_song(Directory *dir, struct song *del)
delete_song(Directory *dir, Song *del)
{
assert(del->parent == dir);
@ -42,7 +42,7 @@ delete_song(Directory *dir, struct song *del)
update_remove_song(del);
/* finally, all possible references gone, free it */
song_free(del);
del->Free();
db_lock();
}
@ -60,7 +60,7 @@ clear_directory(Directory *directory)
directory_for_each_child_safe(child, n, directory)
delete_directory(child);
struct song *song, *ns;
Song *song, *ns;
directory_for_each_song_safe(song, ns, directory) {
assert(song->parent == directory);
delete_song(directory, song);
@ -90,7 +90,7 @@ delete_name_in(Directory *parent, const char *name)
modified = true;
}
struct song *song = parent->FindSong(name);
Song *song = parent->FindSong(name);
if (song != NULL) {
delete_song(parent, song);
modified = true;

View File

@ -23,13 +23,13 @@
#include "check.h"
struct Directory;
struct song;
struct Song;
/**
* Caller must lock the #db_mutex.
*/
void
delete_song(Directory *parent, struct song *song);
delete_song(Directory *parent, Song *song);
/**
* Recursively free a directory and all its contents.

View File

@ -24,7 +24,7 @@
#include "thread/Mutex.hxx"
#include "thread/Cond.hxx"
#include "song.h"
#include "Song.hxx"
#include "Main.hxx"
#include "Instance.hxx"
@ -37,7 +37,7 @@
#include <assert.h>
static const struct song *removed_song;
static const Song *removed_song;
static Mutex remove_mutex;
static Cond remove_cond;
@ -53,7 +53,7 @@ song_remove_event(void)
assert(removed_song != NULL);
uri = song_get_uri(removed_song);
uri = removed_song->GetURI();
g_message("removing %s", uri);
g_free(uri);
@ -79,7 +79,7 @@ update_remove_global_init(void)
}
void
update_remove_song(const struct song *song)
update_remove_song(const Song *song)
{
assert(removed_song == NULL);

View File

@ -22,7 +22,7 @@
#include "check.h"
struct song;
struct Song;
void
update_remove_global_init(void);
@ -33,6 +33,6 @@ update_remove_global_init(void);
* serialized access is implemented to avoid excessive locking.
*/
void
update_remove_song(const struct song *song);
update_remove_song(const Song *song);
#endif

View File

@ -25,7 +25,7 @@
#include "UpdateContainer.hxx"
#include "DatabaseLock.hxx"
#include "Directory.hxx"
#include "song.h"
#include "Song.hxx"
#include "DecoderPlugin.hxx"
#include "DecoderList.hxx"
@ -39,7 +39,7 @@ update_song_file2(Directory *directory,
const struct decoder_plugin *plugin)
{
db_lock();
struct song *song = directory->FindSong(name);
Song *song = directory->FindSong(name);
db_unlock();
if (!directory_child_access(directory, name, R_OK)) {
@ -68,7 +68,7 @@ update_song_file2(Directory *directory,
if (song == NULL) {
g_debug("reading %s/%s", directory->GetPath(), name);
song = song_file_load(name, directory);
song = Song::LoadFile(name, directory);
if (song == NULL) {
g_debug("ignoring unrecognized file %s/%s",
directory->GetPath(), name);
@ -85,7 +85,7 @@ update_song_file2(Directory *directory,
} else if (st->st_mtime != song->mtime || walk_discard) {
g_message("updating %s/%s",
directory->GetPath(), name);
if (!song_file_update(song)) {
if (!song->UpdateFile()) {
g_debug("deleting unrecognized file %s/%s",
directory->GetPath(), name);
db_lock();

View File

@ -26,7 +26,7 @@
#include "DatabaseLock.hxx"
#include "DatabaseSimple.hxx"
#include "Directory.hxx"
#include "song.h"
#include "Song.hxx"
#include "PlaylistVector.hxx"
#include "PlaylistRegistry.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) {
assert(song->parent == directory);
@ -138,7 +138,7 @@ purge_deleted_from_directory(Directory *directory)
modified = true;
}
struct song *song, *ns;
Song *song, *ns;
directory_for_each_song_safe(song, ns, directory) {
const Path path = map_song_fs(song);
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
with potentially the same name */
db_lock();
struct song *conflicting = parent->FindSong(name_utf8);
Song *conflicting = parent->FindSong(name_utf8);
if (conflicting)
delete_song(parent, conflicting);

View File

@ -20,7 +20,7 @@
#include "config.h"
#include "CueParser.hxx"
#include "util/StringUtil.hxx"
#include "song.h"
#include "Song.hxx"
#include "tag.h"
#include <glib.h>
@ -42,13 +42,13 @@ CueParser::~CueParser()
g_free(filename);
if (current != nullptr)
song_free(current);
current->Free();
if (previous != nullptr)
song_free(previous);
previous->Free();
if (finished != nullptr)
song_free(finished);
finished->Free();
}
static const char *
@ -250,7 +250,7 @@ CueParser::Feed2(char *p)
}
state = TRACK;
current = song_remote_new(filename);
current = Song::NewRemote(filename);
assert(current->tag == nullptr);
current->tag = tag_dup(tag);
tag_add_item(current->tag, TAG_TRACK, nr);
@ -304,7 +304,7 @@ CueParser::Finish()
end = true;
}
struct song *
Song *
CueParser::Get()
{
if (finished == nullptr && end) {
@ -316,7 +316,7 @@ CueParser::Get()
previous = nullptr;
}
struct song *song = finished;
Song *song = finished;
finished = nullptr;
return song;
}

View File

@ -23,6 +23,8 @@
#include "check.h"
#include "gcc.h"
struct Song;
class CueParser {
enum {
/**
@ -58,19 +60,19 @@ class CueParser {
/**
* The song currently being edited.
*/
struct song *current;
Song *current;
/**
* The previous song. It is remembered because its end_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
* the caller via cue_parser_get().
*/
struct song *finished;
Song *finished;
/**
* 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
* no song was finished at this time
*/
struct song *Get();
Song *Get();
private:
gcc_pure

View File

@ -23,12 +23,12 @@
#include "DatabaseSelection.hxx"
#include "PlaylistVector.hxx"
#include "Directory.hxx"
#include "Song.hxx"
#include "gcc.h"
#include "conf.h"
extern "C" {
#include "db_error.h"
#include "song.h"
}
#undef MPD_DIRECTORY_H
@ -52,9 +52,9 @@ public:
virtual bool Open(GError **error_r) 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;
virtual void ReturnSong(struct song *song) const;
virtual void ReturnSong(Song *song) const;
virtual bool Visit(const DatabaseSelection &selection,
VisitDirectory visit_directory,
@ -181,10 +181,10 @@ ProxyDatabase::Close()
mpd_connection_free(connection);
}
static song *
static Song *
Convert(const struct mpd_song *song);
struct song *
Song *
ProxyDatabase::GetSong(const char *uri, GError **error_r) const
{
// TODO: implement
@ -196,13 +196,13 @@ ProxyDatabase::GetSong(const char *uri, GError **error_r) const
}
struct mpd_song *song = mpd_recv_song(connection);
struct song *song2 = song != nullptr
Song *song2 = song != nullptr
? Convert(song)
: nullptr;
mpd_song_free(song);
if (!mpd_response_finish(connection)) {
if (song2 != nullptr)
song_free(song2);
song2->Free();
CheckError(connection, error_r);
return nullptr;
@ -216,13 +216,13 @@ ProxyDatabase::GetSong(const char *uri, GError **error_r) const
}
void
ProxyDatabase::ReturnSong(struct song *song) const
ProxyDatabase::ReturnSong(Song *song) const
{
assert(song != nullptr);
assert(song_in_database(song));
assert(song_is_detached(song));
assert(song->IsInDatabase());
assert(song->IsDetached());
song_free(song);
song->Free();
}
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)
{
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->start_ms = mpd_song_get_start(song) * 1000;
@ -297,9 +297,9 @@ Visit(const struct mpd_song *song,
if (!visit_song)
return true;
struct song *s = Convert(song);
Song *s = Convert(song);
bool success = visit_song(*s, error_r);
song_free(s);
s->Free();
return success;
}

View File

@ -211,13 +211,13 @@ SimpleDatabase::Close()
root->Free();
}
struct song *
Song *
SimpleDatabase::GetSong(const char *uri, GError **error_r) const
{
assert(root != NULL);
db_lock();
song *song = root->LookupSong(uri);
Song *song = root->LookupSong(uri);
db_unlock();
if (song == NULL)
g_set_error(error_r, db_quark(), DB_NOT_FOUND,
@ -231,7 +231,7 @@ SimpleDatabase::GetSong(const char *uri, GError **error_r) const
}
void
SimpleDatabase::ReturnSong(gcc_unused struct song *song) const
SimpleDatabase::ReturnSong(gcc_unused Song *song) const
{
assert(song != nullptr);
@ -264,7 +264,7 @@ SimpleDatabase::Visit(const DatabaseSelection &selection,
const Directory *directory = root->LookupDirectory(selection.uri);
if (directory == NULL) {
if (visit_song) {
song *song = root->LookupSong(selection.uri);
Song *song = root->LookupSong(selection.uri);
if (song != nullptr)
return !selection.Match(*song) ||
visit_song(*song, error_r);

View File

@ -66,9 +66,9 @@ public:
virtual bool Open(GError **error_r) 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;
virtual void ReturnSong(struct song *song) const;
virtual void ReturnSong(Song *song) const;
virtual bool Visit(const DatabaseSelection &selection,
VisitDirectory visit_directory,

View File

@ -21,7 +21,7 @@
#include "AsxPlaylistPlugin.hxx"
#include "MemoryPlaylistProvider.hxx"
#include "input_stream.h"
#include "song.h"
#include "Song.hxx"
#include "tag.h"
#include <glib.h>
@ -60,7 +60,7 @@ struct AsxParser {
* The current song. It is allocated after the "location"
* element.
*/
struct song *song;
Song *song;
AsxParser()
:state(ROOT) {}
@ -91,7 +91,7 @@ asx_start_element(G_GNUC_UNUSED GMarkupParseContext *context,
case AsxParser::ROOT:
if (g_ascii_strcasecmp(element_name, "entry") == 0) {
parser->state = AsxParser::ENTRY;
parser->song = song_remote_new("asx:");
parser->song = Song::NewRemote("asx:");
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,
because that attribute is
immutable */
struct song *song = song_remote_new(href);
Song *song = Song::NewRemote(href);
if (parser->song != NULL) {
song->tag = parser->song->tag;
parser->song->tag = NULL;
song_free(parser->song);
parser->song->Free();
}
parser->song = song;
@ -145,7 +145,7 @@ asx_end_element(G_GNUC_UNUSED GMarkupParseContext *context,
if (strcmp(parser->song->uri, "asx:") != 0)
parser->songs.emplace_front(parser->song);
else
song_free(parser->song);
parser->song->Free();
parser->state = AsxParser::ROOT;
} else
@ -192,7 +192,7 @@ asx_parser_destroy(gpointer data)
AsxParser *parser = (AsxParser *)data;
if (parser->state >= AsxParser::ENTRY)
song_free(parser->song);
parser->song->Free();
}
/*

View File

@ -21,7 +21,7 @@
#include "CuePlaylistPlugin.hxx"
#include "PlaylistPlugin.hxx"
#include "tag.h"
#include "song.h"
#include "Song.hxx"
#include "input_stream.h"
#include "cue/CueParser.hxx"
#include "TextInputStream.hxx"
@ -63,12 +63,12 @@ cue_playlist_close(struct playlist_provider *_playlist)
delete playlist;
}
static struct song *
static Song *
cue_playlist_read(struct playlist_provider *_playlist)
{
CuePlaylist *playlist = (CuePlaylist *)_playlist;
struct song *song = playlist->parser.Get();
Song *song = playlist->parser.Get();
if (song != NULL)
return song;

View File

@ -22,7 +22,7 @@
#include "DespotifyUtils.hxx"
#include "MemoryPlaylistProvider.hxx"
#include "tag.h"
#include "song.h"
#include "Song.hxx"
extern "C" {
#include <despotify.h>
@ -37,7 +37,7 @@ static void
add_song(std::forward_list<SongPointer> &songs, struct ds_track *track)
{
const char *dsp_scheme = despotify_playlist_plugin.schemes[0];
struct song *song;
Song *song;
char uri[128];
char *ds_uri;
@ -51,7 +51,7 @@ add_song(std::forward_list<SongPointer> &songs, struct ds_track *track)
return;
}
song = song_remote_new(uri);
song = Song::NewRemote(uri);
song->tag = mpd_despotify_tag_from_track(track);
songs.emplace_front(song);

View File

@ -28,7 +28,7 @@
#include "PlaylistPlugin.hxx"
#include "tag.h"
#include "tag_handler.h"
#include "song.h"
#include "Song.hxx"
#include "TagFile.hxx"
#include "cue/CueParser.hxx"
@ -128,12 +128,12 @@ embcue_playlist_close(struct playlist_provider *_playlist)
g_free(playlist);
}
static struct song *
static Song *
embcue_playlist_read(struct playlist_provider *_playlist)
{
struct embcue_playlist *playlist = (struct embcue_playlist *)_playlist;
struct song *song = playlist->parser->Get();
Song *song = playlist->parser->Get();
if (song != NULL)
return song;
@ -152,13 +152,13 @@ embcue_playlist_read(struct playlist_provider *_playlist)
playlist->parser->Feed(line);
song = playlist->parser->Get();
if (song != NULL)
return song_replace_uri(song, playlist->filename);
return song->ReplaceURI(playlist->filename);
}
playlist->parser->Finish();
song = playlist->parser->Get();
if (song != NULL)
song = song_replace_uri(song, playlist->filename);
song = song->ReplaceURI(playlist->filename);
return song;
}

View File

@ -20,7 +20,7 @@
#include "config.h"
#include "ExtM3uPlaylistPlugin.hxx"
#include "PlaylistPlugin.hxx"
#include "song.h"
#include "Song.hxx"
#include "tag.h"
#include "util/StringUtil.hxx"
#include "TextInputStream.hxx"
@ -105,14 +105,14 @@ extm3u_parse_tag(const char *line)
return tag;
}
static struct song *
static Song *
extm3u_read(struct playlist_provider *_playlist)
{
ExtM3uPlaylist *playlist = (ExtM3uPlaylist *)_playlist;
struct tag *tag = NULL;
std::string line;
const char *line_s;
struct song *song;
Song *song;
do {
if (!playlist->tis->ReadLine(line)) {
@ -134,7 +134,7 @@ extm3u_read(struct playlist_provider *_playlist)
++line_s;
} while (line_s[0] == '#' || *line_s == 0);
song = song_remote_new(line_s);
song = Song::NewRemote(line_s);
song->tag = tag;
return song;
}

View File

@ -22,7 +22,7 @@
#include "PlaylistPlugin.hxx"
#include "PlaylistRegistry.hxx"
#include "conf.h"
#include "song.h"
#include "Song.hxx"
#include "input_stream.h"
#include <glib.h>
@ -268,7 +268,7 @@ lastfm_close(struct playlist_provider *_playlist)
g_free(playlist);
}
static struct song *
static Song *
lastfm_read(struct playlist_provider *_playlist)
{
struct lastfm_playlist *playlist = (struct lastfm_playlist *)_playlist;

View File

@ -20,7 +20,7 @@
#include "config.h"
#include "M3uPlaylistPlugin.hxx"
#include "PlaylistPlugin.hxx"
#include "song.h"
#include "Song.hxx"
#include "TextInputStream.hxx"
#include <glib.h>
@ -51,7 +51,7 @@ m3u_close(struct playlist_provider *_playlist)
g_free(playlist);
}
static struct song *
static Song *
m3u_read(struct playlist_provider *_playlist)
{
M3uPlaylist *playlist = (M3uPlaylist *)_playlist;
@ -68,7 +68,7 @@ m3u_read(struct playlist_provider *_playlist)
++line_s;
} while (line_s[0] == '#' || *line_s == 0);
return song_remote_new(line_s);
return Song::NewRemote(line_s);
}
static const char *const m3u_suffixes[] = {

View File

@ -19,7 +19,7 @@
#include "config.h"
#include "MemoryPlaylistProvider.hxx"
#include "song.h"
#include "Song.hxx"
static void
memory_playlist_close(struct playlist_provider *_playlist)
@ -29,7 +29,7 @@ memory_playlist_close(struct playlist_provider *_playlist)
delete playlist;
}
static struct song *
static Song *
memory_playlist_read(struct playlist_provider *_playlist)
{
MemoryPlaylistProvider *playlist = (MemoryPlaylistProvider *)_playlist;
@ -57,7 +57,7 @@ MemoryPlaylistProvider::MemoryPlaylistProvider(std::forward_list<SongPointer> &&
playlist_provider_init(this, &memory_playlist_plugin);
}
inline song *
inline Song *
MemoryPlaylistProvider::Read()
{
if (songs.empty())

View File

@ -25,7 +25,7 @@
#include <forward_list>
struct song;
struct Song;
class MemoryPlaylistProvider : public playlist_provider {
std::forward_list<SongPointer> songs;
@ -33,7 +33,7 @@ class MemoryPlaylistProvider : public playlist_provider {
public:
MemoryPlaylistProvider(std::forward_list<SongPointer> &&_songs);
song *Read();
Song *Read();
};
#endif

View File

@ -21,7 +21,7 @@
#include "PlsPlaylistPlugin.hxx"
#include "MemoryPlaylistProvider.hxx"
#include "input_stream.h"
#include "song.h"
#include "Song.hxx"
#include "tag.h"
#include <glib.h>
@ -50,7 +50,7 @@ pls_parser(GKeyFile *keyfile, std::forward_list<SongPointer> &songs)
}
while (num_entries > 0) {
struct song *song;
Song *song;
key = g_strdup_printf("File%i", num_entries);
value = g_key_file_get_string(keyfile, "playlist", key,
&error);
@ -62,7 +62,7 @@ pls_parser(GKeyFile *keyfile, std::forward_list<SongPointer> &songs)
}
g_free(key);
song = song_remote_new(value);
song = Song::NewRemote(value);
g_free(value);
key = g_strdup_printf("Title%i", num_entries);

View File

@ -21,7 +21,7 @@
#include "RssPlaylistPlugin.hxx"
#include "MemoryPlaylistProvider.hxx"
#include "input_stream.h"
#include "song.h"
#include "Song.hxx"
#include "tag.h"
#include <glib.h>
@ -60,7 +60,7 @@ struct RssParser {
* The current song. It is allocated after the "location"
* element.
*/
struct song *song;
Song *song;
RssParser()
:state(ROOT) {}
@ -90,7 +90,7 @@ rss_start_element(G_GNUC_UNUSED GMarkupParseContext *context,
case RssParser::ROOT:
if (g_ascii_strcasecmp(element_name, "item") == 0) {
parser->state = RssParser::ITEM;
parser->song = song_remote_new("rss:");
parser->song = Song::NewRemote("rss:");
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,
because that attribute is
immutable */
struct song *song = song_remote_new(href);
Song *song = Song::NewRemote(href);
if (parser->song != NULL) {
song->tag = parser->song->tag;
parser->song->tag = NULL;
song_free(parser->song);
parser->song->Free();
}
parser->song = song;
@ -142,7 +142,7 @@ rss_end_element(G_GNUC_UNUSED GMarkupParseContext *context,
if (strcmp(parser->song->uri, "rss:") != 0)
parser->songs.emplace_front(parser->song);
else
song_free(parser->song);
parser->song->Free();
parser->state = RssParser::ROOT;
} else
@ -189,7 +189,7 @@ rss_parser_destroy(gpointer data)
RssParser *parser = (RssParser *)data;
if (parser->state >= RssParser::ITEM)
song_free(parser->song);
parser->song->Free();
}
/*

View File

@ -22,7 +22,7 @@
#include "MemoryPlaylistProvider.hxx"
#include "conf.h"
#include "input_stream.h"
#include "song.h"
#include "Song.hxx"
#include "tag.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 */
data->got_url = 0;
struct song *s;
Song *s;
struct tag *t;
char *u;
u = g_strconcat(data->stream_url, "?client_id=", soundcloud_config.apikey, NULL);
s = song_remote_new(u);
s = Song::NewRemote(u);
g_free(u);
t = tag_new();
t->time = data->duration / 1000;

View File

@ -60,7 +60,7 @@ struct XspfParser {
* The current song. It is allocated after the "location"
* element.
*/
struct song *song;
Song *song;
XspfParser()
:state(ROOT) {}
@ -187,7 +187,7 @@ xspf_text(G_GNUC_UNUSED GMarkupParseContext *context,
case XspfParser::LOCATION:
if (parser->song == NULL) {
char *uri = g_strndup(text, text_len);
parser->song = song_remote_new(uri);
parser->song = Song::NewRemote(uri);
g_free(uri);
}
@ -209,7 +209,7 @@ xspf_parser_destroy(gpointer data)
XspfParser *parser = (XspfParser *)data;
if (parser->state >= XspfParser::TRACK && parser->song != NULL)
song_free(parser->song);
parser->song->Free();
}
/*

View File

@ -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

View File

@ -22,7 +22,7 @@
#include "DatabasePlugin.hxx"
#include "DatabaseSelection.hxx"
#include "Directory.hxx"
#include "song.h"
#include "Song.hxx"
#include "PlaylistVector.hxx"
#include "conf.h"
#include "tag.h"
@ -53,7 +53,7 @@ DumpDirectory(const Directory &directory, GError **)
}
static bool
DumpSong(song &song, GError **)
DumpSong(Song &song, GError **)
{
cout << "S " << song.parent->path << "/" << song.uri << endl;
return true;

View File

@ -18,7 +18,7 @@
*/
#include "config.h"
#include "song.h"
#include "Song.hxx"
#include "directory.h"
#include "gcc.h"
@ -26,8 +26,8 @@
struct directory detached_root;
struct song *
song_dup_detached(gcc_unused const struct song *src)
Song *
song_dup_detached(gcc_unused const Song *src)
{
abort();
}

View File

@ -19,7 +19,7 @@
#include "config.h"
#include "TagSave.hxx"
#include "song.h"
#include "Song.hxx"
#include "Directory.hxx"
#include "input_stream.h"
#include "conf.h"
@ -141,7 +141,7 @@ int main(int argc, char **argv)
struct input_stream *is = NULL;
GError *error = NULL;
struct playlist_provider *playlist;
struct song *song;
Song *song;
if (argc != 3) {
g_printerr("Usage: dump_playlist CONFIG URI\n");
@ -234,7 +234,7 @@ int main(int argc, char **argv)
if (song->tag != NULL)
tag_save(stdout, song->tag);
song_free(song);
song->Free();
}
/* deinitialize everything */

View File

@ -1,6 +1,6 @@
#include "config.h"
#include "Queue.hxx"
#include "song.h"
#include "Song.hxx"
#include "Directory.hxx"
#include <glib.h>
@ -10,14 +10,14 @@ Directory detached_root;
Directory::Directory() {}
Directory::~Directory() {}
struct song *
song_dup_detached(const struct song *src)
Song *
Song::DupDetached() const
{
return const_cast<song *>(src);
return const_cast<Song *>(this);
}
void
song_free(gcc_unused struct song *song)
Song::Free()
{
}
@ -50,7 +50,7 @@ check_descending_priority(const struct queue *queue,
int
main(gcc_unused int argc, gcc_unused char **argv)
{
static struct song songs[16];
static Song songs[16];
struct queue queue(32);