mirror of
https://github.com/badaix/snapcast.git
synced 2025-04-28 17:57:05 +02:00
Reformat code
This commit is contained in:
parent
58e82ef9e8
commit
d5677b6f78
31 changed files with 236 additions and 330 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
});
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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_);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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())
|
||||
{
|
||||
|
|
|
@ -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()); });
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
|
|
|
@ -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, ¬ificationBatch](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";
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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!");
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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";
|
||||
|
|
Loading…
Add table
Reference in a new issue