Use Gtk4 instead of Gtk3
This commit is contained in:
parent
04655fae70
commit
52aef7e81d
|
@ -1,16 +1,16 @@
|
|||
project('pavucontrol', 'cpp',
|
||||
version : '5.0',
|
||||
meson_version : '>= 0.50.0',
|
||||
default_options : [ 'c_std=gnu11', 'cpp_std=c++11' ]
|
||||
default_options : [ 'c_std=gnu11', 'cpp_std=c++17' ]
|
||||
)
|
||||
|
||||
with_lynx = get_option('lynx')
|
||||
|
||||
cpp = meson.get_compiler('cpp')
|
||||
|
||||
gtkmm_dep = dependency('gtkmm-3.0', version : '>= 3.0', required : true)
|
||||
gtkmm_dep = dependency('gtkmm-4.0', version : '>= 4.0', required : true)
|
||||
sigcpp_dep = dependency('sigc++-2.0', required : true)
|
||||
canberragtk_dep = dependency('libcanberra-gtk3', version : '>= 0.16', required : true)
|
||||
canberragtk_dep = dependency('libcanberra', version : '>= 0.16', required : true)
|
||||
|
||||
libpulse_dep = dependency('libpulse', version : '>= 5.0', required : true)
|
||||
libpulsemlglib_dep = dependency('libpulse-mainloop-glib', version : '>= 0.9.16', required : true)
|
||||
|
|
|
@ -28,14 +28,14 @@
|
|||
|
||||
/*** CardWidget ***/
|
||||
CardWidget::CardWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& x) :
|
||||
Gtk::VBox(cobject) {
|
||||
Gtk::Box(cobject) {
|
||||
|
||||
x->get_widget("cardNameLabel", nameLabel);
|
||||
x->get_widget("profileList", profileList);
|
||||
x->get_widget("cardIconImage", iconImage);
|
||||
x->get_widget("codecBox", codecBox);
|
||||
x->get_widget("codecList", codecList);
|
||||
x->get_widget("profileLockToggleButton", profileLockToggleButton);
|
||||
nameLabel = x->get_widget<Gtk::Label>("cardNameLabel");
|
||||
profileList = x->get_widget<Gtk::ComboBox>("profileList");
|
||||
iconImage = x->get_widget<Gtk::Image>("cardIconImage");
|
||||
codecBox = x->get_widget<Gtk::Box>("codecBox");
|
||||
codecList = x->get_widget<Gtk::ComboBox>("codecList");
|
||||
profileLockToggleButton = x->get_widget<Gtk::ToggleButton>("profileLockToggleButton");
|
||||
|
||||
profileListStore = Gtk::ListStore::create(profileModel);
|
||||
profileList->set_model(profileListStore);
|
||||
|
@ -61,7 +61,7 @@ CardWidget::CardWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>
|
|||
CardWidget* CardWidget::create() {
|
||||
CardWidget* w;
|
||||
Glib::RefPtr<Gtk::Builder> x = Gtk::Builder::create_from_file(GLADE_FILE, "cardWidget");
|
||||
x->get_widget_derived("cardWidget", w);
|
||||
w = Gtk::Builder::get_widget_derived<CardWidget>(x, "cardWidget");
|
||||
w->reference();
|
||||
return w;
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ void CardWidget::onProfileChange() {
|
|||
Glib::ustring profile = row[profileModel.name];
|
||||
|
||||
if (!(o = pa_context_set_card_profile_by_index(get_context(), index, profile.c_str(), NULL, NULL))) {
|
||||
show_error(_("pa_context_set_card_profile_by_index() failed"));
|
||||
show_error(this, _("pa_context_set_card_profile_by_index() failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,13 +34,12 @@ public:
|
|||
std::vector<Glib::ustring> profiles;
|
||||
};
|
||||
|
||||
class CardWidget : public Gtk::VBox {
|
||||
class CardWidget : public Gtk::Box {
|
||||
public:
|
||||
CardWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& x);
|
||||
static CardWidget* create();
|
||||
|
||||
Gtk::Label *nameLabel;
|
||||
Gtk::Menu menu;
|
||||
Gtk::Image *iconImage;
|
||||
Glib::ustring name;
|
||||
std::string pulse_card_name;
|
||||
|
|
|
@ -30,14 +30,14 @@
|
|||
/*** ChannelWidget ***/
|
||||
|
||||
ChannelWidget::ChannelWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& x) :
|
||||
Gtk::EventBox(cobject),
|
||||
Gtk::Widget(cobject),
|
||||
can_decibel(false),
|
||||
volumeScaleEnabled(true),
|
||||
last(false) {
|
||||
|
||||
x->get_widget("channelLabel", channelLabel);
|
||||
x->get_widget("volumeLabel", volumeLabel);
|
||||
x->get_widget("volumeScale", volumeScale);
|
||||
channelLabel = x->get_widget<Gtk::Label>("channelLabel");
|
||||
volumeLabel = x->get_widget<Gtk::Label>("volumeLabel");
|
||||
volumeScale = x->get_widget<Gtk::Scale>("volumeScale");
|
||||
|
||||
volumeScale->set_range((double)PA_VOLUME_MUTED, (double)PA_VOLUME_UI_MAX);
|
||||
volumeScale->set_value((double)PA_VOLUME_NORM);
|
||||
|
@ -52,7 +52,7 @@ ChannelWidget* ChannelWidget::createOne(MinimalStreamWidget *owner, int channelI
|
|||
Glib::RefPtr<Gtk::Builder> x = Gtk::Builder::create();
|
||||
x->add_from_file(GLADE_FILE, "adjustment1");
|
||||
x->add_from_file(GLADE_FILE, "channelWidget");
|
||||
x->get_widget_derived("channelWidget", w);
|
||||
w = Gtk::Builder::get_widget_derived<ChannelWidget>(x, "channelWidget");
|
||||
w->reference();
|
||||
|
||||
w->channel = channelIndex;
|
||||
|
@ -75,8 +75,8 @@ void ChannelWidget::create(MinimalStreamWidget *owner, const pa_channel_map &m,
|
|||
Gtk::Requisition minimumSize;
|
||||
Gtk::Requisition naturalSize;
|
||||
widgets[i]->channelLabel->get_preferred_size(minimumSize, naturalSize);
|
||||
if (naturalSize.width > maxLabelWidth)
|
||||
maxLabelWidth = naturalSize.width;
|
||||
if (naturalSize.get_width() > maxLabelWidth)
|
||||
maxLabelWidth = naturalSize.get_width();
|
||||
}
|
||||
|
||||
widgets[m.channels - 1]->last = true;
|
||||
|
@ -108,6 +108,7 @@ void ChannelWidget::setVolume(pa_volume_t volume) {
|
|||
|
||||
volumeScaleEnabled = false;
|
||||
volumeScale->set_value(volume > PA_VOLUME_UI_MAX ? PA_VOLUME_UI_MAX : volume);
|
||||
currentVolume = volumeScale->get_value();
|
||||
volumeScaleEnabled = true;
|
||||
}
|
||||
|
||||
|
@ -120,11 +121,12 @@ void ChannelWidget::onVolumeScaleValueChanged() {
|
|||
return;
|
||||
|
||||
pa_volume_t volume = (pa_volume_t) volumeScale->get_value();
|
||||
minimalStreamWidget->updateChannelVolume(channel, volume);
|
||||
if (volume != currentVolume)
|
||||
minimalStreamWidget->updateChannelVolume(channel, volume);
|
||||
}
|
||||
|
||||
void ChannelWidget::set_sensitive(bool enabled) {
|
||||
Gtk::EventBox::set_sensitive(enabled);
|
||||
Gtk::Widget::set_sensitive(enabled);
|
||||
|
||||
channelLabel->set_sensitive(enabled);
|
||||
volumeLabel->set_sensitive(enabled);
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
class MinimalStreamWidget;
|
||||
|
||||
class ChannelWidget : public Gtk::EventBox {
|
||||
class ChannelWidget : public Gtk::Widget {
|
||||
public:
|
||||
ChannelWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& x);
|
||||
|
||||
|
@ -53,6 +53,7 @@ public:
|
|||
virtual void setBaseVolume(pa_volume_t);
|
||||
|
||||
private:
|
||||
pa_volume_t currentVolume;
|
||||
static ChannelWidget *createOne(MinimalStreamWidget *owner, int channelIndex, pa_channel_position channelPosition,
|
||||
bool can_decibel);
|
||||
};
|
||||
|
|
|
@ -37,29 +37,45 @@ DeviceWidget::DeviceWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Buil
|
|||
mDigital(false) {
|
||||
|
||||
/* MinimalStreamWidget member variables. */
|
||||
x->get_widget("deviceChannelsVBox", channelsVBox);
|
||||
x->get_widget("deviceNameLabel", nameLabel);
|
||||
x->get_widget("deviceBoldNameLabel", boldNameLabel);
|
||||
x->get_widget("deviceIconImage", iconImage);
|
||||
channelsVBox = x->get_widget<Gtk::Box>("deviceChannelsVBox");
|
||||
nameLabel = x->get_widget<Gtk::Label>("deviceNameLabel");
|
||||
boldNameLabel = x->get_widget<Gtk::Label>("deviceBoldNameLabel");
|
||||
iconImage= x->get_widget<Gtk::Image>("deviceIconImage");
|
||||
|
||||
x->get_widget("deviceLockToggleButton", lockToggleButton);
|
||||
x->get_widget("deviceMuteToggleButton", muteToggleButton);
|
||||
x->get_widget("defaultToggleButton", defaultToggleButton);
|
||||
x->get_widget("portSelect", portSelect);
|
||||
x->get_widget("portList", portList);
|
||||
x->get_widget("advancedOptions", advancedOptions);
|
||||
x->get_widget("offsetSelect", offsetSelect);
|
||||
x->get_widget("offsetButton", offsetButton);
|
||||
lockToggleButton = x->get_widget<Gtk::ToggleButton>("deviceLockToggleButton");
|
||||
muteToggleButton = x->get_widget<Gtk::ToggleButton>("deviceMuteToggleButton");
|
||||
defaultToggleButton= x->get_widget<Gtk::ToggleButton>("defaultToggleButton");
|
||||
portSelect = x->get_widget<Gtk::Box>("portSelect");
|
||||
portList = x->get_widget<Gtk::ComboBox>("portList");
|
||||
advancedOptions = x->get_widget<Gtk::Expander>("advancedOptions");
|
||||
offsetSelect = x->get_widget<Gtk::Box>("offsetSelect");
|
||||
offsetButton = x->get_widget<Gtk::SpinButton>("offsetButton");
|
||||
|
||||
this->signal_button_press_event().connect(sigc::mem_fun(*this, &DeviceWidget::onContextTriggerEvent));
|
||||
muteToggleButton->signal_clicked().connect(sigc::mem_fun(*this, &DeviceWidget::onMuteToggleButton));
|
||||
lockToggleButton->signal_clicked().connect(sigc::mem_fun(*this, &DeviceWidget::onLockToggleButton));
|
||||
defaultToggleButton->signal_clicked().connect(sigc::mem_fun(*this, &DeviceWidget::onDefaultToggleButton));
|
||||
|
||||
rename.set_label(_("Rename Device..."));
|
||||
rename.signal_activate().connect(sigc::mem_fun(*this, &DeviceWidget::renamePopup));
|
||||
contextMenu.append(rename);
|
||||
contextMenu.show_all();
|
||||
auto gesture = Gtk::GestureClick::create();
|
||||
gesture->set_button(3);
|
||||
gesture->set_exclusive(true);
|
||||
gesture->signal_pressed().connect(sigc::mem_fun(*this, &DeviceWidget::onContextTriggerEvent));
|
||||
this->add_controller(gesture);
|
||||
|
||||
const std::string actionName = "rename", groupName="devicewidget";
|
||||
auto action = Gio::SimpleAction::create(actionName);
|
||||
action->set_enabled(true);
|
||||
action->signal_activate().connect(sigc::mem_fun(*this, &DeviceWidget::openRenamePopup));
|
||||
|
||||
auto group = Gio::SimpleActionGroup::create();
|
||||
group->add_action(action);
|
||||
|
||||
insert_action_group(groupName, group);
|
||||
|
||||
auto menuModel = Gio::Menu::create();
|
||||
menuModel->append(_("Rename Device..."), groupName + "." + actionName);
|
||||
contextMenu.set_menu_model(menuModel);
|
||||
contextMenu.set_parent(*this);
|
||||
|
||||
|
||||
treeModel = Gtk::ListStore::create(portModel);
|
||||
portList->set_model(treeModel);
|
||||
|
@ -88,7 +104,7 @@ void DeviceWidget::setChannelMap(const pa_channel_map &m, bool can_decibel) {
|
|||
|
||||
for (int i = 0; i < m.channels; i++) {
|
||||
ChannelWidget *cw = channelWidgets[i];
|
||||
channelsVBox->pack_start(*cw, false, false, 0);
|
||||
channelsVBox->prepend(*cw);
|
||||
cw->unreference();
|
||||
}
|
||||
|
||||
|
@ -160,7 +176,7 @@ void DeviceWidget::onOffsetChange() {
|
|||
|
||||
if (!(o = pa_context_set_port_latency_offset(get_context(),
|
||||
card_name.c_str(), activePort.c_str(), offset, NULL, NULL))) {
|
||||
show_error(_("pa_context_set_port_latency_offset() failed"));
|
||||
show_error(this, _("pa_context_set_port_latency_offset() failed"));
|
||||
return;
|
||||
}
|
||||
pa_operation_unref(o);
|
||||
|
@ -225,55 +241,64 @@ void DeviceWidget::prepareMenu() {
|
|||
updateAdvancedOptionsVisibility();
|
||||
}
|
||||
|
||||
bool DeviceWidget::onContextTriggerEvent(GdkEventButton* event) {
|
||||
if (GDK_BUTTON_PRESS == event->type && 3 == event->button) {
|
||||
contextMenu.popup_at_pointer((GdkEvent*)event);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
void DeviceWidget::onContextTriggerEvent(gint n_press, gdouble x, gdouble y) {
|
||||
if (n_press == 1) {
|
||||
contextMenu.set_pointing_to(Gdk::Rectangle {(int) x, (int) y, 0 , 0});
|
||||
contextMenu.popup();
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceWidget::renamePopup() {
|
||||
void DeviceWidget::openRenamePopup(const Glib::VariantBase& parameter) {
|
||||
if (updating)
|
||||
return;
|
||||
|
||||
if (!mpMainWindow->canRenameDevices) {
|
||||
Gtk::MessageDialog dialog(
|
||||
*mpMainWindow,
|
||||
_("Sorry, but device renaming is not supported."),
|
||||
false,
|
||||
Gtk::MESSAGE_WARNING,
|
||||
Gtk::BUTTONS_OK,
|
||||
true);
|
||||
dialog.set_secondary_text(_("You need to load module-device-manager in the PulseAudio server in order to rename devices"));
|
||||
dialog.run();
|
||||
auto dialog = Gtk::AlertDialog::create(_("Sorry, but device renaming is not supported."));
|
||||
dialog->set_modal(true);
|
||||
dialog->set_detail(_("You need to load module-device-manager in the PulseAudio server in order to rename devices"));
|
||||
dialog->show(*mpMainWindow);
|
||||
return;
|
||||
}
|
||||
|
||||
Gtk::Dialog* dialog;
|
||||
Gtk::Entry* renameText;
|
||||
|
||||
Glib::RefPtr<Gtk::Builder> x = Gtk::Builder::create_from_file(GLADE_FILE, "renameDialog");
|
||||
x->get_widget("renameDialog", dialog);
|
||||
x->get_widget("renameText", renameText);
|
||||
gchar *key = g_markup_printf_escaped("%s:%s", mDeviceType.c_str(), name.c_str());
|
||||
RenameWindow* renameDialog = Gtk::Builder::get_widget_derived<RenameWindow>(x, "renameDialog", description.c_str(), key);
|
||||
renameDialog->set_transient_for(*mpMainWindow);
|
||||
|
||||
renameText->set_text(description);
|
||||
dialog->add_button(_("_Cancel"), Gtk::RESPONSE_CANCEL);
|
||||
dialog->add_button(_("_OK"), Gtk::RESPONSE_OK);
|
||||
dialog->set_default_response(Gtk::RESPONSE_OK);
|
||||
if (Gtk::RESPONSE_OK == dialog->run()) {
|
||||
pa_operation* o;
|
||||
gchar *key = g_markup_printf_escaped("%s:%s", mDeviceType.c_str(), name.c_str());
|
||||
renameDialog->present();
|
||||
}
|
||||
|
||||
if (!(o = pa_ext_device_manager_set_device_description(get_context(), key, renameText->get_text().c_str(), NULL, NULL))) {
|
||||
show_error(_("pa_ext_device_manager_write() failed"));
|
||||
return;
|
||||
}
|
||||
pa_operation_unref(o);
|
||||
g_free(key);
|
||||
RenameWindow::RenameWindow(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& x, const gchar* name, const gchar* key) :
|
||||
Gtk::ApplicationWindow(cobject),
|
||||
deviceKey(key){
|
||||
|
||||
renameText = x->get_widget<Gtk::Entry>("renameText");
|
||||
renameText->set_text(name);
|
||||
|
||||
Gtk::Button* renameButton = x->get_widget<Gtk::Button>("renameButton");
|
||||
set_default_widget(*renameButton);
|
||||
|
||||
auto renameAction = Gio::SimpleAction::create("rename");
|
||||
renameAction->set_enabled(true);
|
||||
renameAction->signal_activate().connect(sigc::mem_fun(*this, &RenameWindow::renamePopup));
|
||||
|
||||
add_action(renameAction);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void RenameWindow::renamePopup(const Glib::VariantBase& parameter){
|
||||
pa_operation* o;
|
||||
auto name = renameText->get_text();
|
||||
|
||||
if (!(o = pa_ext_device_manager_set_device_description(get_context(), deviceKey, name.c_str(), NULL, NULL))) {
|
||||
show_error(this, _("pa_ext_device_manager_write() failed"));
|
||||
return;
|
||||
}
|
||||
delete dialog;
|
||||
pa_operation_unref(o);
|
||||
g_free((char*)deviceKey);
|
||||
delete this;
|
||||
}
|
||||
|
||||
void DeviceWidget::updateAdvancedOptionsVisibility() {
|
||||
|
|
|
@ -57,7 +57,7 @@ public:
|
|||
virtual void onLockToggleButton();
|
||||
virtual void onDefaultToggleButton();
|
||||
virtual void setDefault(bool isDefault);
|
||||
virtual bool onContextTriggerEvent(GdkEventButton*);
|
||||
virtual void onContextTriggerEvent(gint n_press, gdouble x, gdouble y);
|
||||
virtual void setLatencyOffset(int64_t offset);
|
||||
void onOffsetChange();
|
||||
|
||||
|
@ -73,7 +73,7 @@ public:
|
|||
|
||||
void prepareMenu();
|
||||
|
||||
void renamePopup();
|
||||
void openRenamePopup(const Glib::VariantBase& parameter);
|
||||
|
||||
protected:
|
||||
MainWindow *mpMainWindow;
|
||||
|
@ -85,8 +85,7 @@ protected:
|
|||
|
||||
virtual void onPortChange() = 0;
|
||||
|
||||
Gtk::Menu contextMenu;
|
||||
Gtk::MenuItem rename;
|
||||
Gtk::PopoverMenu contextMenu;
|
||||
|
||||
/* Tree model columns */
|
||||
class ModelColumns : public Gtk::TreeModel::ColumnRecord
|
||||
|
@ -103,7 +102,7 @@ protected:
|
|||
ModelColumns portModel;
|
||||
|
||||
Gtk::Expander *advancedOptions;
|
||||
Gtk::HBox *portSelect, *offsetSelect;
|
||||
Gtk::Box *portSelect, *offsetSelect;
|
||||
Gtk::ComboBox *portList;
|
||||
Glib::RefPtr<Gtk::ListStore> treeModel;
|
||||
Glib::RefPtr<Gtk::Adjustment> offsetAdjustment;
|
||||
|
@ -114,7 +113,15 @@ protected:
|
|||
|
||||
private:
|
||||
Glib::ustring mDeviceType;
|
||||
};
|
||||
|
||||
class RenameWindow : public Gtk::ApplicationWindow {
|
||||
public:
|
||||
RenameWindow(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& x, const gchar* name, const gchar* key);
|
||||
Gtk::Entry* renameText;
|
||||
const gchar* deviceKey;
|
||||
private:
|
||||
void renamePopup(const Glib::VariantBase& parameter);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -76,30 +76,26 @@ MainWindow::MainWindow(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>
|
|||
canRenameDevices(false),
|
||||
m_connected(false),
|
||||
m_config_filename(NULL) {
|
||||
ca_context_create (&canberraContext);
|
||||
ca_context_set_driver(canberraContext, "pulse");
|
||||
|
||||
x->get_widget("cardsVBox", cardsVBox);
|
||||
x->get_widget("streamsVBox", streamsVBox);
|
||||
x->get_widget("recsVBox", recsVBox);
|
||||
x->get_widget("sinksVBox", sinksVBox);
|
||||
x->get_widget("sourcesVBox", sourcesVBox);
|
||||
x->get_widget("noCardsLabel", noCardsLabel);
|
||||
x->get_widget("noStreamsLabel", noStreamsLabel);
|
||||
x->get_widget("noRecsLabel", noRecsLabel);
|
||||
x->get_widget("noSinksLabel", noSinksLabel);
|
||||
x->get_widget("noSourcesLabel", noSourcesLabel);
|
||||
x->get_widget("connectingLabel", connectingLabel);
|
||||
x->get_widget("sinkInputTypeComboBox", sinkInputTypeComboBox);
|
||||
x->get_widget("sourceOutputTypeComboBox", sourceOutputTypeComboBox);
|
||||
x->get_widget("sinkTypeComboBox", sinkTypeComboBox);
|
||||
x->get_widget("sourceTypeComboBox", sourceTypeComboBox);
|
||||
x->get_widget("notebook", notebook);
|
||||
x->get_widget("showVolumeMetersCheckButton", showVolumeMetersCheckButton);
|
||||
|
||||
sourcesVBox->signal_size_allocate().connect([this](Gdk::Rectangle _unused){ sourcesVBox->queue_draw(); });
|
||||
cardsVBox->signal_size_allocate().connect([this](Gdk::Rectangle _unused){ cardsVBox->queue_draw(); });
|
||||
streamsVBox->signal_size_allocate().connect([this](Gdk::Rectangle _unused){ streamsVBox->queue_draw(); });
|
||||
recsVBox->signal_size_allocate().connect([this](Gdk::Rectangle _unused){ recsVBox->queue_draw(); });
|
||||
sinksVBox->signal_size_allocate().connect([this](Gdk::Rectangle _unused){ sinksVBox->queue_draw(); });
|
||||
cardsVBox = x->get_widget<Gtk::Box>("cardsVBox");
|
||||
streamsVBox = x->get_widget<Gtk::Box>("streamsVBox");
|
||||
recsVBox = x->get_widget<Gtk::Box>("recsVBox");
|
||||
sinksVBox = x->get_widget<Gtk::Box>("sinksVBox");
|
||||
sourcesVBox = x->get_widget<Gtk::Box>("sourcesVBox");
|
||||
noCardsLabel = x->get_widget<Gtk::Label>("noCardsLabel");
|
||||
noStreamsLabel = x->get_widget<Gtk::Label>("noStreamsLabel");
|
||||
noRecsLabel = x->get_widget<Gtk::Label>("noRecsLabel");
|
||||
noSinksLabel = x->get_widget<Gtk::Label>("noSinksLabel");
|
||||
noSourcesLabel = x->get_widget<Gtk::Label>("noSourcesLabel");
|
||||
connectingLabel = x->get_widget<Gtk::Label>("connectingLabel");
|
||||
sinkInputTypeComboBox = x->get_widget<Gtk::ComboBox>("sinkInputTypeComboBox");
|
||||
sourceOutputTypeComboBox = x->get_widget<Gtk::ComboBox>("sourceOutputTypeComboBox");
|
||||
sinkTypeComboBox = x->get_widget<Gtk::ComboBox>("sinkTypeComboBox");
|
||||
sourceTypeComboBox = x->get_widget<Gtk::ComboBox>("sourceTypeComboBox");
|
||||
notebook = x->get_widget<Gtk::Notebook>("notebook");
|
||||
showVolumeMetersCheckButton = x->get_widget<Gtk::CheckButton>("showVolumeMetersCheckButton");
|
||||
|
||||
sinkInputTypeComboBox->set_active((int) showSinkInputType);
|
||||
sourceOutputTypeComboBox->set_active((int) showSourceOutputType);
|
||||
|
@ -112,6 +108,9 @@ MainWindow::MainWindow(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>
|
|||
sourceTypeComboBox->signal_changed().connect(sigc::mem_fun(*this, &MainWindow::onSourceTypeComboBoxChanged));
|
||||
showVolumeMetersCheckButton->signal_toggled().connect(sigc::mem_fun(*this, &MainWindow::onShowVolumeMetersCheckButtonToggled));
|
||||
|
||||
auto event_controller_key = Gtk::EventControllerKey::create();
|
||||
event_controller_key->signal_key_pressed().connect(sigc::mem_fun(*this, &MainWindow::on_key_press_event), false);
|
||||
this->add_controller(event_controller_key);
|
||||
|
||||
GKeyFile* config = g_key_file_new();
|
||||
g_assert(config);
|
||||
|
@ -134,7 +133,7 @@ MainWindow::MainWindow(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>
|
|||
int default_width, default_height;
|
||||
get_default_size(default_width, default_height);
|
||||
if (width >= default_width && height >= default_height)
|
||||
resize(width, height);
|
||||
set_default_size(width, height);
|
||||
|
||||
int sinkInputTypeSelection = g_key_file_get_integer(config, "window", "sinkInputType", &err);
|
||||
if (err == NULL)
|
||||
|
@ -187,7 +186,7 @@ MainWindow* MainWindow::create(bool maximize) {
|
|||
x->add_from_file(GLADE_FILE, "liststore3");
|
||||
x->add_from_file(GLADE_FILE, "liststore4");
|
||||
x->add_from_file(GLADE_FILE, "mainWindow");
|
||||
x->get_widget_derived("mainWindow", w);
|
||||
w = Gtk::Builder::get_widget_derived<MainWindow>(x, "mainWindow");
|
||||
w->get_style_context()->add_class("pavucontrol-window");
|
||||
if (w && maximize)
|
||||
w->maximize();
|
||||
|
@ -197,26 +196,26 @@ MainWindow* MainWindow::create(bool maximize) {
|
|||
void MainWindow::on_realize() {
|
||||
Gtk::Window::on_realize();
|
||||
|
||||
get_window()->set_cursor(Gdk::Cursor::create(Gdk::WATCH));
|
||||
set_cursor(Gdk::Cursor::create("wait"));
|
||||
}
|
||||
|
||||
bool MainWindow::on_key_press_event(GdkEventKey* event) {
|
||||
bool MainWindow::on_key_press_event(guint keyval, guint keycode, Gdk::ModifierType state) {
|
||||
|
||||
if (event->state & GDK_CONTROL_MASK) {
|
||||
switch (event->keyval) {
|
||||
if ((state & Gdk::ModifierType::CONTROL_MASK) == Gdk::ModifierType::CONTROL_MASK) {
|
||||
switch (keyval) {
|
||||
case GDK_KEY_KP_1:
|
||||
case GDK_KEY_KP_2:
|
||||
case GDK_KEY_KP_3:
|
||||
case GDK_KEY_KP_4:
|
||||
case GDK_KEY_KP_5:
|
||||
notebook->set_current_page(event->keyval - GDK_KEY_KP_1);
|
||||
notebook->set_current_page(keyval - GDK_KEY_KP_1);
|
||||
return true;
|
||||
case GDK_KEY_1:
|
||||
case GDK_KEY_2:
|
||||
case GDK_KEY_3:
|
||||
case GDK_KEY_4:
|
||||
case GDK_KEY_5:
|
||||
notebook->set_current_page(event->keyval - GDK_KEY_1);
|
||||
notebook->set_current_page(keyval - GDK_KEY_1);
|
||||
return true;
|
||||
case GDK_KEY_W:
|
||||
case GDK_KEY_Q:
|
||||
|
@ -226,7 +225,7 @@ bool MainWindow::on_key_press_event(GdkEventKey* event) {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
return Gtk::Window::on_key_press_event(event);
|
||||
return false;
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow() {
|
||||
|
@ -234,7 +233,7 @@ MainWindow::~MainWindow() {
|
|||
g_assert(config);
|
||||
|
||||
int width, height;
|
||||
get_size(width, height);
|
||||
get_default_size(width, height);
|
||||
g_key_file_set_integer(config, "window", "width", width);
|
||||
g_key_file_set_integer(config, "window", "height", height);
|
||||
g_key_file_set_integer(config, "window", "sinkInputType", sinkInputTypeComboBox->get_active_row_number());
|
||||
|
@ -247,7 +246,7 @@ MainWindow::~MainWindow() {
|
|||
GError *err = NULL;
|
||||
gchar *filedata = g_key_file_to_data(config, &filelen, &err);
|
||||
if (err) {
|
||||
show_error(_("Error saving preferences"));
|
||||
show_error(this, _("Error saving preferences"));
|
||||
g_error_free(err);
|
||||
goto finish;
|
||||
}
|
||||
|
@ -256,7 +255,7 @@ MainWindow::~MainWindow() {
|
|||
g_free(filedata);
|
||||
if (err) {
|
||||
gchar* msg = g_strconcat(_("Error writing config file %s"), m_config_filename, NULL);
|
||||
show_error(msg);
|
||||
show_error(this, msg);
|
||||
g_free(msg);
|
||||
g_error_free(err);
|
||||
goto finish;
|
||||
|
@ -274,34 +273,20 @@ finish:
|
|||
}
|
||||
}
|
||||
|
||||
static void set_icon_name_default(Gtk::Image *i, const char *name, Gtk::IconSize size) {
|
||||
static void set_icon_name_default(Gtk::Image *i, const char *name) {
|
||||
/* We emulate the behavior of the GTK_ICON_LOOKUP_GENERIC_FALLBACK flag from Gtk3 */
|
||||
Glib::RefPtr<Gtk::IconTheme> theme;
|
||||
Glib::RefPtr<Gdk::Pixbuf> pixbuf;
|
||||
gint width = 24, height = 24;
|
||||
|
||||
Gtk::IconSize::lookup(size, width, height);
|
||||
theme = Gtk::IconTheme::get_default();
|
||||
|
||||
try {
|
||||
pixbuf = theme->load_icon(name, width, Gtk::ICON_LOOKUP_GENERIC_FALLBACK | Gtk::ICON_LOOKUP_FORCE_SIZE);
|
||||
} catch (Glib::Error &e) {
|
||||
/* Ignore errors. */
|
||||
}
|
||||
|
||||
if (!pixbuf) {
|
||||
try {
|
||||
pixbuf = Gdk::Pixbuf::create_from_file(name);
|
||||
} catch (Glib::FileError &e) {
|
||||
/* Ignore errors. */
|
||||
} catch (Gdk::PixbufError &e) {
|
||||
/* Ignore errors. */
|
||||
theme = Gtk::IconTheme::get_for_display(Gdk::Display::get_default());
|
||||
std::string iconName(name);
|
||||
while (!theme->has_icon(iconName.c_str())) {
|
||||
size_t lastDashIndex = iconName.find_last_of("-");
|
||||
if (lastDashIndex == std::string::npos) {
|
||||
iconName = "gtk-missing-image";
|
||||
break;
|
||||
}
|
||||
iconName = iconName.substr(0,lastDashIndex);
|
||||
}
|
||||
|
||||
if (pixbuf) {
|
||||
pixbuf = pixbuf->scale_simple(width, height, Gdk::INTERP_BILINEAR);
|
||||
i->set(pixbuf);
|
||||
}
|
||||
i->set_from_icon_name(iconName.c_str());
|
||||
}
|
||||
|
||||
static void updatePorts(DeviceWidget *w, std::map<Glib::ustring, PortInfo> &ports) {
|
||||
|
@ -365,7 +350,7 @@ void MainWindow::updateCard(const pa_card_info &info) {
|
|||
w = cardWidgets[info.index];
|
||||
else {
|
||||
cardWidgets[info.index] = w = CardWidget::create();
|
||||
cardsVBox->pack_start(*w, false, false, 0);
|
||||
cardsVBox->append(*w);
|
||||
w->unreference();
|
||||
w->index = info.index;
|
||||
is_new = true;
|
||||
|
@ -382,7 +367,7 @@ void MainWindow::updateCard(const pa_card_info &info) {
|
|||
g_free(txt);
|
||||
|
||||
icon = pa_proplist_gets(info.proplist, PA_PROP_DEVICE_ICON_NAME);
|
||||
set_icon_name_default(w->iconImage, icon ? icon : "audio-card", Gtk::ICON_SIZE_SMALL_TOOLBAR);
|
||||
set_icon_name_default(w->iconImage, icon ? icon : "audio-card");
|
||||
|
||||
w->hasSinks = w->hasSources = false;
|
||||
profile_priorities.clear();
|
||||
|
@ -556,7 +541,7 @@ bool MainWindow::updateSink(const pa_sink_info &info) {
|
|||
else {
|
||||
sinkWidgets[info.index] = w = SinkWidget::create(this);
|
||||
w->setChannelMap(info.channel_map, !!(info.flags & PA_SINK_DECIBEL_VOLUME));
|
||||
sinksVBox->pack_start(*w, false, false, 0);
|
||||
sinksVBox->append(*w);
|
||||
w->unreference();
|
||||
w->index = info.index;
|
||||
w->monitor_index = info.monitor_source;
|
||||
|
@ -580,7 +565,7 @@ bool MainWindow::updateSink(const pa_sink_info &info) {
|
|||
g_free(txt);
|
||||
|
||||
icon = pa_proplist_gets(info.proplist, PA_PROP_DEVICE_ICON_NAME);
|
||||
set_icon_name_default(w->iconImage, icon ? icon : "audio-card", Gtk::ICON_SIZE_SMALL_TOOLBAR);
|
||||
set_icon_name_default(w->iconImage, icon ? icon : "audio-card");
|
||||
|
||||
w->setVolume(info.volume);
|
||||
w->muteToggleButton->set_active(info.mute);
|
||||
|
@ -630,7 +615,7 @@ static void read_callback(pa_stream *s, size_t length, void *userdata) {
|
|||
double v;
|
||||
|
||||
if (pa_stream_peek(s, &data, &length) < 0) {
|
||||
show_error(_("Failed to read data from stream"));
|
||||
show_error(w, _("Failed to read data from stream"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -675,7 +660,7 @@ pa_stream* MainWindow::createMonitorStreamForSource(uint32_t source_idx, uint32_
|
|||
snprintf(t, sizeof(t), "%u", source_idx);
|
||||
|
||||
if (!(s = pa_stream_new(get_context(), _("Peak detect"), &ss, NULL))) {
|
||||
show_error(_("Failed to create monitoring stream"));
|
||||
show_error(this, _("Failed to create monitoring stream"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -690,7 +675,7 @@ pa_stream* MainWindow::createMonitorStreamForSource(uint32_t source_idx, uint32_
|
|||
(!showVolumeMetersCheckButton->get_active() ? PA_STREAM_START_CORKED : PA_STREAM_NOFLAGS));
|
||||
|
||||
if (pa_stream_connect_record(s, t, &attr, flags) < 0) {
|
||||
show_error(_("Failed to connect monitoring stream"));
|
||||
show_error(this, _("Failed to connect monitoring stream"));
|
||||
pa_stream_unref(s);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -722,7 +707,7 @@ void MainWindow::updateSource(const pa_source_info &info) {
|
|||
else {
|
||||
sourceWidgets[info.index] = w = SourceWidget::create(this);
|
||||
w->setChannelMap(info.channel_map, !!(info.flags & PA_SOURCE_DECIBEL_VOLUME));
|
||||
sourcesVBox->pack_start(*w, false, false, 0);
|
||||
sourcesVBox->append(*w);
|
||||
w->unreference();
|
||||
w->index = info.index;
|
||||
is_new = true;
|
||||
|
@ -748,7 +733,7 @@ void MainWindow::updateSource(const pa_source_info &info) {
|
|||
g_free(txt);
|
||||
|
||||
icon = pa_proplist_gets(info.proplist, PA_PROP_DEVICE_ICON_NAME);
|
||||
set_icon_name_default(w->iconImage, icon ? icon : "audio-input-microphone", Gtk::ICON_SIZE_SMALL_TOOLBAR);
|
||||
set_icon_name_default(w->iconImage, icon ? icon : "audio-input-microphone");
|
||||
|
||||
w->setVolume(info.volume);
|
||||
w->muteToggleButton->set_active(info.mute);
|
||||
|
@ -817,7 +802,7 @@ void MainWindow::setIconFromProplist(Gtk::Image *icon, pa_proplist *l, const cha
|
|||
|
||||
finish:
|
||||
|
||||
set_icon_name_default(icon, t, Gtk::ICON_SIZE_SMALL_TOOLBAR);
|
||||
set_icon_name_default(icon, t);
|
||||
}
|
||||
|
||||
void MainWindow::updateSinkInput(const pa_sink_input_info &info) {
|
||||
|
@ -840,7 +825,7 @@ void MainWindow::updateSinkInput(const pa_sink_input_info &info) {
|
|||
} else {
|
||||
sinkInputWidgets[info.index] = w = SinkInputWidget::create(this);
|
||||
w->setChannelMap(info.channel_map, true);
|
||||
streamsVBox->pack_start(*w, false, false, 0);
|
||||
streamsVBox->append(*w);
|
||||
w->unreference();
|
||||
w->index = info.index;
|
||||
w->clientIndex = info.client;
|
||||
|
@ -899,7 +884,7 @@ void MainWindow::updateSourceOutput(const pa_source_output_info &info) {
|
|||
#if HAVE_SOURCE_OUTPUT_VOLUMES
|
||||
w->setChannelMap(info.channel_map, true);
|
||||
#endif
|
||||
recsVBox->pack_start(*w, false, false, 0);
|
||||
recsVBox->append(*w);
|
||||
w->unreference();
|
||||
w->index = info.index;
|
||||
w->clientIndex = info.client;
|
||||
|
@ -996,7 +981,7 @@ bool MainWindow::createEventRoleWidget() {
|
|||
};
|
||||
|
||||
eventRoleWidget = RoleWidget::create();
|
||||
streamsVBox->pack_start(*eventRoleWidget, false, false, 0);
|
||||
streamsVBox->append(*eventRoleWidget);
|
||||
eventRoleWidget->unreference();
|
||||
eventRoleWidget->role = "sink-input-by-media-role:event";
|
||||
eventRoleWidget->setChannelMap(cm, true);
|
||||
|
@ -1004,7 +989,7 @@ bool MainWindow::createEventRoleWidget() {
|
|||
eventRoleWidget->boldNameLabel->set_text("");
|
||||
eventRoleWidget->nameLabel->set_label(_("System Sounds"));
|
||||
|
||||
eventRoleWidget->iconImage->set_from_icon_name("multimedia-volume-control", Gtk::ICON_SIZE_SMALL_TOOLBAR);
|
||||
eventRoleWidget->iconImage->set_from_icon_name("multimedia-volume-control");
|
||||
|
||||
eventRoleWidget->device = "";
|
||||
|
||||
|
@ -1292,7 +1277,7 @@ void MainWindow::removeSink(uint32_t index) {
|
|||
if (!sinkWidgets.count(index))
|
||||
return;
|
||||
|
||||
delete sinkWidgets[index];
|
||||
sinksVBox->remove(*sinkWidgets[index]);
|
||||
sinkWidgets.erase(index);
|
||||
updateDeviceVisibility();
|
||||
}
|
||||
|
@ -1301,7 +1286,7 @@ void MainWindow::removeSource(uint32_t index) {
|
|||
if (!sourceWidgets.count(index))
|
||||
return;
|
||||
|
||||
delete sourceWidgets[index];
|
||||
sourcesVBox->remove(*sourceWidgets[index]);
|
||||
sourceWidgets.erase(index);
|
||||
updateDeviceVisibility();
|
||||
}
|
||||
|
@ -1310,7 +1295,7 @@ void MainWindow::removeSinkInput(uint32_t index) {
|
|||
if (!sinkInputWidgets.count(index))
|
||||
return;
|
||||
|
||||
delete sinkInputWidgets[index];
|
||||
streamsVBox->remove(*sinkInputWidgets[index]);
|
||||
sinkInputWidgets.erase(index);
|
||||
updateDeviceVisibility();
|
||||
}
|
||||
|
@ -1319,7 +1304,7 @@ void MainWindow::removeSourceOutput(uint32_t index) {
|
|||
if (!sourceOutputWidgets.count(index))
|
||||
return;
|
||||
|
||||
delete sourceOutputWidgets[index];
|
||||
recsVBox->remove(*sourceOutputWidgets[index]);
|
||||
sourceOutputWidgets.erase(index);
|
||||
updateDeviceVisibility();
|
||||
}
|
||||
|
|
|
@ -29,6 +29,8 @@ class MainWindow;
|
|||
# include <pulse/ext-device-restore.h>
|
||||
#endif
|
||||
|
||||
#include <canberra.h>
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
class CardWidget;
|
||||
|
@ -76,7 +78,7 @@ public:
|
|||
void setConnectingMessage(const char *string = NULL);
|
||||
|
||||
Gtk::Notebook *notebook;
|
||||
Gtk::VBox *streamsVBox, *recsVBox, *sinksVBox, *sourcesVBox, *cardsVBox;
|
||||
Gtk::Box *streamsVBox, *recsVBox, *sinksVBox, *sourcesVBox, *cardsVBox;
|
||||
Gtk::Label *noStreamsLabel, *noRecsLabel, *noSinksLabel, *noSourcesLabel, *noCardsLabel, *connectingLabel;
|
||||
Gtk::ComboBox *sinkInputTypeComboBox, *sourceOutputTypeComboBox, *sinkTypeComboBox, *sourceTypeComboBox;
|
||||
Gtk::CheckButton *showVolumeMetersCheckButton;
|
||||
|
@ -116,9 +118,11 @@ public:
|
|||
|
||||
bool canRenameDevices;
|
||||
|
||||
ca_context *canberraContext;
|
||||
|
||||
protected:
|
||||
virtual void on_realize();
|
||||
virtual bool on_key_press_event(GdkEventKey* event);
|
||||
virtual bool on_key_press_event(guint keyval, guint keycode, Gdk::ModifierType state);
|
||||
|
||||
private:
|
||||
gboolean m_connected;
|
||||
|
|
|
@ -33,8 +33,8 @@ executable('pavucontrol',
|
|||
install_data('pavucontrol.glade')
|
||||
|
||||
desktop_file = i18n.merge_file(
|
||||
input : 'pavucontrol.desktop.in',
|
||||
output : 'pavucontrol.desktop',
|
||||
input : 'org.pulseaudio.pavucontrol.desktop.in',
|
||||
output : 'org.pulseaudio.pavucontrol.desktop',
|
||||
po_dir : po_dir,
|
||||
type : 'desktop',
|
||||
install : true,
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
/*** MinimalStreamWidget ***/
|
||||
MinimalStreamWidget::MinimalStreamWidget(BaseObjectType* cobject) :
|
||||
Gtk::VBox(cobject),
|
||||
Gtk::Box(cobject),
|
||||
channelsVBox(NULL),
|
||||
nameLabel(NULL),
|
||||
boldNameLabel(NULL),
|
||||
|
@ -53,7 +53,7 @@ void MinimalStreamWidget::init() {
|
|||
* in the constructor. */
|
||||
|
||||
peakProgressBar.set_size_request(-1, 10);
|
||||
channelsVBox->pack_end(peakProgressBar, false, false);
|
||||
channelsVBox->append(peakProgressBar);
|
||||
|
||||
/* XXX: Why is the peak meter hidden by default? Maybe the idea is that if
|
||||
* setting up the monitoring stream fails for whatever reason, then we
|
||||
|
@ -64,20 +64,19 @@ void MinimalStreamWidget::init() {
|
|||
#define DECAY_STEP (1.0 / PEAKS_RATE)
|
||||
|
||||
void MinimalStreamWidget::updatePeak(double v) {
|
||||
|
||||
if (lastPeak >= DECAY_STEP)
|
||||
if (v < lastPeak - DECAY_STEP)
|
||||
v = lastPeak - DECAY_STEP;
|
||||
|
||||
lastPeak = v;
|
||||
|
||||
if (v >= 0) {
|
||||
peakProgressBar.set_sensitive(TRUE);
|
||||
peakProgressBar.set_fraction(v);
|
||||
} else {
|
||||
peakProgressBar.set_sensitive(FALSE);
|
||||
peakProgressBar.set_fraction(0);
|
||||
}
|
||||
if (v >= 0) {
|
||||
peakProgressBar.set_sensitive(TRUE);
|
||||
peakProgressBar.set_fraction(v);
|
||||
} else {
|
||||
peakProgressBar.set_sensitive(FALSE);
|
||||
peakProgressBar.set_fraction(0);
|
||||
}
|
||||
|
||||
enableVolumeMeter();
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
#define PEAKS_RATE 144
|
||||
|
||||
class MinimalStreamWidget : public Gtk::VBox {
|
||||
class MinimalStreamWidget : public Gtk::Box {
|
||||
public:
|
||||
MinimalStreamWidget(BaseObjectType* cobject);
|
||||
virtual ~MinimalStreamWidget();
|
||||
|
@ -33,7 +33,7 @@ public:
|
|||
/* Subclass constructors are expected to initialize these variables.
|
||||
* MinimalStreamWidget can't initialize these, because the glade object
|
||||
* id's depend on the subclass type. */
|
||||
Gtk::VBox *channelsVBox;
|
||||
Gtk::Box *channelsVBox;
|
||||
Gtk::Label *nameLabel, *boldNameLabel;
|
||||
Gtk::Image *iconImage;
|
||||
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
|
||||
#include "i18n.h"
|
||||
|
||||
#include <canberra-gtk.h>
|
||||
|
||||
#include "pavuapplication.h"
|
||||
#include "pavucontrol.h"
|
||||
#include "mainwindow.h"
|
||||
|
@ -39,7 +37,7 @@ PavuApplication::get_instance()
|
|||
}
|
||||
|
||||
PavuApplication::PavuApplication() :
|
||||
Gtk::Application("org.pulseaudio.pavucontrol", Gio::ApplicationFlags::APPLICATION_HANDLES_COMMAND_LINE),
|
||||
Gtk::Application("org.pulseaudio.pavucontrol", Gio::Application::Flags::HANDLES_COMMAND_LINE),
|
||||
mainWindow(NULL),
|
||||
retry(false),
|
||||
maximize(false),
|
||||
|
@ -59,9 +57,8 @@ MainWindow* PavuApplication::create_window()
|
|||
|
||||
MainWindow* pavucontrol_window = pavucontrol_get_window(m, maximize, retry, tab);
|
||||
|
||||
pavucontrol_window->signal_hide().connect(
|
||||
sigc::bind<Gtk::Window*>(sigc::mem_fun(*this,
|
||||
&PavuApplication::on_hide_window), pavucontrol_window));
|
||||
pavucontrol_window->signal_close_request().connect(sigc::mem_fun(*this,
|
||||
&PavuApplication::on_close_window), true);
|
||||
|
||||
return pavucontrol_window;
|
||||
}
|
||||
|
@ -94,9 +91,9 @@ void PavuApplication::on_activate()
|
|||
* exiting : when the last registered window of Gtk::Application is closed,
|
||||
* the application's run() function returns.
|
||||
*/
|
||||
void PavuApplication::on_hide_window(Gtk::Window* window)
|
||||
bool PavuApplication::on_close_window()
|
||||
{
|
||||
delete window;
|
||||
delete mainWindow;
|
||||
mainWindow = NULL;
|
||||
|
||||
if (get_context()) {
|
||||
|
@ -104,6 +101,7 @@ void PavuApplication::on_hide_window(Gtk::Window* window)
|
|||
}
|
||||
pa_glib_mainloop_free(m);
|
||||
m = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T_ArgType>
|
||||
|
@ -155,23 +153,23 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
/* Add command-line options */
|
||||
globalInstance.add_main_option_entry(
|
||||
Gio::Application::OptionType::OPTION_TYPE_INT,
|
||||
Gio::Application::OptionType::INT,
|
||||
"tab", 't',
|
||||
_("Select a specific tab on load."),
|
||||
_("number"));
|
||||
|
||||
globalInstance.add_main_option_entry(
|
||||
Gio::Application::OptionType::OPTION_TYPE_BOOL,
|
||||
Gio::Application::OptionType::BOOL,
|
||||
"retry", 'r',
|
||||
_("Retry forever if pa quits (every 5 seconds)."));
|
||||
|
||||
globalInstance.add_main_option_entry(
|
||||
Gio::Application::OptionType::OPTION_TYPE_BOOL,
|
||||
Gio::Application::OptionType::BOOL,
|
||||
"maximize", 'm',
|
||||
_("Maximize the window."));
|
||||
|
||||
globalInstance.add_main_option_entry(
|
||||
Gio::Application::OptionType::OPTION_TYPE_BOOL,
|
||||
Gio::Application::OptionType::BOOL,
|
||||
"version", 'v',
|
||||
_("Show version."));
|
||||
|
||||
|
|
|
@ -45,7 +45,8 @@ protected:
|
|||
|
||||
private:
|
||||
MainWindow* create_window();
|
||||
void on_hide_window(Gtk::Window* window);
|
||||
void on_hide_window();
|
||||
bool on_close_window();
|
||||
|
||||
pa_glib_mainloop *m;
|
||||
};
|
||||
|
|
|
@ -29,8 +29,6 @@
|
|||
#include <json-glib/json-glib.h>
|
||||
#endif
|
||||
|
||||
#include <canberra-gtk.h>
|
||||
|
||||
#include "pavucontrol.h"
|
||||
#include "i18n.h"
|
||||
#include "minimalstreamwidget.h"
|
||||
|
@ -58,15 +56,27 @@ static int tab_number = 0;
|
|||
static bool retry = false;
|
||||
static int reconnect_timeout = 1;
|
||||
|
||||
void show_error(const char *txt) {
|
||||
void show_error_finish (const Glib::RefPtr<Gio::AsyncResult>& result) {
|
||||
PavuApplication::get_instance().quit();
|
||||
}
|
||||
|
||||
void show_error(Gtk::Widget* widget, const char *txt) {
|
||||
Gtk::Root *root = widget->get_root();
|
||||
char buf[256];
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s: %s", txt, pa_strerror(pa_context_errno(context)));
|
||||
|
||||
Gtk::MessageDialog dialog(buf, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
|
||||
dialog.run();
|
||||
|
||||
PavuApplication::get_instance().quit();
|
||||
auto dialog = Gtk::AlertDialog::create(buf);
|
||||
dialog->set_modal(true);
|
||||
if (GTK_IS_WINDOW(root->gobj())) {
|
||||
GtkWindow* w = (GtkWindow*) root->gobj();
|
||||
Gtk::Window* window = Glib::wrap(w);
|
||||
window->present();
|
||||
dialog->choose(*window, sigc::ptr_fun(show_error_finish));
|
||||
}
|
||||
else {
|
||||
dialog->choose(sigc::ptr_fun(show_error_finish));
|
||||
}
|
||||
}
|
||||
|
||||
static void dec_outstanding(MainWindow *w) {
|
||||
|
@ -74,7 +84,7 @@ static void dec_outstanding(MainWindow *w) {
|
|||
return;
|
||||
|
||||
if (--n_outstanding <= 0) {
|
||||
w->get_window()->set_cursor();
|
||||
w->set_cursor(Gdk::Cursor::create("default"));;
|
||||
w->setConnectionState(true);
|
||||
}
|
||||
}
|
||||
|
@ -355,7 +365,7 @@ void card_cb(pa_context *c, const pa_card_info *i, int eol, void *userdata) {
|
|||
if (pa_context_errno(context) == PA_ERR_NOENTITY)
|
||||
return;
|
||||
|
||||
show_error(_("Card callback failure"));
|
||||
show_error(w, _("Card callback failure"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -383,7 +393,7 @@ void sink_cb(pa_context *c, const pa_sink_info *i, int eol, void *userdata) {
|
|||
if (pa_context_errno(context) == PA_ERR_NOENTITY)
|
||||
return;
|
||||
|
||||
show_error(_("Sink callback failure"));
|
||||
show_error(w, _("Sink callback failure"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -407,7 +417,7 @@ void source_cb(pa_context *, const pa_source_info *i, int eol, void *userdata) {
|
|||
if (pa_context_errno(context) == PA_ERR_NOENTITY)
|
||||
return;
|
||||
|
||||
show_error(_("Source callback failure"));
|
||||
show_error(w, _("Source callback failure"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -426,7 +436,7 @@ void sink_input_cb(pa_context *, const pa_sink_input_info *i, int eol, void *use
|
|||
if (pa_context_errno(context) == PA_ERR_NOENTITY)
|
||||
return;
|
||||
|
||||
show_error(_("Sink input callback failure"));
|
||||
show_error(w, _("Sink input callback failure"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -445,7 +455,7 @@ void source_output_cb(pa_context *, const pa_source_output_info *i, int eol, voi
|
|||
if (pa_context_errno(context) == PA_ERR_NOENTITY)
|
||||
return;
|
||||
|
||||
show_error(_("Source output callback failure"));
|
||||
show_error(w, _("Source output callback failure"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -475,7 +485,7 @@ void client_cb(pa_context *, const pa_client_info *i, int eol, void *userdata) {
|
|||
if (pa_context_errno(context) == PA_ERR_NOENTITY)
|
||||
return;
|
||||
|
||||
show_error(_("Client callback failure"));
|
||||
show_error(w, _("Client callback failure"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -491,7 +501,7 @@ void server_info_cb(pa_context *, const pa_server_info *i, void *userdata) {
|
|||
MainWindow *w = static_cast<MainWindow*>(userdata);
|
||||
|
||||
if (!i) {
|
||||
show_error(_("Server info callback failure"));
|
||||
show_error(w, _("Server info callback failure"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -527,7 +537,7 @@ static void ext_stream_restore_subscribe_cb(pa_context *c, void *userdata) {
|
|||
pa_operation *o;
|
||||
|
||||
if (!(o = pa_ext_stream_restore_read(c, ext_stream_restore_read_cb, w))) {
|
||||
show_error(_("pa_ext_stream_restore_read() failed"));
|
||||
show_error(w, _("pa_ext_stream_restore_read() failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -566,7 +576,7 @@ static void ext_device_restore_subscribe_cb(pa_context *c, pa_device_type_t type
|
|||
return;
|
||||
|
||||
if (!(o = pa_ext_device_restore_read_formats(c, type, idx, ext_device_restore_read_cb, w))) {
|
||||
show_error(_("pa_ext_device_restore_read_sink_formats() failed"));
|
||||
show_error(w, _("pa_ext_device_restore_read_sink_formats() failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -603,7 +613,7 @@ static void ext_device_manager_subscribe_cb(pa_context *c, void *userdata) {
|
|||
pa_operation *o;
|
||||
|
||||
if (!(o = pa_ext_device_manager_read(c, ext_device_manager_read_cb, w))) {
|
||||
show_error(_("pa_ext_device_manager_read() failed"));
|
||||
show_error(w, _("pa_ext_device_manager_read() failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -620,7 +630,7 @@ void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t index,
|
|||
else {
|
||||
pa_operation *o;
|
||||
if (!(o = pa_context_get_sink_info_by_index(c, index, sink_cb, w))) {
|
||||
show_error(_("pa_context_get_sink_info_by_index() failed"));
|
||||
show_error(w, _("pa_context_get_sink_info_by_index() failed"));
|
||||
return;
|
||||
}
|
||||
pa_operation_unref(o);
|
||||
|
@ -633,7 +643,7 @@ void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t index,
|
|||
else {
|
||||
pa_operation *o;
|
||||
if (!(o = pa_context_get_source_info_by_index(c, index, source_cb, w))) {
|
||||
show_error(_("pa_context_get_source_info_by_index() failed"));
|
||||
show_error(w, _("pa_context_get_source_info_by_index() failed"));
|
||||
return;
|
||||
}
|
||||
pa_operation_unref(o);
|
||||
|
@ -646,7 +656,7 @@ void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t index,
|
|||
else {
|
||||
pa_operation *o;
|
||||
if (!(o = pa_context_get_sink_input_info(c, index, sink_input_cb, w))) {
|
||||
show_error(_("pa_context_get_sink_input_info() failed"));
|
||||
show_error(w, _("pa_context_get_sink_input_info() failed"));
|
||||
return;
|
||||
}
|
||||
pa_operation_unref(o);
|
||||
|
@ -659,7 +669,7 @@ void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t index,
|
|||
else {
|
||||
pa_operation *o;
|
||||
if (!(o = pa_context_get_source_output_info(c, index, source_output_cb, w))) {
|
||||
show_error(_("pa_context_get_sink_input_info() failed"));
|
||||
show_error(w, _("pa_context_get_sink_input_info() failed"));
|
||||
return;
|
||||
}
|
||||
pa_operation_unref(o);
|
||||
|
@ -672,7 +682,7 @@ void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t index,
|
|||
else {
|
||||
pa_operation *o;
|
||||
if (!(o = pa_context_get_client_info(c, index, client_cb, w))) {
|
||||
show_error(_("pa_context_get_client_info() failed"));
|
||||
show_error(w, _("pa_context_get_client_info() failed"));
|
||||
return;
|
||||
}
|
||||
pa_operation_unref(o);
|
||||
|
@ -682,7 +692,7 @@ void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t index,
|
|||
case PA_SUBSCRIPTION_EVENT_SERVER: {
|
||||
pa_operation *o;
|
||||
if (!(o = pa_context_get_server_info(c, server_info_cb, w))) {
|
||||
show_error(_("pa_context_get_server_info() failed"));
|
||||
show_error(w, _("pa_context_get_server_info() failed"));
|
||||
return;
|
||||
}
|
||||
pa_operation_unref(o);
|
||||
|
@ -695,7 +705,7 @@ void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t index,
|
|||
else {
|
||||
pa_operation *o;
|
||||
if (!(o = pa_context_get_card_info_by_index(c, index, card_cb, w))) {
|
||||
show_error(_("pa_context_get_card_info_by_index() failed"));
|
||||
show_error(w, _("pa_context_get_card_info_by_index() failed"));
|
||||
return;
|
||||
}
|
||||
pa_operation_unref(o);
|
||||
|
@ -738,7 +748,7 @@ void context_state_callback(pa_context *c, void *userdata) {
|
|||
PA_SUBSCRIPTION_MASK_CLIENT|
|
||||
PA_SUBSCRIPTION_MASK_SERVER|
|
||||
PA_SUBSCRIPTION_MASK_CARD), NULL, NULL))) {
|
||||
show_error(_("pa_context_subscribe() failed"));
|
||||
show_error(w, _("pa_context_subscribe() failed"));
|
||||
return;
|
||||
}
|
||||
pa_operation_unref(o);
|
||||
|
@ -747,49 +757,49 @@ void context_state_callback(pa_context *c, void *userdata) {
|
|||
n_outstanding = 0;
|
||||
|
||||
if (!(o = pa_context_get_server_info(c, server_info_cb, w))) {
|
||||
show_error(_("pa_context_get_server_info() failed"));
|
||||
show_error(w, _("pa_context_get_server_info() failed"));
|
||||
return;
|
||||
}
|
||||
pa_operation_unref(o);
|
||||
n_outstanding++;
|
||||
|
||||
if (!(o = pa_context_get_client_info_list(c, client_cb, w))) {
|
||||
show_error(_("pa_context_client_info_list() failed"));
|
||||
show_error(w, _("pa_context_client_info_list() failed"));
|
||||
return;
|
||||
}
|
||||
pa_operation_unref(o);
|
||||
n_outstanding++;
|
||||
|
||||
if (!(o = pa_context_get_card_info_list(c, card_cb, w))) {
|
||||
show_error(_("pa_context_get_card_info_list() failed"));
|
||||
show_error(w, _("pa_context_get_card_info_list() failed"));
|
||||
return;
|
||||
}
|
||||
pa_operation_unref(o);
|
||||
n_outstanding++;
|
||||
|
||||
if (!(o = pa_context_get_sink_info_list(c, sink_cb, w))) {
|
||||
show_error(_("pa_context_get_sink_info_list() failed"));
|
||||
show_error(w, _("pa_context_get_sink_info_list() failed"));
|
||||
return;
|
||||
}
|
||||
pa_operation_unref(o);
|
||||
n_outstanding++;
|
||||
|
||||
if (!(o = pa_context_get_source_info_list(c, source_cb, w))) {
|
||||
show_error(_("pa_context_get_source_info_list() failed"));
|
||||
show_error(w, _("pa_context_get_source_info_list() failed"));
|
||||
return;
|
||||
}
|
||||
pa_operation_unref(o);
|
||||
n_outstanding++;
|
||||
|
||||
if (!(o = pa_context_get_sink_input_info_list(c, sink_input_cb, w))) {
|
||||
show_error(_("pa_context_get_sink_input_info_list() failed"));
|
||||
show_error(w, _("pa_context_get_sink_input_info_list() failed"));
|
||||
return;
|
||||
}
|
||||
pa_operation_unref(o);
|
||||
n_outstanding++;
|
||||
|
||||
if (!(o = pa_context_get_source_output_info_list(c, source_output_cb, w))) {
|
||||
show_error(_("pa_context_get_source_output_info_list() failed"));
|
||||
show_error(w, _("pa_context_get_source_output_info_list() failed"));
|
||||
return;
|
||||
}
|
||||
pa_operation_unref(o);
|
||||
|
@ -916,8 +926,6 @@ MainWindow* pavucontrol_get_window(pa_glib_mainloop *m, bool maximize, bool _ret
|
|||
tab_number = _tab_number;
|
||||
retry = _retry;
|
||||
|
||||
ca_context_set_driver(ca_gtk_context_get(), "pulse");
|
||||
|
||||
mainWindow = MainWindow::create(maximize);
|
||||
|
||||
api = pa_glib_mainloop_get_api(m);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -29,6 +29,7 @@
|
|||
#include <libintl.h>
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <gtkmm/buildable.h>
|
||||
|
||||
#include <pulse/pulseaudio.h>
|
||||
#include <pulse/glib-mainloop.h>
|
||||
|
@ -74,7 +75,7 @@ enum SourceType {
|
|||
#include "mainwindow.h"
|
||||
|
||||
pa_context* get_context(void);
|
||||
void show_error(const char *txt);
|
||||
void show_error(Gtk::Widget *w, const char *txt);
|
||||
|
||||
MainWindow* pavucontrol_get_window(pa_glib_mainloop *m, bool maximize, bool retry, int tab_number);
|
||||
|
||||
|
|
|
@ -39,15 +39,11 @@ RoleWidget::RoleWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>
|
|||
RoleWidget* RoleWidget::create() {
|
||||
RoleWidget* w;
|
||||
Glib::RefPtr<Gtk::Builder> x = Gtk::Builder::create_from_file(GLADE_FILE, "streamWidget");
|
||||
x->get_widget_derived("streamWidget", w);
|
||||
w = Gtk::Builder::get_widget_derived<RoleWidget>(x, "streamWidget");
|
||||
w->reference();
|
||||
return w;
|
||||
}
|
||||
|
||||
bool RoleWidget::onContextTriggerEvent(GdkEventButton*) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void RoleWidget::onMuteToggleButton() {
|
||||
StreamWidget::onMuteToggleButton();
|
||||
|
||||
|
@ -69,7 +65,7 @@ void RoleWidget::executeVolumeUpdate() {
|
|||
|
||||
pa_operation* o;
|
||||
if (!(o = pa_ext_stream_restore_write(get_context(), PA_UPDATE_REPLACE, &info, 1, TRUE, NULL, NULL))) {
|
||||
show_error(_("pa_ext_stream_restore_write() failed"));
|
||||
show_error(this, _("pa_ext_stream_restore_write() failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@ public:
|
|||
|
||||
virtual void onMuteToggleButton();
|
||||
virtual void executeVolumeUpdate();
|
||||
virtual bool onContextTriggerEvent(GdkEventButton*);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -35,13 +35,13 @@ SinkInputWidget::SinkInputWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk
|
|||
directionLabel->set_label(txt = g_markup_printf_escaped("<i>%s</i>", _("on")));
|
||||
g_free(txt);
|
||||
|
||||
terminate.set_label(_("Terminate Playback"));
|
||||
addKillMenu(_("Terminate Playback"));
|
||||
}
|
||||
|
||||
SinkInputWidget* SinkInputWidget::create(MainWindow* mainWindow) {
|
||||
SinkInputWidget* w;
|
||||
Glib::RefPtr<Gtk::Builder> x = Gtk::Builder::create_from_file(GLADE_FILE, "streamWidget");
|
||||
x->get_widget_derived("streamWidget", w);
|
||||
w = Gtk::Builder::get_widget_derived<SinkInputWidget>(x, "streamWidget");
|
||||
w->init(mainWindow);
|
||||
w->reference();
|
||||
|
||||
|
@ -84,7 +84,7 @@ void SinkInputWidget::executeVolumeUpdate() {
|
|||
pa_operation* o;
|
||||
|
||||
if (!(o = pa_context_set_sink_input_volume(get_context(), index, &volume, NULL, NULL))) {
|
||||
show_error(_("pa_context_set_sink_input_volume() failed"));
|
||||
show_error(this, _("pa_context_set_sink_input_volume() failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -99,17 +99,17 @@ void SinkInputWidget::onMuteToggleButton() {
|
|||
|
||||
pa_operation* o;
|
||||
if (!(o = pa_context_set_sink_input_mute(get_context(), index, muteToggleButton->get_active(), NULL, NULL))) {
|
||||
show_error(_("pa_context_set_sink_input_mute() failed"));
|
||||
show_error(this, _("pa_context_set_sink_input_mute() failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
pa_operation_unref(o);
|
||||
}
|
||||
|
||||
void SinkInputWidget::onKill() {
|
||||
void SinkInputWidget::onKill(const Glib::VariantBase& parameter) {
|
||||
pa_operation* o;
|
||||
if (!(o = pa_context_kill_sink_input(get_context(), index, NULL, NULL))) {
|
||||
show_error(_("pa_context_kill_sink_input() failed"));
|
||||
show_error(this, _("pa_context_kill_sink_input() failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ public:
|
|||
void updateDeviceComboBox();
|
||||
virtual void executeVolumeUpdate();
|
||||
virtual void onMuteToggleButton();
|
||||
virtual void onKill();
|
||||
virtual void onKill(const Glib::VariantBase& parameter);
|
||||
virtual void onDeviceComboBoxChanged();
|
||||
|
||||
private:
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
#include "sinkwidget.h"
|
||||
|
||||
#include <canberra-gtk.h>
|
||||
#include <canberra.h>
|
||||
#if HAVE_EXT_DEVICE_RESTORE_API
|
||||
# include <pulse/format.h>
|
||||
# include <pulse/ext-device-restore.h>
|
||||
|
@ -37,35 +37,35 @@ SinkWidget::SinkWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>
|
|||
#if HAVE_EXT_DEVICE_RESTORE_API
|
||||
uint8_t i = 0;
|
||||
|
||||
x->get_widget("encodingSelect", encodingSelect);
|
||||
encodingSelect = x->get_widget<Gtk::Grid>("encodingSelect");
|
||||
|
||||
encodings[i].encoding = PA_ENCODING_PCM;
|
||||
x->get_widget("encodingFormatPCM", encodings[i].widget);
|
||||
encodings[i].widget = x->get_widget<Gtk::CheckButton>("encodingFormatPCM");
|
||||
encodings[i].widget->signal_toggled().connect(sigc::mem_fun(*this, &SinkWidget::onEncodingsChange));
|
||||
|
||||
++i;
|
||||
encodings[i].encoding = PA_ENCODING_AC3_IEC61937;
|
||||
x->get_widget("encodingFormatAC3", encodings[i].widget);
|
||||
encodings[i].widget = x->get_widget<Gtk::CheckButton>("encodingFormatAC3");
|
||||
encodings[i].widget->signal_toggled().connect(sigc::mem_fun(*this, &SinkWidget::onEncodingsChange));
|
||||
|
||||
++i;
|
||||
encodings[i].encoding = PA_ENCODING_EAC3_IEC61937;
|
||||
x->get_widget("encodingFormatEAC3", encodings[i].widget);
|
||||
encodings[i].widget = x->get_widget<Gtk::CheckButton>("encodingFormatEAC3");
|
||||
encodings[i].widget->signal_toggled().connect(sigc::mem_fun(*this, &SinkWidget::onEncodingsChange));
|
||||
|
||||
++i;
|
||||
encodings[i].encoding = PA_ENCODING_MPEG_IEC61937;
|
||||
x->get_widget("encodingFormatMPEG", encodings[i].widget);
|
||||
encodings[i].widget = x->get_widget<Gtk::CheckButton>("encodingFormatMPEG");
|
||||
encodings[i].widget->signal_toggled().connect(sigc::mem_fun(*this, &SinkWidget::onEncodingsChange));
|
||||
|
||||
++i;
|
||||
encodings[i].encoding = PA_ENCODING_DTS_IEC61937;
|
||||
x->get_widget("encodingFormatDTS", encodings[i].widget);
|
||||
encodings[i].widget = x->get_widget<Gtk::CheckButton>("encodingFormatDTS");
|
||||
encodings[i].widget->signal_toggled().connect(sigc::mem_fun(*this, &SinkWidget::onEncodingsChange));
|
||||
|
||||
++i;
|
||||
encodings[i].encoding = PA_ENCODING_INVALID;
|
||||
x->get_widget("encodingFormatAAC", encodings[i].widget);
|
||||
encodings[i].widget = x->get_widget<Gtk::CheckButton>("encodingFormatAAC");
|
||||
encodings[i].widget->set_sensitive(false);
|
||||
#ifdef PA_ENCODING_MPEG2_AAC_IEC61937
|
||||
if (pa_context_get_server_protocol_version(get_context()) >= 28) {
|
||||
|
@ -76,7 +76,7 @@ SinkWidget::SinkWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>
|
|||
#endif
|
||||
++i;
|
||||
encodings[i].encoding = PA_ENCODING_INVALID;
|
||||
x->get_widget("encodingFormatTRUEHD", encodings[i].widget);
|
||||
encodings[i].widget = x->get_widget<Gtk::CheckButton>("encodingFormatTRUEHD");
|
||||
encodings[i].widget->set_sensitive(false);
|
||||
#ifdef PA_ENCODING_TRUEHD_IEC61937
|
||||
if (pa_context_get_server_protocol_version(get_context()) >= 33) {
|
||||
|
@ -87,7 +87,7 @@ SinkWidget::SinkWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>
|
|||
#endif
|
||||
++i;
|
||||
encodings[i].encoding = PA_ENCODING_INVALID;
|
||||
x->get_widget("encodingFormatDTSHD", encodings[i].widget);
|
||||
encodings[i].widget = x->get_widget<Gtk::CheckButton>("encodingFormatDTSHD");
|
||||
encodings[i].widget->set_sensitive(false);
|
||||
#ifdef PA_ENCODING_DTSHD_IEC61937
|
||||
if (pa_context_get_server_protocol_version(get_context()) >= 33) {
|
||||
|
@ -102,7 +102,7 @@ SinkWidget::SinkWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>
|
|||
SinkWidget* SinkWidget::create(MainWindow* mainWindow) {
|
||||
SinkWidget* w;
|
||||
Glib::RefPtr<Gtk::Builder> x = Gtk::Builder::create_from_file(GLADE_FILE, "deviceWidget");
|
||||
x->get_widget_derived("deviceWidget", w);
|
||||
w = Gtk::Builder::get_widget_derived<SinkWidget>(x, "deviceWidget");
|
||||
w->init(mainWindow, "sink");
|
||||
w->reference();
|
||||
return w;
|
||||
|
@ -114,28 +114,29 @@ void SinkWidget::executeVolumeUpdate() {
|
|||
int playing = 0;
|
||||
|
||||
if (!(o = pa_context_set_sink_volume_by_index(get_context(), index, &volume, NULL, NULL))) {
|
||||
show_error(_("pa_context_set_sink_volume_by_index() failed"));
|
||||
show_error(this, _("pa_context_set_sink_volume_by_index() failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
pa_operation_unref(o);
|
||||
|
||||
ca_context_playing(ca_gtk_context_get(), 2, &playing);
|
||||
snprintf(dev, sizeof(dev), "%lu", (unsigned long) index);
|
||||
|
||||
ca_context_playing(mpMainWindow->canberraContext, 2, &playing);
|
||||
if (playing)
|
||||
return;
|
||||
|
||||
snprintf(dev, sizeof(dev), "%lu", (unsigned long) index);
|
||||
ca_context_change_device(ca_gtk_context_get(), dev);
|
||||
ca_context_change_device(mpMainWindow->canberraContext, dev);
|
||||
|
||||
ca_gtk_play_for_widget(GTK_WIDGET(gobj()),
|
||||
2,
|
||||
CA_PROP_EVENT_DESCRIPTION, _("Volume Control Feedback Sound"),
|
||||
CA_PROP_EVENT_ID, "audio-volume-change",
|
||||
CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
|
||||
CA_PROP_CANBERRA_ENABLE, "1",
|
||||
NULL);
|
||||
ca_context_play(mpMainWindow->canberraContext,
|
||||
2,
|
||||
CA_PROP_EVENT_DESCRIPTION, _("Volume Control Feedback Sound"),
|
||||
CA_PROP_EVENT_ID, "audio-volume-change",
|
||||
CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
|
||||
CA_PROP_CANBERRA_ENABLE, "1",
|
||||
NULL);
|
||||
|
||||
ca_context_change_device(ca_gtk_context_get(), NULL);
|
||||
ca_context_change_device(mpMainWindow->canberraContext, NULL);
|
||||
}
|
||||
|
||||
void SinkWidget::onMuteToggleButton() {
|
||||
|
@ -146,7 +147,7 @@ void SinkWidget::onMuteToggleButton() {
|
|||
|
||||
pa_operation* o;
|
||||
if (!(o = pa_context_set_sink_mute_by_index(get_context(), index, muteToggleButton->get_active(), NULL, NULL))) {
|
||||
show_error(_("pa_context_set_sink_mute_by_index() failed"));
|
||||
show_error(this, _("pa_context_set_sink_mute_by_index() failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -160,7 +161,7 @@ void SinkWidget::onDefaultToggleButton() {
|
|||
return;
|
||||
|
||||
if (!(o = pa_context_set_default_sink(get_context(), name.c_str(), NULL, NULL))) {
|
||||
show_error(_("pa_context_set_default_sink() failed"));
|
||||
show_error(this, _("pa_context_set_default_sink() failed"));
|
||||
return;
|
||||
}
|
||||
pa_operation_unref(o);
|
||||
|
@ -180,7 +181,7 @@ void SinkWidget::onPortChange() {
|
|||
Glib::ustring port = row[portModel.name];
|
||||
|
||||
if (!(o = pa_context_set_sink_port_by_index(get_context(), index, port.c_str(), NULL, NULL))) {
|
||||
show_error(_("pa_context_set_sink_port_by_index() failed"));
|
||||
show_error(this, _("pa_context_set_sink_port_by_index() failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -222,7 +223,7 @@ void SinkWidget::onEncodingsChange() {
|
|||
}
|
||||
|
||||
if (!(o = pa_ext_device_restore_save_formats(get_context(), PA_DEVICE_TYPE_SINK, index, n_formats, formats, NULL, NULL))) {
|
||||
show_error(_("pa_ext_device_restore_save_sink_formats() failed"));
|
||||
show_error(this, _("pa_ext_device_restore_save_sink_formats() failed"));
|
||||
free(formats);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ SourceOutputWidget::SourceOutputWidget(BaseObjectType* cobject, const Glib::RefP
|
|||
directionLabel->set_label(txt = g_markup_printf_escaped("<i>%s</i>", _("from")));
|
||||
g_free(txt);
|
||||
|
||||
terminate.set_label(_("Terminate Recording"));
|
||||
addKillMenu(_("Terminate Recording"));
|
||||
|
||||
#if !HAVE_SOURCE_OUTPUT_VOLUMES
|
||||
/* Source Outputs do not have volume controls in versions of PA < 1.0 */
|
||||
|
@ -47,7 +47,7 @@ SourceOutputWidget::SourceOutputWidget(BaseObjectType* cobject, const Glib::RefP
|
|||
SourceOutputWidget* SourceOutputWidget::create(MainWindow* mainWindow) {
|
||||
SourceOutputWidget* w;
|
||||
Glib::RefPtr<Gtk::Builder> x = Gtk::Builder::create_from_file(GLADE_FILE, "streamWidget");
|
||||
x->get_widget_derived("streamWidget", w);
|
||||
w = Gtk::Builder::get_widget_derived<SourceOutputWidget>(x, "streamWidget");
|
||||
w->init(mainWindow);
|
||||
w->reference();
|
||||
return w;
|
||||
|
@ -90,7 +90,7 @@ void SourceOutputWidget::executeVolumeUpdate() {
|
|||
pa_operation* o;
|
||||
|
||||
if (!(o = pa_context_set_source_output_volume(get_context(), index, &volume, NULL, NULL))) {
|
||||
show_error(_("pa_context_set_source_output_volume() failed"));
|
||||
show_error(this, _("pa_context_set_source_output_volume() failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -105,7 +105,7 @@ void SourceOutputWidget::onMuteToggleButton() {
|
|||
|
||||
pa_operation* o;
|
||||
if (!(o = pa_context_set_source_output_mute(get_context(), index, muteToggleButton->get_active(), NULL, NULL))) {
|
||||
show_error(_("pa_context_set_source_output_mute() failed"));
|
||||
show_error(this, _("pa_context_set_source_output_mute() failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -113,10 +113,10 @@ void SourceOutputWidget::onMuteToggleButton() {
|
|||
}
|
||||
#endif
|
||||
|
||||
void SourceOutputWidget::onKill() {
|
||||
void SourceOutputWidget::onKill(const Glib::VariantBase& parameter) {
|
||||
pa_operation* o;
|
||||
if (!(o = pa_context_kill_source_output(get_context(), index, NULL, NULL))) {
|
||||
show_error(_("pa_context_kill_source_output() failed"));
|
||||
show_error(this, _("pa_context_kill_source_output() failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ public:
|
|||
virtual void executeVolumeUpdate();
|
||||
virtual void onMuteToggleButton();
|
||||
#endif
|
||||
virtual void onKill();
|
||||
virtual void onKill(const Glib::VariantBase& parameter);
|
||||
virtual void onDeviceComboBoxChanged();
|
||||
|
||||
private:
|
||||
|
|
|
@ -33,7 +33,7 @@ SourceWidget::SourceWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Buil
|
|||
SourceWidget* SourceWidget::create(MainWindow* mainWindow) {
|
||||
SourceWidget* w;
|
||||
Glib::RefPtr<Gtk::Builder> x = Gtk::Builder::create_from_file(GLADE_FILE, "deviceWidget");
|
||||
x->get_widget_derived("deviceWidget", w);
|
||||
w = Gtk::Builder::get_widget_derived<SourceWidget>(x, "deviceWidget");
|
||||
w->init(mainWindow, "source");
|
||||
w->reference();
|
||||
return w;
|
||||
|
@ -43,7 +43,7 @@ void SourceWidget::executeVolumeUpdate() {
|
|||
pa_operation* o;
|
||||
|
||||
if (!(o = pa_context_set_source_volume_by_index(get_context(), index, &volume, NULL, NULL))) {
|
||||
show_error(_("pa_context_set_source_volume_by_index() failed"));
|
||||
show_error(this, _("pa_context_set_source_volume_by_index() failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ void SourceWidget::onMuteToggleButton() {
|
|||
|
||||
pa_operation* o;
|
||||
if (!(o = pa_context_set_source_mute_by_index(get_context(), index, muteToggleButton->get_active(), NULL, NULL))) {
|
||||
show_error(_("pa_context_set_source_mute_by_index() failed"));
|
||||
show_error(this, _("pa_context_set_source_mute_by_index() failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ void SourceWidget::onDefaultToggleButton() {
|
|||
return;
|
||||
|
||||
if (!(o = pa_context_set_default_source(get_context(), name.c_str(), NULL, NULL))) {
|
||||
show_error(_("pa_context_set_default_source() failed"));
|
||||
show_error(this, _("pa_context_set_default_source() failed"));
|
||||
return;
|
||||
}
|
||||
pa_operation_unref(o);
|
||||
|
@ -94,7 +94,7 @@ void SourceWidget::onPortChange() {
|
|||
Glib::ustring port = row[portModel.name];
|
||||
|
||||
if (!(o = pa_context_set_source_port_by_index(get_context(), index, port.c_str(), NULL, NULL))) {
|
||||
show_error(_("pa_context_set_source_port_by_index() failed"));
|
||||
show_error(this, _("pa_context_set_source_port_by_index() failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,26 +34,20 @@ StreamWidget::StreamWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Buil
|
|||
mpMainWindow(NULL) {
|
||||
|
||||
/* MinimalStreamWidget member variables. */
|
||||
x->get_widget("streamChannelsVBox", channelsVBox);
|
||||
x->get_widget("streamNameLabel", nameLabel);
|
||||
x->get_widget("streamBoldNameLabel", boldNameLabel);
|
||||
x->get_widget("streamIconImage", iconImage);
|
||||
channelsVBox = x->get_widget<Gtk::Box>("streamChannelsVBox");
|
||||
nameLabel = x->get_widget<Gtk::Label>("streamNameLabel");
|
||||
boldNameLabel = x->get_widget<Gtk::Label>("streamBoldNameLabel");
|
||||
iconImage = x->get_widget<Gtk::Image>("streamIconImage");
|
||||
|
||||
x->get_widget("streamLockToggleButton", lockToggleButton);
|
||||
x->get_widget("streamMuteToggleButton", muteToggleButton);
|
||||
x->get_widget("directionLabel", directionLabel);
|
||||
x->get_widget("deviceComboBox", deviceComboBox);
|
||||
lockToggleButton = x->get_widget<Gtk::ToggleButton>("streamLockToggleButton");
|
||||
muteToggleButton = x->get_widget<Gtk::ToggleButton>("streamMuteToggleButton");
|
||||
directionLabel = x->get_widget<Gtk::Label>("directionLabel");
|
||||
deviceComboBox = x->get_widget<Gtk::ComboBoxText>("deviceComboBox");
|
||||
|
||||
this->signal_button_press_event().connect(sigc::mem_fun(*this, &StreamWidget::onContextTriggerEvent));
|
||||
muteToggleButton->signal_clicked().connect(sigc::mem_fun(*this, &StreamWidget::onMuteToggleButton));
|
||||
lockToggleButton->signal_clicked().connect(sigc::mem_fun(*this, &StreamWidget::onLockToggleButton));
|
||||
deviceComboBox->signal_changed().connect(sigc::mem_fun(*this, &StreamWidget::onDeviceComboBoxChanged));
|
||||
|
||||
terminate.set_label(_("Terminate"));
|
||||
terminate.signal_activate().connect(sigc::mem_fun(*this, &StreamWidget::onKill));
|
||||
contextMenu.append(terminate);
|
||||
contextMenu.show_all();
|
||||
|
||||
for (unsigned i = 0; i < PA_CHANNELS_MAX; i++)
|
||||
channelWidgets[i] = NULL;
|
||||
}
|
||||
|
@ -64,12 +58,35 @@ void StreamWidget::init(MainWindow* mainWindow) {
|
|||
MinimalStreamWidget::init();
|
||||
}
|
||||
|
||||
bool StreamWidget::onContextTriggerEvent(GdkEventButton* event) {
|
||||
if (GDK_BUTTON_PRESS == event->type && 3 == event->button) {
|
||||
contextMenu.popup_at_pointer((GdkEvent*)event);
|
||||
return true;
|
||||
void StreamWidget::addKillMenu(const char* killLabel) {
|
||||
auto gesture = Gtk::GestureClick::create();
|
||||
gesture->set_button(3);
|
||||
gesture->set_exclusive(true);
|
||||
gesture->signal_pressed().connect(sigc::mem_fun(*this, &StreamWidget::onContextTriggerEvent));
|
||||
this->add_controller(gesture);
|
||||
|
||||
const std::string actionName = "kill", groupName="streamwidget";
|
||||
auto action = Gio::SimpleAction::create(actionName);
|
||||
action->set_enabled(true);
|
||||
action->signal_activate().connect(sigc::mem_fun(*this, &StreamWidget::onKill));
|
||||
|
||||
auto group = Gio::SimpleActionGroup::create();
|
||||
group->add_action(action);
|
||||
|
||||
insert_action_group(groupName, group);
|
||||
|
||||
auto menuModel = Gio::Menu::create();
|
||||
menuModel->append(killLabel, groupName + "." + actionName);
|
||||
contextMenu.set_menu_model(menuModel);
|
||||
contextMenu.set_parent(*this);
|
||||
}
|
||||
|
||||
|
||||
void StreamWidget::onContextTriggerEvent(gint n_press, gdouble x, gdouble y) {
|
||||
if (n_press == 1) {
|
||||
contextMenu.set_pointing_to(Gdk::Rectangle {(int) x, (int) y, 0 , 0});
|
||||
contextMenu.popup();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void StreamWidget::setChannelMap(const pa_channel_map &m, bool can_decibel) {
|
||||
|
@ -79,7 +96,7 @@ void StreamWidget::setChannelMap(const pa_channel_map &m, bool can_decibel) {
|
|||
|
||||
for (int i = 0; i < m.channels; i++) {
|
||||
ChannelWidget *cw = channelWidgets[i];
|
||||
channelsVBox->pack_start(*cw, false, false, 0);
|
||||
channelsVBox->prepend(*cw);
|
||||
cw->unreference();
|
||||
}
|
||||
|
||||
|
@ -144,7 +161,7 @@ bool StreamWidget::timeoutEvent() {
|
|||
void StreamWidget::executeVolumeUpdate() {
|
||||
}
|
||||
|
||||
void StreamWidget::onKill() {
|
||||
void StreamWidget::onKill(const Glib::VariantBase& parameter) {
|
||||
}
|
||||
|
||||
void StreamWidget::onDeviceComboBoxChanged() {
|
||||
|
|
|
@ -53,21 +53,21 @@ public:
|
|||
|
||||
virtual void onMuteToggleButton();
|
||||
virtual void onLockToggleButton();
|
||||
virtual bool onContextTriggerEvent(GdkEventButton*);
|
||||
virtual void onContextTriggerEvent(gint n_press, gdouble x, gdouble y);
|
||||
|
||||
sigc::connection timeoutConnection;
|
||||
|
||||
bool timeoutEvent();
|
||||
|
||||
virtual void executeVolumeUpdate();
|
||||
virtual void onKill();
|
||||
virtual void onKill(const Glib::VariantBase& parameter);
|
||||
virtual void onDeviceComboBoxChanged();
|
||||
|
||||
protected:
|
||||
MainWindow* mpMainWindow;
|
||||
|
||||
Gtk::Menu contextMenu;
|
||||
Gtk::MenuItem terminate;
|
||||
Gtk::PopoverMenu contextMenu;
|
||||
void addKillMenu(const char* killLabel);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue