~audio-recorder/audio-recorder/trunk

« back to all changes in this revision

Viewing changes to src/settings.c

  • Committer: Osmo Antero
  • Date: 2014-09-24 13:51:15 UTC
  • Revision ID: osmoma@gmail.com-20140924135115-uq77346mihssi60l
Modifications towards version 1.5. Please see ChangeLog file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) Linux community.
 
3
 *
 
4
 * This library is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU Library General Public
 
6
 * License as published by the Free Software Foundation; either
 
7
 * version 3 of the License (GPL3), or any later version.
 
8
 *
 
9
 * This library is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
 
12
 * See the GNU Library General Public License 3 for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU Library General Public
 
15
 * License 3 along with this program; if not, see /usr/share/common-licenses/GPL file
 
16
 * or write to Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
17
 * Boston, MA 02111-1307, USA.
 
18
*/
 
19
#include "audio-sources.h"
 
20
#include "support.h"
 
21
#include "utility.h"
 
22
#include "timer.h"
 
23
#include "dconf.h"
 
24
 
 
25
#include "rec-window.h"
 
26
#include "auto-start.h"
 
27
#include "help.h"
 
28
#include "dbus-skype.h"
 
29
 
 
30
static GtkWidget *g_dialog = NULL;
 
31
 
 
32
// Currently selected device/player type
 
33
static gint g_current_type = 0;
 
34
 
 
35
// All changed device/player types
 
36
static gint g_changed_types = 0;
 
37
 
 
38
// List of some known players; RhythmBox, Banshee, VLC, Amarok (this is just a label text)
 
39
// static const gchar *g_player_list = NULL;
 
40
 
 
41
// Listbox (GtkTreeView) columns.
 
42
enum {
 
43
    COL_CHECKBOX,// Checkbox (hidden in the upper listbox)
 
44
    COL_TYPE,    // DeviceType  (hidden)
 
45
    COL_ID,      // Device ID (hidden)
 
46
    COL_ICON,    // Device icon (visible)
 
47
    COL_DESCR,   // Device description (visible)
 
48
    COL_HELP,    // Help text (help text shown under the listbox)
 
49
    N_COLUMNS    // Number of columns in this listbox (treeview)
 
50
};
 
51
 
 
52
extern void win_keep_on_top(gboolean on_top);
 
53
 
 
54
static void device_list_reload(gint type, gchar *type_descr, gchar *help_text);
 
55
static void device_list_fill();
 
56
static void device_list_save();
 
57
 
 
58
void win_settings_destroy_dialog() {
 
59
    if (GTK_IS_WIDGET(g_dialog)) {
 
60
        gtk_widget_destroy(GTK_WIDGET(g_dialog));
 
61
    }
 
62
    g_dialog = NULL;
 
63
}
 
64
 
 
65
#if 0 
 
66
static void check_media_players() {
 
67
    // Collect list of (some well known) media players; RhythmBox, Banshee, VLC, Amarok. etc.
 
68
    
 
69
    // Already done?
 
70
    if (g_player_list) {
 
71
        return;
 
72
    }
 
73
 
 
74
    const gchar *lst[] = {"RhythmBox", "Banshee", "Exaile", "Amarok", "VLC", "Audacious"};
 
75
    
 
76
    GString *s = g_string_new(NULL);
 
77
 
 
78
    guint i = 0;
 
79
 
 
80
    guint count = sizeof(lst)/sizeof(lst[0]);
 
81
    for (i=0; i < count; i++) {
 
82
 
 
83
        gchar *player = g_ascii_strdown(lst[i], -1);
 
84
        gchar *path = find_command_path(player);
 
85
 
 
86
        if (path) {
 
87
            if (s->len > 0)
 
88
                g_string_append(s, ", ");
 
89
 
 
90
            g_string_append(s, lst[i]);
 
91
        }
 
92
 
 
93
        g_free(path);
 
94
        g_free(player);
 
95
    
 
96
        if (s->len > 40) break;
 
97
    }
 
98
 
 
99
    g_player_list = g_string_free(s, FALSE);
 
100
    s = NULL;
 
101
}
 
102
#endif
 
103
 
 
104
static void keep_on_top_switch_cb(GtkWidget *widget, gpointer data) {
 
105
    // Is ON/OFF?
 
106
    gboolean active = gtk_switch_get_active(GTK_SWITCH(widget));
 
107
 
 
108
    // Save in Dconf
 
109
    conf_save_boolean_value("keep-on-top", active);
 
110
 
 
111
    win_keep_on_top(active);
 
112
 
 
113
}
 
114
 
 
115
static void show_icon_switch_cb(GtkWidget *widget, gpointer data) {
 
116
    // Is ON/OFF?
 
117
    gboolean active = gtk_switch_get_active(GTK_SWITCH(widget));
 
118
 
 
119
    // Save in gconf
 
120
    conf_save_boolean_value("show-systray-icon", active);
 
121
 
 
122
    // Install or remove systray icon
 
123
    systray_icon_setup(active);
 
124
 
 
125
    // Update also autostart option (mode of autostart depends on the systray icon)
 
126
    active = autostart_get();
 
127
    autostart_set(active);
 
128
}
 
129
 
 
130
static void autostart_switch_cb(GtkWidget *widget, gpointer data) {
 
131
    // Is ON/OFF?
 
132
    gboolean active = gtk_switch_get_active(GTK_SWITCH(widget));
 
133
 
 
134
    // Write autostart values
 
135
    autostart_set(active);
 
136
}
 
