Reformat code

This commit is contained in:
badaix 2025-01-09 15:06:35 +01:00
parent 58e82ef9e8
commit d5677b6f78
31 changed files with 236 additions and 330 deletions

View file

@ -198,17 +198,16 @@ bool BrowseBonjour::browse(const string& serviceName, mDNSResult& result, int /*
deque<mDNSReply> replyCollection;
{
DNSServiceHandle service(new DNSServiceRef(NULL));
CHECKED(DNSServiceBrowse(
service.get(), 0, 0, serviceName.c_str(), "local.",
[](DNSServiceRef /*service*/, DNSServiceFlags /*flags*/, uint32_t /*interfaceIndex*/, DNSServiceErrorType errorCode, const char* serviceName,
const char* regtype, const char* replyDomain, void* context)
{
CHECKED(DNSServiceBrowse(service.get(), 0, 0, serviceName.c_str(), "local.",
[](DNSServiceRef /*service*/, DNSServiceFlags /*flags*/, uint32_t /*interfaceIndex*/, DNSServiceErrorType errorCode,
const char* serviceName, const char* regtype, const char* replyDomain, void* context)
{
auto replyCollection = static_cast<deque<mDNSReply>*>(context);
CHECKED(errorCode);
replyCollection->push_back(mDNSReply{string(serviceName), string(regtype), string(replyDomain)});
},
&replyCollection));
},
&replyCollection));
runService(service);
}
@ -218,17 +217,17 @@ bool BrowseBonjour::browse(const string& serviceName, mDNSResult& result, int /*
{
DNSServiceHandle service(new DNSServiceRef(NULL));
for (auto& reply : replyCollection)
CHECKED(DNSServiceResolve(
service.get(), 0, 0, reply.name.c_str(), reply.regtype.c_str(), reply.domain.c_str(),
[](DNSServiceRef /*service*/, DNSServiceFlags /*flags*/, uint32_t /*interfaceIndex*/, DNSServiceErrorType errorCode, const char* /*fullName*/,
const char* hosttarget, uint16_t port, uint16_t /*txtLen*/, const unsigned char* /*txtRecord*/, void* context)
{
CHECKED(DNSServiceResolve(service.get(), 0, 0, reply.name.c_str(), reply.regtype.c_str(), reply.domain.c_str(),
[](DNSServiceRef /*service*/, DNSServiceFlags /*flags*/, uint32_t /*interfaceIndex*/, DNSServiceErrorType errorCode,
const char* /*fullName*/, const char* hosttarget, uint16_t port, uint16_t /*txtLen*/,
const unsigned char* /*txtRecord*/, void* context)
{
auto resultCollection = static_cast<deque<mDNSResolve>*>(context);
CHECKED(errorCode);
resultCollection->push_back(mDNSResolve{string(hosttarget), ntohs(port)});
},
&resolveCollection));
},
&resolveCollection));
runService(service);
}
@ -241,11 +240,10 @@ bool BrowseBonjour::browse(const string& serviceName, mDNSResult& result, int /*
for (auto& resolve : resolveCollection)
{
resultCollection[i].port = resolve.port;
CHECKED(DNSServiceGetAddrInfo(
service.get(), kDNSServiceFlagsLongLivedQuery, 0, kDNSServiceProtocol_IPv4, resolve.fullName.c_str(),
[](DNSServiceRef /*service*/, DNSServiceFlags /*flags*/, uint32_t interfaceIndex, DNSServiceErrorType /*errorCode*/, const char* hostname,
const sockaddr* address, uint32_t /*ttl*/, void* context)
{
CHECKED(DNSServiceGetAddrInfo(service.get(), kDNSServiceFlagsLongLivedQuery, 0, kDNSServiceProtocol_IPv4, resolve.fullName.c_str(),
[](DNSServiceRef /*service*/, DNSServiceFlags /*flags*/, uint32_t interfaceIndex, DNSServiceErrorType /*errorCode*/,
const char* hostname, const sockaddr* address, uint32_t /*ttl*/, void* context)
{
auto result = static_cast<mDNSResult*>(context);
result->host = string(hostname);
@ -259,8 +257,8 @@ bool BrowseBonjour::browse(const string& serviceName, mDNSResult& result, int /*
else
return;
result->valid = true;
},
&resultCollection[i++]));
},
&resultCollection[i++]));
}
runService(service);
}

View file

@ -49,9 +49,8 @@ PendingRequest::~PendingRequest()
void PendingRequest::setValue(std::unique_ptr<msg::BaseMessage> value)
{
boost::asio::post(strand_,
[this, self = shared_from_this(), val = std::move(value)]() mutable
{
boost::asio::post(strand_, [this, self = shared_from_this(), val = std::move(value)]() mutable
{
timer_.cancel();
if (handler_)
handler_({}, std::move(val));
@ -66,9 +65,8 @@ uint16_t PendingRequest::id() const
void PendingRequest::startTimer(const chronos::usec& timeout)
{
timer_.expires_after(timeout);
timer_.async_wait(
[this, self = shared_from_this()](boost::system::error_code ec)
{
timer_.async_wait([this, self = shared_from_this()](boost::system::error_code ec)
{
if (!handler_)
return;
if (!ec)
@ -212,9 +210,8 @@ void ClientConnection::sendNext()
message.msg->serialize(stream);
auto handler = message.handler;
boost::asio::async_write(socket_, streambuf,
[this, handler](boost::system::error_code ec, std::size_t length)
{
boost::asio::async_write(socket_, streambuf, [this, handler](boost::system::error_code ec, std::size_t length)
{
if (ec)
LOG(ERROR, LOG_TAG) << "Failed to send message, error: " << ec.message() << "\n";
else
@ -232,9 +229,8 @@ void ClientConnection::sendNext()
void ClientConnection::send(const msg::message_ptr& message, const ResultHandler& handler)
{
boost::asio::post(strand_,
[this, message, handler]()
{
boost::asio::post(strand_, [this, message, handler]()
{
messages_.emplace_back(message, handler);
if (messages_.size() > 1)
{
@ -248,9 +244,8 @@ void ClientConnection::send(const msg::message_ptr& message, const ResultHandler
void ClientConnection::sendRequest(const msg::message_ptr& message, const chronos::usec& timeout, const MessageHandler<msg::BaseMessage>& handler)
{
boost::asio::post(strand_,
[this, message, timeout, handler]()
{
boost::asio::post(strand_, [this, message, timeout, handler]()
{
pendingRequests_.erase(
std::remove_if(pendingRequests_.begin(), pendingRequests_.end(), [](std::weak_ptr<PendingRequest> request) { return request.expired(); }),
pendingRequests_.end());
@ -261,9 +256,8 @@ void ClientConnection::sendRequest(const msg::message_ptr& message, const chrono
auto request = make_shared<PendingRequest>(strand_, reqId_, handler);
pendingRequests_.push_back(request);
request->startTimer(timeout);
send(message,
[handler](const boost::system::error_code& ec)
{
send(message, [handler](const boost::system::error_code& ec)
{
if (ec)
handler(ec, nullptr);
});
@ -273,9 +267,8 @@ void ClientConnection::sendRequest(const msg::message_ptr& message, const chrono
void ClientConnection::getNextMessage(const MessageHandler<msg::BaseMessage>& handler)
{
boost::asio::async_read(socket_, boost::asio::buffer(buffer_, base_msg_size_),
[this, handler](boost::system::error_code ec, std::size_t length) mutable
{
boost::asio::async_read(socket_, boost::asio::buffer(buffer_, base_msg_size_), [this, handler](boost::system::error_code ec, std::size_t length) mutable
{
if (ec)
{
LOG(ERROR, LOG_TAG) << "Error reading message header of length " << length << ": " << ec.message() << "\n";
@ -309,7 +302,7 @@ void ClientConnection::getNextMessage(const MessageHandler<msg::BaseMessage>& ha
boost::asio::async_read(socket_, boost::asio::buffer(buffer_, base_message_.size),
[this, handler](boost::system::error_code ec, std::size_t length) mutable
{
{
if (ec)
{
LOG(ERROR, LOG_TAG) << "Error reading message body of length " << length << ": " << ec.message() << "\n";

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2024 Johannes Pohl
Copyright (C) 2014-2025 Johannes Pohl
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -111,9 +111,8 @@ public:
template <typename Message>
void sendRequest(const msg::message_ptr& message, const chronos::usec& timeout, const MessageHandler<Message>& handler)
{
sendRequest(message, timeout,
[handler](const boost::system::error_code& ec, std::unique_ptr<msg::BaseMessage> response)
{
sendRequest(message, timeout, [handler](const boost::system::error_code& ec, std::unique_ptr<msg::BaseMessage> response)
{
if (ec)
handler(ec, nullptr);
else if (auto casted_response = msg::message_cast<Message>(std::move(response)))

View file

@ -122,9 +122,8 @@ std::vector<std::string> Controller::getSupportedPlayerNames()
void Controller::getNextMessage()
{
clientConnection_->getNextMessage(
[this](const boost::system::error_code& ec, std::unique_ptr<msg::BaseMessage> response)
{
clientConnection_->getNextMessage([this](const boost::system::error_code& ec, std::unique_ptr<msg::BaseMessage> response)
{
if (ec)
{
reconnect();
@ -227,9 +226,8 @@ void Controller::getNextMessage()
if (!player_)
throw SnapException("No audio player support" + (settings_.player.player_name.empty() ? "" : " for: " + settings_.player.player_name));
player_->setVolumeCallback(
[this](const Player::Volume& volume)
{
player_->setVolumeCallback([this](const Player::Volume& volume)
{
// Cache the last volume and check if it really changed in the player's volume callback
static Player::Volume last_volume{-1, true};
if (volume != last_volume)
@ -238,9 +236,8 @@ void Controller::getNextMessage()
auto info = std::make_shared<msg::ClientInfo>();
info->setVolume(static_cast<uint16_t>(volume.volume * 100.));
info->setMuted(volume.mute);
clientConnection_->send(info,
[this](const boost::system::error_code& ec)
{
clientConnection_->send(info, [this](const boost::system::error_code& ec)
{
if (ec)
{
LOG(ERROR, LOG_TAG) << "Failed to send client info, error: " << ec.message() << "\n";
@ -272,7 +269,7 @@ void Controller::sendTimeSyncMessage(int quick_syncs)
auto timeReq = std::make_shared<msg::Time>();
clientConnection_->sendRequest<msg::Time>(timeReq, 2s,
[this, quick_syncs](const boost::system::error_code& ec, const std::unique_ptr<msg::Time>& response) mutable
{
{
if (ec)
{
LOG(ERROR, LOG_TAG) << "Time sync request failed: " << ec.message() << "\n";
@ -293,9 +290,8 @@ void Controller::sendTimeSyncMessage(int quick_syncs)
next = 100us;
}
timer_.expires_after(next);
timer_.async_wait(
[this, quick_syncs](const boost::system::error_code& ec)
{
timer_.async_wait([this, quick_syncs](const boost::system::error_code& ec)
{
if (!ec)
{
sendTimeSyncMessage(quick_syncs);
@ -327,9 +323,8 @@ void Controller::browseMdns(const MdnsHandler& handler)
}
timer_.expires_after(500ms);
timer_.async_wait(
[this, handler](const boost::system::error_code& ec)
{
timer_.async_wait([this, handler](const boost::system::error_code& ec)
{
if (!ec)
{
browseMdns(handler);
@ -348,9 +343,8 @@ void Controller::start()
{
if (settings_.server.host.empty())
{
browseMdns(
[this](const boost::system::error_code& ec, const std::string& host, uint16_t port)
{
browseMdns([this](const boost::system::error_code& ec, const std::string& host, uint16_t port)
{
if (ec)
{
LOG(ERROR, LOG_TAG) << "Failed to browse MDNS, error: " << ec.message() << "\n";
@ -387,9 +381,8 @@ void Controller::reconnect()
stream_.reset();
decoder_.reset();
timer_.expires_after(1s);
timer_.async_wait(
[this](const boost::system::error_code& ec)
{
timer_.async_wait([this](const boost::system::error_code& ec)
{
if (!ec)
{
worker();
@ -399,9 +392,8 @@ void Controller::reconnect()
void Controller::worker()
{
clientConnection_->connect(
[this](const boost::system::error_code& ec)
{
clientConnection_->connect([this](const boost::system::error_code& ec)
{
if (!ec)
{
// LOG(INFO, LOG_TAG) << "Connected!\n";
@ -412,9 +404,8 @@ void Controller::worker()
// Say hello to the server
auto hello = std::make_shared<msg::Hello>(macAddress, settings_.host_id, settings_.instance);
clientConnection_->sendRequest<msg::ServerSettings>(
hello, 2s,
[this](const boost::system::error_code& ec, std::unique_ptr<msg::ServerSettings> response) mutable
{
hello, 2s, [this](const boost::system::error_code& ec, std::unique_ptr<msg::ServerSettings> response) mutable
{
if (ec)
{
LOG(ERROR, LOG_TAG) << "Failed to send hello request, error: " << ec.message() << "\n";
@ -427,7 +418,7 @@ void Controller::worker()
LOG(INFO, LOG_TAG) << "ServerSettings - buffer: " << serverSettings_->getBufferMs() << ", latency: " << serverSettings_->getLatency()
<< ", volume: " << serverSettings_->getVolume() << ", muted: " << serverSettings_->isMuted() << "\n";
}
});
});
// Do initial time sync with the server
sendTimeSyncMessage(50);

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2024 Johannes Pohl
Copyright (C) 2014-2025 Johannes Pohl
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -42,7 +42,7 @@ static constexpr std::chrono::milliseconds BUFFER_TIME = 80ms;
static constexpr int PERIODS = 4;
static constexpr int MIN_PERIODS = 3;
#define exp10(x) (exp((x)*log(10)))
#define exp10(x) (exp((x) * log(10)))
static constexpr auto LOG_TAG = "Alsa";
@ -191,9 +191,8 @@ bool AlsaPlayer::getHardwareVolume(Volume& volume)
void AlsaPlayer::waitForEvent()
{
sd_.async_wait(boost::asio::posix::stream_descriptor::wait_read,
[this](const boost::system::error_code& ec)
{
sd_.async_wait(boost::asio::posix::stream_descriptor::wait_read, [this](const boost::system::error_code& ec)
{
if (ec)
{
// TODO: fd is "Bad" after unplugging/plugging USB DAC, i.e. after init/uninit/init cycle
@ -226,9 +225,8 @@ void AlsaPlayer::waitForEvent()
// As workaround we defer getting the volume by 20ms.
timer_.cancel();
timer_.expires_after(20ms);
timer_.async_wait(
[this](const boost::system::error_code& ec)
{
timer_.async_wait([this](const boost::system::error_code& ec)
{
if (!ec)
{
if (getHardwareVolume(volume_))
@ -256,9 +254,8 @@ void AlsaPlayer::initMixer()
throw SnapException("Can't open control for " + mixer_device_ + ", error: " + snd_strerror(err));
if ((err = snd_ctl_subscribe_events(ctl_, 1)) < 0)
throw SnapException("Can't subscribe for events for " + mixer_device_ + ", error: " + snd_strerror(err));
fd_ = std::unique_ptr<pollfd, std::function<void(pollfd*)>>(new pollfd(),
[](pollfd* p)
{
fd_ = std::unique_ptr<pollfd, std::function<void(pollfd*)>>(new pollfd(), [](pollfd* p)
{
close(p->fd);
delete p;
});

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2024 Johannes Pohl
Copyright (C) 2014-2025 Johannes Pohl
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -53,7 +53,7 @@ std::vector<PcmDevice> FilePlayer::pcm_list(const std::string& parameter)
FilePlayer::FilePlayer(boost::asio::io_context& io_context, const ClientSettings::Player& settings, std::shared_ptr<Stream> stream)
: Player(io_context, settings, stream), timer_(io_context), file_(nullptr)
: Player(io_context, settings, std::move(stream)), timer_(io_context), file_(nullptr)
{
auto params = utils::string::split_pairs(settings.parameter, ',', '=');
string filename;
@ -130,9 +130,8 @@ void FilePlayer::loop()
next_request_ = now + 1ms;
timer_.expires_at(next_request_);
timer_.async_wait(
[this](boost::system::error_code ec)
{
timer_.async_wait([this](boost::system::error_code ec)
{
if (ec)
return;
requestAudio();

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2024 Johannes Pohl
Copyright (C) 2014-2025 Johannes Pohl
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -245,7 +245,7 @@ void Player::setVolume(const Volume& volume)
bp::args = {"--volume", cpt::to_string(volume.volume), "--mute", volume.mute ? "true" : "false"},
bp::on_exit(
[&](int ret_val, std::error_code ec)
{
{
std::unique_lock<std::mutex> lock(mutex_);
LOG(DEBUG, LOG_TAG) << "Error code: " << ec.message() << ", i: " << ret_val << "\n";
if (pending_volume_change.has_value())
@ -255,7 +255,7 @@ void Player::setVolume(const Volume& volume)
lock.unlock();
setVolume(v);
}
}),
}),
io_context_);
}
catch (const std::exception& e)

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2024 Johannes Pohl
Copyright (C) 2014-2025 Johannes Pohl
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -53,9 +53,8 @@ vector<PcmDevice> PulsePlayer::pcm_list(const std::string& parameter)
{
auto pa_ml = std::shared_ptr<pa_mainloop>(pa_mainloop_new(), [](pa_mainloop* pa_ml) { pa_mainloop_free(pa_ml); });
pa_mainloop_api* pa_mlapi = pa_mainloop_get_api(pa_ml.get());
auto pa_ctx = std::shared_ptr<pa_context>(pa_context_new(pa_mlapi, "Snapcast"),
[](pa_context* pa_ctx)
{
auto pa_ctx = std::shared_ptr<pa_context>(pa_context_new(pa_mlapi, "Snapcast"), [](pa_context* pa_ctx)
{
pa_context_disconnect(pa_ctx);
pa_context_unref(pa_ctx);
});
@ -69,10 +68,8 @@ vector<PcmDevice> PulsePlayer::pcm_list(const std::string& parameter)
throw SnapException("Failed to connect to PulseAudio context, error: " + std::string(pa_strerror(pa_context_errno(pa_ctx.get()))));
static int pa_ready = 0;
pa_context_set_state_callback(
pa_ctx.get(),
[](pa_context* c, void* userdata)
{
pa_context_set_state_callback(pa_ctx.get(), [](pa_context* c, void* userdata)
{
std::ignore = userdata;
pa_context_state_t state = pa_context_get_state(c);
switch (state)
@ -87,8 +84,7 @@ vector<PcmDevice> PulsePlayer::pcm_list(const std::string& parameter)
default:
break;
}
},
nullptr);
}, nullptr);
// We can't do anything until PA is ready, so just iterate the mainloop
// and continue
@ -107,18 +103,15 @@ vector<PcmDevice> PulsePlayer::pcm_list(const std::string& parameter)
throw SnapException("PulseAudio context failed, error: " + std::string(pa_strerror(pa_context_errno(pa_ctx.get()))));
static std::vector<PcmDevice> devices;
auto* op = pa_context_get_sink_info_list(
pa_ctx.get(),
[](pa_context* ctx, const pa_sink_info* i, int eol, void* userdata) mutable
{
auto* op = pa_context_get_sink_info_list(pa_ctx.get(), [](pa_context* ctx, const pa_sink_info* i, int eol, void* userdata) mutable
{
std::ignore = ctx;
std::ignore = userdata;
// auto self = static_cast<PulsePlayer*>(userdata);
// If eol is set to a positive number, you're at the end of the list
if (eol <= 0)
devices.emplace_back(i->index, i->name, i->description);
},
nullptr);
}, nullptr);
if (op == nullptr)
throw SnapException("PulseAudio get sink info list failed, error: " + std::string(pa_strerror(pa_context_errno(pa_ctx.get()))));
@ -246,10 +239,8 @@ bool PulsePlayer::getHardwareVolume(Volume& volume)
void PulsePlayer::triggerVolumeUpdate()
{
pa_context_get_sink_input_info(
pa_ctx_, pa_stream_get_index(playstream_),
[](pa_context* ctx, const pa_sink_input_info* info, int eol, void* userdata)
{
pa_context_get_sink_input_info(pa_ctx_, pa_stream_get_index(playstream_), [](pa_context* ctx, const pa_sink_input_info* info, int eol, void* userdata)
{
std::ignore = ctx;
LOG(DEBUG, LOG_TAG) << "pa_context_get_sink_info_by_index info: " << (info != nullptr) << ", eol: " << eol << "\n";
if (info != nullptr)
@ -269,8 +260,7 @@ void PulsePlayer::triggerVolumeUpdate()
}
self->notifyVolumeChange(self->volume_);
}
},
this);
}, this);
}
@ -433,14 +423,11 @@ void PulsePlayer::connect()
// modify the variable to 1 so we know when we have a connection and it's
// ready.
// If there's an error, the callback will set pa_ready to 2
pa_context_set_state_callback(
pa_ctx_,
[](pa_context* c, void* userdata)
{
pa_context_set_state_callback(pa_ctx_, [](pa_context* c, void* userdata)
{
auto* self = static_cast<PulsePlayer*>(userdata);
self->stateCallback(c);
},
this);
}, this);
// We can't do anything until PA is ready, so just iterate the mainloop
// and continue
@ -464,47 +451,35 @@ void PulsePlayer::connect()
if (settings_.mixer.mode == ClientSettings::Mixer::Mode::hardware)
{
pa_context_set_subscribe_callback(
pa_ctx_,
[](pa_context* ctx, pa_subscription_event_type_t event_type, uint32_t idx, void* userdata)
{
pa_context_set_subscribe_callback(pa_ctx_, [](pa_context* ctx, pa_subscription_event_type_t event_type, uint32_t idx, void* userdata)
{
auto* self = static_cast<PulsePlayer*>(userdata);
self->subscribeCallback(ctx, event_type, idx);
},
this);
}, this);
const auto mask = static_cast<pa_subscription_mask_t>(PA_SUBSCRIPTION_MASK_SINK_INPUT);
pa_context_subscribe(
pa_ctx_, mask,
[](pa_context* ctx, int success, void* userdata)
{
pa_context_subscribe(pa_ctx_, mask, [](pa_context* ctx, int success, void* userdata)
{
std::ignore = ctx;
if (success != 0)
{
auto* self = static_cast<PulsePlayer*>(userdata);
self->triggerVolumeUpdate();
}
},
this);
}, this);
}
pa_stream_set_write_callback(
playstream_,
[](pa_stream* stream, size_t length, void* userdata)
{
pa_stream_set_write_callback(playstream_, [](pa_stream* stream, size_t length, void* userdata)
{
auto* self = static_cast<PulsePlayer*>(userdata);
self->writeCallback(stream, length);
},
this);
}, this);
pa_stream_set_underflow_callback(
playstream_,
[](pa_stream* stream, void* userdata)
{
pa_stream_set_underflow_callback(playstream_, [](pa_stream* stream, void* userdata)
{
auto* self = static_cast<PulsePlayer*>(userdata);
self->underflowCallback(stream);
},
this);
}, this);
bufattr_.fragsize = pa_usec_to_bytes(latency_.count(), &pa_ss_);
bufattr_.maxlength = pa_usec_to_bytes(latency_.count(), &pa_ss_);

View file

@ -62,8 +62,7 @@ static constexpr auto LOG_TAG = "Snapclient";
PcmDevice getPcmDevice(const std::string& player, const std::string& parameter, const std::string& soundcard)
{
LOG(DEBUG, LOG_TAG) << "Trying to get PCM device for player: " << player << ", parameter: "
<< ", card: " << soundcard << "\n";
LOG(DEBUG, LOG_TAG) << "Trying to get PCM device for player: " << player << ", parameter: " << ", card: " << soundcard << "\n";
#if defined(HAS_ALSA) || defined(HAS_PULSE) || defined(HAS_WASAPI)
vector<PcmDevice> pcm_devices;
#if defined(HAS_ALSA)
@ -430,9 +429,8 @@ int main(int argc, char** argv)
boost::asio::io_context io_context;
// Construct a signal set registered for process termination.
boost::asio::signal_set signals(io_context, SIGHUP, SIGINT, SIGTERM);
signals.async_wait(
[&](const boost::system::error_code& ec, int signal)
{
signals.async_wait([&](const boost::system::error_code& ec, int signal)
{
if (!ec)
LOG(INFO, LOG_TAG) << "Received signal " << signal << ": " << strsignal(signal) << "\n";
else

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2024 Johannes Pohl
Copyright (C) 2014-2025 Johannes Pohl
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -66,9 +66,8 @@ namespace strutils = utils::string;
#ifndef WINDOWS
static std::string execGetOutput(const std::string& cmd)
{
std::shared_ptr<::FILE> pipe(popen((cmd + " 2> /dev/null").c_str(), "r"),
[](::FILE* stream)
{
std::shared_ptr<::FILE> pipe(popen((cmd + " 2> /dev/null").c_str(), "r"), [](::FILE* stream)
{
if (stream != nullptr)
pclose(stream);
});
@ -441,15 +440,15 @@ static std::string getHostId(const std::string& defaultId = "")
result = getProp("ro.serialno");
#endif
//#else
// #else
// // on embedded platforms it's
// // - either not there
// // - or not unique, or changes during boot
// // - or changes during boot
// // - either not there
// // - or not unique, or changes during boot
// // - or changes during boot
// std::ifstream infile("/var/lib/dbus/machine-id");
// if (infile.good())
// std::getline(infile, result);
//#endif
// #endif
strutils::trim(result);
if (!result.empty())
return result;

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2024 Johannes Pohl
Copyright (C) 2014-2025 Johannes Pohl
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -48,12 +48,11 @@ ControlServer::ControlServer(boost::asio::io_context& io_context, const ServerSe
boost::asio::ssl::context::single_dh_use);
if (!ssl.key_password.empty())
{
ssl_context_.set_password_callback(
[pw = ssl.key_password](size_t max_length, boost::asio::ssl::context_base::password_purpose purpose) -> string
{
ssl_context_.set_password_callback([pw = ssl.key_password](size_t max_length, boost::asio::ssl::context_base::password_purpose purpose) -> string
{
LOG(DEBUG, LOG_TAG) << "getPassword, purpose: " << purpose << ", max length: " << max_length << "\n";
return pw;
});
});
}
if (!ssl.certificate.empty() && !ssl.certificate_key.empty())
{

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2024 Johannes Pohl
Copyright (C) 2014-2025 Johannes Pohl
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -174,9 +174,8 @@ void ControlSessionHttp::start()
LOG(DEBUG, LOG_TAG) << "start\n";
if (is_ssl_)
{
ssl_socket_->async_handshake(boost::asio::ssl::stream_base::server,
[this, self = shared_from_this()](const boost::system::error_code& error)
{
ssl_socket_->async_handshake(boost::asio::ssl::stream_base::server, [this, self = shared_from_this()](const boost::system::error_code& error)
{
LOG(DEBUG, LOG_TAG) << "async_handshake\n";
if (error)
{
@ -264,9 +263,8 @@ void ControlSessionHttp::handle_request(http::request<Body, http::basic_fields<A
return send(bad_request("Illegal request-target"));
std::string request = req.body();
return message_receiver_->onMessageReceived(shared_from_this(), request,
[req = std::move(req), send = std::move(send)](const std::string& response)
{
return message_receiver_->onMessageReceived(shared_from_this(), request, [req = std::move(req), send = std::move(send)](const std::string& response)
{
http::response<http::string_body> res{http::status::ok, req.version()};
res.set(http::field::server, HTTP_SERVER_NAME);
res.set(http::field::content_type, "application/json");
@ -363,9 +361,8 @@ void ControlSessionHttp::on_read(beast::error_code ec, std::size_t bytes_transfe
if ((ec == http::error::end_of_stream) || (ec == boost::asio::error::connection_reset))
{
if (is_ssl_)
ssl_socket_->async_shutdown(
[](const boost::system::error_code& error)
{
ssl_socket_->async_shutdown([](const boost::system::error_code& error)
{
if (error.failed())
LOG(ERROR, LOG_TAG) << "Failed to shudown ssl socket: " << error << "\n";
});
@ -395,9 +392,8 @@ void ControlSessionHttp::on_read(beast::error_code ec, std::size_t bytes_transfe
// Create a WebSocket session by transferring the socket
auto ws = std::make_shared<websocket::stream<ssl_socket>>(std::move(*ssl_socket_));
// Accept the websocket handshake
ws->async_accept(req_,
[this, ws, self = shared_from_this()](beast::error_code ec) mutable
{
ws->async_accept(req_, [this, ws, self = shared_from_this()](beast::error_code ec) mutable
{
if (ec)
{
LOG(ERROR, LOG_TAG) << "Error during WebSocket accept (control): " << ec.message() << "\n";
@ -422,9 +418,8 @@ void ControlSessionHttp::on_read(beast::error_code ec, std::size_t bytes_transfe
// Create a WebSocket session by transferring the socket
auto ws = std::make_shared<websocket::stream<tcp_socket>>(std::move(*tcp_socket_));
// Accept the websocket handshake
ws->async_accept(req_,
[this, ws, self = shared_from_this()](beast::error_code ec) mutable
{
ws->async_accept(req_, [this, ws, self = shared_from_this()](beast::error_code ec) mutable
{
if (ec)
{
LOG(ERROR, LOG_TAG) << "Error during WebSocket accept (control): " << ec.message() << "\n";
@ -459,9 +454,8 @@ void ControlSessionHttp::on_read(beast::error_code ec, std::size_t bytes_transfe
}
// Send the response
handle_request(std::move(req_),
[this](auto&& response)
{
handle_request(std::move(req_), [this](auto&& response)
{
// The lifetime of the message has to extend
// for the duration of the async operation so
// we use a shared_ptr to manage it.
@ -470,13 +464,11 @@ void ControlSessionHttp::on_read(beast::error_code ec, std::size_t bytes_transfe
// Write the response
if (is_ssl_)
http::async_write(this->ssl_socket_.value(), *sp,
[this, self = this->shared_from_this(), sp](beast::error_code ec, std::size_t bytes)
{ this->on_write(ec, bytes, sp->need_eof()); });
http::async_write(this->ssl_socket_.value(), *sp, [this, self = this->shared_from_this(), sp](beast::error_code ec, std::size_t bytes)
{ this->on_write(ec, bytes, sp->need_eof()); });
else
http::async_write(this->tcp_socket_.value(), *sp,
[this, self = this->shared_from_this(), sp](beast::error_code ec, std::size_t bytes)
{ this->on_write(ec, bytes, sp->need_eof()); });
http::async_write(this->tcp_socket_.value(), *sp, [this, self = this->shared_from_this(), sp](beast::error_code ec, std::size_t bytes)
{ this->on_write(ec, bytes, sp->need_eof()); });
});
}

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2024 Johannes Pohl
Copyright (C) 2014-2025 Johannes Pohl
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -54,7 +54,7 @@ void ControlSessionTcp::do_read()
const std::string delimiter = "\n";
boost::asio::async_read_until(socket_, streambuf_, delimiter,
[this, self = shared_from_this(), delimiter](const std::error_code& ec, std::size_t bytes_transferred)
{
{
if (ec)
{
LOG(ERROR, LOG_TAG) << "Error while reading from control socket: " << ec.message() << "\n";
@ -70,9 +70,8 @@ void ControlSessionTcp::do_read()
// LOG(DEBUG, LOG_TAG) << "received: " << line << "\n";
if ((message_receiver_ != nullptr) && !line.empty())
{
message_receiver_->onMessageReceived(shared_from_this(), line,
[this](const std::string& response)
{
message_receiver_->onMessageReceived(shared_from_this(), line, [this](const std::string& response)
{
if (!response.empty())
sendAsync(response);
});
@ -106,9 +105,8 @@ void ControlSessionTcp::stop()
void ControlSessionTcp::sendAsync(const std::string& message)
{
boost::asio::post(strand_,
[this, self = shared_from_this(), message]()
{
boost::asio::post(strand_, [this, self = shared_from_this(), message]()
{
messages_.emplace_back(message + "\r\n");
if (messages_.size() > 1)
{
@ -121,9 +119,8 @@ void ControlSessionTcp::sendAsync(const std::string& message)
void ControlSessionTcp::send_next()
{
boost::asio::async_write(socket_, boost::asio::buffer(messages_.front()),
[this, self = shared_from_this()](std::error_code ec, std::size_t length)
{
boost::asio::async_write(socket_, boost::asio::buffer(messages_.front()), [this, self = shared_from_this()](std::error_code ec, std::size_t length)
{
messages_.pop_front();
if (ec)
{

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2024 Johannes Pohl
Copyright (C) 2014-2025 Johannes Pohl
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -73,9 +73,8 @@ void ControlSessionWebsocket::stop()
void ControlSessionWebsocket::sendAsync(const std::string& message)
{
boost::asio::post(strand_,
[this, self = shared_from_this(), msg = message]() mutable
{
boost::asio::post(strand_, [this, self = shared_from_this(), msg = message]() mutable
{
messages_.push_back(std::move(msg));
if (messages_.size() > 1)
{
@ -149,9 +148,8 @@ void ControlSessionWebsocket::on_read_ws(beast::error_code ec, std::size_t bytes
// LOG(DEBUG, LOG_TAG) << "received: " << line << "\n";
if (message_receiver_ != nullptr)
{
message_receiver_->onMessageReceived(shared_from_this(), line,
[this](const std::string& response)
{
message_receiver_->onMessageReceived(shared_from_this(), line, [this](const std::string& response)
{
if (!response.empty())
{
sendAsync(response);

View file

@ -1,7 +1,7 @@
/***
This file is part of snapcast
Copyright (C) 2015 Hannes Ellinger
Copyright (C) 2016-2024 Johannes Pohl
Copyright (C) 2016-2025 Johannes Pohl
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -204,8 +204,7 @@ void OpusEncoder::encode(const msg::PcmChunk& chunk)
if (remainder_->payloadSize < remainder_max_size_)
{
LOG(DEBUG, LOG_TAG) << "not enough data to encode (" << remainder_->payloadSize << " of " << remainder_max_size_ << " bytes)"
<< "\n";
LOG(DEBUG, LOG_TAG) << "not enough data to encode (" << remainder_->payloadSize << " of " << remainder_max_size_ << " bytes)" << "\n";
return;
}
encode(out->format, remainder_->payload, remainder_->payloadSize);

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2024 Johannes Pohl
Copyright (C) 2014-2025 Johannes Pohl
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -69,9 +69,8 @@ void PublishAvahi::publish(const std::vector<mDNSService>& services)
void PublishAvahi::poll()
{
timer_.expires_after(std::chrono::milliseconds(50));
timer_.async_wait(
[this](const boost::system::error_code& ec)
{
timer_.async_wait([this](const boost::system::error_code& ec)
{
if (!ec && (avahi_simple_poll_iterate(simple_poll, 0) == 0))
poll();
});

View file

@ -189,7 +189,7 @@ void Server::onMessageReceived(std::shared_ptr<ControlSession> controlSession, c
jsonrpcpp::request_ptr request = dynamic_pointer_cast<jsonrpcpp::Request>(entity);
processRequest(request, controlSession->authinfo,
[this, controlSession, response_handler](jsonrpcpp::entity_ptr response, jsonrpcpp::notification_ptr notification)
{
{
// if (controlSession->authinfo.hasAuthInfo())
// {
// LOG(INFO, LOG_TAG) << "Request auth info - username: " << controlSession->authinfo->username()
@ -227,7 +227,7 @@ void Server::onMessageReceived(std::shared_ptr<ControlSession> controlSession, c
processRequest(request, controlSession->authinfo,
[controlSession, response_handler, &responseBatch, &notificationBatch](jsonrpcpp::entity_ptr response,
jsonrpcpp::notification_ptr notification)
{
{
if (response != nullptr)
responseBatch.add_ptr(response);
if (notification != nullptr)
@ -381,9 +381,8 @@ void Server::saveConfig(const std::chrono::milliseconds& deferred)
std::lock_guard<std::mutex> lock(mutex);
config_timer_.cancel();
config_timer_.expires_after(deferred);
config_timer_.async_wait(
[](const boost::system::error_code& ec)
{
config_timer_.async_wait([](const boost::system::error_code& ec)
{
if (!ec)
{
LOG(DEBUG, LOG_TAG) << "Saving config\n";

View file

@ -83,11 +83,12 @@ int main(int argc, char* argv[])
// SSL settings
conf.add<Value<std::filesystem::path>>("", "ssl.certificate", "certificate file (PEM format)", settings.ssl.certificate, &settings.ssl.certificate);
conf.add<Value<std::filesystem::path>>("", "ssl.certificate_key", "private key file (PEM format)", settings.ssl.certificate_key, &settings.ssl.certificate_key);
conf.add<Value<std::filesystem::path>>("", "ssl.certificate_key", "private key file (PEM format)", settings.ssl.certificate_key,
&settings.ssl.certificate_key);
conf.add<Value<string>>("", "ssl.key_password", "key password (for encrypted private key)", settings.ssl.key_password, &settings.ssl.key_password);
#if 0 // feature: users
// Users setting
// Users setting
auto users_value = conf.add<Value<string>>("", "users.user", "<User nane>:<permissions>:<password>");
#endif
@ -259,7 +260,8 @@ int main(int argc, char* argv[])
if (!settings.ssl.certificate.empty() && !settings.ssl.certificate_key.empty())
{
namespace fs = std::filesystem;
auto make_absolute = [](const fs::path& filename) {
auto make_absolute = [](const fs::path& filename)
{
const fs::path cert_path = "/etc/snapserver/certs/";
if (filename.is_absolute())
return filename;
@ -288,7 +290,8 @@ int main(int argc, char* argv[])
LOG(INFO, LOG_TAG) << "Version " << version::code << (!version::rev().empty() ? (", revision " + version::rev(8)) : ("")) << "\n";
if (settings.ssl.enabled())
LOG(INFO, LOG_TAG) << "SSL enabled - certificate file: '" << settings.ssl.certificate.native() << "', certificate key file: '" << settings.ssl.certificate_key.native() << "'\n";
LOG(INFO, LOG_TAG) << "SSL enabled - certificate file: '" << settings.ssl.certificate.native() << "', certificate key file: '"
<< settings.ssl.certificate_key.native() << "'\n";
if (!streamValue->is_set() && !sourceValue->is_set())
settings.stream.sources.push_back(sourceValue->value());

View file

@ -140,10 +140,10 @@ void StreamServer::onDisconnect(StreamSession* streamSession)
LOG(DEBUG, LOG_TAG) << "sessions: " << sessions_.size() << "\n";
sessions_.erase(std::remove_if(sessions_.begin(), sessions_.end(),
[streamSession](std::weak_ptr<StreamSession> session)
{
{
auto s = session.lock();
return s.get() == streamSession;
}),
}),
sessions_.end());
LOG(DEBUG, LOG_TAG) << "sessions: " << sessions_.size() << "\n";
if (messageReceiver_ != nullptr)

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2024 Johannes Pohl
Copyright (C) 2014-2025 Johannes Pohl
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -45,7 +45,7 @@ StreamSession::StreamSession(const boost::asio::any_io_executor& executor, Strea
void StreamSession::setPcmStream(PcmStreamPtr pcmStream)
{
std::lock_guard<std::mutex> lock(mutex_);
pcmStream_ = pcmStream;
pcmStream_ = std::move(pcmStream);
}
@ -60,12 +60,10 @@ void StreamSession::send_next()
{
auto& buffer = messages_.front();
buffer.on_air = true;
boost::asio::post(strand_,
[this, self = shared_from_this(), buffer]()
{
sendAsync(buffer,
[this](boost::system::error_code ec, std::size_t length)
{
boost::asio::post(strand_, [this, self = shared_from_this(), buffer]()
{
sendAsync(buffer, [this](boost::system::error_code ec, std::size_t length)
{
messages_.pop_front();
if (ec)
{
@ -82,19 +80,18 @@ void StreamSession::send_next()
void StreamSession::send(shared_const_buffer const_buf)
{
boost::asio::post(strand_,
[this, self = shared_from_this(), const_buf]()
{
boost::asio::post(strand_, [this, self = shared_from_this(), const_buf]()
{
// delete PCM chunks that are older than the overall buffer duration
messages_.erase(std::remove_if(messages_.begin(), messages_.end(),
[this](const shared_const_buffer& buffer)
{
{
const auto& msg = buffer.message();
if (!msg.is_pcm_chunk || buffer.on_air)
return false;
auto age = chronos::clk::now() - msg.rec_time;
return (age > std::chrono::milliseconds(bufferMs_) + 100ms);
}),
}),
messages_.end());
messages_.push_back(const_buf);

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2023 Johannes Pohl
Copyright (C) 2014-2025 Johannes Pohl
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -87,7 +87,7 @@ void StreamSessionTcp::read_next()
{
boost::asio::async_read(socket_, boost::asio::buffer(buffer_, base_msg_size_),
[this, self = shared_from_this()](boost::system::error_code ec, std::size_t length) mutable
{
{
if (ec)
{
LOG(ERROR, LOG_TAG) << "Error reading message header of length " << length << ": " << ec.message() << "\n";
@ -114,9 +114,8 @@ void StreamSessionTcp::read_next()
if (baseMessage_.size > buffer_.size())
buffer_.resize(baseMessage_.size);
boost::asio::async_read(socket_, boost::asio::buffer(buffer_, baseMessage_.size),
[this, self](boost::system::error_code ec, std::size_t length) mutable
{
boost::asio::async_read(socket_, boost::asio::buffer(buffer_, baseMessage_.size), [this, self](boost::system::error_code ec, std::size_t length) mutable
{
if (ec)
{
LOG(ERROR, LOG_TAG) << "Error reading message body of length " << length << ": " << ec.message() << "\n";

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2024 Johannes Pohl
Copyright (C) 2014-2025 Johannes Pohl
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -69,8 +69,7 @@ AirplayStream::AirplayStream(PcmStream::Listener* pcmListener, boost::asio::io_c
createParser();
metadata_dirty_ = false;
#else
LOG(INFO, LOG_TAG) << "Metadata support not enabled (HAS_EXPAT not defined)"
<< "\n";
LOG(INFO, LOG_TAG) << "Metadata support not enabled (HAS_EXPAT not defined)" << "\n";
#endif
}
@ -243,9 +242,8 @@ void AirplayStream::pipeReadLine()
}
const std::string delimiter = "\n";
boost::asio::async_read_until(*pipe_fd_, streambuf_pipe_, delimiter,
[this, delimiter](const std::error_code& ec, std::size_t bytes_transferred)
{
boost::asio::async_read_until(*pipe_fd_, streambuf_pipe_, delimiter, [this, delimiter](const std::error_code& ec, std::size_t bytes_transferred)
{
if (ec)
{
if ((ec.value() == boost::asio::error::eof) || (ec.value() == boost::asio::error::bad_descriptor))

View file

@ -54,9 +54,8 @@ template <typename Rep, typename Period>
void wait(boost::asio::steady_timer& timer, const std::chrono::duration<Rep, Period>& duration, std::function<void()> handler)
{
timer.expires_after(duration);
timer.async_wait(
[handler = std::move(handler)](const boost::system::error_code& ec)
{
timer.async_wait([handler = std::move(handler)](const boost::system::error_code& ec)
{
if (ec)
{
LOG(ERROR, LOG_TAG) << "Error during async wait: " << ec.message() << "\n";

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2024 Johannes Pohl
Copyright (C) 2014-2025 Johannes Pohl
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -82,9 +82,8 @@ template <typename Timer, typename Rep, typename Period>
void AsioStream<ReadStream>::wait(Timer& timer, const std::chrono::duration<Rep, Period>& duration, std::function<void()> handler)
{
timer.expires_after(duration);
timer.async_wait(
[handler = std::move(handler)](const boost::system::error_code& ec)
{
timer.async_wait([handler = std::move(handler)](const boost::system::error_code& ec)
{
if (ec)
{
LOG(ERROR, "AsioStream") << "Error during async wait: " << ec.message() << "\n";
@ -122,9 +121,8 @@ template <typename ReadStream>
void AsioStream<ReadStream>::check_state(const std::chrono::steady_clock::duration& duration)
{
state_timer_.expires_after(duration);
state_timer_.async_wait(
[this, duration](const boost::system::error_code& ec)
{
state_timer_.async_wait([this, duration](const boost::system::error_code& ec)
{
if (!ec)
{
LOG(INFO, "AsioStream") << "No data since " << std::chrono::duration_cast<std::chrono::milliseconds>(duration).count()
@ -177,7 +175,7 @@ void AsioStream<ReadStream>::do_read()
check_state(idle_threshold_ + std::chrono::milliseconds(chunk_ms_));
boost::asio::async_read(*stream_, boost::asio::buffer(chunk_->payload, chunk_->payloadSize),
[this](boost::system::error_code ec, std::size_t length) mutable
{
{
state_timer_.cancel();
if (ec)
@ -242,9 +240,8 @@ void AsioStream<ReadStream>::do_read()
if (nextTick_ >= currentTick)
{
read_timer_.expires_after(nextTick_ - currentTick);
read_timer_.async_wait(
[this](const boost::system::error_code& ec)
{
read_timer_.async_wait([this](const boost::system::error_code& ec)
{
if (ec)
{
LOG(ERROR, "AsioStream") << "Error during async wait: " << ec.message() << "\n";

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2024 Johannes Pohl
Copyright (C) 2014-2025 Johannes Pohl
Copyright (C) 2024 Marcus Weseloh <marcus@weseloh.cc>
This program is free software: you can redistribute it and/or modify
@ -111,9 +111,8 @@ template <typename Rep, typename Period>
void wait(boost::asio::steady_timer& timer, const std::chrono::duration<Rep, Period>& duration, std::function<void()> handler)
{
timer.expires_after(duration);
timer.async_wait(
[handler = std::move(handler)](const boost::system::error_code& ec)
{
timer.async_wait([handler = std::move(handler)](const boost::system::error_code& ec)
{
if (ec)
{
LOG(ERROR, LOG_TAG) << "Error during async wait: " << ec.message() << "\n";
@ -239,13 +238,10 @@ bool JackStream::openJackConnection()
cpt::to_string(jack_sample_rate) + ".");
}
jack_set_process_callback(
client_, [](jack_nframes_t nframes, void* arg) { return static_cast<JackStream*>(arg)->readJackBuffers(nframes); }, this);
jack_on_shutdown(
client_, [](void* arg) { static_cast<JackStream*>(arg)->onJackShutdown(); }, this);
jack_set_port_registration_callback(
client_, [](jack_port_id_t port_id, int registered, void* arg) { return static_cast<JackStream*>(arg)->onJackPortRegistration(port_id, registered); },
this);
jack_set_process_callback(client_, [](jack_nframes_t nframes, void* arg) { return static_cast<JackStream*>(arg)->readJackBuffers(nframes); }, this);
jack_on_shutdown(client_, [](void* arg) { static_cast<JackStream*>(arg)->onJackShutdown(); }, this);
jack_set_port_registration_callback(client_, [](jack_port_id_t port_id, int registered, void* arg)
{ return static_cast<JackStream*>(arg)->onJackPortRegistration(port_id, registered); }, this);
int err = jack_activate(client_);
if (err)
@ -260,7 +256,7 @@ bool JackStream::openJackConnection()
bool JackStream::createJackPorts()
{
if (ports_.size() > 0)
if (!ports_.empty())
{
throw SnapException("Jack ports already created!");
}

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2024 Johannes Pohl
Copyright (C) 2014-2025 Johannes Pohl
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -144,14 +144,12 @@ void PcmStream::onControlRequest(const jsonrpcpp::Request& request)
void PcmStream::pollProperties()
{
property_timer_.expires_after(10s);
property_timer_.async_wait(
[this](const boost::system::error_code& ec)
{
property_timer_.async_wait([this](const boost::system::error_code& ec)
{
if (!ec)
{
stream_ctrl_->command({++req_id_, "Plugin.Stream.Player.GetProperties"},
[this](const jsonrpcpp::Response& response)
{
stream_ctrl_->command({++req_id_, "Plugin.Stream.Player.GetProperties"}, [this](const jsonrpcpp::Response& response)
{
LOG(INFO, LOG_TAG) << "Response for Plugin.Stream.Player.GetProperties: " << response.to_json() << "\n";
if (response.error().code() == 0)
setProperties(response.result());
@ -175,9 +173,8 @@ void PcmStream::onControlNotification(const jsonrpcpp::Notification& notificatio
else if (notification.method() == "Plugin.Stream.Ready")
{
LOG(DEBUG, LOG_TAG) << "Plugin is ready\n";
stream_ctrl_->command({++req_id_, "Plugin.Stream.Player.GetProperties"},
[this](const jsonrpcpp::Response& response)
{
stream_ctrl_->command({++req_id_, "Plugin.Stream.Player.GetProperties"}, [this](const jsonrpcpp::Response& response)
{
LOG(INFO, LOG_TAG) << "Response for Plugin.Stream.Player.GetProperties: " << response.to_json() << "\n";
if (response.error().code() == 0)
setProperties(response.result());
@ -231,14 +228,14 @@ void PcmStream::start()
{
LOG(DEBUG, LOG_TAG) << "Start: " << name_ << ", type: " << uri_.scheme << ", sampleformat: " << sampleFormat_.toString() << ", codec: " << getCodec()
<< "\n";
encoder_->init([this](const encoder::Encoder& encoder, std::shared_ptr<msg::PcmChunk> chunk, double duration) { chunkEncoded(encoder, chunk, duration); },
sampleFormat_);
encoder_->init([this](const encoder::Encoder& encoder, std::shared_ptr<msg::PcmChunk> chunk, double duration)
{ chunkEncoded(encoder, std::move(chunk), duration); }, sampleFormat_);
if (stream_ctrl_)
{
stream_ctrl_->start(
getId(), server_settings_, [this](const jsonrpcpp::Notification& notification) { onControlNotification(notification); },
[this](const jsonrpcpp::Request& request) { onControlRequest(request); }, [this](std::string message) { onControlLog(std::move(message)); });
stream_ctrl_->start(getId(), server_settings_, [this](const jsonrpcpp::Notification& notification) {
onControlNotification(notification);
}, [this](const jsonrpcpp::Request& request) { onControlRequest(request); }, [this](std::string message) { onControlLog(std::move(message)); });
}
active_ = true;
@ -514,9 +511,8 @@ void PcmStream::sendRequest(const std::string& method, const jsonrpcpp::Paramete
return handler({ControlErrc::can_not_control});
jsonrpcpp::Request req(++req_id_, method, params);
stream_ctrl_->command(req,
[handler](const jsonrpcpp::Response& response)
{
stream_ctrl_->command(req, [handler](const jsonrpcpp::Response& response)
{
if (response.error().code() != 0)
handler({static_cast<ControlErrc>(response.error().code()), response.error().data()});
else

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2024 Johannes Pohl
Copyright (C) 2014-2025 Johannes Pohl
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -145,9 +145,8 @@ void ProcessStream::onStderrMsg(const std::string& line)
void ProcessStream::stderrReadLine()
{
const std::string delimiter = "\n";
boost::asio::async_read_until(*stream_stderr_, streambuf_stderr_, delimiter,
[this, delimiter](const std::error_code& ec, std::size_t bytes_transferred)
{
boost::asio::async_read_until(*stream_stderr_, streambuf_stderr_, delimiter, [this, delimiter](const std::error_code& ec, std::size_t bytes_transferred)
{
if (ec)
{
LOG(ERROR, LOG_TAG) << "Error while reading from stderr: " << ec.message() << "\n";

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2024 Johannes Pohl
Copyright (C) 2014-2025 Johannes Pohl
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -59,9 +59,8 @@ void StreamControl::start(const std::string& stream_id, const ServerSettings& se
void StreamControl::command(const jsonrpcpp::Request& request, const OnResponse& response_handler)
{
// use strand to serialize commands sent from different threads
boost::asio::post(executor_,
[this, request, response_handler]()
{
boost::asio::post(executor_, [this, request, response_handler]()
{
if (response_handler)
request_callbacks_[request.id()] = response_handler;
@ -161,16 +160,14 @@ void ScriptStreamControl::doStart(const std::string& stream_id, const ServerSett
LOG(DEBUG, LOG_TAG) << "Starting control script: '" << script_ << "', params: '" << params.str() << "'\n";
try
{
process_ = bp::child(
script_ + params.str(), bp::std_out > pipe_stdout_, bp::std_err > pipe_stderr_, bp::std_in < in_,
bp::on_exit =
[](int exit, const std::error_code& ec_in)
{
process_ = bp::child(script_ + params.str(), bp::std_out > pipe_stdout_, bp::std_err > pipe_stderr_, bp::std_in < in_,
bp::on_exit = [](int exit, const std::error_code& ec_in)
{
auto severity = AixLog::Severity::debug;
if (exit != 0)
severity = AixLog::Severity::error;
LOG(severity, LOG_TAG) << "Exit code: " << exit << ", message: " << ec_in.message() << "\n";
});
});
}
catch (const std::exception& e)
{
@ -196,9 +193,8 @@ void ScriptStreamControl::doCommand(const jsonrpcpp::Request& request)
void ScriptStreamControl::stderrReadLine()
{
const std::string delimiter = "\n";
boost::asio::async_read_until(*stream_stderr_, streambuf_stderr_, delimiter,
[this, delimiter](const std::error_code& ec, std::size_t bytes_transferred)
{
boost::asio::async_read_until(*stream_stderr_, streambuf_stderr_, delimiter, [this, delimiter](const std::error_code& ec, std::size_t bytes_transferred)
{
if (ec)
{
LOG(ERROR, LOG_TAG) << "Error while reading from stderr: " << ec.message() << "\n";
@ -218,9 +214,8 @@ void ScriptStreamControl::stderrReadLine()
void ScriptStreamControl::stdoutReadLine()
{
const std::string delimiter = "\n";
boost::asio::async_read_until(*stream_stdout_, streambuf_stdout_, delimiter,
[this, delimiter](const std::error_code& ec, std::size_t bytes_transferred)
{
boost::asio::async_read_until(*stream_stdout_, streambuf_stdout_, delimiter, [this, delimiter](const std::error_code& ec, std::size_t bytes_transferred)
{
if (ec)
{
LOG(ERROR, LOG_TAG) << "Error while reading from stdout: " << ec.message() << "\n";

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2024 Johannes Pohl
Copyright (C) 2014-2025 Johannes Pohl
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -24,8 +24,8 @@
#include "server_settings.hpp"
// 3rd party headers
#include <boost/process.hpp>
#include <boost/asio/any_io_executor.hpp>
#include <boost/process.hpp>
// standard headers
#include <map>

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2024 Johannes Pohl
Copyright (C) 2014-2025 Johannes Pohl
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -24,12 +24,10 @@
#include "common/snap_exception.hpp"
#include "common/str_compat.hpp"
#include "common/utils/string_utils.hpp"
#include "encoder/encoder_factory.hpp"
// 3rd party headers
// standard headers
#include <cerrno>
#include <memory>
@ -75,9 +73,8 @@ void TcpStream::connect()
if (is_server_)
{
acceptor_->async_accept(
[this](boost::system::error_code ec, tcp::socket socket)
{
acceptor_->async_accept([this](boost::system::error_code ec, tcp::socket socket)
{
if (!ec)
{
LOG(DEBUG, LOG_TAG) << "New client connection\n";
@ -94,9 +91,8 @@ void TcpStream::connect()
{
stream_ = make_unique<tcp::socket>(strand_);
boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::make_address(host_), port_);
stream_->async_connect(endpoint,
[this](const boost::system::error_code& ec)
{
stream_->async_connect(endpoint, [this](const boost::system::error_code& ec)
{
if (!ec)
{
LOG(DEBUG, LOG_TAG) << "Connected\n";

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2022 Johannes Pohl
Copyright (C) 2014-2025 Johannes Pohl
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -65,9 +65,8 @@ void Watchdog::trigger()
{
timer_.cancel();
timer_.expires_after(timeout_ms_);
timer_.async_wait(
[this](const boost::system::error_code& ec)
{
timer_.async_wait([this](const boost::system::error_code& ec)
{
if (!ec)
{
LOG(INFO, LOG_TAG) << "Timed out: " << std::chrono::duration_cast<std::chrono::seconds>(timeout_ms_).count() << "s\n";