From a9bcf8d50dd98897db8e37d5c5141004f475d39f Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 16 Oct 2015 14:55:00 +0200 Subject: [PATCH 01/14] configure.ac: prepare for 0.19.11 --- NEWS | 2 ++ configure.ac | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 1d72d188b..65252a614 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,5 @@ +ver 0.19.11 (not yet released) + ver 0.19.10 (2015/06/21) * input - curl: fix deadlock on small responses diff --git a/configure.ac b/configure.ac index 1a3471f36..3d29e724f 100644 --- a/configure.ac +++ b/configure.ac @@ -1,10 +1,10 @@ AC_PREREQ(2.60) -AC_INIT(mpd, 0.19.10, musicpd-dev-team@lists.sourceforge.net) +AC_INIT(mpd, 0.19.11, musicpd-dev-team@lists.sourceforge.net) VERSION_MAJOR=0 VERSION_MINOR=19 -VERSION_REVISION=10 +VERSION_REVISION=11 VERSION_EXTRA=0 AC_CONFIG_SRCDIR([src/Main.cxx]) From 205fba74cffffb9df985cdf928101633ffc41772 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 16 Oct 2015 14:40:46 +0200 Subject: [PATCH 02/14] tag/ApeLoader: fix buffer overflow after unterminated key --- NEWS | 2 ++ src/tag/ApeLoader.cxx | 12 ++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index 65252a614..7e5f41b3b 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,6 @@ ver 0.19.11 (not yet released) +* tags + - ape: fix buffer overflow ver 0.19.10 (2015/06/21) * input diff --git a/src/tag/ApeLoader.cxx b/src/tag/ApeLoader.cxx index f473c910e..f51cb5c0b 100644 --- a/src/tag/ApeLoader.cxx +++ b/src/tag/ApeLoader.cxx @@ -78,12 +78,12 @@ ape_scan_internal(FILE *fp, ApeTagCallback callback) /* get the key */ const char *key = p; - while (remaining > size && *p != '\0') { - p++; - remaining--; - } - p++; - remaining--; + const char *key_end = (const char *)memchr(p, '\0', remaining); + if (key_end == nullptr) + break; + + p = key_end + 1; + remaining -= p - key; /* get the value */ if (remaining < size) From 4e3d1821895c92d060fc3a9059e83ac58c8c79a3 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 16 Oct 2015 18:05:34 +0200 Subject: [PATCH 03/14] encoder/flac: fix crash with 32 bit playback Copy to encoder->audio_format *after* adjusting the sample format to S24_P32. Fixes http://bugs.musicpd.org/view.php?id=4433 --- NEWS | 2 ++ src/encoder/plugins/FlacEncoderPlugin.cxx | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 7e5f41b3b..9c44eaf0a 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,8 @@ ver 0.19.11 (not yet released) * tags - ape: fix buffer overflow +* encoder + - flac: fix crash with 32 bit playback ver 0.19.10 (2015/06/21) * input diff --git a/src/encoder/plugins/FlacEncoderPlugin.cxx b/src/encoder/plugins/FlacEncoderPlugin.cxx index 26987fe99..9317b02ea 100644 --- a/src/encoder/plugins/FlacEncoderPlugin.cxx +++ b/src/encoder/plugins/FlacEncoderPlugin.cxx @@ -157,8 +157,6 @@ flac_encoder_open(Encoder *_encoder, AudioFormat &audio_format, Error &error) struct flac_encoder *encoder = (struct flac_encoder *)_encoder; unsigned bits_per_sample; - encoder->audio_format = audio_format; - /* FIXME: flac should support 32bit as well */ switch (audio_format.format) { case SampleFormat::S8: @@ -178,6 +176,8 @@ flac_encoder_open(Encoder *_encoder, AudioFormat &audio_format, Error &error) audio_format.format = SampleFormat::S24_P32; } + encoder->audio_format = audio_format; + /* allocate the encoder */ encoder->fse = FLAC__stream_encoder_new(); if (encoder->fse == nullptr) { From f066bb7716200a83e209d27f6b4f87f012033266 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 17 Sep 2015 23:13:53 +0200 Subject: [PATCH 04/14] unix/Daemon, playlist/...: remove unused Domain variables --- src/Main.cxx | 3 --- src/encoder/plugins/ShineEncoderPlugin.cxx | 3 --- src/filter/plugins/VolumeFilterPlugin.cxx | 3 --- src/mixer/MixerAll.cxx | 3 --- src/output/plugins/PipeOutputPlugin.cxx | 3 --- src/playlist/plugins/XspfPlaylistPlugin.cxx | 3 --- src/unix/Daemon.cxx | 3 --- 7 files changed, 21 deletions(-) diff --git a/src/Main.cxx b/src/Main.cxx index 26d4e7ae4..a3a1b0021 100644 --- a/src/Main.cxx +++ b/src/Main.cxx @@ -54,7 +54,6 @@ #include "system/FatalError.hxx" #include "util/UriUtil.hxx" #include "util/Error.hxx" -#include "util/Domain.hxx" #include "thread/Id.hxx" #include "thread/Slack.hxx" #include "lib/icu/Init.hxx" @@ -123,8 +122,6 @@ static constexpr unsigned DEFAULT_BUFFER_SIZE = 4096; static constexpr unsigned DEFAULT_BUFFER_BEFORE_PLAY = 10; -static constexpr Domain main_domain("main"); - #ifdef ANDROID Context *context; #endif diff --git a/src/encoder/plugins/ShineEncoderPlugin.cxx b/src/encoder/plugins/ShineEncoderPlugin.cxx index 61cb8609e..1b00f7d53 100644 --- a/src/encoder/plugins/ShineEncoderPlugin.cxx +++ b/src/encoder/plugins/ShineEncoderPlugin.cxx @@ -26,7 +26,6 @@ #include "util/NumberParser.hxx" #include "util/DynamicFifoBuffer.hxx" #include "util/Error.hxx" -#include "util/Domain.hxx" extern "C" { @@ -60,8 +59,6 @@ struct ShineEncoder { bool WriteChunk(bool flush); }; -static constexpr Domain shine_encoder_domain("shine_encoder"); - inline bool ShineEncoder::Configure(const config_param ¶m, gcc_unused Error &error) diff --git a/src/filter/plugins/VolumeFilterPlugin.cxx b/src/filter/plugins/VolumeFilterPlugin.cxx index 17e061476..39188da00 100644 --- a/src/filter/plugins/VolumeFilterPlugin.cxx +++ b/src/filter/plugins/VolumeFilterPlugin.cxx @@ -26,7 +26,6 @@ #include "AudioFormat.hxx" #include "util/ConstBuffer.hxx" #include "util/Error.hxx" -#include "util/Domain.hxx" #include #include @@ -50,8 +49,6 @@ public: Error &error) override; }; -static constexpr Domain volume_domain("pcm_volume"); - static Filter * volume_filter_init(gcc_unused const config_param ¶m, gcc_unused Error &error) diff --git a/src/mixer/MixerAll.cxx b/src/mixer/MixerAll.cxx index 5fef6a92f..91891e870 100644 --- a/src/mixer/MixerAll.cxx +++ b/src/mixer/MixerAll.cxx @@ -25,13 +25,10 @@ #include "output/Internal.hxx" #include "pcm/Volume.hxx" #include "util/Error.hxx" -#include "util/Domain.hxx" #include "Log.hxx" #include -static constexpr Domain mixer_domain("mixer"); - static int output_mixer_get_volume(const AudioOutput &ao) { diff --git a/src/output/plugins/PipeOutputPlugin.cxx b/src/output/plugins/PipeOutputPlugin.cxx index 7a1f32258..d8075d505 100644 --- a/src/output/plugins/PipeOutputPlugin.cxx +++ b/src/output/plugins/PipeOutputPlugin.cxx @@ -22,7 +22,6 @@ #include "../OutputAPI.hxx" #include "config/ConfigError.hxx" #include "util/Error.hxx" -#include "util/Domain.hxx" #include @@ -44,8 +43,6 @@ struct PipeOutput { bool Configure(const config_param ¶m, Error &error); }; -static constexpr Domain pipe_output_domain("pipe_output"); - inline bool PipeOutput::Configure(const config_param ¶m, Error &error) { diff --git a/src/playlist/plugins/XspfPlaylistPlugin.cxx b/src/playlist/plugins/XspfPlaylistPlugin.cxx index 5b6010b53..d25d6dc28 100644 --- a/src/playlist/plugins/XspfPlaylistPlugin.cxx +++ b/src/playlist/plugins/XspfPlaylistPlugin.cxx @@ -25,14 +25,11 @@ #include "input/InputStream.hxx" #include "tag/TagBuilder.hxx" #include "util/Error.hxx" -#include "util/Domain.hxx" #include "lib/expat/ExpatParser.hxx" #include "Log.hxx" #include -static constexpr Domain xspf_domain("xspf"); - /** * This is the state object for the GLib XML parser. */ diff --git a/src/unix/Daemon.cxx b/src/unix/Daemon.cxx index 490b2def5..d283108ed 100644 --- a/src/unix/Daemon.cxx +++ b/src/unix/Daemon.cxx @@ -22,7 +22,6 @@ #include "system/FatalError.hxx" #include "fs/AllocatedPath.hxx" #include "fs/FileSystem.hxx" -#include "util/Domain.hxx" #include "PidFile.hxx" #include "Log.hxx" @@ -37,8 +36,6 @@ #include #endif -static constexpr Domain daemon_domain("daemon"); - #ifndef WIN32 /** the Unix user name which MPD runs as */ From 2a58f2264936787ddd96b40c7626046592c2d1a0 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 5 Aug 2015 23:19:22 +0200 Subject: [PATCH 05/14] decoder/mpcdec: use Clamp() --- src/decoder/plugins/MpcdecDecoderPlugin.cxx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/decoder/plugins/MpcdecDecoderPlugin.cxx b/src/decoder/plugins/MpcdecDecoderPlugin.cxx index befed0f3b..91b5b55b9 100644 --- a/src/decoder/plugins/MpcdecDecoderPlugin.cxx +++ b/src/decoder/plugins/MpcdecDecoderPlugin.cxx @@ -26,6 +26,7 @@ #include "util/Error.hxx" #include "util/Domain.hxx" #include "util/Macros.hxx" +#include "util/Clamp.hxx" #include "Log.hxx" #include @@ -117,12 +118,7 @@ mpc_to_mpd_sample(MPC_SAMPLE_FORMAT sample) val = sample * float_scale; #endif - if (val < clip_min) - val = clip_min; - else if (val > clip_max) - val = clip_max; - - return val; + return Clamp(val, clip_min, clip_max); } static void From a7ee64a25b7ffe0ccd499341916070c7b6d02f7a Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 5 Aug 2015 23:18:21 +0200 Subject: [PATCH 06/14] decoder/mpcdec: use SampleTraits Eliminates some duplicate code, and as a side effect, this works around clang 3.8 compiler warning because a negative value was shifted. --- src/decoder/plugins/MpcdecDecoderPlugin.cxx | 24 +++++++++++---------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/decoder/plugins/MpcdecDecoderPlugin.cxx b/src/decoder/plugins/MpcdecDecoderPlugin.cxx index 91b5b55b9..391b5d691 100644 --- a/src/decoder/plugins/MpcdecDecoderPlugin.cxx +++ b/src/decoder/plugins/MpcdecDecoderPlugin.cxx @@ -22,6 +22,7 @@ #include "../DecoderAPI.hxx" #include "input/InputStream.hxx" #include "CheckAudioFormat.hxx" +#include "pcm/Traits.hxx" #include "tag/TagHandler.hxx" #include "util/Error.hxx" #include "util/Domain.hxx" @@ -43,6 +44,9 @@ struct mpc_decoder_data { static constexpr Domain mpcdec_domain("mpcdec"); +static constexpr SampleFormat mpcdec_sample_format = SampleFormat::S24_P32; +typedef SampleTraits MpcdecSampleTraits; + static mpc_int32_t mpc_read_cb(mpc_reader *reader, void *ptr, mpc_int32_t size) { @@ -92,18 +96,15 @@ mpc_getsize_cb(mpc_reader *reader) } /* this _looks_ performance-critical, don't de-inline -- eric */ -static inline int32_t +static inline MpcdecSampleTraits::value_type mpc_to_mpd_sample(MPC_SAMPLE_FORMAT sample) { /* only doing 16-bit audio for now */ - int32_t val; + MpcdecSampleTraits::value_type val; - enum { - bits = 24, - }; - - const int clip_min = -1 << (bits - 1); - const int clip_max = (1 << (bits - 1)) - 1; + constexpr int bits = MpcdecSampleTraits::BITS; + constexpr auto clip_min = MpcdecSampleTraits::MIN; + constexpr auto clip_max = MpcdecSampleTraits::MAX; #ifdef MPC_FIXED_POINT const int shift = bits - MPC_FIXED_POINT_SCALE_SHIFT; @@ -122,7 +123,8 @@ mpc_to_mpd_sample(MPC_SAMPLE_FORMAT sample) } static void -mpc_to_mpd_buffer(int32_t *dest, const MPC_SAMPLE_FORMAT *src, +mpc_to_mpd_buffer(MpcdecSampleTraits::pointer_type dest, + const MPC_SAMPLE_FORMAT *src, unsigned num_samples) { while (num_samples-- > 0) @@ -158,7 +160,7 @@ mpcdec_decode(Decoder &mpd_decoder, InputStream &is) Error error; AudioFormat audio_format; if (!audio_format_init_checked(audio_format, info.sample_freq, - SampleFormat::S24_P32, + mpcdec_sample_format, info.channels, error)) { LogError(error); mpc_demux_exit(demux); @@ -210,7 +212,7 @@ mpcdec_decode(Decoder &mpd_decoder, InputStream &is) mpc_uint32_t ret = frame.samples; ret *= info.channels; - int32_t chunk[ARRAY_SIZE(sample_buffer)]; + MpcdecSampleTraits::value_type chunk[ARRAY_SIZE(sample_buffer)]; mpc_to_mpd_buffer(chunk, sample_buffer, ret); long bit_rate = vbr_update_bits * audio_format.sample_rate From 1958f78cc1bd47ce1c9b57db41194f85aed942ab Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 26 Oct 2015 13:06:29 +0100 Subject: [PATCH 07/14] decoder/ffmpeg: fix crash due to wrong avio_alloc_context() call Allocate the buffer dynamically using av_malloc(), and free AVIOContext.buffer in the destructor, as mandated by the libavformat documentation. Fixes http://bugs.musicpd.org/view.php?id=4446 --- NEWS | 2 ++ src/decoder/plugins/FfmpegDecoderPlugin.cxx | 17 +++++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index 9c44eaf0a..7b5d6df07 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,8 @@ ver 0.19.11 (not yet released) * tags - ape: fix buffer overflow +* decoder + - ffmpeg: fix crash due to wrong avio_alloc_context() call * encoder - flac: fix crash with 32 bit playback diff --git a/src/decoder/plugins/FfmpegDecoderPlugin.cxx b/src/decoder/plugins/FfmpegDecoderPlugin.cxx index d5191a3c3..689089107 100644 --- a/src/decoder/plugins/FfmpegDecoderPlugin.cxx +++ b/src/decoder/plugins/FfmpegDecoderPlugin.cxx @@ -92,14 +92,14 @@ struct AvioStream { AVIOContext *io; - unsigned char buffer[8192]; - AvioStream(Decoder *_decoder, InputStream &_input) :decoder(_decoder), input(_input), io(nullptr) {} ~AvioStream() { - if (io != nullptr) + if (io != nullptr) { + av_free(io->buffer); av_free(io); + } } bool Open(); @@ -153,11 +153,20 @@ mpd_ffmpeg_stream_seek(void *opaque, int64_t pos, int whence) bool AvioStream::Open() { - io = avio_alloc_context(buffer, sizeof(buffer), + constexpr size_t BUFFER_SIZE = 8192; + auto buffer = (unsigned char *)av_malloc(BUFFER_SIZE); + if (buffer == nullptr) + return false; + + io = avio_alloc_context(buffer, BUFFER_SIZE, false, this, mpd_ffmpeg_stream_read, nullptr, input.IsSeekable() ? mpd_ffmpeg_stream_seek : nullptr); + /* If avio_alloc_context() fails, who frees the buffer? The + libavformat API documentation does not specify this, it + only says that AVIOContext.buffer must be freed in the end, + however no AVIOContext exists in that failure code path. */ return io != nullptr; } From ac61d43720393803cb3f6bc5c74aea588e1ca68d Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 26 Oct 2015 16:29:07 +0100 Subject: [PATCH 08/14] output/Command: flush the mixer cache when enabling/disabling output Fixes mixer lag (http://bugs.musicpd.org/view.php?id=4425). --- NEWS | 2 ++ src/output/OutputCommand.cxx | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/NEWS b/NEWS index 7b5d6df07..ee3c318b3 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,8 @@ ver 0.19.11 (not yet released) - ffmpeg: fix crash due to wrong avio_alloc_context() call * encoder - flac: fix crash with 32 bit playback +* mixer + - fix mixer lag after enabling/disabling output ver 0.19.10 (2015/06/21) * input diff --git a/src/output/OutputCommand.cxx b/src/output/OutputCommand.cxx index 6afb70cf1..e6b8a8e7f 100644 --- a/src/output/OutputCommand.cxx +++ b/src/output/OutputCommand.cxx @@ -30,6 +30,7 @@ #include "Internal.hxx" #include "PlayerControl.hxx" #include "mixer/MixerControl.hxx" +#include "mixer/Volume.hxx" #include "Idle.hxx" extern unsigned audio_output_state_version; @@ -47,6 +48,11 @@ audio_output_enable_index(MultipleOutputs &outputs, unsigned idx) ao.enabled = true; idle_add(IDLE_OUTPUT); + if (ao.mixer != nullptr) { + InvalidateHardwareVolume(); + idle_add(IDLE_MIXER); + } + ao.player_control->UpdateAudio(); ++audio_output_state_version; @@ -70,6 +76,7 @@ audio_output_disable_index(MultipleOutputs &outputs, unsigned idx) Mixer *mixer = ao.mixer; if (mixer != nullptr) { mixer_close(mixer); + InvalidateHardwareVolume(); idle_add(IDLE_MIXER); } @@ -94,6 +101,7 @@ audio_output_toggle_index(MultipleOutputs &outputs, unsigned idx) Mixer *mixer = ao.mixer; if (mixer != nullptr) { mixer_close(mixer); + InvalidateHardwareVolume(); idle_add(IDLE_MIXER); } } From 93c97972b9cb41284f8af8b653e056484bbf4717 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 26 Oct 2015 16:32:39 +0100 Subject: [PATCH 09/14] decoder/gme: call decoder_seek_error() on seek error --- src/decoder/plugins/GmeDecoderPlugin.cxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/decoder/plugins/GmeDecoderPlugin.cxx b/src/decoder/plugins/GmeDecoderPlugin.cxx index cc6ce5e5d..eab655c91 100644 --- a/src/decoder/plugins/GmeDecoderPlugin.cxx +++ b/src/decoder/plugins/GmeDecoderPlugin.cxx @@ -196,9 +196,11 @@ gme_file_decode(Decoder &decoder, Path path_fs) if (cmd == DecoderCommand::SEEK) { unsigned where = decoder_seek_time(decoder).ToMS(); gme_err = gme_seek(emu, where); - if (gme_err != nullptr) + if (gme_err != nullptr) { LogWarning(gme_domain, gme_err); - decoder_command_finished(decoder); + decoder_seek_error(decoder); + } else + decoder_command_finished(decoder); } if (gme_track_ended(emu)) From a84fbbe32716ecee9c8a02b50251097fc35709ec Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 26 Oct 2015 17:15:24 +0100 Subject: [PATCH 10/14] decoder/gme: free the gme_info_t as early as possible --- src/decoder/plugins/GmeDecoderPlugin.cxx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/decoder/plugins/GmeDecoderPlugin.cxx b/src/decoder/plugins/GmeDecoderPlugin.cxx index eab655c91..bbe2596c9 100644 --- a/src/decoder/plugins/GmeDecoderPlugin.cxx +++ b/src/decoder/plugins/GmeDecoderPlugin.cxx @@ -156,8 +156,11 @@ gme_file_decode(Decoder &decoder, Path path_fs) return; } - const SignedSongTime song_len = ti->length > 0 - ? SignedSongTime::FromMS(ti->length) + const int length = ti->length; + gme_free_info(ti); + + const SignedSongTime song_len = length > 0 + ? SignedSongTime::FromMS(length) : SignedSongTime::Negative(); /* initialize the MPD decoder */ @@ -168,7 +171,6 @@ gme_file_decode(Decoder &decoder, Path path_fs) SampleFormat::S16, GME_CHANNELS, error)) { LogError(error); - gme_free_info(ti); gme_delete(emu); return; } @@ -179,8 +181,8 @@ gme_file_decode(Decoder &decoder, Path path_fs) if (gme_err != nullptr) LogWarning(gme_domain, gme_err); - if (ti->length > 0) - gme_set_fade(emu, ti->length); + if (length > 0) + gme_set_fade(emu, length); /* play */ DecoderCommand cmd; @@ -207,7 +209,6 @@ gme_file_decode(Decoder &decoder, Path path_fs) break; } while (cmd != DecoderCommand::STOP); - gme_free_info(ti); gme_delete(emu); } From 5719207dfa14cfed63e0446f7f7a8343575a465f Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 26 Oct 2015 17:16:20 +0100 Subject: [PATCH 11/14] gme: don't loop forever, fall back to GME's default play length Fixes http://bugs.musicpd.org/view.php?id=4432 --- NEWS | 1 + src/decoder/plugins/GmeDecoderPlugin.cxx | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index ee3c318b3..463701e35 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,7 @@ ver 0.19.11 (not yet released) - ape: fix buffer overflow * decoder - ffmpeg: fix crash due to wrong avio_alloc_context() call + - gme: don't loop forever, fall back to GME's default play length * encoder - flac: fix crash with 32 bit playback * mixer diff --git a/src/decoder/plugins/GmeDecoderPlugin.cxx b/src/decoder/plugins/GmeDecoderPlugin.cxx index bbe2596c9..b47e9ea66 100644 --- a/src/decoder/plugins/GmeDecoderPlugin.cxx +++ b/src/decoder/plugins/GmeDecoderPlugin.cxx @@ -156,7 +156,7 @@ gme_file_decode(Decoder &decoder, Path path_fs) return; } - const int length = ti->length; + const int length = ti->play_length; gme_free_info(ti); const SignedSongTime song_len = length > 0 @@ -239,9 +239,9 @@ gme_scan_file(Path path_fs, assert(ti != nullptr); - if (ti->length > 0) + if (ti->play_length > 0) tag_handler_invoke_duration(handler, handler_ctx, - SongTime::FromMS(ti->length)); + SongTime::FromMS(ti->play_length)); if (ti->song != nullptr) { if (gme_track_count(emu) > 1) { From f901cd042bb7872cc097c6c2d846b70b022ba3f0 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 27 Oct 2015 10:31:50 +0100 Subject: [PATCH 12/14] doc/user: section about real-time scheduling --- doc/user.xml | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/doc/user.xml b/doc/user.xml index d1c7ff595..010d2f980 100644 --- a/doc/user.xml +++ b/doc/user.xml @@ -1190,6 +1190,58 @@ database { plugin). + +
+ Real-Time Scheduling + + + On Linux, MPD attempts to configure + real-time + scheduling for some threads that benefit from it. + + + + This is only possible you allow MPD + to do it. This privilege is controlled by + RLIMIT_RTPRIO + RLIMIT_RTTIME. You can configure this + privilege with ulimit before launching + MPD: + + + ulimit -HS -r 50; mpd + + + Or you can use the prlimit program from the + util-linux package: + + + prlimit --rtprio=50 --rttime=unlimited mpd + + + The systemd service file shipped + with MPD comes with this setting. + + + + This works only if the Linux kernel was compiled with + CONFIG_RT_GROUP_SCHED disabled. Use the + following command to check this option for your current + kernel: + + + zgrep ^CONFIG_RT_GROUP_SCHED /proc/config.gz + + + + There is a rumor that real-time scheduling improves audio + quality. That is not true. All it does is reduce the + probability of skipping (audio buffer xruns) when the + computer is under heavy load. + + +
From 0cbfb610f232c7a77272039698e5b137267c3159 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 27 Oct 2015 10:32:16 +0100 Subject: [PATCH 13/14] systemd: remove obsolete ControlGroup settings This systemd feature has been removed a while ago without replacement, and it turns out that systemd developers suggest not using control groups at all to assign real-time privileges. Therfore, a replacement feature will not be implement in future systemd releases, and we can really remove those lines completely. See http://bugs.musicpd.org/view.php?id=4413 --- systemd/mpd.service.in | 9 --------- 1 file changed, 9 deletions(-) diff --git a/systemd/mpd.service.in b/systemd/mpd.service.in index a72eb925c..de91eb4d5 100644 --- a/systemd/mpd.service.in +++ b/systemd/mpd.service.in @@ -9,14 +9,5 @@ ExecStart=@prefix@/bin/mpd --no-daemon LimitRTPRIO=50 LimitRTTIME=-1 -# move MPD to a top-level cgroup, as real-time budget assignment fails -# in cgroup /system/mpd.service, because /system has a zero real-time -# budget; see -# http://www.freedesktop.org/wiki/Software/systemd/MyServiceCantGetRealtime/ -ControlGroup=cpu:/mpd - -# assign a real-time budget -ControlGroupAttribute=cpu.rt_runtime_us 500000 - [Install] WantedBy=multi-user.target From db9997a1068e00c5f78d4bb9834ce5a13e7b7a3b Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 27 Oct 2015 10:42:20 +0100 Subject: [PATCH 14/14] release v0.19.11 --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 463701e35..94a676b84 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,4 @@ -ver 0.19.11 (not yet released) +ver 0.19.11 (2015/10/27) * tags - ape: fix buffer overflow * decoder