diff options
Diffstat (limited to 'app/paclient.cpp')
-rw-r--r-- | app/paclient.cpp | 329 |
1 files changed, 0 insertions, 329 deletions
diff --git a/app/paclient.cpp b/app/paclient.cpp deleted file mode 100644 index bd53cde..0000000 --- a/app/paclient.cpp +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Copyright (C) 2016,2017 Konsulko Group - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "paclient.h" - -#include <QtCore/QDebug> - -PaClient::PaClient() - : m_init(false), m_ml(nullptr), m_mlapi(nullptr), m_ctx(nullptr) -{ -} - -PaClient::~PaClient() -{ - if (m_init) - close(); -} - -void PaClient::close() -{ - if (!m_init) return; - pa_threaded_mainloop_stop(m_ml); - pa_threaded_mainloop_free(m_ml); - m_init = false; -} - -static void set_sink_volume_cb(pa_context *c, int success, void *data) -{ - Q_UNUSED(data); - - if (!success) - qWarning() << "PaClient: set sink volume: " << - pa_strerror(pa_context_errno(c)); -} - -static void set_source_volume_cb(pa_context *c, int success, void *data) -{ - Q_UNUSED(data); - - if (!success) - qWarning() << "PaClient: set source volume: " << - pa_strerror(pa_context_errno(c)); -} - -void PaClient::setVolume(uint32_t type, uint32_t index, uint32_t channel, uint32_t volume) -{ - pa_operation *o; - pa_context *c = context(); - pa_cvolume *cvolume = NULL; - - if (type == C_SINK) { - cvolume = m_sink_states.value(index); - cvolume->values[channel] = volume; - if (!(o = pa_context_set_sink_volume_by_index(c, index, cvolume, set_sink_volume_cb, NULL))) { - qWarning() << "PaClient: set sink #" << index << - " channel #" << channel << - " volume: " << pa_strerror(pa_context_errno(c)); - return; - } - pa_operation_unref(o); - } else if (type == C_SOURCE) { - cvolume = m_source_states.value(index); - cvolume->values[channel] = volume; - if (!(o = pa_context_set_source_volume_by_index(c, index, cvolume, set_source_volume_cb, NULL))) { - qWarning() << "PaClient: set source #" << index << - " channel #" << channel << - " volume: " << pa_strerror(pa_context_errno(c)); - return; - } - pa_operation_unref(o); - } -} - -void get_source_list_cb(pa_context *c, - const pa_source_info *i, - int eol, - void *data) -{ - int chan; - - PaClient *self = reinterpret_cast<PaClient*>(data); - - if (eol < 0) { - qWarning() << "PaClient: get source list: " << - pa_strerror(pa_context_errno(c)); - - self->close(); - return; - } - - if (!eol) { - self->addOneControlState(C_SOURCE, i->index, &i->volume); - for (chan = 0; chan < i->channel_map.channels; chan++) { - // NOTE: hide input control - if (QString(i->name).endsWith("monitor")) - continue; - - emit self->controlAdded(i->index, QString(i->name), QString(i->description), - C_SOURCE, chan, channel_position_string[i->channel_map.map[chan]], - i->volume.values[chan]); - } - } -} - -void get_sink_list_cb(pa_context *c, - const pa_sink_info *i, - int eol, - void *data) -{ - PaClient *self = reinterpret_cast<PaClient*>(data); - int chan; - - if(eol < 0) { - qWarning() << "PaClient: get sink list: " << - pa_strerror(pa_context_errno(c)); - self->close(); - return; - } - - if(!eol) { - self->addOneControlState(C_SINK, i->index, &i->volume); - for (chan = 0; chan < i->channel_map.channels; chan++) { - emit self->controlAdded(i->index, QString(i->name), QString(i->description), - C_SINK, chan, channel_position_string[i->channel_map.map[chan]], - i->volume.values[chan]); - } - } -} - -void get_sink_info_change_cb(pa_context *c, - const pa_sink_info *i, - int eol, - void *data) -{ - Q_UNUSED(c); - Q_ASSERT(i); - Q_ASSERT(data); - - if (eol) return; - - for (int chan = 0; chan < i->channel_map.channels; chan++) { - PaClient *self = reinterpret_cast<PaClient*>(data); - QHash<int, pa_cvolume *> states = self->sink_states(); - pa_cvolume *cvolume = states.value(i->index); - // Check each channel for volume change - if (cvolume->values[chan] != i->volume.values[chan]) { - // On change, update cache and signal - cvolume->values[chan] = i->volume.values[chan]; - emit self->volumeExternallyChanged(C_SINK, i->index, chan, i->volume.values[chan]); - } - } -} - -void get_source_info_change_cb(pa_context *c, - const pa_source_info *i, - int eol, - void *data) -{ - Q_UNUSED(c); - Q_ASSERT(i); - Q_ASSERT(data); - - if (eol) return; - - for (int chan = 0; chan < i->channel_map.channels; chan++) { - PaClient *self = reinterpret_cast<PaClient*>(data); - QHash<int, pa_cvolume *> states = self->source_states(); - pa_cvolume *cvolume = states.value(i->index); - // Check each channel for volume change - if (cvolume->values[chan] != i->volume.values[chan]) { - // On change, update cache and signal - cvolume->values[chan] = i->volume.values[chan]; - emit self->volumeExternallyChanged(C_SOURCE, i->index, chan, i->volume.values[chan]); - } - } -} - - -void subscribe_cb(pa_context *c, - pa_subscription_event_type_t type, - uint32_t index, - void *data) -{ - pa_operation *o; - - if ((type & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_CHANGE) { - qWarning("PaClient: unhandled subscribe event operation"); - return; - } - - switch (type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) { - case PA_SUBSCRIPTION_EVENT_SINK: - if (!(o = pa_context_get_sink_info_by_index(c, index, get_sink_info_change_cb, data))) { - qWarning() << "PaClient: get sink info by index: " << - pa_strerror(pa_context_errno(c)); - return; - } - break; - case PA_SUBSCRIPTION_EVENT_SOURCE: - if (!(o = pa_context_get_source_info_by_index(c, index, get_source_info_change_cb, data))) { - qWarning() << "PaClient: get source info by index: " << - pa_strerror(pa_context_errno(c)); - return; - } - break; - default: - qWarning("PaClient: unhandled subscribe event facility"); - } -} - -void context_state_cb(pa_context *c, void *data) -{ - pa_operation *o; - PaClient *self = reinterpret_cast<PaClient*>(data); - - switch (pa_context_get_state(c)) { - case PA_CONTEXT_CONNECTING: - case PA_CONTEXT_AUTHORIZING: - case PA_CONTEXT_SETTING_NAME: - break; - case PA_CONTEXT_READY: - // Fetch the controls of interest - if (!(o = pa_context_get_source_info_list(c, get_source_list_cb, data))) { - qWarning() << "PaClient: get source info list: " << - pa_strerror(pa_context_errno(c)); - return; - } - pa_operation_unref(o); - if (!(o = pa_context_get_sink_info_list(c, &get_sink_list_cb, data))) { - qWarning() << "PaClient: get sink info list: " << - pa_strerror(pa_context_errno(c)); - return; - } - pa_operation_unref(o); - pa_context_set_subscribe_callback(c, subscribe_cb, data); - if (!(o = pa_context_subscribe(c, (pa_subscription_mask_t)(PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE), NULL, NULL))) { - qWarning() << "PaClient: subscribe: " << - pa_strerror(pa_context_errno(c)); - return; - } - break; - case PA_CONTEXT_TERMINATED: - self->close(); - break; - - case PA_CONTEXT_FAILED: - default: - qCritical() << "PaClient: connection failed: " << - pa_strerror(pa_context_errno(c)); - self->close(); - break; - } -} - -void PaClient::init() -{ - m_ml = pa_threaded_mainloop_new(); - if (!m_ml) { - qCritical("PaClient: failed to create mainloop"); - return; - } - - pa_threaded_mainloop_set_name(m_ml, "PaClient mainloop"); - - m_mlapi = pa_threaded_mainloop_get_api(m_ml); - - lock(); - - m_ctx = pa_context_new(m_mlapi, "Mixer"); - if (!m_ctx) { - qCritical("PaClient: failed to create context"); - pa_threaded_mainloop_free(m_ml); - return; - } - pa_context_set_state_callback(m_ctx, context_state_cb, this); - - if (pa_context_connect(m_ctx, 0, (pa_context_flags_t)0, 0) < 0) { - qCritical("PaClient: failed to connect"); - pa_context_unref(m_ctx); - pa_threaded_mainloop_free(m_ml); - return; - } - - if (pa_threaded_mainloop_start(m_ml) != 0) { - qCritical("PaClient: failed to start mainloop"); - pa_context_unref(m_ctx); - pa_threaded_mainloop_free(m_ml); - return; - } - - unlock(); - - m_init = true; -} - -void PaClient::addOneControlState(int type, int index, const pa_cvolume *cvolume) -{ - pa_cvolume *cvolume_new = new pa_cvolume; - cvolume_new->channels = cvolume->channels; - for (int i = 0; i < cvolume->channels; i++) - cvolume_new->values[i] = cvolume->values[i]; - if (type == C_SINK) - m_sink_states.insert(index, cvolume_new); - else if (type == C_SOURCE) - m_source_states.insert(index, cvolume_new); -} - -QHash<int, pa_cvolume *> PaClient::sink_states(void) -{ - return m_sink_states; -} - -QHash<int, pa_cvolume *> PaClient::source_states(void) -{ - return m_source_states; -} |