song: convert header to C++
This commit is contained in:
		| @@ -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 \ | ||||
|   | ||||
| @@ -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; | ||||
|  | ||||
|   | ||||
| @@ -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); | ||||
| } | ||||
|   | ||||
| @@ -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. | ||||
|   | ||||
| @@ -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); | ||||
|  | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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" | ||||
|   | ||||
| @@ -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); | ||||
| } | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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; | ||||
|  | ||||
|   | ||||
| @@ -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> | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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(); | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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)) | ||||
|   | ||||
| @@ -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. | ||||
|   | ||||
| @@ -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, | ||||
|   | ||||
| @@ -23,7 +23,7 @@ | ||||
| #include "Idle.hxx" | ||||
|  | ||||
| void | ||||
| Instance::DeleteSong(const song &song) | ||||
| Instance::DeleteSong(const Song &song) | ||||
| { | ||||
| 	partition->DeleteSong(song); | ||||
| } | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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; | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -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); | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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); | ||||
|  | ||||
|   | ||||
| @@ -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; | ||||
| 			} | ||||
|  | ||||
|   | ||||
| @@ -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; | ||||
|  | ||||
|   | ||||
| @@ -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); | ||||
|  | ||||
|   | ||||
| @@ -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); | ||||
|  | ||||
|   | ||||
| @@ -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); | ||||
|  | ||||
|   | ||||
| @@ -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; | ||||
|  | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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); | ||||
|  | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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; | ||||
| } | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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); | ||||
| 	} | ||||
|   | ||||
| @@ -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. | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
							
								
								
									
										97
									
								
								src/Song.cxx
									
									
									
									
									
								
							
							
						
						
									
										97
									
								
								src/Song.cxx
									
									
									
									
									
								
							| @@ -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
									
								
							
							
						
						
									
										147
									
								
								src/Song.hxx
									
									
									
									
									
										Normal 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 | ||||
| @@ -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)) | ||||
|   | ||||
| @@ -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; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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); | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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); | ||||
|  | ||||
|   | ||||
| @@ -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 */ | ||||
|   | ||||
| @@ -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) | ||||
| { | ||||
|   | ||||
| @@ -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); | ||||
|  | ||||
|   | ||||
| @@ -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; | ||||
| } | ||||
|   | ||||
| @@ -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); | ||||
|  | ||||
|   | ||||
| @@ -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> | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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) | ||||
| { | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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. | ||||
|   | ||||
| @@ -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); | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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(); | ||||
|   | ||||
| @@ -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); | ||||
|  | ||||
|   | ||||
| @@ -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; | ||||
| } | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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; | ||||
| } | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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, | ||||
|   | ||||
| @@ -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(); | ||||
| } | ||||
|  | ||||
| /* | ||||
|   | ||||
| @@ -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; | ||||
|  | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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; | ||||
| } | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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[] = { | ||||
|   | ||||
| @@ -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()) | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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(); | ||||
| } | ||||
|  | ||||
| /* | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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(); | ||||
| } | ||||
|  | ||||
| /* | ||||
|   | ||||
							
								
								
									
										167
									
								
								src/song.h
									
									
									
									
									
								
							
							
						
						
									
										167
									
								
								src/song.h
									
									
									
									
									
								
							| @@ -1,167 +0,0 @@ | ||||
| /* | ||||
|  * Copyright (C) 2003-2011 The Music Player Daemon Project | ||||
|  * http://www.musicpd.org | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation; either version 2 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License along | ||||
|  * with this program; if not, write to the Free Software Foundation, Inc., | ||||
|  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  */ | ||||
|  | ||||
| #ifndef MPD_SONG_H | ||||
| #define MPD_SONG_H | ||||
|  | ||||
| #include "util/list.h" | ||||
| #include "gcc.h" | ||||
|  | ||||
| #include <assert.h> | ||||
| #include <stddef.h> | ||||
| #include <stdbool.h> | ||||
| #include <sys/time.h> | ||||
|  | ||||
| #define SONG_FILE	"file: " | ||||
| #define SONG_TIME	"Time: " | ||||
|  | ||||
| struct song { | ||||
| 	/** | ||||
| 	 * Pointers to the siblings of this directory within the | ||||
| 	 * parent directory.  It is unused (undefined) if this song is | ||||
| 	 * not in the database. | ||||
| 	 * | ||||
| 	 * This attribute is protected with the global #db_mutex. | ||||
| 	 * Read access in the update thread does not need protection. | ||||
| 	 */ | ||||
| 	struct list_head siblings; | ||||
|  | ||||
| 	struct tag *tag; | ||||
| 	struct Directory *parent; | ||||
| 	time_t mtime; | ||||
|  | ||||
| 	/** | ||||
| 	 * Start of this sub-song within the file in milliseconds. | ||||
| 	 */ | ||||
| 	unsigned start_ms; | ||||
|  | ||||
| 	/** | ||||
| 	 * End of this sub-song within the file in milliseconds. | ||||
| 	 * Unused if zero. | ||||
| 	 */ | ||||
| 	unsigned end_ms; | ||||
|  | ||||
| 	char uri[sizeof(int)]; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * A dummy #directory instance that is used for "detached" song | ||||
|  * copies. | ||||
|  */ | ||||
| extern struct Directory detached_root; | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| /** allocate a new song with a remote URL */ | ||||
| struct song * | ||||
| song_remote_new(const char *uri); | ||||
|  | ||||
| /** allocate a new song with a local file name */ | ||||
| struct song * | ||||
| song_file_new(const char *path_utf8, struct Directory *parent); | ||||
|  | ||||
| /** | ||||
|  * allocate a new song structure with a local file name and attempt to | ||||
|  * load its metadata.  If all decoder plugin fail to read its meta | ||||
|  * data, NULL is returned. | ||||
|  */ | ||||
| struct song * | ||||
| song_file_load(const char *path_utf8, struct Directory *parent); | ||||
|  | ||||
| /** | ||||
|  * Replaces the URI of a song object.  The given song object is | ||||
|  * destroyed, and a newly allocated one is returned.  It does not | ||||
|  * update the reference within the parent directory; the caller is | ||||
|  * responsible for doing that. | ||||
|  */ | ||||
| struct song * | ||||
| song_replace_uri(struct song *song, const char *uri); | ||||
|  | ||||
| /** | ||||
|  * Creates a "detached" song object. | ||||
|  */ | ||||
| struct song * | ||||
| song_detached_new(const char *uri); | ||||
|  | ||||
| /** | ||||
|  * Creates a duplicate of the song object.  If the object is in the | ||||
|  * database, it creates a "detached" copy of this song, see | ||||
|  * song_is_detached(). | ||||
|  */ | ||||
| gcc_malloc | ||||
| struct song * | ||||
| song_dup_detached(const struct song *src); | ||||
|  | ||||
| void | ||||
| song_free(struct song *song); | ||||
|  | ||||
| static inline bool | ||||
| song_in_database(const struct song *song) | ||||
| { | ||||
| 	return song->parent != NULL; | ||||
| } | ||||
|  | ||||
| static inline bool | ||||
| song_is_file(const struct song *song) | ||||
| { | ||||
| 	return song_in_database(song) || song->uri[0] == '/'; | ||||
| } | ||||
|  | ||||
| static inline bool | ||||
| song_is_detached(const struct song *song) | ||||
| { | ||||
| 	assert(song != NULL); | ||||
| 	assert(song_in_database(song)); | ||||
|  | ||||
| 	return song->parent == &detached_root; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Returns true if both objects refer to the same physical song. | ||||
|  */ | ||||
| gcc_pure | ||||
| bool | ||||
| song_equals(const struct song *a, const struct song *b); | ||||
|  | ||||
| bool | ||||
| song_file_update(struct song *song); | ||||
|  | ||||
| bool | ||||
| song_file_update_inarchive(struct song *song); | ||||
|  | ||||
| /** | ||||
|  * Returns the URI of the song in UTF-8 encoding, including its | ||||
|  * location within the music directory. | ||||
|  * | ||||
|  * The return value is allocated on the heap, and must be freed by the | ||||
|  * caller. | ||||
|  */ | ||||
| char * | ||||
| song_get_uri(const struct song *song); | ||||
|  | ||||
| double | ||||
| song_get_duration(const struct song *song); | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #endif | ||||
| @@ -22,7 +22,7 @@ | ||||
| #include "DatabasePlugin.hxx" | ||||
| #include "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; | ||||
|   | ||||
| @@ -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(); | ||||
| } | ||||
|   | ||||
| @@ -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 */ | ||||
|   | ||||
| @@ -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); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Max Kellermann
					Max Kellermann