From 0c245bc2712f5d38507b8d421cdc0a7e002a3398 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 2 Jan 2013 22:52:08 +0100 Subject: Directory: make the header C++ only --- Makefile.am | 11 +- src/DatabaseGlue.cxx | 3 +- src/DatabasePrint.cxx | 3 +- src/DatabaseSave.cxx | 2 +- src/Directory.cxx | 2 +- src/Directory.hxx | 265 ++++++++++++++++++++++++++++++++++++++ src/DirectorySave.cxx | 2 +- src/Mapper.cxx | 2 +- src/OtherCommands.cxx | 2 +- src/Song.cxx | 2 +- src/SongPrint.cxx | 2 +- src/SongSave.cxx | 2 +- src/SongSticker.cxx | 2 +- src/SongUpdate.cxx | 2 +- src/UpdateArchive.cxx | 2 +- src/UpdateContainer.cxx | 2 +- src/UpdateDatabase.cxx | 2 +- src/UpdateIO.cxx | 2 +- src/UpdateSong.cxx | 2 +- src/UpdateWalk.cxx | 2 +- src/db/ProxyDatabasePlugin.cxx | 3 +- src/db/SimpleDatabasePlugin.cxx | 3 +- src/directory.h | 277 ---------------------------------------- test/DumpDatabase.cxx | 2 +- test/TestQueuePriority.cxx | 187 +++++++++++++++++++++++++++ test/test_queue_priority.c | 190 --------------------------- 26 files changed, 478 insertions(+), 498 deletions(-) create mode 100644 src/Directory.hxx delete mode 100644 src/directory.h create mode 100644 test/TestQueuePriority.cxx delete mode 100644 test/test_queue_priority.c diff --git a/Makefile.am b/Makefile.am index 67734ab85..0f6271aa5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -79,7 +79,6 @@ mpd_headers = \ src/decoder_api.h \ src/decoder_plugin.h \ src/decoder_internal.h \ - src/directory.h \ src/database.h \ src/encoder_plugin.h \ src/encoder_list.h \ @@ -223,7 +222,7 @@ src_mpd_SOURCES = \ src/decoder_api.c \ src/decoder_internal.c \ src/decoder_print.c \ - src/Directory.cxx \ + src/Directory.cxx src/Directory.hxx \ src/DirectorySave.cxx src/DirectorySave.hxx \ src/DatabaseGlue.cxx \ src/DatabasePrint.cxx src/DatabasePrint.hxx \ @@ -1021,7 +1020,7 @@ if ENABLE_TEST C_TESTS = \ test/test_byte_reverse \ test/test_pcm \ - test/test_queue_priority + test/TestQueuePriority TESTS = $(C_TESTS) @@ -1357,10 +1356,10 @@ test_test_pcm_LDADD = \ libutil.a \ $(GLIB_LIBS) -test_test_queue_priority_SOURCES = \ +test_TestQueuePriority_SOURCES = \ src/queue.c \ - test/test_queue_priority.c -test_test_queue_priority_LDADD = \ + test/TestQueuePriority.c +test_TestQueuePriority_LDADD = \ $(GLIB_LIBS) noinst_PROGRAMS += src/dsd2pcm/dsd2pcm diff --git a/src/DatabaseGlue.cxx b/src/DatabaseGlue.cxx index 88791879e..59b582873 100644 --- a/src/DatabaseGlue.cxx +++ b/src/DatabaseGlue.cxx @@ -21,6 +21,7 @@ #include "DatabaseGlue.hxx" #include "DatabaseRegistry.hxx" #include "DatabaseSave.hxx" +#include "Directory.hxx" extern "C" { #include "database.h" @@ -30,8 +31,6 @@ extern "C" { #include "glib_compat.h" } -#include "directory.h" - #include "DatabasePlugin.hxx" #include "db/SimpleDatabasePlugin.hxx" diff --git a/src/DatabasePrint.cxx b/src/DatabasePrint.cxx index 1e2842091..193b126cb 100644 --- a/src/DatabasePrint.cxx +++ b/src/DatabasePrint.cxx @@ -24,6 +24,7 @@ #include "PlaylistVector.hxx" #include "SongPrint.hxx" #include "TimePrint.hxx" +#include "Directory.hxx" extern "C" { #include "database.h" @@ -32,8 +33,6 @@ extern "C" { #include "tag.h" } -#include "directory.h" - #include "DatabaseGlue.hxx" #include "DatabasePlugin.hxx" diff --git a/src/DatabaseSave.cxx b/src/DatabaseSave.cxx index 771699848..32ae7441d 100644 --- a/src/DatabaseSave.cxx +++ b/src/DatabaseSave.cxx @@ -20,7 +20,7 @@ #include "config.h" #include "DatabaseSave.hxx" #include "DatabaseLock.hxx" -#include "directory.h" +#include "Directory.hxx" #include "DirectorySave.hxx" #include "song.h" diff --git a/src/Directory.cxx b/src/Directory.cxx index 84545e54f..f30eef725 100644 --- a/src/Directory.cxx +++ b/src/Directory.cxx @@ -18,7 +18,7 @@ */ #include "config.h" -#include "directory.h" +#include "Directory.hxx" #include "SongFilter.hxx" #include "PlaylistVector.hxx" #include "DatabaseLock.hxx" diff --git a/src/Directory.hxx b/src/Directory.hxx new file mode 100644 index 000000000..c1bb1ec38 --- /dev/null +++ b/src/Directory.hxx @@ -0,0 +1,265 @@ +/* + * 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_DIRECTORY_HXX +#define MPD_DIRECTORY_HXX + +#include "check.h" +#include "util/list.h" +#include "gcc.h" +#include "DatabaseVisitor.hxx" + +#include +#include +#include + +#define DEVICE_INARCHIVE (dev_t)(-1) +#define DEVICE_CONTAINER (dev_t)(-2) + +#define directory_for_each_child(pos, directory) \ + list_for_each_entry(pos, &directory->children, siblings) + +#define directory_for_each_child_safe(pos, n, directory) \ + list_for_each_entry_safe(pos, n, &directory->children, siblings) + +#define directory_for_each_song(pos, directory) \ + list_for_each_entry(pos, &directory->songs, siblings) + +#define directory_for_each_song_safe(pos, n, directory) \ + list_for_each_entry_safe(pos, n, &directory->songs, siblings) + +#define directory_for_each_playlist(pos, directory) \ + list_for_each_entry(pos, &directory->playlists, siblings) + +#define directory_for_each_playlist_safe(pos, n, directory) \ + list_for_each_entry_safe(pos, n, &directory->playlists, siblings) + +struct song; +struct db_visitor; +class SongFilter; + +struct directory { + /** + * Pointers to the siblings of this directory within the + * parent directory. It is unused (undefined) in the root + * directory. + * + * This attribute is protected with the global #db_mutex. + * Read access in the update thread does not need protection. + */ + struct list_head siblings; + + /** + * A doubly linked list of child directories. + * + * This attribute is protected with the global #db_mutex. + * Read access in the update thread does not need protection. + */ + struct list_head children; + + /** + * A doubly linked list of songs within this directory. + * + * This attribute is protected with the global #db_mutex. + * Read access in the update thread does not need protection. + */ + struct list_head songs; + + struct list_head playlists; + + struct directory *parent; + time_t mtime; + ino_t inode; + dev_t device; + bool have_stat; /* not needed if ino_t == dev_t == 0 is impossible */ + char path[sizeof(long)]; + + /** + * Caller must lock #db_mutex. + */ + bool Walk(bool recursive, const SongFilter *match, + VisitDirectory visit_directory, VisitSong visit_song, + VisitPlaylist visit_playlist, + GError **error_r) const; +}; + +static inline bool +isRootDirectory(const char *name) +{ + return name[0] == 0 || (name[0] == '/' && name[1] == 0); +} + +/** + * Generic constructor for #directory object. + */ +gcc_malloc +struct directory * +directory_new(const char *dirname, struct directory *parent); + +/** + * Create a new root #directory object. + */ +gcc_malloc +static inline struct directory * +directory_new_root(void) +{ + return directory_new("", NULL); +} + +/** + * Free this #directory object (and the whole object tree within it), + * assuming it was already removed from the parent. + */ +void +directory_free(struct directory *directory); + +/** + * Remove this #directory object from its parent and free it. This + * must not be called with the root directory. + * + * Caller must lock the #db_mutex. + */ +void +directory_delete(struct directory *directory); + +static inline bool +directory_is_empty(const struct directory *directory) +{ + return list_empty(&directory->children) && + list_empty(&directory->songs) && + list_empty(&directory->playlists); +} + +static inline const char * +directory_get_path(const struct directory *directory) +{ + return directory->path; +} + +/** + * Is this the root directory of the music database? + */ +static inline bool +directory_is_root(const struct directory *directory) +{ + return directory->parent == NULL; +} + +/** + * Returns the base name of the directory. + */ +gcc_pure +const char * +directory_get_name(const struct directory *directory); + +/** + * Caller must lock the #db_mutex. + */ +gcc_pure +struct directory * +directory_get_child(const struct directory *directory, const char *name); + +/** + * Create a new #directory object as a child of the given one. + * + * Caller must lock the #db_mutex. + * + * @param parent the parent directory the new one will be added to + * @param name_utf8 the UTF-8 encoded name of the new sub directory + */ +gcc_malloc +struct directory * +directory_new_child(struct directory *parent, const char *name_utf8); + +/** + * Look up a sub directory, and create the object if it does not + * exist. + * + * Caller must lock the #db_mutex. + */ +static inline struct directory * +directory_make_child(struct directory *directory, const char *name_utf8) +{ + struct directory *child = directory_get_child(directory, name_utf8); + if (child == NULL) + child = directory_new_child(directory, name_utf8); + return child; +} + +/** + * Caller must lock the #db_mutex. + */ +void +directory_prune_empty(struct directory *directory); + +/** + * Looks up a directory by its relative URI. + * + * @param directory the parent (or grandparent, ...) directory + * @param uri the relative URI + * @return the directory, or NULL if none was found + */ +struct directory * +directory_lookup_directory(struct directory *directory, const char *uri); + +/** + * Add a song object to this directory. Its "parent" attribute must + * be set already. + */ +void +directory_add_song(struct directory *directory, struct 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 +directory_remove_song(struct directory *directory, struct song *song); + +/** + * Look up a song in this directory by its name. + * + * Caller must lock the #db_mutex. + */ +gcc_pure +struct song * +directory_get_song(const struct directory *directory, const char *name_utf8); + +/** + * Looks up a song by its relative URI. + * + * Caller must lock the #db_mutex. + * + * @param directory the parent (or grandparent, ...) directory + * @param uri the relative URI + * @return the song, or NULL if none was found + */ +struct song * +directory_lookup_song(struct directory *directory, const char *uri); + +/** + * Sort all directory entries recursively. + * + * Caller must lock the #db_mutex. + */ +void +directory_sort(struct directory *directory); + +#endif diff --git a/src/DirectorySave.cxx b/src/DirectorySave.cxx index 83a1ffd5a..8e677e7d6 100644 --- a/src/DirectorySave.cxx +++ b/src/DirectorySave.cxx @@ -19,7 +19,7 @@ #include "config.h" #include "DirectorySave.hxx" -#include "directory.h" +#include "Directory.hxx" #include "song.h" #include "SongSave.hxx" #include "PlaylistDatabase.hxx" diff --git a/src/Mapper.cxx b/src/Mapper.cxx index 1dc91ed12..eda9c0b35 100644 --- a/src/Mapper.cxx +++ b/src/Mapper.cxx @@ -23,7 +23,7 @@ #include "config.h" #include "Mapper.hxx" -#include "directory.h" +#include "Directory.hxx" #include "song.h" extern "C" { diff --git a/src/OtherCommands.cxx b/src/OtherCommands.cxx index 01f9b71a4..a7a262495 100644 --- a/src/OtherCommands.cxx +++ b/src/OtherCommands.cxx @@ -22,7 +22,7 @@ #include "DatabaseCommands.hxx" #include "CommandError.hxx" #include "UpdateGlue.hxx" -#include "directory.h" +#include "Directory.hxx" #include "song.h" #include "SongPrint.hxx" #include "TagPrint.hxx" diff --git a/src/Song.cxx b/src/Song.cxx index eb4c2e53e..deefe3c21 100644 --- a/src/Song.cxx +++ b/src/Song.cxx @@ -19,7 +19,7 @@ #include "config.h" #include "song.h" -#include "directory.h" +#include "Directory.hxx" extern "C" { #include "tag.h" diff --git a/src/SongPrint.cxx b/src/SongPrint.cxx index 07cf9c3e2..957db76a3 100644 --- a/src/SongPrint.cxx +++ b/src/SongPrint.cxx @@ -20,7 +20,7 @@ #include "config.h" #include "SongPrint.hxx" #include "song.h" -#include "directory.h" +#include "Directory.hxx" #include "TimePrint.hxx" #include "TagPrint.hxx" #include "Mapper.hxx" diff --git a/src/SongSave.cxx b/src/SongSave.cxx index 21d073b86..d78eb3f78 100644 --- a/src/SongSave.cxx +++ b/src/SongSave.cxx @@ -21,7 +21,7 @@ #include "SongSave.hxx" #include "song.h" #include "TagSave.hxx" -#include "directory.h" +#include "Directory.hxx" extern "C" { #include "tag.h" diff --git a/src/SongSticker.cxx b/src/SongSticker.cxx index b32ef9d4b..2c311bfbb 100644 --- a/src/SongSticker.cxx +++ b/src/SongSticker.cxx @@ -21,7 +21,7 @@ #include "SongSticker.hxx" #include "StickerDatabase.hxx" #include "song.h" -#include "directory.h" +#include "Directory.hxx" #include diff --git a/src/SongUpdate.cxx b/src/SongUpdate.cxx index c5258f025..83937b99b 100644 --- a/src/SongUpdate.cxx +++ b/src/SongUpdate.cxx @@ -24,7 +24,7 @@ extern "C" { #include "uri.h" } -#include "directory.h" +#include "Directory.hxx" #include "Mapper.hxx" extern "C" { diff --git a/src/UpdateArchive.cxx b/src/UpdateArchive.cxx index 36f5cdc20..4a45f3756 100644 --- a/src/UpdateArchive.cxx +++ b/src/UpdateArchive.cxx @@ -21,7 +21,7 @@ #include "UpdateArchive.hxx" #include "UpdateInternal.hxx" #include "DatabaseLock.hxx" -#include "directory.h" +#include "Directory.hxx" #include "song.h" #include "Mapper.hxx" diff --git a/src/UpdateContainer.cxx b/src/UpdateContainer.cxx index 909295d98..d0e35299c 100644 --- a/src/UpdateContainer.cxx +++ b/src/UpdateContainer.cxx @@ -22,7 +22,7 @@ #include "UpdateInternal.hxx" #include "UpdateDatabase.hxx" #include "DatabaseLock.hxx" -#include "directory.h" +#include "Directory.hxx" #include "song.h" #include "decoder_plugin.h" #include "Mapper.hxx" diff --git a/src/UpdateDatabase.cxx b/src/UpdateDatabase.cxx index 6ef6e3429..4de18345c 100644 --- a/src/UpdateDatabase.cxx +++ b/src/UpdateDatabase.cxx @@ -21,7 +21,7 @@ #include "UpdateDatabase.hxx" #include "UpdateRemove.hxx" #include "PlaylistVector.hxx" -#include "directory.h" +#include "Directory.hxx" #include "song.h" #include "DatabaseLock.hxx" diff --git a/src/UpdateIO.cxx b/src/UpdateIO.cxx index 77ec30413..200a6136d 100644 --- a/src/UpdateIO.cxx +++ b/src/UpdateIO.cxx @@ -19,7 +19,7 @@ #include "config.h" /* must be first for large file support */ #include "UpdateIO.hxx" -#include "directory.h" +#include "Directory.hxx" #include "Mapper.hxx" #include "glib_compat.h" diff --git a/src/UpdateSong.cxx b/src/UpdateSong.cxx index 48357b9cd..96c5eefb4 100644 --- a/src/UpdateSong.cxx +++ b/src/UpdateSong.cxx @@ -24,7 +24,7 @@ #include "UpdateDatabase.hxx" #include "UpdateContainer.hxx" #include "DatabaseLock.hxx" -#include "directory.h" +#include "Directory.hxx" #include "song.h" #include "decoder_plugin.h" diff --git a/src/UpdateWalk.cxx b/src/UpdateWalk.cxx index b277f0477..91526fb6d 100644 --- a/src/UpdateWalk.cxx +++ b/src/UpdateWalk.cxx @@ -24,7 +24,7 @@ #include "UpdateSong.hxx" #include "UpdateArchive.hxx" #include "DatabaseLock.hxx" -#include "directory.h" +#include "Directory.hxx" #include "song.h" #include "PlaylistVector.hxx" #include "Mapper.hxx" diff --git a/src/db/ProxyDatabasePlugin.cxx b/src/db/ProxyDatabasePlugin.cxx index 01b36a6e3..95aefc14f 100644 --- a/src/db/ProxyDatabasePlugin.cxx +++ b/src/db/ProxyDatabasePlugin.cxx @@ -22,6 +22,7 @@ #include "DatabasePlugin.hxx" #include "DatabaseSelection.hxx" #include "PlaylistVector.hxx" +#include "Directory.hxx" #include "gcc.h" extern "C" { @@ -31,8 +32,6 @@ extern "C" { #include "tag.h" } -#include "directory.h" - #undef MPD_DIRECTORY_H #undef MPD_SONG_H #include diff --git a/src/db/SimpleDatabasePlugin.cxx b/src/db/SimpleDatabasePlugin.cxx index 85d707f52..06a92604f 100644 --- a/src/db/SimpleDatabasePlugin.cxx +++ b/src/db/SimpleDatabasePlugin.cxx @@ -21,6 +21,7 @@ #include "SimpleDatabasePlugin.hxx" #include "DatabaseSelection.hxx" #include "DatabaseHelpers.hxx" +#include "Directory.hxx" #include "SongFilter.hxx" #include "DatabaseSave.hxx" #include "DatabaseLock.hxx" @@ -30,8 +31,6 @@ extern "C" { #include "conf.h" } -#include "directory.h" - #include #include #include diff --git a/src/directory.h b/src/directory.h deleted file mode 100644 index 607e812cd..000000000 --- a/src/directory.h +++ /dev/null @@ -1,277 +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_DIRECTORY_H -#define MPD_DIRECTORY_H - -#include "check.h" -#include "util/list.h" -#include "gcc.h" - -#ifdef __cplusplus -#include "DatabaseVisitor.hxx" -#endif - -#include -#include -#include - -#define DEVICE_INARCHIVE (dev_t)(-1) -#define DEVICE_CONTAINER (dev_t)(-2) - -#define directory_for_each_child(pos, directory) \ - list_for_each_entry(pos, &directory->children, siblings) - -#define directory_for_each_child_safe(pos, n, directory) \ - list_for_each_entry_safe(pos, n, &directory->children, siblings) - -#define directory_for_each_song(pos, directory) \ - list_for_each_entry(pos, &directory->songs, siblings) - -#define directory_for_each_song_safe(pos, n, directory) \ - list_for_each_entry_safe(pos, n, &directory->songs, siblings) - -#define directory_for_each_playlist(pos, directory) \ - list_for_each_entry(pos, &directory->playlists, siblings) - -#define directory_for_each_playlist_safe(pos, n, directory) \ - list_for_each_entry_safe(pos, n, &directory->playlists, siblings) - -struct song; -struct db_visitor; - -#ifdef __cplusplus -class SongFilter; -#endif - -struct directory { - /** - * Pointers to the siblings of this directory within the - * parent directory. It is unused (undefined) in the root - * directory. - * - * This attribute is protected with the global #db_mutex. - * Read access in the update thread does not need protection. - */ - struct list_head siblings; - - /** - * A doubly linked list of child directories. - * - * This attribute is protected with the global #db_mutex. - * Read access in the update thread does not need protection. - */ - struct list_head children; - - /** - * A doubly linked list of songs within this directory. - * - * This attribute is protected with the global #db_mutex. - * Read access in the update thread does not need protection. - */ - struct list_head songs; - - struct list_head playlists; - - struct directory *parent; - time_t mtime; - ino_t inode; - dev_t device; - bool have_stat; /* not needed if ino_t == dev_t == 0 is impossible */ - char path[sizeof(long)]; - -#ifdef __cplusplus - /** - * Caller must lock #db_mutex. - */ - bool Walk(bool recursive, const SongFilter *match, - VisitDirectory visit_directory, VisitSong visit_song, - VisitPlaylist visit_playlist, - GError **error_r) const; -#endif -}; - -G_BEGIN_DECLS - -static inline bool -isRootDirectory(const char *name) -{ - return name[0] == 0 || (name[0] == '/' && name[1] == 0); -} - -/** - * Generic constructor for #directory object. - */ -gcc_malloc -struct directory * -directory_new(const char *dirname, struct directory *parent); - -/** - * Create a new root #directory object. - */ -gcc_malloc -static inline struct directory * -directory_new_root(void) -{ - return directory_new("", NULL); -} - -/** - * Free this #directory object (and the whole object tree within it), - * assuming it was already removed from the parent. - */ -void -directory_free(struct directory *directory); - -/** - * Remove this #directory object from its parent and free it. This - * must not be called with the root directory. - * - * Caller must lock the #db_mutex. - */ -void -directory_delete(struct directory *directory); - -static inline bool -directory_is_empty(const struct directory *directory) -{ - return list_empty(&directory->children) && - list_empty(&directory->songs) && - list_empty(&directory->playlists); -} - -static inline const char * -directory_get_path(const struct directory *directory) -{ - return directory->path; -} - -/** - * Is this the root directory of the music database? - */ -static inline bool -directory_is_root(const struct directory *directory) -{ - return directory->parent == NULL; -} - -/** - * Returns the base name of the directory. - */ -gcc_pure -const char * -directory_get_name(const struct directory *directory); - -/** - * Caller must lock the #db_mutex. - */ -gcc_pure -struct directory * -directory_get_child(const struct directory *directory, const char *name); - -/** - * Create a new #directory object as a child of the given one. - * - * Caller must lock the #db_mutex. - * - * @param parent the parent directory the new one will be added to - * @param name_utf8 the UTF-8 encoded name of the new sub directory - */ -gcc_malloc -struct directory * -directory_new_child(struct directory *parent, const char *name_utf8); - -/** - * Look up a sub directory, and create the object if it does not - * exist. - * - * Caller must lock the #db_mutex. - */ -static inline struct directory * -directory_make_child(struct directory *directory, const char *name_utf8) -{ - struct directory *child = directory_get_child(directory, name_utf8); - if (child == NULL) - child = directory_new_child(directory, name_utf8); - return child; -} - -/** - * Caller must lock the #db_mutex. - */ -void -directory_prune_empty(struct directory *directory); - -/** - * Looks up a directory by its relative URI. - * - * @param directory the parent (or grandparent, ...) directory - * @param uri the relative URI - * @return the directory, or NULL if none was found - */ -struct directory * -directory_lookup_directory(struct directory *directory, const char *uri); - -/** - * Add a song object to this directory. Its "parent" attribute must - * be set already. - */ -void -directory_add_song(struct directory *directory, struct 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 -directory_remove_song(struct directory *directory, struct song *song); - -/** - * Look up a song in this directory by its name. - * - * Caller must lock the #db_mutex. - */ -gcc_pure -struct song * -directory_get_song(const struct directory *directory, const char *name_utf8); - -/** - * Looks up a song by its relative URI. - * - * Caller must lock the #db_mutex. - * - * @param directory the parent (or grandparent, ...) directory - * @param uri the relative URI - * @return the song, or NULL if none was found - */ -struct song * -directory_lookup_song(struct directory *directory, const char *uri); - -/** - * Sort all directory entries recursively. - * - * Caller must lock the #db_mutex. - */ -void -directory_sort(struct directory *directory); - -G_END_DECLS - -#endif diff --git a/test/DumpDatabase.cxx b/test/DumpDatabase.cxx index fc42ba147..3a4e980b1 100644 --- a/test/DumpDatabase.cxx +++ b/test/DumpDatabase.cxx @@ -21,7 +21,7 @@ #include "DatabaseRegistry.hxx" #include "DatabasePlugin.hxx" #include "DatabaseSelection.hxx" -#include "directory.h" +#include "Directory.hxx" #include "song.h" #include "PlaylistVector.hxx" diff --git a/test/TestQueuePriority.cxx b/test/TestQueuePriority.cxx new file mode 100644 index 000000000..a046df524 --- /dev/null +++ b/test/TestQueuePriority.cxx @@ -0,0 +1,187 @@ +#include "config.h" +extern "C" { +#include "queue.h" +} +#include "song.h" +#include "Directory.hxx" + +struct directory detached_root; + +struct song * +song_dup_detached(const struct song *src) +{ + return const_cast(src); +} + +void +song_free(G_GNUC_UNUSED struct song *song) +{ +} + +G_GNUC_UNUSED +static void +dump_order(const struct queue *queue) +{ + g_printerr("queue length=%u, order:\n", queue_length(queue)); + for (unsigned i = 0; i < queue_length(queue); ++i) + g_printerr(" [%u] -> %u (prio=%u)\n", i, queue->order[i], + queue->items[queue->order[i]].priority); +} + +static void +check_descending_priority(G_GNUC_UNUSED const struct queue *queue, + unsigned start_order) +{ + assert(start_order < queue_length(queue)); + + uint8_t last_priority = 0xff; + for (unsigned order = start_order; order < queue_length(queue); ++order) { + unsigned position = queue_order_to_position(queue, order); + uint8_t priority = queue->items[position].priority; + assert(priority <= last_priority); + (void)last_priority; + last_priority = priority; + } +} + +int +main(G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv) +{ + struct song songs[16]; + + struct queue queue; + queue_init(&queue, 32); + + for (unsigned i = 0; i < G_N_ELEMENTS(songs); ++i) + queue_append(&queue, &songs[i], 0); + + assert(queue_length(&queue) == G_N_ELEMENTS(songs)); + + /* priority=10 for 4 items */ + + queue_set_priority_range(&queue, 4, 8, 10, -1); + + queue.random = true; + queue_shuffle_order(&queue); + check_descending_priority(&queue, 0); + + for (unsigned i = 0; i < 4; ++i) { + assert(queue_position_to_order(&queue, i) >= 4); + } + + for (unsigned i = 4; i < 8; ++i) { + assert(queue_position_to_order(&queue, i) < 4); + } + + for (unsigned i = 8; i < G_N_ELEMENTS(songs); ++i) { + assert(queue_position_to_order(&queue, i) >= 4); + } + + /* priority=50 one more item */ + + queue_set_priority_range(&queue, 15, 16, 50, -1); + check_descending_priority(&queue, 0); + + assert(queue_position_to_order(&queue, 15) == 0); + + for (unsigned i = 0; i < 4; ++i) { + assert(queue_position_to_order(&queue, i) >= 4); + } + + for (unsigned i = 4; i < 8; ++i) { + assert(queue_position_to_order(&queue, i) >= 1 && + queue_position_to_order(&queue, i) < 5); + } + + for (unsigned i = 8; i < 15; ++i) { + assert(queue_position_to_order(&queue, i) >= 5); + } + + /* priority=20 for one of the 4 priority=10 items */ + + queue_set_priority_range(&queue, 3, 4, 20, -1); + check_descending_priority(&queue, 0); + + assert(queue_position_to_order(&queue, 3) == 1); + assert(queue_position_to_order(&queue, 15) == 0); + + for (unsigned i = 0; i < 3; ++i) { + assert(queue_position_to_order(&queue, i) >= 5); + } + + for (unsigned i = 4; i < 8; ++i) { + assert(queue_position_to_order(&queue, i) >= 2 && + queue_position_to_order(&queue, i) < 6); + } + + for (unsigned i = 8; i < 15; ++i) { + assert(queue_position_to_order(&queue, i) >= 6); + } + + /* priority=20 for another one of the 4 priority=10 items; + pass "after_order" (with priority=10) and see if it's moved + after that one */ + + unsigned current_order = 4; + unsigned current_position = + queue_order_to_position(&queue, current_order); + + unsigned a_order = 3; + unsigned a_position = queue_order_to_position(&queue, a_order); + assert(queue.items[a_position].priority == 10); + queue_set_priority(&queue, a_position, 20, current_order); + + current_order = queue_position_to_order(&queue, current_position); + assert(current_order == 3); + + a_order = queue_position_to_order(&queue, a_position); + assert(a_order == 4); + + check_descending_priority(&queue, current_order + 1); + + /* priority=70 for one of the last items; must be inserted + right after the current song, before the priority=20 one we + just created */ + + unsigned b_order = 10; + unsigned b_position = queue_order_to_position(&queue, b_order); + assert(queue.items[b_position].priority == 0); + queue_set_priority(&queue, b_position, 70, current_order); + + current_order = queue_position_to_order(&queue, current_position); + assert(current_order == 3); + + b_order = queue_position_to_order(&queue, b_position); + assert(b_order == 4); + + check_descending_priority(&queue, current_order + 1); + + /* priority=60 for the old prio50 item; must not be moved, + because it's before the current song, and it's status + hasn't changed (it was already higher before) */ + + unsigned c_order = 0; + unsigned c_position = queue_order_to_position(&queue, c_order); + assert(queue.items[c_position].priority == 50); + queue_set_priority(&queue, c_position, 60, current_order); + + current_order = queue_position_to_order(&queue, current_position); + assert(current_order == 3); + + c_order = queue_position_to_order(&queue, c_position); + assert(c_order == 0); + + /* move the prio=20 item back */ + + a_order = queue_position_to_order(&queue, a_position); + assert(a_order == 5); + assert(queue.items[a_position].priority == 20); + queue_set_priority(&queue, a_position, 5, current_order); + + + current_order = queue_position_to_order(&queue, current_position); + assert(current_order == 3); + + a_order = queue_position_to_order(&queue, a_position); + assert(a_order == 6); +} diff --git a/test/test_queue_priority.c b/test/test_queue_priority.c deleted file mode 100644 index b4a7366e9..000000000 --- a/test/test_queue_priority.c +++ /dev/null @@ -1,190 +0,0 @@ -#include "config.h" -#include "queue.h" -#include "song.h" -#include "directory.h" - -struct directory detached_root; - -struct song * -song_dup_detached(const struct song *src) -{ - union { - const struct song *in; - struct song *out; - } u = { .in = src }; - - return u.out; -} - -void -song_free(G_GNUC_UNUSED struct song *song) -{ -} - -G_GNUC_UNUSED -static void -dump_order(const struct queue *queue) -{ - g_printerr("queue length=%u, order:\n", queue_length(queue)); - for (unsigned i = 0; i < queue_length(queue); ++i) - g_printerr(" [%u] -> %u (prio=%u)\n", i, queue->order[i], - queue->items[queue->order[i]].priority); -} - -static void -check_descending_priority(G_GNUC_UNUSED const struct queue *queue, - unsigned start_order) -{ - assert(start_order < queue_length(queue)); - - uint8_t last_priority = 0xff; - for (unsigned order = start_order; order < queue_length(queue); ++order) { - unsigned position = queue_order_to_position(queue, order); - uint8_t priority = queue->items[position].priority; - assert(priority <= last_priority); - (void)last_priority; - last_priority = priority; - } -} - -int -main(G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv) -{ - struct song songs[16]; - - struct queue queue; - queue_init(&queue, 32); - - for (unsigned i = 0; i < G_N_ELEMENTS(songs); ++i) - queue_append(&queue, &songs[i], 0); - - assert(queue_length(&queue) == G_N_ELEMENTS(songs)); - - /* priority=10 for 4 items */ - - queue_set_priority_range(&queue, 4, 8, 10, -1); - - queue.random = true; - queue_shuffle_order(&queue); - check_descending_priority(&queue, 0); - - for (unsigned i = 0; i < 4; ++i) { - assert(queue_position_to_order(&queue, i) >= 4); - } - - for (unsigned i = 4; i < 8; ++i) { - assert(queue_position_to_order(&queue, i) < 4); - } - - for (unsigned i = 8; i < G_N_ELEMENTS(songs); ++i) { - assert(queue_position_to_order(&queue, i) >= 4); - } - - /* priority=50 one more item */ - - queue_set_priority_range(&queue, 15, 16, 50, -1); - check_descending_priority(&queue, 0); - - assert(queue_position_to_order(&queue, 15) == 0); - - for (unsigned i = 0; i < 4; ++i) { - assert(queue_position_to_order(&queue, i) >= 4); - } - - for (unsigned i = 4; i < 8; ++i) { - assert(queue_position_to_order(&queue, i) >= 1 && - queue_position_to_order(&queue, i) < 5); - } - - for (unsigned i = 8; i < 15; ++i) { - assert(queue_position_to_order(&queue, i) >= 5); - } - - /* priority=20 for one of the 4 priority=10 items */ - - queue_set_priority_range(&queue, 3, 4, 20, -1); - check_descending_priority(&queue, 0); - - assert(queue_position_to_order(&queue, 3) == 1); - assert(queue_position_to_order(&queue, 15) == 0); - - for (unsigned i = 0; i < 3; ++i) { - assert(queue_position_to_order(&queue, i) >= 5); - } - - for (unsigned i = 4; i < 8; ++i) { - assert(queue_position_to_order(&queue, i) >= 2 && - queue_position_to_order(&queue, i) < 6); - } - - for (unsigned i = 8; i < 15; ++i) { - assert(queue_position_to_order(&queue, i) >= 6); - } - - /* priority=20 for another one of the 4 priority=10 items; - pass "after_order" (with priority=10) and see if it's moved - after that one */ - - unsigned current_order = 4; - unsigned current_position = - queue_order_to_position(&queue, current_order); - - unsigned a_order = 3; - unsigned a_position = queue_order_to_position(&queue, a_order); - assert(queue.items[a_position].priority == 10); - queue_set_priority(&queue, a_position, 20, current_order); - - current_order = queue_position_to_order(&queue, current_position); - assert(current_order == 3); - - a_order = queue_position_to_order(&queue, a_position); - assert(a_order == 4); - - check_descending_priority(&queue, current_order + 1); - - /* priority=70 for one of the last items; must be inserted - right after the current song, before the priority=20 one we - just created */ - - unsigned b_order = 10; - unsigned b_position = queue_order_to_position(&queue, b_order); - assert(queue.items[b_position].priority == 0); - queue_set_priority(&queue, b_position, 70, current_order); - - current_order = queue_position_to_order(&queue, current_position); - assert(current_order == 3); - - b_order = queue_position_to_order(&queue, b_position); - assert(b_order == 4); - - check_descending_priority(&queue, current_order + 1); - - /* priority=60 for the old prio50 item; must not be moved, - because it's before the current song, and it's status - hasn't changed (it was already higher before) */ - - unsigned c_order = 0; - unsigned c_position = queue_order_to_position(&queue, c_order); - assert(queue.items[c_position].priority == 50); - queue_set_priority(&queue, c_position, 60, current_order); - - current_order = queue_position_to_order(&queue, current_position); - assert(current_order == 3); - - c_order = queue_position_to_order(&queue, c_position); - assert(c_order == 0); - - /* move the prio=20 item back */ - - a_order = queue_position_to_order(&queue, a_position); - assert(a_order == 5); - assert(queue.items[a_position].priority == 20); - queue_set_priority(&queue, a_position, 5, current_order); - - - current_order = queue_position_to_order(&queue, current_position); - assert(current_order == 3); - - a_order = queue_position_to_order(&queue, a_position); - assert(a_order == 6); -} -- cgit v1.2.3