Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ ver 0.24.14 (not yet released)
- curl: bound WebDAV PROPFIND responses
* input
- qobuz: use HTTPS for API requests
* output
- osx: fix format selection bugs
- osx: fix volume truncation
* Windows
- enable the "mpg123" decoder plugin
- fix shutdown in console mode
- fix last-modified check during database update

ver 0.24.13 (2026/07/10)
* configuration
Expand Down
2 changes: 1 addition & 1 deletion doc/mpdconf.example
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
# The location of the sticker database. This is a database which
# manages dynamic information attached to songs.
#
#sticker_file "$XDG_CACHE_HOME/sticker.sql"
#sticker_file "$XDG_CACHE_HOME/mpd/sticker.sql"
#sticker_file "~/.mpd/sticker.sql"
#
###############################################################################
Expand Down
11 changes: 11 additions & 0 deletions python/build/libs.py
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,17 @@
],
)

libmpg123 = AutotoolsProject(
'https://mpg123.de/download/mpg123-1.33.6.tar.bz2',
'0b10b3b33547f51e52694d069ca3cfe6',
'lib/libmpg123.a',
[
'--disable-shared', '--enable-static',
'--disable-components', '--enable-libmpg123',
'--disable-modules', '--disable-debug',
],
)

libnfs = AutotoolsProject(
'https://github.com/sahlberg/libnfs/archive/libnfs-6.0.2.tar.gz',
'4e5459cc3e0242447879004e9ad28286d4d27daa42cbdcde423248fad911e747',
Expand Down
35 changes: 7 additions & 28 deletions src/command/OutputCommands.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -14,53 +14,38 @@
#include "util/StringVerify.hxx"

CommandResult
handle_enableoutput(Client &client, Request args, Response &r)
handle_enableoutput(Client &client, Request args, [[maybe_unused]] Response &r)
{
assert(args.size() == 1);
unsigned device = args.ParseUnsigned(0);

auto &partition = client.GetPartition();

if (!audio_output_enable_index(partition,
device)) {
r.Error(ACK_ERROR_NO_EXIST, "No such audio output");
return CommandResult::ERROR;
}

audio_output_enable_index(partition, device);
return CommandResult::OK;
}

CommandResult
handle_disableoutput(Client &client, Request args, Response &r)
handle_disableoutput(Client &client, Request args, [[maybe_unused]] Response &r)
{
assert(args.size() == 1);
unsigned device = args.ParseUnsigned(0);

auto &partition = client.GetPartition();

if (!audio_output_disable_index(partition,
device)) {
r.Error(ACK_ERROR_NO_EXIST, "No such audio output");
return CommandResult::ERROR;
}

audio_output_disable_index(partition, device);
return CommandResult::OK;
}

CommandResult
handle_toggleoutput(Client &client, Request args, Response &r)
handle_toggleoutput(Client &client, Request args, [[maybe_unused]] Response &r)
{
assert(args.size() == 1);
unsigned device = args.ParseUnsigned(0);

auto &partition = client.GetPartition();

if (!audio_output_toggle_index(partition,
device)) {
r.Error(ACK_ERROR_NO_EXIST, "No such audio output");
return CommandResult::ERROR;
}

audio_output_toggle_index(partition, device);
return CommandResult::OK;
}

Expand All @@ -83,13 +68,7 @@ handle_outputset(Client &client, Request request, Response &response)
const unsigned i = request.ParseUnsigned(0);

auto &partition = client.GetPartition();
auto &outputs = partition.outputs;
if (i >= outputs.Size()) {
response.Error(ACK_ERROR_NO_EXIST, "No such audio output");
return CommandResult::ERROR;
}

auto &ao = outputs.Get(i);
auto &ao = CheckPartitionOutput(partition, i);

const char *const name = request[1];
if (!IsValidAttributeName(name)) {
Expand Down
19 changes: 17 additions & 2 deletions src/db/update/UpdateSong.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@

#include <unistd.h>

/**
* Truncate to seconds to match the DB round-trip through time_t.
* This is the precision stored in the database file.
*/
static bool
CompareMtimeCoarse(std::chrono::system_clock::time_point info_mtime,
std::chrono::system_clock::time_point song_mtime) noexcept
{
return std::chrono::system_clock::to_time_t(info_mtime) ==
std::chrono::system_clock::to_time_t(song_mtime);
}

inline void
UpdateWalk::UpdateSongFile2(Directory &directory,
std::string_view name, std::string_view suffix,
Expand All @@ -32,7 +44,9 @@ try {
return;
}

if (!(song != nullptr && info.mtime == song->mtime && !walk_discard) &&
if (!(song != nullptr &&
CompareMtimeCoarse(info.mtime, song->mtime) &&
!walk_discard) &&
UpdateContainerFile(directory, name, suffix, info)) {
return;
}
Expand Down Expand Up @@ -61,7 +75,8 @@ try {
modified = true;
FmtNotice(update_domain, "added {}/{}",
directory.GetPath(), name);
} else if (info.mtime != song->mtime || walk_discard) {
} else if (!CompareMtimeCoarse(info.mtime, song->mtime) ||
walk_discard) {
FmtNotice(update_domain, "updating {}/{}",
directory.GetPath(), name);
if (song->UpdateFile(storage, info))
Expand Down
43 changes: 18 additions & 25 deletions src/output/OutputCommand.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,29 @@
#include "mixer/Mixer.hxx"
#include "mixer/Memento.hxx"
#include "mixer/Listener.hxx"
#include "protocol/Ack.hxx"
#include "protocol/IdleFlags.hxx"
#include "Partition.hxx"

extern unsigned audio_output_state_version;

bool
audio_output_enable_index(Partition &partition,
unsigned idx)
AudioOutputControl &
CheckPartitionOutput(Partition &partition, unsigned idx)
{
auto &outputs = partition.outputs;
if (idx >= outputs.Size())
return false;
throw ProtocolError(ACK_ERROR_NO_EXIST, "No such audio output");

return outputs.Get(idx);
}

auto &ao = outputs.Get(idx);
void
audio_output_enable_index(Partition &partition,
unsigned idx)
{
auto &ao = CheckPartitionOutput(partition, idx);
if (!ao.LockSetEnabled(true))
return true;
return;

partition.EmitIdle(IDLE_OUTPUT);

Expand All @@ -42,21 +49,15 @@ audio_output_enable_index(Partition &partition,
ao.GetClient().ApplyEnabled();

++audio_output_state_version;

return true;
}

bool
void
audio_output_disable_index(Partition &partition,
unsigned idx)
{
auto &outputs = partition.outputs;
if (idx >= outputs.Size())
return false;

auto &ao = outputs.Get(idx);
auto &ao = CheckPartitionOutput(partition, idx);
if (!ao.LockSetEnabled(false))
return true;
return;

partition.EmitIdle(IDLE_OUTPUT);

Expand All @@ -70,19 +71,13 @@ audio_output_disable_index(Partition &partition,
ao.GetClient().ApplyEnabled();

++audio_output_state_version;

return true;
}

bool
void
audio_output_toggle_index(Partition &partition,
unsigned idx)
{
auto &outputs = partition.outputs;
if (idx >= outputs.Size())
return false;

auto &ao = outputs.Get(idx);
auto &ao = CheckPartitionOutput(partition, idx);
const bool enabled = ao.LockToggleEnabled();
partition.EmitIdle(IDLE_OUTPUT);

Expand All @@ -98,6 +93,4 @@ audio_output_toggle_index(Partition &partition,
ao.GetClient().ApplyEnabled();

++audio_output_state_version;

return true;
}
26 changes: 20 additions & 6 deletions src/output/OutputCommand.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,41 @@
*/

struct Partition;
class AudioOutputControl;

/**
* Enables an audio output. Returns false if the specified output
* Look up an output of the specified partition and throw
* #ProtocolError on error.
*/
AudioOutputControl &
CheckPartitionOutput(Partition &partition, unsigned idx);

/**
* Enables an audio output.
*
* Throws #ProtocolError if the specified output
* does not exist.
*/
bool
void
audio_output_enable_index(Partition &partition,
unsigned idx);

/**
* Disables an audio output. Returns false if the specified output
* Disables an audio output.
*
* Throws #ProtocolError if the specified output
* does not exist.
*/
bool
void
audio_output_disable_index(Partition &partition,
unsigned idx);

/**
* Toggles an audio output. Returns false if the specified output
* Toggles an audio output.
*
* Throws #ProtocolError if the specified output
* does not exist.
*/
bool
void
audio_output_toggle_index(Partition &partition,
unsigned idx);
15 changes: 9 additions & 6 deletions src/output/plugins/OSXOutputPlugin.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <AudioToolbox/AudioToolbox.h>
#include <CoreServices/CoreServices.h>

#include <cmath>
#include <memory>
#include <span>

Expand Down Expand Up @@ -196,7 +197,7 @@ OSXOutput::GetVolume()
const auto vol = AudioObjectGetPropertyDataT<Float32>(dev_id,
aopa);

return static_cast<int>(vol * 100.0f);
return std::lround(vol * 100.0f);
}

void
Expand Down Expand Up @@ -387,8 +388,9 @@ osx_output_set_device_format(AudioDeviceID dev_id,
aopa_device_streams);

bool format_found = false;
int output_stream;
AudioStreamBasicDescription output_format;
float output_score = 0;
AudioStreamID output_stream = kAudioObjectUnknown;
AudioStreamBasicDescription output_format{};

for (const auto stream : streams) {
const auto direction =
Expand All @@ -401,8 +403,6 @@ osx_output_set_device_format(AudioDeviceID dev_id,
AudioObjectGetPropertyDataArray<AudioStreamRangedDescription>(stream,
aopa_stream_phys_formats);

float output_score = 0;

for (const auto &format : format_list) {
AudioStreamBasicDescription format_desc = format.mFormat;
std::string format_string;
Expand All @@ -423,7 +423,7 @@ osx_output_set_device_format(AudioDeviceID dev_id,
if (score > output_score) {
output_score = score;
output_format = format_desc;
output_stream = stream; // set the idx of the stream in the device
output_stream = stream;
format_found = true;
}
}
Expand All @@ -441,6 +441,9 @@ osx_output_set_device_format(AudioDeviceID dev_id,
err);
}

/* without a matching format, this returns 0
(kAudioStreamAnyRate), which the caller interprets as "the
requested sample rate is not available" */
return output_format.mSampleRate;
}

Expand Down
2 changes: 1 addition & 1 deletion src/win32/Win32Main.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ console_handler(DWORD event)
// regardless our thread is still active.
// If this did not happen within 3 seconds
// let's shutdown anyway.
global_instance->Break();
global_instance->event_loop.InjectBreak();
// Under debugger it's better to wait indefinitely
// to allow debugging of shutdown code.
Sleep(IsDebuggerPresent() ? INFINITE : 3000);
Expand Down
1 change: 1 addition & 0 deletions win32/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
wildmidi,
gme,
ffmpeg,
libmpg123,
libnfs,
libsamplerate,
]
Expand Down
Loading