137
 
 
138
static void win_settings_get_folder_name(GtkWidget *widget, gpointer data) {
 
139
    // Get folder where to save all recordings.
 
140
    GtkWidget *entry = (GtkWidget*)data;
 
141
 
 
142
    // Translators: This is a title in a directory chooser dialog.
 
143
    GtkWidget *dialog = gtk_file_chooser_dialog_new(_("Select Directory"),
 
144
                        NULL,
 
145
                        GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
 
146
                        "gtk-cancel", GTK_RESPONSE_CANCEL,
 
147
                        "gtk-open", GTK_RESPONSE_ACCEPT,
 
148
                        NULL);
 
149
 
 
150
    // Set current directory
 
151
    gchar *path = g_strdup((gchar*)gtk_entry_get_text(GTK_ENTRY(entry)));
 
152
    if (str_length(path, 2048) < 1) {
 
153
        g_free(path);
 
154
        path = get_home_dir();
 
155
    }
 
156
 
 
157
    gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), path);
 
158
 
 
159
    guint response = gtk_dialog_run(GTK_DIALOG(dialog));
 
160
 
 
161
    g_free(path);
 
162
    path = NULL;
 
163
 
 
164
    switch (response) {
 
165
    case GTK_RESPONSE_ACCEPT: {
 
166
        path = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER (dialog));
 
167
    }
 
168
    }
 
169
 
 
170
    if (GTK_IS_WIDGET(dialog)) {
 
171
        gtk_widget_destroy(GTK_WIDGET(dialog));
 
172
    }
 
173
 
 
174
    if (path) {
 
175
        gtk_entry_set_text(GTK_ENTRY(entry), path);
 
176
        g_free(path);
 
177
    }
 
178
}
 
179
 
 
180
static void win_settings_show_filename_help() {
 
181
    // Show help file
 
182
    help_show_page("filename-format.html");
 
183
}
 
184
 
 
185
// ----------------------------------------------
 
186
 
 
187
static void device_list_checkbox_toggled(GtkCellRendererToggle *toggle, gchar *path_str, gpointer data) {
 
188
    // User clicked on COL_CHECKBOX.
 
189
    GtkTreeIter iter;
 
190
    gboolean active;
 
191
 
 
192
    g_object_get(G_OBJECT(toggle), "active", &active, NULL );
 
193
 
 
194
    GtkTreeModel *model = GTK_TREE_MODEL(data);
 
195
    gtk_tree_model_get_iter_from_string(model, &iter, path_str);
 
196
    gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0, !active, -1);
 
197
 
 
198
    // Save device list in GConf (for g_current_type)
 
199
    device_list_save();
 
200
}
 
201
 
 
202
static GtkWidget *create_listbox() {
 
203
    // Create list store
 
204
    GtkListStore *store = gtk_list_store_new(N_COLUMNS, G_TYPE_BOOLEAN, G_TYPE_INT, G_TYPE_STRING,
 
205
                          GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING);
 
206
 
 
207
    // List view
 
208
    GtkWidget *list_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
 
209
 
 
210
    // Add some extra space
 
211
    gtk_widget_set_size_request (list_view, -1, 85);
 
212
 
 
213
    // Unref store
 
214
    g_object_unref(G_OBJECT(store));
 
215
 
 
216
    // No headers
 
217
    gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list_view), FALSE);
 
218
 
 
219
    // Checkbox (this invisible in the upper listbox (treeview list).
 
220
    GtkTreeViewColumn *col = gtk_tree_view_column_new();
 
221
    gtk_tree_view_column_set_title(col, "Row checkbox");
 
222
    GtkCellRenderer *cell = gtk_cell_renderer_toggle_new();
 
223
    g_signal_connect(G_OBJECT(cell), "toggled", G_CALLBACK(device_list_checkbox_toggled), GTK_TREE_MODEL(store));
 
224
    gtk_tree_view_column_pack_start(col, cell, FALSE );
 
225
    gtk_tree_view_column_add_attribute(col, cell, "active", COL_CHECKBOX);
 
226
    gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), col);
 
227
 
 
228
    // Device type column (invisible)
 
229
    col = gtk_tree_view_column_new();
 
230
    gtk_tree_view_column_set_title(col, "Device type");
 
231
    cell = gtk_cell_renderer_text_new();
 
232
    gtk_tree_view_column_set_visible(col, FALSE);
 
233
    gtk_tree_view_column_pack_start(col, cell, FALSE);
 
234
    gtk_tree_view_column_set_attributes(col, cell, "text", COL_TYPE, NULL);
 
235
    gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), col);
 
236
 
 
237
    // Device id column (invisible)
 
238
    col = gtk_tree_view_column_new();
 
239
    gtk_tree_view_column_set_title(col, "Device id");
 
240
    cell = gtk_cell_renderer_text_new();
 
241
    gtk_tree_view_column_set_visible(col, FALSE);
 
242
    gtk_tree_view_column_pack_start(col, cell, FALSE);
 
243
    gtk_tree_view_column_set_attributes(col, cell, "text", COL_ID, NULL);
 
244
    gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), col);
 
245
 
 
246
    // Device icon (pixbuf) column (visible)
 
247
    col = gtk_tree_view_column_new();
 
248
    gtk_tree_view_column_set_title(col, "Pixbuf");
 
