diff options
Diffstat (limited to 'src/pavucontrol.cc')
-rw-r--r-- | src/pavucontrol.cc | 869 |
1 files changed, 0 insertions, 869 deletions
diff --git a/src/pavucontrol.cc b/src/pavucontrol.cc deleted file mode 100644 index 92bcc48..0000000 --- a/src/pavucontrol.cc +++ /dev/null @@ -1,869 +0,0 @@ -/*** - This file is part of pavucontrol. - - Copyright 2006-2008 Lennart Poettering - Copyright 2008 Sjoerd Simons <sjoerd@luon.net> - - pavucontrol is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - pavucontrol is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with pavucontrol. If not, see <https://www.gnu.org/licenses/>. -***/ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#define PACKAGE_VERSION "0.1" - -#include <pulse/pulseaudio.h> -#include <pulse/glib-mainloop.h> -#include <pulse/ext-stream-restore.h> -#include <pulse/ext-device-manager.h> - -// #include <canberra-gtk.h> - -#include "helper.h" -#include "pavucontrol.h" -#include "minimalstreamwidget.h" -#include "channel.h" -#include "streamwidget.h" -#include "cardwidget.h" -#include "sinkwidget.h" -#include "sourcewidget.h" -#include "sinkinputwidget.h" -#include "sourceoutputwidget.h" -#include "rolewidget.h" -#include "mainwindow.h" -#include <QMessageBox> -#include <QApplication> -#include <QLocale> -#include <QLibraryInfo> -#include <QTranslator> -#include <QCommandLineParser> -#include <QCommandLineOption> -#include <QString> -#include <QRegularExpression> - -#include <unistd.h> - -static pa_context* context = nullptr; -static pa_mainloop_api* api = nullptr; -static int n_outstanding = 0; -static int default_tab = 0; -static bool retry = false; -static int reconnect_timeout = 1; -static QRegularExpression select_output; -static uint32_t select_output_card = UINT32_MAX; - -void show_error(const char *txt) { - char buf[256]; - - snprintf(buf, sizeof(buf), "%s: %s", txt, pa_strerror(pa_context_errno(context))); - - QMessageBox::critical(nullptr, QObject::tr("Error"), QString::fromUtf8(buf)); - qApp->quit(); -} - -static void dec_outstanding(MainWindow *w) { - if (n_outstanding <= 0) - return; - - if (--n_outstanding <= 0) { - // w->get_window()->set_cursor(); - w->setConnectionState(true); - } -} - -static void card_cb(pa_context *, const pa_card_info *i, int eol, void *userdata) { - MainWindow *w = static_cast<MainWindow*>(userdata); - - if (eol < 0) { - if (pa_context_errno(context) == PA_ERR_NOENTITY) - return; - - show_error(QObject::tr("Card callback failure").toUtf8().constData()); - return; - } - - if (eol > 0) { - dec_outstanding(w); - return; - } - - w->updateCard(*i); -} - -static void sink_cb_setdef(pa_context *ctx, const pa_sink_info *sink_info, int eol, void *) { - if (eol < 0) { - if (pa_context_errno(ctx) == PA_ERR_NOENTITY) - return; - show_error(QObject::tr("Card callback failure").toUtf8().constData()); - return; - } - if (eol > 0) - return; - if (sink_info->card != select_output_card) - return; - - printf("Setting default sink of card %d which is sink '%s' (%s)\n", (int)sink_info->card, sink_info->name, sink_info->description); - pa_operation *o; - if (!(o = pa_context_set_default_sink(ctx, sink_info->name, nullptr, nullptr))) { - printf("pa_context_set_default_sink() failed\n"); - return; - } - pa_operation_unref(o); -} - -static void card_cb_setdef(pa_context * ctx, const pa_card_info *card_info, int eol, void *) { - if (eol < 0) { - if (pa_context_errno(ctx) == PA_ERR_NOENTITY) - return; - - show_error(QObject::tr("Card callback failure").toUtf8().constData()); - return; - } - - if (eol > 0) { - pa_operation *o; - printf("Trying to set default sink to card %d\n", (int)select_output_card); - if (select_output_card != UINT32_MAX) { - if (!(o = pa_context_get_sink_info_list(ctx, sink_cb_setdef, nullptr))) { - show_error(QObject::tr("pa_context_get_sink_info_list() failed").toUtf8().constData()); - return; - } - pa_operation_unref(o); - } - return; - } - - // TODO Check stuff - - std::set<pa_card_profile_info2 *, profile_prio_compare> profile_priorities; - std::map<QByteArray, PortInfo> ports; - QMap<QString, ProfileGroup> profiles; - - profile_priorities.clear(); - for (pa_card_profile_info2 ** p_profile = card_info->profiles2; p_profile && *p_profile != nullptr; ++p_profile) { - profile_priorities.insert(*p_profile); - } - - populatePorts(*card_info, ports); - groupProfiles(profile_priorities, ports, profiles); - - ProfileGroup *best = nullptr; - for (auto &p : profiles) { - if (p.getProfileName().contains(select_output)) { - // Maybe we should track per-profile availability too and scan the list... - if (best == nullptr || p.available) { - best = &p; - if (select_output_card == UINT32_MAX || p.available) - select_output_card = card_info->index; - if (p.available) - break; - } - } - } - - if (best != nullptr) { - // Can we do this inside the callback? - pa_operation* o; - const auto *entry = best->entries.first().id.constData(); - printf("Selecting profile %s of card %s\n", entry, card_info->name); - if (!(o = pa_context_set_card_profile_by_index(ctx, card_info->index, entry, nullptr, nullptr))) { - printf("pa_context_set_card_profile_by_index() failed\n"); - return; - } - pa_operation_unref(o); - } -} - -static void context_state_callback_setdef(pa_context *c, void *) { - if (pa_context_get_state(c) == PA_CONTEXT_READY) { - pa_operation *o; - if (!(o = pa_context_get_card_info_list(c, card_cb_setdef, nullptr))) { - show_error(QObject::tr("pa_context_get_card_info_list() failed").toUtf8().constData()); - return; - } - pa_operation_unref(o); - } -} - -#if HAVE_EXT_DEVICE_RESTORE_API -static void ext_device_restore_subscribe_cb(pa_context *c, pa_device_type_t type, uint32_t idx, void *userdata); -#endif - -void sink_cb(pa_context *c, const pa_sink_info *i, int eol, void *userdata) { - MainWindow *w = static_cast<MainWindow*>(userdata); - - if (eol < 0) { - if (pa_context_errno(context) == PA_ERR_NOENTITY) - return; - - show_error(QObject::tr("Sink callback failure").toUtf8().constData()); - return; - } - - if (eol > 0) { - dec_outstanding(w); - return; - } -#if HAVE_EXT_DEVICE_RESTORE_API - if (w->updateSink(*i)) - ext_device_restore_subscribe_cb(c, PA_DEVICE_TYPE_SINK, i->index, w); -#else - w->updateSink(*i); -#endif -} - -void source_cb(pa_context *, const pa_source_info *i, int eol, void *userdata) { - MainWindow *w = static_cast<MainWindow*>(userdata); - - if (eol < 0) { - if (pa_context_errno(context) == PA_ERR_NOENTITY) - return; - - show_error(QObject::tr("Source callback failure").toUtf8().constData()); - return; - } - - if (eol > 0) { - dec_outstanding(w); - return; - } - - w->updateSource(*i); -} - -void sink_input_cb(pa_context *, const pa_sink_input_info *i, int eol, void *userdata) { - MainWindow *w = static_cast<MainWindow*>(userdata); - - if (eol < 0) { - if (pa_context_errno(context) == PA_ERR_NOENTITY) - return; - - show_error(QObject::tr("Sink input callback failure").toUtf8().constData()); - return; - } - - if (eol > 0) { - dec_outstanding(w); - return; - } - - w->updateSinkInput(*i); -} - -void source_output_cb(pa_context *, const pa_source_output_info *i, int eol, void *userdata) { - MainWindow *w = static_cast<MainWindow*>(userdata); - - if (eol < 0) { - if (pa_context_errno(context) == PA_ERR_NOENTITY) - return; - - show_error(QObject::tr("Source output callback failure").toUtf8().constData()); - return; - } - - if (eol > 0) { - - if (n_outstanding > 0) { - /* At this point all notebook pages have been populated, so - * let's open one that isn't empty */ - if (default_tab != -1) { - if (default_tab < 1 || default_tab > w->notebook->count()) { - if (!w->sinkInputWidgets.empty()) - w->notebook->setCurrentIndex(0); - else if (!w->sourceOutputWidgets.empty()) - w->notebook->setCurrentIndex(1); - else if (!w->sourceWidgets.empty() && w->sinkWidgets.empty()) - w->notebook->setCurrentIndex(3); - else - w->notebook->setCurrentIndex(2); - } else { - w->notebook->setCurrentIndex(default_tab - 1); - } - default_tab = -1; - } - } - - dec_outstanding(w); - return; - } - - w->updateSourceOutput(*i); -} - -void client_cb(pa_context *, const pa_client_info *i, int eol, void *userdata) { - MainWindow *w = static_cast<MainWindow*>(userdata); - - if (eol < 0) { - if (pa_context_errno(context) == PA_ERR_NOENTITY) - return; - - show_error(QObject::tr("Client callback failure").toUtf8().constData()); - return; - } - - if (eol > 0) { - dec_outstanding(w); - return; - } - - w->updateClient(*i); -} - -void server_info_cb(pa_context *, const pa_server_info *i, void *userdata) { - MainWindow *w = static_cast<MainWindow*>(userdata); - - if (!i) { - show_error(QObject::tr("Server info callback failure").toUtf8().constData()); - return; - } - - w->updateServer(*i); - dec_outstanding(w); -} - -void ext_stream_restore_read_cb( - pa_context *, - const pa_ext_stream_restore_info *i, - int eol, - void *userdata) { - - MainWindow *w = static_cast<MainWindow*>(userdata); - - if (eol < 0) { - dec_outstanding(w); - g_debug(QObject::tr("Failed to initialize stream_restore extension: %s").toUtf8().constData(), pa_strerror(pa_context_errno(context))); - w->deleteEventRoleWidget(); - return; - } - - if (eol > 0) { - dec_outstanding(w); - return; - } - - w->updateRole(*i); -} - -static void ext_stream_restore_subscribe_cb(pa_context *c, void *userdata) { - MainWindow *w = static_cast<MainWindow*>(userdata); - pa_operation *o; - - if (!(o = pa_ext_stream_restore_read(c, ext_stream_restore_read_cb, w))) { - show_error(QObject::tr("pa_ext_stream_restore_read() failed").toUtf8().constData()); - return; - } - - pa_operation_unref(o); -} - -#if HAVE_EXT_DEVICE_RESTORE_API -void ext_device_restore_read_cb( - pa_context *, - const pa_ext_device_restore_info *i, - int eol, - void *userdata) { - - MainWindow *w = static_cast<MainWindow*>(userdata); - - if (eol < 0) { - dec_outstanding(w); - g_debug(QObject::tr("Failed to initialize device restore extension: %s").toUtf8().constData(), pa_strerror(pa_context_errno(context))); - return; - } - - if (eol > 0) { - dec_outstanding(w); - return; - } - - /* Do something with a widget when this part is written */ - w->updateDeviceInfo(*i); -} - -static void ext_device_restore_subscribe_cb(pa_context *c, pa_device_type_t type, uint32_t idx, void *userdata) { - MainWindow *w = static_cast<MainWindow*>(userdata); - pa_operation *o; - - if (type != PA_DEVICE_TYPE_SINK) - return; - - if (!(o = pa_ext_device_restore_read_formats(c, type, idx, ext_device_restore_read_cb, w))) { - show_error(QObject::tr("pa_ext_device_restore_read_sink_formats() failed").toUtf8().constData()); - return; - } - - pa_operation_unref(o); -} -#endif - -void ext_device_manager_read_cb( - pa_context *, - const pa_ext_device_manager_info *, - int eol, - void *userdata) { - - MainWindow *w = static_cast<MainWindow*>(userdata); - - if (eol < 0) { - dec_outstanding(w); - g_debug(QObject::tr("Failed to initialize device manager extension: %s").toUtf8().constData(), pa_strerror(pa_context_errno(context))); - return; - } - - w->canRenameDevices = true; - - if (eol > 0) { - dec_outstanding(w); - return; - } - - /* Do something with a widget when this part is written */ -} - -static void ext_device_manager_subscribe_cb(pa_context *c, void *userdata) { - MainWindow *w = static_cast<MainWindow*>(userdata); - pa_operation *o; - - if (!(o = pa_ext_device_manager_read(c, ext_device_manager_read_cb, w))) { - show_error(QObject::tr("pa_ext_device_manager_read() failed").toUtf8().constData()); - return; - } - - pa_operation_unref(o); -} - -void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t index, void *userdata) { - MainWindow *w = static_cast<MainWindow*>(userdata); - - switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) { - case PA_SUBSCRIPTION_EVENT_SINK: - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) - w->removeSink(index); - else { - pa_operation *o; - if (!(o = pa_context_get_sink_info_by_index(c, index, sink_cb, w))) { - show_error(QObject::tr("pa_context_get_sink_info_by_index() failed").toUtf8().constData()); - return; - } - pa_operation_unref(o); - } - break; - - case PA_SUBSCRIPTION_EVENT_SOURCE: - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) - w->removeSource(index); - else { - pa_operation *o; - if (!(o = pa_context_get_source_info_by_index(c, index, source_cb, w))) { - show_error(QObject::tr("pa_context_get_source_info_by_index() failed").toUtf8().constData()); - return; - } - pa_operation_unref(o); - } - break; - - case PA_SUBSCRIPTION_EVENT_SINK_INPUT: - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) - w->removeSinkInput(index); - else { - pa_operation *o; - if (!(o = pa_context_get_sink_input_info(c, index, sink_input_cb, w))) { - show_error(QObject::tr("pa_context_get_sink_input_info() failed").toUtf8().constData()); - return; - } - pa_operation_unref(o); - } - break; - - case PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT: - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) - w->removeSourceOutput(index); - else { - pa_operation *o; - if (!(o = pa_context_get_source_output_info(c, index, source_output_cb, w))) { - show_error(QObject::tr("pa_context_get_sink_input_info() failed").toUtf8().constData()); - return; - } - pa_operation_unref(o); - } - break; - - case PA_SUBSCRIPTION_EVENT_CLIENT: - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) - w->removeClient(index); - else { - pa_operation *o; - if (!(o = pa_context_get_client_info(c, index, client_cb, w))) { - show_error(QObject::tr("pa_context_get_client_info() failed").toUtf8().constData()); - return; - } - pa_operation_unref(o); - } - break; - - case PA_SUBSCRIPTION_EVENT_SERVER: { - pa_operation *o; - if (!(o = pa_context_get_server_info(c, server_info_cb, w))) { - show_error(QObject::tr("pa_context_get_server_info() failed").toUtf8().constData()); - return; - } - pa_operation_unref(o); - } - break; - - case PA_SUBSCRIPTION_EVENT_CARD: - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) - w->removeCard(index); - else { - pa_operation *o; - if (!(o = pa_context_get_card_info_by_index(c, index, card_cb, w))) { - show_error(QObject::tr("pa_context_get_card_info_by_index() failed").toUtf8().constData()); - return; - } - pa_operation_unref(o); - } - break; - - } -} - -/* Forward Declaration */ -gboolean connect_to_pulse(gpointer userdata); - -void context_state_callback(pa_context *c, void *userdata) { - MainWindow *w = static_cast<MainWindow*>(userdata); - - g_assert(c); - - switch (pa_context_get_state(c)) { - case PA_CONTEXT_UNCONNECTED: - case PA_CONTEXT_CONNECTING: - case PA_CONTEXT_AUTHORIZING: - case PA_CONTEXT_SETTING_NAME: - break; - - case PA_CONTEXT_READY: { - pa_operation *o; - - reconnect_timeout = 1; - - /* Create event widget immediately so it's first in the list */ - w->createEventRoleWidget(); - - pa_context_set_subscribe_callback(c, subscribe_cb, w); - - if (!(o = pa_context_subscribe(c, (pa_subscription_mask_t) - (PA_SUBSCRIPTION_MASK_SINK| - PA_SUBSCRIPTION_MASK_SOURCE| - PA_SUBSCRIPTION_MASK_SINK_INPUT| - PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT| - PA_SUBSCRIPTION_MASK_CLIENT| - PA_SUBSCRIPTION_MASK_SERVER| - PA_SUBSCRIPTION_MASK_CARD), nullptr, nullptr))) { - show_error(QObject::tr("pa_context_subscribe() failed").toUtf8().constData()); - return; - } - pa_operation_unref(o); - - /* Keep track of the outstanding callbacks for UI tweaks */ - n_outstanding = 0; - - if (!(o = pa_context_get_server_info(c, server_info_cb, w))) { - show_error(QObject::tr("pa_context_get_server_info() failed").toUtf8().constData()); - return; - } - pa_operation_unref(o); - n_outstanding++; - - if (!(o = pa_context_get_client_info_list(c, client_cb, w))) { - show_error(QObject::tr("pa_context_client_info_list() failed").toUtf8().constData()); - return; - } - pa_operation_unref(o); - n_outstanding++; - - if (!(o = pa_context_get_card_info_list(c, card_cb, w))) { - show_error(QObject::tr("pa_context_get_card_info_list() failed").toUtf8().constData()); - return; - } - pa_operation_unref(o); - n_outstanding++; - - if (!(o = pa_context_get_sink_info_list(c, sink_cb, w))) { - show_error(QObject::tr("pa_context_get_sink_info_list() failed").toUtf8().constData()); - return; - } - pa_operation_unref(o); - n_outstanding++; - - if (!(o = pa_context_get_source_info_list(c, source_cb, w))) { - show_error(QObject::tr("pa_context_get_source_info_list() failed").toUtf8().constData()); - return; - } - pa_operation_unref(o); - n_outstanding++; - - if (!(o = pa_context_get_sink_input_info_list(c, sink_input_cb, w))) { - show_error(QObject::tr("pa_context_get_sink_input_info_list() failed").toUtf8().constData()); - return; - } - pa_operation_unref(o); - n_outstanding++; - - if (!(o = pa_context_get_source_output_info_list(c, source_output_cb, w))) { - show_error(QObject::tr("pa_context_get_source_output_info_list() failed").toUtf8().constData()); - return; - } - pa_operation_unref(o); - n_outstanding++; - - /* These calls are not always supported */ - if ((o = pa_ext_stream_restore_read(c, ext_stream_restore_read_cb, w))) { - pa_operation_unref(o); - n_outstanding++; - - pa_ext_stream_restore_set_subscribe_cb(c, ext_stream_restore_subscribe_cb, w); - - if ((o = pa_ext_stream_restore_subscribe(c, 1, nullptr, nullptr))) - pa_operation_unref(o); - - } else - g_debug(QObject::tr("Failed to initialize stream_restore extension: %s").toUtf8().constData(), pa_strerror(pa_context_errno(context))); - -#if HAVE_EXT_DEVICE_RESTORE_API - /* TODO Change this to just the test function */ - if ((o = pa_ext_device_restore_read_formats_all(c, ext_device_restore_read_cb, w))) { - pa_operation_unref(o); - n_outstanding++; - - pa_ext_device_restore_set_subscribe_cb(c, ext_device_restore_subscribe_cb, w); - - if ((o = pa_ext_device_restore_subscribe(c, 1, nullptr, nullptr))) - pa_operation_unref(o); - - } else - g_debug(QObject::tr("Failed to initialize device restore extension: %s").toUtf8().constData(), pa_strerror(pa_context_errno(context))); -#endif - - if ((o = pa_ext_device_manager_read(c, ext_device_manager_read_cb, w))) { - pa_operation_unref(o); - n_outstanding++; - - pa_ext_device_manager_set_subscribe_cb(c, ext_device_manager_subscribe_cb, w); - - if ((o = pa_ext_device_manager_subscribe(c, 1, nullptr, nullptr))) - pa_operation_unref(o); - - } else - g_debug(QObject::tr("Failed to initialize device manager extension: %s").toUtf8().constData(), pa_strerror(pa_context_errno(context))); - - - break; - } - - case PA_CONTEXT_FAILED: - w->setConnectionState(false); - - w->removeAllWidgets(); - w->updateDeviceVisibility(); - pa_context_unref(context); - context = nullptr; - - if (reconnect_timeout > 0) { - g_debug("%s", QObject::tr("Connection failed, attempting reconnect").toUtf8().constData()); - g_timeout_add_seconds(reconnect_timeout, connect_to_pulse, w); - } - return; - - case PA_CONTEXT_TERMINATED: - default: - qApp->quit(); - return; - } -} - -pa_context* get_context(void) { - return context; -} - -void update_default_sinks(MainWindow *w) { - pa_operation *o; - if (!(o = pa_context_get_server_info(context, server_info_cb, w))) { - show_error(QObject::tr("pa_context_get_server_info() failed").toUtf8().constData()); - return; - } - pa_operation_unref(o); - n_outstanding++; -} - -void connectToPulse(void) { - pa_proplist *proplist = pa_proplist_new(); - pa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, QObject::tr("PulseAudio Volume Control").toUtf8().constData()); - pa_proplist_sets(proplist, PA_PROP_APPLICATION_ID, "org.PulseAudio.pavucontrol"); - pa_proplist_sets(proplist, PA_PROP_APPLICATION_ICON_NAME, "audio-card"); - pa_proplist_sets(proplist, PA_PROP_APPLICATION_VERSION, PACKAGE_VERSION); - - context = pa_context_new_with_proplist(api, nullptr, proplist); - g_assert(context); - - pa_proplist_free(proplist); -} - -gboolean connect_to_pulse(gpointer userdata) { - MainWindow *w = static_cast<MainWindow*>(userdata); - - if (context) - return false; - - connectToPulse(); - - pa_context_set_state_callback(context, context_state_callback, w); - - w->setConnectingMessage(); - if (pa_context_connect(context, nullptr, PA_CONTEXT_NOFAIL, nullptr) < 0) { - if (pa_context_errno(context) == PA_ERR_INVALID) { - w->setConnectingMessage(QObject::tr("Connection to PulseAudio failed. Automatic retry in 5s.<br><br>" - "In this case this is likely because PULSE_SERVER in the Environment/X11 Root Window Properties" - "or default-server in client.conf is misconfigured.<br>" - "This situation can also arrise when PulseAudio crashed and left stale details in the X11 Root Window.<br>" - "If this is the case, then PulseAudio should autospawn again, or if this is not configured you should" - "run start-pulseaudio-x11 manually.").toUtf8().constData()); - reconnect_timeout = 5; - } - else { - if(!retry) { - reconnect_timeout = -1; - qApp->quit(); - } else { - g_debug("%s", QObject::tr("Connection failed, attempting reconnect").toUtf8().constData()); - reconnect_timeout = 5; - g_timeout_add_seconds(reconnect_timeout, connect_to_pulse, userdata); - } - } - } - - return false; -} - -int main(int argc, char *argv[]) { - int exit_code = 0, have_regex = 0; - - signal(SIGPIPE, SIG_IGN); - - QApplication app(argc, argv); - - app.setOrganizationName(QStringLiteral("pavucontrol-qt")); - app.setAttribute(Qt::AA_UseHighDpiPixmaps, true); - - QString locale = QLocale::system().name(); - QTranslator qtTranslator; - if(qtTranslator.load(QStringLiteral("qt_") + locale, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) - qApp->installTranslator(&qtTranslator); - - QTranslator appTranslator; - if(appTranslator.load(QStringLiteral("pavucontrol-qt_") + locale, QStringLiteral(PAVUCONTROL_QT_DATA_DIR) + QStringLiteral("/translations"))) - qApp->installTranslator(&appTranslator); - - QCommandLineParser parser; - parser.setApplicationDescription(QObject::tr("PulseAudio Volume Control")); - parser.addHelpOption(); - - const QString VERINFO = QStringLiteral(PAVUCONTROLQT_VERSION - "\nQt " QT_VERSION_STR); - app.setApplicationVersion(VERINFO); - parser.addVersionOption(); - - QCommandLineOption tabOption(QStringList() << QStringLiteral("tab") << QStringLiteral("t"), QObject::tr("Select a specific tab on load."), QStringLiteral("tab")); - parser.addOption(tabOption); - - QCommandLineOption retryOption(QStringList() << QStringLiteral("retry") << QStringLiteral("r"), QObject::tr("Retry forever if pa quits (every 5 seconds).")); - parser.addOption(retryOption); - - QCommandLineOption maximizeOption(QStringList() << QStringLiteral("maximize") << QStringLiteral("m"), QObject::tr("Maximize the window.")); - parser.addOption(maximizeOption); - - QCommandLineOption selectOption(QStringList() << QStringLiteral("output") << QStringLiteral("o"), QObject::tr("Select a specific output configuration and quit."), QStringLiteral("regex")); - parser.addOption(selectOption); - - parser.process(app); - default_tab = parser.value(tabOption).toInt(); - retry = parser.isSet(retryOption); - if (parser.isSet(selectOption)) { - select_output = QRegularExpression(parser.value(selectOption)); - if (!select_output.isValid()) { - select_output = QRegularExpression(QRegularExpression::escape(parser.value(selectOption))); - } - have_regex = select_output.isValid(); - } - - if (have_regex) { - pa_mainloop *m = pa_mainloop_new(); - g_assert(m); - api = pa_mainloop_get_api(m); - g_assert(api); - - connectToPulse(); - pa_context_set_state_callback(context, context_state_callback_setdef, nullptr); - if (pa_context_connect(context, nullptr, PA_CONTEXT_NOFAIL, nullptr) >= 0) { - if (pa_context_errno(context) == PA_ERR_INVALID) { - printf("pa_context_errno = PA_ERR_INVALID\n"); - exit_code = 1; - } else { - int evs; - int tries = 50; - exit_code = 100; - // WTF - while ((evs = pa_mainloop_iterate(m, 0, &exit_code)) >= 0) { - if (evs == 0) { - if (--tries == 0) - break; - usleep(20000); - } - } - printf("Exit: %d\n", exit_code); - } - } - - if (context) - pa_context_unref(context); - pa_mainloop_free(m); - } else { - MainWindow* mainWindow = new MainWindow(); - if(parser.isSet(maximizeOption)) - mainWindow->showMaximized(); - - pa_glib_mainloop *m = pa_glib_mainloop_new(g_main_context_default()); - g_assert(m); - api = pa_glib_mainloop_get_api(m); - g_assert(api); - - connect_to_pulse(mainWindow); - if (reconnect_timeout >= 0) { - mainWindow->show(); - app.exec(); - } - - if (reconnect_timeout < 0) - show_error(QObject::tr("Fatal Error: Unable to connect to PulseAudio").toUtf8().constData()); - - delete mainWindow; - - if (context) - pa_context_unref(context); - pa_glib_mainloop_free(m); - } - - return exit_code; -} |