mirror of
https://github.com/badaix/snapcast.git
synced 2025-08-06 10:09:33 +02:00
Fix crash when unplugging USB DAC
This commit is contained in:
parent
b2bf4f2bfe
commit
535e78ff94
2 changed files with 24 additions and 9 deletions
|
@ -104,18 +104,21 @@ void AlsaPlayer::setHardwareVolume(double volume, bool muted)
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
LOG(ERROR, LOG_TAG) << "Exception: " << e.what() << "\n";
|
LOG(ERROR, LOG_TAG) << "Exception: " << e.what() << "\n";
|
||||||
|
uninitMixer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool AlsaPlayer::getHardwareVolume(double& volume, bool& muted)
|
bool AlsaPlayer::getHardwareVolume(double& volume, bool& muted)
|
||||||
{
|
{
|
||||||
long vol;
|
|
||||||
int err = 0;
|
|
||||||
|
|
||||||
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
||||||
|
if (elem_ == nullptr)
|
||||||
|
throw SnapException("Mixer not initialized");
|
||||||
|
|
||||||
|
long vol;
|
||||||
|
int err = 0;
|
||||||
while (snd_mixer_handle_events(mixer_) > 0)
|
while (snd_mixer_handle_events(mixer_) > 0)
|
||||||
this_thread::sleep_for(1us);
|
this_thread::sleep_for(1us);
|
||||||
long minv, maxv;
|
long minv, maxv;
|
||||||
|
@ -163,11 +166,15 @@ 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)
|
if (ec)
|
||||||
{
|
{
|
||||||
|
// TODO: fd is "Bad" after unplugging/plugging USB DAC, i.e. after init/uninit/init cycle
|
||||||
LOG(DEBUG, LOG_TAG) << "waitForEvent error: " << ec.message() << "\n";
|
LOG(DEBUG, LOG_TAG) << "waitForEvent error: " << ec.message() << "\n";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
||||||
|
if (ctl_ == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
unsigned short revents;
|
unsigned short revents;
|
||||||
snd_ctl_poll_descriptors_revents(ctl_, fd_.get(), 1, &revents);
|
snd_ctl_poll_descriptors_revents(ctl_, fd_.get(), 1, &revents);
|
||||||
if (revents & POLLIN || (revents == 0))
|
if (revents & POLLIN || (revents == 0))
|
||||||
|
@ -212,15 +219,20 @@ void AlsaPlayer::initMixer()
|
||||||
if (settings_.mixer.mode != ClientSettings::Mixer::Mode::hardware)
|
if (settings_.mixer.mode != ClientSettings::Mixer::Mode::hardware)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
LOG(DEBUG, LOG_TAG) << "initMixer\n";
|
||||||
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
||||||
int err;
|
int err;
|
||||||
if ((err = snd_ctl_open(&ctl_, mixer_device_.c_str(), SND_CTL_READONLY)) < 0)
|
if ((err = snd_ctl_open(&ctl_, mixer_device_.c_str(), SND_CTL_READONLY)) < 0)
|
||||||
throw SnapException("Can't open control for " + mixer_device_ + ", error: " + snd_strerror(err));
|
throw SnapException("Can't open control for " + mixer_device_ + ", error: " + snd_strerror(err));
|
||||||
if ((err = snd_ctl_subscribe_events(ctl_, 1)) < 0)
|
if ((err = snd_ctl_subscribe_events(ctl_, 1)) < 0)
|
||||||
throw SnapException("Can't subscribe for events for " + mixer_device_ + ", error: " + snd_strerror(err));
|
throw SnapException("Can't subscribe for events for " + mixer_device_ + ", error: " + snd_strerror(err));
|
||||||
fd_ = std::make_unique<pollfd>();
|
fd_ = std::unique_ptr<pollfd, std::function<void(pollfd*)>>(new pollfd(), [](pollfd* p) {
|
||||||
|
close(p->fd);
|
||||||
|
delete p;
|
||||||
|
});
|
||||||
err = snd_ctl_poll_descriptors(ctl_, fd_.get(), 1);
|
err = snd_ctl_poll_descriptors(ctl_, fd_.get(), 1);
|
||||||
LOG(DEBUG, LOG_TAG) << "Filled " << err << " poll descriptors, poll descriptor count: " << snd_ctl_poll_descriptors_count(ctl_) << "\n";
|
LOG(DEBUG, LOG_TAG) << "Filled " << err << " poll descriptors, poll descriptor count: " << snd_ctl_poll_descriptors_count(ctl_) << ", fd: " << fd_->fd
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
snd_mixer_selem_id_t* sid;
|
snd_mixer_selem_id_t* sid;
|
||||||
snd_mixer_selem_id_alloca(&sid);
|
snd_mixer_selem_id_alloca(&sid);
|
||||||
|
@ -387,14 +399,16 @@ void AlsaPlayer::uninitAlsa(bool uninit_mixer)
|
||||||
|
|
||||||
void AlsaPlayer::uninitMixer()
|
void AlsaPlayer::uninitMixer()
|
||||||
{
|
{
|
||||||
|
if (settings_.mixer.mode != ClientSettings::Mixer::Mode::hardware)
|
||||||
|
return;
|
||||||
|
|
||||||
|
LOG(DEBUG, LOG_TAG) << "uninitMixer\n";
|
||||||
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
||||||
if (sd_.is_open())
|
if (sd_.is_open())
|
||||||
{
|
{
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
sd_.cancel(ec);
|
sd_.cancel(ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
// std::lock_guard<std::mutex> lock(mutex_);
|
|
||||||
if (ctl_ != nullptr)
|
if (ctl_ != nullptr)
|
||||||
{
|
{
|
||||||
snd_ctl_close(ctl_);
|
snd_ctl_close(ctl_);
|
||||||
|
@ -405,6 +419,7 @@ void AlsaPlayer::uninitMixer()
|
||||||
snd_mixer_close(mixer_);
|
snd_mixer_close(mixer_);
|
||||||
mixer_ = nullptr;
|
mixer_ = nullptr;
|
||||||
}
|
}
|
||||||
|
fd_ = nullptr;
|
||||||
elem_ = nullptr;
|
elem_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ private:
|
||||||
std::string mixer_name_;
|
std::string mixer_name_;
|
||||||
std::string mixer_device_;
|
std::string mixer_device_;
|
||||||
|
|
||||||
std::unique_ptr<pollfd> fd_;
|
std::unique_ptr<pollfd, std::function<void(pollfd*)>> fd_;
|
||||||
std::vector<char> buffer_;
|
std::vector<char> buffer_;
|
||||||
snd_pcm_uframes_t frames_;
|
snd_pcm_uframes_t frames_;
|
||||||
boost::asio::posix::stream_descriptor sd_;
|
boost::asio::posix::stream_descriptor sd_;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue