cardwidget: add flag to lock profile from switching automatically
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pavucontrol/-/merge_requests/60>
This commit is contained in:
parent
b874058ae8
commit
a1b4622ad5
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue