Compare commits

...

22 Commits

Author SHA1 Message Date
Max Kellermann
fef45d469c release v0.19.20 2016-12-09 20:02:07 +01:00
Max Kellermann
e7353ec7e7 Queue: "setprio" re-enqueues old song if priority has been raised
This commit changes a minor queue priority design to something which
makes a little bit more sense.

Previously, a song that had already been played would only be
re-enqueued if its priority had just been raised above the current
song's.  This means that if it was already above, it was not
re-enqueued.  That is a surprising behavior, because users expect a
song to be played when its priority is raised.

Now the song is always re-enqueued if its priority is raised (and
above the current song's - no matter if it has already been above
before).

 https://bugs.musicpd.org/view.php?id=4592
2016-12-09 13:02:26 +01:00
Max Kellermann
e3237f057d systemd: more paranoid security settings 2016-12-09 10:41:44 +01:00
Florian Schlichting
54d5d9d1cc systemd: protect /usr when running under systemd 2016-12-09 10:41:44 +01:00
Clément B
31d9aebf0b systemd: also disable mpd.socket when disabling mpd.service
e.g. when running 'update-rc.d mpd disable'
2016-12-09 10:41:43 +01:00
Max Kellermann
301abac0c1 LogInit: initialize out_fd properly to avoid closing stdin 2016-12-04 20:13:37 +01:00
Max Kellermann
7019f6bea4 decoder/pcm: round buffer size down to nearest frame size
https://bugs.musicpd.org/view.php?id=4599
2016-11-17 21:58:27 +01:00
Wieland Hoffmann
8bde47280a doc/protocol: Turn the link to the UTF-8 FAQ into a ulink element 2016-11-16 21:25:45 +01:00
Wieland Hoffmann
521c6da830 doc/protocol: UTF=8 → UTF-8 2016-11-16 21:25:40 +01:00
Max Kellermann
5c3e55b5b1 {input,output}/alsa: fix gcc 7.0 -Wimplicit-fallthrough 2016-11-16 19:50:38 +01:00
Max Kellermann
1859ba5ec8 output/winmm: 8 bit playback is not supported
Everything must be S16.
2016-11-07 08:53:57 +01:00
Max Kellermann
ee026386e5 storage/Composite: avoid setting the error twice
If an error has already been set by f.directory->storage->GetInfo(),
don't set it again.
2016-10-27 21:26:55 +02:00
Max Kellermann
49c04ccfc7 decoder/sidplay: fix playback speed with libsidplayfp
https://bugs.musicpd.org/view.php?id=4577
2016-10-27 20:25:19 +02:00
Max Kellermann
11ba44870b decoder/sidplay: simplify seek loop 2016-10-27 20:25:12 +02:00
Max Kellermann
f9a64d24bf storage/Composite: eliminate the second FindStorage() overload
It was used in a wrong way, which did not deal with errors
consistently.  And if that's wrong, there is no need for FindStorage()
at all - let's remove it and the confusion around it.
2016-10-27 19:55:20 +02:00
Max Kellermann
e1a8dcfcc8 storage/Composite: add FindStorage() API documentation 2016-10-27 19:55:08 +02:00
Max Kellermann
1ee0e29974 storage/Composite: fix documentation typo 2016-10-27 17:12:24 +02:00
Max Kellermann
77a9940461 decoder/ffmpeg: ignore empty packets
An empty packet would be a command for avcodec_send_packet() to
finalize the codec.

Fixes https://bugs.musicpd.org/view.php?id=4588
2016-10-26 18:29:07 +02:00
Max Kellermann
9c1c180ae0 tag/Item: declare value[] to have only one element
By declaring the variable-length array to have a nominal size of 1,
struct TagPoolSlot shrinks from 24 bytes to 16 bytes, because "ref"
and "item" now both fit in one machine word.
2016-10-26 18:26:01 +02:00
Max Kellermann
06682bd2a9 tag/Item: remove "packed" attribute, add static_assert on alignment instead
The "packed" attribute triggers a clang 4.0 warning, and it's not
necessary.  All we want is correct allocation of this
dynamically-sized struct.
2016-10-26 18:24:16 +02:00
dennisschagt
7c251fe190 Fix comment in mpdconf.example ("can setting can" -> "setting can") 2016-10-20 15:02:36 +02:00
Max Kellermann
a85455fb3f configure.ac: prepare for 0.19.20 2016-09-27 22:04:46 +02:00
17 changed files with 111 additions and 49 deletions

