Merge pull request #2866 from Jay-716/pa-reconnect
pulseaudio: reconnect context when pulseaudio server restarts
This commit is contained in:
commit
ddad6ce136
|
@ -22,6 +22,7 @@ class AudioBackend {
|
||||||
static void sourceInfoCb(pa_context*, const pa_source_info* i, int, void* data);
|
static void sourceInfoCb(pa_context*, const pa_source_info* i, int, void* data);
|
||||||
static void serverInfoCb(pa_context*, const pa_server_info*, void*);
|
static void serverInfoCb(pa_context*, const pa_server_info*, void*);
|
||||||
static void volumeModifyCb(pa_context*, int, void*);
|
static void volumeModifyCb(pa_context*, int, void*);
|
||||||
|
void connectContext();
|
||||||
|
|
||||||
pa_threaded_mainloop* mainloop_;
|
pa_threaded_mainloop* mainloop_;
|
||||||
pa_mainloop_api* mainloop_api_;
|
pa_mainloop_api* mainloop_api_;
|
||||||
|
|
|
@ -28,16 +28,7 @@ AudioBackend::AudioBackend(std::function<void()> on_updated_cb, private_construc
|
||||||
}
|
}
|
||||||
pa_threaded_mainloop_lock(mainloop_);
|
pa_threaded_mainloop_lock(mainloop_);
|
||||||
mainloop_api_ = pa_threaded_mainloop_get_api(mainloop_);
|
mainloop_api_ = pa_threaded_mainloop_get_api(mainloop_);
|
||||||
context_ = pa_context_new(mainloop_api_, "waybar");
|
connectContext();
|
||||||
if (context_ == nullptr) {
|
|
||||||
throw std::runtime_error("pa_context_new() failed.");
|
|
||||||
}
|
|
||||||
if (pa_context_connect(context_, nullptr, PA_CONTEXT_NOFAIL, nullptr) < 0) {
|
|
||||||
auto err =
|
|
||||||
fmt::format("pa_context_connect() failed: {}", pa_strerror(pa_context_errno(context_)));
|
|
||||||
throw std::runtime_error(err);
|
|
||||||
}
|
|
||||||
pa_context_set_state_callback(context_, contextStateCb, this);
|
|
||||||
if (pa_threaded_mainloop_start(mainloop_) < 0) {
|
if (pa_threaded_mainloop_start(mainloop_) < 0) {
|
||||||
throw std::runtime_error("pa_mainloop_run() failed.");
|
throw std::runtime_error("pa_mainloop_run() failed.");
|
||||||
}
|
}
|
||||||
|
@ -61,6 +52,19 @@ std::shared_ptr<AudioBackend> AudioBackend::getInstance(std::function<void()> on
|
||||||
return std::make_shared<AudioBackend>(on_updated_cb, tag);
|
return std::make_shared<AudioBackend>(on_updated_cb, tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AudioBackend::connectContext() {
|
||||||
|
context_ = pa_context_new(mainloop_api_, "waybar");
|
||||||
|
if (context_ == nullptr) {
|
||||||
|
throw std::runtime_error("pa_context_new() failed.");
|
||||||
|
}
|
||||||
|
pa_context_set_state_callback(context_, contextStateCb, this);
|
||||||
|
if (pa_context_connect(context_, nullptr, PA_CONTEXT_NOFAIL, nullptr) < 0) {
|
||||||
|
auto err =
|
||||||
|
fmt::format("pa_context_connect() failed: {}", pa_strerror(pa_context_errno(context_)));
|
||||||
|
throw std::runtime_error(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AudioBackend::contextStateCb(pa_context *c, void *data) {
|
void AudioBackend::contextStateCb(pa_context *c, void *data) {
|
||||||
auto backend = static_cast<AudioBackend *>(data);
|
auto backend = static_cast<AudioBackend *>(data);
|
||||||
switch (pa_context_get_state(c)) {
|
switch (pa_context_get_state(c)) {
|
||||||
|
@ -80,7 +84,13 @@ void AudioBackend::contextStateCb(pa_context *c, void *data) {
|
||||||
nullptr, nullptr);
|
nullptr, nullptr);
|
||||||
break;
|
break;
|
||||||
case PA_CONTEXT_FAILED:
|
case PA_CONTEXT_FAILED:
|
||||||
backend->mainloop_api_->quit(backend->mainloop_api_, 1);
|
// When pulseaudio server restarts, the connection is "failed". Try to reconnect.
|
||||||
|
// pa_threaded_mainloop_lock is already acquired in callback threads.
|
||||||
|
// So there is no need to lock it again.
|
||||||
|
if (backend->context_ != nullptr) {
|
||||||
|
pa_context_disconnect(backend->context_);
|
||||||
|
}
|
||||||
|
backend->connectContext();
|
||||||
break;
|
break;
|
||||||
case PA_CONTEXT_CONNECTING:
|
case PA_CONTEXT_CONNECTING:
|
||||||
case PA_CONTEXT_AUTHORIZING:
|
case PA_CONTEXT_AUTHORIZING:
|
||||||
|
|
Loading…
Reference in New Issue