249
    cell = gtk_cell_renderer_pixbuf_new();
 
250
    gtk_tree_view_column_pack_start(col, cell, FALSE);
 
251
    gtk_tree_view_column_set_attributes(col, cell, "pixbuf", COL_ICON, NULL);
 
252
    gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), col);
 
253
 
 
254
    // Device description column (visible)
 
255
    col = gtk_tree_view_column_new();
 
256
    gtk_tree_view_column_set_title(col, "Description");
 
257
    cell = gtk_cell_renderer_text_new();
 
258
    gtk_tree_view_column_pack_start(col, cell, FALSE);
 
259
    gtk_tree_view_column_set_attributes(col, cell, "text", COL_DESCR, NULL);
 
260
    gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), col);
 
261
 
 
262
    // Help text (invisible, text is shown under the second listbox)
 
263
    col = gtk_tree_view_column_new();
 
264
    gtk_tree_view_column_set_title(col, "Help text");
 
265
    gtk_tree_view_column_set_visible(col, FALSE);
 
266
    cell = gtk_cell_renderer_text_new();
 
267
    gtk_tree_view_column_pack_start(col, cell, FALSE);
 
268
    gtk_tree_view_column_set_attributes(col, cell, "text", COL_HELP, NULL);
 
269
    gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), col);
 
270
 
 
271
    return list_view;
 
272
}
 
273
 
 
274
static void player_view_row_changed_cb(GtkTreeSelection *selection, gpointer user_data) {
 
275
    // Row changed in player view.
 
276
    GtkTreeModel *model;
 
277
    GtkTreeIter iter;
 
278
 
 
279
    if (!gtk_tree_selection_get_selected(selection, &model, &iter)) return;
 
280
 
 
281
    // Get row values
 
282
    gint type;
 
283
    gchar *descr = NULL;
 
284
    gchar *help_text = NULL;
 
285
 
 
286
    gtk_tree_model_get(model, &iter,
 
287
                       COL_TYPE, &type,
 
288
                       COL_DESCR, &descr,
 
289
                       COL_HELP, &help_text, -1);
 
290
 
 
291
    // From type to type name
 
292
    const gchar *type_name = device_item_get_type_name(type);
 
293
    (void)type_name; // Avoid unused var message
 
294
 
 
295
    LOG_DEBUG("Selected row is:%s (%d), %s\n", type_name, type, descr);
 
296
 
 
297
    // Reload the device list
 
298
    device_list_reload(type, descr, help_text);
 
299
 
 
300
    g_free(descr);
 
301
    g_free(help_text);
 
302
}
 
303
 
 
304
static void device_list_reload(gint type, gchar *type_descr, gchar *help_text) {
 
305
    // Save type name
 
306
    g_current_type = type;
 
307
 
 
308
    // Show help text
 
309
    GtkWidget *label = (GtkWidget*)g_object_get_data(G_OBJECT(g_dialog), "player-label-widget");
 
310
    gtk_label_set_text(GTK_LABEL(label), help_text);
 
311
 
 
312
    // Set GUI label
 
313
    gchar *txt = g_strdup_printf(_("Recording devices for %s:"), type_descr);
 
314
    label = (GtkWidget*)g_object_get_data(G_OBJECT(g_dialog), "device-label-widget");
 
315
    gtk_label_set_text(GTK_LABEL(label), txt);
 
316
    g_free(txt);
 
317
 
 
318
    // Fill the device list
 
319
    device_list_fill();
 
320
}
 
