From 0bcc477d46e3a4a5c107ed267e1c864be8d7b2c2 Mon Sep 17 00:00:00 2001 From: Denis Krjuchkov Date: Mon, 18 Nov 2013 16:28:39 +0600 Subject: [PATCH 01/27] decoder/OggFind.cxx: include stdio.h for SEEK_END definition --- src/decoder/OggFind.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/decoder/OggFind.cxx b/src/decoder/OggFind.cxx index 821f75ca8..65c7fa3ce 100644 --- a/src/decoder/OggFind.cxx +++ b/src/decoder/OggFind.cxx @@ -22,6 +22,8 @@ #include "OggSyncState.hxx" #include "util/Error.hxx" +#include + bool OggFindEOS(OggSyncState &oy, ogg_stream_state &os, ogg_packet &packet) { From 740d8ec5ab959fce70cecf877a0bddfc52cbfe0e Mon Sep 17 00:00:00 2001 From: Denis Krjuchkov Date: Mon, 18 Nov 2013 16:35:22 +0600 Subject: [PATCH 02/27] system/fd_util.h: avoid symbol conflict with statically linked libmpdclient --- src/system/fd_util.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/system/fd_util.h b/src/system/fd_util.h index 9003b1616..b7a9a6dd3 100644 --- a/src/system/fd_util.h +++ b/src/system/fd_util.h @@ -104,6 +104,11 @@ socketpair_cloexec_nonblock(int domain, int type, int protocol, int sv[2]); #endif +#ifdef HAVE_LIBMPDCLIENT +/* Avoid symbol conflict with statically linked libmpdclient */ +#define socket_cloexec_nonblock socket_cloexec_nonblock_noconflict +#endif + /** * Wrapper for socket(), which sets the CLOEXEC and the NONBLOCK flag * (atomically if supported by the OS). From 1fc0c9fe8a5ae0483c98fbfd0d25c4147879a132 Mon Sep 17 00:00:00 2001 From: Denis Krjuchkov Date: Mon, 18 Nov 2013 16:40:00 +0600 Subject: [PATCH 03/27] NEWS: add version 0.18.5 change log --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index 86ab1a2a0..44f323bfa 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,7 @@ +ver 0.18.5 (20??/??/??) +* fix build failures due to missing includes +* fix build failure with static libmpdclient + ver 0.18.4 (2013/11/13) * decoder - dsdiff: fix byte order bug From 74a778e65fb7dd665d45725b995755e872692334 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 18 Nov 2013 20:03:30 +0100 Subject: [PATCH 04/27] configure.ac: prepare for 0.18.5 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 6805a5d46..268cb7aa7 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ(2.60) -AC_INIT(mpd, 0.18.4, musicpd-dev-team@lists.sourceforge.net) +AC_INIT(mpd, 0.18.5~git, musicpd-dev-team@lists.sourceforge.net) VERSION_MAJOR=0 VERSION_MINOR=18 From 727c6226597fb710239b14e7985d97ec6b53f0ee Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 21 Nov 2013 22:50:58 +0100 Subject: [PATCH 05/27] configure.ac: auto-detect fluidsynth by default The option "--enable-fluidsynth" was documented to be "auto" by default, when it was really "no". --- NEWS | 2 ++ configure.ac | 8 +++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 44f323bfa..3056bf915 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,6 @@ ver 0.18.5 (20??/??/??) +* decoder + - fluidsynth: auto-detect by default * fix build failures due to missing includes * fix build failure with static libmpdclient diff --git a/configure.ac b/configure.ac index 268cb7aa7..b62cb22eb 100644 --- a/configure.ac +++ b/configure.ac @@ -874,10 +874,12 @@ AM_CONDITIONAL(HAVE_FLAC, test x$enable_flac = xyes) enable_flac_encoder=$enable_flac dnl -------------------------------- FluidSynth ------------------------------- + +MPD_AUTO_PKG(fluidsynth, FLUIDSYNTH, [fluidsynth >= 1.1], + [fluidsynth decoder], [fluidsynth not found]) + if test x$enable_fluidsynth = xyes; then - PKG_CHECK_MODULES(FLUIDSYNTH, [fluidsynth >= 1.1], - AC_DEFINE(ENABLE_FLUIDSYNTH, 1, [Define for fluidsynth support]), - enable_fluidsynth=no) + AC_DEFINE(ENABLE_FLUIDSYNTH, 1, [Define for fluidsynth support]) fi AM_CONDITIONAL(ENABLE_FLUIDSYNTH, test x$enable_fluidsynth = xyes) From 37cf78ef456f455d1fb69231a88d8dc3e2b93242 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 21 Nov 2013 23:03:28 +0100 Subject: [PATCH 06/27] util/ByteOrder: indent the preprocessor directives Improve readability. --- src/system/ByteOrder.hxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/system/ByteOrder.hxx b/src/system/ByteOrder.hxx index 622003254..de8991bdb 100644 --- a/src/system/ByteOrder.hxx +++ b/src/system/ByteOrder.hxx @@ -33,11 +33,11 @@ #include #if defined(__i386__) || defined(__x86_64__) || defined(__ARMEL__) -#define IS_LITTLE_ENDIAN true -#define IS_BIG_ENDIAN false +# define IS_LITTLE_ENDIAN true +# define IS_BIG_ENDIAN false #else -#define IS_LITTLE_ENDIAN false -#define IS_BIG_ENDIAN true +# define IS_LITTLE_ENDIAN false +# define IS_BIG_ENDIAN true #endif static inline constexpr bool From 3a4df25db239bbd998a9bf5825567f7e46b7b04c Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 21 Nov 2013 23:04:31 +0100 Subject: [PATCH 07/27] util/ByteOrder: add comments --- src/system/ByteOrder.hxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/system/ByteOrder.hxx b/src/system/ByteOrder.hxx index de8991bdb..2124e92db 100644 --- a/src/system/ByteOrder.hxx +++ b/src/system/ByteOrder.hxx @@ -33,9 +33,11 @@ #include #if defined(__i386__) || defined(__x86_64__) || defined(__ARMEL__) +/* well-known little-endian */ # define IS_LITTLE_ENDIAN true # define IS_BIG_ENDIAN false #else +/* well-known big-endian */ # define IS_LITTLE_ENDIAN false # define IS_BIG_ENDIAN true #endif From 51ec499c89ae62f366fbdfe08c87a05384905e2e Mon Sep 17 00:00:00 2001 From: Florian Schlichting Date: Thu, 21 Nov 2013 22:56:45 +0100 Subject: [PATCH 08/27] system/ByteOrder: testing for endianness in a more general way Fixes build tests on ia64 and mipsel by testing for endianness in a more general / portable way. --- NEWS | 1 + src/system/ByteOrder.hxx | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 3056bf915..8fc7435ae 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,7 @@ ver 0.18.5 (20??/??/??) * decoder - fluidsynth: auto-detect by default +* fix ia64, mipsel and other little-endian architectures * fix build failures due to missing includes * fix build failure with static libmpdclient diff --git a/src/system/ByteOrder.hxx b/src/system/ByteOrder.hxx index 2124e92db..8beda61c7 100644 --- a/src/system/ByteOrder.hxx +++ b/src/system/ByteOrder.hxx @@ -36,10 +36,20 @@ /* well-known little-endian */ # define IS_LITTLE_ENDIAN true # define IS_BIG_ENDIAN false -#else +#elif defined(__MIPSEB__) /* well-known big-endian */ # define IS_LITTLE_ENDIAN false # define IS_BIG_ENDIAN true +#else +/* generic compile-time check */ +# include +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define IS_LITTLE_ENDIAN true +# define IS_BIG_ENDIAN false +# else +# define IS_LITTLE_ENDIAN false +# define IS_BIG_ENDIAN true +# endif #endif static inline constexpr bool From 67b8124a1d34c2fa850005317503663407b9648e Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 22 Nov 2013 00:02:17 +0100 Subject: [PATCH 09/27] Mapper: _get_music_directory_utf8() may return nullptr If no music_directory is configured, return nullptr instead of an empty string. This fixes a crash when db_file is configured without music_directory. --- NEWS | 2 ++ src/Mapper.cxx | 4 +++- src/Mapper.hxx | 3 ++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 8fc7435ae..8a433e202 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,6 @@ ver 0.18.5 (20??/??/??) +* configuration + - fix crash when db_file is configured without music_directory * decoder - fluidsynth: auto-detect by default * fix ia64, mipsel and other little-endian architectures diff --git a/src/Mapper.cxx b/src/Mapper.cxx index 08597732a..cbe45daa0 100644 --- a/src/Mapper.cxx +++ b/src/Mapper.cxx @@ -133,7 +133,9 @@ void mapper_finish(void) const char * mapper_get_music_directory_utf8(void) { - return music_dir_utf8.c_str(); + return music_dir_utf8.empty() + ? nullptr + : music_dir_utf8.c_str(); } const AllocatedPath & diff --git a/src/Mapper.hxx b/src/Mapper.hxx index be69a7110..947fd2822 100644 --- a/src/Mapper.hxx +++ b/src/Mapper.hxx @@ -41,7 +41,8 @@ mapper_init(AllocatedPath &&music_dir, AllocatedPath &&playlist_dir); void mapper_finish(void); /** - * Return the absolute path of the music directory encoded in UTF-8. + * Return the absolute path of the music directory encoded in UTF-8 or + * nullptr if no music directory was configured. */ gcc_const const char * From e719b6cc410cc0d9699df7ab5c308d6af4ec01e3 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 21 Nov 2013 23:34:32 +0100 Subject: [PATCH 10/27] Stats: print db_update as unsigned integer --- src/Stats.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Stats.cxx b/src/Stats.cxx index 88f76928f..6cd6977ec 100644 --- a/src/Stats.cxx +++ b/src/Stats.cxx @@ -83,6 +83,6 @@ stats_print(Client &client) if (db_is_simple()) client_printf(client, - "db_update: %li\n", - (long)db_get_mtime()); + "db_update: %lu\n", + (unsigned long)db_get_mtime()); } From 2ecd5fa28d05e20e7ef281ccd6760d73cbc04e8d Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 22 Nov 2013 00:08:43 +0100 Subject: [PATCH 11/27] Stats: don't export the global variable "stats" Unused outside of Stats.cxx. --- src/Stats.cxx | 2 +- src/Stats.hxx | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Stats.cxx b/src/Stats.cxx index 6cd6977ec..93795aee5 100644 --- a/src/Stats.cxx +++ b/src/Stats.cxx @@ -30,7 +30,7 @@ #include -struct stats stats; +static struct stats stats; void stats_global_init(void) { diff --git a/src/Stats.hxx b/src/Stats.hxx index 1b141355c..525dc154c 100644 --- a/src/Stats.hxx +++ b/src/Stats.hxx @@ -40,8 +40,6 @@ struct stats { unsigned album_count; }; -extern struct stats stats; - void stats_global_init(void); void stats_global_finish(void); From b9169a5670c4cb603b25f0b07e93d9739c5b06f8 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 22 Nov 2013 00:10:53 +0100 Subject: [PATCH 12/27] Stats: move the GTimer variable out of struct stats --- src/Stats.cxx | 7 ++++--- src/Stats.hxx | 3 --- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Stats.cxx b/src/Stats.cxx index 93795aee5..63be2a7bc 100644 --- a/src/Stats.cxx +++ b/src/Stats.cxx @@ -30,16 +30,17 @@ #include +static GTimer *uptime; static struct stats stats; void stats_global_init(void) { - stats.timer = g_timer_new(); + uptime = g_timer_new(); } void stats_global_finish(void) { - g_timer_destroy(stats.timer); + g_timer_destroy(uptime); } void stats_update(void) @@ -77,7 +78,7 @@ stats_print(Client &client) stats.artist_count, stats.album_count, stats.song_count, - (long)g_timer_elapsed(stats.timer, NULL), + (long)g_timer_elapsed(uptime, NULL), (long)(client.player_control.GetTotalPlayTime() + 0.5), stats.song_duration); diff --git a/src/Stats.hxx b/src/Stats.hxx index 525dc154c..898048bc5 100644 --- a/src/Stats.hxx +++ b/src/Stats.hxx @@ -21,11 +21,8 @@ #define MPD_STATS_HXX class Client; -typedef struct _GTimer GTimer; struct stats { - GTimer *timer; - /** number of song files in the music directory */ unsigned song_count; From 41a3fd0fd06dd9d99b77982eac9b91aca9a768d0 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 22 Nov 2013 00:12:12 +0100 Subject: [PATCH 13/27] Stats: use struct DatabaseStats Eliminate redundant declaration. --- src/Stats.cxx | 14 ++++---------- src/Stats.hxx | 15 --------------- 2 files changed, 4 insertions(+), 25 deletions(-) diff --git a/src/Stats.cxx b/src/Stats.cxx index 63be2a7bc..2baeafa39 100644 --- a/src/Stats.cxx +++ b/src/Stats.cxx @@ -31,7 +31,7 @@ #include static GTimer *uptime; -static struct stats stats; +static DatabaseStats stats; void stats_global_init(void) { @@ -51,17 +51,11 @@ void stats_update(void) const DatabaseSelection selection("", true); if (GetDatabase()->GetStats(selection, stats2, error)) { - stats.song_count = stats2.song_count; - stats.song_duration = stats2.total_duration; - stats.artist_count = stats2.artist_count; - stats.album_count = stats2.album_count; + stats = stats2; } else { LogError(error); - stats.song_count = 0; - stats.song_duration = 0; - stats.artist_count = 0; - stats.album_count = 0; + stats.Clear(); } } @@ -80,7 +74,7 @@ stats_print(Client &client) stats.song_count, (long)g_timer_elapsed(uptime, NULL), (long)(client.player_control.GetTotalPlayTime() + 0.5), - stats.song_duration); + stats.total_duration); if (db_is_simple()) client_printf(client, diff --git a/src/Stats.hxx b/src/Stats.hxx index 898048bc5..dd131ce19 100644 --- a/src/Stats.hxx +++ b/src/Stats.hxx @@ -22,21 +22,6 @@ class Client; -struct stats { - /** number of song files in the music directory */ - unsigned song_count; - - /** sum of all song durations in the music directory (in - seconds) */ - unsigned long song_duration; - - /** number of distinct artist names in the music directory */ - unsigned artist_count; - - /** number of distinct album names in the music directory */ - unsigned album_count; -}; - void stats_global_init(void); void stats_global_finish(void); From ff1c1107f3a7ad0cfbdfefbe26f2f5e1cb9b00c5 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 21 Nov 2013 23:30:49 +0100 Subject: [PATCH 14/27] Stats: auto-reload statistics with proxy plugin --- NEWS | 2 ++ src/Stats.cxx | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/NEWS b/NEWS index 8a433e202..34867b245 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,8 @@ ver 0.18.5 (20??/??/??) * configuration - fix crash when db_file is configured without music_directory +* database + - proxy: auto-reload statistics * decoder - fluidsynth: auto-detect by default * fix ia64, mipsel and other little-endian architectures diff --git a/src/Stats.cxx b/src/Stats.cxx index 2baeafa39..8f9d90b0f 100644 --- a/src/Stats.cxx +++ b/src/Stats.cxx @@ -62,6 +62,13 @@ void stats_update(void) void stats_print(Client &client) { + if (!db_is_simple()) + /* reload statistics if we're using the "proxy" + database plugin */ + /* TODO: move this into the "proxy" database plugin as + an "idle" handler */ + stats_update(); + client_printf(client, "artists: %u\n" "albums: %u\n" From 042fe2a9d0e34d74e26aeedc1d1fd73f784c1afe Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 22 Nov 2013 00:23:27 +0100 Subject: [PATCH 15/27] Stats: print more unsigned integers --- src/Stats.cxx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Stats.cxx b/src/Stats.cxx index 8f9d90b0f..8e39c8dfa 100644 --- a/src/Stats.cxx +++ b/src/Stats.cxx @@ -72,15 +72,15 @@ stats_print(Client &client) client_printf(client, "artists: %u\n" "albums: %u\n" - "songs: %i\n" - "uptime: %li\n" - "playtime: %li\n" - "db_playtime: %li\n", + "songs: %u\n" + "uptime: %lu\n" + "playtime: %lu\n" + "db_playtime: %lu\n", stats.artist_count, stats.album_count, stats.song_count, - (long)g_timer_elapsed(uptime, NULL), - (long)(client.player_control.GetTotalPlayTime() + 0.5), + (unsigned long)g_timer_elapsed(uptime, NULL), + (unsigned long)(client.player_control.GetTotalPlayTime() + 0.5), stats.total_duration); if (db_is_simple()) From 099a2cb586524cf49dd3a9a0107ce003fd2e27e5 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 22 Nov 2013 00:23:17 +0100 Subject: [PATCH 16/27] Stats: print db statistics only if db is available Fixes crash on "stats" in certain configurations. --- NEWS | 1 + src/Stats.cxx | 25 +++++++++++++++++++------ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index 34867b245..b184425d6 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,7 @@ ver 0.18.5 (20??/??/??) * configuration - fix crash when db_file is configured without music_directory + - fix crash on "stats" without db_file/music_directory * database - proxy: auto-reload statistics * decoder diff --git a/src/Stats.cxx b/src/Stats.cxx index 8e39c8dfa..d2d18d6a9 100644 --- a/src/Stats.cxx +++ b/src/Stats.cxx @@ -45,6 +45,8 @@ void stats_global_finish(void) void stats_update(void) { + assert(GetDatabase() != nullptr); + Error error; DatabaseStats stats2; @@ -59,9 +61,11 @@ void stats_update(void) } } -void -stats_print(Client &client) +static void +db_stats_print(Client &client) { + assert(GetDatabase() != nullptr); + if (!db_is_simple()) /* reload statistics if we're using the "proxy" database plugin */ @@ -73,14 +77,10 @@ stats_print(Client &client) "artists: %u\n" "albums: %u\n" "songs: %u\n" - "uptime: %lu\n" - "playtime: %lu\n" "db_playtime: %lu\n", stats.artist_count, stats.album_count, stats.song_count, - (unsigned long)g_timer_elapsed(uptime, NULL), - (unsigned long)(client.player_control.GetTotalPlayTime() + 0.5), stats.total_duration); if (db_is_simple()) @@ -88,3 +88,16 @@ stats_print(Client &client) "db_update: %lu\n", (unsigned long)db_get_mtime()); } + +void +stats_print(Client &client) +{ + client_printf(client, + "uptime: %lu\n" + "playtime: %lu\n", + (unsigned long)g_timer_elapsed(uptime, NULL), + (unsigned long)(client.player_control.GetTotalPlayTime() + 0.5)); + + if (GetDatabase() != nullptr) + db_stats_print(client); +} From c064e8d62f0d2b46159570f21708c2546970718d Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 22 Nov 2013 00:35:29 +0100 Subject: [PATCH 17/27] DatabasePlugin: add method GetUpdateStamp() Refactor SimpleDatabase::GetLastModified() to be generic for all plugins. Remove the SimpleDatabase assumption from db_stats_print(), allowing it to be implemented by all database plugins. --- src/DatabaseGlue.cxx | 6 +++--- src/DatabasePlugin.hxx | 9 +++++++++ src/DatabaseSimple.hxx | 16 ++-------------- src/Stats.cxx | 5 +++-- src/db/ProxyDatabasePlugin.cxx | 5 +++++ src/db/SimpleDatabasePlugin.hxx | 11 ++++------- 6 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/DatabaseGlue.cxx b/src/DatabaseGlue.cxx index e84503713..013a3e329 100644 --- a/src/DatabaseGlue.cxx +++ b/src/DatabaseGlue.cxx @@ -148,12 +148,12 @@ DatabaseGlobalOpen(Error &error) return true; } -time_t -db_get_mtime(void) +bool +db_exists() { assert(db != nullptr); assert(db_is_open); assert(db_is_simple()); - return ((SimpleDatabase *)db)->GetLastModified(); + return ((SimpleDatabase *)db)->GetUpdateStamp() > 0; } diff --git a/src/DatabasePlugin.hxx b/src/DatabasePlugin.hxx index 629dff329..ccf899389 100644 --- a/src/DatabasePlugin.hxx +++ b/src/DatabasePlugin.hxx @@ -30,6 +30,8 @@ #include "tag/TagType.h" #include "Compiler.h" +#include + struct config_param; struct DatabaseSelection; struct db_visitor; @@ -132,6 +134,13 @@ public: virtual bool GetStats(const DatabaseSelection &selection, DatabaseStats &stats, Error &error) const = 0; + + /** + * Returns the time stamp of the last database update. + * Returns 0 if that is not not known/available. + */ + gcc_pure + virtual time_t GetUpdateStamp() const = 0; }; struct DatabasePlugin { diff --git a/src/DatabaseSimple.hxx b/src/DatabaseSimple.hxx index 124d78a30..6d52ac0b3 100644 --- a/src/DatabaseSimple.hxx +++ b/src/DatabaseSimple.hxx @@ -62,25 +62,13 @@ db_get_directory(const char *name); bool db_save(Error &error); -/** - * May only be used if db_is_simple() returns true. - */ -gcc_pure -time_t -db_get_mtime(void); - /** * Returns true if there is a valid database file on the disk. * * May only be used if db_is_simple() returns true. */ gcc_pure -static inline bool -db_exists(void) -{ - /* mtime is set only if the database file was loaded or saved - successfully */ - return db_get_mtime() > 0; -} +bool +db_exists(); #endif diff --git a/src/Stats.cxx b/src/Stats.cxx index d2d18d6a9..f224bdf49 100644 --- a/src/Stats.cxx +++ b/src/Stats.cxx @@ -83,10 +83,11 @@ db_stats_print(Client &client) stats.song_count, stats.total_duration); - if (db_is_simple()) + const time_t update_stamp = GetDatabase()->GetUpdateStamp(); + if (update_stamp > 0) client_printf(client, "db_update: %lu\n", - (unsigned long)db_get_mtime()); + (unsigned long)update_stamp); } void diff --git a/src/db/ProxyDatabasePlugin.cxx b/src/db/ProxyDatabasePlugin.cxx index fc99242ee..d4861623f 100644 --- a/src/db/ProxyDatabasePlugin.cxx +++ b/src/db/ProxyDatabasePlugin.cxx @@ -71,6 +71,11 @@ public: DatabaseStats &stats, Error &error) const override; + virtual time_t GetUpdateStamp() const override { + // TODO: implement + return 0; + } + private: bool Configure(const config_param ¶m, Error &error); diff --git a/src/db/SimpleDatabasePlugin.hxx b/src/db/SimpleDatabasePlugin.hxx index 24e150a97..dfe981dd8 100644 --- a/src/db/SimpleDatabasePlugin.hxx +++ b/src/db/SimpleDatabasePlugin.hxx @@ -26,8 +26,6 @@ #include -#include - struct Directory; class SimpleDatabase : public Database { @@ -55,11 +53,6 @@ public: bool Save(Error &error); - gcc_pure - time_t GetLastModified() const { - return mtime; - } - static Database *Create(const config_param ¶m, Error &error); @@ -85,6 +78,10 @@ public: DatabaseStats &stats, Error &error) const override; + virtual time_t GetUpdateStamp() const override { + return mtime; + } + protected: bool Configure(const config_param ¶m, Error &error); From d22acc59c928bf4fd96eb569897bf6f64ae7df7a Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 22 Nov 2013 00:45:27 +0100 Subject: [PATCH 18/27] db/proxy: implement method GetUpdateStamp() --- NEWS | 1 + src/db/ProxyDatabasePlugin.cxx | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index b184425d6..45b0ef242 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,7 @@ ver 0.18.5 (20??/??/??) - fix crash on "stats" without db_file/music_directory * database - proxy: auto-reload statistics + - proxy: provide "db_update" in "stats" response * decoder - fluidsynth: auto-detect by default * fix ia64, mipsel and other little-endian architectures diff --git a/src/db/ProxyDatabasePlugin.cxx b/src/db/ProxyDatabasePlugin.cxx index d4861623f..00b5d445f 100644 --- a/src/db/ProxyDatabasePlugin.cxx +++ b/src/db/ProxyDatabasePlugin.cxx @@ -46,6 +46,9 @@ class ProxyDatabase : public Database { struct mpd_connection *connection; Directory *root; + /* this is mutable because GetStats() must be "const" */ + mutable time_t update_stamp; + public: static Database *Create(const config_param ¶m, Error &error); @@ -72,8 +75,7 @@ public: Error &error) const override; virtual time_t GetUpdateStamp() const override { - // TODO: implement - return 0; + return update_stamp; } private: @@ -242,6 +244,7 @@ ProxyDatabase::Open(Error &error) return false; root = Directory::NewRoot(); + update_stamp = 0; return true; } @@ -636,6 +639,8 @@ ProxyDatabase::GetStats(const DatabaseSelection &selection, if (stats2 == nullptr) return CheckError(connection, error); + update_stamp = (time_t)mpd_stats_get_db_update_time(stats2); + stats.song_count = mpd_stats_get_number_of_songs(stats2); stats.total_duration = mpd_stats_get_db_play_time(stats2); stats.artist_count = mpd_stats_get_number_of_artists(stats2); From 45d27a52f17be05f5269d7dc37f380ed595196e7 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 22 Nov 2013 23:00:39 +0100 Subject: [PATCH 19/27] PcmUtils: add function PcmClampN() --- src/pcm/PcmUtils.hxx | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/pcm/PcmUtils.hxx b/src/pcm/PcmUtils.hxx index 108ba85ae..febe12d7b 100644 --- a/src/pcm/PcmUtils.hxx +++ b/src/pcm/PcmUtils.hxx @@ -63,4 +63,16 @@ PcmClamp(U x) return T(x); } +/** + * Check if the values in this buffer are within the range of the + * provided bit size, and clamps them whenever necessary. + */ +template +static inline void +PcmClampN(T *dest, const U *src, unsigned n) +{ + while (n-- > 0) + *dest++ = PcmClamp(*src++); +} + #endif From 87c8953e8ed660b59ea2452b4d3a431785c47495 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 22 Nov 2013 22:50:43 +0100 Subject: [PATCH 20/27] PcmResample: un-inline Resample24() --- src/pcm/PcmResample.cxx | 12 ++++++++++++ src/pcm/PcmResample.hxx | 8 +------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/pcm/PcmResample.cxx b/src/pcm/PcmResample.cxx index e2ce095d1..df37826ba 100644 --- a/src/pcm/PcmResample.cxx +++ b/src/pcm/PcmResample.cxx @@ -148,3 +148,15 @@ PcmResampler::Resample32(unsigned channels, unsigned src_rate, src_rate, src_buffer, src_size, dest_rate, dest_size_r); } + +const int32_t * +PcmResampler::Resample24(unsigned channels, unsigned src_rate, + const int32_t *src_buffer, size_t src_size, + unsigned dest_rate, size_t *dest_size_r, + Error &error_r) +{ + /* reuse the 32 bit code - the resampler code doesn't care if + the upper 8 bits are actually used */ + return Resample32(channels, src_rate, src_buffer, src_size, + dest_rate, dest_size_r, error_r); +} diff --git a/src/pcm/PcmResample.hxx b/src/pcm/PcmResample.hxx index 8a740744a..e839d6ecd 100644 --- a/src/pcm/PcmResample.hxx +++ b/src/pcm/PcmResample.hxx @@ -124,13 +124,7 @@ struct PcmResampler { const int32_t *Resample24(unsigned channels, unsigned src_rate, const int32_t *src_buffer, size_t src_size, unsigned dest_rate, size_t *dest_size_r, - Error &error_r) - { - /* reuse the 32 bit code - the resampler code doesn't care if - the upper 8 bits are actually used */ - return Resample32(channels, src_rate, src_buffer, src_size, - dest_rate, dest_size_r, error_r); - } + Error &error_r); }; bool From fc7d5b055d98306af0c882282902a23e963f026d Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 22 Nov 2013 22:50:29 +0100 Subject: [PATCH 21/27] PcmResampleLibsamplerate: clip 24 bit data Using pcm_resample_lsr_32() for 24 bit samples works, but may cause 24 bit overflows. This commit makes 24 bit a special case with explicit clipping. --- NEWS | 1 + src/pcm/PcmResample.cxx | 15 +++++++++++++-- src/pcm/PcmResampleInternal.hxx | 9 +++++++++ src/pcm/PcmResampleLibsamplerate.cxx | 25 +++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 45b0ef242..51a0437ed 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,7 @@ ver 0.18.5 (20??/??/??) - proxy: provide "db_update" in "stats" response * decoder - fluidsynth: auto-detect by default +* clip 24 bit data from libsamplerate * fix ia64, mipsel and other little-endian architectures * fix build failures due to missing includes * fix build failure with static libmpdclient diff --git a/src/pcm/PcmResample.cxx b/src/pcm/PcmResample.cxx index df37826ba..01f269ea9 100644 --- a/src/pcm/PcmResample.cxx +++ b/src/pcm/PcmResample.cxx @@ -155,8 +155,19 @@ PcmResampler::Resample24(unsigned channels, unsigned src_rate, unsigned dest_rate, size_t *dest_size_r, Error &error_r) { +#ifdef HAVE_LIBSAMPLERATE + if (pcm_resample_lsr_enabled()) + return pcm_resample_lsr_24(this, channels, + src_rate, src_buffer, src_size, + dest_rate, dest_size_r, + error_r); +#else + (void)error_r; +#endif + /* reuse the 32 bit code - the resampler code doesn't care if the upper 8 bits are actually used */ - return Resample32(channels, src_rate, src_buffer, src_size, - dest_rate, dest_size_r, error_r); + return pcm_resample_fallback_32(this, channels, + src_rate, src_buffer, src_size, + dest_rate, dest_size_r); } diff --git a/src/pcm/PcmResampleInternal.hxx b/src/pcm/PcmResampleInternal.hxx index 59bb2f5df..5090c13d1 100644 --- a/src/pcm/PcmResampleInternal.hxx +++ b/src/pcm/PcmResampleInternal.hxx @@ -69,6 +69,15 @@ pcm_resample_lsr_32(PcmResampler *state, unsigned dest_rate, size_t *dest_size_r, Error &error); +const int32_t * +pcm_resample_lsr_24(PcmResampler *state, + unsigned channels, + unsigned src_rate, + const int32_t *src_buffer, + size_t src_size, + unsigned dest_rate, size_t *dest_size_r, + Error &error); + #endif const int16_t * diff --git a/src/pcm/PcmResampleLibsamplerate.cxx b/src/pcm/PcmResampleLibsamplerate.cxx index 1986e8821..9eac2d545 100644 --- a/src/pcm/PcmResampleLibsamplerate.cxx +++ b/src/pcm/PcmResampleLibsamplerate.cxx @@ -19,6 +19,7 @@ #include "config.h" #include "PcmResampleInternal.hxx" +#include "PcmUtils.hxx" #include "util/ASCII.hxx" #include "util/Error.hxx" #include "util/Domain.hxx" @@ -283,3 +284,27 @@ pcm_resample_lsr_32(PcmResampler *state, return dest_buffer; } + +const int32_t * +pcm_resample_lsr_24(PcmResampler *state, + unsigned channels, + unsigned src_rate, + const int32_t *src_buffer, size_t src_size, + unsigned dest_rate, size_t *dest_size_r, + Error &error) +{ + const auto result = pcm_resample_lsr_32(state, channels, + src_rate, src_buffer, src_size, + dest_rate, dest_size_r, + error); + if (result != nullptr) + /* src_float_to_int_array() clamps for 32 bit + integers; now make sure everything's fine for 24 + bit */ + /* TODO: eliminate the 32 bit clamp to reduce overhead */ + PcmClampN(const_cast(result), + result, + *dest_size_r / sizeof(*result)); + + return result; +} From 2eddb63a83c94c9cf55e6a5ef2b7be7431247ecd Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sat, 23 Nov 2013 12:02:17 +0100 Subject: [PATCH 22/27] input/curl: dump version number --- src/input/CurlInputPlugin.cxx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/input/CurlInputPlugin.cxx b/src/input/CurlInputPlugin.cxx index 841db6ceb..73c1fc4b7 100644 --- a/src/input/CurlInputPlugin.cxx +++ b/src/input/CurlInputPlugin.cxx @@ -586,6 +586,14 @@ input_curl_init(const config_param ¶m, Error &error) return false; } + const auto version_info = curl_version_info(CURLVERSION_FIRST); + if (version_info != nullptr) { + FormatDebug(curl_domain, "version %s", version_info->version); + if (version_info->features & CURL_VERSION_SSL) + FormatDebug(curl_domain, "with %s", + version_info->ssl_version); + } + http_200_aliases = curl_slist_append(http_200_aliases, "ICY 200 OK"); proxy = param.GetBlockValue("proxy"); From a566c28a49a72bf4dd2f33ad5ee0bf5635871550 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sat, 23 Nov 2013 12:08:46 +0100 Subject: [PATCH 23/27] input/curl: add global variable "curl_version" --- src/input/CurlInputPlugin.cxx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/input/CurlInputPlugin.cxx b/src/input/CurlInputPlugin.cxx index 73c1fc4b7..b51fb99ac 100644 --- a/src/input/CurlInputPlugin.cxx +++ b/src/input/CurlInputPlugin.cxx @@ -279,6 +279,11 @@ private: virtual void OnTimeout() override; }; +/** + * libcurl version number encoded in a 24 bit integer. + */ +static unsigned curl_version_num; + /** libcurl should accept "ICY 200 OK" */ static struct curl_slist *http_200_aliases; @@ -592,6 +597,8 @@ input_curl_init(const config_param ¶m, Error &error) if (version_info->features & CURL_VERSION_SSL) FormatDebug(curl_domain, "with %s", version_info->ssl_version); + + curl_version_num = version_info->version_num; } http_200_aliases = curl_slist_append(http_200_aliases, "ICY 200 OK"); From d6247902eca44aa45f92ac095397738f7f633283 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sat, 23 Nov 2013 11:59:32 +0100 Subject: [PATCH 24/27] input/curl: work around stream resume bug (fixed in libcurl 7.32.0) --- NEWS | 2 ++ src/input/CurlInputPlugin.cxx | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/NEWS b/NEWS index 51a0437ed..f9ce5f45d 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,8 @@ ver 0.18.5 (20??/??/??) * database - proxy: auto-reload statistics - proxy: provide "db_update" in "stats" response +* input + - curl: work around stream resume bug (fixed in libcurl 7.32.0) * decoder - fluidsynth: auto-detect by default * clip 24 bit data from libsamplerate diff --git a/src/input/CurlInputPlugin.cxx b/src/input/CurlInputPlugin.cxx index b51fb99ac..b78545951 100644 --- a/src/input/CurlInputPlugin.cxx +++ b/src/input/CurlInputPlugin.cxx @@ -273,6 +273,16 @@ public: SocketAction(CURL_SOCKET_TIMEOUT, 0); } + /** + * This is a kludge to allow pausing/resuming a stream with + * libcurl < 7.32.0. Read the curl_easy_pause manpage for + * more information. + */ + void ResumeSockets() { + int running_handles; + curl_multi_socket_all(multi, &running_handles); + } + private: static int TimerFunction(CURLM *multi, long timeout_ms, void *userp); @@ -335,6 +345,13 @@ input_curl_resume(struct input_curl *c) if (c->paused) { c->paused = false; curl_easy_pause(c->easy, CURLPAUSE_CONT); + + if (curl_version_num < 0x072000) + /* libcurl older than 7.32.0 does not update + its sockets after curl_easy_pause(); force + libcurl to do it now */ + curl_multi->ResumeSockets(); + curl_multi->InvalidateSockets(); } } From ae88ba986e0c50d922845f65d9b432404f41c532 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sat, 23 Nov 2013 18:29:43 +0100 Subject: [PATCH 25/27] archive/iso9660: eliminate useless assignments --- src/archive/Iso9660ArchivePlugin.cxx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/archive/Iso9660ArchivePlugin.cxx b/src/archive/Iso9660ArchivePlugin.cxx index 8233d03f7..ad21d4a3d 100644 --- a/src/archive/Iso9660ArchivePlugin.cxx +++ b/src/archive/Iso9660ArchivePlugin.cxx @@ -190,18 +190,16 @@ iso9660_input_read(InputStream *is, void *ptr, size_t size, Error &error) { Iso9660InputStream *iis = (Iso9660InputStream *)is; - int toread, readed = 0; + int readed = 0; int no_blocks, cur_block; size_t left_bytes = iis->statbuf->size - is->offset; size = (size * ISO_BLOCKSIZE) / ISO_BLOCKSIZE; if (left_bytes < size) { - toread = left_bytes; no_blocks = CEILING(left_bytes,ISO_BLOCKSIZE); } else { - toread = size; - no_blocks = toread / ISO_BLOCKSIZE; + no_blocks = size / ISO_BLOCKSIZE; } if (no_blocks > 0) { From 73f45d87d5d3fd078bdf9acd3077e4c8b6a638c9 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sat, 23 Nov 2013 18:30:06 +0100 Subject: [PATCH 26/27] decoder/{dsf,dsdiff}: eliminate useless assignments --- src/decoder/DsdiffDecoderPlugin.cxx | 5 ++--- src/decoder/DsfDecoderPlugin.cxx | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/decoder/DsdiffDecoderPlugin.cxx b/src/decoder/DsdiffDecoderPlugin.cxx index 347f5b586..a3c0149b9 100644 --- a/src/decoder/DsdiffDecoderPlugin.cxx +++ b/src/decoder/DsdiffDecoderPlugin.cxx @@ -294,7 +294,6 @@ dsdiff_read_metadata_extra(Decoder *decoder, InputStream &is, if (!dsdiff_read_chunk_header(decoder, is, chunk_header)) return false; } - chunk_size = 0; } /* done processing chunk headers, process tags if any */ @@ -385,10 +384,10 @@ dsdiff_decode_chunk(Decoder &decoder, InputStream &is, while (chunk_size > 0) { /* see how much aligned data from the remaining chunk fits into the local buffer */ - unsigned now_frames = buffer_frames; size_t now_size = buffer_size; if (chunk_size < (uint64_t)now_size) { - now_frames = (unsigned)chunk_size / frame_size; + unsigned now_frames = + (unsigned)chunk_size / frame_size; now_size = now_frames * frame_size; } diff --git a/src/decoder/DsfDecoderPlugin.cxx b/src/decoder/DsfDecoderPlugin.cxx index 0507f5047..5ef94e647 100644 --- a/src/decoder/DsfDecoderPlugin.cxx +++ b/src/decoder/DsfDecoderPlugin.cxx @@ -240,10 +240,10 @@ dsf_decode_chunk(Decoder &decoder, InputStream &is, while (chunk_size > 0) { /* see how much aligned data from the remaining chunk fits into the local buffer */ - unsigned now_frames = buffer_frames; size_t now_size = buffer_size; if (chunk_size < (uint64_t)now_size) { - now_frames = (unsigned)chunk_size / frame_size; + unsigned now_frames = + (unsigned)chunk_size / frame_size; now_size = now_frames * frame_size; } From 57e0cc54424561499039967aa501c17d4b179019 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sat, 23 Nov 2013 18:08:39 +0100 Subject: [PATCH 27/27] release v0.18.5 --- NEWS | 2 +- configure.ac | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index f9ce5f45d..9301f1dcc 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,4 @@ -ver 0.18.5 (20??/??/??) +ver 0.18.5 (2013/11/23) * configuration - fix crash when db_file is configured without music_directory - fix crash on "stats" without db_file/music_directory diff --git a/configure.ac b/configure.ac index b62cb22eb..b55c19e30 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ(2.60) -AC_INIT(mpd, 0.18.5~git, musicpd-dev-team@lists.sourceforge.net) +AC_INIT(mpd, 0.18.5, musicpd-dev-team@lists.sourceforge.net) VERSION_MAJOR=0 VERSION_MINOR=18