~ubuntu-branches/ubuntu/oneiric/pavucontrol/oneiric

« back to all changes in this revision

Viewing changes to src/mainwindow.cc

  • Committer: Bazaar Package Importer
  • Author(s): Luke Yelavich
  • Date: 2011-08-17 07:47:11 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20110817074711-5ud24e9y5dv2wjxc
Tags: 0.99.1-0ubuntu1
* New upstream release. (LP: #827119)
* debian/control: update build dependencies to build against gtk3
* debian/patches/0001-Define-missing-flags.patch: dropped

Show diffs side-by-side

added added

removed removed

Lines of Context:
66
66
    }
67
67
};
68
68
 
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),
 
77
    m_connected(false),
 
78
    m_config_filename(NULL) {
76
79
 
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));
 
112
 
 
113
    GKeyFile* config = g_key_file_new();
 
114
    g_assert(config);
 
115
    GKeyFileFlags flags = (GKeyFileFlags)( G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS);
 
116
    GError *err = NULL;
 
117
    m_config_filename = g_strconcat(g_get_user_config_dir(), "/pavucontrol.ini", NULL);
 
118
 
 
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);
 
123
 
 
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);
 
128
    } else {
 
129
        g_debug(_("Error reading config file %s: %s"), m_config_filename, err->message);
 
130
        g_error_free(err);
 
131
    }
 
132
    g_key_file_free(config);
 
133
 
 
134
 
 
135
    /* Hide first and show when we're connected */
 
136
    notebook->hide();
 
137
    connectingLabel->show();
108
138
}
109
139
 
110
140
MainWindow* MainWindow::create() {
111
141
    MainWindow* w;
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);
114
149
    return w;
115
150
}
117
152
void MainWindow::on_realize() {
118
153
    Gtk::Window::on_realize();
119
154
 
 
155
#ifdef HAVE_GTK3
 
156
    get_window()->set_cursor(Gdk::Cursor::create(Gdk::WATCH));
 
157
#else
120
158
    get_window()->set_cursor(Gdk::Cursor(Gdk::WATCH));
 
159
#endif /* HAVE_GTK3 */
 
160
}
 
161
 
 
162
bool MainWindow::on_key_press_event(GdkEventKey* event) {
 
163
 
 
164
    if (GDK_KEY_Escape == event->keyval) {
 
165
        Gtk::Main::quit();
 
166
        return true;
 
167
    }
 
168
    if (event->state & GDK_CONTROL_MASK) {
 
169
        switch (event->keyval) {
 
170
            case GDK_KEY_KP_1:
 
171
            case GDK_KEY_KP_2:
 
172
            case GDK_KEY_KP_3:
 
173
            case GDK_KEY_KP_4:
 
174
            case GDK_KEY_KP_5:
 
175
                notebook->set_current_page(event->keyval - GDK_KEY_KP_1);
 
176
                return true;
 
177
            case GDK_KEY_1:
 
178
            case GDK_KEY_2:
 
179
            case GDK_KEY_3:
 
180
            case GDK_KEY_4:
 
181
            case GDK_KEY_5:
 
182
                notebook->set_current_page(event->keyval - GDK_KEY_1);
 
183
                return true;
 
184
            case GDK_KEY_W:
 
185
            case GDK_KEY_Q:
 
186
            case GDK_KEY_w:
 
187
            case GDK_KEY_q:
 
188
                Gtk::Main::quit();
 
189
                return true;
 
190
        }
 
191
    }
 
192
    return Gtk::Window::on_key_press_event(event);
121
193
}
122
194
 
123
195
MainWindow::~MainWindow() {
 
196
    GKeyFile* config = g_key_file_new();
 
197
    g_assert(config);
 
198
 
 
199
    int width, height;
 
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);
 
203
 
 
204
    gsize filelen;
 
205
    GError *err = NULL;
 
206
    gchar *filedata = g_key_file_to_data(config, &filelen, &err);
 
207
    if (err) {
 
208
        show_error(_("Error saving preferences"));
 
209
        g_error_free(err);
 
210
        goto finish;
 
211
    }
 
212
 
 
213
    g_file_set_contents(m_config_filename, filedata, filelen, &err);
 
214
    g_free(filedata);
 
215
    if (err) {
 
216
        gchar* msg = g_strconcat(_("Error writing config file %s"), m_config_filename, NULL);
 
217
        show_error(msg);
 
218
        g_free(msg);
 
219
        g_error_free(err);
 
220
        goto finish;
 
221
    }
 
222
 
 
223
finish:
 
224
 
 
225
    g_key_file_free(config);
 
226
    g_free(m_config_filename);
 
227
 
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];
205
309
    else {
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;
211
315
        is_new = true;
212
316
 
213
317
        w->setBaseVolume(info.base_volume);
214
 
        w->setSteps(info.n_volume_steps);
215
318
    }
216
319
 
217
320
    w->updating = true;
285
388
    w->updateVolumeMeter(pa_stream_get_device_index(s), pa_stream_get_monitor_stream(s), v);
286
389
}
287
390
 
288
 
void MainWindow::createMonitorStreamForSource(uint32_t source_idx) {
 
391
pa_stream* MainWindow::createMonitorStreamForSource(uint32_t source_idx, uint32_t stream_idx = -1) {
289
392
    pa_stream *s;
290
393
    char t[16];
291
394
    pa_buffer_attr attr;
303
406
 
304
407
    if (!(s = pa_stream_new(get_context(), _("Peak detect"), &ss, NULL))) {
305
408
        show_error(_("Failed to create monitoring stream"));
306
 
        return;
 
409
        return NULL;
307
410
    }
308
411
 
 
412
    if (stream_idx != (uint32_t) -1)
 
413
        pa_stream_set_monitor_stream(s, stream_idx);
 
414
 
309
415
    pa_stream_set_read_callback(s, read_callback, this);
310
416
    pa_stream_set_suspended_callback(s, suspended_callback, this);
311
417
 
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);
315
 
        return;
 
421
        return NULL;
316
422
    }
 