321
 
 
322
static void player_view_fill() {
 
323
    GtkWidget *view = g_object_get_data(G_OBJECT(g_dialog), "player-list-widget");
 
324
 
 
325
    GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
 
326
    GtkTreeIter  iter;
 
327
 
 
328
    if (!GTK_IS_TREE_MODEL(model)) {
 
329
        return;
 
330
    }
 
331
 
 
332
    // Clear view
 
333
    gtk_list_store_clear(GTK_LIST_STORE(model));
 
334
 
 
335
    // Get available players, comm progs.
 
336
    GList *dev_list = audio_sources_get_for_type(MEDIA_PLAYER | COMM_PROGRAM | USER_DEFINED);
 
337
    // Debug print:
 
338
    // audio_sources_print_list(dev_list, "Players:");
 
339
 
 
340
    // Collect types
 
341
    gint item_types = 0;
 
342
 
 
343
    // Add items to the listbox
 
344
    GList *n = g_list_first(dev_list);
 
345
    while (n) {
 
346
        DeviceItem *item = (DeviceItem*)n->data;
 
347
 
 
348
        // Already in the list?
 
349
        if (item_types & item->type) {
 
350
            // Next item thanks
 
351
            n = g_list_next(n);
 
352
            continue;
 
353
        }
 
354
 
 
355
        // Collect types
 
356
        item_types = item_types | item->type;
 
357
 
 
358
        // Add new row
 
359
        gtk_list_store_append(GTK_LIST_STORE(model), &iter);
 
360
 
 
361
        gchar *descr = NULL;
 
362
        gchar *help_text = NULL;
 
363
        GdkPixbuf *pixbuf = NULL;
 
364
 
 
365
        switch (item->type) {
 
366
        case MEDIA_PLAYER:
 
367
            // Translators: This is a label in the [Additional settings] dialog
 
368
            descr = g_strdup(_("Media players (RhythmBox, Banshee, etc.)"));
 
369
 
 
370
            pixbuf = NULL;
 
371
            
 
372
            // Translators: This is a label/help text in the [Additional settings] dialog
 
373
            help_text = g_strdup(_("Select output device (speakers) for recording."));
 
374
            break;
 
375
 
 
376
        case COMM_PROGRAM:
 
377
            descr = g_strdup(item->description);
 
378
 
 
379
            pixbuf = load_icon_pixbuf(item->icon_name);
 
380
 
 
381
            // Translators: This is a label/help text in the [Additional settings] dialog
 
382
            help_text = g_strdup(_("Select both output device (speakers) and webcam/microphone."));
 
383
            break;
 
384
 
 
385
            //case USER_DEFINED:
 
386
        default:
 
387
            descr = g_strdup(item->description);
 
388
 
 
389
            gchar *path = get_image_path(item->icon_name);
 
390
            pixbuf = get_pixbuf_from_file(path, 22, 22);
 
391
            g_free(path);
 
392
            
 
393
            // Translators: This is a label/help text in the [Additional settings] dialog
 
394
            help_text = g_strdup(_("Select one or more devices for recording."));
 
395
            break;
 
396
        }
 
397
 
 
398
        if (!GDK_IS_PIXBUF(pixbuf)) {
 
399
            // No. Load a default icon.
 
400
            gchar *path = get_image_path("mediaplayer.png");
 
401
            pixbuf = get_pixbuf_from_file(path, 22, 22);
 
402
            g_free(path);
 
403
        }
 
404
 
 
405
        // Set column data
 
406
        gtk_list_store_set(GTK_LIST_STORE(model), &iter,
 
407
                           COL_CHECKBOX, 0, /* not used */
 
408
                           COL_TYPE, item->type, /* type */
 
409
                           COL_ID, "", /* not used */
 
410
                           COL_ICON, pixbuf, /* icon pixbuf */
 
411
                           COL_DESCR, descr /* text */,
 
412
                           COL_HELP, help_text /* help text */, -1);
 
413
 
 
414
        // Pixbuf has a reference count of 2 now, as the list store has added its own
 
415
        if (GDK_IS_PIXBUF(pixbuf)) {
 
416
            g_object_unref(pixbuf);
 
417
        }
 
418
        
 
419
        g_free(descr);
 
420
        g_free(help_text);
 
421
 
 
422
        // Next item
 
423
        n = g_list_next(n);
 
424
    }
 
425
 
 
426
    // Free dev_list
 
427
    audio_sources_free_list(dev_list);
 
428
    dev_list = NULL;
 
429
}
 
430
 
 
431
// ----------------------------------------------
 
432
 
 
433
static void device_list_save() {
 
434
    // Save device list in GConf registry (for g_current_type)
 
435
    if (!g_current_type) return;
 
436
 
 
437
    // Remember all changed types (save bit)
 
438
    g_changed_types = g_changed_types | g_current_type;
 
439
 
 
440
    GtkWidget *list_view = g_object_get_data(G_OBJECT(g_dialog), "device-list-widget");
 
441
 
 
442
    GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(list_view));
 
443
    if (!GTK_IS_TREE_MODEL(model)) {
 
444
        return;
 
445
    }
 
446
 
 
447
    // Collect selected devices for g_current_type
 
448
    GList  *selected_devs = NULL;
 
449
 
 
450
    // For each row
 
451
    GtkTreeIter iter;
 
452
    gint ret = gtk_tree_model_get_iter_first(model, &iter);
 
453
    while (ret) {
 
454
        // Read checkbox value and device_id value
 
455
        gint active = 0;
 
456
        gchar *device_id = NULL;
 
457
 
 
458
        gtk_tree_model_get(model, &iter,
 
459
                           COL_CHECKBOX, &active,
 
460
                           COL_ID, &device_id, -1);
 
461
 
 
462
        // Checkbox is checked?
 
463
        if (active) {
 
464
            selected_devs = g_list_append(selected_devs, g_strdup(device_id));
 
465
        }
 
466
 
 
467
        g_free(device_id);
 
468
 
 
469
        // Take next row
 
470
        ret = gtk_tree_model_iter_next(model, &iter);
 
471
    }
 
472
 
 
473
    // Save the list in GSettings (dconf) registry
 
474
    gchar *conf_key = g_strdup_printf("players/device-type-%d", g_current_type);
 
475
 
 
476
    conf_save_string_list(conf_key, selected_devs);
 
477
    // Check this in dconf-editor, key: /apps/audio-recorder/players/
 
478
 
 
479
    g_free(conf_key);
 
480
 
 
481
// MOMA
 
482
#if defined(ACTIVE_DEBUGGING) || defined(DEBUG_ALL)
 
483
    LOG_DEBUG("-------------------\n");
 
484
    const gchar *type_name= device_item_get_type_name(g_current_type);
 
485
    LOG_DEBUG("Selected devices for %s (%d):\n", type_name, g_current_type);
 
486
    str_list_print("Device", selected_devs);
 
487
#endif
 
488
 
 
489
    // Free GList
 
490
    str_list_free(selected_devs);
 
491
    selected_devs = NULL;
 
492
}
 
493
 
 
494
static gboolean is_in_selected_list(gchar *dev_id, GList *dev_list) {
 
495
    // Check if dev_id is in dev_list list
 
496
    GList *n = g_list_first(dev_list);
 
497
    while (n) {
 
498
        if (!g_strcmp0(dev_id, (gchar*)(n->data))) {
 
499
            return TRUE;
 
500
        }
 
501
        n = g_list_next(n);
 
502
    }
 
503
    return FALSE;
 
504
}
 
