69
MainWindow::MainWindow(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& x) :
69
MainWindow::MainWindow(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& x) :
70
70
Gtk::Window(cobject),
71
71
showSinkInputType(SINK_INPUT_CLIENT),
72
72
showSinkType(SINK_ALL),
73
73
showSourceOutputType(SOURCE_OUTPUT_CLIENT),
74
74
showSourceType(SOURCE_NO_MONITOR),
75
eventRoleWidget(NULL){
75
eventRoleWidget(NULL),
76
canRenameDevices(false),
78
m_config_filename(NULL) {
77
80
x->get_widget("cardsVBox", cardsVBox);
78
81
x->get_widget("streamsVBox", streamsVBox);
84
87
x->get_widget("noRecsLabel", noRecsLabel);
85
88
x->get_widget("noSinksLabel", noSinksLabel);
86
89
x->get_widget("noSourcesLabel", noSourcesLabel);
90
x->get_widget("connectingLabel", connectingLabel);
87
91
x->get_widget("sinkInputTypeComboBox", sinkInputTypeComboBox);
88
92
x->get_widget("sourceOutputTypeComboBox", sourceOutputTypeComboBox);
89
93
x->get_widget("sinkTypeComboBox", sinkTypeComboBox);
105
109
sourceOutputTypeComboBox->signal_changed().connect(sigc::mem_fun(*this, &MainWindow::onSourceOutputTypeComboBoxChanged));
106
110
sinkTypeComboBox->signal_changed().connect(sigc::mem_fun(*this, &MainWindow::onSinkTypeComboBoxChanged));
107
111
sourceTypeComboBox->signal_changed().connect(sigc::mem_fun(*this, &MainWindow::onSourceTypeComboBoxChanged));
113
GKeyFile* config = g_key_file_new();
115
GKeyFileFlags flags = (GKeyFileFlags)( G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS);
117
m_config_filename = g_strconcat(g_get_user_config_dir(), "/pavucontrol.ini", NULL);
119
/* Load the GKeyFile from keyfile.conf or return. */
120
if (g_key_file_load_from_file (config, m_config_filename, flags, &err)) {
121
int width = g_key_file_get_integer(config, "window", "width", NULL);
122
int height = g_key_file_get_integer(config, "window", "height", NULL);
124
int default_width, default_height;
125
get_default_size(default_width, default_height);
126
if (width >= default_width && height >= default_height)
127
resize(width, height);
129
g_debug(_("Error reading config file %s: %s"), m_config_filename, err->message);
132
g_key_file_free(config);
135
/* Hide first and show when we're connected */
137
connectingLabel->show();
110
140
MainWindow* MainWindow::create() {
112
Glib::RefPtr<Gnome::Glade::Xml> x = Gnome::Glade::Xml::create(GLADE_FILE, "mainWindow");
142
Glib::RefPtr<Gtk::Builder> x = Gtk::Builder::create();
143
x->add_from_file(GLADE_FILE, "liststore1");
144
x->add_from_file(GLADE_FILE, "liststore2");
145
x->add_from_file(GLADE_FILE, "liststore3");
146
x->add_from_file(GLADE_FILE, "liststore4");
147
x->add_from_file(GLADE_FILE, "mainWindow");
113
148
x->get_widget_derived("mainWindow", w);
117
152
void MainWindow::on_realize() {
118
153
Gtk::Window::on_realize();
156
get_window()->set_cursor(Gdk::Cursor::create(Gdk::WATCH));
120
158
get_window()->set_cursor(Gdk::Cursor(Gdk::WATCH));
159
#endif /* HAVE_GTK3 */
162
bool MainWindow::on_key_press_event(GdkEventKey* event) {
164
if (GDK_KEY_Escape == event->keyval) {
168
if (event->state & GDK_CONTROL_MASK) {
169
switch (event->keyval) {
175
notebook->set_current_page(event->keyval - GDK_KEY_KP_1);
182
notebook->set_current_page(event->keyval - GDK_KEY_1);
192
return Gtk::Window::on_key_press_event(event);
123
195
MainWindow::~MainWindow() {
196
GKeyFile* config = g_key_file_new();
200
get_size(width, height);
201
g_key_file_set_integer(config, "window", "width", width);
202
g_key_file_set_integer(config, "window", "height", height);
206
gchar *filedata = g_key_file_to_data(config, &filelen, &err);
208
show_error(_("Error saving preferences"));
213
g_file_set_contents(m_config_filename, filedata, filelen, &err);
216
gchar* msg = g_strconcat(_("Error writing config file %s"), m_config_filename, NULL);
225
g_key_file_free(config);
226
g_free(m_config_filename);
124
228
while (!clientNames.empty()) {
125
229
std::map<uint32_t, char*>::iterator i = clientNames.begin();
126
230
g_free(i->second);
203
307
if (sinkWidgets.count(info.index))
204
308
w = sinkWidgets[info.index];
206
sinkWidgets[info.index] = w = SinkWidget::create();
310
sinkWidgets[info.index] = w = SinkWidget::create(this);
207
311
w->setChannelMap(info.channel_map, !!(info.flags & PA_SINK_DECIBEL_VOLUME));
208
312
sinksVBox->pack_start(*w, false, false, 0);
209
313
w->index = info.index;
304
407
if (!(s = pa_stream_new(get_context(), _("Peak detect"), &ss, NULL))) {
305
408
show_error(_("Failed to create monitoring stream"));
412
if (stream_idx != (uint32_t) -1)
413
pa_stream_set_monitor_stream(s, stream_idx);
309
415
pa_stream_set_read_callback(s, read_callback, this);
310
416
pa_stream_set_suspended_callback(s, suspended_callback, this);
312
if (pa_stream_connect_record(s, t, &attr, (pa_stream_flags_t) (PA_STREAM_DONT_MOVE|PA_STREAM_PEAK_DETECT|PA_STREAM_ADJUST_LATENCY)) < 0) {
418
if (pa_stream_connect_record(s, t, &attr, (pa_stream_flags_t) (PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND|PA_STREAM_DONT_MOVE|PA_STREAM_PEAK_DETECT|PA_STREAM_ADJUST_LATENCY)) < 0) {
313
419
show_error(_("Failed to connect monitoring stream"));
314
420
pa_stream_unref(s);
319
void MainWindow::createMonitorStreamForSinkInput(uint32_t sink_input_idx, uint32_t sink_idx) {
324
uint32_t monitor_source_idx;
327
ss.format = PA_SAMPLE_FLOAT32;
426
void MainWindow::createMonitorStreamForSinkInput(SinkInputWidget* w, uint32_t sink_idx) {
330
427
if (!sinkWidgets.count(sink_idx))
333
monitor_source_idx = sinkWidgets[sink_idx]->monitor_index;
335
memset(&attr, 0, sizeof(attr));
336
attr.fragsize = sizeof(float);
337
attr.maxlength = (uint32_t) -1;
339
snprintf(t, sizeof(t), "%u", monitor_source_idx);
341
if (!(s = pa_stream_new(get_context(), _("Peak detect"), &ss, NULL))) {
342
show_error(_("Failed to create monitoring stream"));
346
pa_stream_set_monitor_stream(s, sink_input_idx);
347
pa_stream_set_read_callback(s, read_callback, this);
348
pa_stream_set_suspended_callback(s, suspended_callback, this);
350
if (pa_stream_connect_record(s, t, &attr, (pa_stream_flags_t) (PA_STREAM_DONT_MOVE|PA_STREAM_PEAK_DETECT|PA_STREAM_ADJUST_LATENCY)) < 0) {
351
show_error(_("Failed to connect monitoring stream"));
431
pa_stream_disconnect(w->peak);
435
w->peak = createMonitorStreamForSource(sinkWidgets[sink_idx]->monitor_index, w->index);
357
438
void MainWindow::updateSource(const pa_source_info &info) {
363
444
if (sourceWidgets.count(info.index))
364
445
w = sourceWidgets[info.index];
366
sourceWidgets[info.index] = w = SourceWidget::create();
447
sourceWidgets[info.index] = w = SourceWidget::create(this);
367
448
w->setChannelMap(info.channel_map, !!(info.flags & PA_SOURCE_DECIBEL_VOLUME));
368
449
sourcesVBox->pack_start(*w, false, false, 0);
369
450
w->index = info.index;
372
453
w->setBaseVolume(info.base_volume);
373
w->setSteps(info.n_volume_steps);
375
455
if (pa_context_get_server_protocol_version(get_context()) >= 13)
376
456
createMonitorStreamForSource(info.index);
471
if (sinkInputWidgets.count(info.index))
551
if (sinkInputWidgets.count(info.index)) {
472
552
w = sinkInputWidgets[info.index];
553
if (pa_context_get_server_protocol_version(get_context()) >= 13)
554
if (w->sinkIndex() != info.sink)
555
createMonitorStreamForSinkInput(w, info.sink);
474
557
sinkInputWidgets[info.index] = w = SinkInputWidget::create(this);
475
558
w->setChannelMap(info.channel_map, true);
476
559
streamsVBox->pack_start(*w, false, false, 0);
523
606
w = sourceOutputWidgets[info.index];
525
608
sourceOutputWidgets[info.index] = w = SourceOutputWidget::create(this);
609
#if HAVE_SOURCE_OUTPUT_VOLUMES
610
w->setChannelMap(info.channel_map, true);
526
612
recsVBox->pack_start(*w, false, false, 0);
527
613
w->index = info.index;
528
614
w->clientIndex = info.client;
531
618
w->updating = true;
887
992
clientNames.erase(index);
995
void MainWindow::removeAllWidgets() {
996
for (std::map<uint32_t, SinkInputWidget*>::iterator it = sinkInputWidgets.begin(); it != sinkInputWidgets.end(); ++it)
997
removeSinkInput(it->first);
998
for (std::map<uint32_t, SourceOutputWidget*>::iterator it = sourceOutputWidgets.begin(); it != sourceOutputWidgets.end(); ++it)
999
removeSourceOutput(it->first);
1000
for (std::map<uint32_t, SinkWidget*>::iterator it = sinkWidgets.begin(); it != sinkWidgets.end(); ++it)
1001
removeSink(it->first);
1002
for (std::map<uint32_t, SourceWidget*>::iterator it = sourceWidgets.begin(); it != sourceWidgets.end(); ++it)
1003
removeSource(it->first);
1004
for (std::map<uint32_t, CardWidget*>::iterator it = cardWidgets.begin(); it != cardWidgets.end(); ++it)
1005
removeCard(it->first);
1006
for (std::map<uint32_t, char*>::iterator it = clientNames.begin(); it != clientNames.end(); ++it)
1007
removeClient(it->first);
1008
deleteEventRoleWidget();
1011
void MainWindow::setConnectingMessage(const char *string) {
1012
Glib::ustring markup = "<i>";
1014
markup += _("Establishing connection to PulseAudio. Please wait...");
1018
connectingLabel->set_markup(markup);
890
1021
void MainWindow::onSinkTypeComboBoxChanged() {
891
1022
showSinkType = (SinkType) sinkTypeComboBox->get_active_row_number();