423
    return s;
317
424
}
318
425
 
319
 
void MainWindow::createMonitorStreamForSinkInput(uint32_t sink_input_idx, uint32_t sink_idx) {
320
 
    pa_stream *s;
321
 
    char t[16];
322
 
    pa_buffer_attr attr;
323
 
    pa_sample_spec ss;
324
 
    uint32_t monitor_source_idx;
325
 
 
326
 
    ss.channels = 1;
327
 
    ss.format = PA_SAMPLE_FLOAT32;
328
 
    ss.rate = 25;
329
 
 
 
426
void MainWindow::createMonitorStreamForSinkInput(SinkInputWidget* w, uint32_t sink_idx) {
330
427
    if (!sinkWidgets.count(sink_idx))
331
428
        return;
332
429
 
333
 
    monitor_source_idx = sinkWidgets[sink_idx]->monitor_index;
334
 
 
335
 
    memset(&attr, 0, sizeof(attr));
336
 
    attr.fragsize = sizeof(float);
337
 
    attr.maxlength = (uint32_t) -1;
338
 
 
339
 
    snprintf(t, sizeof(t), "%u", monitor_source_idx);
340
 
 
341
 
    if (!(s = pa_stream_new(get_context(), _("Peak detect"), &ss, NULL))) {
342
 
        show_error(_("Failed to create monitoring stream"));
343
 
        return;
344
 
    }
345
 
 
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);
349
 
 
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"));
352
 
        pa_stream_unref(s);
353
 
        return;
354
 
    }
 
430
    if (w->peak) {
 
431
        pa_stream_disconnect(w->peak);
 
432
        w->peak = NULL;
 
433
    }
 
434
 
 
435
    w->peak = createMonitorStreamForSource(sinkWidgets[sink_idx]->monitor_index, w->index);
355
436
}
356
437
 
357
438
void MainWindow::updateSource(const pa_source_info &info) {
363
444
    if (sourceWidgets.count(info.index))
364
445
        w = sourceWidgets[info.index];
365
446
    else {
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;
370
451
        is_new = true;
371
452
 
372
453
        w->setBaseVolume(info.base_volume);
373
 
        w->setSteps(info.n_volume_steps);
374
454
 
375
455
        if (pa_context_get_server_protocol_version(get_context()) >= 13)
376
456
            createMonitorStreamForSource(info.index);
468
548
        }
469
549
    }
470
550
 
471
 
    if (sinkInputWidgets.count(info.index))
 
551
    if (sinkInputWidgets.count(info.index)) {
472
552
        w = sinkInputWidgets[info.index];
473
 
    else {
 
553
        if (pa_context_get_server_protocol_version(get_context()) >= 13)
 
554
            if (w->sinkIndex() != info.sink)
 
555
                createMonitorStreamForSinkInput(w, info.sink);
 
556
    } else {
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);
479
562
        is_new = true;
480
563
 
481
564
        if (pa_context_get_server_protocol_version(get_context()) >= 13)
482
 
            createMonitorStreamForSinkInput(info.index, info.sink);
 
565
            createMonitorStreamForSinkInput(w, info.sink);
483
566
    }
484
567
 
485
568
    w->updating = true;
523
606
        w = sourceOutputWidgets[info.index];
524
607
    else {
525
608
        sourceOutputWidgets[info.index] = w = SourceOutputWidget::create(this);
 
609
#if HAVE_SOURCE_OUTPUT_VOLUMES
 
610
        w->setChannelMap(info.channel_map, true);
 
611
#endif
526
612
        recsVBox->pack_start(*w, false, false, 0);
527
613
        w->index = info.index;
528
614
        w->clientIndex = info.client;
 
615
        is_new = true;
529
616
    }
530
617
 
531
618
    w->updating = true;
547
634
 
548
635
    setIconFromProplist(w->iconImage, info.proplist, "audio-input-microphone");
549
636
 
 
637
#if HAVE_SOURCE_OUTPUT_VOLUMES
 
638
    w->setVolume(info.volume);
 
639
    w->muteToggleButton->set_active(info.mute);
 
640
#endif
 
641
 
550
642
    w->updating = false;
551
643
 
552
644
    if (is_new)
711
803
    return FALSE;
712
804
}
713
805
 
 
806
void MainWindow::setConnectionState(gboolean connected) {
 
807
    if (m_connected != connected) {
 
808
        m_connected = connected;
 
809
        if (m_connected) {
 
810
            connectingLabel->hide();
 
811
            notebook->show();
 
812
        } else {
 
813
            notebook->hide();
 
814
            connectingLabel->show();
 
815
        }
 
816
    }
 
817
}
 
818
 
714
819
void MainWindow::updateDeviceVisibility() {
715
820
 
716
821
    if (idle_source)
887
992
    clientNames.erase(index);
888
993
}
889
994
 
 
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();
 
1009
}
 
1010
 
 
1011
void MainWindow::setConnectingMessage(const char *string) {
 
1012
    Glib::ustring markup = "<i>";
 
1013
    if (!string)
 
1014
        markup += _("Establishing connection to PulseAudio. Please wait...");
 
1015
    else
 
1016
        markup += string;
 
1017
    markup += "</i>";
 
1018
    connectingLabel->set_markup(markup);
 
1019
}
 
1020
 
890
1021
void MainWindow::onSinkTypeComboBoxChanged() {
891
1022
    showSinkType = (SinkType) sinkTypeComboBox->get_active_row_number();
892
1023