505
 
 
506
static void device_list_fill() {
 
507
    GtkWidget *list_view = g_object_get_data(G_OBJECT(g_dialog), "device-list-widget");
 
508
 
 
509
    GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(list_view));
 
510
    GtkTreeIter  iter;
 
511
 
 
512
    if (!GTK_IS_TREE_MODEL(model)) {
 
513
        return;
 
514
    }
 
515
 
 
516
    // Get device list for g_current_type
 
517
    GList *selected_list = NULL;
 
518
    if (g_current_type) {
 
519
        // See dconf-editor, key: /apps/audio-recorder/players/
 
520
 
 
521
        gchar *conf_key = g_strdup_printf("players/device-type-%d", g_current_type);
 
522
        conf_get_string_list(conf_key, &selected_list);
 
523
        g_free(conf_key);
 
524
    }
 
525
 
 
526
    // Clear the old list
 
527
    gtk_list_store_clear(GTK_LIST_STORE(model));
 
528
 
 
529
    // Get list of microphones and audio cards
 
530
    GList *dev_list = audio_sources_get_for_type(AUDIO_INPUT/*microphones*/ | AUDIO_SINK_MONITOR/*audio cards*/);
 
531
    // Debug print:
 
532
    // audio_sources_print_list(dev_list, "Device list:");
 
533
 
 
534
    // Add items to the view
 
535
    GList *n = g_list_first(dev_list);
 
536
    while (n) {
 
537
        DeviceItem *item = (DeviceItem*)n->data;
 
538
 
 
539
        // Add new row
 
540
        gtk_list_store_append(GTK_LIST_STORE(model), &iter);
 
541
 
 
542
        // Icon pixbuf
 
543
        gchar *p = item->icon_name;
 
544
        if (!p)
 
545
            p = "loudspeaker.png";
 
546
 
 
547
        gchar *path = get_image_path(p);
 
548
 
 
549
        GdkPixbuf *pixbuf = get_pixbuf_from_file(path, 24, 24);
 
550
 
 
551
        // Check if item->id is in selected_devs list
 
552
        gboolean is_active = is_in_selected_list(item->id, selected_list/*GList*/);
 
553
 
 
554
        // Set column data
 
555
        gtk_list_store_set(GTK_LIST_STORE(model), &iter,
 
556
                           COL_CHECKBOX, is_active, /* row checkbox */
 
557
                           COL_TYPE, 0, /* not used */
 
558
                           COL_ID, item->id, /* device id */
 
559
                           COL_ICON, pixbuf, /* icon pixbuf */
 
560
                           COL_DESCR, item->description, /* visible text */
 
561
                           COL_HELP, "", /* not used */
 
562
                           -1);
 
563
 
 
564
        // Pixbuf has a reference count of 2 now, as the list store has added its own
 
565
        g_object_unref(pixbuf);
 
566
 
 
567
        g_free(path);
 
568
 
 
569
        // Next item
 
570
        n = g_list_next(n);
 
571
    }
 
572
 
 
573
    // Free dev_list
 
574
    audio_sources_free_list(dev_list);
 
575
 
 
576
    // Free selected_list and its data
 
577
    str_list_free(selected_list);
 
578
    selected_list = NULL;
 
579
}
 
580
 
 
581
void player_view_set(const gchar *type_name) {
 
582
    GtkWidget *view = g_object_get_data(G_OBJECT(g_dialog), "player-list-widget");
 
583
 
 
584
    GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
 
585
    if (!GTK_IS_TREE_MODEL(model)) {
 
586
        return;
 
587
    }
 
588
 
 
589
    // For each row
 
590
    GtkTreeIter iter;
 
591
    gint ret = gtk_tree_model_get_iter_first(model, &iter);
 
592
    while (ret) {
 
593
        gint type = -1;
 
594
        gtk_tree_model_get(model, &iter,  COL_TYPE, &type, -1);
 
595
        const gchar *name = device_item_get_type_name(type);
 
596
 
 
597
        if (!g_strcmp0(type_name, (gchar*)name)) {
 
598
            GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
 
599
            gtk_tree_selection_select_iter(selection, &iter);
 
600
            return;
 
601
 
 
602
        }
 
603
 
 
604
        // Take next row
 
605
        ret = gtk_tree_model_iter_next(model, &iter);
 
606
    }
 
607
 
 
608
    // Select first
 
609
    gtk_tree_model_get_iter_from_string(model, &iter, "0");
 
610
    GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
 
611
    gtk_tree_selection_select_iter(selection, &iter);
 
612
}
 