12
NEWS

@@ -1,3 +1,15 @@
ver 0.19.20 (2016/12/09)
* protocol
- "setprio" re-enqueues old song if priority has been raised
* decoder
- ffmpeg: ignore empty packets
- pcm: fix corruption bug with partial frames (after short read)
- sidplay: fix playback speed with libsidplayfp
* output
- winmm: fix 8 bit playback
* fix gcc 7.0 -Wimplicit-fallthrough
* systemd: paranoid security settings
ver 0.19.19 (2016/08/23)
* decoder
- ffmpeg: bug fix for FFmpeg 3.1 support

@@ -1,10 +1,10 @@
AC_PREREQ(2.60)
AC_INIT(mpd, 0.19.19, musicpd-dev-team@lists.sourceforge.net)
AC_INIT(mpd, 0.19.20, musicpd-dev-team@lists.sourceforge.net)
VERSION_MAJOR=0
VERSION_MINOR=19
VERSION_REVISION=19
VERSION_REVISION=20
VERSION_EXTRA=0
AC_CONFIG_SRCDIR([src/Main.cxx])

@@ -164,7 +164,7 @@
# Permissions #################################################################
#
# If this setting is set, MPD will require password authorization. The password
# can setting can be specified multiple times for different password profiles.
# setting can be specified multiple times for different password profiles.
#
#password "password@read,add,control,admin"
#

@@ -66,8 +66,8 @@
<function>strcpy</function> just fine with UTF-8 encoded
strings. For example: <returnvalue>OK</returnvalue> encoded in
UTF-8 is simply <returnvalue>OK</returnvalue>. For more
information on UTF=8:
http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8)
information on UTF-8:
<ulink url="http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8"/>)
</para>
</section>

@@ -51,7 +51,7 @@ static constexpr Domain log_domain("log");
#ifndef ANDROID
static int out_fd;
static int out_fd = -1;
static AllocatedPath out_path = AllocatedPath::Null();
static void redirect_logs(int fd)

