Merge tag 'v0.23.17'
release v0.23.17
This commit is contained in:
7
NEWS
7
NEWS
@@ -70,11 +70,16 @@ ver 0.24 (not yet released)
|
||||
* documentation: switch to sphinx-rtd-theme
|
||||
* require Meson 1.0
|
||||
|
||||
ver 0.23.17 (not yet released)
|
||||
ver 0.23.17 (2025/01/29)
|
||||
* protocol
|
||||
- "albumart" tries to send larger chunks if available
|
||||
- explicitly disallow "idle" and "noidle" in command lists
|
||||
* storage
|
||||
- nfs: require libnfs 4.0 or later
|
||||
* database
|
||||
- inotify: trigger update after symlink was created
|
||||
* decoder
|
||||
- ffmpeg: prefer over sndfile and audiofile for its DTS-WAV support
|
||||
* support libfmt 11.1
|
||||
|
||||
ver 0.23.16 (2024/12/03)
|
||||
|
@@ -156,6 +156,9 @@ fails, no more commands are executed and the appropriate
|
||||
``list_OK`` is returned for each
|
||||
successful command executed in the command list.
|
||||
|
||||
Only synchronous commands can be used in command lists. Commands that
|
||||
suspend execution (``idle`` and ``noidle``) are not allowed.
|
||||
|
||||
Ranges
|
||||
======
|
||||
|
||||
|
@@ -36,6 +36,13 @@ Client::ProcessCommandList(bool list_ok,
|
||||
return CommandResult::OK;
|
||||
}
|
||||
|
||||
[[gnu::pure]]
|
||||
static bool
|
||||
IsAsyncCommmand(const char *line) noexcept
|
||||
{
|
||||
return StringIsEqual(line, "idle") || StringIsEqual(line, "noidle");
|
||||
}
|
||||
|
||||
CommandResult
|
||||
Client::ProcessLine(char *line) noexcept
|
||||
{
|
||||
@@ -51,6 +58,13 @@ Client::ProcessLine(char *line) noexcept
|
||||
return CommandResult::CLOSE;
|
||||
}
|
||||
|
||||
if (cmd_list.IsActive() && IsAsyncCommmand(line)) {
|
||||
FmtWarning(client_domain,
|
||||
"[{}] not possible in comand list: \"{}\"",
|
||||
num, line);
|
||||
return CommandResult::CLOSE;
|
||||
}
|
||||
|
||||
if (StringIsEqual(line, "noidle")) {
|
||||
if (idle_waiting) {
|
||||
/* send empty idle response and leave idle mode */
|
||||
|
@@ -197,7 +197,19 @@ read_stream_art(Response &r, const std::string_view art_directory,
|
||||
if (buffer_size > 0) {
|
||||
std::unique_lock lock{is->mutex};
|
||||
is->Seek(lock, offset);
|
||||
|
||||
const bool was_ready = is->IsReady();
|
||||
|
||||
read_size = is->Read(lock, {buffer.get(), buffer_size});
|
||||
|
||||
if (was_ready && read_size < buffer_size / 2)
|
||||
/* the InputStream was ready before, but we
|
||||
got only very little data; probably just
|
||||
some data left in the buffer without doing
|
||||
any I/O; let's wait for the next low-level
|
||||
read to complete to get more data for the
|
||||
client */
|
||||
read_size += is->Read(lock, {buffer.get() + read_size, buffer_size - read_size});
|
||||
}
|
||||
|
||||
r.Fmt("size: {}\n", art_file_size);
|
||||
|
@@ -57,12 +57,6 @@ constinit const struct DecoderPlugin *const decoder_plugins[] = {
|
||||
#ifdef ENABLE_OPUS
|
||||
&opus_decoder_plugin,
|
||||
#endif
|
||||
#ifdef ENABLE_SNDFILE
|
||||
&sndfile_decoder_plugin,
|
||||
#endif
|
||||
#ifdef ENABLE_AUDIOFILE
|
||||
&audiofile_decoder_plugin,
|
||||
#endif
|
||||
#ifdef ENABLE_DSD
|
||||
&dsdiff_decoder_plugin,
|
||||
&dsf_decoder_plugin,
|
||||
@@ -103,6 +97,19 @@ constinit const struct DecoderPlugin *const decoder_plugins[] = {
|
||||
#ifdef ENABLE_FFMPEG
|
||||
&ffmpeg_decoder_plugin,
|
||||
#endif
|
||||
|
||||
/* these WAV-decoding plugins are below ffmpeg_decoder_plugin
|
||||
to give FFmpeg a chance to decode DTS-WAV files which is
|
||||
technically DTS Coherent Acoustics (DCA) stream wrapped in
|
||||
fake 16-bit stereo samples; neither libsndfile nor
|
||||
libaudiofile detect this, but FFmpeg does */
|
||||
#ifdef ENABLE_SNDFILE
|
||||
&sndfile_decoder_plugin,
|
||||
#endif
|
||||
#ifdef ENABLE_AUDIOFILE
|
||||
&audiofile_decoder_plugin,
|
||||
#endif
|
||||
|
||||
&pcm_decoder_plugin,
|
||||
nullptr
|
||||
};
|
||||
|
@@ -171,9 +171,12 @@ AsyncInputStream::Read(std::unique_lock<Mutex> &lock,
|
||||
Check();
|
||||
|
||||
r = buffer.Read();
|
||||
if (!r.empty() || IsEOF())
|
||||
if (!r.empty())
|
||||
break;
|
||||
|
||||
if (IsEOF())
|
||||
return 0;
|
||||
|
||||
caller_cond.wait(lock);
|
||||
}
|
||||
|
||||
@@ -181,6 +184,12 @@ AsyncInputStream::Read(std::unique_lock<Mutex> &lock,
|
||||
memcpy(dest.data(), r.data(), nbytes);
|
||||
buffer.Consume(nbytes);
|
||||
|
||||
if (buffer.empty())
|
||||
/* when the buffer becomes empty, reset its head and
|
||||
tail so the next write can fill the whole buffer
|
||||
and not just the part after the tail */
|
||||
buffer.Clear();
|
||||
|
||||
offset += (offset_type)nbytes;
|
||||
|
||||
if (paused && buffer.GetSize() < resume_at)
|
||||
|
@@ -169,6 +169,14 @@ ThreadInputStream::Read(std::unique_lock<Mutex> &lock,
|
||||
size_t nbytes = std::min(dest.size(), r.size());
|
||||
memcpy(dest.data(), r.data(), nbytes);
|
||||
buffer.Consume(nbytes);
|
||||
|
||||
if (buffer.empty())
|
||||
/* when the buffer becomes empty,
|
||||
reset its head and tail so the next
|
||||
write can fill the whole buffer and
|
||||
not just the part after the tail */
|
||||
buffer.Clear();
|
||||
|
||||
wake_cond.notify_one();
|
||||
offset += nbytes;
|
||||
return nbytes;
|
||||
|
Reference in New Issue
Block a user