613
 
 
614
void win_settings_show_dialog(GtkWindow *parent) {
 
615
 
 
616
    // Translators: This is a title in the additional settings dialog
 
617
    g_dialog = gtk_dialog_new_with_buttons(_("Additional settings"),
 
618
                                           parent,
 
619
                                           GTK_DIALOG_DESTROY_WITH_PARENT,
 
620
                                           "gtk-cancel", GTK_RESPONSE_REJECT,
 
621
                                           "gtk-ok", GTK_RESPONSE_OK,
 
622
                                           NULL);
 
623
 
 
624
    gtk_window_set_transient_for(GTK_WINDOW(g_dialog), parent);
 
625
 
 
626
    //gtk_window_set_default_size(GTK_WINDOW(g_dialog), 500, 600);
 
627
    gtk_window_set_resizable(GTK_WINDOW(g_dialog), FALSE);
 
628
 
 
629
    gtk_dialog_set_default_response(GTK_DIALOG(g_dialog), GTK_RESPONSE_OK);
 
630
    // ---------------------------------------
 
631
 
 
632
    GtkWidget *content_area = gtk_dialog_get_content_area(GTK_DIALOG(g_dialog));
 
633
 
 
634
    // A notebook with 2 tabs
 
635
    GtkWidget *notebook = gtk_notebook_new();
 
636
    gtk_container_add(GTK_CONTAINER(content_area), notebook);
 
637
 
 
638
    // -----------------------------------
 
639
    // Tab page 0, General
 
640
    // -----------------------------------
 
641
    GtkWidget *vbox0 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 3);
 
642
    // Translators: This is a [Tab-page] in the [Additional settings] dialog.
 
643
    GtkWidget *page_label = gtk_label_new(_("General"));
 
644
 
 
645
    // Create a GtkGrid. 
 
646
    // Ref: http://developer.gnome.org/gtk3/3.3/GtkGrid.html
 
647
    GtkWidget *grid0 = gtk_grid_new();
 
648
    gtk_grid_set_row_homogeneous(GTK_GRID(grid0), FALSE);
 
649
    gtk_grid_set_column_homogeneous(GTK_GRID(grid0), FALSE);
 
650
 
 
651
    gtk_box_pack_start(GTK_BOX(vbox0), grid0, FALSE, TRUE, 0);
 
652
    gtk_grid_set_row_spacing(GTK_GRID(grid0), 3);
 
653
 
 
654
    // "Folder name:" label
 
655
    // Translators: This is a GUI label. Keep it short.
 
656
    GtkWidget *label0 = gtk_label_new(_("Folder name:"));
 
657
 
 
658
    gtk_grid_attach(GTK_GRID(grid0), label0, 0, 0, 1, 1);
 
659
    gtk_misc_set_alignment(GTK_MISC(label0), 0, 0.5);
 
660
 
 
661
    GtkWidget *folder_name_field = gtk_entry_new();
 
662
    gtk_grid_attach(GTK_GRID(grid0), folder_name_field, 1, 0, 5, 1);
 
663
    gtk_entry_set_invisible_char(GTK_ENTRY(folder_name_field), 9679);
 
664
 
 
665
    GtkWidget *button0 = gtk_button_new_with_mnemonic("...");
 
666
    gtk_grid_attach(GTK_GRID(grid0), button0, 6, 0, 1, 1);
 
667
    g_signal_connect(button0, "clicked", G_CALLBACK(win_settings_get_folder_name), folder_name_field);
 
668
 
 
669
    // Get and show current folder name (/home/username/Audio)
 
670
    gchar *folder_name = get_audio_folder();
 
671
    gtk_entry_set_text(GTK_ENTRY(folder_name_field), folder_name);
 
672
    g_free(folder_name);
 
673
 
 
674
    // "Filename format:" label
 
675
    // Translators: This is a GUI label. Keep it short.
 
676
    label0 = gtk_label_new(_("Filename format:"));
 
677
    gtk_grid_attach(GTK_GRID(grid0), label0, 0, 1, 1, 1);
 
678
    gtk_misc_set_alignment(GTK_MISC(label0), 0, 0.5);
 
679
 
 
680
    GtkWidget *file_name_pattern = gtk_entry_new();
 
681
    gtk_grid_attach(GTK_GRID(grid0), file_name_pattern, 1, 1, 5, 1);
 
682
    gtk_entry_set_invisible_char(GTK_ENTRY(file_name_pattern), 9679);
 
683
 
 
684
    button0 = gtk_button_new();
 
685
    GtkWidget *image = gtk_image_new_from_icon_name("gtk-info", GTK_ICON_SIZE_BUTTON);
 
686
    gtk_button_set_image(GTK_BUTTON(button0), image);
 
687
    g_signal_connect(button0, "clicked", G_CALLBACK(win_settings_show_filename_help), NULL);
 
688
    gtk_grid_attach(GTK_GRID(grid0), button0, 6, 1, 1, 1);
 
689
 
 
690
    // Get filename pattern
 
691
    gchar *str_value = get_filename_pattern();
 
692
    gtk_entry_set_text(GTK_ENTRY(file_name_pattern), str_value);
 
693
    g_free(str_value);
 
694
 
 
695
    gboolean bool_val = FALSE;
 
696
 
 
697
    // Create GtkGrid for some GtkSwitch'es
 
698
    GtkWidget *grid1 = gtk_grid_new();
 
699
    gtk_grid_set_row_homogeneous(GTK_GRID(grid1), FALSE);
 
700
 
 
701
    gtk_grid_attach(GTK_GRID(grid0), grid1, 1, 5, 5, 5);
 
702
 
 
703
    // Setting for "Keep window on top?"
 
704
    GtkWidget *keep_top_switch = gtk_switch_new();
 
705
    gtk_grid_attach(GTK_GRID(grid1), keep_top_switch, 0, 0, 1, 1);
 
706
 
 
707
    // Translators: This is a label for an ON/OFF switch.
 
708
    label0 =  gtk_label_new(_("Keep window on top."));
 
