This allows canceling the blocking method LockWaitWriteAvailable(),
and thus allows breaking free of misbehaving ALSA drivers, avoiding a
MPD lockup.
Closes https://github.com/MusicPlayerDaemon/MPD/issues/966
This fixes a spurious "single" mode bug which occurs when using "play"
or "seek" to start playback on the song that is currently paused: in
that case, the main thread never queues the next song, and at the end
of the song, the player thread exits Run(), stopping playback, and
after that, the main thread starts the next song without considering
"single" mode.
By calling OnPlayerSync(), we ensure that the main thread gets a
chance to queue the next song before the player thread exits the Run()
loop.
Closes https://github.com/MusicPlayerDaemon/MPD/issues/850
The log levels have always been very confusing (and badly named), but
this was most confusing: if there's a log level called "default", why
is it not the default?
Closes https://github.com/MusicPlayerDaemon/MPD/issues/926
Oh the horror! This plugin cannot possibly ever have worked. It was
broken from the start, when it was added in commit 37796699cf nearly
twelve (!) years ago.
The plugin would always read at sector boundaries, so it could only
ever work at multiples of 2 kB.
While libsndfile doesn't like partial reads in the middle of a file
(see commit 95ac6071b9), it allows partial reads at the end of a file.
It doesn't pay attention to the file size when issuing a read.
Commit ecb67a1ed1 (MPD 0.18.12) was a regression: previously,
partial reads at the end of a file were possible, but switching to
decoder_read_full() made this an error condition. This way, a portion
at the end of each file was lost, leading to corruption with gapless
playback (https://github.com/MusicPlayerDaemon/MPD/issues/936).
This fix switches to the newly introduced function
decoder_read_much(), which does the same as the code before commit
ecb67a1ed1.
Closes https://github.com/MusicPlayerDaemon/MPD/issues/936
Our AudioObjectGetPropertyDataT() wrapper throws exception on error,
and calling it from OSXOutput::Disable() can cause MPD crash due to
std::terminate().
Closes https://github.com/MusicPlayerDaemon/MPD/issues/932
When mounting something over a directory that is already a mount
point, CompositeStorage::Mount() silently overwrites the previously
mounted storage, disposing it. After that, SimpleDatabase::Mount()
will fail and handle_mount() will roll back the
CompositeStorage::Mount() command, effectively unmounting what was
there before (and also leaking memory).
Closes https://github.com/MusicPlayerDaemon/MPD/issues/918
Bug #915 is about an I/O exception thrown where none was allowed,
leading to crash via std::terminate(). However, instead of catching
and logging the error inside the decoder plugin, it should be able to
propagate the I/O error to the MPD core, so MPD can avoid trying other
decoder plugins.
Closes https://github.com/MusicPlayerDaemon/MPD/issues/915
The formula in osx_output_score_sample_rate() to detect multiples of
the source sample rate was broken: when given a 44.1 kHz input file,
it preferred 16 kHz over 48 kHz, because its `frac_portion(16)=0.75`
is smaller than `frac_portion(48)=0.91`.
That formula, introduced by commit 40a1ebee29, looks completely
wrong. It doesn't do what the code comment pretends it does.
Instead of using that `frac_portion` to calculate a score, this patch
adds to the score only if `frac_portion` is nearly `0` or `1`. This
means that the factor is nearly integer.
Closes https://github.com/MusicPlayerDaemon/MPD/issues/904
A bug report (https://github.com/MusicPlayerDaemon/MPD/issues/912)
suggests that on Linux, reading on `cifs` files may rarely return 0 (=
end of file) before the end of the file has really been reached. But
that's just a theory which I need to validate, so this runtime check
shall catch this condition before the assertion in
DecoderBridge::Read() crashes MPD. Let's see.
Closes https://github.com/MusicPlayerDaemon/MPD/issues/912
An assertion failure in UpdateQueuedSong() could trigger because the
`prev` parameter is always `nullptr`, but `queued` may be set. And in
fact, calling UpdateQueuedSong() is only necessary when the queued
song was edited, to re-queue it with the new range.
Closes https://github.com/MusicPlayerDaemon/MPD/issues/901
When the client wants to seek, but the decoder has already finished
decoding the current song, the player restarts the decoder with an
initial seek at the new position. When this initial seek fails, MPD
pretends nothing has happened and plays this song from the start.
With this new flag, a restarted decoder marks the initial seek as
"essential" and fails the decoder if that seek fails.
Closes https://github.com/MusicPlayerDaemon/MPD/issues/895
The WildMidi project added the pkg-config file in version 0.3.3, but
unfortunately, Debian still doesn't ship it 4 years later:
https://bugs.debian.org/916631
However, for cross-compiling, the pkg-config file is very helpful.
This is the final piece of the series to establish io_uring support on
Linux.
MPD doesn't need io_uring for its efficient bulk I/O support, but to
allow file I/O to be cancelled. This is a big problem on CIFS/NFS
mounts where processes sleep uninterruptable if the file server
disappears, deadlocking MPD.
With io_uring, a flaky NFS connection allows MPD to continue to work
(even though there are still deadlocks inside MPD which need to be
addressed).
This plugin does not yet use cancellable `open()` using
`IORING_OP_OPENAT`. This will be implemented later.
Lots of other optimization opportunities for io_uring are still
missing as well - for example the database update could benefit a lot,
but unfortunately, io_uring doesn't have `readdir()` support just yet.
The command is used to configure the client's connection, and this
shouldn't require any permissions. The client should be able to do
that before sending a password.
This fixes a freeze bug in the NFS input/storage plugins: when libnfs
auto-reconnets after a failure, it installs the new socket on the same
file descriptor number. MPD's attempt to unregister the old socket by
calling SocketMonitor::Steal() from NfsConnection::ScheduleSocket()
fails because the new/old socket number is not registered in epoll, so
epoll_ctl() returns ENOENT. The problem is that it left
`scheduled_flags`, and so subsequent Schedule() calls will use
`EPOLL_CTL_MOD`, which will fail again and again. Instead, we need to
use `EPOLL_CTL_ADD` to register the new socket.
Closes https://github.com/MusicPlayerDaemon/MPD/issues/806
Closes https://github.com/MusicPlayerDaemon/MPD/issues/756
Unescape the base path and the path coming from the server (href) to fix the
comparison when the server uses different escaped characters.
The outputted name need to be unescaped. Doing that before or after the
HrefToEscapedName() call should not change the current behavior.
If the file name is "Hello & bye", 3 CharacterData events will be sent with the
State::HREF state:
- "Hello%20"
- "&"
- "%20bye"
Reproduced with files hosted on an apache2 DAV server: 2.4.38-3+deb10u3.
Documentation says the limit is 5, but it was really 10 (at least
since 2004). But since MPD wants to promote using many small clients
idling around, and these clients consume only very few resources, it
seems reasonable to raise this limit's default value.
Aparently, libcdio sometimes returns empty filenames, causing MPD
crashes. This shouldn't really happen, and I consider this a libcdio
bug - but if it happens, people blame MPD, so let's add a check.
Closes https://github.com/MusicPlayerDaemon/MPD/issues/776
Using libgme 0.6.2 on macOS, it appears that gme_info_t strings can be
empty, which creates weird track titles: (001/050)
This adds an additional check for an empty string.
"The issue is that ParseCommandArgSignedSongTime parses with
SongTime::FromS, not SignedSongTime::FromS, before casting back to a
SignedSongTime for the return. With x86 overflow rules this doesn't
matter, but on ARM the first cast turns negative values to zero."
Closes https://github.com/MusicPlayerDaemon/MPD/issues/757
This reverts commit c84bae739a. A
configuration option is not necessary, because the PcmConvert
constructor knows already whether integer or floating point is needed.
It appears that [[fallthrough]] is valid in C++ but not in C. And
in some Clang versions (e.g. Clang 11 on macOS), Clang is pedantic
about this and considers it an error to use [[fallthrough]] in a
.c file such as src/util/format.c.
This changes makes gcc_fallthrough a no-op under Clang in C files.
This prepares the migration away from strptime() for Windows
portability.
But the real reason I'm doing this is that strptime() on Apple is
buggy: strptime("14", "%H%M%S") (without separating colons) succeeds
even though only the hour has been parsed. This fixes recent Travis
failures in the ParseISO8601() unit test.
This can cause request completion in the I/O thread before this
constructor returns, leaving the object in an abstract state, causing
a crash due to pure virtual method call. We should not start the
request until this object is fully constructed.
Closes https://github.com/MusicPlayerDaemon/MPD/issues/665
The ALSA "null" driver opens /dev/null and returns the file handle
from snd_pcm_poll_descriptors(), but /dev/null cannot be used with
epoll, the epoll_ctl() system call returns -EPERM. This means that
the ALSA output hangs, eventually freezing the whole MPD process.
This commit adds a workaround to the MultiSocketMonitor class which is
used by the ALSA output plugin.
Closes https://github.com/MusicPlayerDaemon/MPD/issues/695
Most importantly, this commit translates ZZIP_ENOENT to
std::system_error(ENOENT) so IsFileNotFound() returns true and
find_stream_art() can suppress the log line.
Commit 13208bf5a7 added range support to
the `move` command, but applied the wrong offset to the `to` variable.
When the source range is before the current song, and the song thus
gets decremented by the range size, then the final destination offset
must also be decremented by the range size.
Closes https://github.com/MusicPlayerDaemon/MPD/issues/663
On linux-rt, kernel IRQ threads are configured with priority=50, and
this change configures MPD somewhat below that priority, leaving some
room for other programs to be configured in between.
Closes https://github.com/MusicPlayerDaemon/MPD/issues/643
Without requesting the property, "good" WebDAV servers would not send
it, and so MPD could never recognize a directory, failing the database
update.
Closes https://github.com/MusicPlayerDaemon/MPD/issues/660
Apparently, libmpcdec sets gain/peak variables to zero if they are not
present. This clashes with our formula and results in bogus values
which cause noise during playback.
Closes https://github.com/MusicPlayerDaemon/MPD/issues/640
This commit adds a PlaylistPlugin attribute "as_folder" which for now
is only enabled in the "CUE" playlist plugin (which handles separate
"*.cue" files). If a playlist with this flag set is being scanned
during database update, it will be parsed and its contents will be
added to the database. This allows clients to inspect them like
directories and its contents will be searchable.
Closes https://github.com/MusicPlayerDaemon/MPD/issues/39
The new Response instance in the `catch` block didn't have the
`command` attribute set, so the error response didn't indicate which
command had failed, which however is required in the MPD protocol.
Closes https://github.com/MusicPlayerDaemon/MPD/issues/628
SID files are generally collections of tunes, so a SID name field makes
sense as an MPD album. The SID tune information list (STIL) has name
and title fields for individual tunes, when such are known, but MPD is
currently not using the STIL.
High Voltage SID Collection (HVSC) metadata fields are encoded in
windows-1252, as described in DOCUMENTS/SID_file_format.txt:
https://www.hvsc.c64.org/download/C64Music/DOCUMENTS/SID_file_format.txt
If utf-8 transcoding fails, or the ICU library is unavailable, fall
back to plain ASCII and replace other characters with '?'.
Version 10.2+0.93+1 was released five years ago in 2014 and is the
first version to feature cdio_cddap_free_messages(). There is no way
to check the libcdio-paranoia version at compile time, so let's just
remove support for older versions instead of attempting to fix the
cdio_cddap_free_messages() check at build time.
Closes https://github.com/MusicPlayerDaemon/MPD/issues/613
This reverts commit f7ed7446ae. It was
a bad idea, because MAD_F_MIN and MAD_F_MAX do not represent the
clamping limits, but the theoretical minimum and maximum values of the
mad_fixed_t data type.
Closes https://github.com/MusicPlayerDaemon/MPD/issues/617
This is useful in multiple mpd instances scenario, or multiple pulse outputs defined on the same mpd instance.
It is actually a more flexible way to route flows than the "sink" parameter, letting the PulseAudio routing do its job, but with the ability to isolate routing for each output.
If not specified, the role remains like it was before this commit, ie "music"
The check IsSeekableCurrentSong() was added by commit
44b200240f in version 0.20.19, but it
caused a regression: by doing the branch only if the current song is
seekable, the player would restart the current song if it was not
seekable, and later the initial seek would fail; but we already know
it's not seekable, and so we should fail early.
Applying software volume to S16 samples means several bits of
precision are lost; at 25% volume, two bits are lost. Additionally,
dithering adds some noise.
The problem gets worse when you apply the software volume code twice:
for the software mixer volume, and again for the replay gain. This
loses some more precision and adds even more dithering noise, which
can become audible (see
https://github.com/MusicPlayerDaemon/MPD/issues/542).
By converting everything to 24 bit, we need to shift only two bits to
the right instead of ten, losing nearly no precision, and dithering is
not needed. Even if the output device is unable to play S24 directly,
we can convert back to S16 with only one stage of dithering.
Closes https://github.com/MusicPlayerDaemon/MPD/issues/542
MPD used to do that when this code lived in the player thread, but it
was removed by commit 98a7c62d7a4f716d90af6d78e18d1a3b10bc54b3; and
the replacement code in the ALSA output plugin didn't have it.
Without this timer, DispatchSockets() may disable the
MultiSocketMonitor and if Play() doesn't get called soon, it never
gets a chance to generate silence. However if Play() gets called,
generating silence isn't necessary anymore...
Resulting from this misdesign (added by commit ccafe3f3cf in 0.21.3),
the silence generator didn't work reliably.
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
When switching to another song manually, the player checks if the
decoder is already decoding that song; if so, it will attempt to reuse
it by seeking it to the new position. That however fails if the
decoder is not seekable (e.g. a radio stream) which leaves the user
unable to switch to that song with the bogus error message "Not
seekable".
Instead of stopping playback (due to seek time overflow), reject the
seek command. Closes#240
Relative negative values (with "seekcur") are still allowed, and MPD
will fix the resulting position if it turns out to be negative. But
the "seek" and "seekid" commands use an unsigned time stamp which must
not be negative.
With Grand Central Dispatch used in Main.cxx, debug builds on macOS
crash as the IsInside() assertion gets triggered in the event loop. As
a simple fix, usage of GCD is removed. Plugging and unplugging
headphones or changes of the default output device was tested without
issues. Whatever the original commit tried to fix by GCD probably does
not need fixing anymore.
From: Christian Kröner <ckroener@gmx.net>
This just copies the necessary bits and pieces from the ALSA plugin and applies them to OSXOutput based on dop config setting. It only changes the OSXOutput plugin as needed for DoP (further changes to support additionally e.g. integer mode or setting the physical device mode require rather a complete rewrite of the output plugin).
Fortunately the Core Audio API is by default bit perfect and supports DoP with minimal changes (setting the sampling rate accordingly after ensuring that the physical mode supports at least 24 bits per channel seems to be enough). This was tested on an Amanero Combo384 device hooked up to a ES9018 DAC.
USAGE (try only on DACs that support DoP):
- Add dop "yes" option to mpdconf
- Be sure to set at least 24bits per channel before playing some DSD file (using Audio-MIDI-Setup)
- Based on the dop setting, MPD will change the sample rate as required and output DoP signal to the DAC
- Hog mode is recommended to ensure that no other program will try to mix some output with the DoP stream (resulting in bad noise)
- Alternatively set the default output device to another device (e.g. the built-in output) to avoid having other audio interfere with DSD playback
support for chaining ogg opus streams to enable changing stream' metadata on the fly.
currently support is opt-in (enabled by additional option) because lots of clients can't handle this properly yet.
This addresses two problems:
1. the libFLAC write callback had to send an error status to its
caller when SubmitData() returned a command; this disrupted libFLAC
and the resulting command could not be used for anything;
2. the libFLAC function FLAC__stream_decoder_seek_absolute() also
calls the write callback, but its result cannot be used, because
seeking is still in progress, so we lose all data from one FLAC frame.
By moving the SubmitData() call until after CommandFinished(), we
avoid losing this data. This fixes another part of #113
Instead of passing whole chunks to the MusicPipe and checking the
end_time after each chunk, truncate the last chunk if it would exceed
the end_time. This requires keeping track of the absolute PCM frame
number.
This fixes a problem with gapless CUE song transitions: a small part
of the following song was always played twice.
Closes#113
Due to rounding errors, a slightly negative value can be passed to
set_normalized_volume(), which will make the log10() call fail.
Actually, volume 0 is already failing because log10(0) is illegal. So
let's fix this by implementing two corner cases: <=0 and >=100.
Closes#212
There is a POSIX definition for sched_setscheduler(), but Linux does
not implement that; instead of changing the process's scheduler, it
only affects one thread. This has caused some confusion among
application developers and C library developers.
While glibc implements Linux semantics, Musl has made their
sched_setscheduler() function an always-failing no-op, causing the
error message "sched_setscheduler failed: Function not implemented".
http://git.musl-libc.org/cgit/musl/commit/src/sched/sched_setscheduler.c?id=1e21e78bf7a5c24c217446d8760be7b7188711c2
Instead of relying on the C library which may be unreliable here, we
now roll our own system call wrapper.
Closes#218