Apparently, if snd_pcm_drain() returns EAGAIN, it does not actually
want to be called again; the next call will snd_pcm_drain() will also
return EAGAIN, forever, even though the PCM state has meanwhile
switched to SND_PCM_STATE_SETUP. This causes a busy loop; to fix
this, we should always check snd_pcm_state() to see if draining is
really required.
Workaround for a regression caused by commit
a06bf388d9, revealing a problem with
discarding odd numer of frames in the DSD_U32 and DoP converters,
causing distortions with DSD_U32 and DoP on 32 bit CPUs.
Closes https://github.com/MusicPlayerDaemon/MPD/issues/469
Instead of passing tag and group, pass an array of tags. To support a
nested return value, return a nested std::map of std::maps. Each key
specifies the tag value, and each value may be another nesting level.
Closes https://github.com/MusicPlayerDaemon/MPD/issues/408
Since we now don't duplicate all items, we can easily remove the 64kB
limit from OpusReader::ReadString() and instead silently ignore and
skip all strings which are longer than 4 kB.
This fixes a tag duplication bug with Opus file containing a very long
`METADATA_BLOCK_PICTURE` tag, which occurred because the Opus plugin
returned false after parsing all tags, and then the MPD core fell back
to FFmpeg which scanned the tags again.
Return `404 not found` for some common well-known paths, as clients requesting them usually do that automatically and don't expect endless audio stram.
Closes#572
This reverts commit ff3e2c0514. The
check was necessary, after all, because this is what checked whether
the decoder had finished the current or the next song.
> The "queued" flag can only possibly be set if the decoder is still
> decoding the current song or if the decoder is stopped.
That was wrong because ProcessCommand() sets `queued=true` and also
starts the decoder (if it was idle).
> This is also what the following assert() checks.
That was also wrong, because the assert() has two conditions.
Closes https://github.com/MusicPlayerDaemon/MPD/issues/566
If the decoder finishes decoding the current song between the two
IsIdle() checks, MPD stops playback instead of starting the decoder
for the next song.
This is usually not visible problem, because the main thread restarts
it via playlist::ResumePlayback(), but that way it, ignores "single"
mode.
As a workaround, this commit adds another "queued" check which
re-enters the player loop and checks again whether to start the
decoder.
Closes https://github.com/MusicPlayerDaemon/MPD/issues/556
Commit b3a458338a added a LocateUri()
call to several playlist commands, which applied InputPlugin URI
scheme verification to playlist URIs. This broke the SoundCloud
playlist plugin which uses "soundcloud://" URIs for which no input
plugin exists.
This commit allows the caller to specify the kind of plugin which
shall be used to verify the URI. Right now, only "input" is
implemented; "storage" uses the "input" verification for now; and
"playlist" has no verification at all (for now).
Closes https://github.com/MusicPlayerDaemon/MPD/issues/528
Expect OnSocketReady() to cancel events. If it returns false, the
SocketMonitor may be destructed already. This fixes a use-after-free
bug in the "httpd" output plugin.
Fixes:
src/net/IPv4Address.hxx: In member function 'constexpr IPv4Address::operator SocketAddress() const':
src/net/IPv4Address.hxx:171:24: error: a reinterpret_cast is not a constant expression
171 | return SocketAddress((const struct sockaddr *)&address,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/net/IPv6Address.hxx: In member function 'constexpr IPv6Address::operator SocketAddress() const':
src/net/IPv6Address.hxx:138:24: error: a reinterpret_cast is not a constant expression
138 | return SocketAddress((const struct sockaddr *)&address,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Closes https://github.com/MusicPlayerDaemon/MPD/issues/522
Meson 0.49.0 adds native support for `libgcrypt-config` which is
necessary for detecting libgcrypt dependencies, as the latest
version 1.8.4 of libgcrypt does not provide a .pc file.
And disable libvorbis detection if Tremor was explicitly enabled.
This fixes a crash bug caused by libvorbis/Tremor ABI conflict caused
by commit 4f7d52dbf2
Previously, MPD would skip the current song after attempting to seek
to its beginnig, because that was a seek to offset 0. At offset 0,
MPD will see the BOS packet again, which results in throwing
StopDecoder in MPDOpusDecoder::OnOggEnd().
Closes https://github.com/MusicPlayerDaemon/MPD/issues/470
Unlike pa_channel_map_init_auto(), pa_channel_map_init_extend() does
not fail if there is no valid mapping for the given channel count, but
instead maps additional "AUX" channels.
Closes https://github.com/MusicPlayerDaemon/MPD/issues/493
libwrap is an obscure artefact from a past long ago, when source IP
address meant something.
And its API is "interesting"; it requires the application to expose
two global variables `allow_severity` and `deny_severity`. This led
to bug #437. I don't want to declare those variables; instead, I'd
like to remove libwrap support.
Closes#437
This fixes a problem which caused a failure with snd_pcm_writei()
because snd_pcm_drain() had already been called in the previous
iteration. This commit makes sure that snd_pcm_drain() is only called
after the final snd_pcm_writei() call.
This fixes discarded samples at the end of playback.
If our `ring_buffer` is smaller than the ALSA-PCM buffer (if the
latter has more than the 4 periods we allocate), it can happen that
the start threshold is crossed and ALSA switches to
`SND_PCM_STATE_RUNNING`, but the `ring_buffer` is empty. In this
case, MPDD will generate silence, even though the ALSA-PCM buffer has
enough data. This causes stuttering (#420).
This commit amends an older workaround for a similar problem (commit
e08598e7e2) by adding a snd_pcm_avail()
check, and only generate silence if there is less than one period of
data in the ALSA-PCM buffer.
Fixes#420
The method Cancel() assumes that the `period_buffer` must be empty
when `active==false`, but that is not the case when Play() fails.
Of course the assertion in Cancel() is not 100% correct, but I decided
to rather fix this in LockCaughtError() because the `period_buffer`
should only be accessed from within the RTIO thread, and this is the
only code path where `active` can be set to `false` with a non-empty
`period_buffer`.
Fixes#423
When `metadata_sent` is `false`, the plugin assumes there is metadata
which must be sent, even if no metadata page was passed to the plugin.
Initializing it to `true` avoids dereferencing this `nullptr`.
Fixes#412
If the output is already open, the `current_chunk` pointer may be
bogus and out of sync with `SharedPipeConsumer::chunk`, leading to an
assertion failure in `SharedPipeConsumer::Consume()`.
Fixes#411
`AVCodecParameters` contains values from the codec detected by
avformat_find_stream_info(), but after avcodec_open2(), a different
codec might be selected with a different `AVSampleFormat`. This leads
to misinterpretation of data returned from FFmpeg, leading to random
noise or silence.
This was observed with FFmpeg 4.0.2 and a TS container file containing
MP2. A mp3-float codec was detected returning `AV_SAMPLE_FMT_FLTP`,
but finally the `mpegaudiodec_fixed.c` was used, returning
`AV_SAMPLE_FMT_S16`.
By using the audio format from `AVCodecContext`, we ensure that MPD
and FFmpeg always agree on the actual audio format in the buffer.
This removes the FFmpeg bug workaround from commit e1b032cbad which I
assume is obsolete after 7 years.
Fixes#380
The protocol documentation says that the difference between `find` and
`search` is that `search` is case insensitive, but that's only half
the truth: `search` also searches for sub strings instead of matching
the whole string. This part is undocumented and unfortunate, but at
this point, we can't change it.
However leaking this surprising behavior to the new filter expressions
was a bad idea; the "==" operator should never match substrings. For
people who need that, we should add a new operator.
Meson 0.47.1 suffers from a bug which breaks linking the MPD
executable because the `-lpthread` flag is not propagated from our
`thread.a`.
See https://github.com/mesonbuild/meson/pull/3895Closes#403
Thanks to C++14, we can declare and fill variables inside `constexpr`
functions. This means me can stop make assumptions on the `struct`
layouts without losing `constexpr`.
Closes#393
Bugs in libroar which broke the MPD build have been annoying me for
quite some time, and the newest bug has now hit my main build machine:
https://github.com/MusicPlayerDaemon/MPD/issues/377
Problem is the usage of the typedef `_IO_off64_t` in libroar's
`vio_stdio.h`:
int roar_vio_to_stdio_lseek (void *__cookie, _IO_off64_t *__pos, int __w);
This `_IO_off64_t` is an internal implementation detail of glibc and
was removed in version 2.28. Nobody must ever use it. Why the ****
did the RoarAudio developers use it? Not using internal typedefs
isn't exactly rocket science.
This annoys me enough to finally remove the plugin. Anyway, I've
never heard of anybody using RoarAudio, so my best guess is that
nobody will notice.
The compile-time calculation for `factor` overflows because `1<<31`
cannot be represented by `int`. By casting to `uintmax_t` first, we
can avoid this overflow.
Closes#380
Grouping in the "list" command was completely broken from the start,
unlike "count group". I have no idea what I have been thinking when I
wrote commit ae178c77bd, but it didn't
make any sense.
This commit is a rewrite of the feature.
For clients to be able to detect this feature, this commit also
increments the protocol version.
So long, autotools! This is my last MPD related project to migrate
away from it. It has its strengths, but also very obvious weaknesses
and weirdnesses. Today, many of its quirks are not needed anymore,
and are cumbersome and slow. Now welcome our new Meson overlords!
Previously, there was the setting `buffered_before_play` which
specified a percentage of the audio buffer, defaulting to `10%`. That
was working well enough for quite some time, until high-quality audio
formats became common.
At 44.1 kHz, 16 bit stereo, MPD collected 2.3 seconds worth of data in
the buffer before starting playback. With the same default settings
and 192 kHz, 24 bit stereo, that was only 0.27 seconds.
Making this depend on the byte size only leads to high latency at low
quality, and too little data at high quality. The natural choice
would be to use a duration instead of a byte size, which should give
the same good experience with all audio formats.
Since the `buffered_before_play` configuration setting was not
understood well by users and caused more harm than good, this commit
deprecates it. It has now no effect.
- add Settings: Activity to start / stop MPD Service (Main).
- Main is a service that run in foreground with a notification. See
Service.startForeground documentation for more details.
- Main.Client is used to control the service: start or stop it and also receive
callbacks when service encounters an error, is killed, is started or is
stopped.
- Main.start to start the service without any fallback.
When using a database that was not created with a WebDAV music_directory
(i.e., if using a remote database, on which updates happen locally) and
using the Curl storage plugin, MPD would previously send GET requests that
had unescaped spaces in them. This change uses Curl's URL-encode API to
solve this.
With a "+" or "-" prefix, the "metadata_to_use" setting can manipulate
the existing default. This way, one can enable `TAG_COMMENT` without
having to list all the other tags.
This code was added in 21851c0673 but
looks completely broken:
- the status code is "206 OK" but "206" would be "Partial Content"
- the "Content-Length" header has a bogus value
- the "Content-RangeX" parameter has different bogus values (why
"Content-RangeX" anyway and not "Content-Range"?)
Apart from that, there are strange undocumented non-standard headers
which are probably there to work around bugs/expectations in one
broken proprietary client product. But these days, MPD doesn't bend
over to support broken clients. So let's kill this code.
Closes#304
For remote files (not streams), this downloads as quickly as possible
to a large buffer instead of throttling the stream during playback.
Throttling can make the server impatient and it may then disconnect.
This is what Qobuz and Tidal do, and this commit attempts to solve
this by not letting the Qobuz/Tidal server wait (closes#241).
Error message sent to client was "basic_string::_M_construct null not
valid" due to passing nullptr to the std::string constructor.
Regression caused by commit 386688b87a