709
    gtk_misc_set_alignment(GTK_MISC(label0), 0, 0.5);
 
710
    gtk_misc_set_padding(GTK_MISC(label0), 3, 0);
 
711
    gtk_grid_attach(GTK_GRID(grid1), label0, 1, 0, 4, 1);
 
712
 
 
713
    conf_get_boolean_value("keep-on-top", &bool_val);
 
714
    gtk_switch_set_active(GTK_SWITCH(keep_top_switch), bool_val);
 
715
    g_signal_connect(keep_top_switch, "notify::active", G_CALLBACK(keep_on_top_switch_cb), NULL);
 
716
 
 
717
 
 
718
    // Setting for "Show systray icon"
 
719
    GtkWidget *show_icon_switch = gtk_switch_new();
 
720
    gtk_grid_attach(GTK_GRID(grid1), show_icon_switch, 0, 1, 1, 1);
 
721
 
 
722
    // Translators: This is a label for an ON/OFF switch.
 
723
    label0 =  gtk_label_new(_("Show icon on the system tray."));
 
724
    gtk_misc_set_alignment(GTK_MISC(label0), 0, 0.5);
 
725
    gtk_misc_set_padding(GTK_MISC(label0), 3, 0);
 
726
    gtk_grid_attach(GTK_GRID(grid1), label0, 1, 1, 4, 1);
 
727
 
 
728
    conf_get_boolean_value("show-systray-icon", &bool_val);
 
729
    gtk_switch_set_active(GTK_SWITCH(show_icon_switch), bool_val);
 
730
    g_signal_connect(show_icon_switch, "notify::active", G_CALLBACK(show_icon_switch_cb), NULL);
 
731
 
 
732
    // Setting for "Auto-start application at login"
 
733
    GtkWidget *autostart_switch = gtk_switch_new();
 
734
    gtk_grid_attach(GTK_GRID(grid1), autostart_switch, 0, 2, 1, 1);
 
735
 
 
736
    bool_val = autostart_get();
 
737
    gtk_switch_set_active(GTK_SWITCH(autostart_switch), bool_val);
 
738
    g_signal_connect(autostart_switch, "notify::active", G_CALLBACK(autostart_switch_cb), NULL);
 
739
 
 
740
    // Translators: This is a label for an ON/OFF switch.
 
741
    label0 =  gtk_label_new(_("Auto-start this application at login."));
 
742
    gtk_misc_set_alignment(GTK_MISC(label0), 0, 0.5);
 
743
    gtk_misc_set_padding(GTK_MISC(label0), 3, 0);
 
744
    gtk_grid_attach(GTK_GRID(grid1), label0, 1, 2, 4, 1);
 
745
 
 
746
 
 
747
    // TODO:
 
748
    // This is a fix.
 
749
    // A hard-coded setting for Skype.
 
750
    // We should create a properties class for device items, so they can expose this type of settings without hardcoding.
 
751
    DeviceItem *item = audio_sources_find_id("com.Skype.API");
 
752
    GtkWidget *skype_switch = NULL;
 
753
    if (item) {
 
754
        // Separator line
 
755
        GtkWidget *hseparator0 = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
 
756
        gtk_grid_attach(GTK_GRID(grid1), hseparator0, 0, 3, 1, 1);
 
757
 
 
758
        hseparator0 = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
 
759
        gtk_grid_attach(GTK_GRID(grid1), hseparator0, 1, 3, 4, 1);
 
760
 
 
761
        // Setting for "Record ringing sound for Skype"
 
762
        skype_switch = gtk_switch_new();
 
763
        gtk_grid_attach(GTK_GRID(grid1), skype_switch, 0, 4, 1, 1);
 
764
 
 
765
        // Translators: This is a label for an ON/OFF switch.
 
766
        label0 =  gtk_label_new(_("Record ringing sound for Skype."));
 
767
        gtk_misc_set_alignment(GTK_MISC(label0), 0, 0.5);
 
768
        gtk_misc_set_padding(GTK_MISC(label0), 3, 0);
 
769
        gtk_grid_attach(GTK_GRID(grid1), label0, 1, 4, 4, 1);
 
770
 
 
771
        gboolean bool_val = FALSE;
 
772
        conf_get_boolean_value("skype/record-ringing-sound", &bool_val);
 
773
        gtk_switch_set_active(GTK_SWITCH(skype_switch), bool_val);
 
774
    }
 
775
 
 
776
    // Add new tab page
 
777
    gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox0, page_label);
 
778
 
 
779
    // -----------------------------------------------------
 
780
    // Tab page 1, Device settings for Media Players, Skype
 
781
    // -----------------------------------------------------
 
782
    GtkWidget *vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 3);
 
783
    // Translators: This is a [Tab-page] in the [Additional settings] dialog.
 
784
    page_label = gtk_label_new(_("Device settings"));
 
785
 
 
786
    label0 = gtk_label_new(_("Installed items:"));
 
787
    gtk_misc_set_alignment(GTK_MISC(label0), 0, 0.5);
 
788
    gtk_box_pack_start(GTK_BOX(vbox1), label0, FALSE, FALSE, 0);
 
789
 
 
790
    // Create a listbox (a GtkTreeView) for Media Player, Skype and one line for "User defined devices"
 
791
    GtkWidget *player_view = create_listbox();
 
792
 
 
793
    // COL_CHECKBOX is not used by this view. Hide it.
 
