summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIgor V. Kovalenko <igor.v.kovalenko@gmail.com>2020-12-25 17:38:01 +0300
committerIgor V. Kovalenko <igor.v.kovalenko@gmail.com>2021-06-01 02:28:40 +0300
commita1b4622ad5de0513361b8638152d5e5b1ac6980f (patch)
tree3977577e87e31ad1dea1e4bc16ee60ef734f1408 /src
parentb874058ae81e683cf8468c847d1bb1e9686de94a (diff)
cardwidget: add flag to lock profile from switching automatically
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pavucontrol/-/merge_requests/60>
Diffstat (limited to 'src')
-rw-r--r--src/cardwidget.cc37
-rw-r--r--src/cardwidget.h4
-rw-r--r--src/mainwindow.cc22
-rw-r--r--src/mainwindow.h2
-rw-r--r--src/pavucontrol.cc45
-rw-r--r--src/pavucontrol.glade35
-rw-r--r--src/pavucontrol.h1
7 files changed, 146 insertions, 0 deletions
diff --git a/src/cardwidget.cc b/src/cardwidget.cc
index b4fe378..d751fd2 100644
--- a/src/cardwidget.cc
+++ b/src/cardwidget.cc
@@ -35,6 +35,7 @@ CardWidget::CardWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>
x->get_widget("cardIconImage", iconImage);
x->get_widget("codecBox", codecBox);
x->get_widget("codecList", codecList);
+ x->get_widget("profileLockToggleButton", profileLockToggleButton);
profileListStore = Gtk::ListStore::create(profileModel);
profileList->set_model(profileListStore);
@@ -49,6 +50,12 @@ CardWidget::CardWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>
codecList->pack_start(codecModel.desc);
codecList->signal_changed().connect( sigc::mem_fun(*this, &CardWidget::onCodecChange));
+
+ hasProfileLock = false;
+
+ profileLockToggleButton->signal_clicked().connect(sigc::mem_fun(*this, &CardWidget::onProfileLockToggleButton));
+ profileLockToggleButton->set_sensitive(true);
+ profileLockToggleButton->set_visible(hasProfileLock);
}
CardWidget* CardWidget::create() {
@@ -96,6 +103,8 @@ void CardWidget::prepareMenu() {
codecBox->show();
else
codecBox->hide();
+
+ profileLockToggleButton->set_visible(hasProfileLock);
}
void CardWidget::onProfileChange() {
@@ -150,3 +159,31 @@ void CardWidget::onCodecChange() {
}
#endif
}
+
+void CardWidget::onProfileLockToggleButton() {
+ if (updating)
+ return;
+
+#ifdef HAVE_PULSE_MESSAGING_API
+ Gtk::TreeModel::iterator iter = profileList->get_active();
+ if (iter)
+ {
+ Gtk::TreeModel::Row row = *iter;
+ if (row)
+ {
+ pa_operation* o;
+ Glib::ustring profile = row[profileModel.name];
+
+ bool profileIsLocked = profileLockToggleButton->get_active();
+
+ if (!(o = pa_context_send_message_to_object(get_context(), card_message_handler_path(pulse_card_name).c_str(),
+ "set-profile-sticky", profileIsLocked ? "true" : "false", NULL, NULL))) {
+ g_debug(_("pa_context_send_message_to_object() failed: %s"), pa_strerror(pa_context_errno(get_context())));
+ return;
+ }
+
+ pa_operation_unref(o);
+ }
+ }
+#endif
+}
diff --git a/src/cardwidget.h b/src/cardwidget.h
index 98201a4..3c86659 100644
--- a/src/cardwidget.h
+++ b/src/cardwidget.h
@@ -45,6 +45,7 @@ public:
Glib::ustring name;
std::string pulse_card_name;
Gtk::Box *codecBox;
+ Gtk::ToggleButton *profileLockToggleButton;
uint32_t index;
bool updating;
@@ -59,11 +60,14 @@ public:
std::vector<std::pair<Glib::ustring, Glib::ustring>> codecs;
Glib::ustring activeCodec;
+ bool hasProfileLock;
+
void prepareMenu();
protected:
virtual void onProfileChange();
virtual void onCodecChange();
+ virtual void onProfileLockToggleButton();
/* Tree model columns */
class ModelColumns : public Gtk::TreeModel::ColumnRecord
diff --git a/src/mainwindow.cc b/src/mainwindow.cc
index ea290bd..bae4c7a 100644
--- a/src/mainwindow.cc
+++ b/src/mainwindow.cc
@@ -522,6 +522,28 @@ void MainWindow::setActiveCodec(const std::string& card_name, const std::string&
w->updating = false;
}
+void MainWindow::setCardProfileIsSticky(const std::string& card_name, gboolean profile_is_sticky) {
+ CardWidget *w = NULL;
+
+ for (auto c : cardWidgets) {
+ if (card_name.compare(c.second->pulse_card_name) == 0)
+ w = c.second;
+ }
+
+ if (!w)
+ return;
+
+ w->updating = true;
+
+ /* make sure that profile lock toggle button is visible */
+ w->hasProfileLock = true;
+ w->profileLockToggleButton->set_active(profile_is_sticky);
+
+ w->prepareMenu();
+
+ w->updating = false;
+}
+
bool MainWindow::updateSink(const pa_sink_info &info) {
SinkWidget *w;
bool is_new = false;
diff --git a/src/mainwindow.h b/src/mainwindow.h
index 50f3985..5015144 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -59,6 +59,8 @@ public:
void updateCardCodecs(const std::string& card_name, const std::unordered_map<std::string, std::string>& codecs);
void setActiveCodec(const std::string& card_name, const std::string& codec);
+ void setCardProfileIsSticky(const std::string& card_name, gboolean profile_is_sticky);
+
void removeCard(uint32_t index);
void removeSink(uint32_t index);
void removeSource(uint32_t index);
diff --git a/src/pavucontrol.cc b/src/pavucontrol.cc
index 3f5c218..18d5400 100644
--- a/src/pavucontrol.cc
+++ b/src/pavucontrol.cc
@@ -81,6 +81,10 @@ static void dec_outstanding(MainWindow *w) {
#ifdef HAVE_PULSE_MESSAGING_API
+std::string card_message_handler_path(const std::string& name) {
+ return "/card/" + name;
+}
+
std::string card_bluez_message_handler_path(const std::string& name) {
return "/card/" + name + "/bluez";
}
@@ -201,6 +205,39 @@ static void context_bluetooth_card_active_codec_cb(pa_context *c, int success, c
g_object_unref(parser);
}
+static void context_card_profile_is_sticky_cb(pa_context *c, int success, char *response, void *userdata) {
+ auto u = std::unique_ptr<WindowAndCardName>(reinterpret_cast<WindowAndCardName*>(userdata));
+
+ if (!success)
+ return;
+
+ gboolean profile_is_sticky;
+ GError *gerror = NULL;
+
+ JsonParser *parser = json_parser_new();
+
+ if (!json_parser_load_from_data(parser, response, strlen(response), &gerror)) {
+ g_debug(_("could not read JSON from get-profile-sticky message response: %s"), gerror->message);
+ g_error_free(gerror);
+ g_object_unref(parser);
+ return;
+ }
+
+ JsonNode *root = json_parser_get_root(parser);
+
+ if (!root || JSON_NODE_TYPE(root) != JSON_NODE_VALUE) {
+ g_debug(_("get-profile-sticky message response is not a JSON value"));
+ g_object_unref(parser);
+ return;
+ }
+
+ profile_is_sticky = json_node_get_boolean(root);
+
+ u->first->setCardProfileIsSticky(u->second, profile_is_sticky);
+
+ g_object_unref(parser);
+}
+
template<typename U> void send_message(pa_context *c, const char *target, const char *request, pa_context_string_cb_t cb, const U& u)
{
auto send_message_userdata = new U(u);
@@ -300,6 +337,14 @@ static void context_message_handlers_cb(pa_context *c, int success, char *respon
/* list-codecs: retrieve list of codecs */
send_message(c, e->first.c_str(), "list-codecs", context_bluetooth_card_codec_list_cb, *u);
}
+
+ /* send requests to card if card message handler is registered */
+ e = message_handler_map.find(card_message_handler_path(u->second));
+
+ if (e != message_handler_map.end()) {
+ /* get-profile-sticky: retrieve active codec name */
+ send_message(c, e->first.c_str(), "get-profile-sticky", context_card_profile_is_sticky_cb, *u);
+ }
}
#endif
diff --git a/src/pavucontrol.glade b/src/pavucontrol.glade
index e5cf31a..253534e 100644
--- a/src/pavucontrol.glade
+++ b/src/pavucontrol.glade
@@ -134,6 +134,41 @@
<property name="position">1</property>
</packing>
</child>
+ <child>
+ <object class="GtkHBox" id="hbox14">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">3</property>
+ <child>
+ <object class="GtkToggleButton" id="profileLockToggleButton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Lock card to this profile</property>
+ <property name="relief">none</property>
+ <property name="active">True</property>
+ <child>
+ <object class="GtkImage" id="image4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">changes-prevent</property>
+ <property name="icon_size">1</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
</object>
<packing>
<property name="expand">False</property>
diff --git a/src/pavucontrol.h b/src/pavucontrol.h
index 7bf7f49..c8696e6 100644
--- a/src/pavucontrol.h
+++ b/src/pavucontrol.h
@@ -79,6 +79,7 @@ void show_error(const char *txt);
MainWindow* pavucontrol_get_window(pa_glib_mainloop *m, bool maximize, bool retry, int tab_number);
#ifdef HAVE_PULSE_MESSAGING_API
+std::string card_message_handler_path(const std::string& name);
std::string card_bluez_message_handler_path(const std::string& name);
#endif