@@ -643,7 +643,7 @@ FfmpegDecode(Decoder &decoder, InputStream &input,
/* end of file */
break;
if (packet.stream_index == audio_stream) {
if (packet.size > 0 && packet.stream_index == audio_stream) {
cmd = ffmpeg_send_packet(decoder, input,
packet,
*codec_context,

@@ -23,10 +23,28 @@
#include "input/InputStream.hxx"
#include "util/Error.hxx"
#include "util/ByteReverse.hxx"
#include "util/StaticFifoBuffer.hxx"
#include "Log.hxx"
#include <assert.h>
#include <string.h>
template<typename B>
static bool
FillBuffer(Decoder &decoder, InputStream &is, B &buffer)
{
buffer.Shift();
auto w = buffer.Write();
assert(!w.IsEmpty());
size_t nbytes = decoder_read(decoder, is, w.data, w.size);
if (nbytes == 0 && is.LockIsEOF())
return false;
buffer.Append(nbytes);
return true;
}
static void
pcm_stream_decode(Decoder &decoder, InputStream &is)
{
@@ -50,25 +68,27 @@ pcm_stream_decode(Decoder &decoder, InputStream &is)
decoder_initialized(decoder, audio_format,
is.IsSeekable(), total_time);
StaticFifoBuffer<uint8_t, 4096> buffer;
DecoderCommand cmd;
do {
char buffer[4096];
size_t nbytes = decoder_read(decoder, is,
buffer, sizeof(buffer));
if (nbytes == 0 && is.LockIsEOF())
if (!FillBuffer(decoder, is, buffer))
break;
auto r = buffer.Read();
/* round down to the nearest frame size, because we
must not pass partial frames to decoder_data() */
r.size -= r.size % frame_size;
buffer.Consume(r.size);
if (reverse_endian)
/* make sure we deliver samples in host byte order */
reverse_bytes_16((uint16_t *)buffer,
(uint16_t *)buffer,
(uint16_t *)(buffer + nbytes));
reverse_bytes_16((uint16_t *)r.data,
(uint16_t *)r.data,
(uint16_t *)(r.data + r.size));
cmd = nbytes > 0
? decoder_data(decoder, is,
buffer, nbytes, 0)
cmd = !r.IsEmpty()
? decoder_data(decoder, is, r.data, r.size, 0)
: decoder_get_command(decoder);
if (cmd == DecoderCommand::SEEK) {
uint64_t frame = decoder_seek_where_frame(decoder);
@@ -76,6 +96,7 @@ pcm_stream_decode(Decoder &decoder, InputStream &is)
Error error;
if (is.LockSeek(offset, error)) {
buffer.Clear();
decoder_command_finished(decoder);
} else {
LogError(error);

@@ -354,12 +354,19 @@ sidplay_file_decode(Decoder &decoder, Path path_fs)
DecoderCommand cmd;
do {
short buffer[4096];
size_t nbytes;
nbytes = player.play(buffer, ARRAY_SIZE(buffer));
if (nbytes == 0)
const auto result = player.play(buffer, ARRAY_SIZE(buffer));
if (result <= 0)
break;
#ifdef HAVE_SIDPLAYFP
/* libsidplayfp returns the number of samples */
const size_t nbytes = result * sizeof(buffer[0]);
#else
/* libsidplay2 returns the number of bytes */
const size_t nbytes = result;
#endif
decoder_timestamp(decoder, (double)player.time() / timebase);
cmd = decoder_data(decoder, nullptr, buffer, nbytes, 0);
@@ -376,12 +383,9 @@ sidplay_file_decode(Decoder &decoder, Path path_fs)
}
/* ignore data until target time is reached */
while(data_time<target_time) {
nbytes=player.play(buffer, ARRAY_SIZE(buffer));
if(nbytes==0)
break;
while (data_time < target_time &&
player.play(buffer, ARRAY_SIZE(buffer)) > 0)
data_time = player.time();
}
decoder_command_finished(decoder);
}

@@ -247,6 +247,10 @@ AlsaInputStream::Recover(int err)
case -EPIPE:
LogDebug(alsa_input_domain, "Buffer Overrun");
// drop through
#if GCC_CHECK_VERSION(7,0)
[[fallthrough]];
#endif
case -ESTRPIPE:
case -EINTR:
err = snd_pcm_recover(capture_handle, err, 1);

@@ -760,6 +760,9 @@ alsa_recover(AlsaOutput *ad, int err)
if (err == -EAGAIN)
return 0;
/* fall-through to snd_pcm_prepare: */
#if GCC_CHECK_VERSION(7,0)
[[fallthrough]];
#endif
case SND_PCM_STATE_SETUP:
case SND_PCM_STATE_XRUN:
ad->period_position = 0;

@@ -148,10 +148,10 @@ winmm_output_open(AudioOutput *ao, AudioFormat &audio_format,
}
switch (audio_format.format) {
case SampleFormat::S8:
case SampleFormat::S16:
break;
case SampleFormat::S8:
case SampleFormat::S24_P32:
case SampleFormat::S32:
case SampleFormat::FLOAT:

@@ -426,14 +426,15 @@ Queue::SetPriority(unsigned position, uint8_t priority, int after_order)
if (_order < (unsigned)after_order) {
/* the specified song has been played already
- enqueue it only if its priority has just
become bigger than the current one's */
- enqueue it only if its priority has been
increased and is now bigger than the
current one's */
const unsigned after_position =
OrderToPosition(after_order);
const Item *after_item =
&items[after_position];
if (old_priority > after_item->priority ||
if (priority <= old_priority ||
priority <= after_item->priority)
/* priority hasn't become bigger */
return true;

@@ -265,22 +265,13 @@ CompositeStorage::FindStorage(const char *uri) const
return result;
}
CompositeStorage::FindResult
CompositeStorage::FindStorage(const char *uri, Error &error) const
{
auto result = FindStorage(uri);
if (result.directory == nullptr)
error.Set(composite_domain, "No such directory");
return result;
}
bool
CompositeStorage::GetInfo(const char *uri, bool follow, FileInfo &info,
Error &error)
{
const ScopeLock protect(mutex);
auto f = FindStorage(uri, error);
auto f = FindStorage(uri);
if (f.directory->storage != nullptr &&
f.directory->storage->GetInfo(f.uri, follow, info, error))
return true;
@@ -295,6 +286,8 @@ CompositeStorage::GetInfo(const char *uri, bool follow, FileInfo &info,
return true;
}
if (!error.IsDefined())
error.Set(composite_domain, "No such directory");
return false;
}
@@ -304,13 +297,15 @@ CompositeStorage::OpenDirectory(const char *uri,
{
const ScopeLock protect(mutex);
auto f = FindStorage(uri, error);
auto f = FindStorage(uri);
const Directory *directory = f.directory->Find(f.uri);
if (directory == nullptr || directory->children.empty()) {
/* no virtual directories here */
if (f.directory->storage == nullptr)
if (f.directory->storage == nullptr) {
error.Set(composite_domain, "No such directory");
return nullptr;
}
return f.directory->storage->OpenDirectory(f.uri, error);
}

@@ -45,7 +45,7 @@ class CompositeStorage final : public Storage {
*/
struct Directory {
/**
* The #Storage mounted n this virtual directory. All
* The #Storage mounted in this virtual directory. All
* "leaf" Directory instances must have a #Storage.
* Other Directory instances may have one, and child
* mounts will be "mixed" in.
@@ -155,9 +155,16 @@ private:
}
}
/**
* Follow the given URI path, and find the outermost directory
* which is a #Storage mount point. If there are no mounts,
* it returns the root directory (with a nullptr "storage"
* attribute, of course). FindResult::uri contains the
* remaining unused part of the URI (may be empty if all of
* the URI was used).
*/
gcc_pure
FindResult FindStorage(const char *uri) const;
FindResult FindStorage(const char *uri, Error &error) const;
const char *MapToRelativeUTF8(const Directory &directory,
const char *uri) const;

@@ -21,7 +21,6 @@
#define MPD_TAG_ITEM_HXX
#include "TagType.h"
#include "Compiler.h"
/**
* One tag value. It is a mapping of #TagType to am arbitrary string
@@ -35,11 +34,14 @@ struct TagItem {
/**
* the value of this tag; this is a variable length string
*/
char value[sizeof(long) - sizeof(type)];
char value[1];
TagItem() = default;
TagItem(const TagItem &other) = delete;
TagItem &operator=(const TagItem &other) = delete;
} gcc_packed;
};
static_assert(sizeof(TagItem) == 2, "Unexpected size");
static_assert(alignof(TagItem) == 1, "Unexpected alignment");
#endif

@@ -50,7 +50,7 @@ struct TagPoolSlot {
static TagPoolSlot *Create(TagPoolSlot *_next, TagType type,
const char *value, size_t length);
} gcc_packed;
};
TagPoolSlot *
TagPoolSlot::Create(TagPoolSlot *_next, TagType type,

@@ -9,5 +9,18 @@ ExecStart=@prefix@/bin/mpd --no-daemon
LimitRTPRIO=50
LimitRTTIME=infinity
# disallow writing to /usr, /bin, /sbin, ...
ProtectSystem=yes
# more paranoid security settings
NoNewPrivileges=yes
ProtectKernelTunables=yes
ProtectControlGroups=yes
ProtectKernelModules=yes
# AF_NETLINK is required by libsmbclient, or it will exit() .. *sigh*
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX AF_NETLINK
RestrictNamespaces=yes
[Install]
WantedBy=multi-user.target
Also=mpd.socket