794
    GtkTreeViewColumn *col = gtk_tree_view_get_column(GTK_TREE_VIEW(player_view), COL_CHECKBOX);
 
795
    gtk_tree_view_column_set_visible(col, FALSE);
 
796
 
 
797
    GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(player_view));
 
798
    g_signal_connect(sel, "changed", G_CALLBACK(player_view_row_changed_cb), NULL);
 
799
 
 
800
    // Reset current (selected) type
 
801
    g_current_type = 0;
 
802
    g_changed_types = 0;
 
803
 
 
804
    g_object_set_data(G_OBJECT(g_dialog), "player-list-widget", player_view);
 
805
    gtk_box_pack_start(GTK_BOX(vbox1), player_view, FALSE, FALSE, 0);
 
806
 
 
807
    // Fill the player view
 
808
    player_view_fill();
 
809
 
 
810
    // Separator line
 
811
    GtkWidget *hseparator0 = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
 
812
    gtk_box_pack_start(GTK_BOX(vbox1), hseparator0, TRUE, TRUE, 0);
 
813
 
 
814
    label0 = gtk_label_new("");
 
815
    g_object_set_data(G_OBJECT(g_dialog), "device-label-widget", label0);
 
816
    gtk_misc_set_alignment(GTK_MISC(label0), 0, 0.5);
 
817
    gtk_box_pack_start(GTK_BOX(vbox1), label0, TRUE, TRUE, 0);
 
818
 
 
819
    // Listbox for devices
 
820
    GtkWidget *dev_view = create_listbox();
 
821
    g_object_set_data(G_OBJECT(g_dialog), "device-list-widget", dev_view);
 
822
 
 
823
    gtk_box_pack_start(GTK_BOX(vbox1), dev_view, FALSE, FALSE, 0);
 
824
 
 
825
    // Label for help text
 
826
    label0 = gtk_label_new("");
 
827
    g_object_set_data(G_OBJECT(g_dialog), "player-label-widget", label0);
 
828
    gtk_misc_set_alignment(GTK_MISC(label0), 0, 0.5);
 
829
    gtk_box_pack_start(GTK_BOX(vbox1), label0, TRUE, TRUE, 0);
 
830
 
 
831
    // Get lastly selected device type (set in the main window)
 
832
    gint saved_dev_type = -1;
 
833
    conf_get_int_value("audio-device-type", &saved_dev_type);
 
834
    const gchar *type_name = device_item_get_type_name(saved_dev_type);
 
835
    // Select row in the view
 
836
    player_view_set(type_name);
 
837
 
 
838
    // Add new tab page
 
839
    gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox1, page_label);
 
840
 
 
841
//moma
 
842
    // -----------------------------------------------------
 
843
    // Tab page 2, Page to edit Gstreamer pipelines
 
844
    // -----------------------------------------------------
 
845
    GtkWidget *vbox2 = page_to_edit_pipelines();
 
846
 
 
847
    // Translators: This is a [Tab-page] in the [Additional settings] dialog.
 
848
    page_label = gtk_label_new(_("Recording pipelines"));
 
849
 
 
850
    // Add new tab page
 
851
    gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox2, page_label);
 
852
 
 
853
 
 
854
 
 
855
 
 
856
    // Show dialog
 
857
    gtk_widget_show_all(g_dialog);
 
858
 
 
859
    gint res = gtk_dialog_run(GTK_DIALOG(g_dialog));
 
860
 
 
861
    switch (res) {
 
862
    case GTK_RESPONSE_ACCEPT:
 
863
    case GTK_RESPONSE_OK: {
 
864
        // Save folder name
 
865
        gchar *str_value = (gchar*)gtk_entry_get_text(GTK_ENTRY(folder_name_field));
 
866
        conf_save_string_value("folder-name", str_value);
 
867
        // Do not g_free() str_value
 
868
        // Ref: http://library.gnome.org/devel/gtk/unstable/GtkEntry.html#gtk-entry-get-text
 
869
 
 
870
        // Save filename pattern
 
871
        str_value = (gchar*)gtk_entry_get_text(GTK_ENTRY(file_name_pattern));
 
872
        conf_save_string_value("filename-pattern", str_value);
 
873
        // Do not g_free() str_value
 
874
 
 
875
        // Device types changed (bitwise test)?
 
876
        if ((g_changed_types & saved_dev_type) != 0) {
 
877
            // Let timer know that the settings have been altered, so it 
 
878
            // can re-load commands and re-start the VAD (in gst-vad.c).
 
879
            timer_settings_changed();
 
880
        }
 
881
 
 
882
        // Record ringing sound for Skype?
 
883
        if (GTK_IS_SWITCH(skype_switch)) {
 
884
            bool_val = gtk_switch_get_active(GTK_SWITCH(skype_switch));
 
885
            // Save value
 
886
            skype_set_record_ringing_sound(bool_val);
 
887
        }
 
888
    }
 
889
    break;
 
890
 
 
891
 
 
892
    default:
 
893
        break;
 
894
    }
 
895
 
 
896
    g_current_type = 0;
 
897
    g_changed_types = 0;
 
898
 
 
899
    // Destroy this dialog
 
900
    if (GTK_IS_WIDGET(g_dialog)) {
 
901
        gtk_widget_destroy(GTK_WIDGET(g_dialog));
 
902
    }
 
903
    g_dialog = NULL;
 
904
}
 
905