From 5a3083d23ab4cc54f43034d42d4f62707fab623b Mon Sep 17 00:00:00 2001 From: "raveit65 (via Travis CI)" Date: Tue, 18 Aug 2020 17:06:55 +0000 Subject: Deploy mate-desktop/mate-media to github.com/mate-desktop/mate-media.git:gh-pages --- .../0.html | 1038 +++++++++ .../1.html | 2368 +++++++++++++++++++ .../2.html | 1110 +++++++++ .../index.html | 108 + .../stats.html | 93 + .../style.css | 149 ++ .../0.html | 1038 +++++++++ .../1.html | 2368 +++++++++++++++++++ .../2.html | 1110 +++++++++ .../index.html | 108 + .../stats.html | 93 + .../style.css | 149 ++ .../0.html | 1038 +++++++++ .../1.html | 2368 +++++++++++++++++++ .../2.html | 1110 +++++++++ .../index.html | 108 + .../stats.html | 93 + .../style.css | 149 ++ .../0.html | 1038 +++++++++ .../1.html | 2368 +++++++++++++++++++ .../2.html | 1110 +++++++++ .../index.html | 108 + .../stats.html | 93 + .../style.css | 149 ++ .../0.html | 1038 +++++++++ .../1.html | 2368 +++++++++++++++++++ .../2.html | 1110 +++++++++ .../index.html | 108 + .../stats.html | 93 + .../style.css | 149 ++ .../0.html | 1038 +++++++++ .../1.html | 2368 +++++++++++++++++++ .../2.html | 1110 +++++++++ .../index.html | 108 + .../stats.html | 93 + .../style.css | 149 ++ .../0.html | 1038 +++++++++ .../1.html | 2368 +++++++++++++++++++ .../2.html | 1110 +++++++++ .../index.html | 108 + .../stats.html | 93 + .../style.css | 149 ++ .../0.html | 1038 +++++++++ .../1.html | 2368 +++++++++++++++++++ .../2.html | 1110 +++++++++ .../index.html | 108 + .../stats.html | 93 + .../style.css | 149 ++ .../0.html | 1038 +++++++++ .../1.html | 2368 +++++++++++++++++++ .../2.html | 1110 +++++++++ .../index.html | 108 + .../stats.html | 93 + .../style.css | 149 ++ .../0.html | 1038 +++++++++ .../1.html | 2368 +++++++++++++++++++ .../2.html | 1110 +++++++++ .../index.html | 108 + .../stats.html | 93 + .../style.css | 149 ++ .../0.html | 1038 +++++++++ .../1.html | 2368 +++++++++++++++++++ .../2.html | 1110 +++++++++ .../index.html | 108 + .../stats.html | 93 + .../style.css | 149 ++ .../0.html | 1038 +++++++++ .../1.html | 2368 +++++++++++++++++++ .../2.html | 1110 +++++++++ .../index.html | 108 + .../stats.html | 93 + .../style.css | 149 ++ .../0.html | 1038 +++++++++ .../1.html | 2368 +++++++++++++++++++ .../2.html | 1110 +++++++++ .../index.html | 108 + .../stats.html | 93 + .../style.css | 149 ++ .../0.html | 1038 +++++++++ .../1.html | 2368 +++++++++++++++++++ .../2.html | 1110 +++++++++ .../index.html | 108 + .../stats.html | 93 + .../style.css | 149 ++ .../0.html | 1038 +++++++++ .../1.html | 2368 +++++++++++++++++++ .../2.html | 1110 +++++++++ .../index.html | 108 + .../stats.html | 93 + .../style.css | 149 ++ .../0.html | 1038 +++++++++ .../1.html | 2368 +++++++++++++++++++ .../2.html | 1110 +++++++++ .../index.html | 108 + .../stats.html | 93 + .../style.css | 149 ++ .../0.html | 1054 +++++++++ .../1.html | 2384 ++++++++++++++++++++ .../2.html | 1126 +++++++++ .../index.html | 124 + .../stats.html | 109 + .../style.css | 137 ++ .../0.html | 1054 +++++++++ .../1.html | 2384 ++++++++++++++++++++ .../2.html | 1126 +++++++++ .../index.html | 124 + .../stats.html | 109 + .../style.css | 137 ++ .../0.html | 1054 +++++++++ .../1.html | 2384 ++++++++++++++++++++ .../2.html | 1126 +++++++++ .../index.html | 124 + .../stats.html | 109 + .../style.css | 137 ++ .../0.html | 1054 +++++++++ .../1.html | 2384 ++++++++++++++++++++ .../2.html | 1126 +++++++++ .../index.html | 124 + .../stats.html | 109 + .../style.css | 137 ++ CNAME | 1 + index.html | 47 + 122 files changed, 97640 insertions(+) create mode 100644 2020-04-09-114613-2421-cppcheck@b19fbdc7119f_master/0.html create mode 100644 2020-04-09-114613-2421-cppcheck@b19fbdc7119f_master/1.html create mode 100644 2020-04-09-114613-2421-cppcheck@b19fbdc7119f_master/2.html create mode 100644 2020-04-09-114613-2421-cppcheck@b19fbdc7119f_master/index.html create mode 100644 2020-04-09-114613-2421-cppcheck@b19fbdc7119f_master/stats.html create mode 100644 2020-04-09-114613-2421-cppcheck@b19fbdc7119f_master/style.css create mode 100644 2020-04-09-124106-6009-cppcheck@49d783c683ff_enum-conversion/0.html create mode 100644 2020-04-09-124106-6009-cppcheck@49d783c683ff_enum-conversion/1.html create mode 100644 2020-04-09-124106-6009-cppcheck@49d783c683ff_enum-conversion/2.html create mode 100644 2020-04-09-124106-6009-cppcheck@49d783c683ff_enum-conversion/index.html create mode 100644 2020-04-09-124106-6009-cppcheck@49d783c683ff_enum-conversion/stats.html create mode 100644 2020-04-09-124106-6009-cppcheck@49d783c683ff_enum-conversion/style.css create mode 100644 2020-04-10-141956-3126-cppcheck@de1524253905_master/0.html create mode 100644 2020-04-10-141956-3126-cppcheck@de1524253905_master/1.html create mode 100644 2020-04-10-141956-3126-cppcheck@de1524253905_master/2.html create mode 100644 2020-04-10-141956-3126-cppcheck@de1524253905_master/index.html create mode 100644 2020-04-10-141956-3126-cppcheck@de1524253905_master/stats.html create mode 100644 2020-04-10-141956-3126-cppcheck@de1524253905_master/style.css create mode 100644 2020-04-19-141137-3704-cppcheck@7dca88a484ae_master/0.html create mode 100644 2020-04-19-141137-3704-cppcheck@7dca88a484ae_master/1.html create mode 100644 2020-04-19-141137-3704-cppcheck@7dca88a484ae_master/2.html create mode 100644 2020-04-19-141137-3704-cppcheck@7dca88a484ae_master/index.html create mode 100644 2020-04-19-141137-3704-cppcheck@7dca88a484ae_master/stats.html create mode 100644 2020-04-19-141137-3704-cppcheck@7dca88a484ae_master/style.css create mode 100644 2020-04-21-011735-7455-cppcheck@e864ce9bb951_travis/0.html create mode 100644 2020-04-21-011735-7455-cppcheck@e864ce9bb951_travis/1.html create mode 100644 2020-04-21-011735-7455-cppcheck@e864ce9bb951_travis/2.html create mode 100644 2020-04-21-011735-7455-cppcheck@e864ce9bb951_travis/index.html create mode 100644 2020-04-21-011735-7455-cppcheck@e864ce9bb951_travis/stats.html create mode 100644 2020-04-21-011735-7455-cppcheck@e864ce9bb951_travis/style.css create mode 100644 2020-04-21-012206-8805-cppcheck@d4487123b370_travis/0.html create mode 100644 2020-04-21-012206-8805-cppcheck@d4487123b370_travis/1.html create mode 100644 2020-04-21-012206-8805-cppcheck@d4487123b370_travis/2.html create mode 100644 2020-04-21-012206-8805-cppcheck@d4487123b370_travis/index.html create mode 100644 2020-04-21-012206-8805-cppcheck@d4487123b370_travis/stats.html create mode 100644 2020-04-21-012206-8805-cppcheck@d4487123b370_travis/style.css create mode 100644 2020-04-21-012601-6120-cppcheck@11fc77a34034_travis/0.html create mode 100644 2020-04-21-012601-6120-cppcheck@11fc77a34034_travis/1.html create mode 100644 2020-04-21-012601-6120-cppcheck@11fc77a34034_travis/2.html create mode 100644 2020-04-21-012601-6120-cppcheck@11fc77a34034_travis/index.html create mode 100644 2020-04-21-012601-6120-cppcheck@11fc77a34034_travis/stats.html create mode 100644 2020-04-21-012601-6120-cppcheck@11fc77a34034_travis/style.css create mode 100644 2020-04-21-013643-7310-cppcheck@85e50bb1e8b0_master/0.html create mode 100644 2020-04-21-013643-7310-cppcheck@85e50bb1e8b0_master/1.html create mode 100644 2020-04-21-013643-7310-cppcheck@85e50bb1e8b0_master/2.html create mode 100644 2020-04-21-013643-7310-cppcheck@85e50bb1e8b0_master/index.html create mode 100644 2020-04-21-013643-7310-cppcheck@85e50bb1e8b0_master/stats.html create mode 100644 2020-04-21-013643-7310-cppcheck@85e50bb1e8b0_master/style.css create mode 100644 2020-04-25-161832-9866-cppcheck@0de220f56e3d_master/0.html create mode 100644 2020-04-25-161832-9866-cppcheck@0de220f56e3d_master/1.html create mode 100644 2020-04-25-161832-9866-cppcheck@0de220f56e3d_master/2.html create mode 100644 2020-04-25-161832-9866-cppcheck@0de220f56e3d_master/index.html create mode 100644 2020-04-25-161832-9866-cppcheck@0de220f56e3d_master/stats.html create mode 100644 2020-04-25-161832-9866-cppcheck@0de220f56e3d_master/style.css create mode 100644 2020-06-17-120043-0378-cppcheck@7a8fcf3b18bf_master/0.html create mode 100644 2020-06-17-120043-0378-cppcheck@7a8fcf3b18bf_master/1.html create mode 100644 2020-06-17-120043-0378-cppcheck@7a8fcf3b18bf_master/2.html create mode 100644 2020-06-17-120043-0378-cppcheck@7a8fcf3b18bf_master/index.html create mode 100644 2020-06-17-120043-0378-cppcheck@7a8fcf3b18bf_master/stats.html create mode 100644 2020-06-17-120043-0378-cppcheck@7a8fcf3b18bf_master/style.css create mode 100644 2020-06-22-145654-0244-cppcheck@3eda50f90193_travis-ci/0.html create mode 100644 2020-06-22-145654-0244-cppcheck@3eda50f90193_travis-ci/1.html create mode 100644 2020-06-22-145654-0244-cppcheck@3eda50f90193_travis-ci/2.html create mode 100644 2020-06-22-145654-0244-cppcheck@3eda50f90193_travis-ci/index.html create mode 100644 2020-06-22-145654-0244-cppcheck@3eda50f90193_travis-ci/stats.html create mode 100644 2020-06-22-145654-0244-cppcheck@3eda50f90193_travis-ci/style.css create mode 100644 2020-06-26-095009-5434-cppcheck@7f8975cc6d8d_master/0.html create mode 100644 2020-06-26-095009-5434-cppcheck@7f8975cc6d8d_master/1.html create mode 100644 2020-06-26-095009-5434-cppcheck@7f8975cc6d8d_master/2.html create mode 100644 2020-06-26-095009-5434-cppcheck@7f8975cc6d8d_master/index.html create mode 100644 2020-06-26-095009-5434-cppcheck@7f8975cc6d8d_master/stats.html create mode 100644 2020-06-26-095009-5434-cppcheck@7f8975cc6d8d_master/style.css create mode 100644 2020-06-29-181100-6971-cppcheck@ea7fcb89ced5_on_notebook_scroll_event/0.html create mode 100644 2020-06-29-181100-6971-cppcheck@ea7fcb89ced5_on_notebook_scroll_event/1.html create mode 100644 2020-06-29-181100-6971-cppcheck@ea7fcb89ced5_on_notebook_scroll_event/2.html create mode 100644 2020-06-29-181100-6971-cppcheck@ea7fcb89ced5_on_notebook_scroll_event/index.html create mode 100644 2020-06-29-181100-6971-cppcheck@ea7fcb89ced5_on_notebook_scroll_event/stats.html create mode 100644 2020-06-29-181100-6971-cppcheck@ea7fcb89ced5_on_notebook_scroll_event/style.css create mode 100644 2020-06-29-181553-0160-cppcheck@7993c4636f49_on_notebook_scroll_event/0.html create mode 100644 2020-06-29-181553-0160-cppcheck@7993c4636f49_on_notebook_scroll_event/1.html create mode 100644 2020-06-29-181553-0160-cppcheck@7993c4636f49_on_notebook_scroll_event/2.html create mode 100644 2020-06-29-181553-0160-cppcheck@7993c4636f49_on_notebook_scroll_event/index.html create mode 100644 2020-06-29-181553-0160-cppcheck@7993c4636f49_on_notebook_scroll_event/stats.html create mode 100644 2020-06-29-181553-0160-cppcheck@7993c4636f49_on_notebook_scroll_event/style.css create mode 100644 2020-07-08-164015-4803-cppcheck@5ba75b44b5f8_master/0.html create mode 100644 2020-07-08-164015-4803-cppcheck@5ba75b44b5f8_master/1.html create mode 100644 2020-07-08-164015-4803-cppcheck@5ba75b44b5f8_master/2.html create mode 100644 2020-07-08-164015-4803-cppcheck@5ba75b44b5f8_master/index.html create mode 100644 2020-07-08-164015-4803-cppcheck@5ba75b44b5f8_master/stats.html create mode 100644 2020-07-08-164015-4803-cppcheck@5ba75b44b5f8_master/style.css create mode 100644 2020-07-11-174721-5648-cppcheck@b755fd7fe3c4_master/0.html create mode 100644 2020-07-11-174721-5648-cppcheck@b755fd7fe3c4_master/1.html create mode 100644 2020-07-11-174721-5648-cppcheck@b755fd7fe3c4_master/2.html create mode 100644 2020-07-11-174721-5648-cppcheck@b755fd7fe3c4_master/index.html create mode 100644 2020-07-11-174721-5648-cppcheck@b755fd7fe3c4_master/stats.html create mode 100644 2020-07-11-174721-5648-cppcheck@b755fd7fe3c4_master/style.css create mode 100644 2020-08-14-155418-9073-cppcheck@acc599546ad3_master/0.html create mode 100644 2020-08-14-155418-9073-cppcheck@acc599546ad3_master/1.html create mode 100644 2020-08-14-155418-9073-cppcheck@acc599546ad3_master/2.html create mode 100644 2020-08-14-155418-9073-cppcheck@acc599546ad3_master/index.html create mode 100644 2020-08-14-155418-9073-cppcheck@acc599546ad3_master/stats.html create mode 100644 2020-08-14-155418-9073-cppcheck@acc599546ad3_master/style.css create mode 100644 2020-08-18-164117-7831-cppcheck@af4178682b21_master/0.html create mode 100644 2020-08-18-164117-7831-cppcheck@af4178682b21_master/1.html create mode 100644 2020-08-18-164117-7831-cppcheck@af4178682b21_master/2.html create mode 100644 2020-08-18-164117-7831-cppcheck@af4178682b21_master/index.html create mode 100644 2020-08-18-164117-7831-cppcheck@af4178682b21_master/stats.html create mode 100644 2020-08-18-164117-7831-cppcheck@af4178682b21_master/style.css create mode 100644 2020-08-18-170145-8061-cppcheck@c82f5feb6c8f_master/0.html create mode 100644 2020-08-18-170145-8061-cppcheck@c82f5feb6c8f_master/1.html create mode 100644 2020-08-18-170145-8061-cppcheck@c82f5feb6c8f_master/2.html create mode 100644 2020-08-18-170145-8061-cppcheck@c82f5feb6c8f_master/index.html create mode 100644 2020-08-18-170145-8061-cppcheck@c82f5feb6c8f_master/stats.html create mode 100644 2020-08-18-170145-8061-cppcheck@c82f5feb6c8f_master/style.css create mode 100644 2020-08-18-170623-4816-cppcheck@c82f5feb6c8f_v1.25.0/0.html create mode 100644 2020-08-18-170623-4816-cppcheck@c82f5feb6c8f_v1.25.0/1.html create mode 100644 2020-08-18-170623-4816-cppcheck@c82f5feb6c8f_v1.25.0/2.html create mode 100644 2020-08-18-170623-4816-cppcheck@c82f5feb6c8f_v1.25.0/index.html create mode 100644 2020-08-18-170623-4816-cppcheck@c82f5feb6c8f_v1.25.0/stats.html create mode 100644 2020-08-18-170623-4816-cppcheck@c82f5feb6c8f_v1.25.0/style.css create mode 100644 CNAME create mode 100644 index.html diff --git a/2020-04-09-114613-2421-cppcheck@b19fbdc7119f_master/0.html b/2020-04-09-114613-2421-cppcheck@b19fbdc7119f_master/0.html new file mode 100644 index 0000000..e262ed0 --- /dev/null +++ b/2020-04-09-114613-2421-cppcheck@b19fbdc7119f_master/0.html @@ -0,0 +1,1038 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-combo-box.h"
+
+struct _GvcComboBoxPrivate
+{
+        GtkWidget       *drop_box;
+        GtkWidget       *start_box;
+        GtkWidget       *end_box;
+        GtkWidget       *label;
+        GtkWidget       *button;
+        GtkTreeModel    *model;
+        GtkWidget       *combobox;
+        MateMixerSwitch *swtch;
+};
+
+enum {
+        COL_NAME,
+        COL_HUMAN_NAME,
+        NUM_COLS
+};
+
+enum {
+        CHANGING,
+        BUTTON_CLICKED,
+        LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+enum {
+        PROP_0,
+        PROP_SWITCH,
+        PROP_LABEL,
+        PROP_SHOW_BUTTON,
+        PROP_BUTTON_LABEL,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_combo_box_dispose    (GObject          *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcComboBox, gvc_combo_box, GTK_TYPE_BOX)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+MateMixerSwitch *
+gvc_combo_box_get_switch (GvcComboBox *combobox)
+{
+        g_return_val_if_fail (GVC_IS_COMBO_BOX (combobox), NULL);
+
+        return combobox->priv->swtch;
+}
+
+void
+gvc_combo_box_set_size_group (GvcComboBox  *combobox,
+                              GtkSizeGroup *group,
+                              gboolean      symmetric)
+{
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (GTK_IS_SIZE_GROUP (group));
+
+        if (group != NULL) {
+                gtk_size_group_add_widget (group, combobox->priv->start_box);
+                if (symmetric == TRUE)
+                        gtk_size_group_add_widget (group, combobox->priv->end_box);
+        }
+        gtk_widget_queue_draw (GTK_WIDGET (combobox));
+}
+
+static void
+on_switch_active_option_notify (MateMixerSwitch *swtch,
+                                GParamSpec      *pspec,
+                                GvcComboBox     *combobox)
+{
+        GtkTreeIter            iter;
+        MateMixerSwitchOption *active;
+        gboolean               cont;
+        const gchar           *name;
+
+        active = mate_mixer_switch_get_active_option (swtch);
+        if (G_UNLIKELY (active == NULL)) {
+                g_warn_if_reached ();
+                return;
+        }
+
+        /* Select the newly activated switch option in the combo box */
+        name = mate_mixer_switch_option_get_name (active);
+        cont = gtk_tree_model_get_iter_first (combobox->priv->model, &iter);
+        while (cont == TRUE) {
+                gchar *current;
+
+                gtk_tree_model_get (combobox->priv->model, &iter,
+                                    COL_NAME, &current,
+                                    -1);
+                if (g_strcmp0 (name, current) == 0) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox), &iter);
+                        g_free (current);
+                        return;
+                }
+                g_free (current);
+
+                cont = gtk_tree_model_iter_next (combobox->priv->model, &iter);
+        }
+        g_warning ("Could not find switch option '%s' in combo box", name);
+}
+
+static void
+gvc_combo_box_set_switch (GvcComboBox *combobox, MateMixerSwitch *swtch)
+{
+        MateMixerSwitchOption *active;
+        const GList           *options;
+
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (MATE_MIXER_IS_SWITCH (swtch));
+
+        combobox->priv->swtch = g_object_ref (swtch);
+
+        active  = mate_mixer_switch_get_active_option (swtch);
+        options = mate_mixer_switch_list_options (swtch);
+        while (options != NULL) {
+                GtkTreeIter            iter;
+                MateMixerSwitchOption *option = MATE_MIXER_SWITCH_OPTION (options->data);
+
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (combobox->priv->model),
+                                                   &iter,
+                                                   G_MAXINT,
+                                                   COL_NAME,
+                                                   mate_mixer_switch_option_get_name (option),
+                                                   COL_HUMAN_NAME,
+                                                   mate_mixer_switch_option_get_label (option),
+                                                   -1);
+
+                /* Select the currently active option of the switch */
+                if (option == active) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox),
+                                                       &iter);
+                }
+                options = options->next;
+        }
+
+        g_signal_connect (G_OBJECT (swtch),
+                          "notify::active-option",
+                          G_CALLBACK (on_switch_active_option_notify),
+                          combobox);
+}
+
+static void
+gvc_combo_box_set_property (GObject       *object,
+                            guint          prop_id,
+                            const GValue  *value,
+                            GParamSpec    *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                gvc_combo_box_set_switch (self, g_value_get_object (value));
+                break;
+        case PROP_LABEL:
+                gtk_label_set_text_with_mnemonic (GTK_LABEL (self->priv->label), g_value_get_string (value));
+                break;
+        case PROP_BUTTON_LABEL:
+                gtk_button_set_label (GTK_BUTTON (self->priv->button), g_value_get_string (value));
+                break;
+        case PROP_SHOW_BUTTON:
+                gtk_widget_set_visible (self->priv->button, g_value_get_boolean (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_get_property (GObject     *object,
+                            guint        prop_id,
+                            GValue      *value,
+                            GParamSpec  *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                g_value_set_object (value, self->priv->swtch);
+                break;
+        case PROP_LABEL:
+                g_value_set_string (value, gtk_label_get_text (GTK_LABEL (self->priv->label)));
+                break;
+        case PROP_BUTTON_LABEL:
+                g_value_set_string (value, gtk_button_get_label (GTK_BUTTON (self->priv->button)));
+                break;
+        case PROP_SHOW_BUTTON:
+                g_value_set_boolean (value, gtk_widget_get_visible (self->priv->button));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_class_init (GvcComboBoxClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_combo_box_dispose;
+        object_class->set_property = gvc_combo_box_set_property;
+        object_class->get_property = gvc_combo_box_get_property;
+
+        properties[PROP_SWITCH] =
+                g_param_spec_object ("switch",
+                                     "switch",
+                                     "The MateMixerSwitch",
+                                     MATE_MIXER_TYPE_SWITCH,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_LABEL] =
+                g_param_spec_string ("label",
+                                     "label",
+                                     "The combo box label",
+                                     _("_Profile:"),
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_SHOW_BUTTON] =
+                g_param_spec_boolean ("show-button",
+                                      "show-button",
+                                      "Whether to show the button",
+                                      FALSE,
+                                      G_PARAM_READWRITE |
+                                      G_PARAM_CONSTRUCT |
+                                      G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_BUTTON_LABEL] =
+                g_param_spec_string ("button-label",
+                                     "button-label",
+                                     "The button's label",
+                                     "",
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+
+        signals[CHANGING] =
+                g_signal_new ("changing",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, changing),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__OBJECT,
+                              G_TYPE_NONE,
+                              1,
+                              MATE_MIXER_TYPE_SWITCH_OPTION);
+
+        signals[BUTTON_CLICKED] =
+                g_signal_new ("button-clicked",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, button_clicked),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
+}
+
+static void
+on_combo_box_changed (GtkComboBox *widget, GvcComboBox *combobox)
+{
+        GtkTreeIter            iter;
+        gchar                 *name;
+        MateMixerSwitchOption *option;
+
+        if (G_UNLIKELY (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter) == FALSE))
+                return;
+
+        gtk_tree_model_get (combobox->priv->model, &iter,
+                            COL_NAME, &name,
+                            -1);
+
+        option = mate_mixer_switch_get_option (combobox->priv->swtch, name);
+        if (G_UNLIKELY (option == NULL)) {
+                g_warn_if_reached ();
+                g_free (name);
+                return;
+        }
+
+        /* Inform that we are about to change the active option of the switch */
+        g_signal_emit (combobox, signals[CHANGING], 0, option);
+
+        mate_mixer_switch_set_active_option (combobox->priv->swtch, option);
+        g_free (name);
+}
+
+static void
+on_combo_box_button_clicked (GtkButton *button, GvcComboBox *combobox)
+{
+        /* The meaning of the button is defined by the owner, so only notify
+         * when it is clicked on */
+        g_signal_emit (combobox, signals[BUTTON_CLICKED], 0);
+}
+
+static void
+gvc_combo_box_init (GvcComboBox *combobox)
+{
+        GtkWidget       *frame;
+        GtkCellRenderer *renderer;
+
+        frame = gtk_frame_new (NULL);
+        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
+
+        combobox->priv = gvc_combo_box_get_instance_private (combobox);
+
+        combobox->priv->model = GTK_TREE_MODEL (gtk_list_store_new (NUM_COLS,
+                                                                    G_TYPE_STRING,
+                                                                    G_TYPE_STRING));
+
+        combobox->priv->combobox = gtk_combo_box_new_with_model (combobox->priv->model);
+
+        combobox->priv->label = gtk_label_new (NULL);
+
+        gtk_label_set_xalign (GTK_LABEL (combobox->priv->label), 0.0);
+        gtk_label_set_yalign (GTK_LABEL (combobox->priv->label), 0.5);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (combobox->priv->label),
+                                       combobox->priv->combobox);
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                    renderer,
+                                    FALSE);
+        gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                       renderer,
+                                       "text",
+                                       COL_HUMAN_NAME);
+
+        combobox->priv->drop_box  = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->start_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->end_box   = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+        /* Make sure the combo box does not get too long on long profile names */
+        g_object_set (G_OBJECT (renderer),
+                      "ellipsize",
+                      PANGO_ELLIPSIZE_END,
+                      NULL);
+
+        gtk_combo_box_set_popup_fixed_width (GTK_COMBO_BOX (combobox->priv->combobox), FALSE);
+
+        gtk_box_pack_start (GTK_BOX (combobox),
+                            frame,
+                            TRUE, TRUE, 0);
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->start_box,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->start_box),
+                            combobox->priv->label,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->combobox,
+                            TRUE, TRUE, 0);
+
+        combobox->priv->button = gtk_button_new_with_label ("");
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->button,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->end_box,
+                            FALSE, FALSE, 0);
+
+        gtk_container_add (GTK_CONTAINER (frame), combobox->priv->drop_box);
+
+        g_signal_connect (G_OBJECT (combobox->priv->combobox),
+                          "changed",
+                          G_CALLBACK (on_combo_box_changed),
+                          combobox);
+        g_signal_connect (G_OBJECT (combobox->priv->button),
+                          "clicked",
+                          G_CALLBACK (on_combo_box_button_clicked),
+                          combobox);
+
+        gtk_widget_set_no_show_all (combobox->priv->button, TRUE);
+        gtk_widget_show_all (frame);
+}
+
+static void
+gvc_combo_box_dispose (GObject *object)
+{
+        GvcComboBox *combobox;
+
+        combobox = GVC_COMBO_BOX (object);
+
+        if (G_LIKELY (combobox->priv->swtch != NULL)) {
+                g_signal_handlers_disconnect_by_func (G_OBJECT (combobox->priv->swtch),
+                                                      G_CALLBACK (on_switch_active_option_notify),
+                                                      combobox);
+                g_clear_object (&combobox->priv->swtch);
+        }
+
+        g_clear_object (&combobox->priv->model);
+
+        G_OBJECT_CLASS (gvc_combo_box_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_combo_box_new (MateMixerSwitch *swtch, const gchar *label)
+{
+        return g_object_new (GVC_TYPE_COMBO_BOX,
+                             "switch", swtch,
+                             "label", label,
+                             "orientation", GTK_ORIENTATION_HORIZONTAL,
+                             NULL);
+}
+
+
+
+ + + diff --git a/2020-04-09-114613-2421-cppcheck@b19fbdc7119f_master/1.html b/2020-04-09-114613-2421-cppcheck@b19fbdc7119f_master/1.html new file mode 100644 index 0000000..67179f2 --- /dev/null +++ b/2020-04-09-114613-2421-cppcheck@b19fbdc7119f_master/1.html @@ -0,0 +1,2368 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
+ * Copyright (C) 2008 William Jon McCann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <utime.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+#include <canberra-gtk.h>
+#include <libxml/tree.h>
+
+#include "gvc-sound-theme-chooser.h"
+#include "sound-theme-file-utils.h"
+
+struct GvcSoundThemeChooserPrivate
+{
+        GtkWidget *combo_box;
+        GtkWidget *treeview;
+        GtkWidget *theme_box;
+        GtkWidget *selection_box;
+        GtkWidget *click_feedback_button;
+        GSettings *sound_settings;
+};
+
+static void     gvc_sound_theme_chooser_dispose   (GObject            *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSoundThemeChooser, gvc_sound_theme_chooser, GTK_TYPE_BOX)
+
+#define KEY_SOUNDS_SCHEMA          "org.mate.sound"
+#define EVENT_SOUNDS_KEY           "event-sounds"
+#define INPUT_SOUNDS_KEY           "input-feedback-sounds"
+#define SOUND_THEME_KEY            "theme-name"
+
+#define DEFAULT_ALERT_ID        "__default"
+#define CUSTOM_THEME_NAME       "__custom"
+#define NO_SOUNDS_THEME_NAME    "__no_sounds"
+
+enum {
+        THEME_DISPLAY_COL,
+        THEME_IDENTIFIER_COL,
+        THEME_PARENT_ID_COL,
+        THEME_NUM_COLS
+};
+
+enum {
+        ALERT_DISPLAY_COL,
+        ALERT_IDENTIFIER_COL,
+        ALERT_SOUND_TYPE_COL,
+        ALERT_ACTIVE_COL,
+        ALERT_NUM_COLS
+};
+
+enum {
+        SOUND_TYPE_UNSET,
+        SOUND_TYPE_OFF,
+        SOUND_TYPE_DEFAULT_FROM_THEME,
+        SOUND_TYPE_BUILTIN,
+        SOUND_TYPE_CUSTOM
+};
+
+static void
+on_combobox_changed (GtkComboBox          *widget,
+                     GvcSoundThemeChooser *chooser)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        char         *theme_name;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &theme_name, -1);
+
+        g_assert (theme_name != NULL);
+
+        /* It is necessary to update the theme name before any other setting as
+         * the "changed" notification will reload the contents of the widget */
+        g_settings_set_string (chooser->priv->sound_settings, SOUND_THEME_KEY, theme_name);
+
+        /* special case for no sounds */
+        if (strcmp (theme_name, NO_SOUNDS_THEME_NAME) == 0) {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, FALSE);
+                return;
+        } else {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, TRUE);
+        }
+
+        g_free (theme_name);
+
+        /* FIXME: reset alert model */
+}
+
+static char *
+load_index_theme_name (const char *index,
+                       char      **parent)
+{
+        GKeyFile *file;
+        char *indexname = NULL;
+        gboolean hidden;
+
+        file = g_key_file_new ();
+        if (g_key_file_load_from_file (file, index, G_KEY_FILE_KEEP_TRANSLATIONS, NULL) == FALSE) {
+                g_key_file_free (file);
+                return NULL;
+        }
+        /* Don't add hidden themes to the list */
+        hidden = g_key_file_get_boolean (file, "Sound Theme", "Hidden", NULL);
+        if (!hidden) {
+                indexname = g_key_file_get_locale_string (file,
+                                                          "Sound Theme",
+                                                          "Name",
+                                                          NULL,
+                                                          NULL);
+
+                /* Save the parent theme, if there's one */
+                if (parent != NULL) {
+                        *parent = g_key_file_get_string (file,
+                                                         "Sound Theme",
+                                                         "Inherits",
+                                                         NULL);
+                }
+        }
+
+        g_key_file_free (file);
+        return indexname;
+}
+
+static void
+sound_theme_in_dir (GHashTable *hash,
+                    const char *dir)
+{
+        GDir *d;
+        const char *name;
+
+        d = g_dir_open (dir, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *dirname, *index, *indexname;
+
+                /* Look for directories */
+                dirname = g_build_filename (dir, name, NULL);
+                if (g_file_test (dirname, G_FILE_TEST_IS_DIR) == FALSE) {
+                        g_free (dirname);
+                        continue;
+                }
+
+                /* Look for index files */
+                index = g_build_filename (dirname, "index.theme", NULL);
+                g_free (dirname);
+
+                /* Check the name of the theme in the index.theme file */
+                indexname = load_index_theme_name (index, NULL);
+                g_free (index);
+                if (indexname == NULL) {
+                        continue;
+                }
+
+                g_hash_table_insert (hash, g_strdup (name), indexname);
+        }
+
+        g_dir_close (d);
+}
+
+static void
+add_theme_to_store (const char   *key,
+                    const char   *value,
+                    GtkListStore *store)
+{
+        char *parent;
+
+        parent = NULL;
+
+        /* Get the parent, if we're checking the custom theme */
+        if (strcmp (key, CUSTOM_THEME_NAME) == 0) {
+                char *name, *path;
+
+                path = custom_theme_dir_path ("index.theme");
+                name = load_index_theme_name (path, &parent);
+                g_free (name);
+                g_free (path);
+        }
+        gtk_list_store_insert_with_values (store, NULL, G_MAXINT,
+                                           THEME_DISPLAY_COL, value,
+                                           THEME_IDENTIFIER_COL, key,
+                                           THEME_PARENT_ID_COL, parent,
+                                           -1);
+        g_free (parent);
+}
+
+static void
+set_combox_for_theme_name (GvcSoundThemeChooser *chooser,
+                           const char           *name)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        gboolean      found;
+
+        /* If the name is empty, use "freedesktop" */
+        if (name == NULL || *name == '\0') {
+                name = "freedesktop";
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+        if (gtk_tree_model_get_iter_first (model, &iter) == FALSE) {
+                return;
+        }
+
+        do {
+                char *value;
+
+                gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &value, -1);
+                found = (value != NULL && strcmp (value, name) == 0);
+                g_free (value);
+
+        } while (!found && gtk_tree_model_iter_next (model, &iter));
+
+        /* When we can't find the theme we need to set, try to set the default
+         * one "freedesktop" */
+        if (found) {
+                gtk_combo_box_set_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter);
+        } else if (strcmp (name, "freedesktop") != 0) {
+                g_debug ("not found, falling back to fdo");
+                set_combox_for_theme_name (chooser, "freedesktop");
+        }
+}
+
+static void
+set_input_feedback_enabled (GvcSoundThemeChooser *chooser,
+                            gboolean              enabled)
+{
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      enabled);
+}
+
+static void
+setup_theme_selector (GvcSoundThemeChooser *chooser)
+{
+        GHashTable           *hash;
+        GtkListStore         *store;
+        GtkCellRenderer      *renderer;
+        const char * const   *data_dirs;
+        const char           *data_dir;
+        char                 *dir;
+        guint                 i;
+
+        /* Add the theme names and their display name to a hash table,
+         * makes it easy to avoid duplicate themes */
+        hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+        data_dirs = g_get_system_data_dirs ();
+        for (i = 0; data_dirs[i] != NULL; i++) {
+                dir = g_build_filename (data_dirs[i], "sounds", NULL);
+                sound_theme_in_dir (hash, dir);
+                g_free (dir);
+        }
+
+        data_dir = g_get_user_data_dir ();
+        dir = g_build_filename (data_dir, "sounds", NULL);
+        sound_theme_in_dir (hash, dir);
+        g_free (dir);
+
+        /* If there isn't at least one theme, make everything
+         * insensitive, LAME! */
+        if (g_hash_table_size (hash) == 0) {
+                gtk_widget_set_sensitive (GTK_WIDGET (chooser), FALSE);
+                g_warning ("Bad setup, install the freedesktop sound theme");
+                g_hash_table_destroy (hash);
+                return;
+        }
+
+        /* Setup the tree model, 3 columns:
+         * - internal theme name/directory
+         * - display theme name
+         * - the internal id for the parent theme, used for the custom theme */
+        store = gtk_list_store_new (THEME_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING);
+
+        /* Add the themes to a combobox */
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           THEME_DISPLAY_COL, _("No sounds"),
+                                           THEME_IDENTIFIER_COL, "__no_sounds",
+                                           THEME_PARENT_ID_COL, NULL,
+                                           -1);
+        g_hash_table_foreach (hash, (GHFunc) add_theme_to_store, store);
+        g_hash_table_destroy (hash);
+
+        /* Set the display */
+        gtk_combo_box_set_model (GTK_COMBO_BOX (chooser->priv->combo_box),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                    renderer,
+                                    TRUE);
+        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                        renderer,
+                                        "text", THEME_DISPLAY_COL,
+                                        NULL);
+
+        g_signal_connect (G_OBJECT (chooser->priv->combo_box),
+                          "changed",
+                          G_CALLBACK (on_combobox_changed),
+                          chooser);
+}
+
+#define GVC_SOUND_SOUND    (xmlChar *) "sound"
+#define GVC_SOUND_NAME     (xmlChar *) "name"
+#define GVC_SOUND_FILENAME (xmlChar *) "filename"
+
+/* Adapted from yelp-toc-pager.c */
+static xmlChar *
+xml_get_and_trim_names (xmlNodePtr node)
+{
+        xmlNodePtr cur;
+        xmlChar *keep_lang = NULL;
+        xmlChar *value;
+        int j, keep_pri = INT_MAX;
+
+        const gchar * const * langs = g_get_language_names ();
+
+        value = NULL;
+
+        for (cur = node->children; cur; cur = cur->next) {
+                if (! xmlStrcmp (cur->name, GVC_SOUND_NAME)) {
+                        xmlChar *cur_lang = NULL;
+                        int cur_pri = INT_MAX;
+
+                        cur_lang = xmlNodeGetLang (cur);
+
+                        if (cur_lang) {
+                                for (j = 0; langs[j]; j++) {
+                                        if (g_str_equal (cur_lang, langs[j])) {
+                                                cur_pri = j;
+                                                break;
+                                        }
+                                }
+                        } else {
+                                cur_pri = INT_MAX - 1;
+                        }
+
+                        if (cur_pri <= keep_pri) {
+                                if (keep_lang)
+                                        xmlFree (keep_lang);
+                                if (value)
+                                        xmlFree (value);
+
+                                value = xmlNodeGetContent (cur);
+
+                                keep_lang = cur_lang;
+                                keep_pri = cur_pri;
+                        } else {
+                                if (cur_lang)
+                                        xmlFree (cur_lang);
+                        }
+                }
+        }
+
+        /* Delete all GVC_SOUND_NAME nodes */
+        cur = node->children;
+        while (cur) {
+                xmlNodePtr this = cur;
+                cur = cur->next;
+                if (! xmlStrcmp (this->name, GVC_SOUND_NAME)) {
+                        xmlUnlinkNode (this);
+                        xmlFreeNode (this);
+                }
+        }
+
+        return value;
+}
+
+static void
+populate_model_from_node (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          xmlNodePtr            node)
+{
+        xmlNodePtr child;
+        xmlChar   *filename;
+        xmlChar   *name;
+
+        filename = NULL;
+        name = xml_get_and_trim_names (node);
+        for (child = node->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+
+                if (xmlStrcmp (child->name, GVC_SOUND_FILENAME) == 0) {
+                        filename = xmlNodeGetContent (child);
+                } else if (xmlStrcmp (child->name, GVC_SOUND_NAME) == 0) {
+                        /* EH? should have been trimmed */
+                }
+        }
+
+        if (filename != NULL && name != NULL) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   ALERT_IDENTIFIER_COL, filename,
+                                                   ALERT_DISPLAY_COL, name,
+                                                   ALERT_SOUND_TYPE_COL, _("Built-in"),
+                                                   ALERT_ACTIVE_COL, FALSE,
+                                                   -1);
+        }
+
+        xmlFree (filename);
+        xmlFree (name);
+}
+
+static void
+populate_model_from_file (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          const char           *filename)
+{
+        xmlDocPtr  doc;
+        xmlNodePtr root;
+        xmlNodePtr child;
+        gboolean   exists;
+
+        exists = g_file_test (filename, G_FILE_TEST_EXISTS);
+        if (! exists) {
+                return;
+        }
+
+        doc = xmlParseFile (filename);
+        if (doc == NULL) {
+                return;
+        }
+
+        root = xmlDocGetRootElement (doc);
+
+        for (child = root->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+                if (xmlStrcmp (child->name, GVC_SOUND_SOUND) != 0) {
+                        continue;
+                }
+
+                populate_model_from_node (chooser, model, child);
+        }
+
+        xmlFreeDoc (doc);
+}
+
+static void
+populate_model_from_dir (GvcSoundThemeChooser *chooser,
+                         GtkTreeModel         *model,
+                         const char           *dirname)
+{
+        GDir       *d;
+        const char *name;
+
+        d = g_dir_open (dirname, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *path;
+
+                if (! g_str_has_suffix (name, ".xml")) {
+                        continue;
+                }
+
+                path = g_build_filename (dirname, name, NULL);
+                populate_model_from_file (chooser, model, path);
+                g_free (path);
+        }
+
+        g_dir_close (d);
+}
+
+static gboolean
+save_alert_sounds (GvcSoundThemeChooser  *chooser,
+                   const char            *id)
+{
+        const char *sounds[3] = { "bell-terminal", "bell-window-system", NULL };
+        char *path;
+
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+        } else {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+                add_custom_file (sounds, id);
+        }
+
+        /* And poke the directory so the theme gets updated */
+        path = custom_theme_dir_path (NULL);
+        if (utime (path, NULL) != 0) {
+                g_warning ("Failed to update mtime for directory '%s': %s",
+                           path, g_strerror (errno));
+        }
+        g_free (path);
+
+        return FALSE;
+}
+
+
+static void
+update_alert_model (GvcSoundThemeChooser  *chooser,
+                    const char            *id)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        gtk_tree_model_get_iter_first (model, &iter);
+        do {
+                gboolean toggled;
+                char    *this_id;
+
+                gtk_tree_model_get (model, &iter,
+                                    ALERT_IDENTIFIER_COL, &this_id,
+                                    -1);
+
+                if (strcmp (this_id, id) == 0) {
+                        toggled = TRUE;
+                } else {
+                        toggled = FALSE;
+                }
+                g_free (this_id);
+
+                gtk_list_store_set (GTK_LIST_STORE (model),
+                                    &iter,
+                                    ALERT_ACTIVE_COL, toggled,
+                                    -1);
+        } while (gtk_tree_model_iter_next (model, &iter));
+}
+
+static void
+update_alert (GvcSoundThemeChooser *chooser,
+              const char           *alert_id)
+{
+        GtkTreeModel *theme_model;
+        GtkTreeIter   iter;
+        char         *theme;
+        char         *parent;
+        gboolean      is_custom;
+        gboolean      is_default;
+        gboolean      add_custom;
+        gboolean      remove_custom;
+
+        theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        /* Get the current theme's name, and set the parent */
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        gtk_tree_model_get (theme_model, &iter,
+                            THEME_IDENTIFIER_COL, &theme,
+                            THEME_IDENTIFIER_COL, &parent,
+                            -1);
+        is_custom = strcmp (theme, CUSTOM_THEME_NAME) == 0;
+        is_default = strcmp (alert_id, DEFAULT_ALERT_ID) == 0;
+
+        /* So a few possibilities:
+         * 1. Named theme, default alert selected: noop
+         * 2. Named theme, alternate alert selected: create new custom with sound
+         * 3. Custom theme, default alert selected: remove sound and possibly custom
+         * 4. Custom theme, alternate alert selected: update custom sound
+         */
+        add_custom = FALSE;
+        remove_custom = FALSE;
+        if (! is_custom && is_default) {
+                /* remove custom just in case */
+                remove_custom = TRUE;
+        } else if (! is_custom && ! is_default) {
+                create_custom_theme (parent);
+                save_alert_sounds (chooser, alert_id);
+                add_custom = TRUE;
+        } else if (is_custom && is_default) {
+                save_alert_sounds (chooser, alert_id);
+                /* after removing files check if it is empty */
+                if (custom_theme_dir_is_empty ()) {
+                        remove_custom = TRUE;
+                }
+        } else if (is_custom && ! is_default) {
+                save_alert_sounds (chooser, alert_id);
+        }
+
+        if (add_custom) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (theme_model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   THEME_DISPLAY_COL, _("Custom"),
+                                                   THEME_IDENTIFIER_COL, CUSTOM_THEME_NAME,
+                                                   THEME_PARENT_ID_COL, theme,
+                                                   -1);
+                set_combox_for_theme_name (chooser, CUSTOM_THEME_NAME);
+        } else if (remove_custom) {
+                gtk_tree_model_get_iter_first (theme_model, &iter);
+                do {
+                        char *this_parent;
+
+                        gtk_tree_model_get (theme_model, &iter,
+                                            THEME_PARENT_ID_COL, &this_parent,
+                                            -1);
+                        if (this_parent != NULL && strcmp (this_parent, CUSTOM_THEME_NAME) != 0) {
+                                g_free (this_parent);
+                                gtk_list_store_remove (GTK_LIST_STORE (theme_model), &iter);
+                                break;
+                        }
+                        g_free (this_parent);
+                } while (gtk_tree_model_iter_next (theme_model, &iter));
+
+                delete_custom_theme_dir ();
+
+                set_combox_for_theme_name (chooser, parent);
+        }
+
+        update_alert_model (chooser, alert_id);
+
+        g_free (theme);
+        g_free (parent);
+}
+
+static void
+on_alert_toggled (GtkCellRendererToggle *renderer,
+                  char                  *path_str,
+                  GvcSoundThemeChooser  *chooser)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreePath  *path;
+        gboolean      toggled;
+        char         *id;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        path = gtk_tree_path_new_from_string (path_str);
+        gtk_tree_model_get_iter (model, &iter, path);
+        gtk_tree_path_free (path);
+
+        id = NULL;
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            ALERT_ACTIVE_COL, &toggled,
+                            -1);
+
+        toggled ^= 1;
+        if (toggled) {
+                update_alert (chooser, id);
+        }
+
+        g_free (id);
+}
+
+static void
+play_preview_for_path (GvcSoundThemeChooser *chooser, GtkTreePath *path)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreeIter   theme_iter;
+        gchar        *id = NULL;
+        gchar        *parent_theme = NULL;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        if (gtk_tree_model_get_iter (model, &iter, path) == FALSE)
+                return;
+
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            -1);
+        if (id == NULL)
+                return;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &theme_iter)) {
+                GtkTreeModel *theme_model;
+                gchar        *theme_id = NULL;
+                gchar        *parent_id = NULL;
+
+                theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+                gtk_tree_model_get (theme_model, &theme_iter,
+                                    THEME_IDENTIFIER_COL, &theme_id,
+                                    THEME_PARENT_ID_COL, &parent_id, -1);
+                if (theme_id && strcmp (theme_id, CUSTOM_THEME_NAME) == 0)
+                        parent_theme = g_strdup (parent_id);
+
+                g_free (theme_id);
+                g_free (parent_id);
+        }
+
+        /* special case: for the default item on custom themes
+         * play the alert for the parent theme */
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                if (parent_theme != NULL) {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_CANBERRA_XDG_THEME_NAME, parent_theme,
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                } else {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                }
+        } else {
+                ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                        CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                        CA_PROP_MEDIA_FILENAME, id,
+                                        CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                        CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                        CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                        CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                        NULL);
+
+        }
+        g_free (parent_theme);
+        g_free (id);
+}
+
+static void
+on_treeview_row_activated (GtkTreeView          *treeview,
+                           GtkTreePath          *path,
+                           GtkTreeViewColumn    *column,
+                           GvcSoundThemeChooser *chooser)
+{
+        play_preview_for_path (chooser, path);
+}
+
+static void
+on_treeview_selection_changed (GtkTreeSelection     *selection,
+                               GvcSoundThemeChooser *chooser)
+{
+        GList        *paths;
+        GtkTreeModel *model;
+        GtkTreePath  *path;
+
+        if (chooser->priv->treeview == NULL)
+                return;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        paths = gtk_tree_selection_get_selected_rows (selection, &model);
+        if (paths == NULL)
+                return;
+
+        path = paths->data;
+        play_preview_for_path (chooser, path);
+
+        g_list_foreach (paths, (GFunc)gtk_tree_path_free, NULL);
+        g_list_free (paths);
+}
+
+static GtkWidget *
+create_alert_treeview (GvcSoundThemeChooser *chooser)
+{
+        GtkListStore         *store;
+        GtkWidget            *treeview;
+        GtkCellRenderer      *renderer;
+        GtkTreeViewColumn    *column;
+        GtkTreeSelection     *selection;
+
+        treeview = gtk_tree_view_new ();
+
+        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
+        g_signal_connect (G_OBJECT (treeview),
+                          "row-activated",
+                          G_CALLBACK (on_treeview_row_activated),
+                          chooser);
+
+        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+        gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+        g_signal_connect (G_OBJECT (selection),
+                          "changed",
+                          G_CALLBACK (on_treeview_selection_changed),
+                          chooser);
+
+        /* Setup the tree model, 3 columns:
+         * - display name
+         * - sound id
+         * - sound type
+         */
+        store = gtk_list_store_new (ALERT_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_BOOLEAN);
+
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           ALERT_IDENTIFIER_COL, DEFAULT_ALERT_ID,
+                                           ALERT_DISPLAY_COL, _("Default"),
+                                           ALERT_SOUND_TYPE_COL, _("From theme"),
+                                           ALERT_ACTIVE_COL, TRUE,
+                                           -1);
+
+        populate_model_from_dir (chooser, GTK_TREE_MODEL (store), SOUND_SET_DIR);
+
+        gtk_tree_view_set_model (GTK_TREE_VIEW (treeview),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_toggle_new ();
+        gtk_cell_renderer_toggle_set_radio (GTK_CELL_RENDERER_TOGGLE (renderer), TRUE);
+
+        column = gtk_tree_view_column_new_with_attributes (NULL,
+                                                           renderer,
+                                                           "active", ALERT_ACTIVE_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+        g_signal_connect (renderer,
+                          "toggled",
+                          G_CALLBACK (on_alert_toggled),
+                          chooser);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Name"),
+                                                           renderer,
+                                                           "text", ALERT_DISPLAY_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Type"),
+                                                           renderer,
+                                                           "text", ALERT_SOUND_TYPE_COL,
+                                                           NULL);
+
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        return treeview;
+}
+
+static int
+get_file_type (const char *sound_name,
+               char      **linked_name)
+{
+        char *name, *filename;
+
+        *linked_name = NULL;
+
+        name = g_strdup_printf ("%s.disabled", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_REGULAR) != FALSE) {
+                g_free (filename);
+                return SOUND_TYPE_OFF;
+        }
+        g_free (filename);
+
+        /* We only check for .ogg files because those are the
+         * only ones we create */
+        name = g_strdup_printf ("%s.ogg", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_SYMLINK) != FALSE) {
+                *linked_name = g_file_read_link (filename, NULL);
+                g_free (filename);
+                return SOUND_TYPE_CUSTOM;
+        }
+        g_free (filename);
+
+        return SOUND_TYPE_BUILTIN;
+}
+
+static void
+update_alerts_from_theme_name (GvcSoundThemeChooser *chooser,
+                               const gchar          *name)
+{
+        if (strcmp (name, CUSTOM_THEME_NAME) != 0) {
+                /* reset alert to default */
+                update_alert (chooser, DEFAULT_ALERT_ID);
+        } else {
+                int   sound_type;
+                char *linkname;
+
+                linkname = NULL;
+                sound_type = get_file_type ("bell-terminal", &linkname);
+                g_debug ("Found link: %s", linkname);
+                if (sound_type == SOUND_TYPE_CUSTOM) {
+                        update_alert (chooser, linkname);
+                }
+        }
+}
+
+static void
+update_theme (GvcSoundThemeChooser *chooser)
+{
+        char        *theme_name;
+        gboolean     events_enabled;
+        gboolean     feedback_enabled;
+
+        feedback_enabled = g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY);
+        set_input_feedback_enabled (chooser, feedback_enabled);
+
+        events_enabled = g_settings_get_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY);
+        if (events_enabled) {
+                theme_name = g_settings_get_string (chooser->priv->sound_settings, SOUND_THEME_KEY);
+        } else {
+                theme_name = g_strdup (NO_SOUNDS_THEME_NAME);
+        }
+
+        gtk_widget_set_sensitive (chooser->priv->selection_box, events_enabled);
+        gtk_widget_set_sensitive (chooser->priv->click_feedback_button, events_enabled);
+
+        set_combox_for_theme_name (chooser, theme_name);
+
+        update_alerts_from_theme_name (chooser, theme_name);
+
+        g_free (theme_name);
+}
+
+static void
+gvc_sound_theme_chooser_class_init (GvcSoundThemeChooserClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_sound_theme_chooser_dispose;
+}
+
+static void
+on_click_feedback_toggled (GtkToggleButton      *button,
+                           GvcSoundThemeChooser *chooser)
+{
+        gboolean enabled;
+
+        enabled = gtk_toggle_button_get_active (button);
+
+        g_settings_set_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY, enabled);
+}
+
+static void
+on_key_changed (GSettings            *settings,
+                gchar                *key,
+                GvcSoundThemeChooser *chooser)
+{
+        if (!strcmp (key, EVENT_SOUNDS_KEY) ||
+            !strcmp (key, SOUND_THEME_KEY) ||
+            !strcmp (key, INPUT_SOUNDS_KEY))
+                update_theme (chooser);
+}
+
+static void
+setup_list_size_constraint (GtkWidget *widget,
+                            GtkWidget *to_size)
+{
+        GtkRequisition req;
+        gint           sc_height;
+        int            max_height;
+
+        /* Constrain height to be the tree height up to a max */
+        gdk_window_get_geometry (gdk_screen_get_root_window (gtk_widget_get_screen (widget)),
+                                 NULL, NULL, NULL, &sc_height);
+
+        max_height = sc_height / 4;
+
+        // XXX this doesn't work
+        gtk_widget_get_preferred_size (to_size, NULL, &req);
+
+        gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (widget),
+                                                    MIN (req.height, max_height));
+}
+
+static void
+gvc_sound_theme_chooser_init (GvcSoundThemeChooser *chooser)
+{
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *scrolled_window;
+        gchar       *str;
+
+        chooser->priv = gvc_sound_theme_chooser_get_instance_private (chooser);
+
+        chooser->priv->theme_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->theme_box, FALSE, FALSE, 0);
+
+        label = gtk_label_new_with_mnemonic (_("Sound _theme:"));
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), label, FALSE, FALSE, 0);
+        chooser->priv->combo_box = gtk_combo_box_new ();
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), chooser->priv->combo_box, FALSE, FALSE, 6);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->combo_box);
+
+        chooser->priv->sound_settings = g_settings_new (KEY_SOUNDS_SCHEMA);
+
+        g_signal_connect (G_OBJECT (chooser->priv->sound_settings),
+                          "changed",
+                          G_CALLBACK (on_key_changed),
+                          chooser);
+
+        str = g_strdup_printf ("<b>%s</b>", _("C_hoose an alert sound:"));
+        chooser->priv->selection_box = box = gtk_frame_new (str);
+        g_free (str);
+
+        label = gtk_frame_get_label_widget (GTK_FRAME (box));
+        gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
+        gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+        gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
+
+        gtk_box_pack_start (GTK_BOX (chooser), box, TRUE, TRUE, 6);
+
+        chooser->priv->treeview = create_alert_treeview (chooser);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->treeview);
+
+        scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+        gtk_widget_set_hexpand (scrolled_window, TRUE);
+        gtk_widget_set_vexpand (scrolled_window, TRUE);
+        gtk_widget_set_margin_top (scrolled_window, 6);
+
+        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+                                        GTK_POLICY_NEVER,
+                                        GTK_POLICY_AUTOMATIC);
+        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
+                                             GTK_SHADOW_IN);
+
+        gtk_container_add (GTK_CONTAINER (scrolled_window), chooser->priv->treeview);
+        gtk_container_add (GTK_CONTAINER (box), scrolled_window);
+
+        chooser->priv->click_feedback_button = gtk_check_button_new_with_mnemonic (_("Enable _window and button sounds"));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY));
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->click_feedback_button,
+                            FALSE, FALSE, 0);
+
+        g_signal_connect (G_OBJECT (chooser->priv->click_feedback_button),
+                          "toggled",
+                          G_CALLBACK (on_click_feedback_toggled),
+                          chooser);
+
+        setup_theme_selector (chooser);
+        update_theme (chooser);
+
+        setup_list_size_constraint (scrolled_window, chooser->priv->treeview);
+}
+
+static void
+gvc_sound_theme_chooser_dispose (GObject *object)
+{
+        GvcSoundThemeChooser *chooser;
+
+        chooser = GVC_SOUND_THEME_CHOOSER (object);
+
+        g_clear_object (&chooser->priv->sound_settings);
+
+        G_OBJECT_CLASS (gvc_sound_theme_chooser_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_sound_theme_chooser_new (void)
+{
+        return g_object_new (GVC_TYPE_SOUND_THEME_CHOOSER,
+                                "spacing", 6,
+                                "orientation", GTK_ORIENTATION_VERTICAL,
+                                NULL);
+}
+
+
+
+ + + diff --git a/2020-04-09-114613-2421-cppcheck@b19fbdc7119f_master/2.html b/2020-04-09-114613-2421-cppcheck@b19fbdc7119f_master/2.html new file mode 100644 index 0000000..bacfabb --- /dev/null +++ b/2020-04-09-114613-2421-cppcheck@b19fbdc7119f_master/2.html @@ -0,0 +1,1110 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <canberra.h>
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-speaker-test.h"
+#include "gvc-utils.h"
+
+struct _GvcSpeakerTestPrivate
+{
+        GArray           *controls;
+        ca_context       *canberra;
+        MateMixerStream  *stream;
+};
+
+enum {
+        PROP_0,
+        PROP_STREAM,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_speaker_test_dispose    (GObject             *object);
+static void gvc_speaker_test_finalize   (GObject             *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSpeakerTest, gvc_speaker_test, GTK_TYPE_GRID)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+typedef struct {
+        MateMixerChannelPosition position;
+        guint left;
+        guint top;
+} TablePosition;
+
+static const TablePosition positions[] = {
+        /* Position, X, Y */
+        { MATE_MIXER_CHANNEL_FRONT_LEFT, 0, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_LEFT_CENTER, 1, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_CENTER, 2, 0, },
+        { MATE_MIXER_CHANNEL_MONO, 2, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT_CENTER, 3, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT, 4, 0, },
+        { MATE_MIXER_CHANNEL_SIDE_LEFT, 0, 1, },
+        { MATE_MIXER_CHANNEL_SIDE_RIGHT, 4, 1, },
+        { MATE_MIXER_CHANNEL_BACK_LEFT, 0, 2, },
+        { MATE_MIXER_CHANNEL_BACK_CENTER, 2, 2, },
+        { MATE_MIXER_CHANNEL_BACK_RIGHT, 4, 2, },
+        { MATE_MIXER_CHANNEL_LFE, 3, 2 }
+};
+
+MateMixerStream *
+gvc_speaker_test_get_stream (GvcSpeakerTest *test)
+{
+        g_return_val_if_fail (GVC_IS_SPEAKER_TEST (test), NULL);
+
+        return test->priv->stream;
+}
+
+static void
+gvc_speaker_test_set_stream (GvcSpeakerTest *test, MateMixerStream *stream)
+{
+        MateMixerStreamControl *control;
+        const gchar            *name;
+        guint                   i;
+
+        name = mate_mixer_stream_get_name (stream);
+        control = mate_mixer_stream_get_default_control (stream);
+
+        ca_context_change_device (test->priv->canberra, name);
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                gboolean has_position =
+                        mate_mixer_stream_control_has_channel_position (control, positions[i].position);
+
+                gtk_widget_set_visible (g_array_index (test->priv->controls, GtkWidget *, i),
+                                        has_position);
+        }
+
+        test->priv->stream = g_object_ref (stream);
+}
+
+static void
+gvc_speaker_test_set_property (GObject       *object,
+                               guint          prop_id,
+                               const GValue  *value,
+                               GParamSpec    *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                gvc_speaker_test_set_stream (self, g_value_get_object (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_get_property (GObject     *object,
+                               guint        prop_id,
+                               GValue      *value,
+                               GParamSpec  *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                g_value_set_object (value, self->priv->stream);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_class_init (GvcSpeakerTestClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose  = gvc_speaker_test_dispose;
+        object_class->finalize = gvc_speaker_test_finalize;
+        object_class->set_property = gvc_speaker_test_set_property;
+        object_class->get_property = gvc_speaker_test_get_property;
+
+        properties[PROP_STREAM] =
+                g_param_spec_object ("stream",
+                                     "Stream",
+                                     "MateMixer stream",
+                                     MATE_MIXER_TYPE_STREAM,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+}
+
+static const gchar *
+sound_name (MateMixerChannelPosition position)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return "audio-channel-front-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return "audio-channel-front-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return "audio-channel-front-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return "audio-channel-rear-left";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return "audio-channel-rear-right";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return "audio-channel-rear-center";
+        case MATE_MIXER_CHANNEL_LFE:
+                return "audio-channel-lfe";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return "audio-channel-side-left";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return "audio-channel-side-right";
+        default:
+                return NULL;
+        }
+}
+
+static const gchar *
+icon_name (MateMixerChannelPosition position, gboolean playing)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return playing
+                        ? "audio-speaker-left-testing"
+                        : "audio-speaker-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return playing
+                        ? "audio-speaker-right-testing"
+                        : "audio-speaker-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return playing
+                        ? "audio-speaker-center-testing"
+                        : "audio-speaker-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return playing
+                        ? "audio-speaker-left-back-testing"
+                        : "audio-speaker-left-back";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return playing
+                        ? "audio-speaker-right-back-testing"
+                        : "audio-speaker-right-back";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return playing
+                        ? "audio-speaker-center-back-testing"
+                        : "audio-speaker-center-back";
+        case MATE_MIXER_CHANNEL_LFE:
+                return playing
+                        ? "audio-subwoofer-testing"
+                        : "audio-subwoofer";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return playing
+                        ? "audio-speaker-left-side-testing"
+                        : "audio-speaker-left-side";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return playing
+                        ? "audio-speaker-right-side-testing"
+                        : "audio-speaker-right-side";
+        default:
+                return NULL;
+        }
+}
+
+static void
+update_button (GtkWidget *control)
+{
+        GtkWidget *button;
+        GtkWidget *image;
+        gboolean   playing;
+        MateMixerChannelPosition position;
+
+        button = g_object_get_data (G_OBJECT (control), "button");
+        image  = g_object_get_data (G_OBJECT (control), "image");
+
+        position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+        playing  = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        gtk_button_set_label (GTK_BUTTON (button), playing ? _("Stop") : _("Test"));
+
+        gtk_image_set_from_icon_name (GTK_IMAGE (image),
+                                      icon_name (position, playing),
+                                      GTK_ICON_SIZE_DIALOG);
+}
+
+static gboolean
+idle_cb (GtkWidget *control)
+{
+        if (control != NULL) {
+                /* This is called in the background thread, hence forward to main thread
+                 * via idle callback */
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+
+                update_button (control);
+        }
+        return FALSE;
+}
+
+static void
+finish_cb (ca_context *c, uint32_t id, int error_code, void *userdata)
+{
+        GtkWidget *control = (GtkWidget *) userdata;
+
+        if (error_code == CA_ERROR_DESTROYED || control == NULL)
+                return;
+
+        g_idle_add ((GSourceFunc) idle_cb, control);
+}
+
+static void
+on_test_button_clicked (GtkButton *button, GtkWidget *control)
+{
+        gboolean    playing;
+        ca_context *canberra;
+
+        canberra = g_object_get_data (G_OBJECT (control), "canberra");
+
+        ca_context_cancel (canberra, 1);
+
+        playing = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        if (playing) {
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        } else {
+                MateMixerChannelPosition position;
+                const gchar *name;
+                ca_proplist *proplist;
+
+                position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+
+                ca_proplist_create (&proplist);
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_ROLE, "test");
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_NAME,
+                                  gvc_channel_position_to_pretty_string (position));
+                ca_proplist_sets (proplist,
+                                  CA_PROP_CANBERRA_FORCE_CHANNEL,
+                                  gvc_channel_position_to_pulse_string (position));
+
+                ca_proplist_sets (proplist, CA_PROP_CANBERRA_ENABLE, "1");
+
+                name = sound_name (position);
+                if (name != NULL) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, name);
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, "audio-test-signal");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets(proplist, CA_PROP_EVENT_ID, "bell-window-system");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (playing));
+        }
+
+        update_button (control);
+}
+
+static GtkWidget *
+create_control (ca_context *canberra, MateMixerChannelPosition position)
+{
+        GtkWidget   *control;
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *image;
+        GtkWidget   *test_button;
+        const gchar *name;
+
+        control = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+        box     = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        g_object_set_data (G_OBJECT (control), "position", GINT_TO_POINTER (position));
+        g_object_set_data (G_OBJECT (control), "canberra", canberra);
+
+        name = icon_name (position, FALSE);
+        if (name == NULL)
+                name = "audio-volume-medium";
+
+        image = gtk_image_new_from_icon_name (name, GTK_ICON_SIZE_DIALOG);
+        g_object_set_data (G_OBJECT (control), "image", image);
+        gtk_box_pack_start (GTK_BOX (control), image, FALSE, FALSE, 0);
+
+        label = gtk_label_new (gvc_channel_position_to_pretty_string (position));
+        gtk_box_pack_start (GTK_BOX (control), label, FALSE, FALSE, 0);
+
+        test_button = gtk_button_new_with_label (_("Test"));
+        g_signal_connect (G_OBJECT (test_button),
+                          "clicked",
+                          G_CALLBACK (on_test_button_clicked),
+                          control);
+
+        g_object_set_data (G_OBJECT (control), "button", test_button);
+
+        gtk_box_pack_start (GTK_BOX (box), test_button, TRUE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (control), box, FALSE, FALSE, 0);
+
+        gtk_widget_show_all (control);
+
+        return control;
+}
+
+static void
+create_controls (GvcSpeakerTest *test)
+{
+        guint i;
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                GtkWidget *control = create_control (test->priv->canberra, positions[i].position);
+
+                gtk_grid_attach (GTK_GRID (test),
+                                 control,
+                                 positions[i].left,
+                                 positions[i].top,
+                                 1, 1);
+                g_array_insert_val (test->priv->controls, i, control);
+        }
+}
+
+static void
+gvc_speaker_test_init (GvcSpeakerTest *test)
+{
+        GtkWidget *face;
+
+        test->priv = gvc_speaker_test_get_instance_private (test);
+
+        gtk_container_set_border_width (GTK_CONTAINER (test), 12);
+
+        face = gtk_image_new_from_icon_name ("face-smile", GTK_ICON_SIZE_DIALOG);
+
+        gtk_grid_attach (GTK_GRID (test),
+                         face,
+                         1, 1,
+                         3, 1);
+
+
+        gtk_grid_set_baseline_row (GTK_GRID (test), 1);
+        gtk_widget_show (face);
+
+        ca_context_create (&test->priv->canberra);
+
+        /* The test sounds are played for a single channel, set up using the
+         * FORCE_CHANNEL property of libcanberra; this property is only supported
+         * in the PulseAudio backend, so avoid other backends completely */
+        ca_context_set_driver (test->priv->canberra, "pulse");
+
+        ca_context_change_props (test->priv->canberra,
+                                 CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+                                 CA_PROP_APPLICATION_NAME, _("Volume Control"),
+                                 CA_PROP_APPLICATION_VERSION, VERSION,
+                                 CA_PROP_APPLICATION_ICON_NAME, "multimedia-volume-control",
+                                 NULL);
+
+        test->priv->controls = g_array_new (FALSE, FALSE, sizeof (GtkWidget *));
+
+        create_controls (test);
+}
+
+static void
+gvc_speaker_test_dispose (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        g_clear_object (&test->priv->stream);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->dispose (object);
+}
+
+static void
+gvc_speaker_test_finalize (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        ca_context_destroy (test->priv->canberra);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->finalize (object);
+}
+
+GtkWidget *
+gvc_speaker_test_new (MateMixerStream *stream)
+{
+        GObject *test;
+
+        g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL);
+
+        test = g_object_new (GVC_TYPE_SPEAKER_TEST,
+                             "row-spacing", 6,
+                             "column-spacing", 6,
+                             "row-homogeneous", TRUE,
+                             "column-homogeneous", TRUE,
+                             "stream", stream,
+                             NULL);
+
+        return GTK_WIDGET (test);
+}
+
+
+
+ + + diff --git a/2020-04-09-114613-2421-cppcheck@b19fbdc7119f_master/index.html b/2020-04-09-114613-2421-cppcheck@b19fbdc7119f_master/index.html new file mode 100644 index 0000000..59baeb0 --- /dev/null +++ b/2020-04-09-114613-2421-cppcheck@b19fbdc7119f_master/index.html @@ -0,0 +1,108 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
mate-volume-control/gvc-combo-box.c
70unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
mate-volume-control/gvc-sound-theme-chooser.c
735ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
746ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
758ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
mate-volume-control/gvc-speaker-test.c
53unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+ + + diff --git a/2020-04-09-114613-2421-cppcheck@b19fbdc7119f_master/stats.html b/2020-04-09-114613-2421-cppcheck@b19fbdc7119f_master/stats.html new file mode 100644 index 0000000..3fb6add --- /dev/null +++ b/2020-04-09-114613-2421-cppcheck@b19fbdc7119f_master/stats.html @@ -0,0 +1,93 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+

Top 10 files for error severity, total findings: 2
+   1  mate-volume-control/gvc-speaker-test.c
+   1  mate-volume-control/gvc-combo-box.c
+

+

Top 10 files for information severity, total findings: 3
+   3  mate-volume-control/gvc-sound-theme-chooser.c
+

+ +
+ + + diff --git a/2020-04-09-114613-2421-cppcheck@b19fbdc7119f_master/style.css b/2020-04-09-114613-2421-cppcheck@b19fbdc7119f_master/style.css new file mode 100644 index 0000000..c39571c --- /dev/null +++ b/2020-04-09-114613-2421-cppcheck@b19fbdc7119f_master/style.css @@ -0,0 +1,149 @@ + +body { + font: 13px Arial, Verdana, Sans-Serif; + margin: 0; + width: auto; +} + +h1 { + margin: 10px; +} + +#footer > p { + margin: 4px; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + border: 1px dotted black; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #B6B6B4; +} + +.inconclusive2 { + background-color: #B6B6B4; + border: 1px dotted black; + display: inline-block; + margin-left: 4px; +} + +div.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +div.verbose div.content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid black; + background-color: #FFFFCC; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +#header { + border-bottom: thin solid #aaa; +} + +#menu { + float: left; + margin-top: 5px; + text-align: left; + width: 150px; + /*height: 75%;*/ + position: fixed; + overflow: auto; + z-index: 1; +} + +#menu_index { + float: left; + margin-top: 5px; + padding-left: 5px; + text-align: left; + width: 300px; + /*height: 75%;*/ + position: fixed; + overflow: auto; + z-index: 1; +} + +#menu > a { + display: block; + margin-left: 10px; + font: 12px; + z-index: 1; +} + +#filename { + margin-left: 10px; + font: 12px; + z-index: 1; +} + +.highlighttable { + background-color:white; + z-index: 10; + position: relative; + margin: -10 px; +} + +#content { + background-color: white; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + float: left; + margin: 5px; + margin-left: 10px; + padding: 0 10px 10px 10px; + width: 80%; + padding-left: 150px; +} + +#content_index { + background-color: white; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + float: left; + margin: 5px; + margin-left: 10px; + padding: 0 10px 10px 10px; + width: 80%; + padding-left: 300px; +} + +.linenos { + border-right: thin solid #aaa; + color: lightgray; + padding-right: 6px; +} + +#footer { + border-top: thin solid #aaa; + clear: both; + font-size: 90%; + margin-top: 5px; +} + +#footer ul { + list-style-type: none; + padding-left: 0; +} diff --git a/2020-04-09-124106-6009-cppcheck@49d783c683ff_enum-conversion/0.html b/2020-04-09-124106-6009-cppcheck@49d783c683ff_enum-conversion/0.html new file mode 100644 index 0000000..e262ed0 --- /dev/null +++ b/2020-04-09-124106-6009-cppcheck@49d783c683ff_enum-conversion/0.html @@ -0,0 +1,1038 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-combo-box.h"
+
+struct _GvcComboBoxPrivate
+{
+        GtkWidget       *drop_box;
+        GtkWidget       *start_box;
+        GtkWidget       *end_box;
+        GtkWidget       *label;
+        GtkWidget       *button;
+        GtkTreeModel    *model;
+        GtkWidget       *combobox;
+        MateMixerSwitch *swtch;
+};
+
+enum {
+        COL_NAME,
+        COL_HUMAN_NAME,
+        NUM_COLS
+};
+
+enum {
+        CHANGING,
+        BUTTON_CLICKED,
+        LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+enum {
+        PROP_0,
+        PROP_SWITCH,
+        PROP_LABEL,
+        PROP_SHOW_BUTTON,
+        PROP_BUTTON_LABEL,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_combo_box_dispose    (GObject          *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcComboBox, gvc_combo_box, GTK_TYPE_BOX)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+MateMixerSwitch *
+gvc_combo_box_get_switch (GvcComboBox *combobox)
+{
+        g_return_val_if_fail (GVC_IS_COMBO_BOX (combobox), NULL);
+
+        return combobox->priv->swtch;
+}
+
+void
+gvc_combo_box_set_size_group (GvcComboBox  *combobox,
+                              GtkSizeGroup *group,
+                              gboolean      symmetric)
+{
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (GTK_IS_SIZE_GROUP (group));
+
+        if (group != NULL) {
+                gtk_size_group_add_widget (group, combobox->priv->start_box);
+                if (symmetric == TRUE)
+                        gtk_size_group_add_widget (group, combobox->priv->end_box);
+        }
+        gtk_widget_queue_draw (GTK_WIDGET (combobox));
+}
+
+static void
+on_switch_active_option_notify (MateMixerSwitch *swtch,
+                                GParamSpec      *pspec,
+                                GvcComboBox     *combobox)
+{
+        GtkTreeIter            iter;
+        MateMixerSwitchOption *active;
+        gboolean               cont;
+        const gchar           *name;
+
+        active = mate_mixer_switch_get_active_option (swtch);
+        if (G_UNLIKELY (active == NULL)) {
+                g_warn_if_reached ();
+                return;
+        }
+
+        /* Select the newly activated switch option in the combo box */
+        name = mate_mixer_switch_option_get_name (active);
+        cont = gtk_tree_model_get_iter_first (combobox->priv->model, &iter);
+        while (cont == TRUE) {
+                gchar *current;
+
+                gtk_tree_model_get (combobox->priv->model, &iter,
+                                    COL_NAME, &current,
+                                    -1);
+                if (g_strcmp0 (name, current) == 0) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox), &iter);
+                        g_free (current);
+                        return;
+                }
+                g_free (current);
+
+                cont = gtk_tree_model_iter_next (combobox->priv->model, &iter);
+        }
+        g_warning ("Could not find switch option '%s' in combo box", name);
+}
+
+static void
+gvc_combo_box_set_switch (GvcComboBox *combobox, MateMixerSwitch *swtch)
+{
+        MateMixerSwitchOption *active;
+        const GList           *options;
+
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (MATE_MIXER_IS_SWITCH (swtch));
+
+        combobox->priv->swtch = g_object_ref (swtch);
+
+        active  = mate_mixer_switch_get_active_option (swtch);
+        options = mate_mixer_switch_list_options (swtch);
+        while (options != NULL) {
+                GtkTreeIter            iter;
+                MateMixerSwitchOption *option = MATE_MIXER_SWITCH_OPTION (options->data);
+
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (combobox->priv->model),
+                                                   &iter,
+                                                   G_MAXINT,
+                                                   COL_NAME,
+                                                   mate_mixer_switch_option_get_name (option),
+                                                   COL_HUMAN_NAME,
+                                                   mate_mixer_switch_option_get_label (option),
+                                                   -1);
+
+                /* Select the currently active option of the switch */
+                if (option == active) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox),
+                                                       &iter);
+                }
+                options = options->next;
+        }
+
+        g_signal_connect (G_OBJECT (swtch),
+                          "notify::active-option",
+                          G_CALLBACK (on_switch_active_option_notify),
+                          combobox);
+}
+
+static void
+gvc_combo_box_set_property (GObject       *object,
+                            guint          prop_id,
+                            const GValue  *value,
+                            GParamSpec    *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                gvc_combo_box_set_switch (self, g_value_get_object (value));
+                break;
+        case PROP_LABEL:
+                gtk_label_set_text_with_mnemonic (GTK_LABEL (self->priv->label), g_value_get_string (value));
+                break;
+        case PROP_BUTTON_LABEL:
+                gtk_button_set_label (GTK_BUTTON (self->priv->button), g_value_get_string (value));
+                break;
+        case PROP_SHOW_BUTTON:
+                gtk_widget_set_visible (self->priv->button, g_value_get_boolean (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_get_property (GObject     *object,
+                            guint        prop_id,
+                            GValue      *value,
+                            GParamSpec  *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                g_value_set_object (value, self->priv->swtch);
+                break;
+        case PROP_LABEL:
+                g_value_set_string (value, gtk_label_get_text (GTK_LABEL (self->priv->label)));
+                break;
+        case PROP_BUTTON_LABEL:
+                g_value_set_string (value, gtk_button_get_label (GTK_BUTTON (self->priv->button)));
+                break;
+        case PROP_SHOW_BUTTON:
+                g_value_set_boolean (value, gtk_widget_get_visible (self->priv->button));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_class_init (GvcComboBoxClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_combo_box_dispose;
+        object_class->set_property = gvc_combo_box_set_property;
+        object_class->get_property = gvc_combo_box_get_property;
+
+        properties[PROP_SWITCH] =
+                g_param_spec_object ("switch",
+                                     "switch",
+                                     "The MateMixerSwitch",
+                                     MATE_MIXER_TYPE_SWITCH,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_LABEL] =
+                g_param_spec_string ("label",
+                                     "label",
+                                     "The combo box label",
+                                     _("_Profile:"),
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_SHOW_BUTTON] =
+                g_param_spec_boolean ("show-button",
+                                      "show-button",
+                                      "Whether to show the button",
+                                      FALSE,
+                                      G_PARAM_READWRITE |
+                                      G_PARAM_CONSTRUCT |
+                                      G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_BUTTON_LABEL] =
+                g_param_spec_string ("button-label",
+                                     "button-label",
+                                     "The button's label",
+                                     "",
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+
+        signals[CHANGING] =
+                g_signal_new ("changing",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, changing),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__OBJECT,
+                              G_TYPE_NONE,
+                              1,
+                              MATE_MIXER_TYPE_SWITCH_OPTION);
+
+        signals[BUTTON_CLICKED] =
+                g_signal_new ("button-clicked",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, button_clicked),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
+}
+
+static void
+on_combo_box_changed (GtkComboBox *widget, GvcComboBox *combobox)
+{
+        GtkTreeIter            iter;
+        gchar                 *name;
+        MateMixerSwitchOption *option;
+
+        if (G_UNLIKELY (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter) == FALSE))
+                return;
+
+        gtk_tree_model_get (combobox->priv->model, &iter,
+                            COL_NAME, &name,
+                            -1);
+
+        option = mate_mixer_switch_get_option (combobox->priv->swtch, name);
+        if (G_UNLIKELY (option == NULL)) {
+                g_warn_if_reached ();
+                g_free (name);
+                return;
+        }
+
+        /* Inform that we are about to change the active option of the switch */
+        g_signal_emit (combobox, signals[CHANGING], 0, option);
+
+        mate_mixer_switch_set_active_option (combobox->priv->swtch, option);
+        g_free (name);
+}
+
+static void
+on_combo_box_button_clicked (GtkButton *button, GvcComboBox *combobox)
+{
+        /* The meaning of the button is defined by the owner, so only notify
+         * when it is clicked on */
+        g_signal_emit (combobox, signals[BUTTON_CLICKED], 0);
+}
+
+static void
+gvc_combo_box_init (GvcComboBox *combobox)
+{
+        GtkWidget       *frame;
+        GtkCellRenderer *renderer;
+
+        frame = gtk_frame_new (NULL);
+        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
+
+        combobox->priv = gvc_combo_box_get_instance_private (combobox);
+
+        combobox->priv->model = GTK_TREE_MODEL (gtk_list_store_new (NUM_COLS,
+                                                                    G_TYPE_STRING,
+                                                                    G_TYPE_STRING));
+
+        combobox->priv->combobox = gtk_combo_box_new_with_model (combobox->priv->model);
+
+        combobox->priv->label = gtk_label_new (NULL);
+
+        gtk_label_set_xalign (GTK_LABEL (combobox->priv->label), 0.0);
+        gtk_label_set_yalign (GTK_LABEL (combobox->priv->label), 0.5);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (combobox->priv->label),
+                                       combobox->priv->combobox);
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                    renderer,
+                                    FALSE);
+        gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                       renderer,
+                                       "text",
+                                       COL_HUMAN_NAME);
+
+        combobox->priv->drop_box  = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->start_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->end_box   = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+        /* Make sure the combo box does not get too long on long profile names */
+        g_object_set (G_OBJECT (renderer),
+                      "ellipsize",
+                      PANGO_ELLIPSIZE_END,
+                      NULL);
+
+        gtk_combo_box_set_popup_fixed_width (GTK_COMBO_BOX (combobox->priv->combobox), FALSE);
+
+        gtk_box_pack_start (GTK_BOX (combobox),
+                            frame,
+                            TRUE, TRUE, 0);
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->start_box,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->start_box),
+                            combobox->priv->label,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->combobox,
+                            TRUE, TRUE, 0);
+
+        combobox->priv->button = gtk_button_new_with_label ("");
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->button,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->end_box,
+                            FALSE, FALSE, 0);
+
+        gtk_container_add (GTK_CONTAINER (frame), combobox->priv->drop_box);
+
+        g_signal_connect (G_OBJECT (combobox->priv->combobox),
+                          "changed",
+                          G_CALLBACK (on_combo_box_changed),
+                          combobox);
+        g_signal_connect (G_OBJECT (combobox->priv->button),
+                          "clicked",
+                          G_CALLBACK (on_combo_box_button_clicked),
+                          combobox);
+
+        gtk_widget_set_no_show_all (combobox->priv->button, TRUE);
+        gtk_widget_show_all (frame);
+}
+
+static void
+gvc_combo_box_dispose (GObject *object)
+{
+        GvcComboBox *combobox;
+
+        combobox = GVC_COMBO_BOX (object);
+
+        if (G_LIKELY (combobox->priv->swtch != NULL)) {
+                g_signal_handlers_disconnect_by_func (G_OBJECT (combobox->priv->swtch),
+                                                      G_CALLBACK (on_switch_active_option_notify),
+                                                      combobox);
+                g_clear_object (&combobox->priv->swtch);
+        }
+
+        g_clear_object (&combobox->priv->model);
+
+        G_OBJECT_CLASS (gvc_combo_box_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_combo_box_new (MateMixerSwitch *swtch, const gchar *label)
+{
+        return g_object_new (GVC_TYPE_COMBO_BOX,
+                             "switch", swtch,
+                             "label", label,
+                             "orientation", GTK_ORIENTATION_HORIZONTAL,
+                             NULL);
+}
+
+
+
+ + + diff --git a/2020-04-09-124106-6009-cppcheck@49d783c683ff_enum-conversion/1.html b/2020-04-09-124106-6009-cppcheck@49d783c683ff_enum-conversion/1.html new file mode 100644 index 0000000..67179f2 --- /dev/null +++ b/2020-04-09-124106-6009-cppcheck@49d783c683ff_enum-conversion/1.html @@ -0,0 +1,2368 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
+ * Copyright (C) 2008 William Jon McCann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <utime.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+#include <canberra-gtk.h>
+#include <libxml/tree.h>
+
+#include "gvc-sound-theme-chooser.h"
+#include "sound-theme-file-utils.h"
+
+struct GvcSoundThemeChooserPrivate
+{
+        GtkWidget *combo_box;
+        GtkWidget *treeview;
+        GtkWidget *theme_box;
+        GtkWidget *selection_box;
+        GtkWidget *click_feedback_button;
+        GSettings *sound_settings;
+};
+
+static void     gvc_sound_theme_chooser_dispose   (GObject            *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSoundThemeChooser, gvc_sound_theme_chooser, GTK_TYPE_BOX)
+
+#define KEY_SOUNDS_SCHEMA          "org.mate.sound"
+#define EVENT_SOUNDS_KEY           "event-sounds"
+#define INPUT_SOUNDS_KEY           "input-feedback-sounds"
+#define SOUND_THEME_KEY            "theme-name"
+
+#define DEFAULT_ALERT_ID        "__default"
+#define CUSTOM_THEME_NAME       "__custom"
+#define NO_SOUNDS_THEME_NAME    "__no_sounds"
+
+enum {
+        THEME_DISPLAY_COL,
+        THEME_IDENTIFIER_COL,
+        THEME_PARENT_ID_COL,
+        THEME_NUM_COLS
+};
+
+enum {
+        ALERT_DISPLAY_COL,
+        ALERT_IDENTIFIER_COL,
+        ALERT_SOUND_TYPE_COL,
+        ALERT_ACTIVE_COL,
+        ALERT_NUM_COLS
+};
+
+enum {
+        SOUND_TYPE_UNSET,
+        SOUND_TYPE_OFF,
+        SOUND_TYPE_DEFAULT_FROM_THEME,
+        SOUND_TYPE_BUILTIN,
+        SOUND_TYPE_CUSTOM
+};
+
+static void
+on_combobox_changed (GtkComboBox          *widget,
+                     GvcSoundThemeChooser *chooser)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        char         *theme_name;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &theme_name, -1);
+
+        g_assert (theme_name != NULL);
+
+        /* It is necessary to update the theme name before any other setting as
+         * the "changed" notification will reload the contents of the widget */
+        g_settings_set_string (chooser->priv->sound_settings, SOUND_THEME_KEY, theme_name);
+
+        /* special case for no sounds */
+        if (strcmp (theme_name, NO_SOUNDS_THEME_NAME) == 0) {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, FALSE);
+                return;
+        } else {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, TRUE);
+        }
+
+        g_free (theme_name);
+
+        /* FIXME: reset alert model */
+}
+
+static char *
+load_index_theme_name (const char *index,
+                       char      **parent)
+{
+        GKeyFile *file;
+        char *indexname = NULL;
+        gboolean hidden;
+
+        file = g_key_file_new ();
+        if (g_key_file_load_from_file (file, index, G_KEY_FILE_KEEP_TRANSLATIONS, NULL) == FALSE) {
+                g_key_file_free (file);
+                return NULL;
+        }
+        /* Don't add hidden themes to the list */
+        hidden = g_key_file_get_boolean (file, "Sound Theme", "Hidden", NULL);
+        if (!hidden) {
+                indexname = g_key_file_get_locale_string (file,
+                                                          "Sound Theme",
+                                                          "Name",
+                                                          NULL,
+                                                          NULL);
+
+                /* Save the parent theme, if there's one */
+                if (parent != NULL) {
+                        *parent = g_key_file_get_string (file,
+                                                         "Sound Theme",
+                                                         "Inherits",
+                                                         NULL);
+                }
+        }
+
+        g_key_file_free (file);
+        return indexname;
+}
+
+static void
+sound_theme_in_dir (GHashTable *hash,
+                    const char *dir)
+{
+        GDir *d;
+        const char *name;
+
+        d = g_dir_open (dir, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *dirname, *index, *indexname;
+
+                /* Look for directories */
+                dirname = g_build_filename (dir, name, NULL);
+                if (g_file_test (dirname, G_FILE_TEST_IS_DIR) == FALSE) {
+                        g_free (dirname);
+                        continue;
+                }
+
+                /* Look for index files */
+                index = g_build_filename (dirname, "index.theme", NULL);
+                g_free (dirname);
+
+                /* Check the name of the theme in the index.theme file */
+                indexname = load_index_theme_name (index, NULL);
+                g_free (index);
+                if (indexname == NULL) {
+                        continue;
+                }
+
+                g_hash_table_insert (hash, g_strdup (name), indexname);
+        }
+
+        g_dir_close (d);
+}
+
+static void
+add_theme_to_store (const char   *key,
+                    const char   *value,
+                    GtkListStore *store)
+{
+        char *parent;
+
+        parent = NULL;
+
+        /* Get the parent, if we're checking the custom theme */
+        if (strcmp (key, CUSTOM_THEME_NAME) == 0) {
+                char *name, *path;
+
+                path = custom_theme_dir_path ("index.theme");
+                name = load_index_theme_name (path, &parent);
+                g_free (name);
+                g_free (path);
+        }
+        gtk_list_store_insert_with_values (store, NULL, G_MAXINT,
+                                           THEME_DISPLAY_COL, value,
+                                           THEME_IDENTIFIER_COL, key,
+                                           THEME_PARENT_ID_COL, parent,
+                                           -1);
+        g_free (parent);
+}
+
+static void
+set_combox_for_theme_name (GvcSoundThemeChooser *chooser,
+                           const char           *name)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        gboolean      found;
+
+        /* If the name is empty, use "freedesktop" */
+        if (name == NULL || *name == '\0') {
+                name = "freedesktop";
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+        if (gtk_tree_model_get_iter_first (model, &iter) == FALSE) {
+                return;
+        }
+
+        do {
+                char *value;
+
+                gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &value, -1);
+                found = (value != NULL && strcmp (value, name) == 0);
+                g_free (value);
+
+        } while (!found && gtk_tree_model_iter_next (model, &iter));
+
+        /* When we can't find the theme we need to set, try to set the default
+         * one "freedesktop" */
+        if (found) {
+                gtk_combo_box_set_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter);
+        } else if (strcmp (name, "freedesktop") != 0) {
+                g_debug ("not found, falling back to fdo");
+                set_combox_for_theme_name (chooser, "freedesktop");
+        }
+}
+
+static void
+set_input_feedback_enabled (GvcSoundThemeChooser *chooser,
+                            gboolean              enabled)
+{
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      enabled);
+}
+
+static void
+setup_theme_selector (GvcSoundThemeChooser *chooser)
+{
+        GHashTable           *hash;
+        GtkListStore         *store;
+        GtkCellRenderer      *renderer;
+        const char * const   *data_dirs;
+        const char           *data_dir;
+        char                 *dir;
+        guint                 i;
+
+        /* Add the theme names and their display name to a hash table,
+         * makes it easy to avoid duplicate themes */
+        hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+        data_dirs = g_get_system_data_dirs ();
+        for (i = 0; data_dirs[i] != NULL; i++) {
+                dir = g_build_filename (data_dirs[i], "sounds", NULL);
+                sound_theme_in_dir (hash, dir);
+                g_free (dir);
+        }
+
+        data_dir = g_get_user_data_dir ();
+        dir = g_build_filename (data_dir, "sounds", NULL);
+        sound_theme_in_dir (hash, dir);
+        g_free (dir);
+
+        /* If there isn't at least one theme, make everything
+         * insensitive, LAME! */
+        if (g_hash_table_size (hash) == 0) {
+                gtk_widget_set_sensitive (GTK_WIDGET (chooser), FALSE);
+                g_warning ("Bad setup, install the freedesktop sound theme");
+                g_hash_table_destroy (hash);
+                return;
+        }
+
+        /* Setup the tree model, 3 columns:
+         * - internal theme name/directory
+         * - display theme name
+         * - the internal id for the parent theme, used for the custom theme */
+        store = gtk_list_store_new (THEME_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING);
+
+        /* Add the themes to a combobox */
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           THEME_DISPLAY_COL, _("No sounds"),
+                                           THEME_IDENTIFIER_COL, "__no_sounds",
+                                           THEME_PARENT_ID_COL, NULL,
+                                           -1);
+        g_hash_table_foreach (hash, (GHFunc) add_theme_to_store, store);
+        g_hash_table_destroy (hash);
+
+        /* Set the display */
+        gtk_combo_box_set_model (GTK_COMBO_BOX (chooser->priv->combo_box),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                    renderer,
+                                    TRUE);
+        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                        renderer,
+                                        "text", THEME_DISPLAY_COL,
+                                        NULL);
+
+        g_signal_connect (G_OBJECT (chooser->priv->combo_box),
+                          "changed",
+                          G_CALLBACK (on_combobox_changed),
+                          chooser);
+}
+
+#define GVC_SOUND_SOUND    (xmlChar *) "sound"
+#define GVC_SOUND_NAME     (xmlChar *) "name"
+#define GVC_SOUND_FILENAME (xmlChar *) "filename"
+
+/* Adapted from yelp-toc-pager.c */
+static xmlChar *
+xml_get_and_trim_names (xmlNodePtr node)
+{
+        xmlNodePtr cur;
+        xmlChar *keep_lang = NULL;
+        xmlChar *value;
+        int j, keep_pri = INT_MAX;
+
+        const gchar * const * langs = g_get_language_names ();
+
+        value = NULL;
+
+        for (cur = node->children; cur; cur = cur->next) {
+                if (! xmlStrcmp (cur->name, GVC_SOUND_NAME)) {
+                        xmlChar *cur_lang = NULL;
+                        int cur_pri = INT_MAX;
+
+                        cur_lang = xmlNodeGetLang (cur);
+
+                        if (cur_lang) {
+                                for (j = 0; langs[j]; j++) {
+                                        if (g_str_equal (cur_lang, langs[j])) {
+                                                cur_pri = j;
+                                                break;
+                                        }
+                                }
+                        } else {
+                                cur_pri = INT_MAX - 1;
+                        }
+
+                        if (cur_pri <= keep_pri) {
+                                if (keep_lang)
+                                        xmlFree (keep_lang);
+                                if (value)
+                                        xmlFree (value);
+
+                                value = xmlNodeGetContent (cur);
+
+                                keep_lang = cur_lang;
+                                keep_pri = cur_pri;
+                        } else {
+                                if (cur_lang)
+                                        xmlFree (cur_lang);
+                        }
+                }
+        }
+
+        /* Delete all GVC_SOUND_NAME nodes */
+        cur = node->children;
+        while (cur) {
+                xmlNodePtr this = cur;
+                cur = cur->next;
+                if (! xmlStrcmp (this->name, GVC_SOUND_NAME)) {
+                        xmlUnlinkNode (this);
+                        xmlFreeNode (this);
+                }
+        }
+
+        return value;
+}
+
+static void
+populate_model_from_node (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          xmlNodePtr            node)
+{
+        xmlNodePtr child;
+        xmlChar   *filename;
+        xmlChar   *name;
+
+        filename = NULL;
+        name = xml_get_and_trim_names (node);
+        for (child = node->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+
+                if (xmlStrcmp (child->name, GVC_SOUND_FILENAME) == 0) {
+                        filename = xmlNodeGetContent (child);
+                } else if (xmlStrcmp (child->name, GVC_SOUND_NAME) == 0) {
+                        /* EH? should have been trimmed */
+                }
+        }
+
+        if (filename != NULL && name != NULL) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   ALERT_IDENTIFIER_COL, filename,
+                                                   ALERT_DISPLAY_COL, name,
+                                                   ALERT_SOUND_TYPE_COL, _("Built-in"),
+                                                   ALERT_ACTIVE_COL, FALSE,
+                                                   -1);
+        }
+
+        xmlFree (filename);
+        xmlFree (name);
+}
+
+static void
+populate_model_from_file (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          const char           *filename)
+{
+        xmlDocPtr  doc;
+        xmlNodePtr root;
+        xmlNodePtr child;
+        gboolean   exists;
+
+        exists = g_file_test (filename, G_FILE_TEST_EXISTS);
+        if (! exists) {
+                return;
+        }
+
+        doc = xmlParseFile (filename);
+        if (doc == NULL) {
+                return;
+        }
+
+        root = xmlDocGetRootElement (doc);
+
+        for (child = root->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+                if (xmlStrcmp (child->name, GVC_SOUND_SOUND) != 0) {
+                        continue;
+                }
+
+                populate_model_from_node (chooser, model, child);
+        }
+
+        xmlFreeDoc (doc);
+}
+
+static void
+populate_model_from_dir (GvcSoundThemeChooser *chooser,
+                         GtkTreeModel         *model,
+                         const char           *dirname)
+{
+        GDir       *d;
+        const char *name;
+
+        d = g_dir_open (dirname, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *path;
+
+                if (! g_str_has_suffix (name, ".xml")) {
+                        continue;
+                }
+
+                path = g_build_filename (dirname, name, NULL);
+                populate_model_from_file (chooser, model, path);
+                g_free (path);
+        }
+
+        g_dir_close (d);
+}
+
+static gboolean
+save_alert_sounds (GvcSoundThemeChooser  *chooser,
+                   const char            *id)
+{
+        const char *sounds[3] = { "bell-terminal", "bell-window-system", NULL };
+        char *path;
+
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+        } else {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+                add_custom_file (sounds, id);
+        }
+
+        /* And poke the directory so the theme gets updated */
+        path = custom_theme_dir_path (NULL);
+        if (utime (path, NULL) != 0) {
+                g_warning ("Failed to update mtime for directory '%s': %s",
+                           path, g_strerror (errno));
+        }
+        g_free (path);
+
+        return FALSE;
+}
+
+
+static void
+update_alert_model (GvcSoundThemeChooser  *chooser,
+                    const char            *id)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        gtk_tree_model_get_iter_first (model, &iter);
+        do {
+                gboolean toggled;
+                char    *this_id;
+
+                gtk_tree_model_get (model, &iter,
+                                    ALERT_IDENTIFIER_COL, &this_id,
+                                    -1);
+
+                if (strcmp (this_id, id) == 0) {
+                        toggled = TRUE;
+                } else {
+                        toggled = FALSE;
+                }
+                g_free (this_id);
+
+                gtk_list_store_set (GTK_LIST_STORE (model),
+                                    &iter,
+                                    ALERT_ACTIVE_COL, toggled,
+                                    -1);
+        } while (gtk_tree_model_iter_next (model, &iter));
+}
+
+static void
+update_alert (GvcSoundThemeChooser *chooser,
+              const char           *alert_id)
+{
+        GtkTreeModel *theme_model;
+        GtkTreeIter   iter;
+        char         *theme;
+        char         *parent;
+        gboolean      is_custom;
+        gboolean      is_default;
+        gboolean      add_custom;
+        gboolean      remove_custom;
+
+        theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        /* Get the current theme's name, and set the parent */
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        gtk_tree_model_get (theme_model, &iter,
+                            THEME_IDENTIFIER_COL, &theme,
+                            THEME_IDENTIFIER_COL, &parent,
+                            -1);
+        is_custom = strcmp (theme, CUSTOM_THEME_NAME) == 0;
+        is_default = strcmp (alert_id, DEFAULT_ALERT_ID) == 0;
+
+        /* So a few possibilities:
+         * 1. Named theme, default alert selected: noop
+         * 2. Named theme, alternate alert selected: create new custom with sound
+         * 3. Custom theme, default alert selected: remove sound and possibly custom
+         * 4. Custom theme, alternate alert selected: update custom sound
+         */
+        add_custom = FALSE;
+        remove_custom = FALSE;
+        if (! is_custom && is_default) {
+                /* remove custom just in case */
+                remove_custom = TRUE;
+        } else if (! is_custom && ! is_default) {
+                create_custom_theme (parent);
+                save_alert_sounds (chooser, alert_id);
+                add_custom = TRUE;
+        } else if (is_custom && is_default) {
+                save_alert_sounds (chooser, alert_id);
+                /* after removing files check if it is empty */
+                if (custom_theme_dir_is_empty ()) {
+                        remove_custom = TRUE;
+                }
+        } else if (is_custom && ! is_default) {
+                save_alert_sounds (chooser, alert_id);
+        }
+
+        if (add_custom) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (theme_model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   THEME_DISPLAY_COL, _("Custom"),
+                                                   THEME_IDENTIFIER_COL, CUSTOM_THEME_NAME,
+                                                   THEME_PARENT_ID_COL, theme,
+                                                   -1);
+                set_combox_for_theme_name (chooser, CUSTOM_THEME_NAME);
+        } else if (remove_custom) {
+                gtk_tree_model_get_iter_first (theme_model, &iter);
+                do {
+                        char *this_parent;
+
+                        gtk_tree_model_get (theme_model, &iter,
+                                            THEME_PARENT_ID_COL, &this_parent,
+                                            -1);
+                        if (this_parent != NULL && strcmp (this_parent, CUSTOM_THEME_NAME) != 0) {
+                                g_free (this_parent);
+                                gtk_list_store_remove (GTK_LIST_STORE (theme_model), &iter);
+                                break;
+                        }
+                        g_free (this_parent);
+                } while (gtk_tree_model_iter_next (theme_model, &iter));
+
+                delete_custom_theme_dir ();
+
+                set_combox_for_theme_name (chooser, parent);
+        }
+
+        update_alert_model (chooser, alert_id);
+
+        g_free (theme);
+        g_free (parent);
+}
+
+static void
+on_alert_toggled (GtkCellRendererToggle *renderer,
+                  char                  *path_str,
+                  GvcSoundThemeChooser  *chooser)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreePath  *path;
+        gboolean      toggled;
+        char         *id;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        path = gtk_tree_path_new_from_string (path_str);
+        gtk_tree_model_get_iter (model, &iter, path);
+        gtk_tree_path_free (path);
+
+        id = NULL;
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            ALERT_ACTIVE_COL, &toggled,
+                            -1);
+
+        toggled ^= 1;
+        if (toggled) {
+                update_alert (chooser, id);
+        }
+
+        g_free (id);
+}
+
+static void
+play_preview_for_path (GvcSoundThemeChooser *chooser, GtkTreePath *path)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreeIter   theme_iter;
+        gchar        *id = NULL;
+        gchar        *parent_theme = NULL;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        if (gtk_tree_model_get_iter (model, &iter, path) == FALSE)
+                return;
+
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            -1);
+        if (id == NULL)
+                return;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &theme_iter)) {
+                GtkTreeModel *theme_model;
+                gchar        *theme_id = NULL;
+                gchar        *parent_id = NULL;
+
+                theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+                gtk_tree_model_get (theme_model, &theme_iter,
+                                    THEME_IDENTIFIER_COL, &theme_id,
+                                    THEME_PARENT_ID_COL, &parent_id, -1);
+                if (theme_id && strcmp (theme_id, CUSTOM_THEME_NAME) == 0)
+                        parent_theme = g_strdup (parent_id);
+
+                g_free (theme_id);
+                g_free (parent_id);
+        }
+
+        /* special case: for the default item on custom themes
+         * play the alert for the parent theme */
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                if (parent_theme != NULL) {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_CANBERRA_XDG_THEME_NAME, parent_theme,
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                } else {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                }
+        } else {
+                ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                        CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                        CA_PROP_MEDIA_FILENAME, id,
+                                        CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                        CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                        CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                        CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                        NULL);
+
+        }
+        g_free (parent_theme);
+        g_free (id);
+}
+
+static void
+on_treeview_row_activated (GtkTreeView          *treeview,
+                           GtkTreePath          *path,
+                           GtkTreeViewColumn    *column,
+                           GvcSoundThemeChooser *chooser)
+{
+        play_preview_for_path (chooser, path);
+}
+
+static void
+on_treeview_selection_changed (GtkTreeSelection     *selection,
+                               GvcSoundThemeChooser *chooser)
+{
+        GList        *paths;
+        GtkTreeModel *model;
+        GtkTreePath  *path;
+
+        if (chooser->priv->treeview == NULL)
+                return;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        paths = gtk_tree_selection_get_selected_rows (selection, &model);
+        if (paths == NULL)
+                return;
+
+        path = paths->data;
+        play_preview_for_path (chooser, path);
+
+        g_list_foreach (paths, (GFunc)gtk_tree_path_free, NULL);
+        g_list_free (paths);
+}
+
+static GtkWidget *
+create_alert_treeview (GvcSoundThemeChooser *chooser)
+{
+        GtkListStore         *store;
+        GtkWidget            *treeview;
+        GtkCellRenderer      *renderer;
+        GtkTreeViewColumn    *column;
+        GtkTreeSelection     *selection;
+
+        treeview = gtk_tree_view_new ();
+
+        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
+        g_signal_connect (G_OBJECT (treeview),
+                          "row-activated",
+                          G_CALLBACK (on_treeview_row_activated),
+                          chooser);
+
+        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+        gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+        g_signal_connect (G_OBJECT (selection),
+                          "changed",
+                          G_CALLBACK (on_treeview_selection_changed),
+                          chooser);
+
+        /* Setup the tree model, 3 columns:
+         * - display name
+         * - sound id
+         * - sound type
+         */
+        store = gtk_list_store_new (ALERT_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_BOOLEAN);
+
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           ALERT_IDENTIFIER_COL, DEFAULT_ALERT_ID,
+                                           ALERT_DISPLAY_COL, _("Default"),
+                                           ALERT_SOUND_TYPE_COL, _("From theme"),
+                                           ALERT_ACTIVE_COL, TRUE,
+                                           -1);
+
+        populate_model_from_dir (chooser, GTK_TREE_MODEL (store), SOUND_SET_DIR);
+
+        gtk_tree_view_set_model (GTK_TREE_VIEW (treeview),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_toggle_new ();
+        gtk_cell_renderer_toggle_set_radio (GTK_CELL_RENDERER_TOGGLE (renderer), TRUE);
+
+        column = gtk_tree_view_column_new_with_attributes (NULL,
+                                                           renderer,
+                                                           "active", ALERT_ACTIVE_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+        g_signal_connect (renderer,
+                          "toggled",
+                          G_CALLBACK (on_alert_toggled),
+                          chooser);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Name"),
+                                                           renderer,
+                                                           "text", ALERT_DISPLAY_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Type"),
+                                                           renderer,
+                                                           "text", ALERT_SOUND_TYPE_COL,
+                                                           NULL);
+
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        return treeview;
+}
+
+static int
+get_file_type (const char *sound_name,
+               char      **linked_name)
+{
+        char *name, *filename;
+
+        *linked_name = NULL;
+
+        name = g_strdup_printf ("%s.disabled", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_REGULAR) != FALSE) {
+                g_free (filename);
+                return SOUND_TYPE_OFF;
+        }
+        g_free (filename);
+
+        /* We only check for .ogg files because those are the
+         * only ones we create */
+        name = g_strdup_printf ("%s.ogg", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_SYMLINK) != FALSE) {
+                *linked_name = g_file_read_link (filename, NULL);
+                g_free (filename);
+                return SOUND_TYPE_CUSTOM;
+        }
+        g_free (filename);
+
+        return SOUND_TYPE_BUILTIN;
+}
+
+static void
+update_alerts_from_theme_name (GvcSoundThemeChooser *chooser,
+                               const gchar          *name)
+{
+        if (strcmp (name, CUSTOM_THEME_NAME) != 0) {
+                /* reset alert to default */
+                update_alert (chooser, DEFAULT_ALERT_ID);
+        } else {
+                int   sound_type;
+                char *linkname;
+
+                linkname = NULL;
+                sound_type = get_file_type ("bell-terminal", &linkname);
+                g_debug ("Found link: %s", linkname);
+                if (sound_type == SOUND_TYPE_CUSTOM) {
+                        update_alert (chooser, linkname);
+                }
+        }
+}
+
+static void
+update_theme (GvcSoundThemeChooser *chooser)
+{
+        char        *theme_name;
+        gboolean     events_enabled;
+        gboolean     feedback_enabled;
+
+        feedback_enabled = g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY);
+        set_input_feedback_enabled (chooser, feedback_enabled);
+
+        events_enabled = g_settings_get_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY);
+        if (events_enabled) {
+                theme_name = g_settings_get_string (chooser->priv->sound_settings, SOUND_THEME_KEY);
+        } else {
+                theme_name = g_strdup (NO_SOUNDS_THEME_NAME);
+        }
+
+        gtk_widget_set_sensitive (chooser->priv->selection_box, events_enabled);
+        gtk_widget_set_sensitive (chooser->priv->click_feedback_button, events_enabled);
+
+        set_combox_for_theme_name (chooser, theme_name);
+
+        update_alerts_from_theme_name (chooser, theme_name);
+
+        g_free (theme_name);
+}
+
+static void
+gvc_sound_theme_chooser_class_init (GvcSoundThemeChooserClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_sound_theme_chooser_dispose;
+}
+
+static void
+on_click_feedback_toggled (GtkToggleButton      *button,
+                           GvcSoundThemeChooser *chooser)
+{
+        gboolean enabled;
+
+        enabled = gtk_toggle_button_get_active (button);
+
+        g_settings_set_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY, enabled);
+}
+
+static void
+on_key_changed (GSettings            *settings,
+                gchar                *key,
+                GvcSoundThemeChooser *chooser)
+{
+        if (!strcmp (key, EVENT_SOUNDS_KEY) ||
+            !strcmp (key, SOUND_THEME_KEY) ||
+            !strcmp (key, INPUT_SOUNDS_KEY))
+                update_theme (chooser);
+}
+
+static void
+setup_list_size_constraint (GtkWidget *widget,
+                            GtkWidget *to_size)
+{
+        GtkRequisition req;
+        gint           sc_height;
+        int            max_height;
+
+        /* Constrain height to be the tree height up to a max */
+        gdk_window_get_geometry (gdk_screen_get_root_window (gtk_widget_get_screen (widget)),
+                                 NULL, NULL, NULL, &sc_height);
+
+        max_height = sc_height / 4;
+
+        // XXX this doesn't work
+        gtk_widget_get_preferred_size (to_size, NULL, &req);
+
+        gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (widget),
+                                                    MIN (req.height, max_height));
+}
+
+static void
+gvc_sound_theme_chooser_init (GvcSoundThemeChooser *chooser)
+{
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *scrolled_window;
+        gchar       *str;
+
+        chooser->priv = gvc_sound_theme_chooser_get_instance_private (chooser);
+
+        chooser->priv->theme_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->theme_box, FALSE, FALSE, 0);
+
+        label = gtk_label_new_with_mnemonic (_("Sound _theme:"));
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), label, FALSE, FALSE, 0);
+        chooser->priv->combo_box = gtk_combo_box_new ();
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), chooser->priv->combo_box, FALSE, FALSE, 6);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->combo_box);
+
+        chooser->priv->sound_settings = g_settings_new (KEY_SOUNDS_SCHEMA);
+
+        g_signal_connect (G_OBJECT (chooser->priv->sound_settings),
+                          "changed",
+                          G_CALLBACK (on_key_changed),
+                          chooser);
+
+        str = g_strdup_printf ("<b>%s</b>", _("C_hoose an alert sound:"));
+        chooser->priv->selection_box = box = gtk_frame_new (str);
+        g_free (str);
+
+        label = gtk_frame_get_label_widget (GTK_FRAME (box));
+        gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
+        gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+        gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
+
+        gtk_box_pack_start (GTK_BOX (chooser), box, TRUE, TRUE, 6);
+
+        chooser->priv->treeview = create_alert_treeview (chooser);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->treeview);
+
+        scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+        gtk_widget_set_hexpand (scrolled_window, TRUE);
+        gtk_widget_set_vexpand (scrolled_window, TRUE);
+        gtk_widget_set_margin_top (scrolled_window, 6);
+
+        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+                                        GTK_POLICY_NEVER,
+                                        GTK_POLICY_AUTOMATIC);
+        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
+                                             GTK_SHADOW_IN);
+
+        gtk_container_add (GTK_CONTAINER (scrolled_window), chooser->priv->treeview);
+        gtk_container_add (GTK_CONTAINER (box), scrolled_window);
+
+        chooser->priv->click_feedback_button = gtk_check_button_new_with_mnemonic (_("Enable _window and button sounds"));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY));
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->click_feedback_button,
+                            FALSE, FALSE, 0);
+
+        g_signal_connect (G_OBJECT (chooser->priv->click_feedback_button),
+                          "toggled",
+                          G_CALLBACK (on_click_feedback_toggled),
+                          chooser);
+
+        setup_theme_selector (chooser);
+        update_theme (chooser);
+
+        setup_list_size_constraint (scrolled_window, chooser->priv->treeview);
+}
+
+static void
+gvc_sound_theme_chooser_dispose (GObject *object)
+{
+        GvcSoundThemeChooser *chooser;
+
+        chooser = GVC_SOUND_THEME_CHOOSER (object);
+
+        g_clear_object (&chooser->priv->sound_settings);
+
+        G_OBJECT_CLASS (gvc_sound_theme_chooser_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_sound_theme_chooser_new (void)
+{
+        return g_object_new (GVC_TYPE_SOUND_THEME_CHOOSER,
+                                "spacing", 6,
+                                "orientation", GTK_ORIENTATION_VERTICAL,
+                                NULL);
+}
+
+
+
+ + + diff --git a/2020-04-09-124106-6009-cppcheck@49d783c683ff_enum-conversion/2.html b/2020-04-09-124106-6009-cppcheck@49d783c683ff_enum-conversion/2.html new file mode 100644 index 0000000..bacfabb --- /dev/null +++ b/2020-04-09-124106-6009-cppcheck@49d783c683ff_enum-conversion/2.html @@ -0,0 +1,1110 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <canberra.h>
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-speaker-test.h"
+#include "gvc-utils.h"
+
+struct _GvcSpeakerTestPrivate
+{
+        GArray           *controls;
+        ca_context       *canberra;
+        MateMixerStream  *stream;
+};
+
+enum {
+        PROP_0,
+        PROP_STREAM,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_speaker_test_dispose    (GObject             *object);
+static void gvc_speaker_test_finalize   (GObject             *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSpeakerTest, gvc_speaker_test, GTK_TYPE_GRID)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+typedef struct {
+        MateMixerChannelPosition position;
+        guint left;
+        guint top;
+} TablePosition;
+
+static const TablePosition positions[] = {
+        /* Position, X, Y */
+        { MATE_MIXER_CHANNEL_FRONT_LEFT, 0, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_LEFT_CENTER, 1, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_CENTER, 2, 0, },
+        { MATE_MIXER_CHANNEL_MONO, 2, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT_CENTER, 3, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT, 4, 0, },
+        { MATE_MIXER_CHANNEL_SIDE_LEFT, 0, 1, },
+        { MATE_MIXER_CHANNEL_SIDE_RIGHT, 4, 1, },
+        { MATE_MIXER_CHANNEL_BACK_LEFT, 0, 2, },
+        { MATE_MIXER_CHANNEL_BACK_CENTER, 2, 2, },
+        { MATE_MIXER_CHANNEL_BACK_RIGHT, 4, 2, },
+        { MATE_MIXER_CHANNEL_LFE, 3, 2 }
+};
+
+MateMixerStream *
+gvc_speaker_test_get_stream (GvcSpeakerTest *test)
+{
+        g_return_val_if_fail (GVC_IS_SPEAKER_TEST (test), NULL);
+
+        return test->priv->stream;
+}
+
+static void
+gvc_speaker_test_set_stream (GvcSpeakerTest *test, MateMixerStream *stream)
+{
+        MateMixerStreamControl *control;
+        const gchar            *name;
+        guint                   i;
+
+        name = mate_mixer_stream_get_name (stream);
+        control = mate_mixer_stream_get_default_control (stream);
+
+        ca_context_change_device (test->priv->canberra, name);
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                gboolean has_position =
+                        mate_mixer_stream_control_has_channel_position (control, positions[i].position);
+
+                gtk_widget_set_visible (g_array_index (test->priv->controls, GtkWidget *, i),
+                                        has_position);
+        }
+
+        test->priv->stream = g_object_ref (stream);
+}
+
+static void
+gvc_speaker_test_set_property (GObject       *object,
+                               guint          prop_id,
+                               const GValue  *value,
+                               GParamSpec    *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                gvc_speaker_test_set_stream (self, g_value_get_object (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_get_property (GObject     *object,
+                               guint        prop_id,
+                               GValue      *value,
+                               GParamSpec  *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                g_value_set_object (value, self->priv->stream);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_class_init (GvcSpeakerTestClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose  = gvc_speaker_test_dispose;
+        object_class->finalize = gvc_speaker_test_finalize;
+        object_class->set_property = gvc_speaker_test_set_property;
+        object_class->get_property = gvc_speaker_test_get_property;
+
+        properties[PROP_STREAM] =
+                g_param_spec_object ("stream",
+                                     "Stream",
+                                     "MateMixer stream",
+                                     MATE_MIXER_TYPE_STREAM,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+}
+
+static const gchar *
+sound_name (MateMixerChannelPosition position)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return "audio-channel-front-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return "audio-channel-front-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return "audio-channel-front-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return "audio-channel-rear-left";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return "audio-channel-rear-right";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return "audio-channel-rear-center";
+        case MATE_MIXER_CHANNEL_LFE:
+                return "audio-channel-lfe";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return "audio-channel-side-left";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return "audio-channel-side-right";
+        default:
+                return NULL;
+        }
+}
+
+static const gchar *
+icon_name (MateMixerChannelPosition position, gboolean playing)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return playing
+                        ? "audio-speaker-left-testing"
+                        : "audio-speaker-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return playing
+                        ? "audio-speaker-right-testing"
+                        : "audio-speaker-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return playing
+                        ? "audio-speaker-center-testing"
+                        : "audio-speaker-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return playing
+                        ? "audio-speaker-left-back-testing"
+                        : "audio-speaker-left-back";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return playing
+                        ? "audio-speaker-right-back-testing"
+                        : "audio-speaker-right-back";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return playing
+                        ? "audio-speaker-center-back-testing"
+                        : "audio-speaker-center-back";
+        case MATE_MIXER_CHANNEL_LFE:
+                return playing
+                        ? "audio-subwoofer-testing"
+                        : "audio-subwoofer";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return playing
+                        ? "audio-speaker-left-side-testing"
+                        : "audio-speaker-left-side";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return playing
+                        ? "audio-speaker-right-side-testing"
+                        : "audio-speaker-right-side";
+        default:
+                return NULL;
+        }
+}
+
+static void
+update_button (GtkWidget *control)
+{
+        GtkWidget *button;
+        GtkWidget *image;
+        gboolean   playing;
+        MateMixerChannelPosition position;
+
+        button = g_object_get_data (G_OBJECT (control), "button");
+        image  = g_object_get_data (G_OBJECT (control), "image");
+
+        position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+        playing  = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        gtk_button_set_label (GTK_BUTTON (button), playing ? _("Stop") : _("Test"));
+
+        gtk_image_set_from_icon_name (GTK_IMAGE (image),
+                                      icon_name (position, playing),
+                                      GTK_ICON_SIZE_DIALOG);
+}
+
+static gboolean
+idle_cb (GtkWidget *control)
+{
+        if (control != NULL) {
+                /* This is called in the background thread, hence forward to main thread
+                 * via idle callback */
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+
+                update_button (control);
+        }
+        return FALSE;
+}
+
+static void
+finish_cb (ca_context *c, uint32_t id, int error_code, void *userdata)
+{
+        GtkWidget *control = (GtkWidget *) userdata;
+
+        if (error_code == CA_ERROR_DESTROYED || control == NULL)
+                return;
+
+        g_idle_add ((GSourceFunc) idle_cb, control);
+}
+
+static void
+on_test_button_clicked (GtkButton *button, GtkWidget *control)
+{
+        gboolean    playing;
+        ca_context *canberra;
+
+        canberra = g_object_get_data (G_OBJECT (control), "canberra");
+
+        ca_context_cancel (canberra, 1);
+
+        playing = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        if (playing) {
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        } else {
+                MateMixerChannelPosition position;
+                const gchar *name;
+                ca_proplist *proplist;
+
+                position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+
+                ca_proplist_create (&proplist);
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_ROLE, "test");
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_NAME,
+                                  gvc_channel_position_to_pretty_string (position));
+                ca_proplist_sets (proplist,
+                                  CA_PROP_CANBERRA_FORCE_CHANNEL,
+                                  gvc_channel_position_to_pulse_string (position));
+
+                ca_proplist_sets (proplist, CA_PROP_CANBERRA_ENABLE, "1");
+
+                name = sound_name (position);
+                if (name != NULL) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, name);
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, "audio-test-signal");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets(proplist, CA_PROP_EVENT_ID, "bell-window-system");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (playing));
+        }
+
+        update_button (control);
+}
+
+static GtkWidget *
+create_control (ca_context *canberra, MateMixerChannelPosition position)
+{
+        GtkWidget   *control;
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *image;
+        GtkWidget   *test_button;
+        const gchar *name;
+
+        control = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+        box     = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        g_object_set_data (G_OBJECT (control), "position", GINT_TO_POINTER (position));
+        g_object_set_data (G_OBJECT (control), "canberra", canberra);
+
+        name = icon_name (position, FALSE);
+        if (name == NULL)
+                name = "audio-volume-medium";
+
+        image = gtk_image_new_from_icon_name (name, GTK_ICON_SIZE_DIALOG);
+        g_object_set_data (G_OBJECT (control), "image", image);
+        gtk_box_pack_start (GTK_BOX (control), image, FALSE, FALSE, 0);
+
+        label = gtk_label_new (gvc_channel_position_to_pretty_string (position));
+        gtk_box_pack_start (GTK_BOX (control), label, FALSE, FALSE, 0);
+
+        test_button = gtk_button_new_with_label (_("Test"));
+        g_signal_connect (G_OBJECT (test_button),
+                          "clicked",
+                          G_CALLBACK (on_test_button_clicked),
+                          control);
+
+        g_object_set_data (G_OBJECT (control), "button", test_button);
+
+        gtk_box_pack_start (GTK_BOX (box), test_button, TRUE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (control), box, FALSE, FALSE, 0);
+
+        gtk_widget_show_all (control);
+
+        return control;
+}
+
+static void
+create_controls (GvcSpeakerTest *test)
+{
+        guint i;
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                GtkWidget *control = create_control (test->priv->canberra, positions[i].position);
+
+                gtk_grid_attach (GTK_GRID (test),
+                                 control,
+                                 positions[i].left,
+                                 positions[i].top,
+                                 1, 1);
+                g_array_insert_val (test->priv->controls, i, control);
+        }
+}
+
+static void
+gvc_speaker_test_init (GvcSpeakerTest *test)
+{
+        GtkWidget *face;
+
+        test->priv = gvc_speaker_test_get_instance_private (test);
+
+        gtk_container_set_border_width (GTK_CONTAINER (test), 12);
+
+        face = gtk_image_new_from_icon_name ("face-smile", GTK_ICON_SIZE_DIALOG);
+
+        gtk_grid_attach (GTK_GRID (test),
+                         face,
+                         1, 1,
+                         3, 1);
+
+
+        gtk_grid_set_baseline_row (GTK_GRID (test), 1);
+        gtk_widget_show (face);
+
+        ca_context_create (&test->priv->canberra);
+
+        /* The test sounds are played for a single channel, set up using the
+         * FORCE_CHANNEL property of libcanberra; this property is only supported
+         * in the PulseAudio backend, so avoid other backends completely */
+        ca_context_set_driver (test->priv->canberra, "pulse");
+
+        ca_context_change_props (test->priv->canberra,
+                                 CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+                                 CA_PROP_APPLICATION_NAME, _("Volume Control"),
+                                 CA_PROP_APPLICATION_VERSION, VERSION,
+                                 CA_PROP_APPLICATION_ICON_NAME, "multimedia-volume-control",
+                                 NULL);
+
+        test->priv->controls = g_array_new (FALSE, FALSE, sizeof (GtkWidget *));
+
+        create_controls (test);
+}
+
+static void
+gvc_speaker_test_dispose (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        g_clear_object (&test->priv->stream);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->dispose (object);
+}
+
+static void
+gvc_speaker_test_finalize (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        ca_context_destroy (test->priv->canberra);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->finalize (object);
+}
+
+GtkWidget *
+gvc_speaker_test_new (MateMixerStream *stream)
+{
+        GObject *test;
+
+        g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL);
+
+        test = g_object_new (GVC_TYPE_SPEAKER_TEST,
+                             "row-spacing", 6,
+                             "column-spacing", 6,
+                             "row-homogeneous", TRUE,
+                             "column-homogeneous", TRUE,
+                             "stream", stream,
+                             NULL);
+
+        return GTK_WIDGET (test);
+}
+
+
+
+ + + diff --git a/2020-04-09-124106-6009-cppcheck@49d783c683ff_enum-conversion/index.html b/2020-04-09-124106-6009-cppcheck@49d783c683ff_enum-conversion/index.html new file mode 100644 index 0000000..59baeb0 --- /dev/null +++ b/2020-04-09-124106-6009-cppcheck@49d783c683ff_enum-conversion/index.html @@ -0,0 +1,108 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
mate-volume-control/gvc-combo-box.c
70unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
mate-volume-control/gvc-sound-theme-chooser.c
735ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
746ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
758ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
mate-volume-control/gvc-speaker-test.c
53unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+ + + diff --git a/2020-04-09-124106-6009-cppcheck@49d783c683ff_enum-conversion/stats.html b/2020-04-09-124106-6009-cppcheck@49d783c683ff_enum-conversion/stats.html new file mode 100644 index 0000000..3fb6add --- /dev/null +++ b/2020-04-09-124106-6009-cppcheck@49d783c683ff_enum-conversion/stats.html @@ -0,0 +1,93 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+

Top 10 files for error severity, total findings: 2
+   1  mate-volume-control/gvc-speaker-test.c
+   1  mate-volume-control/gvc-combo-box.c
+

+

Top 10 files for information severity, total findings: 3
+   3  mate-volume-control/gvc-sound-theme-chooser.c
+

+ +
+ + + diff --git a/2020-04-09-124106-6009-cppcheck@49d783c683ff_enum-conversion/style.css b/2020-04-09-124106-6009-cppcheck@49d783c683ff_enum-conversion/style.css new file mode 100644 index 0000000..c39571c --- /dev/null +++ b/2020-04-09-124106-6009-cppcheck@49d783c683ff_enum-conversion/style.css @@ -0,0 +1,149 @@ + +body { + font: 13px Arial, Verdana, Sans-Serif; + margin: 0; + width: auto; +} + +h1 { + margin: 10px; +} + +#footer > p { + margin: 4px; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + border: 1px dotted black; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #B6B6B4; +} + +.inconclusive2 { + background-color: #B6B6B4; + border: 1px dotted black; + display: inline-block; + margin-left: 4px; +} + +div.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +div.verbose div.content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid black; + background-color: #FFFFCC; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +#header { + border-bottom: thin solid #aaa; +} + +#menu { + float: left; + margin-top: 5px; + text-align: left; + width: 150px; + /*height: 75%;*/ + position: fixed; + overflow: auto; + z-index: 1; +} + +#menu_index { + float: left; + margin-top: 5px; + padding-left: 5px; + text-align: left; + width: 300px; + /*height: 75%;*/ + position: fixed; + overflow: auto; + z-index: 1; +} + +#menu > a { + display: block; + margin-left: 10px; + font: 12px; + z-index: 1; +} + +#filename { + margin-left: 10px; + font: 12px; + z-index: 1; +} + +.highlighttable { + background-color:white; + z-index: 10; + position: relative; + margin: -10 px; +} + +#content { + background-color: white; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + float: left; + margin: 5px; + margin-left: 10px; + padding: 0 10px 10px 10px; + width: 80%; + padding-left: 150px; +} + +#content_index { + background-color: white; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + float: left; + margin: 5px; + margin-left: 10px; + padding: 0 10px 10px 10px; + width: 80%; + padding-left: 300px; +} + +.linenos { + border-right: thin solid #aaa; + color: lightgray; + padding-right: 6px; +} + +#footer { + border-top: thin solid #aaa; + clear: both; + font-size: 90%; + margin-top: 5px; +} + +#footer ul { + list-style-type: none; + padding-left: 0; +} diff --git a/2020-04-10-141956-3126-cppcheck@de1524253905_master/0.html b/2020-04-10-141956-3126-cppcheck@de1524253905_master/0.html new file mode 100644 index 0000000..e262ed0 --- /dev/null +++ b/2020-04-10-141956-3126-cppcheck@de1524253905_master/0.html @@ -0,0 +1,1038 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-combo-box.h"
+
+struct _GvcComboBoxPrivate
+{
+        GtkWidget       *drop_box;
+        GtkWidget       *start_box;
+        GtkWidget       *end_box;
+        GtkWidget       *label;
+        GtkWidget       *button;
+        GtkTreeModel    *model;
+        GtkWidget       *combobox;
+        MateMixerSwitch *swtch;
+};
+
+enum {
+        COL_NAME,
+        COL_HUMAN_NAME,
+        NUM_COLS
+};
+
+enum {
+        CHANGING,
+        BUTTON_CLICKED,
+        LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+enum {
+        PROP_0,
+        PROP_SWITCH,
+        PROP_LABEL,
+        PROP_SHOW_BUTTON,
+        PROP_BUTTON_LABEL,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_combo_box_dispose    (GObject          *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcComboBox, gvc_combo_box, GTK_TYPE_BOX)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+MateMixerSwitch *
+gvc_combo_box_get_switch (GvcComboBox *combobox)
+{
+        g_return_val_if_fail (GVC_IS_COMBO_BOX (combobox), NULL);
+
+        return combobox->priv->swtch;
+}
+
+void
+gvc_combo_box_set_size_group (GvcComboBox  *combobox,
+                              GtkSizeGroup *group,
+                              gboolean      symmetric)
+{
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (GTK_IS_SIZE_GROUP (group));
+
+        if (group != NULL) {
+                gtk_size_group_add_widget (group, combobox->priv->start_box);
+                if (symmetric == TRUE)
+                        gtk_size_group_add_widget (group, combobox->priv->end_box);
+        }
+        gtk_widget_queue_draw (GTK_WIDGET (combobox));
+}
+
+static void
+on_switch_active_option_notify (MateMixerSwitch *swtch,
+                                GParamSpec      *pspec,
+                                GvcComboBox     *combobox)
+{
+        GtkTreeIter            iter;
+        MateMixerSwitchOption *active;
+        gboolean               cont;
+        const gchar           *name;
+
+        active = mate_mixer_switch_get_active_option (swtch);
+        if (G_UNLIKELY (active == NULL)) {
+                g_warn_if_reached ();
+                return;
+        }
+
+        /* Select the newly activated switch option in the combo box */
+        name = mate_mixer_switch_option_get_name (active);
+        cont = gtk_tree_model_get_iter_first (combobox->priv->model, &iter);
+        while (cont == TRUE) {
+                gchar *current;
+
+                gtk_tree_model_get (combobox->priv->model, &iter,
+                                    COL_NAME, &current,
+                                    -1);
+                if (g_strcmp0 (name, current) == 0) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox), &iter);
+                        g_free (current);
+                        return;
+                }
+                g_free (current);
+
+                cont = gtk_tree_model_iter_next (combobox->priv->model, &iter);
+        }
+        g_warning ("Could not find switch option '%s' in combo box", name);
+}
+
+static void
+gvc_combo_box_set_switch (GvcComboBox *combobox, MateMixerSwitch *swtch)
+{
+        MateMixerSwitchOption *active;
+        const GList           *options;
+
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (MATE_MIXER_IS_SWITCH (swtch));
+
+        combobox->priv->swtch = g_object_ref (swtch);
+
+        active  = mate_mixer_switch_get_active_option (swtch);
+        options = mate_mixer_switch_list_options (swtch);
+        while (options != NULL) {
+                GtkTreeIter            iter;
+                MateMixerSwitchOption *option = MATE_MIXER_SWITCH_OPTION (options->data);
+
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (combobox->priv->model),
+                                                   &iter,
+                                                   G_MAXINT,
+                                                   COL_NAME,
+                                                   mate_mixer_switch_option_get_name (option),
+                                                   COL_HUMAN_NAME,
+                                                   mate_mixer_switch_option_get_label (option),
+                                                   -1);
+
+                /* Select the currently active option of the switch */
+                if (option == active) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox),
+                                                       &iter);
+                }
+                options = options->next;
+        }
+
+        g_signal_connect (G_OBJECT (swtch),
+                          "notify::active-option",
+                          G_CALLBACK (on_switch_active_option_notify),
+                          combobox);
+}
+
+static void
+gvc_combo_box_set_property (GObject       *object,
+                            guint          prop_id,
+                            const GValue  *value,
+                            GParamSpec    *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                gvc_combo_box_set_switch (self, g_value_get_object (value));
+                break;
+        case PROP_LABEL:
+                gtk_label_set_text_with_mnemonic (GTK_LABEL (self->priv->label), g_value_get_string (value));
+                break;
+        case PROP_BUTTON_LABEL:
+                gtk_button_set_label (GTK_BUTTON (self->priv->button), g_value_get_string (value));
+                break;
+        case PROP_SHOW_BUTTON:
+                gtk_widget_set_visible (self->priv->button, g_value_get_boolean (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_get_property (GObject     *object,
+                            guint        prop_id,
+                            GValue      *value,
+                            GParamSpec  *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                g_value_set_object (value, self->priv->swtch);
+                break;
+        case PROP_LABEL:
+                g_value_set_string (value, gtk_label_get_text (GTK_LABEL (self->priv->label)));
+                break;
+        case PROP_BUTTON_LABEL:
+                g_value_set_string (value, gtk_button_get_label (GTK_BUTTON (self->priv->button)));
+                break;
+        case PROP_SHOW_BUTTON:
+                g_value_set_boolean (value, gtk_widget_get_visible (self->priv->button));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_class_init (GvcComboBoxClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_combo_box_dispose;
+        object_class->set_property = gvc_combo_box_set_property;
+        object_class->get_property = gvc_combo_box_get_property;
+
+        properties[PROP_SWITCH] =
+                g_param_spec_object ("switch",
+                                     "switch",
+                                     "The MateMixerSwitch",
+                                     MATE_MIXER_TYPE_SWITCH,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_LABEL] =
+                g_param_spec_string ("label",
+                                     "label",
+                                     "The combo box label",
+                                     _("_Profile:"),
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_SHOW_BUTTON] =
+                g_param_spec_boolean ("show-button",
+                                      "show-button",
+                                      "Whether to show the button",
+                                      FALSE,
+                                      G_PARAM_READWRITE |
+                                      G_PARAM_CONSTRUCT |
+                                      G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_BUTTON_LABEL] =
+                g_param_spec_string ("button-label",
+                                     "button-label",
+                                     "The button's label",
+                                     "",
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+
+        signals[CHANGING] =
+                g_signal_new ("changing",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, changing),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__OBJECT,
+                              G_TYPE_NONE,
+                              1,
+                              MATE_MIXER_TYPE_SWITCH_OPTION);
+
+        signals[BUTTON_CLICKED] =
+                g_signal_new ("button-clicked",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, button_clicked),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
+}
+
+static void
+on_combo_box_changed (GtkComboBox *widget, GvcComboBox *combobox)
+{
+        GtkTreeIter            iter;
+        gchar                 *name;
+        MateMixerSwitchOption *option;
+
+        if (G_UNLIKELY (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter) == FALSE))
+                return;
+
+        gtk_tree_model_get (combobox->priv->model, &iter,
+                            COL_NAME, &name,
+                            -1);
+
+        option = mate_mixer_switch_get_option (combobox->priv->swtch, name);
+        if (G_UNLIKELY (option == NULL)) {
+                g_warn_if_reached ();
+                g_free (name);
+                return;
+        }
+
+        /* Inform that we are about to change the active option of the switch */
+        g_signal_emit (combobox, signals[CHANGING], 0, option);
+
+        mate_mixer_switch_set_active_option (combobox->priv->swtch, option);
+        g_free (name);
+}
+
+static void
+on_combo_box_button_clicked (GtkButton *button, GvcComboBox *combobox)
+{
+        /* The meaning of the button is defined by the owner, so only notify
+         * when it is clicked on */
+        g_signal_emit (combobox, signals[BUTTON_CLICKED], 0);
+}
+
+static void
+gvc_combo_box_init (GvcComboBox *combobox)
+{
+        GtkWidget       *frame;
+        GtkCellRenderer *renderer;
+
+        frame = gtk_frame_new (NULL);
+        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
+
+        combobox->priv = gvc_combo_box_get_instance_private (combobox);
+
+        combobox->priv->model = GTK_TREE_MODEL (gtk_list_store_new (NUM_COLS,
+                                                                    G_TYPE_STRING,
+                                                                    G_TYPE_STRING));
+
+        combobox->priv->combobox = gtk_combo_box_new_with_model (combobox->priv->model);
+
+        combobox->priv->label = gtk_label_new (NULL);
+
+        gtk_label_set_xalign (GTK_LABEL (combobox->priv->label), 0.0);
+        gtk_label_set_yalign (GTK_LABEL (combobox->priv->label), 0.5);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (combobox->priv->label),
+                                       combobox->priv->combobox);
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                    renderer,
+                                    FALSE);
+        gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                       renderer,
+                                       "text",
+                                       COL_HUMAN_NAME);
+
+        combobox->priv->drop_box  = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->start_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->end_box   = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+        /* Make sure the combo box does not get too long on long profile names */
+        g_object_set (G_OBJECT (renderer),
+                      "ellipsize",
+                      PANGO_ELLIPSIZE_END,
+                      NULL);
+
+        gtk_combo_box_set_popup_fixed_width (GTK_COMBO_BOX (combobox->priv->combobox), FALSE);
+
+        gtk_box_pack_start (GTK_BOX (combobox),
+                            frame,
+                            TRUE, TRUE, 0);
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->start_box,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->start_box),
+                            combobox->priv->label,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->combobox,
+                            TRUE, TRUE, 0);
+
+        combobox->priv->button = gtk_button_new_with_label ("");
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->button,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->end_box,
+                            FALSE, FALSE, 0);
+
+        gtk_container_add (GTK_CONTAINER (frame), combobox->priv->drop_box);
+
+        g_signal_connect (G_OBJECT (combobox->priv->combobox),
+                          "changed",
+                          G_CALLBACK (on_combo_box_changed),
+                          combobox);
+        g_signal_connect (G_OBJECT (combobox->priv->button),
+                          "clicked",
+                          G_CALLBACK (on_combo_box_button_clicked),
+                          combobox);
+
+        gtk_widget_set_no_show_all (combobox->priv->button, TRUE);
+        gtk_widget_show_all (frame);
+}
+
+static void
+gvc_combo_box_dispose (GObject *object)
+{
+        GvcComboBox *combobox;
+
+        combobox = GVC_COMBO_BOX (object);
+
+        if (G_LIKELY (combobox->priv->swtch != NULL)) {
+                g_signal_handlers_disconnect_by_func (G_OBJECT (combobox->priv->swtch),
+                                                      G_CALLBACK (on_switch_active_option_notify),
+                                                      combobox);
+                g_clear_object (&combobox->priv->swtch);
+        }
+
+        g_clear_object (&combobox->priv->model);
+
+        G_OBJECT_CLASS (gvc_combo_box_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_combo_box_new (MateMixerSwitch *swtch, const gchar *label)
+{
+        return g_object_new (GVC_TYPE_COMBO_BOX,
+                             "switch", swtch,
+                             "label", label,
+                             "orientation", GTK_ORIENTATION_HORIZONTAL,
+                             NULL);
+}
+
+
+
+ + + diff --git a/2020-04-10-141956-3126-cppcheck@de1524253905_master/1.html b/2020-04-10-141956-3126-cppcheck@de1524253905_master/1.html new file mode 100644 index 0000000..67179f2 --- /dev/null +++ b/2020-04-10-141956-3126-cppcheck@de1524253905_master/1.html @@ -0,0 +1,2368 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
+ * Copyright (C) 2008 William Jon McCann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <utime.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+#include <canberra-gtk.h>
+#include <libxml/tree.h>
+
+#include "gvc-sound-theme-chooser.h"
+#include "sound-theme-file-utils.h"
+
+struct GvcSoundThemeChooserPrivate
+{
+        GtkWidget *combo_box;
+        GtkWidget *treeview;
+        GtkWidget *theme_box;
+        GtkWidget *selection_box;
+        GtkWidget *click_feedback_button;
+        GSettings *sound_settings;
+};
+
+static void     gvc_sound_theme_chooser_dispose   (GObject            *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSoundThemeChooser, gvc_sound_theme_chooser, GTK_TYPE_BOX)
+
+#define KEY_SOUNDS_SCHEMA          "org.mate.sound"
+#define EVENT_SOUNDS_KEY           "event-sounds"
+#define INPUT_SOUNDS_KEY           "input-feedback-sounds"
+#define SOUND_THEME_KEY            "theme-name"
+
+#define DEFAULT_ALERT_ID        "__default"
+#define CUSTOM_THEME_NAME       "__custom"
+#define NO_SOUNDS_THEME_NAME    "__no_sounds"
+
+enum {
+        THEME_DISPLAY_COL,
+        THEME_IDENTIFIER_COL,
+        THEME_PARENT_ID_COL,
+        THEME_NUM_COLS
+};
+
+enum {
+        ALERT_DISPLAY_COL,
+        ALERT_IDENTIFIER_COL,
+        ALERT_SOUND_TYPE_COL,
+        ALERT_ACTIVE_COL,
+        ALERT_NUM_COLS
+};
+
+enum {
+        SOUND_TYPE_UNSET,
+        SOUND_TYPE_OFF,
+        SOUND_TYPE_DEFAULT_FROM_THEME,
+        SOUND_TYPE_BUILTIN,
+        SOUND_TYPE_CUSTOM
+};
+
+static void
+on_combobox_changed (GtkComboBox          *widget,
+                     GvcSoundThemeChooser *chooser)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        char         *theme_name;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &theme_name, -1);
+
+        g_assert (theme_name != NULL);
+
+        /* It is necessary to update the theme name before any other setting as
+         * the "changed" notification will reload the contents of the widget */
+        g_settings_set_string (chooser->priv->sound_settings, SOUND_THEME_KEY, theme_name);
+
+        /* special case for no sounds */
+        if (strcmp (theme_name, NO_SOUNDS_THEME_NAME) == 0) {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, FALSE);
+                return;
+        } else {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, TRUE);
+        }
+
+        g_free (theme_name);
+
+        /* FIXME: reset alert model */
+}
+
+static char *
+load_index_theme_name (const char *index,
+                       char      **parent)
+{
+        GKeyFile *file;
+        char *indexname = NULL;
+        gboolean hidden;
+
+        file = g_key_file_new ();
+        if (g_key_file_load_from_file (file, index, G_KEY_FILE_KEEP_TRANSLATIONS, NULL) == FALSE) {
+                g_key_file_free (file);
+                return NULL;
+        }
+        /* Don't add hidden themes to the list */
+        hidden = g_key_file_get_boolean (file, "Sound Theme", "Hidden", NULL);
+        if (!hidden) {
+                indexname = g_key_file_get_locale_string (file,
+                                                          "Sound Theme",
+                                                          "Name",
+                                                          NULL,
+                                                          NULL);
+
+                /* Save the parent theme, if there's one */
+                if (parent != NULL) {
+                        *parent = g_key_file_get_string (file,
+                                                         "Sound Theme",
+                                                         "Inherits",
+                                                         NULL);
+                }
+        }
+
+        g_key_file_free (file);
+        return indexname;
+}
+
+static void
+sound_theme_in_dir (GHashTable *hash,
+                    const char *dir)
+{
+        GDir *d;
+        const char *name;
+
+        d = g_dir_open (dir, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *dirname, *index, *indexname;
+
+                /* Look for directories */
+                dirname = g_build_filename (dir, name, NULL);
+                if (g_file_test (dirname, G_FILE_TEST_IS_DIR) == FALSE) {
+                        g_free (dirname);
+                        continue;
+                }
+
+                /* Look for index files */
+                index = g_build_filename (dirname, "index.theme", NULL);
+                g_free (dirname);
+
+                /* Check the name of the theme in the index.theme file */
+                indexname = load_index_theme_name (index, NULL);
+                g_free (index);
+                if (indexname == NULL) {
+                        continue;
+                }
+
+                g_hash_table_insert (hash, g_strdup (name), indexname);
+        }
+
+        g_dir_close (d);
+}
+
+static void
+add_theme_to_store (const char   *key,
+                    const char   *value,
+                    GtkListStore *store)
+{
+        char *parent;
+
+        parent = NULL;
+
+        /* Get the parent, if we're checking the custom theme */
+        if (strcmp (key, CUSTOM_THEME_NAME) == 0) {
+                char *name, *path;
+
+                path = custom_theme_dir_path ("index.theme");
+                name = load_index_theme_name (path, &parent);
+                g_free (name);
+                g_free (path);
+        }
+        gtk_list_store_insert_with_values (store, NULL, G_MAXINT,
+                                           THEME_DISPLAY_COL, value,
+                                           THEME_IDENTIFIER_COL, key,
+                                           THEME_PARENT_ID_COL, parent,
+                                           -1);
+        g_free (parent);
+}
+
+static void
+set_combox_for_theme_name (GvcSoundThemeChooser *chooser,
+                           const char           *name)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        gboolean      found;
+
+        /* If the name is empty, use "freedesktop" */
+        if (name == NULL || *name == '\0') {
+                name = "freedesktop";
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+        if (gtk_tree_model_get_iter_first (model, &iter) == FALSE) {
+                return;
+        }
+
+        do {
+                char *value;
+
+                gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &value, -1);
+                found = (value != NULL && strcmp (value, name) == 0);
+                g_free (value);
+
+        } while (!found && gtk_tree_model_iter_next (model, &iter));
+
+        /* When we can't find the theme we need to set, try to set the default
+         * one "freedesktop" */
+        if (found) {
+                gtk_combo_box_set_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter);
+        } else if (strcmp (name, "freedesktop") != 0) {
+                g_debug ("not found, falling back to fdo");
+                set_combox_for_theme_name (chooser, "freedesktop");
+        }
+}
+
+static void
+set_input_feedback_enabled (GvcSoundThemeChooser *chooser,
+                            gboolean              enabled)
+{
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      enabled);
+}
+
+static void
+setup_theme_selector (GvcSoundThemeChooser *chooser)
+{
+        GHashTable           *hash;
+        GtkListStore         *store;
+        GtkCellRenderer      *renderer;
+        const char * const   *data_dirs;
+        const char           *data_dir;
+        char                 *dir;
+        guint                 i;
+
+        /* Add the theme names and their display name to a hash table,
+         * makes it easy to avoid duplicate themes */
+        hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+        data_dirs = g_get_system_data_dirs ();
+        for (i = 0; data_dirs[i] != NULL; i++) {
+                dir = g_build_filename (data_dirs[i], "sounds", NULL);
+                sound_theme_in_dir (hash, dir);
+                g_free (dir);
+        }
+
+        data_dir = g_get_user_data_dir ();
+        dir = g_build_filename (data_dir, "sounds", NULL);
+        sound_theme_in_dir (hash, dir);
+        g_free (dir);
+
+        /* If there isn't at least one theme, make everything
+         * insensitive, LAME! */
+        if (g_hash_table_size (hash) == 0) {
+                gtk_widget_set_sensitive (GTK_WIDGET (chooser), FALSE);
+                g_warning ("Bad setup, install the freedesktop sound theme");
+                g_hash_table_destroy (hash);
+                return;
+        }
+
+        /* Setup the tree model, 3 columns:
+         * - internal theme name/directory
+         * - display theme name
+         * - the internal id for the parent theme, used for the custom theme */
+        store = gtk_list_store_new (THEME_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING);
+
+        /* Add the themes to a combobox */
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           THEME_DISPLAY_COL, _("No sounds"),
+                                           THEME_IDENTIFIER_COL, "__no_sounds",
+                                           THEME_PARENT_ID_COL, NULL,
+                                           -1);
+        g_hash_table_foreach (hash, (GHFunc) add_theme_to_store, store);
+        g_hash_table_destroy (hash);
+
+        /* Set the display */
+        gtk_combo_box_set_model (GTK_COMBO_BOX (chooser->priv->combo_box),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                    renderer,
+                                    TRUE);
+        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                        renderer,
+                                        "text", THEME_DISPLAY_COL,
+                                        NULL);
+
+        g_signal_connect (G_OBJECT (chooser->priv->combo_box),
+                          "changed",
+                          G_CALLBACK (on_combobox_changed),
+                          chooser);
+}
+
+#define GVC_SOUND_SOUND    (xmlChar *) "sound"
+#define GVC_SOUND_NAME     (xmlChar *) "name"
+#define GVC_SOUND_FILENAME (xmlChar *) "filename"
+
+/* Adapted from yelp-toc-pager.c */
+static xmlChar *
+xml_get_and_trim_names (xmlNodePtr node)
+{
+        xmlNodePtr cur;
+        xmlChar *keep_lang = NULL;
+        xmlChar *value;
+        int j, keep_pri = INT_MAX;
+
+        const gchar * const * langs = g_get_language_names ();
+
+        value = NULL;
+
+        for (cur = node->children; cur; cur = cur->next) {
+                if (! xmlStrcmp (cur->name, GVC_SOUND_NAME)) {
+                        xmlChar *cur_lang = NULL;
+                        int cur_pri = INT_MAX;
+
+                        cur_lang = xmlNodeGetLang (cur);
+
+                        if (cur_lang) {
+                                for (j = 0; langs[j]; j++) {
+                                        if (g_str_equal (cur_lang, langs[j])) {
+                                                cur_pri = j;
+                                                break;
+                                        }
+                                }
+                        } else {
+                                cur_pri = INT_MAX - 1;
+                        }
+
+                        if (cur_pri <= keep_pri) {
+                                if (keep_lang)
+                                        xmlFree (keep_lang);
+                                if (value)
+                                        xmlFree (value);
+
+                                value = xmlNodeGetContent (cur);
+
+                                keep_lang = cur_lang;
+                                keep_pri = cur_pri;
+                        } else {
+                                if (cur_lang)
+                                        xmlFree (cur_lang);
+                        }
+                }
+        }
+
+        /* Delete all GVC_SOUND_NAME nodes */
+        cur = node->children;
+        while (cur) {
+                xmlNodePtr this = cur;
+                cur = cur->next;
+                if (! xmlStrcmp (this->name, GVC_SOUND_NAME)) {
+                        xmlUnlinkNode (this);
+                        xmlFreeNode (this);
+                }
+        }
+
+        return value;
+}
+
+static void
+populate_model_from_node (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          xmlNodePtr            node)
+{
+        xmlNodePtr child;
+        xmlChar   *filename;
+        xmlChar   *name;
+
+        filename = NULL;
+        name = xml_get_and_trim_names (node);
+        for (child = node->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+
+                if (xmlStrcmp (child->name, GVC_SOUND_FILENAME) == 0) {
+                        filename = xmlNodeGetContent (child);
+                } else if (xmlStrcmp (child->name, GVC_SOUND_NAME) == 0) {
+                        /* EH? should have been trimmed */
+                }
+        }
+
+        if (filename != NULL && name != NULL) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   ALERT_IDENTIFIER_COL, filename,
+                                                   ALERT_DISPLAY_COL, name,
+                                                   ALERT_SOUND_TYPE_COL, _("Built-in"),
+                                                   ALERT_ACTIVE_COL, FALSE,
+                                                   -1);
+        }
+
+        xmlFree (filename);
+        xmlFree (name);
+}
+
+static void
+populate_model_from_file (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          const char           *filename)
+{
+        xmlDocPtr  doc;
+        xmlNodePtr root;
+        xmlNodePtr child;
+        gboolean   exists;
+
+        exists = g_file_test (filename, G_FILE_TEST_EXISTS);
+        if (! exists) {
+                return;
+        }
+
+        doc = xmlParseFile (filename);
+        if (doc == NULL) {
+                return;
+        }
+
+        root = xmlDocGetRootElement (doc);
+
+        for (child = root->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+                if (xmlStrcmp (child->name, GVC_SOUND_SOUND) != 0) {
+                        continue;
+                }
+
+                populate_model_from_node (chooser, model, child);
+        }
+
+        xmlFreeDoc (doc);
+}
+
+static void
+populate_model_from_dir (GvcSoundThemeChooser *chooser,
+                         GtkTreeModel         *model,
+                         const char           *dirname)
+{
+        GDir       *d;
+        const char *name;
+
+        d = g_dir_open (dirname, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *path;
+
+                if (! g_str_has_suffix (name, ".xml")) {
+                        continue;
+                }
+
+                path = g_build_filename (dirname, name, NULL);
+                populate_model_from_file (chooser, model, path);
+                g_free (path);
+        }
+
+        g_dir_close (d);
+}
+
+static gboolean
+save_alert_sounds (GvcSoundThemeChooser  *chooser,
+                   const char            *id)
+{
+        const char *sounds[3] = { "bell-terminal", "bell-window-system", NULL };
+        char *path;
+
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+        } else {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+                add_custom_file (sounds, id);
+        }
+
+        /* And poke the directory so the theme gets updated */
+        path = custom_theme_dir_path (NULL);
+        if (utime (path, NULL) != 0) {
+                g_warning ("Failed to update mtime for directory '%s': %s",
+                           path, g_strerror (errno));
+        }
+        g_free (path);
+
+        return FALSE;
+}
+
+
+static void
+update_alert_model (GvcSoundThemeChooser  *chooser,
+                    const char            *id)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        gtk_tree_model_get_iter_first (model, &iter);
+        do {
+                gboolean toggled;
+                char    *this_id;
+
+                gtk_tree_model_get (model, &iter,
+                                    ALERT_IDENTIFIER_COL, &this_id,
+                                    -1);
+
+                if (strcmp (this_id, id) == 0) {
+                        toggled = TRUE;
+                } else {
+                        toggled = FALSE;
+                }
+                g_free (this_id);
+
+                gtk_list_store_set (GTK_LIST_STORE (model),
+                                    &iter,
+                                    ALERT_ACTIVE_COL, toggled,
+                                    -1);
+        } while (gtk_tree_model_iter_next (model, &iter));
+}
+
+static void
+update_alert (GvcSoundThemeChooser *chooser,
+              const char           *alert_id)
+{
+        GtkTreeModel *theme_model;
+        GtkTreeIter   iter;
+        char         *theme;
+        char         *parent;
+        gboolean      is_custom;
+        gboolean      is_default;
+        gboolean      add_custom;
+        gboolean      remove_custom;
+
+        theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        /* Get the current theme's name, and set the parent */
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        gtk_tree_model_get (theme_model, &iter,
+                            THEME_IDENTIFIER_COL, &theme,
+                            THEME_IDENTIFIER_COL, &parent,
+                            -1);
+        is_custom = strcmp (theme, CUSTOM_THEME_NAME) == 0;
+        is_default = strcmp (alert_id, DEFAULT_ALERT_ID) == 0;
+
+        /* So a few possibilities:
+         * 1. Named theme, default alert selected: noop
+         * 2. Named theme, alternate alert selected: create new custom with sound
+         * 3. Custom theme, default alert selected: remove sound and possibly custom
+         * 4. Custom theme, alternate alert selected: update custom sound
+         */
+        add_custom = FALSE;
+        remove_custom = FALSE;
+        if (! is_custom && is_default) {
+                /* remove custom just in case */
+                remove_custom = TRUE;
+        } else if (! is_custom && ! is_default) {
+                create_custom_theme (parent);
+                save_alert_sounds (chooser, alert_id);
+                add_custom = TRUE;
+        } else if (is_custom && is_default) {
+                save_alert_sounds (chooser, alert_id);
+                /* after removing files check if it is empty */
+                if (custom_theme_dir_is_empty ()) {
+                        remove_custom = TRUE;
+                }
+        } else if (is_custom && ! is_default) {
+                save_alert_sounds (chooser, alert_id);
+        }
+
+        if (add_custom) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (theme_model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   THEME_DISPLAY_COL, _("Custom"),
+                                                   THEME_IDENTIFIER_COL, CUSTOM_THEME_NAME,
+                                                   THEME_PARENT_ID_COL, theme,
+                                                   -1);
+                set_combox_for_theme_name (chooser, CUSTOM_THEME_NAME);
+        } else if (remove_custom) {
+                gtk_tree_model_get_iter_first (theme_model, &iter);
+                do {
+                        char *this_parent;
+
+                        gtk_tree_model_get (theme_model, &iter,
+                                            THEME_PARENT_ID_COL, &this_parent,
+                                            -1);
+                        if (this_parent != NULL && strcmp (this_parent, CUSTOM_THEME_NAME) != 0) {
+                                g_free (this_parent);
+                                gtk_list_store_remove (GTK_LIST_STORE (theme_model), &iter);
+                                break;
+                        }
+                        g_free (this_parent);
+                } while (gtk_tree_model_iter_next (theme_model, &iter));
+
+                delete_custom_theme_dir ();
+
+                set_combox_for_theme_name (chooser, parent);
+        }
+
+        update_alert_model (chooser, alert_id);
+
+        g_free (theme);
+        g_free (parent);
+}
+
+static void
+on_alert_toggled (GtkCellRendererToggle *renderer,
+                  char                  *path_str,
+                  GvcSoundThemeChooser  *chooser)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreePath  *path;
+        gboolean      toggled;
+        char         *id;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        path = gtk_tree_path_new_from_string (path_str);
+        gtk_tree_model_get_iter (model, &iter, path);
+        gtk_tree_path_free (path);
+
+        id = NULL;
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            ALERT_ACTIVE_COL, &toggled,
+                            -1);
+
+        toggled ^= 1;
+        if (toggled) {
+                update_alert (chooser, id);
+        }
+
+        g_free (id);
+}
+
+static void
+play_preview_for_path (GvcSoundThemeChooser *chooser, GtkTreePath *path)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreeIter   theme_iter;
+        gchar        *id = NULL;
+        gchar        *parent_theme = NULL;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        if (gtk_tree_model_get_iter (model, &iter, path) == FALSE)
+                return;
+
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            -1);
+        if (id == NULL)
+                return;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &theme_iter)) {
+                GtkTreeModel *theme_model;
+                gchar        *theme_id = NULL;
+                gchar        *parent_id = NULL;
+
+                theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+                gtk_tree_model_get (theme_model, &theme_iter,
+                                    THEME_IDENTIFIER_COL, &theme_id,
+                                    THEME_PARENT_ID_COL, &parent_id, -1);
+                if (theme_id && strcmp (theme_id, CUSTOM_THEME_NAME) == 0)
+                        parent_theme = g_strdup (parent_id);
+
+                g_free (theme_id);
+                g_free (parent_id);
+        }
+
+        /* special case: for the default item on custom themes
+         * play the alert for the parent theme */
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                if (parent_theme != NULL) {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_CANBERRA_XDG_THEME_NAME, parent_theme,
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                } else {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                }
+        } else {
+                ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                        CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                        CA_PROP_MEDIA_FILENAME, id,
+                                        CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                        CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                        CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                        CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                        NULL);
+
+        }
+        g_free (parent_theme);
+        g_free (id);
+}
+
+static void
+on_treeview_row_activated (GtkTreeView          *treeview,
+                           GtkTreePath          *path,
+                           GtkTreeViewColumn    *column,
+                           GvcSoundThemeChooser *chooser)
+{
+        play_preview_for_path (chooser, path);
+}
+
+static void
+on_treeview_selection_changed (GtkTreeSelection     *selection,
+                               GvcSoundThemeChooser *chooser)
+{
+        GList        *paths;
+        GtkTreeModel *model;
+        GtkTreePath  *path;
+
+        if (chooser->priv->treeview == NULL)
+                return;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        paths = gtk_tree_selection_get_selected_rows (selection, &model);
+        if (paths == NULL)
+                return;
+
+        path = paths->data;
+        play_preview_for_path (chooser, path);
+
+        g_list_foreach (paths, (GFunc)gtk_tree_path_free, NULL);
+        g_list_free (paths);
+}
+
+static GtkWidget *
+create_alert_treeview (GvcSoundThemeChooser *chooser)
+{
+        GtkListStore         *store;
+        GtkWidget            *treeview;
+        GtkCellRenderer      *renderer;
+        GtkTreeViewColumn    *column;
+        GtkTreeSelection     *selection;
+
+        treeview = gtk_tree_view_new ();
+
+        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
+        g_signal_connect (G_OBJECT (treeview),
+                          "row-activated",
+                          G_CALLBACK (on_treeview_row_activated),
+                          chooser);
+
+        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+        gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+        g_signal_connect (G_OBJECT (selection),
+                          "changed",
+                          G_CALLBACK (on_treeview_selection_changed),
+                          chooser);
+
+        /* Setup the tree model, 3 columns:
+         * - display name
+         * - sound id
+         * - sound type
+         */
+        store = gtk_list_store_new (ALERT_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_BOOLEAN);
+
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           ALERT_IDENTIFIER_COL, DEFAULT_ALERT_ID,
+                                           ALERT_DISPLAY_COL, _("Default"),
+                                           ALERT_SOUND_TYPE_COL, _("From theme"),
+                                           ALERT_ACTIVE_COL, TRUE,
+                                           -1);
+
+        populate_model_from_dir (chooser, GTK_TREE_MODEL (store), SOUND_SET_DIR);
+
+        gtk_tree_view_set_model (GTK_TREE_VIEW (treeview),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_toggle_new ();
+        gtk_cell_renderer_toggle_set_radio (GTK_CELL_RENDERER_TOGGLE (renderer), TRUE);
+
+        column = gtk_tree_view_column_new_with_attributes (NULL,
+                                                           renderer,
+                                                           "active", ALERT_ACTIVE_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+        g_signal_connect (renderer,
+                          "toggled",
+                          G_CALLBACK (on_alert_toggled),
+                          chooser);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Name"),
+                                                           renderer,
+                                                           "text", ALERT_DISPLAY_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Type"),
+                                                           renderer,
+                                                           "text", ALERT_SOUND_TYPE_COL,
+                                                           NULL);
+
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        return treeview;
+}
+
+static int
+get_file_type (const char *sound_name,
+               char      **linked_name)
+{
+        char *name, *filename;
+
+        *linked_name = NULL;
+
+        name = g_strdup_printf ("%s.disabled", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_REGULAR) != FALSE) {
+                g_free (filename);
+                return SOUND_TYPE_OFF;
+        }
+        g_free (filename);
+
+        /* We only check for .ogg files because those are the
+         * only ones we create */
+        name = g_strdup_printf ("%s.ogg", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_SYMLINK) != FALSE) {
+                *linked_name = g_file_read_link (filename, NULL);
+                g_free (filename);
+                return SOUND_TYPE_CUSTOM;
+        }
+        g_free (filename);
+
+        return SOUND_TYPE_BUILTIN;
+}
+
+static void
+update_alerts_from_theme_name (GvcSoundThemeChooser *chooser,
+                               const gchar          *name)
+{
+        if (strcmp (name, CUSTOM_THEME_NAME) != 0) {
+                /* reset alert to default */
+                update_alert (chooser, DEFAULT_ALERT_ID);
+        } else {
+                int   sound_type;
+                char *linkname;
+
+                linkname = NULL;
+                sound_type = get_file_type ("bell-terminal", &linkname);
+                g_debug ("Found link: %s", linkname);
+                if (sound_type == SOUND_TYPE_CUSTOM) {
+                        update_alert (chooser, linkname);
+                }
+        }
+}
+
+static void
+update_theme (GvcSoundThemeChooser *chooser)
+{
+        char        *theme_name;
+        gboolean     events_enabled;
+        gboolean     feedback_enabled;
+
+        feedback_enabled = g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY);
+        set_input_feedback_enabled (chooser, feedback_enabled);
+
+        events_enabled = g_settings_get_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY);
+        if (events_enabled) {
+                theme_name = g_settings_get_string (chooser->priv->sound_settings, SOUND_THEME_KEY);
+        } else {
+                theme_name = g_strdup (NO_SOUNDS_THEME_NAME);
+        }
+
+        gtk_widget_set_sensitive (chooser->priv->selection_box, events_enabled);
+        gtk_widget_set_sensitive (chooser->priv->click_feedback_button, events_enabled);
+
+        set_combox_for_theme_name (chooser, theme_name);
+
+        update_alerts_from_theme_name (chooser, theme_name);
+
+        g_free (theme_name);
+}
+
+static void
+gvc_sound_theme_chooser_class_init (GvcSoundThemeChooserClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_sound_theme_chooser_dispose;
+}
+
+static void
+on_click_feedback_toggled (GtkToggleButton      *button,
+                           GvcSoundThemeChooser *chooser)
+{
+        gboolean enabled;
+
+        enabled = gtk_toggle_button_get_active (button);
+
+        g_settings_set_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY, enabled);
+}
+
+static void
+on_key_changed (GSettings            *settings,
+                gchar                *key,
+                GvcSoundThemeChooser *chooser)
+{
+        if (!strcmp (key, EVENT_SOUNDS_KEY) ||
+            !strcmp (key, SOUND_THEME_KEY) ||
+            !strcmp (key, INPUT_SOUNDS_KEY))
+                update_theme (chooser);
+}
+
+static void
+setup_list_size_constraint (GtkWidget *widget,
+                            GtkWidget *to_size)
+{
+        GtkRequisition req;
+        gint           sc_height;
+        int            max_height;
+
+        /* Constrain height to be the tree height up to a max */
+        gdk_window_get_geometry (gdk_screen_get_root_window (gtk_widget_get_screen (widget)),
+                                 NULL, NULL, NULL, &sc_height);
+
+        max_height = sc_height / 4;
+
+        // XXX this doesn't work
+        gtk_widget_get_preferred_size (to_size, NULL, &req);
+
+        gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (widget),
+                                                    MIN (req.height, max_height));
+}
+
+static void
+gvc_sound_theme_chooser_init (GvcSoundThemeChooser *chooser)
+{
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *scrolled_window;
+        gchar       *str;
+
+        chooser->priv = gvc_sound_theme_chooser_get_instance_private (chooser);
+
+        chooser->priv->theme_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->theme_box, FALSE, FALSE, 0);
+
+        label = gtk_label_new_with_mnemonic (_("Sound _theme:"));
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), label, FALSE, FALSE, 0);
+        chooser->priv->combo_box = gtk_combo_box_new ();
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), chooser->priv->combo_box, FALSE, FALSE, 6);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->combo_box);
+
+        chooser->priv->sound_settings = g_settings_new (KEY_SOUNDS_SCHEMA);
+
+        g_signal_connect (G_OBJECT (chooser->priv->sound_settings),
+                          "changed",
+                          G_CALLBACK (on_key_changed),
+                          chooser);
+
+        str = g_strdup_printf ("<b>%s</b>", _("C_hoose an alert sound:"));
+        chooser->priv->selection_box = box = gtk_frame_new (str);
+        g_free (str);
+
+        label = gtk_frame_get_label_widget (GTK_FRAME (box));
+        gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
+        gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+        gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
+
+        gtk_box_pack_start (GTK_BOX (chooser), box, TRUE, TRUE, 6);
+
+        chooser->priv->treeview = create_alert_treeview (chooser);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->treeview);
+
+        scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+        gtk_widget_set_hexpand (scrolled_window, TRUE);
+        gtk_widget_set_vexpand (scrolled_window, TRUE);
+        gtk_widget_set_margin_top (scrolled_window, 6);
+
+        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+                                        GTK_POLICY_NEVER,
+                                        GTK_POLICY_AUTOMATIC);
+        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
+                                             GTK_SHADOW_IN);
+
+        gtk_container_add (GTK_CONTAINER (scrolled_window), chooser->priv->treeview);
+        gtk_container_add (GTK_CONTAINER (box), scrolled_window);
+
+        chooser->priv->click_feedback_button = gtk_check_button_new_with_mnemonic (_("Enable _window and button sounds"));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY));
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->click_feedback_button,
+                            FALSE, FALSE, 0);
+
+        g_signal_connect (G_OBJECT (chooser->priv->click_feedback_button),
+                          "toggled",
+                          G_CALLBACK (on_click_feedback_toggled),
+                          chooser);
+
+        setup_theme_selector (chooser);
+        update_theme (chooser);
+
+        setup_list_size_constraint (scrolled_window, chooser->priv->treeview);
+}
+
+static void
+gvc_sound_theme_chooser_dispose (GObject *object)
+{
+        GvcSoundThemeChooser *chooser;
+
+        chooser = GVC_SOUND_THEME_CHOOSER (object);
+
+        g_clear_object (&chooser->priv->sound_settings);
+
+        G_OBJECT_CLASS (gvc_sound_theme_chooser_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_sound_theme_chooser_new (void)
+{
+        return g_object_new (GVC_TYPE_SOUND_THEME_CHOOSER,
+                                "spacing", 6,
+                                "orientation", GTK_ORIENTATION_VERTICAL,
+                                NULL);
+}
+
+
+
+ + + diff --git a/2020-04-10-141956-3126-cppcheck@de1524253905_master/2.html b/2020-04-10-141956-3126-cppcheck@de1524253905_master/2.html new file mode 100644 index 0000000..bacfabb --- /dev/null +++ b/2020-04-10-141956-3126-cppcheck@de1524253905_master/2.html @@ -0,0 +1,1110 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <canberra.h>
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-speaker-test.h"
+#include "gvc-utils.h"
+
+struct _GvcSpeakerTestPrivate
+{
+        GArray           *controls;
+        ca_context       *canberra;
+        MateMixerStream  *stream;
+};
+
+enum {
+        PROP_0,
+        PROP_STREAM,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_speaker_test_dispose    (GObject             *object);
+static void gvc_speaker_test_finalize   (GObject             *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSpeakerTest, gvc_speaker_test, GTK_TYPE_GRID)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+typedef struct {
+        MateMixerChannelPosition position;
+        guint left;
+        guint top;
+} TablePosition;
+
+static const TablePosition positions[] = {
+        /* Position, X, Y */
+        { MATE_MIXER_CHANNEL_FRONT_LEFT, 0, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_LEFT_CENTER, 1, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_CENTER, 2, 0, },
+        { MATE_MIXER_CHANNEL_MONO, 2, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT_CENTER, 3, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT, 4, 0, },
+        { MATE_MIXER_CHANNEL_SIDE_LEFT, 0, 1, },
+        { MATE_MIXER_CHANNEL_SIDE_RIGHT, 4, 1, },
+        { MATE_MIXER_CHANNEL_BACK_LEFT, 0, 2, },
+        { MATE_MIXER_CHANNEL_BACK_CENTER, 2, 2, },
+        { MATE_MIXER_CHANNEL_BACK_RIGHT, 4, 2, },
+        { MATE_MIXER_CHANNEL_LFE, 3, 2 }
+};
+
+MateMixerStream *
+gvc_speaker_test_get_stream (GvcSpeakerTest *test)
+{
+        g_return_val_if_fail (GVC_IS_SPEAKER_TEST (test), NULL);
+
+        return test->priv->stream;
+}
+
+static void
+gvc_speaker_test_set_stream (GvcSpeakerTest *test, MateMixerStream *stream)
+{
+        MateMixerStreamControl *control;
+        const gchar            *name;
+        guint                   i;
+
+        name = mate_mixer_stream_get_name (stream);
+        control = mate_mixer_stream_get_default_control (stream);
+
+        ca_context_change_device (test->priv->canberra, name);
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                gboolean has_position =
+                        mate_mixer_stream_control_has_channel_position (control, positions[i].position);
+
+                gtk_widget_set_visible (g_array_index (test->priv->controls, GtkWidget *, i),
+                                        has_position);
+        }
+
+        test->priv->stream = g_object_ref (stream);
+}
+
+static void
+gvc_speaker_test_set_property (GObject       *object,
+                               guint          prop_id,
+                               const GValue  *value,
+                               GParamSpec    *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                gvc_speaker_test_set_stream (self, g_value_get_object (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_get_property (GObject     *object,
+                               guint        prop_id,
+                               GValue      *value,
+                               GParamSpec  *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                g_value_set_object (value, self->priv->stream);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_class_init (GvcSpeakerTestClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose  = gvc_speaker_test_dispose;
+        object_class->finalize = gvc_speaker_test_finalize;
+        object_class->set_property = gvc_speaker_test_set_property;
+        object_class->get_property = gvc_speaker_test_get_property;
+
+        properties[PROP_STREAM] =
+                g_param_spec_object ("stream",
+                                     "Stream",
+                                     "MateMixer stream",
+                                     MATE_MIXER_TYPE_STREAM,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+}
+
+static const gchar *
+sound_name (MateMixerChannelPosition position)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return "audio-channel-front-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return "audio-channel-front-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return "audio-channel-front-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return "audio-channel-rear-left";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return "audio-channel-rear-right";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return "audio-channel-rear-center";
+        case MATE_MIXER_CHANNEL_LFE:
+                return "audio-channel-lfe";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return "audio-channel-side-left";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return "audio-channel-side-right";
+        default:
+                return NULL;
+        }
+}
+
+static const gchar *
+icon_name (MateMixerChannelPosition position, gboolean playing)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return playing
+                        ? "audio-speaker-left-testing"
+                        : "audio-speaker-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return playing
+                        ? "audio-speaker-right-testing"
+                        : "audio-speaker-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return playing
+                        ? "audio-speaker-center-testing"
+                        : "audio-speaker-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return playing
+                        ? "audio-speaker-left-back-testing"
+                        : "audio-speaker-left-back";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return playing
+                        ? "audio-speaker-right-back-testing"
+                        : "audio-speaker-right-back";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return playing
+                        ? "audio-speaker-center-back-testing"
+                        : "audio-speaker-center-back";
+        case MATE_MIXER_CHANNEL_LFE:
+                return playing
+                        ? "audio-subwoofer-testing"
+                        : "audio-subwoofer";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return playing
+                        ? "audio-speaker-left-side-testing"
+                        : "audio-speaker-left-side";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return playing
+                        ? "audio-speaker-right-side-testing"
+                        : "audio-speaker-right-side";
+        default:
+                return NULL;
+        }
+}
+
+static void
+update_button (GtkWidget *control)
+{
+        GtkWidget *button;
+        GtkWidget *image;
+        gboolean   playing;
+        MateMixerChannelPosition position;
+
+        button = g_object_get_data (G_OBJECT (control), "button");
+        image  = g_object_get_data (G_OBJECT (control), "image");
+
+        position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+        playing  = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        gtk_button_set_label (GTK_BUTTON (button), playing ? _("Stop") : _("Test"));
+
+        gtk_image_set_from_icon_name (GTK_IMAGE (image),
+                                      icon_name (position, playing),
+                                      GTK_ICON_SIZE_DIALOG);
+}
+
+static gboolean
+idle_cb (GtkWidget *control)
+{
+        if (control != NULL) {
+                /* This is called in the background thread, hence forward to main thread
+                 * via idle callback */
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+
+                update_button (control);
+        }
+        return FALSE;
+}
+
+static void
+finish_cb (ca_context *c, uint32_t id, int error_code, void *userdata)
+{
+        GtkWidget *control = (GtkWidget *) userdata;
+
+        if (error_code == CA_ERROR_DESTROYED || control == NULL)
+                return;
+
+        g_idle_add ((GSourceFunc) idle_cb, control);
+}
+
+static void
+on_test_button_clicked (GtkButton *button, GtkWidget *control)
+{
+        gboolean    playing;
+        ca_context *canberra;
+
+        canberra = g_object_get_data (G_OBJECT (control), "canberra");
+
+        ca_context_cancel (canberra, 1);
+
+        playing = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        if (playing) {
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        } else {
+                MateMixerChannelPosition position;
+                const gchar *name;
+                ca_proplist *proplist;
+
+                position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+
+                ca_proplist_create (&proplist);
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_ROLE, "test");
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_NAME,
+                                  gvc_channel_position_to_pretty_string (position));
+                ca_proplist_sets (proplist,
+                                  CA_PROP_CANBERRA_FORCE_CHANNEL,
+                                  gvc_channel_position_to_pulse_string (position));
+
+                ca_proplist_sets (proplist, CA_PROP_CANBERRA_ENABLE, "1");
+
+                name = sound_name (position);
+                if (name != NULL) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, name);
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, "audio-test-signal");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets(proplist, CA_PROP_EVENT_ID, "bell-window-system");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (playing));
+        }
+
+        update_button (control);
+}
+
+static GtkWidget *
+create_control (ca_context *canberra, MateMixerChannelPosition position)
+{
+        GtkWidget   *control;
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *image;
+        GtkWidget   *test_button;
+        const gchar *name;
+
+        control = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+        box     = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        g_object_set_data (G_OBJECT (control), "position", GINT_TO_POINTER (position));
+        g_object_set_data (G_OBJECT (control), "canberra", canberra);
+
+        name = icon_name (position, FALSE);
+        if (name == NULL)
+                name = "audio-volume-medium";
+
+        image = gtk_image_new_from_icon_name (name, GTK_ICON_SIZE_DIALOG);
+        g_object_set_data (G_OBJECT (control), "image", image);
+        gtk_box_pack_start (GTK_BOX (control), image, FALSE, FALSE, 0);
+
+        label = gtk_label_new (gvc_channel_position_to_pretty_string (position));
+        gtk_box_pack_start (GTK_BOX (control), label, FALSE, FALSE, 0);
+
+        test_button = gtk_button_new_with_label (_("Test"));
+        g_signal_connect (G_OBJECT (test_button),
+                          "clicked",
+                          G_CALLBACK (on_test_button_clicked),
+                          control);
+
+        g_object_set_data (G_OBJECT (control), "button", test_button);
+
+        gtk_box_pack_start (GTK_BOX (box), test_button, TRUE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (control), box, FALSE, FALSE, 0);
+
+        gtk_widget_show_all (control);
+
+        return control;
+}
+
+static void
+create_controls (GvcSpeakerTest *test)
+{
+        guint i;
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                GtkWidget *control = create_control (test->priv->canberra, positions[i].position);
+
+                gtk_grid_attach (GTK_GRID (test),
+                                 control,
+                                 positions[i].left,
+                                 positions[i].top,
+                                 1, 1);
+                g_array_insert_val (test->priv->controls, i, control);
+        }
+}
+
+static void
+gvc_speaker_test_init (GvcSpeakerTest *test)
+{
+        GtkWidget *face;
+
+        test->priv = gvc_speaker_test_get_instance_private (test);
+
+        gtk_container_set_border_width (GTK_CONTAINER (test), 12);
+
+        face = gtk_image_new_from_icon_name ("face-smile", GTK_ICON_SIZE_DIALOG);
+
+        gtk_grid_attach (GTK_GRID (test),
+                         face,
+                         1, 1,
+                         3, 1);
+
+
+        gtk_grid_set_baseline_row (GTK_GRID (test), 1);
+        gtk_widget_show (face);
+
+        ca_context_create (&test->priv->canberra);
+
+        /* The test sounds are played for a single channel, set up using the
+         * FORCE_CHANNEL property of libcanberra; this property is only supported
+         * in the PulseAudio backend, so avoid other backends completely */
+        ca_context_set_driver (test->priv->canberra, "pulse");
+
+        ca_context_change_props (test->priv->canberra,
+                                 CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+                                 CA_PROP_APPLICATION_NAME, _("Volume Control"),
+                                 CA_PROP_APPLICATION_VERSION, VERSION,
+                                 CA_PROP_APPLICATION_ICON_NAME, "multimedia-volume-control",
+                                 NULL);
+
+        test->priv->controls = g_array_new (FALSE, FALSE, sizeof (GtkWidget *));
+
+        create_controls (test);
+}
+
+static void
+gvc_speaker_test_dispose (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        g_clear_object (&test->priv->stream);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->dispose (object);
+}
+
+static void
+gvc_speaker_test_finalize (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        ca_context_destroy (test->priv->canberra);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->finalize (object);
+}
+
+GtkWidget *
+gvc_speaker_test_new (MateMixerStream *stream)
+{
+        GObject *test;
+
+        g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL);
+
+        test = g_object_new (GVC_TYPE_SPEAKER_TEST,
+                             "row-spacing", 6,
+                             "column-spacing", 6,
+                             "row-homogeneous", TRUE,
+                             "column-homogeneous", TRUE,
+                             "stream", stream,
+                             NULL);
+
+        return GTK_WIDGET (test);
+}
+
+
+
+ + + diff --git a/2020-04-10-141956-3126-cppcheck@de1524253905_master/index.html b/2020-04-10-141956-3126-cppcheck@de1524253905_master/index.html new file mode 100644 index 0000000..59baeb0 --- /dev/null +++ b/2020-04-10-141956-3126-cppcheck@de1524253905_master/index.html @@ -0,0 +1,108 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
mate-volume-control/gvc-combo-box.c
70unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
mate-volume-control/gvc-sound-theme-chooser.c
735ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
746ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
758ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
mate-volume-control/gvc-speaker-test.c
53unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+ + + diff --git a/2020-04-10-141956-3126-cppcheck@de1524253905_master/stats.html b/2020-04-10-141956-3126-cppcheck@de1524253905_master/stats.html new file mode 100644 index 0000000..3fb6add --- /dev/null +++ b/2020-04-10-141956-3126-cppcheck@de1524253905_master/stats.html @@ -0,0 +1,93 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+

Top 10 files for error severity, total findings: 2
+   1  mate-volume-control/gvc-speaker-test.c
+   1  mate-volume-control/gvc-combo-box.c
+

+

Top 10 files for information severity, total findings: 3
+   3  mate-volume-control/gvc-sound-theme-chooser.c
+

+ +
+ + + diff --git a/2020-04-10-141956-3126-cppcheck@de1524253905_master/style.css b/2020-04-10-141956-3126-cppcheck@de1524253905_master/style.css new file mode 100644 index 0000000..c39571c --- /dev/null +++ b/2020-04-10-141956-3126-cppcheck@de1524253905_master/style.css @@ -0,0 +1,149 @@ + +body { + font: 13px Arial, Verdana, Sans-Serif; + margin: 0; + width: auto; +} + +h1 { + margin: 10px; +} + +#footer > p { + margin: 4px; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + border: 1px dotted black; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #B6B6B4; +} + +.inconclusive2 { + background-color: #B6B6B4; + border: 1px dotted black; + display: inline-block; + margin-left: 4px; +} + +div.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +div.verbose div.content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid black; + background-color: #FFFFCC; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +#header { + border-bottom: thin solid #aaa; +} + +#menu { + float: left; + margin-top: 5px; + text-align: left; + width: 150px; + /*height: 75%;*/ + position: fixed; + overflow: auto; + z-index: 1; +} + +#menu_index { + float: left; + margin-top: 5px; + padding-left: 5px; + text-align: left; + width: 300px; + /*height: 75%;*/ + position: fixed; + overflow: auto; + z-index: 1; +} + +#menu > a { + display: block; + margin-left: 10px; + font: 12px; + z-index: 1; +} + +#filename { + margin-left: 10px; + font: 12px; + z-index: 1; +} + +.highlighttable { + background-color:white; + z-index: 10; + position: relative; + margin: -10 px; +} + +#content { + background-color: white; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + float: left; + margin: 5px; + margin-left: 10px; + padding: 0 10px 10px 10px; + width: 80%; + padding-left: 150px; +} + +#content_index { + background-color: white; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + float: left; + margin: 5px; + margin-left: 10px; + padding: 0 10px 10px 10px; + width: 80%; + padding-left: 300px; +} + +.linenos { + border-right: thin solid #aaa; + color: lightgray; + padding-right: 6px; +} + +#footer { + border-top: thin solid #aaa; + clear: both; + font-size: 90%; + margin-top: 5px; +} + +#footer ul { + list-style-type: none; + padding-left: 0; +} diff --git a/2020-04-19-141137-3704-cppcheck@7dca88a484ae_master/0.html b/2020-04-19-141137-3704-cppcheck@7dca88a484ae_master/0.html new file mode 100644 index 0000000..e262ed0 --- /dev/null +++ b/2020-04-19-141137-3704-cppcheck@7dca88a484ae_master/0.html @@ -0,0 +1,1038 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-combo-box.h"
+
+struct _GvcComboBoxPrivate
+{
+        GtkWidget       *drop_box;
+        GtkWidget       *start_box;
+        GtkWidget       *end_box;
+        GtkWidget       *label;
+        GtkWidget       *button;
+        GtkTreeModel    *model;
+        GtkWidget       *combobox;
+        MateMixerSwitch *swtch;
+};
+
+enum {
+        COL_NAME,
+        COL_HUMAN_NAME,
+        NUM_COLS
+};
+
+enum {
+        CHANGING,
+        BUTTON_CLICKED,
+        LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+enum {
+        PROP_0,
+        PROP_SWITCH,
+        PROP_LABEL,
+        PROP_SHOW_BUTTON,
+        PROP_BUTTON_LABEL,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_combo_box_dispose    (GObject          *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcComboBox, gvc_combo_box, GTK_TYPE_BOX)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+MateMixerSwitch *
+gvc_combo_box_get_switch (GvcComboBox *combobox)
+{
+        g_return_val_if_fail (GVC_IS_COMBO_BOX (combobox), NULL);
+
+        return combobox->priv->swtch;
+}
+
+void
+gvc_combo_box_set_size_group (GvcComboBox  *combobox,
+                              GtkSizeGroup *group,
+                              gboolean      symmetric)
+{
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (GTK_IS_SIZE_GROUP (group));
+
+        if (group != NULL) {
+                gtk_size_group_add_widget (group, combobox->priv->start_box);
+                if (symmetric == TRUE)
+                        gtk_size_group_add_widget (group, combobox->priv->end_box);
+        }
+        gtk_widget_queue_draw (GTK_WIDGET (combobox));
+}
+
+static void
+on_switch_active_option_notify (MateMixerSwitch *swtch,
+                                GParamSpec      *pspec,
+                                GvcComboBox     *combobox)
+{
+        GtkTreeIter            iter;
+        MateMixerSwitchOption *active;
+        gboolean               cont;
+        const gchar           *name;
+
+        active = mate_mixer_switch_get_active_option (swtch);
+        if (G_UNLIKELY (active == NULL)) {
+                g_warn_if_reached ();
+                return;
+        }
+
+        /* Select the newly activated switch option in the combo box */
+        name = mate_mixer_switch_option_get_name (active);
+        cont = gtk_tree_model_get_iter_first (combobox->priv->model, &iter);
+        while (cont == TRUE) {
+                gchar *current;
+
+                gtk_tree_model_get (combobox->priv->model, &iter,
+                                    COL_NAME, &current,
+                                    -1);
+                if (g_strcmp0 (name, current) == 0) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox), &iter);
+                        g_free (current);
+                        return;
+                }
+                g_free (current);
+
+                cont = gtk_tree_model_iter_next (combobox->priv->model, &iter);
+        }
+        g_warning ("Could not find switch option '%s' in combo box", name);
+}
+
+static void
+gvc_combo_box_set_switch (GvcComboBox *combobox, MateMixerSwitch *swtch)
+{
+        MateMixerSwitchOption *active;
+        const GList           *options;
+
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (MATE_MIXER_IS_SWITCH (swtch));
+
+        combobox->priv->swtch = g_object_ref (swtch);
+
+        active  = mate_mixer_switch_get_active_option (swtch);
+        options = mate_mixer_switch_list_options (swtch);
+        while (options != NULL) {
+                GtkTreeIter            iter;
+                MateMixerSwitchOption *option = MATE_MIXER_SWITCH_OPTION (options->data);
+
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (combobox->priv->model),
+                                                   &iter,
+                                                   G_MAXINT,
+                                                   COL_NAME,
+                                                   mate_mixer_switch_option_get_name (option),
+                                                   COL_HUMAN_NAME,
+                                                   mate_mixer_switch_option_get_label (option),
+                                                   -1);
+
+                /* Select the currently active option of the switch */
+                if (option == active) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox),
+                                                       &iter);
+                }
+                options = options->next;
+        }
+
+        g_signal_connect (G_OBJECT (swtch),
+                          "notify::active-option",
+                          G_CALLBACK (on_switch_active_option_notify),
+                          combobox);
+}
+
+static void
+gvc_combo_box_set_property (GObject       *object,
+                            guint          prop_id,
+                            const GValue  *value,
+                            GParamSpec    *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                gvc_combo_box_set_switch (self, g_value_get_object (value));
+                break;
+        case PROP_LABEL:
+                gtk_label_set_text_with_mnemonic (GTK_LABEL (self->priv->label), g_value_get_string (value));
+                break;
+        case PROP_BUTTON_LABEL:
+                gtk_button_set_label (GTK_BUTTON (self->priv->button), g_value_get_string (value));
+                break;
+        case PROP_SHOW_BUTTON:
+                gtk_widget_set_visible (self->priv->button, g_value_get_boolean (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_get_property (GObject     *object,
+                            guint        prop_id,
+                            GValue      *value,
+                            GParamSpec  *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                g_value_set_object (value, self->priv->swtch);
+                break;
+        case PROP_LABEL:
+                g_value_set_string (value, gtk_label_get_text (GTK_LABEL (self->priv->label)));
+                break;
+        case PROP_BUTTON_LABEL:
+                g_value_set_string (value, gtk_button_get_label (GTK_BUTTON (self->priv->button)));
+                break;
+        case PROP_SHOW_BUTTON:
+                g_value_set_boolean (value, gtk_widget_get_visible (self->priv->button));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_class_init (GvcComboBoxClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_combo_box_dispose;
+        object_class->set_property = gvc_combo_box_set_property;
+        object_class->get_property = gvc_combo_box_get_property;
+
+        properties[PROP_SWITCH] =
+                g_param_spec_object ("switch",
+                                     "switch",
+                                     "The MateMixerSwitch",
+                                     MATE_MIXER_TYPE_SWITCH,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_LABEL] =
+                g_param_spec_string ("label",
+                                     "label",
+                                     "The combo box label",
+                                     _("_Profile:"),
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_SHOW_BUTTON] =
+                g_param_spec_boolean ("show-button",
+                                      "show-button",
+                                      "Whether to show the button",
+                                      FALSE,
+                                      G_PARAM_READWRITE |
+                                      G_PARAM_CONSTRUCT |
+                                      G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_BUTTON_LABEL] =
+                g_param_spec_string ("button-label",
+                                     "button-label",
+                                     "The button's label",
+                                     "",
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+
+        signals[CHANGING] =
+                g_signal_new ("changing",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, changing),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__OBJECT,
+                              G_TYPE_NONE,
+                              1,
+                              MATE_MIXER_TYPE_SWITCH_OPTION);
+
+        signals[BUTTON_CLICKED] =
+                g_signal_new ("button-clicked",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, button_clicked),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
+}
+
+static void
+on_combo_box_changed (GtkComboBox *widget, GvcComboBox *combobox)
+{
+        GtkTreeIter            iter;
+        gchar                 *name;
+        MateMixerSwitchOption *option;
+
+        if (G_UNLIKELY (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter) == FALSE))
+                return;
+
+        gtk_tree_model_get (combobox->priv->model, &iter,
+                            COL_NAME, &name,
+                            -1);
+
+        option = mate_mixer_switch_get_option (combobox->priv->swtch, name);
+        if (G_UNLIKELY (option == NULL)) {
+                g_warn_if_reached ();
+                g_free (name);
+                return;
+        }
+
+        /* Inform that we are about to change the active option of the switch */
+        g_signal_emit (combobox, signals[CHANGING], 0, option);
+
+        mate_mixer_switch_set_active_option (combobox->priv->swtch, option);
+        g_free (name);
+}
+
+static void
+on_combo_box_button_clicked (GtkButton *button, GvcComboBox *combobox)
+{
+        /* The meaning of the button is defined by the owner, so only notify
+         * when it is clicked on */
+        g_signal_emit (combobox, signals[BUTTON_CLICKED], 0);
+}
+
+static void
+gvc_combo_box_init (GvcComboBox *combobox)
+{
+        GtkWidget       *frame;
+        GtkCellRenderer *renderer;
+
+        frame = gtk_frame_new (NULL);
+        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
+
+        combobox->priv = gvc_combo_box_get_instance_private (combobox);
+
+        combobox->priv->model = GTK_TREE_MODEL (gtk_list_store_new (NUM_COLS,
+                                                                    G_TYPE_STRING,
+                                                                    G_TYPE_STRING));
+
+        combobox->priv->combobox = gtk_combo_box_new_with_model (combobox->priv->model);
+
+        combobox->priv->label = gtk_label_new (NULL);
+
+        gtk_label_set_xalign (GTK_LABEL (combobox->priv->label), 0.0);
+        gtk_label_set_yalign (GTK_LABEL (combobox->priv->label), 0.5);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (combobox->priv->label),
+                                       combobox->priv->combobox);
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                    renderer,
+                                    FALSE);
+        gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                       renderer,
+                                       "text",
+                                       COL_HUMAN_NAME);
+
+        combobox->priv->drop_box  = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->start_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->end_box   = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+        /* Make sure the combo box does not get too long on long profile names */
+        g_object_set (G_OBJECT (renderer),
+                      "ellipsize",
+                      PANGO_ELLIPSIZE_END,
+                      NULL);
+
+        gtk_combo_box_set_popup_fixed_width (GTK_COMBO_BOX (combobox->priv->combobox), FALSE);
+
+        gtk_box_pack_start (GTK_BOX (combobox),
+                            frame,
+                            TRUE, TRUE, 0);
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->start_box,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->start_box),
+                            combobox->priv->label,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->combobox,
+                            TRUE, TRUE, 0);
+
+        combobox->priv->button = gtk_button_new_with_label ("");
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->button,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->end_box,
+                            FALSE, FALSE, 0);
+
+        gtk_container_add (GTK_CONTAINER (frame), combobox->priv->drop_box);
+
+        g_signal_connect (G_OBJECT (combobox->priv->combobox),
+                          "changed",
+                          G_CALLBACK (on_combo_box_changed),
+                          combobox);
+        g_signal_connect (G_OBJECT (combobox->priv->button),
+                          "clicked",
+                          G_CALLBACK (on_combo_box_button_clicked),
+                          combobox);
+
+        gtk_widget_set_no_show_all (combobox->priv->button, TRUE);
+        gtk_widget_show_all (frame);
+}
+
+static void
+gvc_combo_box_dispose (GObject *object)
+{
+        GvcComboBox *combobox;
+
+        combobox = GVC_COMBO_BOX (object);
+
+        if (G_LIKELY (combobox->priv->swtch != NULL)) {
+                g_signal_handlers_disconnect_by_func (G_OBJECT (combobox->priv->swtch),
+                                                      G_CALLBACK (on_switch_active_option_notify),
+                                                      combobox);
+                g_clear_object (&combobox->priv->swtch);
+        }
+
+        g_clear_object (&combobox->priv->model);
+
+        G_OBJECT_CLASS (gvc_combo_box_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_combo_box_new (MateMixerSwitch *swtch, const gchar *label)
+{
+        return g_object_new (GVC_TYPE_COMBO_BOX,
+                             "switch", swtch,
+                             "label", label,
+                             "orientation", GTK_ORIENTATION_HORIZONTAL,
+                             NULL);
+}
+
+
+
+ + + diff --git a/2020-04-19-141137-3704-cppcheck@7dca88a484ae_master/1.html b/2020-04-19-141137-3704-cppcheck@7dca88a484ae_master/1.html new file mode 100644 index 0000000..67179f2 --- /dev/null +++ b/2020-04-19-141137-3704-cppcheck@7dca88a484ae_master/1.html @@ -0,0 +1,2368 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
+ * Copyright (C) 2008 William Jon McCann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <utime.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+#include <canberra-gtk.h>
+#include <libxml/tree.h>
+
+#include "gvc-sound-theme-chooser.h"
+#include "sound-theme-file-utils.h"
+
+struct GvcSoundThemeChooserPrivate
+{
+        GtkWidget *combo_box;
+        GtkWidget *treeview;
+        GtkWidget *theme_box;
+        GtkWidget *selection_box;
+        GtkWidget *click_feedback_button;
+        GSettings *sound_settings;
+};
+
+static void     gvc_sound_theme_chooser_dispose   (GObject            *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSoundThemeChooser, gvc_sound_theme_chooser, GTK_TYPE_BOX)
+
+#define KEY_SOUNDS_SCHEMA          "org.mate.sound"
+#define EVENT_SOUNDS_KEY           "event-sounds"
+#define INPUT_SOUNDS_KEY           "input-feedback-sounds"
+#define SOUND_THEME_KEY            "theme-name"
+
+#define DEFAULT_ALERT_ID        "__default"
+#define CUSTOM_THEME_NAME       "__custom"
+#define NO_SOUNDS_THEME_NAME    "__no_sounds"
+
+enum {
+        THEME_DISPLAY_COL,
+        THEME_IDENTIFIER_COL,
+        THEME_PARENT_ID_COL,
+        THEME_NUM_COLS
+};
+
+enum {
+        ALERT_DISPLAY_COL,
+        ALERT_IDENTIFIER_COL,
+        ALERT_SOUND_TYPE_COL,
+        ALERT_ACTIVE_COL,
+        ALERT_NUM_COLS
+};
+
+enum {
+        SOUND_TYPE_UNSET,
+        SOUND_TYPE_OFF,
+        SOUND_TYPE_DEFAULT_FROM_THEME,
+        SOUND_TYPE_BUILTIN,
+        SOUND_TYPE_CUSTOM
+};
+
+static void
+on_combobox_changed (GtkComboBox          *widget,
+                     GvcSoundThemeChooser *chooser)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        char         *theme_name;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &theme_name, -1);
+
+        g_assert (theme_name != NULL);
+
+        /* It is necessary to update the theme name before any other setting as
+         * the "changed" notification will reload the contents of the widget */
+        g_settings_set_string (chooser->priv->sound_settings, SOUND_THEME_KEY, theme_name);
+
+        /* special case for no sounds */
+        if (strcmp (theme_name, NO_SOUNDS_THEME_NAME) == 0) {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, FALSE);
+                return;
+        } else {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, TRUE);
+        }
+
+        g_free (theme_name);
+
+        /* FIXME: reset alert model */
+}
+
+static char *
+load_index_theme_name (const char *index,
+                       char      **parent)
+{
+        GKeyFile *file;
+        char *indexname = NULL;
+        gboolean hidden;
+
+        file = g_key_file_new ();
+        if (g_key_file_load_from_file (file, index, G_KEY_FILE_KEEP_TRANSLATIONS, NULL) == FALSE) {
+                g_key_file_free (file);
+                return NULL;
+        }
+        /* Don't add hidden themes to the list */
+        hidden = g_key_file_get_boolean (file, "Sound Theme", "Hidden", NULL);
+        if (!hidden) {
+                indexname = g_key_file_get_locale_string (file,
+                                                          "Sound Theme",
+                                                          "Name",
+                                                          NULL,
+                                                          NULL);
+
+                /* Save the parent theme, if there's one */
+                if (parent != NULL) {
+                        *parent = g_key_file_get_string (file,
+                                                         "Sound Theme",
+                                                         "Inherits",
+                                                         NULL);
+                }
+        }
+
+        g_key_file_free (file);
+        return indexname;
+}
+
+static void
+sound_theme_in_dir (GHashTable *hash,
+                    const char *dir)
+{
+        GDir *d;
+        const char *name;
+
+        d = g_dir_open (dir, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *dirname, *index, *indexname;
+
+                /* Look for directories */
+                dirname = g_build_filename (dir, name, NULL);
+                if (g_file_test (dirname, G_FILE_TEST_IS_DIR) == FALSE) {
+                        g_free (dirname);
+                        continue;
+                }
+
+                /* Look for index files */
+                index = g_build_filename (dirname, "index.theme", NULL);
+                g_free (dirname);
+
+                /* Check the name of the theme in the index.theme file */
+                indexname = load_index_theme_name (index, NULL);
+                g_free (index);
+                if (indexname == NULL) {
+                        continue;
+                }
+
+                g_hash_table_insert (hash, g_strdup (name), indexname);
+        }
+
+        g_dir_close (d);
+}
+
+static void
+add_theme_to_store (const char   *key,
+                    const char   *value,
+                    GtkListStore *store)
+{
+        char *parent;
+
+        parent = NULL;
+
+        /* Get the parent, if we're checking the custom theme */
+        if (strcmp (key, CUSTOM_THEME_NAME) == 0) {
+                char *name, *path;
+
+                path = custom_theme_dir_path ("index.theme");
+                name = load_index_theme_name (path, &parent);
+                g_free (name);
+                g_free (path);
+        }
+        gtk_list_store_insert_with_values (store, NULL, G_MAXINT,
+                                           THEME_DISPLAY_COL, value,
+                                           THEME_IDENTIFIER_COL, key,
+                                           THEME_PARENT_ID_COL, parent,
+                                           -1);
+        g_free (parent);
+}
+
+static void
+set_combox_for_theme_name (GvcSoundThemeChooser *chooser,
+                           const char           *name)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        gboolean      found;
+
+        /* If the name is empty, use "freedesktop" */
+        if (name == NULL || *name == '\0') {
+                name = "freedesktop";
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+        if (gtk_tree_model_get_iter_first (model, &iter) == FALSE) {
+                return;
+        }
+
+        do {
+                char *value;
+
+                gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &value, -1);
+                found = (value != NULL && strcmp (value, name) == 0);
+                g_free (value);
+
+        } while (!found && gtk_tree_model_iter_next (model, &iter));
+
+        /* When we can't find the theme we need to set, try to set the default
+         * one "freedesktop" */
+        if (found) {
+                gtk_combo_box_set_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter);
+        } else if (strcmp (name, "freedesktop") != 0) {
+                g_debug ("not found, falling back to fdo");
+                set_combox_for_theme_name (chooser, "freedesktop");
+        }
+}
+
+static void
+set_input_feedback_enabled (GvcSoundThemeChooser *chooser,
+                            gboolean              enabled)
+{
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      enabled);
+}
+
+static void
+setup_theme_selector (GvcSoundThemeChooser *chooser)
+{
+        GHashTable           *hash;
+        GtkListStore         *store;
+        GtkCellRenderer      *renderer;
+        const char * const   *data_dirs;
+        const char           *data_dir;
+        char                 *dir;
+        guint                 i;
+
+        /* Add the theme names and their display name to a hash table,
+         * makes it easy to avoid duplicate themes */
+        hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+        data_dirs = g_get_system_data_dirs ();
+        for (i = 0; data_dirs[i] != NULL; i++) {
+                dir = g_build_filename (data_dirs[i], "sounds", NULL);
+                sound_theme_in_dir (hash, dir);
+                g_free (dir);
+        }
+
+        data_dir = g_get_user_data_dir ();
+        dir = g_build_filename (data_dir, "sounds", NULL);
+        sound_theme_in_dir (hash, dir);
+        g_free (dir);
+
+        /* If there isn't at least one theme, make everything
+         * insensitive, LAME! */
+        if (g_hash_table_size (hash) == 0) {
+                gtk_widget_set_sensitive (GTK_WIDGET (chooser), FALSE);
+                g_warning ("Bad setup, install the freedesktop sound theme");
+                g_hash_table_destroy (hash);
+                return;
+        }
+
+        /* Setup the tree model, 3 columns:
+         * - internal theme name/directory
+         * - display theme name
+         * - the internal id for the parent theme, used for the custom theme */
+        store = gtk_list_store_new (THEME_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING);
+
+        /* Add the themes to a combobox */
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           THEME_DISPLAY_COL, _("No sounds"),
+                                           THEME_IDENTIFIER_COL, "__no_sounds",
+                                           THEME_PARENT_ID_COL, NULL,
+                                           -1);
+        g_hash_table_foreach (hash, (GHFunc) add_theme_to_store, store);
+        g_hash_table_destroy (hash);
+
+        /* Set the display */
+        gtk_combo_box_set_model (GTK_COMBO_BOX (chooser->priv->combo_box),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                    renderer,
+                                    TRUE);
+        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                        renderer,
+                                        "text", THEME_DISPLAY_COL,
+                                        NULL);
+
+        g_signal_connect (G_OBJECT (chooser->priv->combo_box),
+                          "changed",
+                          G_CALLBACK (on_combobox_changed),
+                          chooser);
+}
+
+#define GVC_SOUND_SOUND    (xmlChar *) "sound"
+#define GVC_SOUND_NAME     (xmlChar *) "name"
+#define GVC_SOUND_FILENAME (xmlChar *) "filename"
+
+/* Adapted from yelp-toc-pager.c */
+static xmlChar *
+xml_get_and_trim_names (xmlNodePtr node)
+{
+        xmlNodePtr cur;
+        xmlChar *keep_lang = NULL;
+        xmlChar *value;
+        int j, keep_pri = INT_MAX;
+
+        const gchar * const * langs = g_get_language_names ();
+
+        value = NULL;
+
+        for (cur = node->children; cur; cur = cur->next) {
+                if (! xmlStrcmp (cur->name, GVC_SOUND_NAME)) {
+                        xmlChar *cur_lang = NULL;
+                        int cur_pri = INT_MAX;
+
+                        cur_lang = xmlNodeGetLang (cur);
+
+                        if (cur_lang) {
+                                for (j = 0; langs[j]; j++) {
+                                        if (g_str_equal (cur_lang, langs[j])) {
+                                                cur_pri = j;
+                                                break;
+                                        }
+                                }
+                        } else {
+                                cur_pri = INT_MAX - 1;
+                        }
+
+                        if (cur_pri <= keep_pri) {
+                                if (keep_lang)
+                                        xmlFree (keep_lang);
+                                if (value)
+                                        xmlFree (value);
+
+                                value = xmlNodeGetContent (cur);
+
+                                keep_lang = cur_lang;
+                                keep_pri = cur_pri;
+                        } else {
+                                if (cur_lang)
+                                        xmlFree (cur_lang);
+                        }
+                }
+        }
+
+        /* Delete all GVC_SOUND_NAME nodes */
+        cur = node->children;
+        while (cur) {
+                xmlNodePtr this = cur;
+                cur = cur->next;
+                if (! xmlStrcmp (this->name, GVC_SOUND_NAME)) {
+                        xmlUnlinkNode (this);
+                        xmlFreeNode (this);
+                }
+        }
+
+        return value;
+}
+
+static void
+populate_model_from_node (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          xmlNodePtr            node)
+{
+        xmlNodePtr child;
+        xmlChar   *filename;
+        xmlChar   *name;
+
+        filename = NULL;
+        name = xml_get_and_trim_names (node);
+        for (child = node->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+
+                if (xmlStrcmp (child->name, GVC_SOUND_FILENAME) == 0) {
+                        filename = xmlNodeGetContent (child);
+                } else if (xmlStrcmp (child->name, GVC_SOUND_NAME) == 0) {
+                        /* EH? should have been trimmed */
+                }
+        }
+
+        if (filename != NULL && name != NULL) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   ALERT_IDENTIFIER_COL, filename,
+                                                   ALERT_DISPLAY_COL, name,
+                                                   ALERT_SOUND_TYPE_COL, _("Built-in"),
+                                                   ALERT_ACTIVE_COL, FALSE,
+                                                   -1);
+        }
+
+        xmlFree (filename);
+        xmlFree (name);
+}
+
+static void
+populate_model_from_file (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          const char           *filename)
+{
+        xmlDocPtr  doc;
+        xmlNodePtr root;
+        xmlNodePtr child;
+        gboolean   exists;
+
+        exists = g_file_test (filename, G_FILE_TEST_EXISTS);
+        if (! exists) {
+                return;
+        }
+
+        doc = xmlParseFile (filename);
+        if (doc == NULL) {
+                return;
+        }
+
+        root = xmlDocGetRootElement (doc);
+
+        for (child = root->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+                if (xmlStrcmp (child->name, GVC_SOUND_SOUND) != 0) {
+                        continue;
+                }
+
+                populate_model_from_node (chooser, model, child);
+        }
+
+        xmlFreeDoc (doc);
+}
+
+static void
+populate_model_from_dir (GvcSoundThemeChooser *chooser,
+                         GtkTreeModel         *model,
+                         const char           *dirname)
+{
+        GDir       *d;
+        const char *name;
+
+        d = g_dir_open (dirname, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *path;
+
+                if (! g_str_has_suffix (name, ".xml")) {
+                        continue;
+                }
+
+                path = g_build_filename (dirname, name, NULL);
+                populate_model_from_file (chooser, model, path);
+                g_free (path);
+        }
+
+        g_dir_close (d);
+}
+
+static gboolean
+save_alert_sounds (GvcSoundThemeChooser  *chooser,
+                   const char            *id)
+{
+        const char *sounds[3] = { "bell-terminal", "bell-window-system", NULL };
+        char *path;
+
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+        } else {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+                add_custom_file (sounds, id);
+        }
+
+        /* And poke the directory so the theme gets updated */
+        path = custom_theme_dir_path (NULL);
+        if (utime (path, NULL) != 0) {
+                g_warning ("Failed to update mtime for directory '%s': %s",
+                           path, g_strerror (errno));
+        }
+        g_free (path);
+
+        return FALSE;
+}
+
+
+static void
+update_alert_model (GvcSoundThemeChooser  *chooser,
+                    const char            *id)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        gtk_tree_model_get_iter_first (model, &iter);
+        do {
+                gboolean toggled;
+                char    *this_id;
+
+                gtk_tree_model_get (model, &iter,
+                                    ALERT_IDENTIFIER_COL, &this_id,
+                                    -1);
+
+                if (strcmp (this_id, id) == 0) {
+                        toggled = TRUE;
+                } else {
+                        toggled = FALSE;
+                }
+                g_free (this_id);
+
+                gtk_list_store_set (GTK_LIST_STORE (model),
+                                    &iter,
+                                    ALERT_ACTIVE_COL, toggled,
+                                    -1);
+        } while (gtk_tree_model_iter_next (model, &iter));
+}
+
+static void
+update_alert (GvcSoundThemeChooser *chooser,
+              const char           *alert_id)
+{
+        GtkTreeModel *theme_model;
+        GtkTreeIter   iter;
+        char         *theme;
+        char         *parent;
+        gboolean      is_custom;
+        gboolean      is_default;
+        gboolean      add_custom;
+        gboolean      remove_custom;
+
+        theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        /* Get the current theme's name, and set the parent */
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        gtk_tree_model_get (theme_model, &iter,
+                            THEME_IDENTIFIER_COL, &theme,
+                            THEME_IDENTIFIER_COL, &parent,
+                            -1);
+        is_custom = strcmp (theme, CUSTOM_THEME_NAME) == 0;
+        is_default = strcmp (alert_id, DEFAULT_ALERT_ID) == 0;
+
+        /* So a few possibilities:
+         * 1. Named theme, default alert selected: noop
+         * 2. Named theme, alternate alert selected: create new custom with sound
+         * 3. Custom theme, default alert selected: remove sound and possibly custom
+         * 4. Custom theme, alternate alert selected: update custom sound
+         */
+        add_custom = FALSE;
+        remove_custom = FALSE;
+        if (! is_custom && is_default) {
+                /* remove custom just in case */
+                remove_custom = TRUE;
+        } else if (! is_custom && ! is_default) {
+                create_custom_theme (parent);
+                save_alert_sounds (chooser, alert_id);
+                add_custom = TRUE;
+        } else if (is_custom && is_default) {
+                save_alert_sounds (chooser, alert_id);
+                /* after removing files check if it is empty */
+                if (custom_theme_dir_is_empty ()) {
+                        remove_custom = TRUE;
+                }
+        } else if (is_custom && ! is_default) {
+                save_alert_sounds (chooser, alert_id);
+        }
+
+        if (add_custom) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (theme_model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   THEME_DISPLAY_COL, _("Custom"),
+                                                   THEME_IDENTIFIER_COL, CUSTOM_THEME_NAME,
+                                                   THEME_PARENT_ID_COL, theme,
+                                                   -1);
+                set_combox_for_theme_name (chooser, CUSTOM_THEME_NAME);
+        } else if (remove_custom) {
+                gtk_tree_model_get_iter_first (theme_model, &iter);
+                do {
+                        char *this_parent;
+
+                        gtk_tree_model_get (theme_model, &iter,
+                                            THEME_PARENT_ID_COL, &this_parent,
+                                            -1);
+                        if (this_parent != NULL && strcmp (this_parent, CUSTOM_THEME_NAME) != 0) {
+                                g_free (this_parent);
+                                gtk_list_store_remove (GTK_LIST_STORE (theme_model), &iter);
+                                break;
+                        }
+                        g_free (this_parent);
+                } while (gtk_tree_model_iter_next (theme_model, &iter));
+
+                delete_custom_theme_dir ();
+
+                set_combox_for_theme_name (chooser, parent);
+        }
+
+        update_alert_model (chooser, alert_id);
+
+        g_free (theme);
+        g_free (parent);
+}
+
+static void
+on_alert_toggled (GtkCellRendererToggle *renderer,
+                  char                  *path_str,
+                  GvcSoundThemeChooser  *chooser)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreePath  *path;
+        gboolean      toggled;
+        char         *id;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        path = gtk_tree_path_new_from_string (path_str);
+        gtk_tree_model_get_iter (model, &iter, path);
+        gtk_tree_path_free (path);
+
+        id = NULL;
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            ALERT_ACTIVE_COL, &toggled,
+                            -1);
+
+        toggled ^= 1;
+        if (toggled) {
+                update_alert (chooser, id);
+        }
+
+        g_free (id);
+}
+
+static void
+play_preview_for_path (GvcSoundThemeChooser *chooser, GtkTreePath *path)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreeIter   theme_iter;
+        gchar        *id = NULL;
+        gchar        *parent_theme = NULL;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        if (gtk_tree_model_get_iter (model, &iter, path) == FALSE)
+                return;
+
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            -1);
+        if (id == NULL)
+                return;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &theme_iter)) {
+                GtkTreeModel *theme_model;
+                gchar        *theme_id = NULL;
+                gchar        *parent_id = NULL;
+
+                theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+                gtk_tree_model_get (theme_model, &theme_iter,
+                                    THEME_IDENTIFIER_COL, &theme_id,
+                                    THEME_PARENT_ID_COL, &parent_id, -1);
+                if (theme_id && strcmp (theme_id, CUSTOM_THEME_NAME) == 0)
+                        parent_theme = g_strdup (parent_id);
+
+                g_free (theme_id);
+                g_free (parent_id);
+        }
+
+        /* special case: for the default item on custom themes
+         * play the alert for the parent theme */
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                if (parent_theme != NULL) {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_CANBERRA_XDG_THEME_NAME, parent_theme,
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                } else {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                }
+        } else {
+                ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                        CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                        CA_PROP_MEDIA_FILENAME, id,
+                                        CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                        CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                        CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                        CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                        NULL);
+
+        }
+        g_free (parent_theme);
+        g_free (id);
+}
+
+static void
+on_treeview_row_activated (GtkTreeView          *treeview,
+                           GtkTreePath          *path,
+                           GtkTreeViewColumn    *column,
+                           GvcSoundThemeChooser *chooser)
+{
+        play_preview_for_path (chooser, path);
+}
+
+static void
+on_treeview_selection_changed (GtkTreeSelection     *selection,
+                               GvcSoundThemeChooser *chooser)
+{
+        GList        *paths;
+        GtkTreeModel *model;
+        GtkTreePath  *path;
+
+        if (chooser->priv->treeview == NULL)
+                return;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        paths = gtk_tree_selection_get_selected_rows (selection, &model);
+        if (paths == NULL)
+                return;
+
+        path = paths->data;
+        play_preview_for_path (chooser, path);
+
+        g_list_foreach (paths, (GFunc)gtk_tree_path_free, NULL);
+        g_list_free (paths);
+}
+
+static GtkWidget *
+create_alert_treeview (GvcSoundThemeChooser *chooser)
+{
+        GtkListStore         *store;
+        GtkWidget            *treeview;
+        GtkCellRenderer      *renderer;
+        GtkTreeViewColumn    *column;
+        GtkTreeSelection     *selection;
+
+        treeview = gtk_tree_view_new ();
+
+        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
+        g_signal_connect (G_OBJECT (treeview),
+                          "row-activated",
+                          G_CALLBACK (on_treeview_row_activated),
+                          chooser);
+
+        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+        gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+        g_signal_connect (G_OBJECT (selection),
+                          "changed",
+                          G_CALLBACK (on_treeview_selection_changed),
+                          chooser);
+
+        /* Setup the tree model, 3 columns:
+         * - display name
+         * - sound id
+         * - sound type
+         */
+        store = gtk_list_store_new (ALERT_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_BOOLEAN);
+
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           ALERT_IDENTIFIER_COL, DEFAULT_ALERT_ID,
+                                           ALERT_DISPLAY_COL, _("Default"),
+                                           ALERT_SOUND_TYPE_COL, _("From theme"),
+                                           ALERT_ACTIVE_COL, TRUE,
+                                           -1);
+
+        populate_model_from_dir (chooser, GTK_TREE_MODEL (store), SOUND_SET_DIR);
+
+        gtk_tree_view_set_model (GTK_TREE_VIEW (treeview),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_toggle_new ();
+        gtk_cell_renderer_toggle_set_radio (GTK_CELL_RENDERER_TOGGLE (renderer), TRUE);
+
+        column = gtk_tree_view_column_new_with_attributes (NULL,
+                                                           renderer,
+                                                           "active", ALERT_ACTIVE_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+        g_signal_connect (renderer,
+                          "toggled",
+                          G_CALLBACK (on_alert_toggled),
+                          chooser);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Name"),
+                                                           renderer,
+                                                           "text", ALERT_DISPLAY_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Type"),
+                                                           renderer,
+                                                           "text", ALERT_SOUND_TYPE_COL,
+                                                           NULL);
+
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        return treeview;
+}
+
+static int
+get_file_type (const char *sound_name,
+               char      **linked_name)
+{
+        char *name, *filename;
+
+        *linked_name = NULL;
+
+        name = g_strdup_printf ("%s.disabled", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_REGULAR) != FALSE) {
+                g_free (filename);
+                return SOUND_TYPE_OFF;
+        }
+        g_free (filename);
+
+        /* We only check for .ogg files because those are the
+         * only ones we create */
+        name = g_strdup_printf ("%s.ogg", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_SYMLINK) != FALSE) {
+                *linked_name = g_file_read_link (filename, NULL);
+                g_free (filename);
+                return SOUND_TYPE_CUSTOM;
+        }
+        g_free (filename);
+
+        return SOUND_TYPE_BUILTIN;
+}
+
+static void
+update_alerts_from_theme_name (GvcSoundThemeChooser *chooser,
+                               const gchar          *name)
+{
+        if (strcmp (name, CUSTOM_THEME_NAME) != 0) {
+                /* reset alert to default */
+                update_alert (chooser, DEFAULT_ALERT_ID);
+        } else {
+                int   sound_type;
+                char *linkname;
+
+                linkname = NULL;
+                sound_type = get_file_type ("bell-terminal", &linkname);
+                g_debug ("Found link: %s", linkname);
+                if (sound_type == SOUND_TYPE_CUSTOM) {
+                        update_alert (chooser, linkname);
+                }
+        }
+}
+
+static void
+update_theme (GvcSoundThemeChooser *chooser)
+{
+        char        *theme_name;
+        gboolean     events_enabled;
+        gboolean     feedback_enabled;
+
+        feedback_enabled = g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY);
+        set_input_feedback_enabled (chooser, feedback_enabled);
+
+        events_enabled = g_settings_get_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY);
+        if (events_enabled) {
+                theme_name = g_settings_get_string (chooser->priv->sound_settings, SOUND_THEME_KEY);
+        } else {
+                theme_name = g_strdup (NO_SOUNDS_THEME_NAME);
+        }
+
+        gtk_widget_set_sensitive (chooser->priv->selection_box, events_enabled);
+        gtk_widget_set_sensitive (chooser->priv->click_feedback_button, events_enabled);
+
+        set_combox_for_theme_name (chooser, theme_name);
+
+        update_alerts_from_theme_name (chooser, theme_name);
+
+        g_free (theme_name);
+}
+
+static void
+gvc_sound_theme_chooser_class_init (GvcSoundThemeChooserClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_sound_theme_chooser_dispose;
+}
+
+static void
+on_click_feedback_toggled (GtkToggleButton      *button,
+                           GvcSoundThemeChooser *chooser)
+{
+        gboolean enabled;
+
+        enabled = gtk_toggle_button_get_active (button);
+
+        g_settings_set_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY, enabled);
+}
+
+static void
+on_key_changed (GSettings            *settings,
+                gchar                *key,
+                GvcSoundThemeChooser *chooser)
+{
+        if (!strcmp (key, EVENT_SOUNDS_KEY) ||
+            !strcmp (key, SOUND_THEME_KEY) ||
+            !strcmp (key, INPUT_SOUNDS_KEY))
+                update_theme (chooser);
+}
+
+static void
+setup_list_size_constraint (GtkWidget *widget,
+                            GtkWidget *to_size)
+{
+        GtkRequisition req;
+        gint           sc_height;
+        int            max_height;
+
+        /* Constrain height to be the tree height up to a max */
+        gdk_window_get_geometry (gdk_screen_get_root_window (gtk_widget_get_screen (widget)),
+                                 NULL, NULL, NULL, &sc_height);
+
+        max_height = sc_height / 4;
+
+        // XXX this doesn't work
+        gtk_widget_get_preferred_size (to_size, NULL, &req);
+
+        gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (widget),
+                                                    MIN (req.height, max_height));
+}
+
+static void
+gvc_sound_theme_chooser_init (GvcSoundThemeChooser *chooser)
+{
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *scrolled_window;
+        gchar       *str;
+
+        chooser->priv = gvc_sound_theme_chooser_get_instance_private (chooser);
+
+        chooser->priv->theme_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->theme_box, FALSE, FALSE, 0);
+
+        label = gtk_label_new_with_mnemonic (_("Sound _theme:"));
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), label, FALSE, FALSE, 0);
+        chooser->priv->combo_box = gtk_combo_box_new ();
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), chooser->priv->combo_box, FALSE, FALSE, 6);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->combo_box);
+
+        chooser->priv->sound_settings = g_settings_new (KEY_SOUNDS_SCHEMA);
+
+        g_signal_connect (G_OBJECT (chooser->priv->sound_settings),
+                          "changed",
+                          G_CALLBACK (on_key_changed),
+                          chooser);
+
+        str = g_strdup_printf ("<b>%s</b>", _("C_hoose an alert sound:"));
+        chooser->priv->selection_box = box = gtk_frame_new (str);
+        g_free (str);
+
+        label = gtk_frame_get_label_widget (GTK_FRAME (box));
+        gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
+        gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+        gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
+
+        gtk_box_pack_start (GTK_BOX (chooser), box, TRUE, TRUE, 6);
+
+        chooser->priv->treeview = create_alert_treeview (chooser);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->treeview);
+
+        scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+        gtk_widget_set_hexpand (scrolled_window, TRUE);
+        gtk_widget_set_vexpand (scrolled_window, TRUE);
+        gtk_widget_set_margin_top (scrolled_window, 6);
+
+        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+                                        GTK_POLICY_NEVER,
+                                        GTK_POLICY_AUTOMATIC);
+        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
+                                             GTK_SHADOW_IN);
+
+        gtk_container_add (GTK_CONTAINER (scrolled_window), chooser->priv->treeview);
+        gtk_container_add (GTK_CONTAINER (box), scrolled_window);
+
+        chooser->priv->click_feedback_button = gtk_check_button_new_with_mnemonic (_("Enable _window and button sounds"));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY));
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->click_feedback_button,
+                            FALSE, FALSE, 0);
+
+        g_signal_connect (G_OBJECT (chooser->priv->click_feedback_button),
+                          "toggled",
+                          G_CALLBACK (on_click_feedback_toggled),
+                          chooser);
+
+        setup_theme_selector (chooser);
+        update_theme (chooser);
+
+        setup_list_size_constraint (scrolled_window, chooser->priv->treeview);
+}
+
+static void
+gvc_sound_theme_chooser_dispose (GObject *object)
+{
+        GvcSoundThemeChooser *chooser;
+
+        chooser = GVC_SOUND_THEME_CHOOSER (object);
+
+        g_clear_object (&chooser->priv->sound_settings);
+
+        G_OBJECT_CLASS (gvc_sound_theme_chooser_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_sound_theme_chooser_new (void)
+{
+        return g_object_new (GVC_TYPE_SOUND_THEME_CHOOSER,
+                                "spacing", 6,
+                                "orientation", GTK_ORIENTATION_VERTICAL,
+                                NULL);
+}
+
+
+
+ + + diff --git a/2020-04-19-141137-3704-cppcheck@7dca88a484ae_master/2.html b/2020-04-19-141137-3704-cppcheck@7dca88a484ae_master/2.html new file mode 100644 index 0000000..bacfabb --- /dev/null +++ b/2020-04-19-141137-3704-cppcheck@7dca88a484ae_master/2.html @@ -0,0 +1,1110 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <canberra.h>
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-speaker-test.h"
+#include "gvc-utils.h"
+
+struct _GvcSpeakerTestPrivate
+{
+        GArray           *controls;
+        ca_context       *canberra;
+        MateMixerStream  *stream;
+};
+
+enum {
+        PROP_0,
+        PROP_STREAM,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_speaker_test_dispose    (GObject             *object);
+static void gvc_speaker_test_finalize   (GObject             *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSpeakerTest, gvc_speaker_test, GTK_TYPE_GRID)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+typedef struct {
+        MateMixerChannelPosition position;
+        guint left;
+        guint top;
+} TablePosition;
+
+static const TablePosition positions[] = {
+        /* Position, X, Y */
+        { MATE_MIXER_CHANNEL_FRONT_LEFT, 0, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_LEFT_CENTER, 1, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_CENTER, 2, 0, },
+        { MATE_MIXER_CHANNEL_MONO, 2, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT_CENTER, 3, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT, 4, 0, },
+        { MATE_MIXER_CHANNEL_SIDE_LEFT, 0, 1, },
+        { MATE_MIXER_CHANNEL_SIDE_RIGHT, 4, 1, },
+        { MATE_MIXER_CHANNEL_BACK_LEFT, 0, 2, },
+        { MATE_MIXER_CHANNEL_BACK_CENTER, 2, 2, },
+        { MATE_MIXER_CHANNEL_BACK_RIGHT, 4, 2, },
+        { MATE_MIXER_CHANNEL_LFE, 3, 2 }
+};
+
+MateMixerStream *
+gvc_speaker_test_get_stream (GvcSpeakerTest *test)
+{
+        g_return_val_if_fail (GVC_IS_SPEAKER_TEST (test), NULL);
+
+        return test->priv->stream;
+}
+
+static void
+gvc_speaker_test_set_stream (GvcSpeakerTest *test, MateMixerStream *stream)
+{
+        MateMixerStreamControl *control;
+        const gchar            *name;
+        guint                   i;
+
+        name = mate_mixer_stream_get_name (stream);
+        control = mate_mixer_stream_get_default_control (stream);
+
+        ca_context_change_device (test->priv->canberra, name);
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                gboolean has_position =
+                        mate_mixer_stream_control_has_channel_position (control, positions[i].position);
+
+                gtk_widget_set_visible (g_array_index (test->priv->controls, GtkWidget *, i),
+                                        has_position);
+        }
+
+        test->priv->stream = g_object_ref (stream);
+}
+
+static void
+gvc_speaker_test_set_property (GObject       *object,
+                               guint          prop_id,
+                               const GValue  *value,
+                               GParamSpec    *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                gvc_speaker_test_set_stream (self, g_value_get_object (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_get_property (GObject     *object,
+                               guint        prop_id,
+                               GValue      *value,
+                               GParamSpec  *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                g_value_set_object (value, self->priv->stream);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_class_init (GvcSpeakerTestClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose  = gvc_speaker_test_dispose;
+        object_class->finalize = gvc_speaker_test_finalize;
+        object_class->set_property = gvc_speaker_test_set_property;
+        object_class->get_property = gvc_speaker_test_get_property;
+
+        properties[PROP_STREAM] =
+                g_param_spec_object ("stream",
+                                     "Stream",
+                                     "MateMixer stream",
+                                     MATE_MIXER_TYPE_STREAM,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+}
+
+static const gchar *
+sound_name (MateMixerChannelPosition position)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return "audio-channel-front-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return "audio-channel-front-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return "audio-channel-front-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return "audio-channel-rear-left";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return "audio-channel-rear-right";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return "audio-channel-rear-center";
+        case MATE_MIXER_CHANNEL_LFE:
+                return "audio-channel-lfe";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return "audio-channel-side-left";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return "audio-channel-side-right";
+        default:
+                return NULL;
+        }
+}
+
+static const gchar *
+icon_name (MateMixerChannelPosition position, gboolean playing)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return playing
+                        ? "audio-speaker-left-testing"
+                        : "audio-speaker-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return playing
+                        ? "audio-speaker-right-testing"
+                        : "audio-speaker-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return playing
+                        ? "audio-speaker-center-testing"
+                        : "audio-speaker-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return playing
+                        ? "audio-speaker-left-back-testing"
+                        : "audio-speaker-left-back";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return playing
+                        ? "audio-speaker-right-back-testing"
+                        : "audio-speaker-right-back";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return playing
+                        ? "audio-speaker-center-back-testing"
+                        : "audio-speaker-center-back";
+        case MATE_MIXER_CHANNEL_LFE:
+                return playing
+                        ? "audio-subwoofer-testing"
+                        : "audio-subwoofer";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return playing
+                        ? "audio-speaker-left-side-testing"
+                        : "audio-speaker-left-side";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return playing
+                        ? "audio-speaker-right-side-testing"
+                        : "audio-speaker-right-side";
+        default:
+                return NULL;
+        }
+}
+
+static void
+update_button (GtkWidget *control)
+{
+        GtkWidget *button;
+        GtkWidget *image;
+        gboolean   playing;
+        MateMixerChannelPosition position;
+
+        button = g_object_get_data (G_OBJECT (control), "button");
+        image  = g_object_get_data (G_OBJECT (control), "image");
+
+        position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+        playing  = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        gtk_button_set_label (GTK_BUTTON (button), playing ? _("Stop") : _("Test"));
+
+        gtk_image_set_from_icon_name (GTK_IMAGE (image),
+                                      icon_name (position, playing),
+                                      GTK_ICON_SIZE_DIALOG);
+}
+
+static gboolean
+idle_cb (GtkWidget *control)
+{
+        if (control != NULL) {
+                /* This is called in the background thread, hence forward to main thread
+                 * via idle callback */
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+
+                update_button (control);
+        }
+        return FALSE;
+}
+
+static void
+finish_cb (ca_context *c, uint32_t id, int error_code, void *userdata)
+{
+        GtkWidget *control = (GtkWidget *) userdata;
+
+        if (error_code == CA_ERROR_DESTROYED || control == NULL)
+                return;
+
+        g_idle_add ((GSourceFunc) idle_cb, control);
+}
+
+static void
+on_test_button_clicked (GtkButton *button, GtkWidget *control)
+{
+        gboolean    playing;
+        ca_context *canberra;
+
+        canberra = g_object_get_data (G_OBJECT (control), "canberra");
+
+        ca_context_cancel (canberra, 1);
+
+        playing = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        if (playing) {
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        } else {
+                MateMixerChannelPosition position;
+                const gchar *name;
+                ca_proplist *proplist;
+
+                position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+
+                ca_proplist_create (&proplist);
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_ROLE, "test");
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_NAME,
+                                  gvc_channel_position_to_pretty_string (position));
+                ca_proplist_sets (proplist,
+                                  CA_PROP_CANBERRA_FORCE_CHANNEL,
+                                  gvc_channel_position_to_pulse_string (position));
+
+                ca_proplist_sets (proplist, CA_PROP_CANBERRA_ENABLE, "1");
+
+                name = sound_name (position);
+                if (name != NULL) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, name);
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, "audio-test-signal");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets(proplist, CA_PROP_EVENT_ID, "bell-window-system");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (playing));
+        }
+
+        update_button (control);
+}
+
+static GtkWidget *
+create_control (ca_context *canberra, MateMixerChannelPosition position)
+{
+        GtkWidget   *control;
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *image;
+        GtkWidget   *test_button;
+        const gchar *name;
+
+        control = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+        box     = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        g_object_set_data (G_OBJECT (control), "position", GINT_TO_POINTER (position));
+        g_object_set_data (G_OBJECT (control), "canberra", canberra);
+
+        name = icon_name (position, FALSE);
+        if (name == NULL)
+                name = "audio-volume-medium";
+
+        image = gtk_image_new_from_icon_name (name, GTK_ICON_SIZE_DIALOG);
+        g_object_set_data (G_OBJECT (control), "image", image);
+        gtk_box_pack_start (GTK_BOX (control), image, FALSE, FALSE, 0);
+
+        label = gtk_label_new (gvc_channel_position_to_pretty_string (position));
+        gtk_box_pack_start (GTK_BOX (control), label, FALSE, FALSE, 0);
+
+        test_button = gtk_button_new_with_label (_("Test"));
+        g_signal_connect (G_OBJECT (test_button),
+                          "clicked",
+                          G_CALLBACK (on_test_button_clicked),
+                          control);
+
+        g_object_set_data (G_OBJECT (control), "button", test_button);
+
+        gtk_box_pack_start (GTK_BOX (box), test_button, TRUE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (control), box, FALSE, FALSE, 0);
+
+        gtk_widget_show_all (control);
+
+        return control;
+}
+
+static void
+create_controls (GvcSpeakerTest *test)
+{
+        guint i;
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                GtkWidget *control = create_control (test->priv->canberra, positions[i].position);
+
+                gtk_grid_attach (GTK_GRID (test),
+                                 control,
+                                 positions[i].left,
+                                 positions[i].top,
+                                 1, 1);
+                g_array_insert_val (test->priv->controls, i, control);
+        }
+}
+
+static void
+gvc_speaker_test_init (GvcSpeakerTest *test)
+{
+        GtkWidget *face;
+
+        test->priv = gvc_speaker_test_get_instance_private (test);
+
+        gtk_container_set_border_width (GTK_CONTAINER (test), 12);
+
+        face = gtk_image_new_from_icon_name ("face-smile", GTK_ICON_SIZE_DIALOG);
+
+        gtk_grid_attach (GTK_GRID (test),
+                         face,
+                         1, 1,
+                         3, 1);
+
+
+        gtk_grid_set_baseline_row (GTK_GRID (test), 1);
+        gtk_widget_show (face);
+
+        ca_context_create (&test->priv->canberra);
+
+        /* The test sounds are played for a single channel, set up using the
+         * FORCE_CHANNEL property of libcanberra; this property is only supported
+         * in the PulseAudio backend, so avoid other backends completely */
+        ca_context_set_driver (test->priv->canberra, "pulse");
+
+        ca_context_change_props (test->priv->canberra,
+                                 CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+                                 CA_PROP_APPLICATION_NAME, _("Volume Control"),
+                                 CA_PROP_APPLICATION_VERSION, VERSION,
+                                 CA_PROP_APPLICATION_ICON_NAME, "multimedia-volume-control",
+                                 NULL);
+
+        test->priv->controls = g_array_new (FALSE, FALSE, sizeof (GtkWidget *));
+
+        create_controls (test);
+}
+
+static void
+gvc_speaker_test_dispose (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        g_clear_object (&test->priv->stream);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->dispose (object);
+}
+
+static void
+gvc_speaker_test_finalize (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        ca_context_destroy (test->priv->canberra);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->finalize (object);
+}
+
+GtkWidget *
+gvc_speaker_test_new (MateMixerStream *stream)
+{
+        GObject *test;
+
+        g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL);
+
+        test = g_object_new (GVC_TYPE_SPEAKER_TEST,
+                             "row-spacing", 6,
+                             "column-spacing", 6,
+                             "row-homogeneous", TRUE,
+                             "column-homogeneous", TRUE,
+                             "stream", stream,
+                             NULL);
+
+        return GTK_WIDGET (test);
+}
+
+
+
+ + + diff --git a/2020-04-19-141137-3704-cppcheck@7dca88a484ae_master/index.html b/2020-04-19-141137-3704-cppcheck@7dca88a484ae_master/index.html new file mode 100644 index 0000000..59baeb0 --- /dev/null +++ b/2020-04-19-141137-3704-cppcheck@7dca88a484ae_master/index.html @@ -0,0 +1,108 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
mate-volume-control/gvc-combo-box.c
70unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
mate-volume-control/gvc-sound-theme-chooser.c
735ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
746ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
758ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
mate-volume-control/gvc-speaker-test.c
53unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+ + + diff --git a/2020-04-19-141137-3704-cppcheck@7dca88a484ae_master/stats.html b/2020-04-19-141137-3704-cppcheck@7dca88a484ae_master/stats.html new file mode 100644 index 0000000..3fb6add --- /dev/null +++ b/2020-04-19-141137-3704-cppcheck@7dca88a484ae_master/stats.html @@ -0,0 +1,93 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+

Top 10 files for error severity, total findings: 2
+   1  mate-volume-control/gvc-speaker-test.c
+   1  mate-volume-control/gvc-combo-box.c
+

+

Top 10 files for information severity, total findings: 3
+   3  mate-volume-control/gvc-sound-theme-chooser.c
+

+ +
+ + + diff --git a/2020-04-19-141137-3704-cppcheck@7dca88a484ae_master/style.css b/2020-04-19-141137-3704-cppcheck@7dca88a484ae_master/style.css new file mode 100644 index 0000000..c39571c --- /dev/null +++ b/2020-04-19-141137-3704-cppcheck@7dca88a484ae_master/style.css @@ -0,0 +1,149 @@ + +body { + font: 13px Arial, Verdana, Sans-Serif; + margin: 0; + width: auto; +} + +h1 { + margin: 10px; +} + +#footer > p { + margin: 4px; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + border: 1px dotted black; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #B6B6B4; +} + +.inconclusive2 { + background-color: #B6B6B4; + border: 1px dotted black; + display: inline-block; + margin-left: 4px; +} + +div.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +div.verbose div.content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid black; + background-color: #FFFFCC; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +#header { + border-bottom: thin solid #aaa; +} + +#menu { + float: left; + margin-top: 5px; + text-align: left; + width: 150px; + /*height: 75%;*/ + position: fixed; + overflow: auto; + z-index: 1; +} + +#menu_index { + float: left; + margin-top: 5px; + padding-left: 5px; + text-align: left; + width: 300px; + /*height: 75%;*/ + position: fixed; + overflow: auto; + z-index: 1; +} + +#menu > a { + display: block; + margin-left: 10px; + font: 12px; + z-index: 1; +} + +#filename { + margin-left: 10px; + font: 12px; + z-index: 1; +} + +.highlighttable { + background-color:white; + z-index: 10; + position: relative; + margin: -10 px; +} + +#content { + background-color: white; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + float: left; + margin: 5px; + margin-left: 10px; + padding: 0 10px 10px 10px; + width: 80%; + padding-left: 150px; +} + +#content_index { + background-color: white; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + float: left; + margin: 5px; + margin-left: 10px; + padding: 0 10px 10px 10px; + width: 80%; + padding-left: 300px; +} + +.linenos { + border-right: thin solid #aaa; + color: lightgray; + padding-right: 6px; +} + +#footer { + border-top: thin solid #aaa; + clear: both; + font-size: 90%; + margin-top: 5px; +} + +#footer ul { + list-style-type: none; + padding-left: 0; +} diff --git a/2020-04-21-011735-7455-cppcheck@e864ce9bb951_travis/0.html b/2020-04-21-011735-7455-cppcheck@e864ce9bb951_travis/0.html new file mode 100644 index 0000000..e262ed0 --- /dev/null +++ b/2020-04-21-011735-7455-cppcheck@e864ce9bb951_travis/0.html @@ -0,0 +1,1038 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-combo-box.h"
+
+struct _GvcComboBoxPrivate
+{
+        GtkWidget       *drop_box;
+        GtkWidget       *start_box;
+        GtkWidget       *end_box;
+        GtkWidget       *label;
+        GtkWidget       *button;
+        GtkTreeModel    *model;
+        GtkWidget       *combobox;
+        MateMixerSwitch *swtch;
+};
+
+enum {
+        COL_NAME,
+        COL_HUMAN_NAME,
+        NUM_COLS
+};
+
+enum {
+        CHANGING,
+        BUTTON_CLICKED,
+        LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+enum {
+        PROP_0,
+        PROP_SWITCH,
+        PROP_LABEL,
+        PROP_SHOW_BUTTON,
+        PROP_BUTTON_LABEL,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_combo_box_dispose    (GObject          *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcComboBox, gvc_combo_box, GTK_TYPE_BOX)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+MateMixerSwitch *
+gvc_combo_box_get_switch (GvcComboBox *combobox)
+{
+        g_return_val_if_fail (GVC_IS_COMBO_BOX (combobox), NULL);
+
+        return combobox->priv->swtch;
+}
+
+void
+gvc_combo_box_set_size_group (GvcComboBox  *combobox,
+                              GtkSizeGroup *group,
+                              gboolean      symmetric)
+{
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (GTK_IS_SIZE_GROUP (group));
+
+        if (group != NULL) {
+                gtk_size_group_add_widget (group, combobox->priv->start_box);
+                if (symmetric == TRUE)
+                        gtk_size_group_add_widget (group, combobox->priv->end_box);
+        }
+        gtk_widget_queue_draw (GTK_WIDGET (combobox));
+}
+
+static void
+on_switch_active_option_notify (MateMixerSwitch *swtch,
+                                GParamSpec      *pspec,
+                                GvcComboBox     *combobox)
+{
+        GtkTreeIter            iter;
+        MateMixerSwitchOption *active;
+        gboolean               cont;
+        const gchar           *name;
+
+        active = mate_mixer_switch_get_active_option (swtch);
+        if (G_UNLIKELY (active == NULL)) {
+                g_warn_if_reached ();
+                return;
+        }
+
+        /* Select the newly activated switch option in the combo box */
+        name = mate_mixer_switch_option_get_name (active);
+        cont = gtk_tree_model_get_iter_first (combobox->priv->model, &iter);
+        while (cont == TRUE) {
+                gchar *current;
+
+                gtk_tree_model_get (combobox->priv->model, &iter,
+                                    COL_NAME, &current,
+                                    -1);
+                if (g_strcmp0 (name, current) == 0) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox), &iter);
+                        g_free (current);
+                        return;
+                }
+                g_free (current);
+
+                cont = gtk_tree_model_iter_next (combobox->priv->model, &iter);
+        }
+        g_warning ("Could not find switch option '%s' in combo box", name);
+}
+
+static void
+gvc_combo_box_set_switch (GvcComboBox *combobox, MateMixerSwitch *swtch)
+{
+        MateMixerSwitchOption *active;
+        const GList           *options;
+
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (MATE_MIXER_IS_SWITCH (swtch));
+
+        combobox->priv->swtch = g_object_ref (swtch);
+
+        active  = mate_mixer_switch_get_active_option (swtch);
+        options = mate_mixer_switch_list_options (swtch);
+        while (options != NULL) {
+                GtkTreeIter            iter;
+                MateMixerSwitchOption *option = MATE_MIXER_SWITCH_OPTION (options->data);
+
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (combobox->priv->model),
+                                                   &iter,
+                                                   G_MAXINT,
+                                                   COL_NAME,
+                                                   mate_mixer_switch_option_get_name (option),
+                                                   COL_HUMAN_NAME,
+                                                   mate_mixer_switch_option_get_label (option),
+                                                   -1);
+
+                /* Select the currently active option of the switch */
+                if (option == active) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox),
+                                                       &iter);
+                }
+                options = options->next;
+        }
+
+        g_signal_connect (G_OBJECT (swtch),
+                          "notify::active-option",
+                          G_CALLBACK (on_switch_active_option_notify),
+                          combobox);
+}
+
+static void
+gvc_combo_box_set_property (GObject       *object,
+                            guint          prop_id,
+                            const GValue  *value,
+                            GParamSpec    *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                gvc_combo_box_set_switch (self, g_value_get_object (value));
+                break;
+        case PROP_LABEL:
+                gtk_label_set_text_with_mnemonic (GTK_LABEL (self->priv->label), g_value_get_string (value));
+                break;
+        case PROP_BUTTON_LABEL:
+                gtk_button_set_label (GTK_BUTTON (self->priv->button), g_value_get_string (value));
+                break;
+        case PROP_SHOW_BUTTON:
+                gtk_widget_set_visible (self->priv->button, g_value_get_boolean (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_get_property (GObject     *object,
+                            guint        prop_id,
+                            GValue      *value,
+                            GParamSpec  *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                g_value_set_object (value, self->priv->swtch);
+                break;
+        case PROP_LABEL:
+                g_value_set_string (value, gtk_label_get_text (GTK_LABEL (self->priv->label)));
+                break;
+        case PROP_BUTTON_LABEL:
+                g_value_set_string (value, gtk_button_get_label (GTK_BUTTON (self->priv->button)));
+                break;
+        case PROP_SHOW_BUTTON:
+                g_value_set_boolean (value, gtk_widget_get_visible (self->priv->button));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_class_init (GvcComboBoxClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_combo_box_dispose;
+        object_class->set_property = gvc_combo_box_set_property;
+        object_class->get_property = gvc_combo_box_get_property;
+
+        properties[PROP_SWITCH] =
+                g_param_spec_object ("switch",
+                                     "switch",
+                                     "The MateMixerSwitch",
+                                     MATE_MIXER_TYPE_SWITCH,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_LABEL] =
+                g_param_spec_string ("label",
+                                     "label",
+                                     "The combo box label",
+                                     _("_Profile:"),
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_SHOW_BUTTON] =
+                g_param_spec_boolean ("show-button",
+                                      "show-button",
+                                      "Whether to show the button",
+                                      FALSE,
+                                      G_PARAM_READWRITE |
+                                      G_PARAM_CONSTRUCT |
+                                      G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_BUTTON_LABEL] =
+                g_param_spec_string ("button-label",
+                                     "button-label",
+                                     "The button's label",
+                                     "",
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+
+        signals[CHANGING] =
+                g_signal_new ("changing",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, changing),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__OBJECT,
+                              G_TYPE_NONE,
+                              1,
+                              MATE_MIXER_TYPE_SWITCH_OPTION);
+
+        signals[BUTTON_CLICKED] =
+                g_signal_new ("button-clicked",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, button_clicked),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
+}
+
+static void
+on_combo_box_changed (GtkComboBox *widget, GvcComboBox *combobox)
+{
+        GtkTreeIter            iter;
+        gchar                 *name;
+        MateMixerSwitchOption *option;
+
+        if (G_UNLIKELY (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter) == FALSE))
+                return;
+
+        gtk_tree_model_get (combobox->priv->model, &iter,
+                            COL_NAME, &name,
+                            -1);
+
+        option = mate_mixer_switch_get_option (combobox->priv->swtch, name);
+        if (G_UNLIKELY (option == NULL)) {
+                g_warn_if_reached ();
+                g_free (name);
+                return;
+        }
+
+        /* Inform that we are about to change the active option of the switch */
+        g_signal_emit (combobox, signals[CHANGING], 0, option);
+
+        mate_mixer_switch_set_active_option (combobox->priv->swtch, option);
+        g_free (name);
+}
+
+static void
+on_combo_box_button_clicked (GtkButton *button, GvcComboBox *combobox)
+{
+        /* The meaning of the button is defined by the owner, so only notify
+         * when it is clicked on */
+        g_signal_emit (combobox, signals[BUTTON_CLICKED], 0);
+}
+
+static void
+gvc_combo_box_init (GvcComboBox *combobox)
+{
+        GtkWidget       *frame;
+        GtkCellRenderer *renderer;
+
+        frame = gtk_frame_new (NULL);
+        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
+
+        combobox->priv = gvc_combo_box_get_instance_private (combobox);
+
+        combobox->priv->model = GTK_TREE_MODEL (gtk_list_store_new (NUM_COLS,
+                                                                    G_TYPE_STRING,
+                                                                    G_TYPE_STRING));
+
+        combobox->priv->combobox = gtk_combo_box_new_with_model (combobox->priv->model);
+
+        combobox->priv->label = gtk_label_new (NULL);
+
+        gtk_label_set_xalign (GTK_LABEL (combobox->priv->label), 0.0);
+        gtk_label_set_yalign (GTK_LABEL (combobox->priv->label), 0.5);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (combobox->priv->label),
+                                       combobox->priv->combobox);
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                    renderer,
+                                    FALSE);
+        gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                       renderer,
+                                       "text",
+                                       COL_HUMAN_NAME);
+
+        combobox->priv->drop_box  = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->start_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->end_box   = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+        /* Make sure the combo box does not get too long on long profile names */
+        g_object_set (G_OBJECT (renderer),
+                      "ellipsize",
+                      PANGO_ELLIPSIZE_END,
+                      NULL);
+
+        gtk_combo_box_set_popup_fixed_width (GTK_COMBO_BOX (combobox->priv->combobox), FALSE);
+
+        gtk_box_pack_start (GTK_BOX (combobox),
+                            frame,
+                            TRUE, TRUE, 0);
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->start_box,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->start_box),
+                            combobox->priv->label,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->combobox,
+                            TRUE, TRUE, 0);
+
+        combobox->priv->button = gtk_button_new_with_label ("");
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->button,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->end_box,
+                            FALSE, FALSE, 0);
+
+        gtk_container_add (GTK_CONTAINER (frame), combobox->priv->drop_box);
+
+        g_signal_connect (G_OBJECT (combobox->priv->combobox),
+                          "changed",
+                          G_CALLBACK (on_combo_box_changed),
+                          combobox);
+        g_signal_connect (G_OBJECT (combobox->priv->button),
+                          "clicked",
+                          G_CALLBACK (on_combo_box_button_clicked),
+                          combobox);
+
+        gtk_widget_set_no_show_all (combobox->priv->button, TRUE);
+        gtk_widget_show_all (frame);
+}
+
+static void
+gvc_combo_box_dispose (GObject *object)
+{
+        GvcComboBox *combobox;
+
+        combobox = GVC_COMBO_BOX (object);
+
+        if (G_LIKELY (combobox->priv->swtch != NULL)) {
+                g_signal_handlers_disconnect_by_func (G_OBJECT (combobox->priv->swtch),
+                                                      G_CALLBACK (on_switch_active_option_notify),
+                                                      combobox);
+                g_clear_object (&combobox->priv->swtch);
+        }
+
+        g_clear_object (&combobox->priv->model);
+
+        G_OBJECT_CLASS (gvc_combo_box_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_combo_box_new (MateMixerSwitch *swtch, const gchar *label)
+{
+        return g_object_new (GVC_TYPE_COMBO_BOX,
+                             "switch", swtch,
+                             "label", label,
+                             "orientation", GTK_ORIENTATION_HORIZONTAL,
+                             NULL);
+}
+
+
+
+ + + diff --git a/2020-04-21-011735-7455-cppcheck@e864ce9bb951_travis/1.html b/2020-04-21-011735-7455-cppcheck@e864ce9bb951_travis/1.html new file mode 100644 index 0000000..67179f2 --- /dev/null +++ b/2020-04-21-011735-7455-cppcheck@e864ce9bb951_travis/1.html @@ -0,0 +1,2368 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
+ * Copyright (C) 2008 William Jon McCann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <utime.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+#include <canberra-gtk.h>
+#include <libxml/tree.h>
+
+#include "gvc-sound-theme-chooser.h"
+#include "sound-theme-file-utils.h"
+
+struct GvcSoundThemeChooserPrivate
+{
+        GtkWidget *combo_box;
+        GtkWidget *treeview;
+        GtkWidget *theme_box;
+        GtkWidget *selection_box;
+        GtkWidget *click_feedback_button;
+        GSettings *sound_settings;
+};
+
+static void     gvc_sound_theme_chooser_dispose   (GObject            *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSoundThemeChooser, gvc_sound_theme_chooser, GTK_TYPE_BOX)
+
+#define KEY_SOUNDS_SCHEMA          "org.mate.sound"
+#define EVENT_SOUNDS_KEY           "event-sounds"
+#define INPUT_SOUNDS_KEY           "input-feedback-sounds"
+#define SOUND_THEME_KEY            "theme-name"
+
+#define DEFAULT_ALERT_ID        "__default"
+#define CUSTOM_THEME_NAME       "__custom"
+#define NO_SOUNDS_THEME_NAME    "__no_sounds"
+
+enum {
+        THEME_DISPLAY_COL,
+        THEME_IDENTIFIER_COL,
+        THEME_PARENT_ID_COL,
+        THEME_NUM_COLS
+};
+
+enum {
+        ALERT_DISPLAY_COL,
+        ALERT_IDENTIFIER_COL,
+        ALERT_SOUND_TYPE_COL,
+        ALERT_ACTIVE_COL,
+        ALERT_NUM_COLS
+};
+
+enum {
+        SOUND_TYPE_UNSET,
+        SOUND_TYPE_OFF,
+        SOUND_TYPE_DEFAULT_FROM_THEME,
+        SOUND_TYPE_BUILTIN,
+        SOUND_TYPE_CUSTOM
+};
+
+static void
+on_combobox_changed (GtkComboBox          *widget,
+                     GvcSoundThemeChooser *chooser)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        char         *theme_name;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &theme_name, -1);
+
+        g_assert (theme_name != NULL);
+
+        /* It is necessary to update the theme name before any other setting as
+         * the "changed" notification will reload the contents of the widget */
+        g_settings_set_string (chooser->priv->sound_settings, SOUND_THEME_KEY, theme_name);
+
+        /* special case for no sounds */
+        if (strcmp (theme_name, NO_SOUNDS_THEME_NAME) == 0) {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, FALSE);
+                return;
+        } else {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, TRUE);
+        }
+
+        g_free (theme_name);
+
+        /* FIXME: reset alert model */
+}
+
+static char *
+load_index_theme_name (const char *index,
+                       char      **parent)
+{
+        GKeyFile *file;
+        char *indexname = NULL;
+        gboolean hidden;
+
+        file = g_key_file_new ();
+        if (g_key_file_load_from_file (file, index, G_KEY_FILE_KEEP_TRANSLATIONS, NULL) == FALSE) {
+                g_key_file_free (file);
+                return NULL;
+        }
+        /* Don't add hidden themes to the list */
+        hidden = g_key_file_get_boolean (file, "Sound Theme", "Hidden", NULL);
+        if (!hidden) {
+                indexname = g_key_file_get_locale_string (file,
+                                                          "Sound Theme",
+                                                          "Name",
+                                                          NULL,
+                                                          NULL);
+
+                /* Save the parent theme, if there's one */
+                if (parent != NULL) {
+                        *parent = g_key_file_get_string (file,
+                                                         "Sound Theme",
+                                                         "Inherits",
+                                                         NULL);
+                }
+        }
+
+        g_key_file_free (file);
+        return indexname;
+}
+
+static void
+sound_theme_in_dir (GHashTable *hash,
+                    const char *dir)
+{
+        GDir *d;
+        const char *name;
+
+        d = g_dir_open (dir, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *dirname, *index, *indexname;
+
+                /* Look for directories */
+                dirname = g_build_filename (dir, name, NULL);
+                if (g_file_test (dirname, G_FILE_TEST_IS_DIR) == FALSE) {
+                        g_free (dirname);
+                        continue;
+                }
+
+                /* Look for index files */
+                index = g_build_filename (dirname, "index.theme", NULL);
+                g_free (dirname);
+
+                /* Check the name of the theme in the index.theme file */
+                indexname = load_index_theme_name (index, NULL);
+                g_free (index);
+                if (indexname == NULL) {
+                        continue;
+                }
+
+                g_hash_table_insert (hash, g_strdup (name), indexname);
+        }
+
+        g_dir_close (d);
+}
+
+static void
+add_theme_to_store (const char   *key,
+                    const char   *value,
+                    GtkListStore *store)
+{
+        char *parent;
+
+        parent = NULL;
+
+        /* Get the parent, if we're checking the custom theme */
+        if (strcmp (key, CUSTOM_THEME_NAME) == 0) {
+                char *name, *path;
+
+                path = custom_theme_dir_path ("index.theme");
+                name = load_index_theme_name (path, &parent);
+                g_free (name);
+                g_free (path);
+        }
+        gtk_list_store_insert_with_values (store, NULL, G_MAXINT,
+                                           THEME_DISPLAY_COL, value,
+                                           THEME_IDENTIFIER_COL, key,
+                                           THEME_PARENT_ID_COL, parent,
+                                           -1);
+        g_free (parent);
+}
+
+static void
+set_combox_for_theme_name (GvcSoundThemeChooser *chooser,
+                           const char           *name)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        gboolean      found;
+
+        /* If the name is empty, use "freedesktop" */
+        if (name == NULL || *name == '\0') {
+                name = "freedesktop";
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+        if (gtk_tree_model_get_iter_first (model, &iter) == FALSE) {
+                return;
+        }
+
+        do {
+                char *value;
+
+                gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &value, -1);
+                found = (value != NULL && strcmp (value, name) == 0);
+                g_free (value);
+
+        } while (!found && gtk_tree_model_iter_next (model, &iter));
+
+        /* When we can't find the theme we need to set, try to set the default
+         * one "freedesktop" */
+        if (found) {
+                gtk_combo_box_set_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter);
+        } else if (strcmp (name, "freedesktop") != 0) {
+                g_debug ("not found, falling back to fdo");
+                set_combox_for_theme_name (chooser, "freedesktop");
+        }
+}
+
+static void
+set_input_feedback_enabled (GvcSoundThemeChooser *chooser,
+                            gboolean              enabled)
+{
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      enabled);
+}
+
+static void
+setup_theme_selector (GvcSoundThemeChooser *chooser)
+{
+        GHashTable           *hash;
+        GtkListStore         *store;
+        GtkCellRenderer      *renderer;
+        const char * const   *data_dirs;
+        const char           *data_dir;
+        char                 *dir;
+        guint                 i;
+
+        /* Add the theme names and their display name to a hash table,
+         * makes it easy to avoid duplicate themes */
+        hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+        data_dirs = g_get_system_data_dirs ();
+        for (i = 0; data_dirs[i] != NULL; i++) {
+                dir = g_build_filename (data_dirs[i], "sounds", NULL);
+                sound_theme_in_dir (hash, dir);
+                g_free (dir);
+        }
+
+        data_dir = g_get_user_data_dir ();
+        dir = g_build_filename (data_dir, "sounds", NULL);
+        sound_theme_in_dir (hash, dir);
+        g_free (dir);
+
+        /* If there isn't at least one theme, make everything
+         * insensitive, LAME! */
+        if (g_hash_table_size (hash) == 0) {
+                gtk_widget_set_sensitive (GTK_WIDGET (chooser), FALSE);
+                g_warning ("Bad setup, install the freedesktop sound theme");
+                g_hash_table_destroy (hash);
+                return;
+        }
+
+        /* Setup the tree model, 3 columns:
+         * - internal theme name/directory
+         * - display theme name
+         * - the internal id for the parent theme, used for the custom theme */
+        store = gtk_list_store_new (THEME_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING);
+
+        /* Add the themes to a combobox */
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           THEME_DISPLAY_COL, _("No sounds"),
+                                           THEME_IDENTIFIER_COL, "__no_sounds",
+                                           THEME_PARENT_ID_COL, NULL,
+                                           -1);
+        g_hash_table_foreach (hash, (GHFunc) add_theme_to_store, store);
+        g_hash_table_destroy (hash);
+
+        /* Set the display */
+        gtk_combo_box_set_model (GTK_COMBO_BOX (chooser->priv->combo_box),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                    renderer,
+                                    TRUE);
+        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                        renderer,
+                                        "text", THEME_DISPLAY_COL,
+                                        NULL);
+
+        g_signal_connect (G_OBJECT (chooser->priv->combo_box),
+                          "changed",
+                          G_CALLBACK (on_combobox_changed),
+                          chooser);
+}
+
+#define GVC_SOUND_SOUND    (xmlChar *) "sound"
+#define GVC_SOUND_NAME     (xmlChar *) "name"
+#define GVC_SOUND_FILENAME (xmlChar *) "filename"
+
+/* Adapted from yelp-toc-pager.c */
+static xmlChar *
+xml_get_and_trim_names (xmlNodePtr node)
+{
+        xmlNodePtr cur;
+        xmlChar *keep_lang = NULL;
+        xmlChar *value;
+        int j, keep_pri = INT_MAX;
+
+        const gchar * const * langs = g_get_language_names ();
+
+        value = NULL;
+
+        for (cur = node->children; cur; cur = cur->next) {
+                if (! xmlStrcmp (cur->name, GVC_SOUND_NAME)) {
+                        xmlChar *cur_lang = NULL;
+                        int cur_pri = INT_MAX;
+
+                        cur_lang = xmlNodeGetLang (cur);
+
+                        if (cur_lang) {
+                                for (j = 0; langs[j]; j++) {
+                                        if (g_str_equal (cur_lang, langs[j])) {
+                                                cur_pri = j;
+                                                break;
+                                        }
+                                }
+                        } else {
+                                cur_pri = INT_MAX - 1;
+                        }
+
+                        if (cur_pri <= keep_pri) {
+                                if (keep_lang)
+                                        xmlFree (keep_lang);
+                                if (value)
+                                        xmlFree (value);
+
+                                value = xmlNodeGetContent (cur);
+
+                                keep_lang = cur_lang;
+                                keep_pri = cur_pri;
+                        } else {
+                                if (cur_lang)
+                                        xmlFree (cur_lang);
+                        }
+                }
+        }
+
+        /* Delete all GVC_SOUND_NAME nodes */
+        cur = node->children;
+        while (cur) {
+                xmlNodePtr this = cur;
+                cur = cur->next;
+                if (! xmlStrcmp (this->name, GVC_SOUND_NAME)) {
+                        xmlUnlinkNode (this);
+                        xmlFreeNode (this);
+                }
+        }
+
+        return value;
+}
+
+static void
+populate_model_from_node (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          xmlNodePtr            node)
+{
+        xmlNodePtr child;
+        xmlChar   *filename;
+        xmlChar   *name;
+
+        filename = NULL;
+        name = xml_get_and_trim_names (node);
+        for (child = node->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+
+                if (xmlStrcmp (child->name, GVC_SOUND_FILENAME) == 0) {
+                        filename = xmlNodeGetContent (child);
+                } else if (xmlStrcmp (child->name, GVC_SOUND_NAME) == 0) {
+                        /* EH? should have been trimmed */
+                }
+        }
+
+        if (filename != NULL && name != NULL) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   ALERT_IDENTIFIER_COL, filename,
+                                                   ALERT_DISPLAY_COL, name,
+                                                   ALERT_SOUND_TYPE_COL, _("Built-in"),
+                                                   ALERT_ACTIVE_COL, FALSE,
+                                                   -1);
+        }
+
+        xmlFree (filename);
+        xmlFree (name);
+}
+
+static void
+populate_model_from_file (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          const char           *filename)
+{
+        xmlDocPtr  doc;
+        xmlNodePtr root;
+        xmlNodePtr child;
+        gboolean   exists;
+
+        exists = g_file_test (filename, G_FILE_TEST_EXISTS);
+        if (! exists) {
+                return;
+        }
+
+        doc = xmlParseFile (filename);
+        if (doc == NULL) {
+                return;
+        }
+
+        root = xmlDocGetRootElement (doc);
+
+        for (child = root->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+                if (xmlStrcmp (child->name, GVC_SOUND_SOUND) != 0) {
+                        continue;
+                }
+
+                populate_model_from_node (chooser, model, child);
+        }
+
+        xmlFreeDoc (doc);
+}
+
+static void
+populate_model_from_dir (GvcSoundThemeChooser *chooser,
+                         GtkTreeModel         *model,
+                         const char           *dirname)
+{
+        GDir       *d;
+        const char *name;
+
+        d = g_dir_open (dirname, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *path;
+
+                if (! g_str_has_suffix (name, ".xml")) {
+                        continue;
+                }
+
+                path = g_build_filename (dirname, name, NULL);
+                populate_model_from_file (chooser, model, path);
+                g_free (path);
+        }
+
+        g_dir_close (d);
+}
+
+static gboolean
+save_alert_sounds (GvcSoundThemeChooser  *chooser,
+                   const char            *id)
+{
+        const char *sounds[3] = { "bell-terminal", "bell-window-system", NULL };
+        char *path;
+
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+        } else {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+                add_custom_file (sounds, id);
+        }
+
+        /* And poke the directory so the theme gets updated */
+        path = custom_theme_dir_path (NULL);
+        if (utime (path, NULL) != 0) {
+                g_warning ("Failed to update mtime for directory '%s': %s",
+                           path, g_strerror (errno));
+        }
+        g_free (path);
+
+        return FALSE;
+}
+
+
+static void
+update_alert_model (GvcSoundThemeChooser  *chooser,
+                    const char            *id)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        gtk_tree_model_get_iter_first (model, &iter);
+        do {
+                gboolean toggled;
+                char    *this_id;
+
+                gtk_tree_model_get (model, &iter,
+                                    ALERT_IDENTIFIER_COL, &this_id,
+                                    -1);
+
+                if (strcmp (this_id, id) == 0) {
+                        toggled = TRUE;
+                } else {
+                        toggled = FALSE;
+                }
+                g_free (this_id);
+
+                gtk_list_store_set (GTK_LIST_STORE (model),
+                                    &iter,
+                                    ALERT_ACTIVE_COL, toggled,
+                                    -1);
+        } while (gtk_tree_model_iter_next (model, &iter));
+}
+
+static void
+update_alert (GvcSoundThemeChooser *chooser,
+              const char           *alert_id)
+{
+        GtkTreeModel *theme_model;
+        GtkTreeIter   iter;
+        char         *theme;
+        char         *parent;
+        gboolean      is_custom;
+        gboolean      is_default;
+        gboolean      add_custom;
+        gboolean      remove_custom;
+
+        theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        /* Get the current theme's name, and set the parent */
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        gtk_tree_model_get (theme_model, &iter,
+                            THEME_IDENTIFIER_COL, &theme,
+                            THEME_IDENTIFIER_COL, &parent,
+                            -1);
+        is_custom = strcmp (theme, CUSTOM_THEME_NAME) == 0;
+        is_default = strcmp (alert_id, DEFAULT_ALERT_ID) == 0;
+
+        /* So a few possibilities:
+         * 1. Named theme, default alert selected: noop
+         * 2. Named theme, alternate alert selected: create new custom with sound
+         * 3. Custom theme, default alert selected: remove sound and possibly custom
+         * 4. Custom theme, alternate alert selected: update custom sound
+         */
+        add_custom = FALSE;
+        remove_custom = FALSE;
+        if (! is_custom && is_default) {
+                /* remove custom just in case */
+                remove_custom = TRUE;
+        } else if (! is_custom && ! is_default) {
+                create_custom_theme (parent);
+                save_alert_sounds (chooser, alert_id);
+                add_custom = TRUE;
+        } else if (is_custom && is_default) {
+                save_alert_sounds (chooser, alert_id);
+                /* after removing files check if it is empty */
+                if (custom_theme_dir_is_empty ()) {
+                        remove_custom = TRUE;
+                }
+        } else if (is_custom && ! is_default) {
+                save_alert_sounds (chooser, alert_id);
+        }
+
+        if (add_custom) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (theme_model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   THEME_DISPLAY_COL, _("Custom"),
+                                                   THEME_IDENTIFIER_COL, CUSTOM_THEME_NAME,
+                                                   THEME_PARENT_ID_COL, theme,
+                                                   -1);
+                set_combox_for_theme_name (chooser, CUSTOM_THEME_NAME);
+        } else if (remove_custom) {
+                gtk_tree_model_get_iter_first (theme_model, &iter);
+                do {
+                        char *this_parent;
+
+                        gtk_tree_model_get (theme_model, &iter,
+                                            THEME_PARENT_ID_COL, &this_parent,
+                                            -1);
+                        if (this_parent != NULL && strcmp (this_parent, CUSTOM_THEME_NAME) != 0) {
+                                g_free (this_parent);
+                                gtk_list_store_remove (GTK_LIST_STORE (theme_model), &iter);
+                                break;
+                        }
+                        g_free (this_parent);
+                } while (gtk_tree_model_iter_next (theme_model, &iter));
+
+                delete_custom_theme_dir ();
+
+                set_combox_for_theme_name (chooser, parent);
+        }
+
+        update_alert_model (chooser, alert_id);
+
+        g_free (theme);
+        g_free (parent);
+}
+
+static void
+on_alert_toggled (GtkCellRendererToggle *renderer,
+                  char                  *path_str,
+                  GvcSoundThemeChooser  *chooser)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreePath  *path;
+        gboolean      toggled;
+        char         *id;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        path = gtk_tree_path_new_from_string (path_str);
+        gtk_tree_model_get_iter (model, &iter, path);
+        gtk_tree_path_free (path);
+
+        id = NULL;
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            ALERT_ACTIVE_COL, &toggled,
+                            -1);
+
+        toggled ^= 1;
+        if (toggled) {
+                update_alert (chooser, id);
+        }
+
+        g_free (id);
+}
+
+static void
+play_preview_for_path (GvcSoundThemeChooser *chooser, GtkTreePath *path)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreeIter   theme_iter;
+        gchar        *id = NULL;
+        gchar        *parent_theme = NULL;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        if (gtk_tree_model_get_iter (model, &iter, path) == FALSE)
+                return;
+
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            -1);
+        if (id == NULL)
+                return;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &theme_iter)) {
+                GtkTreeModel *theme_model;
+                gchar        *theme_id = NULL;
+                gchar        *parent_id = NULL;
+
+                theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+                gtk_tree_model_get (theme_model, &theme_iter,
+                                    THEME_IDENTIFIER_COL, &theme_id,
+                                    THEME_PARENT_ID_COL, &parent_id, -1);
+                if (theme_id && strcmp (theme_id, CUSTOM_THEME_NAME) == 0)
+                        parent_theme = g_strdup (parent_id);
+
+                g_free (theme_id);
+                g_free (parent_id);
+        }
+
+        /* special case: for the default item on custom themes
+         * play the alert for the parent theme */
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                if (parent_theme != NULL) {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_CANBERRA_XDG_THEME_NAME, parent_theme,
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                } else {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                }
+        } else {
+                ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                        CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                        CA_PROP_MEDIA_FILENAME, id,
+                                        CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                        CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                        CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                        CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                        NULL);
+
+        }
+        g_free (parent_theme);
+        g_free (id);
+}
+
+static void
+on_treeview_row_activated (GtkTreeView          *treeview,
+                           GtkTreePath          *path,
+                           GtkTreeViewColumn    *column,
+                           GvcSoundThemeChooser *chooser)
+{
+        play_preview_for_path (chooser, path);
+}
+
+static void
+on_treeview_selection_changed (GtkTreeSelection     *selection,
+                               GvcSoundThemeChooser *chooser)
+{
+        GList        *paths;
+        GtkTreeModel *model;
+        GtkTreePath  *path;
+
+        if (chooser->priv->treeview == NULL)
+                return;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        paths = gtk_tree_selection_get_selected_rows (selection, &model);
+        if (paths == NULL)
+                return;
+
+        path = paths->data;
+        play_preview_for_path (chooser, path);
+
+        g_list_foreach (paths, (GFunc)gtk_tree_path_free, NULL);
+        g_list_free (paths);
+}
+
+static GtkWidget *
+create_alert_treeview (GvcSoundThemeChooser *chooser)
+{
+        GtkListStore         *store;
+        GtkWidget            *treeview;
+        GtkCellRenderer      *renderer;
+        GtkTreeViewColumn    *column;
+        GtkTreeSelection     *selection;
+
+        treeview = gtk_tree_view_new ();
+
+        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
+        g_signal_connect (G_OBJECT (treeview),
+                          "row-activated",
+                          G_CALLBACK (on_treeview_row_activated),
+                          chooser);
+
+        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+        gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+        g_signal_connect (G_OBJECT (selection),
+                          "changed",
+                          G_CALLBACK (on_treeview_selection_changed),
+                          chooser);
+
+        /* Setup the tree model, 3 columns:
+         * - display name
+         * - sound id
+         * - sound type
+         */
+        store = gtk_list_store_new (ALERT_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_BOOLEAN);
+
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           ALERT_IDENTIFIER_COL, DEFAULT_ALERT_ID,
+                                           ALERT_DISPLAY_COL, _("Default"),
+                                           ALERT_SOUND_TYPE_COL, _("From theme"),
+                                           ALERT_ACTIVE_COL, TRUE,
+                                           -1);
+
+        populate_model_from_dir (chooser, GTK_TREE_MODEL (store), SOUND_SET_DIR);
+
+        gtk_tree_view_set_model (GTK_TREE_VIEW (treeview),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_toggle_new ();
+        gtk_cell_renderer_toggle_set_radio (GTK_CELL_RENDERER_TOGGLE (renderer), TRUE);
+
+        column = gtk_tree_view_column_new_with_attributes (NULL,
+                                                           renderer,
+                                                           "active", ALERT_ACTIVE_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+        g_signal_connect (renderer,
+                          "toggled",
+                          G_CALLBACK (on_alert_toggled),
+                          chooser);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Name"),
+                                                           renderer,
+                                                           "text", ALERT_DISPLAY_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Type"),
+                                                           renderer,
+                                                           "text", ALERT_SOUND_TYPE_COL,
+                                                           NULL);
+
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        return treeview;
+}
+
+static int
+get_file_type (const char *sound_name,
+               char      **linked_name)
+{
+        char *name, *filename;
+
+        *linked_name = NULL;
+
+        name = g_strdup_printf ("%s.disabled", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_REGULAR) != FALSE) {
+                g_free (filename);
+                return SOUND_TYPE_OFF;
+        }
+        g_free (filename);
+
+        /* We only check for .ogg files because those are the
+         * only ones we create */
+        name = g_strdup_printf ("%s.ogg", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_SYMLINK) != FALSE) {
+                *linked_name = g_file_read_link (filename, NULL);
+                g_free (filename);
+                return SOUND_TYPE_CUSTOM;
+        }
+        g_free (filename);
+
+        return SOUND_TYPE_BUILTIN;
+}
+
+static void
+update_alerts_from_theme_name (GvcSoundThemeChooser *chooser,
+                               const gchar          *name)
+{
+        if (strcmp (name, CUSTOM_THEME_NAME) != 0) {
+                /* reset alert to default */
+                update_alert (chooser, DEFAULT_ALERT_ID);
+        } else {
+                int   sound_type;
+                char *linkname;
+
+                linkname = NULL;
+                sound_type = get_file_type ("bell-terminal", &linkname);
+                g_debug ("Found link: %s", linkname);
+                if (sound_type == SOUND_TYPE_CUSTOM) {
+                        update_alert (chooser, linkname);
+                }
+        }
+}
+
+static void
+update_theme (GvcSoundThemeChooser *chooser)
+{
+        char        *theme_name;
+        gboolean     events_enabled;
+        gboolean     feedback_enabled;
+
+        feedback_enabled = g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY);
+        set_input_feedback_enabled (chooser, feedback_enabled);
+
+        events_enabled = g_settings_get_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY);
+        if (events_enabled) {
+                theme_name = g_settings_get_string (chooser->priv->sound_settings, SOUND_THEME_KEY);
+        } else {
+                theme_name = g_strdup (NO_SOUNDS_THEME_NAME);
+        }
+
+        gtk_widget_set_sensitive (chooser->priv->selection_box, events_enabled);
+        gtk_widget_set_sensitive (chooser->priv->click_feedback_button, events_enabled);
+
+        set_combox_for_theme_name (chooser, theme_name);
+
+        update_alerts_from_theme_name (chooser, theme_name);
+
+        g_free (theme_name);
+}
+
+static void
+gvc_sound_theme_chooser_class_init (GvcSoundThemeChooserClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_sound_theme_chooser_dispose;
+}
+
+static void
+on_click_feedback_toggled (GtkToggleButton      *button,
+                           GvcSoundThemeChooser *chooser)
+{
+        gboolean enabled;
+
+        enabled = gtk_toggle_button_get_active (button);
+
+        g_settings_set_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY, enabled);
+}
+
+static void
+on_key_changed (GSettings            *settings,
+                gchar                *key,
+                GvcSoundThemeChooser *chooser)
+{
+        if (!strcmp (key, EVENT_SOUNDS_KEY) ||
+            !strcmp (key, SOUND_THEME_KEY) ||
+            !strcmp (key, INPUT_SOUNDS_KEY))
+                update_theme (chooser);
+}
+
+static void
+setup_list_size_constraint (GtkWidget *widget,
+                            GtkWidget *to_size)
+{
+        GtkRequisition req;
+        gint           sc_height;
+        int            max_height;
+
+        /* Constrain height to be the tree height up to a max */
+        gdk_window_get_geometry (gdk_screen_get_root_window (gtk_widget_get_screen (widget)),
+                                 NULL, NULL, NULL, &sc_height);
+
+        max_height = sc_height / 4;
+
+        // XXX this doesn't work
+        gtk_widget_get_preferred_size (to_size, NULL, &req);
+
+        gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (widget),
+                                                    MIN (req.height, max_height));
+}
+
+static void
+gvc_sound_theme_chooser_init (GvcSoundThemeChooser *chooser)
+{
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *scrolled_window;
+        gchar       *str;
+
+        chooser->priv = gvc_sound_theme_chooser_get_instance_private (chooser);
+
+        chooser->priv->theme_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->theme_box, FALSE, FALSE, 0);
+
+        label = gtk_label_new_with_mnemonic (_("Sound _theme:"));
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), label, FALSE, FALSE, 0);
+        chooser->priv->combo_box = gtk_combo_box_new ();
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), chooser->priv->combo_box, FALSE, FALSE, 6);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->combo_box);
+
+        chooser->priv->sound_settings = g_settings_new (KEY_SOUNDS_SCHEMA);
+
+        g_signal_connect (G_OBJECT (chooser->priv->sound_settings),
+                          "changed",
+                          G_CALLBACK (on_key_changed),
+                          chooser);
+
+        str = g_strdup_printf ("<b>%s</b>", _("C_hoose an alert sound:"));
+        chooser->priv->selection_box = box = gtk_frame_new (str);
+        g_free (str);
+
+        label = gtk_frame_get_label_widget (GTK_FRAME (box));
+        gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
+        gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+        gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
+
+        gtk_box_pack_start (GTK_BOX (chooser), box, TRUE, TRUE, 6);
+
+        chooser->priv->treeview = create_alert_treeview (chooser);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->treeview);
+
+        scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+        gtk_widget_set_hexpand (scrolled_window, TRUE);
+        gtk_widget_set_vexpand (scrolled_window, TRUE);
+        gtk_widget_set_margin_top (scrolled_window, 6);
+
+        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+                                        GTK_POLICY_NEVER,
+                                        GTK_POLICY_AUTOMATIC);
+        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
+                                             GTK_SHADOW_IN);
+
+        gtk_container_add (GTK_CONTAINER (scrolled_window), chooser->priv->treeview);
+        gtk_container_add (GTK_CONTAINER (box), scrolled_window);
+
+        chooser->priv->click_feedback_button = gtk_check_button_new_with_mnemonic (_("Enable _window and button sounds"));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY));
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->click_feedback_button,
+                            FALSE, FALSE, 0);
+
+        g_signal_connect (G_OBJECT (chooser->priv->click_feedback_button),
+                          "toggled",
+                          G_CALLBACK (on_click_feedback_toggled),
+                          chooser);
+
+        setup_theme_selector (chooser);
+        update_theme (chooser);
+
+        setup_list_size_constraint (scrolled_window, chooser->priv->treeview);
+}
+
+static void
+gvc_sound_theme_chooser_dispose (GObject *object)
+{
+        GvcSoundThemeChooser *chooser;
+
+        chooser = GVC_SOUND_THEME_CHOOSER (object);
+
+        g_clear_object (&chooser->priv->sound_settings);
+
+        G_OBJECT_CLASS (gvc_sound_theme_chooser_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_sound_theme_chooser_new (void)
+{
+        return g_object_new (GVC_TYPE_SOUND_THEME_CHOOSER,
+                                "spacing", 6,
+                                "orientation", GTK_ORIENTATION_VERTICAL,
+                                NULL);
+}
+
+
+
+ + + diff --git a/2020-04-21-011735-7455-cppcheck@e864ce9bb951_travis/2.html b/2020-04-21-011735-7455-cppcheck@e864ce9bb951_travis/2.html new file mode 100644 index 0000000..bacfabb --- /dev/null +++ b/2020-04-21-011735-7455-cppcheck@e864ce9bb951_travis/2.html @@ -0,0 +1,1110 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <canberra.h>
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-speaker-test.h"
+#include "gvc-utils.h"
+
+struct _GvcSpeakerTestPrivate
+{
+        GArray           *controls;
+        ca_context       *canberra;
+        MateMixerStream  *stream;
+};
+
+enum {
+        PROP_0,
+        PROP_STREAM,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_speaker_test_dispose    (GObject             *object);
+static void gvc_speaker_test_finalize   (GObject             *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSpeakerTest, gvc_speaker_test, GTK_TYPE_GRID)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+typedef struct {
+        MateMixerChannelPosition position;
+        guint left;
+        guint top;
+} TablePosition;
+
+static const TablePosition positions[] = {
+        /* Position, X, Y */
+        { MATE_MIXER_CHANNEL_FRONT_LEFT, 0, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_LEFT_CENTER, 1, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_CENTER, 2, 0, },
+        { MATE_MIXER_CHANNEL_MONO, 2, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT_CENTER, 3, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT, 4, 0, },
+        { MATE_MIXER_CHANNEL_SIDE_LEFT, 0, 1, },
+        { MATE_MIXER_CHANNEL_SIDE_RIGHT, 4, 1, },
+        { MATE_MIXER_CHANNEL_BACK_LEFT, 0, 2, },
+        { MATE_MIXER_CHANNEL_BACK_CENTER, 2, 2, },
+        { MATE_MIXER_CHANNEL_BACK_RIGHT, 4, 2, },
+        { MATE_MIXER_CHANNEL_LFE, 3, 2 }
+};
+
+MateMixerStream *
+gvc_speaker_test_get_stream (GvcSpeakerTest *test)
+{
+        g_return_val_if_fail (GVC_IS_SPEAKER_TEST (test), NULL);
+
+        return test->priv->stream;
+}
+
+static void
+gvc_speaker_test_set_stream (GvcSpeakerTest *test, MateMixerStream *stream)
+{
+        MateMixerStreamControl *control;
+        const gchar            *name;
+        guint                   i;
+
+        name = mate_mixer_stream_get_name (stream);
+        control = mate_mixer_stream_get_default_control (stream);
+
+        ca_context_change_device (test->priv->canberra, name);
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                gboolean has_position =
+                        mate_mixer_stream_control_has_channel_position (control, positions[i].position);
+
+                gtk_widget_set_visible (g_array_index (test->priv->controls, GtkWidget *, i),
+                                        has_position);
+        }
+
+        test->priv->stream = g_object_ref (stream);
+}
+
+static void
+gvc_speaker_test_set_property (GObject       *object,
+                               guint          prop_id,
+                               const GValue  *value,
+                               GParamSpec    *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                gvc_speaker_test_set_stream (self, g_value_get_object (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_get_property (GObject     *object,
+                               guint        prop_id,
+                               GValue      *value,
+                               GParamSpec  *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                g_value_set_object (value, self->priv->stream);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_class_init (GvcSpeakerTestClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose  = gvc_speaker_test_dispose;
+        object_class->finalize = gvc_speaker_test_finalize;
+        object_class->set_property = gvc_speaker_test_set_property;
+        object_class->get_property = gvc_speaker_test_get_property;
+
+        properties[PROP_STREAM] =
+                g_param_spec_object ("stream",
+                                     "Stream",
+                                     "MateMixer stream",
+                                     MATE_MIXER_TYPE_STREAM,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+}
+
+static const gchar *
+sound_name (MateMixerChannelPosition position)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return "audio-channel-front-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return "audio-channel-front-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return "audio-channel-front-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return "audio-channel-rear-left";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return "audio-channel-rear-right";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return "audio-channel-rear-center";
+        case MATE_MIXER_CHANNEL_LFE:
+                return "audio-channel-lfe";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return "audio-channel-side-left";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return "audio-channel-side-right";
+        default:
+                return NULL;
+        }
+}
+
+static const gchar *
+icon_name (MateMixerChannelPosition position, gboolean playing)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return playing
+                        ? "audio-speaker-left-testing"
+                        : "audio-speaker-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return playing
+                        ? "audio-speaker-right-testing"
+                        : "audio-speaker-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return playing
+                        ? "audio-speaker-center-testing"
+                        : "audio-speaker-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return playing
+                        ? "audio-speaker-left-back-testing"
+                        : "audio-speaker-left-back";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return playing
+                        ? "audio-speaker-right-back-testing"
+                        : "audio-speaker-right-back";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return playing
+                        ? "audio-speaker-center-back-testing"
+                        : "audio-speaker-center-back";
+        case MATE_MIXER_CHANNEL_LFE:
+                return playing
+                        ? "audio-subwoofer-testing"
+                        : "audio-subwoofer";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return playing
+                        ? "audio-speaker-left-side-testing"
+                        : "audio-speaker-left-side";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return playing
+                        ? "audio-speaker-right-side-testing"
+                        : "audio-speaker-right-side";
+        default:
+                return NULL;
+        }
+}
+
+static void
+update_button (GtkWidget *control)
+{
+        GtkWidget *button;
+        GtkWidget *image;
+        gboolean   playing;
+        MateMixerChannelPosition position;
+
+        button = g_object_get_data (G_OBJECT (control), "button");
+        image  = g_object_get_data (G_OBJECT (control), "image");
+
+        position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+        playing  = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        gtk_button_set_label (GTK_BUTTON (button), playing ? _("Stop") : _("Test"));
+
+        gtk_image_set_from_icon_name (GTK_IMAGE (image),
+                                      icon_name (position, playing),
+                                      GTK_ICON_SIZE_DIALOG);
+}
+
+static gboolean
+idle_cb (GtkWidget *control)
+{
+        if (control != NULL) {
+                /* This is called in the background thread, hence forward to main thread
+                 * via idle callback */
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+
+                update_button (control);
+        }
+        return FALSE;
+}
+
+static void
+finish_cb (ca_context *c, uint32_t id, int error_code, void *userdata)
+{
+        GtkWidget *control = (GtkWidget *) userdata;
+
+        if (error_code == CA_ERROR_DESTROYED || control == NULL)
+                return;
+
+        g_idle_add ((GSourceFunc) idle_cb, control);
+}
+
+static void
+on_test_button_clicked (GtkButton *button, GtkWidget *control)
+{
+        gboolean    playing;
+        ca_context *canberra;
+
+        canberra = g_object_get_data (G_OBJECT (control), "canberra");
+
+        ca_context_cancel (canberra, 1);
+
+        playing = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        if (playing) {
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        } else {
+                MateMixerChannelPosition position;
+                const gchar *name;
+                ca_proplist *proplist;
+
+                position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+
+                ca_proplist_create (&proplist);
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_ROLE, "test");
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_NAME,
+                                  gvc_channel_position_to_pretty_string (position));
+                ca_proplist_sets (proplist,
+                                  CA_PROP_CANBERRA_FORCE_CHANNEL,
+                                  gvc_channel_position_to_pulse_string (position));
+
+                ca_proplist_sets (proplist, CA_PROP_CANBERRA_ENABLE, "1");
+
+                name = sound_name (position);
+                if (name != NULL) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, name);
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, "audio-test-signal");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets(proplist, CA_PROP_EVENT_ID, "bell-window-system");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (playing));
+        }
+
+        update_button (control);
+}
+
+static GtkWidget *
+create_control (ca_context *canberra, MateMixerChannelPosition position)
+{
+        GtkWidget   *control;
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *image;
+        GtkWidget   *test_button;
+        const gchar *name;
+
+        control = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+        box     = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        g_object_set_data (G_OBJECT (control), "position", GINT_TO_POINTER (position));
+        g_object_set_data (G_OBJECT (control), "canberra", canberra);
+
+        name = icon_name (position, FALSE);
+        if (name == NULL)
+                name = "audio-volume-medium";
+
+        image = gtk_image_new_from_icon_name (name, GTK_ICON_SIZE_DIALOG);
+        g_object_set_data (G_OBJECT (control), "image", image);
+        gtk_box_pack_start (GTK_BOX (control), image, FALSE, FALSE, 0);
+
+        label = gtk_label_new (gvc_channel_position_to_pretty_string (position));
+        gtk_box_pack_start (GTK_BOX (control), label, FALSE, FALSE, 0);
+
+        test_button = gtk_button_new_with_label (_("Test"));
+        g_signal_connect (G_OBJECT (test_button),
+                          "clicked",
+                          G_CALLBACK (on_test_button_clicked),
+                          control);
+
+        g_object_set_data (G_OBJECT (control), "button", test_button);
+
+        gtk_box_pack_start (GTK_BOX (box), test_button, TRUE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (control), box, FALSE, FALSE, 0);
+
+        gtk_widget_show_all (control);
+
+        return control;
+}
+
+static void
+create_controls (GvcSpeakerTest *test)
+{
+        guint i;
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                GtkWidget *control = create_control (test->priv->canberra, positions[i].position);
+
+                gtk_grid_attach (GTK_GRID (test),
+                                 control,
+                                 positions[i].left,
+                                 positions[i].top,
+                                 1, 1);
+                g_array_insert_val (test->priv->controls, i, control);
+        }
+}
+
+static void
+gvc_speaker_test_init (GvcSpeakerTest *test)
+{
+        GtkWidget *face;
+
+        test->priv = gvc_speaker_test_get_instance_private (test);
+
+        gtk_container_set_border_width (GTK_CONTAINER (test), 12);
+
+        face = gtk_image_new_from_icon_name ("face-smile", GTK_ICON_SIZE_DIALOG);
+
+        gtk_grid_attach (GTK_GRID (test),
+                         face,
+                         1, 1,
+                         3, 1);
+
+
+        gtk_grid_set_baseline_row (GTK_GRID (test), 1);
+        gtk_widget_show (face);
+
+        ca_context_create (&test->priv->canberra);
+
+        /* The test sounds are played for a single channel, set up using the
+         * FORCE_CHANNEL property of libcanberra; this property is only supported
+         * in the PulseAudio backend, so avoid other backends completely */
+        ca_context_set_driver (test->priv->canberra, "pulse");
+
+        ca_context_change_props (test->priv->canberra,
+                                 CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+                                 CA_PROP_APPLICATION_NAME, _("Volume Control"),
+                                 CA_PROP_APPLICATION_VERSION, VERSION,
+                                 CA_PROP_APPLICATION_ICON_NAME, "multimedia-volume-control",
+                                 NULL);
+
+        test->priv->controls = g_array_new (FALSE, FALSE, sizeof (GtkWidget *));
+
+        create_controls (test);
+}
+
+static void
+gvc_speaker_test_dispose (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        g_clear_object (&test->priv->stream);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->dispose (object);
+}
+
+static void
+gvc_speaker_test_finalize (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        ca_context_destroy (test->priv->canberra);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->finalize (object);
+}
+
+GtkWidget *
+gvc_speaker_test_new (MateMixerStream *stream)
+{
+        GObject *test;
+
+        g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL);
+
+        test = g_object_new (GVC_TYPE_SPEAKER_TEST,
+                             "row-spacing", 6,
+                             "column-spacing", 6,
+                             "row-homogeneous", TRUE,
+                             "column-homogeneous", TRUE,
+                             "stream", stream,
+                             NULL);
+
+        return GTK_WIDGET (test);
+}
+
+
+
+ + + diff --git a/2020-04-21-011735-7455-cppcheck@e864ce9bb951_travis/index.html b/2020-04-21-011735-7455-cppcheck@e864ce9bb951_travis/index.html new file mode 100644 index 0000000..59baeb0 --- /dev/null +++ b/2020-04-21-011735-7455-cppcheck@e864ce9bb951_travis/index.html @@ -0,0 +1,108 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
mate-volume-control/gvc-combo-box.c
70unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
mate-volume-control/gvc-sound-theme-chooser.c
735ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
746ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
758ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
mate-volume-control/gvc-speaker-test.c
53unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+ + + diff --git a/2020-04-21-011735-7455-cppcheck@e864ce9bb951_travis/stats.html b/2020-04-21-011735-7455-cppcheck@e864ce9bb951_travis/stats.html new file mode 100644 index 0000000..3fb6add --- /dev/null +++ b/2020-04-21-011735-7455-cppcheck@e864ce9bb951_travis/stats.html @@ -0,0 +1,93 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+

Top 10 files for error severity, total findings: 2
+   1  mate-volume-control/gvc-speaker-test.c
+   1  mate-volume-control/gvc-combo-box.c
+

+

Top 10 files for information severity, total findings: 3
+   3  mate-volume-control/gvc-sound-theme-chooser.c
+

+ +
+ + + diff --git a/2020-04-21-011735-7455-cppcheck@e864ce9bb951_travis/style.css b/2020-04-21-011735-7455-cppcheck@e864ce9bb951_travis/style.css new file mode 100644 index 0000000..c39571c --- /dev/null +++ b/2020-04-21-011735-7455-cppcheck@e864ce9bb951_travis/style.css @@ -0,0 +1,149 @@ + +body { + font: 13px Arial, Verdana, Sans-Serif; + margin: 0; + width: auto; +} + +h1 { + margin: 10px; +} + +#footer > p { + margin: 4px; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + border: 1px dotted black; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #B6B6B4; +} + +.inconclusive2 { + background-color: #B6B6B4; + border: 1px dotted black; + display: inline-block; + margin-left: 4px; +} + +div.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +div.verbose div.content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid black; + background-color: #FFFFCC; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +#header { + border-bottom: thin solid #aaa; +} + +#menu { + float: left; + margin-top: 5px; + text-align: left; + width: 150px; + /*height: 75%;*/ + position: fixed; + overflow: auto; + z-index: 1; +} + +#menu_index { + float: left; + margin-top: 5px; + padding-left: 5px; + text-align: left; + width: 300px; + /*height: 75%;*/ + position: fixed; + overflow: auto; + z-index: 1; +} + +#menu > a { + display: block; + margin-left: 10px; + font: 12px; + z-index: 1; +} + +#filename { + margin-left: 10px; + font: 12px; + z-index: 1; +} + +.highlighttable { + background-color:white; + z-index: 10; + position: relative; + margin: -10 px; +} + +#content { + background-color: white; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + float: left; + margin: 5px; + margin-left: 10px; + padding: 0 10px 10px 10px; + width: 80%; + padding-left: 150px; +} + +#content_index { + background-color: white; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + float: left; + margin: 5px; + margin-left: 10px; + padding: 0 10px 10px 10px; + width: 80%; + padding-left: 300px; +} + +.linenos { + border-right: thin solid #aaa; + color: lightgray; + padding-right: 6px; +} + +#footer { + border-top: thin solid #aaa; + clear: both; + font-size: 90%; + margin-top: 5px; +} + +#footer ul { + list-style-type: none; + padding-left: 0; +} diff --git a/2020-04-21-012206-8805-cppcheck@d4487123b370_travis/0.html b/2020-04-21-012206-8805-cppcheck@d4487123b370_travis/0.html new file mode 100644 index 0000000..e262ed0 --- /dev/null +++ b/2020-04-21-012206-8805-cppcheck@d4487123b370_travis/0.html @@ -0,0 +1,1038 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-combo-box.h"
+
+struct _GvcComboBoxPrivate
+{
+        GtkWidget       *drop_box;
+        GtkWidget       *start_box;
+        GtkWidget       *end_box;
+        GtkWidget       *label;
+        GtkWidget       *button;
+        GtkTreeModel    *model;
+        GtkWidget       *combobox;
+        MateMixerSwitch *swtch;
+};
+
+enum {
+        COL_NAME,
+        COL_HUMAN_NAME,
+        NUM_COLS
+};
+
+enum {
+        CHANGING,
+        BUTTON_CLICKED,
+        LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+enum {
+        PROP_0,
+        PROP_SWITCH,
+        PROP_LABEL,
+        PROP_SHOW_BUTTON,
+        PROP_BUTTON_LABEL,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_combo_box_dispose    (GObject          *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcComboBox, gvc_combo_box, GTK_TYPE_BOX)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+MateMixerSwitch *
+gvc_combo_box_get_switch (GvcComboBox *combobox)
+{
+        g_return_val_if_fail (GVC_IS_COMBO_BOX (combobox), NULL);
+
+        return combobox->priv->swtch;
+}
+
+void
+gvc_combo_box_set_size_group (GvcComboBox  *combobox,
+                              GtkSizeGroup *group,
+                              gboolean      symmetric)
+{
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (GTK_IS_SIZE_GROUP (group));
+
+        if (group != NULL) {
+                gtk_size_group_add_widget (group, combobox->priv->start_box);
+                if (symmetric == TRUE)
+                        gtk_size_group_add_widget (group, combobox->priv->end_box);
+        }
+        gtk_widget_queue_draw (GTK_WIDGET (combobox));
+}
+
+static void
+on_switch_active_option_notify (MateMixerSwitch *swtch,
+                                GParamSpec      *pspec,
+                                GvcComboBox     *combobox)
+{
+        GtkTreeIter            iter;
+        MateMixerSwitchOption *active;
+        gboolean               cont;
+        const gchar           *name;
+
+        active = mate_mixer_switch_get_active_option (swtch);
+        if (G_UNLIKELY (active == NULL)) {
+                g_warn_if_reached ();
+                return;
+        }
+
+        /* Select the newly activated switch option in the combo box */
+        name = mate_mixer_switch_option_get_name (active);
+        cont = gtk_tree_model_get_iter_first (combobox->priv->model, &iter);
+        while (cont == TRUE) {
+                gchar *current;
+
+                gtk_tree_model_get (combobox->priv->model, &iter,
+                                    COL_NAME, &current,
+                                    -1);
+                if (g_strcmp0 (name, current) == 0) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox), &iter);
+                        g_free (current);
+                        return;
+                }
+                g_free (current);
+
+                cont = gtk_tree_model_iter_next (combobox->priv->model, &iter);
+        }
+        g_warning ("Could not find switch option '%s' in combo box", name);
+}
+
+static void
+gvc_combo_box_set_switch (GvcComboBox *combobox, MateMixerSwitch *swtch)
+{
+        MateMixerSwitchOption *active;
+        const GList           *options;
+
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (MATE_MIXER_IS_SWITCH (swtch));
+
+        combobox->priv->swtch = g_object_ref (swtch);
+
+        active  = mate_mixer_switch_get_active_option (swtch);
+        options = mate_mixer_switch_list_options (swtch);
+        while (options != NULL) {
+                GtkTreeIter            iter;
+                MateMixerSwitchOption *option = MATE_MIXER_SWITCH_OPTION (options->data);
+
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (combobox->priv->model),
+                                                   &iter,
+                                                   G_MAXINT,
+                                                   COL_NAME,
+                                                   mate_mixer_switch_option_get_name (option),
+                                                   COL_HUMAN_NAME,
+                                                   mate_mixer_switch_option_get_label (option),
+                                                   -1);
+
+                /* Select the currently active option of the switch */
+                if (option == active) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox),
+                                                       &iter);
+                }
+                options = options->next;
+        }
+
+        g_signal_connect (G_OBJECT (swtch),
+                          "notify::active-option",
+                          G_CALLBACK (on_switch_active_option_notify),
+                          combobox);
+}
+
+static void
+gvc_combo_box_set_property (GObject       *object,
+                            guint          prop_id,
+                            const GValue  *value,
+                            GParamSpec    *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                gvc_combo_box_set_switch (self, g_value_get_object (value));
+                break;
+        case PROP_LABEL:
+                gtk_label_set_text_with_mnemonic (GTK_LABEL (self->priv->label), g_value_get_string (value));
+                break;
+        case PROP_BUTTON_LABEL:
+                gtk_button_set_label (GTK_BUTTON (self->priv->button), g_value_get_string (value));
+                break;
+        case PROP_SHOW_BUTTON:
+                gtk_widget_set_visible (self->priv->button, g_value_get_boolean (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_get_property (GObject     *object,
+                            guint        prop_id,
+                            GValue      *value,
+                            GParamSpec  *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                g_value_set_object (value, self->priv->swtch);
+                break;
+        case PROP_LABEL:
+                g_value_set_string (value, gtk_label_get_text (GTK_LABEL (self->priv->label)));
+                break;
+        case PROP_BUTTON_LABEL:
+                g_value_set_string (value, gtk_button_get_label (GTK_BUTTON (self->priv->button)));
+                break;
+        case PROP_SHOW_BUTTON:
+                g_value_set_boolean (value, gtk_widget_get_visible (self->priv->button));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_class_init (GvcComboBoxClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_combo_box_dispose;
+        object_class->set_property = gvc_combo_box_set_property;
+        object_class->get_property = gvc_combo_box_get_property;
+
+        properties[PROP_SWITCH] =
+                g_param_spec_object ("switch",
+                                     "switch",
+                                     "The MateMixerSwitch",
+                                     MATE_MIXER_TYPE_SWITCH,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_LABEL] =
+                g_param_spec_string ("label",
+                                     "label",
+                                     "The combo box label",
+                                     _("_Profile:"),
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_SHOW_BUTTON] =
+                g_param_spec_boolean ("show-button",
+                                      "show-button",
+                                      "Whether to show the button",
+                                      FALSE,
+                                      G_PARAM_READWRITE |
+                                      G_PARAM_CONSTRUCT |
+                                      G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_BUTTON_LABEL] =
+                g_param_spec_string ("button-label",
+                                     "button-label",
+                                     "The button's label",
+                                     "",
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+
+        signals[CHANGING] =
+                g_signal_new ("changing",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, changing),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__OBJECT,
+                              G_TYPE_NONE,
+                              1,
+                              MATE_MIXER_TYPE_SWITCH_OPTION);
+
+        signals[BUTTON_CLICKED] =
+                g_signal_new ("button-clicked",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, button_clicked),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
+}
+
+static void
+on_combo_box_changed (GtkComboBox *widget, GvcComboBox *combobox)
+{
+        GtkTreeIter            iter;
+        gchar                 *name;
+        MateMixerSwitchOption *option;
+
+        if (G_UNLIKELY (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter) == FALSE))
+                return;
+
+        gtk_tree_model_get (combobox->priv->model, &iter,
+                            COL_NAME, &name,
+                            -1);
+
+        option = mate_mixer_switch_get_option (combobox->priv->swtch, name);
+        if (G_UNLIKELY (option == NULL)) {
+                g_warn_if_reached ();
+                g_free (name);
+                return;
+        }
+
+        /* Inform that we are about to change the active option of the switch */
+        g_signal_emit (combobox, signals[CHANGING], 0, option);
+
+        mate_mixer_switch_set_active_option (combobox->priv->swtch, option);
+        g_free (name);
+}
+
+static void
+on_combo_box_button_clicked (GtkButton *button, GvcComboBox *combobox)
+{
+        /* The meaning of the button is defined by the owner, so only notify
+         * when it is clicked on */
+        g_signal_emit (combobox, signals[BUTTON_CLICKED], 0);
+}
+
+static void
+gvc_combo_box_init (GvcComboBox *combobox)
+{
+        GtkWidget       *frame;
+        GtkCellRenderer *renderer;
+
+        frame = gtk_frame_new (NULL);
+        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
+
+        combobox->priv = gvc_combo_box_get_instance_private (combobox);
+
+        combobox->priv->model = GTK_TREE_MODEL (gtk_list_store_new (NUM_COLS,
+                                                                    G_TYPE_STRING,
+                                                                    G_TYPE_STRING));
+
+        combobox->priv->combobox = gtk_combo_box_new_with_model (combobox->priv->model);
+
+        combobox->priv->label = gtk_label_new (NULL);
+
+        gtk_label_set_xalign (GTK_LABEL (combobox->priv->label), 0.0);
+        gtk_label_set_yalign (GTK_LABEL (combobox->priv->label), 0.5);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (combobox->priv->label),
+                                       combobox->priv->combobox);
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                    renderer,
+                                    FALSE);
+        gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                       renderer,
+                                       "text",
+                                       COL_HUMAN_NAME);
+
+        combobox->priv->drop_box  = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->start_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->end_box   = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+        /* Make sure the combo box does not get too long on long profile names */
+        g_object_set (G_OBJECT (renderer),
+                      "ellipsize",
+                      PANGO_ELLIPSIZE_END,
+                      NULL);
+
+        gtk_combo_box_set_popup_fixed_width (GTK_COMBO_BOX (combobox->priv->combobox), FALSE);
+
+        gtk_box_pack_start (GTK_BOX (combobox),
+                            frame,
+                            TRUE, TRUE, 0);
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->start_box,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->start_box),
+                            combobox->priv->label,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->combobox,
+                            TRUE, TRUE, 0);
+
+        combobox->priv->button = gtk_button_new_with_label ("");
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->button,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->end_box,
+                            FALSE, FALSE, 0);
+
+        gtk_container_add (GTK_CONTAINER (frame), combobox->priv->drop_box);
+
+        g_signal_connect (G_OBJECT (combobox->priv->combobox),
+                          "changed",
+                          G_CALLBACK (on_combo_box_changed),
+                          combobox);
+        g_signal_connect (G_OBJECT (combobox->priv->button),
+                          "clicked",
+                          G_CALLBACK (on_combo_box_button_clicked),
+                          combobox);
+
+        gtk_widget_set_no_show_all (combobox->priv->button, TRUE);
+        gtk_widget_show_all (frame);
+}
+
+static void
+gvc_combo_box_dispose (GObject *object)
+{
+        GvcComboBox *combobox;
+
+        combobox = GVC_COMBO_BOX (object);
+
+        if (G_LIKELY (combobox->priv->swtch != NULL)) {
+                g_signal_handlers_disconnect_by_func (G_OBJECT (combobox->priv->swtch),
+                                                      G_CALLBACK (on_switch_active_option_notify),
+                                                      combobox);
+                g_clear_object (&combobox->priv->swtch);
+        }
+
+        g_clear_object (&combobox->priv->model);
+
+        G_OBJECT_CLASS (gvc_combo_box_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_combo_box_new (MateMixerSwitch *swtch, const gchar *label)
+{
+        return g_object_new (GVC_TYPE_COMBO_BOX,
+                             "switch", swtch,
+                             "label", label,
+                             "orientation", GTK_ORIENTATION_HORIZONTAL,
+                             NULL);
+}
+
+
+
+ + + diff --git a/2020-04-21-012206-8805-cppcheck@d4487123b370_travis/1.html b/2020-04-21-012206-8805-cppcheck@d4487123b370_travis/1.html new file mode 100644 index 0000000..67179f2 --- /dev/null +++ b/2020-04-21-012206-8805-cppcheck@d4487123b370_travis/1.html @@ -0,0 +1,2368 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
+ * Copyright (C) 2008 William Jon McCann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <utime.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+#include <canberra-gtk.h>
+#include <libxml/tree.h>
+
+#include "gvc-sound-theme-chooser.h"
+#include "sound-theme-file-utils.h"
+
+struct GvcSoundThemeChooserPrivate
+{
+        GtkWidget *combo_box;
+        GtkWidget *treeview;
+        GtkWidget *theme_box;
+        GtkWidget *selection_box;
+        GtkWidget *click_feedback_button;
+        GSettings *sound_settings;
+};
+
+static void     gvc_sound_theme_chooser_dispose   (GObject            *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSoundThemeChooser, gvc_sound_theme_chooser, GTK_TYPE_BOX)
+
+#define KEY_SOUNDS_SCHEMA          "org.mate.sound"
+#define EVENT_SOUNDS_KEY           "event-sounds"
+#define INPUT_SOUNDS_KEY           "input-feedback-sounds"
+#define SOUND_THEME_KEY            "theme-name"
+
+#define DEFAULT_ALERT_ID        "__default"
+#define CUSTOM_THEME_NAME       "__custom"
+#define NO_SOUNDS_THEME_NAME    "__no_sounds"
+
+enum {
+        THEME_DISPLAY_COL,
+        THEME_IDENTIFIER_COL,
+        THEME_PARENT_ID_COL,
+        THEME_NUM_COLS
+};
+
+enum {
+        ALERT_DISPLAY_COL,
+        ALERT_IDENTIFIER_COL,
+        ALERT_SOUND_TYPE_COL,
+        ALERT_ACTIVE_COL,
+        ALERT_NUM_COLS
+};
+
+enum {
+        SOUND_TYPE_UNSET,
+        SOUND_TYPE_OFF,
+        SOUND_TYPE_DEFAULT_FROM_THEME,
+        SOUND_TYPE_BUILTIN,
+        SOUND_TYPE_CUSTOM
+};
+
+static void
+on_combobox_changed (GtkComboBox          *widget,
+                     GvcSoundThemeChooser *chooser)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        char         *theme_name;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &theme_name, -1);
+
+        g_assert (theme_name != NULL);
+
+        /* It is necessary to update the theme name before any other setting as
+         * the "changed" notification will reload the contents of the widget */
+        g_settings_set_string (chooser->priv->sound_settings, SOUND_THEME_KEY, theme_name);
+
+        /* special case for no sounds */
+        if (strcmp (theme_name, NO_SOUNDS_THEME_NAME) == 0) {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, FALSE);
+                return;
+        } else {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, TRUE);
+        }
+
+        g_free (theme_name);
+
+        /* FIXME: reset alert model */
+}
+
+static char *
+load_index_theme_name (const char *index,
+                       char      **parent)
+{
+        GKeyFile *file;
+        char *indexname = NULL;
+        gboolean hidden;
+
+        file = g_key_file_new ();
+        if (g_key_file_load_from_file (file, index, G_KEY_FILE_KEEP_TRANSLATIONS, NULL) == FALSE) {
+                g_key_file_free (file);
+                return NULL;
+        }
+        /* Don't add hidden themes to the list */
+        hidden = g_key_file_get_boolean (file, "Sound Theme", "Hidden", NULL);
+        if (!hidden) {
+                indexname = g_key_file_get_locale_string (file,
+                                                          "Sound Theme",
+                                                          "Name",
+                                                          NULL,
+                                                          NULL);
+
+                /* Save the parent theme, if there's one */
+                if (parent != NULL) {
+                        *parent = g_key_file_get_string (file,
+                                                         "Sound Theme",
+                                                         "Inherits",
+                                                         NULL);
+                }
+        }
+
+        g_key_file_free (file);
+        return indexname;
+}
+
+static void
+sound_theme_in_dir (GHashTable *hash,
+                    const char *dir)
+{
+        GDir *d;
+        const char *name;
+
+        d = g_dir_open (dir, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *dirname, *index, *indexname;
+
+                /* Look for directories */
+                dirname = g_build_filename (dir, name, NULL);
+                if (g_file_test (dirname, G_FILE_TEST_IS_DIR) == FALSE) {
+                        g_free (dirname);
+                        continue;
+                }
+
+                /* Look for index files */
+                index = g_build_filename (dirname, "index.theme", NULL);
+                g_free (dirname);
+
+                /* Check the name of the theme in the index.theme file */
+                indexname = load_index_theme_name (index, NULL);
+                g_free (index);
+                if (indexname == NULL) {
+                        continue;
+                }
+
+                g_hash_table_insert (hash, g_strdup (name), indexname);
+        }
+
+        g_dir_close (d);
+}
+
+static void
+add_theme_to_store (const char   *key,
+                    const char   *value,
+                    GtkListStore *store)
+{
+        char *parent;
+
+        parent = NULL;
+
+        /* Get the parent, if we're checking the custom theme */
+        if (strcmp (key, CUSTOM_THEME_NAME) == 0) {
+                char *name, *path;
+
+                path = custom_theme_dir_path ("index.theme");
+                name = load_index_theme_name (path, &parent);
+                g_free (name);
+                g_free (path);
+        }
+        gtk_list_store_insert_with_values (store, NULL, G_MAXINT,
+                                           THEME_DISPLAY_COL, value,
+                                           THEME_IDENTIFIER_COL, key,
+                                           THEME_PARENT_ID_COL, parent,
+                                           -1);
+        g_free (parent);
+}
+
+static void
+set_combox_for_theme_name (GvcSoundThemeChooser *chooser,
+                           const char           *name)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        gboolean      found;
+
+        /* If the name is empty, use "freedesktop" */
+        if (name == NULL || *name == '\0') {
+                name = "freedesktop";
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+        if (gtk_tree_model_get_iter_first (model, &iter) == FALSE) {
+                return;
+        }
+
+        do {
+                char *value;
+
+                gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &value, -1);
+                found = (value != NULL && strcmp (value, name) == 0);
+                g_free (value);
+
+        } while (!found && gtk_tree_model_iter_next (model, &iter));
+
+        /* When we can't find the theme we need to set, try to set the default
+         * one "freedesktop" */
+        if (found) {
+                gtk_combo_box_set_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter);
+        } else if (strcmp (name, "freedesktop") != 0) {
+                g_debug ("not found, falling back to fdo");
+                set_combox_for_theme_name (chooser, "freedesktop");
+        }
+}
+
+static void
+set_input_feedback_enabled (GvcSoundThemeChooser *chooser,
+                            gboolean              enabled)
+{
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      enabled);
+}
+
+static void
+setup_theme_selector (GvcSoundThemeChooser *chooser)
+{
+        GHashTable           *hash;
+        GtkListStore         *store;
+        GtkCellRenderer      *renderer;
+        const char * const   *data_dirs;
+        const char           *data_dir;
+        char                 *dir;
+        guint                 i;
+
+        /* Add the theme names and their display name to a hash table,
+         * makes it easy to avoid duplicate themes */
+        hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+        data_dirs = g_get_system_data_dirs ();
+        for (i = 0; data_dirs[i] != NULL; i++) {
+                dir = g_build_filename (data_dirs[i], "sounds", NULL);
+                sound_theme_in_dir (hash, dir);
+                g_free (dir);
+        }
+
+        data_dir = g_get_user_data_dir ();
+        dir = g_build_filename (data_dir, "sounds", NULL);
+        sound_theme_in_dir (hash, dir);
+        g_free (dir);
+
+        /* If there isn't at least one theme, make everything
+         * insensitive, LAME! */
+        if (g_hash_table_size (hash) == 0) {
+                gtk_widget_set_sensitive (GTK_WIDGET (chooser), FALSE);
+                g_warning ("Bad setup, install the freedesktop sound theme");
+                g_hash_table_destroy (hash);
+                return;
+        }
+
+        /* Setup the tree model, 3 columns:
+         * - internal theme name/directory
+         * - display theme name
+         * - the internal id for the parent theme, used for the custom theme */
+        store = gtk_list_store_new (THEME_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING);
+
+        /* Add the themes to a combobox */
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           THEME_DISPLAY_COL, _("No sounds"),
+                                           THEME_IDENTIFIER_COL, "__no_sounds",
+                                           THEME_PARENT_ID_COL, NULL,
+                                           -1);
+        g_hash_table_foreach (hash, (GHFunc) add_theme_to_store, store);
+        g_hash_table_destroy (hash);
+
+        /* Set the display */
+        gtk_combo_box_set_model (GTK_COMBO_BOX (chooser->priv->combo_box),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                    renderer,
+                                    TRUE);
+        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                        renderer,
+                                        "text", THEME_DISPLAY_COL,
+                                        NULL);
+
+        g_signal_connect (G_OBJECT (chooser->priv->combo_box),
+                          "changed",
+                          G_CALLBACK (on_combobox_changed),
+                          chooser);
+}
+
+#define GVC_SOUND_SOUND    (xmlChar *) "sound"
+#define GVC_SOUND_NAME     (xmlChar *) "name"
+#define GVC_SOUND_FILENAME (xmlChar *) "filename"
+
+/* Adapted from yelp-toc-pager.c */
+static xmlChar *
+xml_get_and_trim_names (xmlNodePtr node)
+{
+        xmlNodePtr cur;
+        xmlChar *keep_lang = NULL;
+        xmlChar *value;
+        int j, keep_pri = INT_MAX;
+
+        const gchar * const * langs = g_get_language_names ();
+
+        value = NULL;
+
+        for (cur = node->children; cur; cur = cur->next) {
+                if (! xmlStrcmp (cur->name, GVC_SOUND_NAME)) {
+                        xmlChar *cur_lang = NULL;
+                        int cur_pri = INT_MAX;
+
+                        cur_lang = xmlNodeGetLang (cur);
+
+                        if (cur_lang) {
+                                for (j = 0; langs[j]; j++) {
+                                        if (g_str_equal (cur_lang, langs[j])) {
+                                                cur_pri = j;
+                                                break;
+                                        }
+                                }
+                        } else {
+                                cur_pri = INT_MAX - 1;
+                        }
+
+                        if (cur_pri <= keep_pri) {
+                                if (keep_lang)
+                                        xmlFree (keep_lang);
+                                if (value)
+                                        xmlFree (value);
+
+                                value = xmlNodeGetContent (cur);
+
+                                keep_lang = cur_lang;
+                                keep_pri = cur_pri;
+                        } else {
+                                if (cur_lang)
+                                        xmlFree (cur_lang);
+                        }
+                }
+        }
+
+        /* Delete all GVC_SOUND_NAME nodes */
+        cur = node->children;
+        while (cur) {
+                xmlNodePtr this = cur;
+                cur = cur->next;
+                if (! xmlStrcmp (this->name, GVC_SOUND_NAME)) {
+                        xmlUnlinkNode (this);
+                        xmlFreeNode (this);
+                }
+        }
+
+        return value;
+}
+
+static void
+populate_model_from_node (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          xmlNodePtr            node)
+{
+        xmlNodePtr child;
+        xmlChar   *filename;
+        xmlChar   *name;
+
+        filename = NULL;
+        name = xml_get_and_trim_names (node);
+        for (child = node->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+
+                if (xmlStrcmp (child->name, GVC_SOUND_FILENAME) == 0) {
+                        filename = xmlNodeGetContent (child);
+                } else if (xmlStrcmp (child->name, GVC_SOUND_NAME) == 0) {
+                        /* EH? should have been trimmed */
+                }
+        }
+
+        if (filename != NULL && name != NULL) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   ALERT_IDENTIFIER_COL, filename,
+                                                   ALERT_DISPLAY_COL, name,
+                                                   ALERT_SOUND_TYPE_COL, _("Built-in"),
+                                                   ALERT_ACTIVE_COL, FALSE,
+                                                   -1);
+        }
+
+        xmlFree (filename);
+        xmlFree (name);
+}
+
+static void
+populate_model_from_file (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          const char           *filename)
+{
+        xmlDocPtr  doc;
+        xmlNodePtr root;
+        xmlNodePtr child;
+        gboolean   exists;
+
+        exists = g_file_test (filename, G_FILE_TEST_EXISTS);
+        if (! exists) {
+                return;
+        }
+
+        doc = xmlParseFile (filename);
+        if (doc == NULL) {
+                return;
+        }
+
+        root = xmlDocGetRootElement (doc);
+
+        for (child = root->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+                if (xmlStrcmp (child->name, GVC_SOUND_SOUND) != 0) {
+                        continue;
+                }
+
+                populate_model_from_node (chooser, model, child);
+        }
+
+        xmlFreeDoc (doc);
+}
+
+static void
+populate_model_from_dir (GvcSoundThemeChooser *chooser,
+                         GtkTreeModel         *model,
+                         const char           *dirname)
+{
+        GDir       *d;
+        const char *name;
+
+        d = g_dir_open (dirname, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *path;
+
+                if (! g_str_has_suffix (name, ".xml")) {
+                        continue;
+                }
+
+                path = g_build_filename (dirname, name, NULL);
+                populate_model_from_file (chooser, model, path);
+                g_free (path);
+        }
+
+        g_dir_close (d);
+}
+
+static gboolean
+save_alert_sounds (GvcSoundThemeChooser  *chooser,
+                   const char            *id)
+{
+        const char *sounds[3] = { "bell-terminal", "bell-window-system", NULL };
+        char *path;
+
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+        } else {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+                add_custom_file (sounds, id);
+        }
+
+        /* And poke the directory so the theme gets updated */
+        path = custom_theme_dir_path (NULL);
+        if (utime (path, NULL) != 0) {
+                g_warning ("Failed to update mtime for directory '%s': %s",
+                           path, g_strerror (errno));
+        }
+        g_free (path);
+
+        return FALSE;
+}
+
+
+static void
+update_alert_model (GvcSoundThemeChooser  *chooser,
+                    const char            *id)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        gtk_tree_model_get_iter_first (model, &iter);
+        do {
+                gboolean toggled;
+                char    *this_id;
+
+                gtk_tree_model_get (model, &iter,
+                                    ALERT_IDENTIFIER_COL, &this_id,
+                                    -1);
+
+                if (strcmp (this_id, id) == 0) {
+                        toggled = TRUE;
+                } else {
+                        toggled = FALSE;
+                }
+                g_free (this_id);
+
+                gtk_list_store_set (GTK_LIST_STORE (model),
+                                    &iter,
+                                    ALERT_ACTIVE_COL, toggled,
+                                    -1);
+        } while (gtk_tree_model_iter_next (model, &iter));
+}
+
+static void
+update_alert (GvcSoundThemeChooser *chooser,
+              const char           *alert_id)
+{
+        GtkTreeModel *theme_model;
+        GtkTreeIter   iter;
+        char         *theme;
+        char         *parent;
+        gboolean      is_custom;
+        gboolean      is_default;
+        gboolean      add_custom;
+        gboolean      remove_custom;
+
+        theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        /* Get the current theme's name, and set the parent */
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        gtk_tree_model_get (theme_model, &iter,
+                            THEME_IDENTIFIER_COL, &theme,
+                            THEME_IDENTIFIER_COL, &parent,
+                            -1);
+        is_custom = strcmp (theme, CUSTOM_THEME_NAME) == 0;
+        is_default = strcmp (alert_id, DEFAULT_ALERT_ID) == 0;
+
+        /* So a few possibilities:
+         * 1. Named theme, default alert selected: noop
+         * 2. Named theme, alternate alert selected: create new custom with sound
+         * 3. Custom theme, default alert selected: remove sound and possibly custom
+         * 4. Custom theme, alternate alert selected: update custom sound
+         */
+        add_custom = FALSE;
+        remove_custom = FALSE;
+        if (! is_custom && is_default) {
+                /* remove custom just in case */
+                remove_custom = TRUE;
+        } else if (! is_custom && ! is_default) {
+                create_custom_theme (parent);
+                save_alert_sounds (chooser, alert_id);
+                add_custom = TRUE;
+        } else if (is_custom && is_default) {
+                save_alert_sounds (chooser, alert_id);
+                /* after removing files check if it is empty */
+                if (custom_theme_dir_is_empty ()) {
+                        remove_custom = TRUE;
+                }
+        } else if (is_custom && ! is_default) {
+                save_alert_sounds (chooser, alert_id);
+        }
+
+        if (add_custom) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (theme_model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   THEME_DISPLAY_COL, _("Custom"),
+                                                   THEME_IDENTIFIER_COL, CUSTOM_THEME_NAME,
+                                                   THEME_PARENT_ID_COL, theme,
+                                                   -1);
+                set_combox_for_theme_name (chooser, CUSTOM_THEME_NAME);
+        } else if (remove_custom) {
+                gtk_tree_model_get_iter_first (theme_model, &iter);
+                do {
+                        char *this_parent;
+
+                        gtk_tree_model_get (theme_model, &iter,
+                                            THEME_PARENT_ID_COL, &this_parent,
+                                            -1);
+                        if (this_parent != NULL && strcmp (this_parent, CUSTOM_THEME_NAME) != 0) {
+                                g_free (this_parent);
+                                gtk_list_store_remove (GTK_LIST_STORE (theme_model), &iter);
+                                break;
+                        }
+                        g_free (this_parent);
+                } while (gtk_tree_model_iter_next (theme_model, &iter));
+
+                delete_custom_theme_dir ();
+
+                set_combox_for_theme_name (chooser, parent);
+        }
+
+        update_alert_model (chooser, alert_id);
+
+        g_free (theme);
+        g_free (parent);
+}
+
+static void
+on_alert_toggled (GtkCellRendererToggle *renderer,
+                  char                  *path_str,
+                  GvcSoundThemeChooser  *chooser)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreePath  *path;
+        gboolean      toggled;
+        char         *id;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        path = gtk_tree_path_new_from_string (path_str);
+        gtk_tree_model_get_iter (model, &iter, path);
+        gtk_tree_path_free (path);
+
+        id = NULL;
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            ALERT_ACTIVE_COL, &toggled,
+                            -1);
+
+        toggled ^= 1;
+        if (toggled) {
+                update_alert (chooser, id);
+        }
+
+        g_free (id);
+}
+
+static void
+play_preview_for_path (GvcSoundThemeChooser *chooser, GtkTreePath *path)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreeIter   theme_iter;
+        gchar        *id = NULL;
+        gchar        *parent_theme = NULL;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        if (gtk_tree_model_get_iter (model, &iter, path) == FALSE)
+                return;
+
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            -1);
+        if (id == NULL)
+                return;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &theme_iter)) {
+                GtkTreeModel *theme_model;
+                gchar        *theme_id = NULL;
+                gchar        *parent_id = NULL;
+
+                theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+                gtk_tree_model_get (theme_model, &theme_iter,
+                                    THEME_IDENTIFIER_COL, &theme_id,
+                                    THEME_PARENT_ID_COL, &parent_id, -1);
+                if (theme_id && strcmp (theme_id, CUSTOM_THEME_NAME) == 0)
+                        parent_theme = g_strdup (parent_id);
+
+                g_free (theme_id);
+                g_free (parent_id);
+        }
+
+        /* special case: for the default item on custom themes
+         * play the alert for the parent theme */
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                if (parent_theme != NULL) {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_CANBERRA_XDG_THEME_NAME, parent_theme,
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                } else {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                }
+        } else {
+                ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                        CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                        CA_PROP_MEDIA_FILENAME, id,
+                                        CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                        CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                        CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                        CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                        NULL);
+
+        }
+        g_free (parent_theme);
+        g_free (id);
+}
+
+static void
+on_treeview_row_activated (GtkTreeView          *treeview,
+                           GtkTreePath          *path,
+                           GtkTreeViewColumn    *column,
+                           GvcSoundThemeChooser *chooser)
+{
+        play_preview_for_path (chooser, path);
+}
+
+static void
+on_treeview_selection_changed (GtkTreeSelection     *selection,
+                               GvcSoundThemeChooser *chooser)
+{
+        GList        *paths;
+        GtkTreeModel *model;
+        GtkTreePath  *path;
+
+        if (chooser->priv->treeview == NULL)
+                return;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        paths = gtk_tree_selection_get_selected_rows (selection, &model);
+        if (paths == NULL)
+                return;
+
+        path = paths->data;
+        play_preview_for_path (chooser, path);
+
+        g_list_foreach (paths, (GFunc)gtk_tree_path_free, NULL);
+        g_list_free (paths);
+}
+
+static GtkWidget *
+create_alert_treeview (GvcSoundThemeChooser *chooser)
+{
+        GtkListStore         *store;
+        GtkWidget            *treeview;
+        GtkCellRenderer      *renderer;
+        GtkTreeViewColumn    *column;
+        GtkTreeSelection     *selection;
+
+        treeview = gtk_tree_view_new ();
+
+        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
+        g_signal_connect (G_OBJECT (treeview),
+                          "row-activated",
+                          G_CALLBACK (on_treeview_row_activated),
+                          chooser);
+
+        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+        gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+        g_signal_connect (G_OBJECT (selection),
+                          "changed",
+                          G_CALLBACK (on_treeview_selection_changed),
+                          chooser);
+
+        /* Setup the tree model, 3 columns:
+         * - display name
+         * - sound id
+         * - sound type
+         */
+        store = gtk_list_store_new (ALERT_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_BOOLEAN);
+
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           ALERT_IDENTIFIER_COL, DEFAULT_ALERT_ID,
+                                           ALERT_DISPLAY_COL, _("Default"),
+                                           ALERT_SOUND_TYPE_COL, _("From theme"),
+                                           ALERT_ACTIVE_COL, TRUE,
+                                           -1);
+
+        populate_model_from_dir (chooser, GTK_TREE_MODEL (store), SOUND_SET_DIR);
+
+        gtk_tree_view_set_model (GTK_TREE_VIEW (treeview),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_toggle_new ();
+        gtk_cell_renderer_toggle_set_radio (GTK_CELL_RENDERER_TOGGLE (renderer), TRUE);
+
+        column = gtk_tree_view_column_new_with_attributes (NULL,
+                                                           renderer,
+                                                           "active", ALERT_ACTIVE_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+        g_signal_connect (renderer,
+                          "toggled",
+                          G_CALLBACK (on_alert_toggled),
+                          chooser);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Name"),
+                                                           renderer,
+                                                           "text", ALERT_DISPLAY_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Type"),
+                                                           renderer,
+                                                           "text", ALERT_SOUND_TYPE_COL,
+                                                           NULL);
+
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        return treeview;
+}
+
+static int
+get_file_type (const char *sound_name,
+               char      **linked_name)
+{
+        char *name, *filename;
+
+        *linked_name = NULL;
+
+        name = g_strdup_printf ("%s.disabled", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_REGULAR) != FALSE) {
+                g_free (filename);
+                return SOUND_TYPE_OFF;
+        }
+        g_free (filename);
+
+        /* We only check for .ogg files because those are the
+         * only ones we create */
+        name = g_strdup_printf ("%s.ogg", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_SYMLINK) != FALSE) {
+                *linked_name = g_file_read_link (filename, NULL);
+                g_free (filename);
+                return SOUND_TYPE_CUSTOM;
+        }
+        g_free (filename);
+
+        return SOUND_TYPE_BUILTIN;
+}
+
+static void
+update_alerts_from_theme_name (GvcSoundThemeChooser *chooser,
+                               const gchar          *name)
+{
+        if (strcmp (name, CUSTOM_THEME_NAME) != 0) {
+                /* reset alert to default */
+                update_alert (chooser, DEFAULT_ALERT_ID);
+        } else {
+                int   sound_type;
+                char *linkname;
+
+                linkname = NULL;
+                sound_type = get_file_type ("bell-terminal", &linkname);
+                g_debug ("Found link: %s", linkname);
+                if (sound_type == SOUND_TYPE_CUSTOM) {
+                        update_alert (chooser, linkname);
+                }
+        }
+}
+
+static void
+update_theme (GvcSoundThemeChooser *chooser)
+{
+        char        *theme_name;
+        gboolean     events_enabled;
+        gboolean     feedback_enabled;
+
+        feedback_enabled = g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY);
+        set_input_feedback_enabled (chooser, feedback_enabled);
+
+        events_enabled = g_settings_get_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY);
+        if (events_enabled) {
+                theme_name = g_settings_get_string (chooser->priv->sound_settings, SOUND_THEME_KEY);
+        } else {
+                theme_name = g_strdup (NO_SOUNDS_THEME_NAME);
+        }
+
+        gtk_widget_set_sensitive (chooser->priv->selection_box, events_enabled);
+        gtk_widget_set_sensitive (chooser->priv->click_feedback_button, events_enabled);
+
+        set_combox_for_theme_name (chooser, theme_name);
+
+        update_alerts_from_theme_name (chooser, theme_name);
+
+        g_free (theme_name);
+}
+
+static void
+gvc_sound_theme_chooser_class_init (GvcSoundThemeChooserClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_sound_theme_chooser_dispose;
+}
+
+static void
+on_click_feedback_toggled (GtkToggleButton      *button,
+                           GvcSoundThemeChooser *chooser)
+{
+        gboolean enabled;
+
+        enabled = gtk_toggle_button_get_active (button);
+
+        g_settings_set_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY, enabled);
+}
+
+static void
+on_key_changed (GSettings            *settings,
+                gchar                *key,
+                GvcSoundThemeChooser *chooser)
+{
+        if (!strcmp (key, EVENT_SOUNDS_KEY) ||
+            !strcmp (key, SOUND_THEME_KEY) ||
+            !strcmp (key, INPUT_SOUNDS_KEY))
+                update_theme (chooser);
+}
+
+static void
+setup_list_size_constraint (GtkWidget *widget,
+                            GtkWidget *to_size)
+{
+        GtkRequisition req;
+        gint           sc_height;
+        int            max_height;
+
+        /* Constrain height to be the tree height up to a max */
+        gdk_window_get_geometry (gdk_screen_get_root_window (gtk_widget_get_screen (widget)),
+                                 NULL, NULL, NULL, &sc_height);
+
+        max_height = sc_height / 4;
+
+        // XXX this doesn't work
+        gtk_widget_get_preferred_size (to_size, NULL, &req);
+
+        gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (widget),
+                                                    MIN (req.height, max_height));
+}
+
+static void
+gvc_sound_theme_chooser_init (GvcSoundThemeChooser *chooser)
+{
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *scrolled_window;
+        gchar       *str;
+
+        chooser->priv = gvc_sound_theme_chooser_get_instance_private (chooser);
+
+        chooser->priv->theme_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->theme_box, FALSE, FALSE, 0);
+
+        label = gtk_label_new_with_mnemonic (_("Sound _theme:"));
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), label, FALSE, FALSE, 0);
+        chooser->priv->combo_box = gtk_combo_box_new ();
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), chooser->priv->combo_box, FALSE, FALSE, 6);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->combo_box);
+
+        chooser->priv->sound_settings = g_settings_new (KEY_SOUNDS_SCHEMA);
+
+        g_signal_connect (G_OBJECT (chooser->priv->sound_settings),
+                          "changed",
+                          G_CALLBACK (on_key_changed),
+                          chooser);
+
+        str = g_strdup_printf ("<b>%s</b>", _("C_hoose an alert sound:"));
+        chooser->priv->selection_box = box = gtk_frame_new (str);
+        g_free (str);
+
+        label = gtk_frame_get_label_widget (GTK_FRAME (box));
+        gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
+        gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+        gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
+
+        gtk_box_pack_start (GTK_BOX (chooser), box, TRUE, TRUE, 6);
+
+        chooser->priv->treeview = create_alert_treeview (chooser);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->treeview);
+
+        scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+        gtk_widget_set_hexpand (scrolled_window, TRUE);
+        gtk_widget_set_vexpand (scrolled_window, TRUE);
+        gtk_widget_set_margin_top (scrolled_window, 6);
+
+        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+                                        GTK_POLICY_NEVER,
+                                        GTK_POLICY_AUTOMATIC);
+        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
+                                             GTK_SHADOW_IN);
+
+        gtk_container_add (GTK_CONTAINER (scrolled_window), chooser->priv->treeview);
+        gtk_container_add (GTK_CONTAINER (box), scrolled_window);
+
+        chooser->priv->click_feedback_button = gtk_check_button_new_with_mnemonic (_("Enable _window and button sounds"));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY));
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->click_feedback_button,
+                            FALSE, FALSE, 0);
+
+        g_signal_connect (G_OBJECT (chooser->priv->click_feedback_button),
+                          "toggled",
+                          G_CALLBACK (on_click_feedback_toggled),
+                          chooser);
+
+        setup_theme_selector (chooser);
+        update_theme (chooser);
+
+        setup_list_size_constraint (scrolled_window, chooser->priv->treeview);
+}
+
+static void
+gvc_sound_theme_chooser_dispose (GObject *object)
+{
+        GvcSoundThemeChooser *chooser;
+
+        chooser = GVC_SOUND_THEME_CHOOSER (object);
+
+        g_clear_object (&chooser->priv->sound_settings);
+
+        G_OBJECT_CLASS (gvc_sound_theme_chooser_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_sound_theme_chooser_new (void)
+{
+        return g_object_new (GVC_TYPE_SOUND_THEME_CHOOSER,
+                                "spacing", 6,
+                                "orientation", GTK_ORIENTATION_VERTICAL,
+                                NULL);
+}
+
+
+
+ + + diff --git a/2020-04-21-012206-8805-cppcheck@d4487123b370_travis/2.html b/2020-04-21-012206-8805-cppcheck@d4487123b370_travis/2.html new file mode 100644 index 0000000..bacfabb --- /dev/null +++ b/2020-04-21-012206-8805-cppcheck@d4487123b370_travis/2.html @@ -0,0 +1,1110 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <canberra.h>
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-speaker-test.h"
+#include "gvc-utils.h"
+
+struct _GvcSpeakerTestPrivate
+{
+        GArray           *controls;
+        ca_context       *canberra;
+        MateMixerStream  *stream;
+};
+
+enum {
+        PROP_0,
+        PROP_STREAM,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_speaker_test_dispose    (GObject             *object);
+static void gvc_speaker_test_finalize   (GObject             *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSpeakerTest, gvc_speaker_test, GTK_TYPE_GRID)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+typedef struct {
+        MateMixerChannelPosition position;
+        guint left;
+        guint top;
+} TablePosition;
+
+static const TablePosition positions[] = {
+        /* Position, X, Y */
+        { MATE_MIXER_CHANNEL_FRONT_LEFT, 0, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_LEFT_CENTER, 1, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_CENTER, 2, 0, },
+        { MATE_MIXER_CHANNEL_MONO, 2, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT_CENTER, 3, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT, 4, 0, },
+        { MATE_MIXER_CHANNEL_SIDE_LEFT, 0, 1, },
+        { MATE_MIXER_CHANNEL_SIDE_RIGHT, 4, 1, },
+        { MATE_MIXER_CHANNEL_BACK_LEFT, 0, 2, },
+        { MATE_MIXER_CHANNEL_BACK_CENTER, 2, 2, },
+        { MATE_MIXER_CHANNEL_BACK_RIGHT, 4, 2, },
+        { MATE_MIXER_CHANNEL_LFE, 3, 2 }
+};
+
+MateMixerStream *
+gvc_speaker_test_get_stream (GvcSpeakerTest *test)
+{
+        g_return_val_if_fail (GVC_IS_SPEAKER_TEST (test), NULL);
+
+        return test->priv->stream;
+}
+
+static void
+gvc_speaker_test_set_stream (GvcSpeakerTest *test, MateMixerStream *stream)
+{
+        MateMixerStreamControl *control;
+        const gchar            *name;
+        guint                   i;
+
+        name = mate_mixer_stream_get_name (stream);
+        control = mate_mixer_stream_get_default_control (stream);
+
+        ca_context_change_device (test->priv->canberra, name);
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                gboolean has_position =
+                        mate_mixer_stream_control_has_channel_position (control, positions[i].position);
+
+                gtk_widget_set_visible (g_array_index (test->priv->controls, GtkWidget *, i),
+                                        has_position);
+        }
+
+        test->priv->stream = g_object_ref (stream);
+}
+
+static void
+gvc_speaker_test_set_property (GObject       *object,
+                               guint          prop_id,
+                               const GValue  *value,
+                               GParamSpec    *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                gvc_speaker_test_set_stream (self, g_value_get_object (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_get_property (GObject     *object,
+                               guint        prop_id,
+                               GValue      *value,
+                               GParamSpec  *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                g_value_set_object (value, self->priv->stream);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_class_init (GvcSpeakerTestClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose  = gvc_speaker_test_dispose;
+        object_class->finalize = gvc_speaker_test_finalize;
+        object_class->set_property = gvc_speaker_test_set_property;
+        object_class->get_property = gvc_speaker_test_get_property;
+
+        properties[PROP_STREAM] =
+                g_param_spec_object ("stream",
+                                     "Stream",
+                                     "MateMixer stream",
+                                     MATE_MIXER_TYPE_STREAM,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+}
+
+static const gchar *
+sound_name (MateMixerChannelPosition position)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return "audio-channel-front-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return "audio-channel-front-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return "audio-channel-front-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return "audio-channel-rear-left";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return "audio-channel-rear-right";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return "audio-channel-rear-center";
+        case MATE_MIXER_CHANNEL_LFE:
+                return "audio-channel-lfe";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return "audio-channel-side-left";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return "audio-channel-side-right";
+        default:
+                return NULL;
+        }
+}
+
+static const gchar *
+icon_name (MateMixerChannelPosition position, gboolean playing)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return playing
+                        ? "audio-speaker-left-testing"
+                        : "audio-speaker-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return playing
+                        ? "audio-speaker-right-testing"
+                        : "audio-speaker-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return playing
+                        ? "audio-speaker-center-testing"
+                        : "audio-speaker-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return playing
+                        ? "audio-speaker-left-back-testing"
+                        : "audio-speaker-left-back";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return playing
+                        ? "audio-speaker-right-back-testing"
+                        : "audio-speaker-right-back";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return playing
+                        ? "audio-speaker-center-back-testing"
+                        : "audio-speaker-center-back";
+        case MATE_MIXER_CHANNEL_LFE:
+                return playing
+                        ? "audio-subwoofer-testing"
+                        : "audio-subwoofer";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return playing
+                        ? "audio-speaker-left-side-testing"
+                        : "audio-speaker-left-side";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return playing
+                        ? "audio-speaker-right-side-testing"
+                        : "audio-speaker-right-side";
+        default:
+                return NULL;
+        }
+}
+
+static void
+update_button (GtkWidget *control)
+{
+        GtkWidget *button;
+        GtkWidget *image;
+        gboolean   playing;
+        MateMixerChannelPosition position;
+
+        button = g_object_get_data (G_OBJECT (control), "button");
+        image  = g_object_get_data (G_OBJECT (control), "image");
+
+        position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+        playing  = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        gtk_button_set_label (GTK_BUTTON (button), playing ? _("Stop") : _("Test"));
+
+        gtk_image_set_from_icon_name (GTK_IMAGE (image),
+                                      icon_name (position, playing),
+                                      GTK_ICON_SIZE_DIALOG);
+}
+
+static gboolean
+idle_cb (GtkWidget *control)
+{
+        if (control != NULL) {
+                /* This is called in the background thread, hence forward to main thread
+                 * via idle callback */
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+
+                update_button (control);
+        }
+        return FALSE;
+}
+
+static void
+finish_cb (ca_context *c, uint32_t id, int error_code, void *userdata)
+{
+        GtkWidget *control = (GtkWidget *) userdata;
+
+        if (error_code == CA_ERROR_DESTROYED || control == NULL)
+                return;
+
+        g_idle_add ((GSourceFunc) idle_cb, control);
+}
+
+static void
+on_test_button_clicked (GtkButton *button, GtkWidget *control)
+{
+        gboolean    playing;
+        ca_context *canberra;
+
+        canberra = g_object_get_data (G_OBJECT (control), "canberra");
+
+        ca_context_cancel (canberra, 1);
+
+        playing = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        if (playing) {
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        } else {
+                MateMixerChannelPosition position;
+                const gchar *name;
+                ca_proplist *proplist;
+
+                position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+
+                ca_proplist_create (&proplist);
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_ROLE, "test");
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_NAME,
+                                  gvc_channel_position_to_pretty_string (position));
+                ca_proplist_sets (proplist,
+                                  CA_PROP_CANBERRA_FORCE_CHANNEL,
+                                  gvc_channel_position_to_pulse_string (position));
+
+                ca_proplist_sets (proplist, CA_PROP_CANBERRA_ENABLE, "1");
+
+                name = sound_name (position);
+                if (name != NULL) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, name);
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, "audio-test-signal");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets(proplist, CA_PROP_EVENT_ID, "bell-window-system");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (playing));
+        }
+
+        update_button (control);
+}
+
+static GtkWidget *
+create_control (ca_context *canberra, MateMixerChannelPosition position)
+{
+        GtkWidget   *control;
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *image;
+        GtkWidget   *test_button;
+        const gchar *name;
+
+        control = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+        box     = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        g_object_set_data (G_OBJECT (control), "position", GINT_TO_POINTER (position));
+        g_object_set_data (G_OBJECT (control), "canberra", canberra);
+
+        name = icon_name (position, FALSE);
+        if (name == NULL)
+                name = "audio-volume-medium";
+
+        image = gtk_image_new_from_icon_name (name, GTK_ICON_SIZE_DIALOG);
+        g_object_set_data (G_OBJECT (control), "image", image);
+        gtk_box_pack_start (GTK_BOX (control), image, FALSE, FALSE, 0);
+
+        label = gtk_label_new (gvc_channel_position_to_pretty_string (position));
+        gtk_box_pack_start (GTK_BOX (control), label, FALSE, FALSE, 0);
+
+        test_button = gtk_button_new_with_label (_("Test"));
+        g_signal_connect (G_OBJECT (test_button),
+                          "clicked",
+                          G_CALLBACK (on_test_button_clicked),
+                          control);
+
+        g_object_set_data (G_OBJECT (control), "button", test_button);
+
+        gtk_box_pack_start (GTK_BOX (box), test_button, TRUE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (control), box, FALSE, FALSE, 0);
+
+        gtk_widget_show_all (control);
+
+        return control;
+}
+
+static void
+create_controls (GvcSpeakerTest *test)
+{
+        guint i;
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                GtkWidget *control = create_control (test->priv->canberra, positions[i].position);
+
+                gtk_grid_attach (GTK_GRID (test),
+                                 control,
+                                 positions[i].left,
+                                 positions[i].top,
+                                 1, 1);
+                g_array_insert_val (test->priv->controls, i, control);
+        }
+}
+
+static void
+gvc_speaker_test_init (GvcSpeakerTest *test)
+{
+        GtkWidget *face;
+
+        test->priv = gvc_speaker_test_get_instance_private (test);
+
+        gtk_container_set_border_width (GTK_CONTAINER (test), 12);
+
+        face = gtk_image_new_from_icon_name ("face-smile", GTK_ICON_SIZE_DIALOG);
+
+        gtk_grid_attach (GTK_GRID (test),
+                         face,
+                         1, 1,
+                         3, 1);
+
+
+        gtk_grid_set_baseline_row (GTK_GRID (test), 1);
+        gtk_widget_show (face);
+
+        ca_context_create (&test->priv->canberra);
+
+        /* The test sounds are played for a single channel, set up using the
+         * FORCE_CHANNEL property of libcanberra; this property is only supported
+         * in the PulseAudio backend, so avoid other backends completely */
+        ca_context_set_driver (test->priv->canberra, "pulse");
+
+        ca_context_change_props (test->priv->canberra,
+                                 CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+                                 CA_PROP_APPLICATION_NAME, _("Volume Control"),
+                                 CA_PROP_APPLICATION_VERSION, VERSION,
+                                 CA_PROP_APPLICATION_ICON_NAME, "multimedia-volume-control",
+                                 NULL);
+
+        test->priv->controls = g_array_new (FALSE, FALSE, sizeof (GtkWidget *));
+
+        create_controls (test);
+}
+
+static void
+gvc_speaker_test_dispose (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        g_clear_object (&test->priv->stream);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->dispose (object);
+}
+
+static void
+gvc_speaker_test_finalize (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        ca_context_destroy (test->priv->canberra);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->finalize (object);
+}
+
+GtkWidget *
+gvc_speaker_test_new (MateMixerStream *stream)
+{
+        GObject *test;
+
+        g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL);
+
+        test = g_object_new (GVC_TYPE_SPEAKER_TEST,
+                             "row-spacing", 6,
+                             "column-spacing", 6,
+                             "row-homogeneous", TRUE,
+                             "column-homogeneous", TRUE,
+                             "stream", stream,
+                             NULL);
+
+        return GTK_WIDGET (test);
+}
+
+
+
+ + + diff --git a/2020-04-21-012206-8805-cppcheck@d4487123b370_travis/index.html b/2020-04-21-012206-8805-cppcheck@d4487123b370_travis/index.html new file mode 100644 index 0000000..59baeb0 --- /dev/null +++ b/2020-04-21-012206-8805-cppcheck@d4487123b370_travis/index.html @@ -0,0 +1,108 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
mate-volume-control/gvc-combo-box.c
70unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
mate-volume-control/gvc-sound-theme-chooser.c
735ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
746ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
758ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
mate-volume-control/gvc-speaker-test.c
53unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+ + + diff --git a/2020-04-21-012206-8805-cppcheck@d4487123b370_travis/stats.html b/2020-04-21-012206-8805-cppcheck@d4487123b370_travis/stats.html new file mode 100644 index 0000000..3fb6add --- /dev/null +++ b/2020-04-21-012206-8805-cppcheck@d4487123b370_travis/stats.html @@ -0,0 +1,93 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+

Top 10 files for error severity, total findings: 2
+   1  mate-volume-control/gvc-speaker-test.c
+   1  mate-volume-control/gvc-combo-box.c
+

+

Top 10 files for information severity, total findings: 3
+   3  mate-volume-control/gvc-sound-theme-chooser.c
+

+ +
+ + + diff --git a/2020-04-21-012206-8805-cppcheck@d4487123b370_travis/style.css b/2020-04-21-012206-8805-cppcheck@d4487123b370_travis/style.css new file mode 100644 index 0000000..c39571c --- /dev/null +++ b/2020-04-21-012206-8805-cppcheck@d4487123b370_travis/style.css @@ -0,0 +1,149 @@ + +body { + font: 13px Arial, Verdana, Sans-Serif; + margin: 0; + width: auto; +} + +h1 { + margin: 10px; +} + +#footer > p { + margin: 4px; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + border: 1px dotted black; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #B6B6B4; +} + +.inconclusive2 { + background-color: #B6B6B4; + border: 1px dotted black; + display: inline-block; + margin-left: 4px; +} + +div.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +div.verbose div.content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid black; + background-color: #FFFFCC; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +#header { + border-bottom: thin solid #aaa; +} + +#menu { + float: left; + margin-top: 5px; + text-align: left; + width: 150px; + /*height: 75%;*/ + position: fixed; + overflow: auto; + z-index: 1; +} + +#menu_index { + float: left; + margin-top: 5px; + padding-left: 5px; + text-align: left; + width: 300px; + /*height: 75%;*/ + position: fixed; + overflow: auto; + z-index: 1; +} + +#menu > a { + display: block; + margin-left: 10px; + font: 12px; + z-index: 1; +} + +#filename { + margin-left: 10px; + font: 12px; + z-index: 1; +} + +.highlighttable { + background-color:white; + z-index: 10; + position: relative; + margin: -10 px; +} + +#content { + background-color: white; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + float: left; + margin: 5px; + margin-left: 10px; + padding: 0 10px 10px 10px; + width: 80%; + padding-left: 150px; +} + +#content_index { + background-color: white; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + float: left; + margin: 5px; + margin-left: 10px; + padding: 0 10px 10px 10px; + width: 80%; + padding-left: 300px; +} + +.linenos { + border-right: thin solid #aaa; + color: lightgray; + padding-right: 6px; +} + +#footer { + border-top: thin solid #aaa; + clear: both; + font-size: 90%; + margin-top: 5px; +} + +#footer ul { + list-style-type: none; + padding-left: 0; +} diff --git a/2020-04-21-012601-6120-cppcheck@11fc77a34034_travis/0.html b/2020-04-21-012601-6120-cppcheck@11fc77a34034_travis/0.html new file mode 100644 index 0000000..e262ed0 --- /dev/null +++ b/2020-04-21-012601-6120-cppcheck@11fc77a34034_travis/0.html @@ -0,0 +1,1038 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-combo-box.h"
+
+struct _GvcComboBoxPrivate
+{
+        GtkWidget       *drop_box;
+        GtkWidget       *start_box;
+        GtkWidget       *end_box;
+        GtkWidget       *label;
+        GtkWidget       *button;
+        GtkTreeModel    *model;
+        GtkWidget       *combobox;
+        MateMixerSwitch *swtch;
+};
+
+enum {
+        COL_NAME,
+        COL_HUMAN_NAME,
+        NUM_COLS
+};
+
+enum {
+        CHANGING,
+        BUTTON_CLICKED,
+        LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+enum {
+        PROP_0,
+        PROP_SWITCH,
+        PROP_LABEL,
+        PROP_SHOW_BUTTON,
+        PROP_BUTTON_LABEL,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_combo_box_dispose    (GObject          *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcComboBox, gvc_combo_box, GTK_TYPE_BOX)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+MateMixerSwitch *
+gvc_combo_box_get_switch (GvcComboBox *combobox)
+{
+        g_return_val_if_fail (GVC_IS_COMBO_BOX (combobox), NULL);
+
+        return combobox->priv->swtch;
+}
+
+void
+gvc_combo_box_set_size_group (GvcComboBox  *combobox,
+                              GtkSizeGroup *group,
+                              gboolean      symmetric)
+{
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (GTK_IS_SIZE_GROUP (group));
+
+        if (group != NULL) {
+                gtk_size_group_add_widget (group, combobox->priv->start_box);
+                if (symmetric == TRUE)
+                        gtk_size_group_add_widget (group, combobox->priv->end_box);
+        }
+        gtk_widget_queue_draw (GTK_WIDGET (combobox));
+}
+
+static void
+on_switch_active_option_notify (MateMixerSwitch *swtch,
+                                GParamSpec      *pspec,
+                                GvcComboBox     *combobox)
+{
+        GtkTreeIter            iter;
+        MateMixerSwitchOption *active;
+        gboolean               cont;
+        const gchar           *name;
+
+        active = mate_mixer_switch_get_active_option (swtch);
+        if (G_UNLIKELY (active == NULL)) {
+                g_warn_if_reached ();
+                return;
+        }
+
+        /* Select the newly activated switch option in the combo box */
+        name = mate_mixer_switch_option_get_name (active);
+        cont = gtk_tree_model_get_iter_first (combobox->priv->model, &iter);
+        while (cont == TRUE) {
+                gchar *current;
+
+                gtk_tree_model_get (combobox->priv->model, &iter,
+                                    COL_NAME, &current,
+                                    -1);
+                if (g_strcmp0 (name, current) == 0) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox), &iter);
+                        g_free (current);
+                        return;
+                }
+                g_free (current);
+
+                cont = gtk_tree_model_iter_next (combobox->priv->model, &iter);
+        }
+        g_warning ("Could not find switch option '%s' in combo box", name);
+}
+
+static void
+gvc_combo_box_set_switch (GvcComboBox *combobox, MateMixerSwitch *swtch)
+{
+        MateMixerSwitchOption *active;
+        const GList           *options;
+
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (MATE_MIXER_IS_SWITCH (swtch));
+
+        combobox->priv->swtch = g_object_ref (swtch);
+
+        active  = mate_mixer_switch_get_active_option (swtch);
+        options = mate_mixer_switch_list_options (swtch);
+        while (options != NULL) {
+                GtkTreeIter            iter;
+                MateMixerSwitchOption *option = MATE_MIXER_SWITCH_OPTION (options->data);
+
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (combobox->priv->model),
+                                                   &iter,
+                                                   G_MAXINT,
+                                                   COL_NAME,
+                                                   mate_mixer_switch_option_get_name (option),
+                                                   COL_HUMAN_NAME,
+                                                   mate_mixer_switch_option_get_label (option),
+                                                   -1);
+
+                /* Select the currently active option of the switch */
+                if (option == active) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox),
+                                                       &iter);
+                }
+                options = options->next;
+        }
+
+        g_signal_connect (G_OBJECT (swtch),
+                          "notify::active-option",
+                          G_CALLBACK (on_switch_active_option_notify),
+                          combobox);
+}
+
+static void
+gvc_combo_box_set_property (GObject       *object,
+                            guint          prop_id,
+                            const GValue  *value,
+                            GParamSpec    *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                gvc_combo_box_set_switch (self, g_value_get_object (value));
+                break;
+        case PROP_LABEL:
+                gtk_label_set_text_with_mnemonic (GTK_LABEL (self->priv->label), g_value_get_string (value));
+                break;
+        case PROP_BUTTON_LABEL:
+                gtk_button_set_label (GTK_BUTTON (self->priv->button), g_value_get_string (value));
+                break;
+        case PROP_SHOW_BUTTON:
+                gtk_widget_set_visible (self->priv->button, g_value_get_boolean (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_get_property (GObject     *object,
+                            guint        prop_id,
+                            GValue      *value,
+                            GParamSpec  *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                g_value_set_object (value, self->priv->swtch);
+                break;
+        case PROP_LABEL:
+                g_value_set_string (value, gtk_label_get_text (GTK_LABEL (self->priv->label)));
+                break;
+        case PROP_BUTTON_LABEL:
+                g_value_set_string (value, gtk_button_get_label (GTK_BUTTON (self->priv->button)));
+                break;
+        case PROP_SHOW_BUTTON:
+                g_value_set_boolean (value, gtk_widget_get_visible (self->priv->button));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_class_init (GvcComboBoxClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_combo_box_dispose;
+        object_class->set_property = gvc_combo_box_set_property;
+        object_class->get_property = gvc_combo_box_get_property;
+
+        properties[PROP_SWITCH] =
+                g_param_spec_object ("switch",
+                                     "switch",
+                                     "The MateMixerSwitch",
+                                     MATE_MIXER_TYPE_SWITCH,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_LABEL] =
+                g_param_spec_string ("label",
+                                     "label",
+                                     "The combo box label",
+                                     _("_Profile:"),
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_SHOW_BUTTON] =
+                g_param_spec_boolean ("show-button",
+                                      "show-button",
+                                      "Whether to show the button",
+                                      FALSE,
+                                      G_PARAM_READWRITE |
+                                      G_PARAM_CONSTRUCT |
+                                      G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_BUTTON_LABEL] =
+                g_param_spec_string ("button-label",
+                                     "button-label",
+                                     "The button's label",
+                                     "",
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+
+        signals[CHANGING] =
+                g_signal_new ("changing",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, changing),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__OBJECT,
+                              G_TYPE_NONE,
+                              1,
+                              MATE_MIXER_TYPE_SWITCH_OPTION);
+
+        signals[BUTTON_CLICKED] =
+                g_signal_new ("button-clicked",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, button_clicked),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
+}
+
+static void
+on_combo_box_changed (GtkComboBox *widget, GvcComboBox *combobox)
+{
+        GtkTreeIter            iter;
+        gchar                 *name;
+        MateMixerSwitchOption *option;
+
+        if (G_UNLIKELY (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter) == FALSE))
+                return;
+
+        gtk_tree_model_get (combobox->priv->model, &iter,
+                            COL_NAME, &name,
+                            -1);
+
+        option = mate_mixer_switch_get_option (combobox->priv->swtch, name);
+        if (G_UNLIKELY (option == NULL)) {
+                g_warn_if_reached ();
+                g_free (name);
+                return;
+        }
+
+        /* Inform that we are about to change the active option of the switch */
+        g_signal_emit (combobox, signals[CHANGING], 0, option);
+
+        mate_mixer_switch_set_active_option (combobox->priv->swtch, option);
+        g_free (name);
+}
+
+static void
+on_combo_box_button_clicked (GtkButton *button, GvcComboBox *combobox)
+{
+        /* The meaning of the button is defined by the owner, so only notify
+         * when it is clicked on */
+        g_signal_emit (combobox, signals[BUTTON_CLICKED], 0);
+}
+
+static void
+gvc_combo_box_init (GvcComboBox *combobox)
+{
+        GtkWidget       *frame;
+        GtkCellRenderer *renderer;
+
+        frame = gtk_frame_new (NULL);
+        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
+
+        combobox->priv = gvc_combo_box_get_instance_private (combobox);
+
+        combobox->priv->model = GTK_TREE_MODEL (gtk_list_store_new (NUM_COLS,
+                                                                    G_TYPE_STRING,
+                                                                    G_TYPE_STRING));
+
+        combobox->priv->combobox = gtk_combo_box_new_with_model (combobox->priv->model);
+
+        combobox->priv->label = gtk_label_new (NULL);
+
+        gtk_label_set_xalign (GTK_LABEL (combobox->priv->label), 0.0);
+        gtk_label_set_yalign (GTK_LABEL (combobox->priv->label), 0.5);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (combobox->priv->label),
+                                       combobox->priv->combobox);
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                    renderer,
+                                    FALSE);
+        gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                       renderer,
+                                       "text",
+                                       COL_HUMAN_NAME);
+
+        combobox->priv->drop_box  = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->start_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->end_box   = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+        /* Make sure the combo box does not get too long on long profile names */
+        g_object_set (G_OBJECT (renderer),
+                      "ellipsize",
+                      PANGO_ELLIPSIZE_END,
+                      NULL);
+
+        gtk_combo_box_set_popup_fixed_width (GTK_COMBO_BOX (combobox->priv->combobox), FALSE);
+
+        gtk_box_pack_start (GTK_BOX (combobox),
+                            frame,
+                            TRUE, TRUE, 0);
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->start_box,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->start_box),
+                            combobox->priv->label,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->combobox,
+                            TRUE, TRUE, 0);
+
+        combobox->priv->button = gtk_button_new_with_label ("");
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->button,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->end_box,
+                            FALSE, FALSE, 0);
+
+        gtk_container_add (GTK_CONTAINER (frame), combobox->priv->drop_box);
+
+        g_signal_connect (G_OBJECT (combobox->priv->combobox),
+                          "changed",
+                          G_CALLBACK (on_combo_box_changed),
+                          combobox);
+        g_signal_connect (G_OBJECT (combobox->priv->button),
+                          "clicked",
+                          G_CALLBACK (on_combo_box_button_clicked),
+                          combobox);
+
+        gtk_widget_set_no_show_all (combobox->priv->button, TRUE);
+        gtk_widget_show_all (frame);
+}
+
+static void
+gvc_combo_box_dispose (GObject *object)
+{
+        GvcComboBox *combobox;
+
+        combobox = GVC_COMBO_BOX (object);
+
+        if (G_LIKELY (combobox->priv->swtch != NULL)) {
+                g_signal_handlers_disconnect_by_func (G_OBJECT (combobox->priv->swtch),
+                                                      G_CALLBACK (on_switch_active_option_notify),
+                                                      combobox);
+                g_clear_object (&combobox->priv->swtch);
+        }
+
+        g_clear_object (&combobox->priv->model);
+
+        G_OBJECT_CLASS (gvc_combo_box_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_combo_box_new (MateMixerSwitch *swtch, const gchar *label)
+{
+        return g_object_new (GVC_TYPE_COMBO_BOX,
+                             "switch", swtch,
+                             "label", label,
+                             "orientation", GTK_ORIENTATION_HORIZONTAL,
+                             NULL);
+}
+
+
+
+ + + diff --git a/2020-04-21-012601-6120-cppcheck@11fc77a34034_travis/1.html b/2020-04-21-012601-6120-cppcheck@11fc77a34034_travis/1.html new file mode 100644 index 0000000..67179f2 --- /dev/null +++ b/2020-04-21-012601-6120-cppcheck@11fc77a34034_travis/1.html @@ -0,0 +1,2368 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
+ * Copyright (C) 2008 William Jon McCann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <utime.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+#include <canberra-gtk.h>
+#include <libxml/tree.h>
+
+#include "gvc-sound-theme-chooser.h"
+#include "sound-theme-file-utils.h"
+
+struct GvcSoundThemeChooserPrivate
+{
+        GtkWidget *combo_box;
+        GtkWidget *treeview;
+        GtkWidget *theme_box;
+        GtkWidget *selection_box;
+        GtkWidget *click_feedback_button;
+        GSettings *sound_settings;
+};
+
+static void     gvc_sound_theme_chooser_dispose   (GObject            *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSoundThemeChooser, gvc_sound_theme_chooser, GTK_TYPE_BOX)
+
+#define KEY_SOUNDS_SCHEMA          "org.mate.sound"
+#define EVENT_SOUNDS_KEY           "event-sounds"
+#define INPUT_SOUNDS_KEY           "input-feedback-sounds"
+#define SOUND_THEME_KEY            "theme-name"
+
+#define DEFAULT_ALERT_ID        "__default"
+#define CUSTOM_THEME_NAME       "__custom"
+#define NO_SOUNDS_THEME_NAME    "__no_sounds"
+
+enum {
+        THEME_DISPLAY_COL,
+        THEME_IDENTIFIER_COL,
+        THEME_PARENT_ID_COL,
+        THEME_NUM_COLS
+};
+
+enum {
+        ALERT_DISPLAY_COL,
+        ALERT_IDENTIFIER_COL,
+        ALERT_SOUND_TYPE_COL,
+        ALERT_ACTIVE_COL,
+        ALERT_NUM_COLS
+};
+
+enum {
+        SOUND_TYPE_UNSET,
+        SOUND_TYPE_OFF,
+        SOUND_TYPE_DEFAULT_FROM_THEME,
+        SOUND_TYPE_BUILTIN,
+        SOUND_TYPE_CUSTOM
+};
+
+static void
+on_combobox_changed (GtkComboBox          *widget,
+                     GvcSoundThemeChooser *chooser)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        char         *theme_name;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &theme_name, -1);
+
+        g_assert (theme_name != NULL);
+
+        /* It is necessary to update the theme name before any other setting as
+         * the "changed" notification will reload the contents of the widget */
+        g_settings_set_string (chooser->priv->sound_settings, SOUND_THEME_KEY, theme_name);
+
+        /* special case for no sounds */
+        if (strcmp (theme_name, NO_SOUNDS_THEME_NAME) == 0) {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, FALSE);
+                return;
+        } else {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, TRUE);
+        }
+
+        g_free (theme_name);
+
+        /* FIXME: reset alert model */
+}
+
+static char *
+load_index_theme_name (const char *index,
+                       char      **parent)
+{
+        GKeyFile *file;
+        char *indexname = NULL;
+        gboolean hidden;
+
+        file = g_key_file_new ();
+        if (g_key_file_load_from_file (file, index, G_KEY_FILE_KEEP_TRANSLATIONS, NULL) == FALSE) {
+                g_key_file_free (file);
+                return NULL;
+        }
+        /* Don't add hidden themes to the list */
+        hidden = g_key_file_get_boolean (file, "Sound Theme", "Hidden", NULL);
+        if (!hidden) {
+                indexname = g_key_file_get_locale_string (file,
+                                                          "Sound Theme",
+                                                          "Name",
+                                                          NULL,
+                                                          NULL);
+
+                /* Save the parent theme, if there's one */
+                if (parent != NULL) {
+                        *parent = g_key_file_get_string (file,
+                                                         "Sound Theme",
+                                                         "Inherits",
+                                                         NULL);
+                }
+        }
+
+        g_key_file_free (file);
+        return indexname;
+}
+
+static void
+sound_theme_in_dir (GHashTable *hash,
+                    const char *dir)
+{
+        GDir *d;
+        const char *name;
+
+        d = g_dir_open (dir, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *dirname, *index, *indexname;
+
+                /* Look for directories */
+                dirname = g_build_filename (dir, name, NULL);
+                if (g_file_test (dirname, G_FILE_TEST_IS_DIR) == FALSE) {
+                        g_free (dirname);
+                        continue;
+                }
+
+                /* Look for index files */
+                index = g_build_filename (dirname, "index.theme", NULL);
+                g_free (dirname);
+
+                /* Check the name of the theme in the index.theme file */
+                indexname = load_index_theme_name (index, NULL);
+                g_free (index);
+                if (indexname == NULL) {
+                        continue;
+                }
+
+                g_hash_table_insert (hash, g_strdup (name), indexname);
+        }
+
+        g_dir_close (d);
+}
+
+static void
+add_theme_to_store (const char   *key,
+                    const char   *value,
+                    GtkListStore *store)
+{
+        char *parent;
+
+        parent = NULL;
+
+        /* Get the parent, if we're checking the custom theme */
+        if (strcmp (key, CUSTOM_THEME_NAME) == 0) {
+                char *name, *path;
+
+                path = custom_theme_dir_path ("index.theme");
+                name = load_index_theme_name (path, &parent);
+                g_free (name);
+                g_free (path);
+        }
+        gtk_list_store_insert_with_values (store, NULL, G_MAXINT,
+                                           THEME_DISPLAY_COL, value,
+                                           THEME_IDENTIFIER_COL, key,
+                                           THEME_PARENT_ID_COL, parent,
+                                           -1);
+        g_free (parent);
+}
+
+static void
+set_combox_for_theme_name (GvcSoundThemeChooser *chooser,
+                           const char           *name)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        gboolean      found;
+
+        /* If the name is empty, use "freedesktop" */
+        if (name == NULL || *name == '\0') {
+                name = "freedesktop";
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+        if (gtk_tree_model_get_iter_first (model, &iter) == FALSE) {
+                return;
+        }
+
+        do {
+                char *value;
+
+                gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &value, -1);
+                found = (value != NULL && strcmp (value, name) == 0);
+                g_free (value);
+
+        } while (!found && gtk_tree_model_iter_next (model, &iter));
+
+        /* When we can't find the theme we need to set, try to set the default
+         * one "freedesktop" */
+        if (found) {
+                gtk_combo_box_set_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter);
+        } else if (strcmp (name, "freedesktop") != 0) {
+                g_debug ("not found, falling back to fdo");
+                set_combox_for_theme_name (chooser, "freedesktop");
+        }
+}
+
+static void
+set_input_feedback_enabled (GvcSoundThemeChooser *chooser,
+                            gboolean              enabled)
+{
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      enabled);
+}
+
+static void
+setup_theme_selector (GvcSoundThemeChooser *chooser)
+{
+        GHashTable           *hash;
+        GtkListStore         *store;
+        GtkCellRenderer      *renderer;
+        const char * const   *data_dirs;
+        const char           *data_dir;
+        char                 *dir;
+        guint                 i;
+
+        /* Add the theme names and their display name to a hash table,
+         * makes it easy to avoid duplicate themes */
+        hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+        data_dirs = g_get_system_data_dirs ();
+        for (i = 0; data_dirs[i] != NULL; i++) {
+                dir = g_build_filename (data_dirs[i], "sounds", NULL);
+                sound_theme_in_dir (hash, dir);
+                g_free (dir);
+        }
+
+        data_dir = g_get_user_data_dir ();
+        dir = g_build_filename (data_dir, "sounds", NULL);
+        sound_theme_in_dir (hash, dir);
+        g_free (dir);
+
+        /* If there isn't at least one theme, make everything
+         * insensitive, LAME! */
+        if (g_hash_table_size (hash) == 0) {
+                gtk_widget_set_sensitive (GTK_WIDGET (chooser), FALSE);
+                g_warning ("Bad setup, install the freedesktop sound theme");
+                g_hash_table_destroy (hash);
+                return;
+        }
+
+        /* Setup the tree model, 3 columns:
+         * - internal theme name/directory
+         * - display theme name
+         * - the internal id for the parent theme, used for the custom theme */
+        store = gtk_list_store_new (THEME_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING);
+
+        /* Add the themes to a combobox */
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           THEME_DISPLAY_COL, _("No sounds"),
+                                           THEME_IDENTIFIER_COL, "__no_sounds",
+                                           THEME_PARENT_ID_COL, NULL,
+                                           -1);
+        g_hash_table_foreach (hash, (GHFunc) add_theme_to_store, store);
+        g_hash_table_destroy (hash);
+
+        /* Set the display */
+        gtk_combo_box_set_model (GTK_COMBO_BOX (chooser->priv->combo_box),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                    renderer,
+                                    TRUE);
+        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                        renderer,
+                                        "text", THEME_DISPLAY_COL,
+                                        NULL);
+
+        g_signal_connect (G_OBJECT (chooser->priv->combo_box),
+                          "changed",
+                          G_CALLBACK (on_combobox_changed),
+                          chooser);
+}
+
+#define GVC_SOUND_SOUND    (xmlChar *) "sound"
+#define GVC_SOUND_NAME     (xmlChar *) "name"
+#define GVC_SOUND_FILENAME (xmlChar *) "filename"
+
+/* Adapted from yelp-toc-pager.c */
+static xmlChar *
+xml_get_and_trim_names (xmlNodePtr node)
+{
+        xmlNodePtr cur;
+        xmlChar *keep_lang = NULL;
+        xmlChar *value;
+        int j, keep_pri = INT_MAX;
+
+        const gchar * const * langs = g_get_language_names ();
+
+        value = NULL;
+
+        for (cur = node->children; cur; cur = cur->next) {
+                if (! xmlStrcmp (cur->name, GVC_SOUND_NAME)) {
+                        xmlChar *cur_lang = NULL;
+                        int cur_pri = INT_MAX;
+
+                        cur_lang = xmlNodeGetLang (cur);
+
+                        if (cur_lang) {
+                                for (j = 0; langs[j]; j++) {
+                                        if (g_str_equal (cur_lang, langs[j])) {
+                                                cur_pri = j;
+                                                break;
+                                        }
+                                }
+                        } else {
+                                cur_pri = INT_MAX - 1;
+                        }
+
+                        if (cur_pri <= keep_pri) {
+                                if (keep_lang)
+                                        xmlFree (keep_lang);
+                                if (value)
+                                        xmlFree (value);
+
+                                value = xmlNodeGetContent (cur);
+
+                                keep_lang = cur_lang;
+                                keep_pri = cur_pri;
+                        } else {
+                                if (cur_lang)
+                                        xmlFree (cur_lang);
+                        }
+                }
+        }
+
+        /* Delete all GVC_SOUND_NAME nodes */
+        cur = node->children;
+        while (cur) {
+                xmlNodePtr this = cur;
+                cur = cur->next;
+                if (! xmlStrcmp (this->name, GVC_SOUND_NAME)) {
+                        xmlUnlinkNode (this);
+                        xmlFreeNode (this);
+                }
+        }
+
+        return value;
+}
+
+static void
+populate_model_from_node (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          xmlNodePtr            node)
+{
+        xmlNodePtr child;
+        xmlChar   *filename;
+        xmlChar   *name;
+
+        filename = NULL;
+        name = xml_get_and_trim_names (node);
+        for (child = node->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+
+                if (xmlStrcmp (child->name, GVC_SOUND_FILENAME) == 0) {
+                        filename = xmlNodeGetContent (child);
+                } else if (xmlStrcmp (child->name, GVC_SOUND_NAME) == 0) {
+                        /* EH? should have been trimmed */
+                }
+        }
+
+        if (filename != NULL && name != NULL) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   ALERT_IDENTIFIER_COL, filename,
+                                                   ALERT_DISPLAY_COL, name,
+                                                   ALERT_SOUND_TYPE_COL, _("Built-in"),
+                                                   ALERT_ACTIVE_COL, FALSE,
+                                                   -1);
+        }
+
+        xmlFree (filename);
+        xmlFree (name);
+}
+
+static void
+populate_model_from_file (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          const char           *filename)
+{
+        xmlDocPtr  doc;
+        xmlNodePtr root;
+        xmlNodePtr child;
+        gboolean   exists;
+
+        exists = g_file_test (filename, G_FILE_TEST_EXISTS);
+        if (! exists) {
+                return;
+        }
+
+        doc = xmlParseFile (filename);
+        if (doc == NULL) {
+                return;
+        }
+
+        root = xmlDocGetRootElement (doc);
+
+        for (child = root->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+                if (xmlStrcmp (child->name, GVC_SOUND_SOUND) != 0) {
+                        continue;
+                }
+
+                populate_model_from_node (chooser, model, child);
+        }
+
+        xmlFreeDoc (doc);
+}
+
+static void
+populate_model_from_dir (GvcSoundThemeChooser *chooser,
+                         GtkTreeModel         *model,
+                         const char           *dirname)
+{
+        GDir       *d;
+        const char *name;
+
+        d = g_dir_open (dirname, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *path;
+
+                if (! g_str_has_suffix (name, ".xml")) {
+                        continue;
+                }
+
+                path = g_build_filename (dirname, name, NULL);
+                populate_model_from_file (chooser, model, path);
+                g_free (path);
+        }
+
+        g_dir_close (d);
+}
+
+static gboolean
+save_alert_sounds (GvcSoundThemeChooser  *chooser,
+                   const char            *id)
+{
+        const char *sounds[3] = { "bell-terminal", "bell-window-system", NULL };
+        char *path;
+
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+        } else {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+                add_custom_file (sounds, id);
+        }
+
+        /* And poke the directory so the theme gets updated */
+        path = custom_theme_dir_path (NULL);
+        if (utime (path, NULL) != 0) {
+                g_warning ("Failed to update mtime for directory '%s': %s",
+                           path, g_strerror (errno));
+        }
+        g_free (path);
+
+        return FALSE;
+}
+
+
+static void
+update_alert_model (GvcSoundThemeChooser  *chooser,
+                    const char            *id)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        gtk_tree_model_get_iter_first (model, &iter);
+        do {
+                gboolean toggled;
+                char    *this_id;
+
+                gtk_tree_model_get (model, &iter,
+                                    ALERT_IDENTIFIER_COL, &this_id,
+                                    -1);
+
+                if (strcmp (this_id, id) == 0) {
+                        toggled = TRUE;
+                } else {
+                        toggled = FALSE;
+                }
+                g_free (this_id);
+
+                gtk_list_store_set (GTK_LIST_STORE (model),
+                                    &iter,
+                                    ALERT_ACTIVE_COL, toggled,
+                                    -1);
+        } while (gtk_tree_model_iter_next (model, &iter));
+}
+
+static void
+update_alert (GvcSoundThemeChooser *chooser,
+              const char           *alert_id)
+{
+        GtkTreeModel *theme_model;
+        GtkTreeIter   iter;
+        char         *theme;
+        char         *parent;
+        gboolean      is_custom;
+        gboolean      is_default;
+        gboolean      add_custom;
+        gboolean      remove_custom;
+
+        theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        /* Get the current theme's name, and set the parent */
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        gtk_tree_model_get (theme_model, &iter,
+                            THEME_IDENTIFIER_COL, &theme,
+                            THEME_IDENTIFIER_COL, &parent,
+                            -1);
+        is_custom = strcmp (theme, CUSTOM_THEME_NAME) == 0;
+        is_default = strcmp (alert_id, DEFAULT_ALERT_ID) == 0;
+
+        /* So a few possibilities:
+         * 1. Named theme, default alert selected: noop
+         * 2. Named theme, alternate alert selected: create new custom with sound
+         * 3. Custom theme, default alert selected: remove sound and possibly custom
+         * 4. Custom theme, alternate alert selected: update custom sound
+         */
+        add_custom = FALSE;
+        remove_custom = FALSE;
+        if (! is_custom && is_default) {
+                /* remove custom just in case */
+                remove_custom = TRUE;
+        } else if (! is_custom && ! is_default) {
+                create_custom_theme (parent);
+                save_alert_sounds (chooser, alert_id);
+                add_custom = TRUE;
+        } else if (is_custom && is_default) {
+                save_alert_sounds (chooser, alert_id);
+                /* after removing files check if it is empty */
+                if (custom_theme_dir_is_empty ()) {
+                        remove_custom = TRUE;
+                }
+        } else if (is_custom && ! is_default) {
+                save_alert_sounds (chooser, alert_id);
+        }
+
+        if (add_custom) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (theme_model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   THEME_DISPLAY_COL, _("Custom"),
+                                                   THEME_IDENTIFIER_COL, CUSTOM_THEME_NAME,
+                                                   THEME_PARENT_ID_COL, theme,
+                                                   -1);
+                set_combox_for_theme_name (chooser, CUSTOM_THEME_NAME);
+        } else if (remove_custom) {
+                gtk_tree_model_get_iter_first (theme_model, &iter);
+                do {
+                        char *this_parent;
+
+                        gtk_tree_model_get (theme_model, &iter,
+                                            THEME_PARENT_ID_COL, &this_parent,
+                                            -1);
+                        if (this_parent != NULL && strcmp (this_parent, CUSTOM_THEME_NAME) != 0) {
+                                g_free (this_parent);
+                                gtk_list_store_remove (GTK_LIST_STORE (theme_model), &iter);
+                                break;
+                        }
+                        g_free (this_parent);
+                } while (gtk_tree_model_iter_next (theme_model, &iter));
+
+                delete_custom_theme_dir ();
+
+                set_combox_for_theme_name (chooser, parent);
+        }
+
+        update_alert_model (chooser, alert_id);
+
+        g_free (theme);
+        g_free (parent);
+}
+
+static void
+on_alert_toggled (GtkCellRendererToggle *renderer,
+                  char                  *path_str,
+                  GvcSoundThemeChooser  *chooser)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreePath  *path;
+        gboolean      toggled;
+        char         *id;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        path = gtk_tree_path_new_from_string (path_str);
+        gtk_tree_model_get_iter (model, &iter, path);
+        gtk_tree_path_free (path);
+
+        id = NULL;
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            ALERT_ACTIVE_COL, &toggled,
+                            -1);
+
+        toggled ^= 1;
+        if (toggled) {
+                update_alert (chooser, id);
+        }
+
+        g_free (id);
+}
+
+static void
+play_preview_for_path (GvcSoundThemeChooser *chooser, GtkTreePath *path)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreeIter   theme_iter;
+        gchar        *id = NULL;
+        gchar        *parent_theme = NULL;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        if (gtk_tree_model_get_iter (model, &iter, path) == FALSE)
+                return;
+
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            -1);
+        if (id == NULL)
+                return;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &theme_iter)) {
+                GtkTreeModel *theme_model;
+                gchar        *theme_id = NULL;
+                gchar        *parent_id = NULL;
+
+                theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+                gtk_tree_model_get (theme_model, &theme_iter,
+                                    THEME_IDENTIFIER_COL, &theme_id,
+                                    THEME_PARENT_ID_COL, &parent_id, -1);
+                if (theme_id && strcmp (theme_id, CUSTOM_THEME_NAME) == 0)
+                        parent_theme = g_strdup (parent_id);
+
+                g_free (theme_id);
+                g_free (parent_id);
+        }
+
+        /* special case: for the default item on custom themes
+         * play the alert for the parent theme */
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                if (parent_theme != NULL) {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_CANBERRA_XDG_THEME_NAME, parent_theme,
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                } else {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                }
+        } else {
+                ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                        CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                        CA_PROP_MEDIA_FILENAME, id,
+                                        CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                        CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                        CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                        CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                        NULL);
+
+        }
+        g_free (parent_theme);
+        g_free (id);
+}
+
+static void
+on_treeview_row_activated (GtkTreeView          *treeview,
+                           GtkTreePath          *path,
+                           GtkTreeViewColumn    *column,
+                           GvcSoundThemeChooser *chooser)
+{
+        play_preview_for_path (chooser, path);
+}
+
+static void
+on_treeview_selection_changed (GtkTreeSelection     *selection,
+                               GvcSoundThemeChooser *chooser)
+{
+        GList        *paths;
+        GtkTreeModel *model;
+        GtkTreePath  *path;
+
+        if (chooser->priv->treeview == NULL)
+                return;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        paths = gtk_tree_selection_get_selected_rows (selection, &model);
+        if (paths == NULL)
+                return;
+
+        path = paths->data;
+        play_preview_for_path (chooser, path);
+
+        g_list_foreach (paths, (GFunc)gtk_tree_path_free, NULL);
+        g_list_free (paths);
+}
+
+static GtkWidget *
+create_alert_treeview (GvcSoundThemeChooser *chooser)
+{
+        GtkListStore         *store;
+        GtkWidget            *treeview;
+        GtkCellRenderer      *renderer;
+        GtkTreeViewColumn    *column;
+        GtkTreeSelection     *selection;
+
+        treeview = gtk_tree_view_new ();
+
+        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
+        g_signal_connect (G_OBJECT (treeview),
+                          "row-activated",
+                          G_CALLBACK (on_treeview_row_activated),
+                          chooser);
+
+        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+        gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+        g_signal_connect (G_OBJECT (selection),
+                          "changed",
+                          G_CALLBACK (on_treeview_selection_changed),
+                          chooser);
+
+        /* Setup the tree model, 3 columns:
+         * - display name
+         * - sound id
+         * - sound type
+         */
+        store = gtk_list_store_new (ALERT_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_BOOLEAN);
+
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           ALERT_IDENTIFIER_COL, DEFAULT_ALERT_ID,
+                                           ALERT_DISPLAY_COL, _("Default"),
+                                           ALERT_SOUND_TYPE_COL, _("From theme"),
+                                           ALERT_ACTIVE_COL, TRUE,
+                                           -1);
+
+        populate_model_from_dir (chooser, GTK_TREE_MODEL (store), SOUND_SET_DIR);
+
+        gtk_tree_view_set_model (GTK_TREE_VIEW (treeview),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_toggle_new ();
+        gtk_cell_renderer_toggle_set_radio (GTK_CELL_RENDERER_TOGGLE (renderer), TRUE);
+
+        column = gtk_tree_view_column_new_with_attributes (NULL,
+                                                           renderer,
+                                                           "active", ALERT_ACTIVE_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+        g_signal_connect (renderer,
+                          "toggled",
+                          G_CALLBACK (on_alert_toggled),
+                          chooser);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Name"),
+                                                           renderer,
+                                                           "text", ALERT_DISPLAY_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Type"),
+                                                           renderer,
+                                                           "text", ALERT_SOUND_TYPE_COL,
+                                                           NULL);
+
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        return treeview;
+}
+
+static int
+get_file_type (const char *sound_name,
+               char      **linked_name)
+{
+        char *name, *filename;
+
+        *linked_name = NULL;
+
+        name = g_strdup_printf ("%s.disabled", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_REGULAR) != FALSE) {
+                g_free (filename);
+                return SOUND_TYPE_OFF;
+        }
+        g_free (filename);
+
+        /* We only check for .ogg files because those are the
+         * only ones we create */
+        name = g_strdup_printf ("%s.ogg", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_SYMLINK) != FALSE) {
+                *linked_name = g_file_read_link (filename, NULL);
+                g_free (filename);
+                return SOUND_TYPE_CUSTOM;
+        }
+        g_free (filename);
+
+        return SOUND_TYPE_BUILTIN;
+}
+
+static void
+update_alerts_from_theme_name (GvcSoundThemeChooser *chooser,
+                               const gchar          *name)
+{
+        if (strcmp (name, CUSTOM_THEME_NAME) != 0) {
+                /* reset alert to default */
+                update_alert (chooser, DEFAULT_ALERT_ID);
+        } else {
+                int   sound_type;
+                char *linkname;
+
+                linkname = NULL;
+                sound_type = get_file_type ("bell-terminal", &linkname);
+                g_debug ("Found link: %s", linkname);
+                if (sound_type == SOUND_TYPE_CUSTOM) {
+                        update_alert (chooser, linkname);
+                }
+        }
+}
+
+static void
+update_theme (GvcSoundThemeChooser *chooser)
+{
+        char        *theme_name;
+        gboolean     events_enabled;
+        gboolean     feedback_enabled;
+
+        feedback_enabled = g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY);
+        set_input_feedback_enabled (chooser, feedback_enabled);
+
+        events_enabled = g_settings_get_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY);
+        if (events_enabled) {
+                theme_name = g_settings_get_string (chooser->priv->sound_settings, SOUND_THEME_KEY);
+        } else {
+                theme_name = g_strdup (NO_SOUNDS_THEME_NAME);
+        }
+
+        gtk_widget_set_sensitive (chooser->priv->selection_box, events_enabled);
+        gtk_widget_set_sensitive (chooser->priv->click_feedback_button, events_enabled);
+
+        set_combox_for_theme_name (chooser, theme_name);
+
+        update_alerts_from_theme_name (chooser, theme_name);
+
+        g_free (theme_name);
+}
+
+static void
+gvc_sound_theme_chooser_class_init (GvcSoundThemeChooserClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_sound_theme_chooser_dispose;
+}
+
+static void
+on_click_feedback_toggled (GtkToggleButton      *button,
+                           GvcSoundThemeChooser *chooser)
+{
+        gboolean enabled;
+
+        enabled = gtk_toggle_button_get_active (button);
+
+        g_settings_set_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY, enabled);
+}
+
+static void
+on_key_changed (GSettings            *settings,
+                gchar                *key,
+                GvcSoundThemeChooser *chooser)
+{
+        if (!strcmp (key, EVENT_SOUNDS_KEY) ||
+            !strcmp (key, SOUND_THEME_KEY) ||
+            !strcmp (key, INPUT_SOUNDS_KEY))
+                update_theme (chooser);
+}
+
+static void
+setup_list_size_constraint (GtkWidget *widget,
+                            GtkWidget *to_size)
+{
+        GtkRequisition req;
+        gint           sc_height;
+        int            max_height;
+
+        /* Constrain height to be the tree height up to a max */
+        gdk_window_get_geometry (gdk_screen_get_root_window (gtk_widget_get_screen (widget)),
+                                 NULL, NULL, NULL, &sc_height);
+
+        max_height = sc_height / 4;
+
+        // XXX this doesn't work
+        gtk_widget_get_preferred_size (to_size, NULL, &req);
+
+        gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (widget),
+                                                    MIN (req.height, max_height));
+}
+
+static void
+gvc_sound_theme_chooser_init (GvcSoundThemeChooser *chooser)
+{
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *scrolled_window;
+        gchar       *str;
+
+        chooser->priv = gvc_sound_theme_chooser_get_instance_private (chooser);
+
+        chooser->priv->theme_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->theme_box, FALSE, FALSE, 0);
+
+        label = gtk_label_new_with_mnemonic (_("Sound _theme:"));
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), label, FALSE, FALSE, 0);
+        chooser->priv->combo_box = gtk_combo_box_new ();
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), chooser->priv->combo_box, FALSE, FALSE, 6);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->combo_box);
+
+        chooser->priv->sound_settings = g_settings_new (KEY_SOUNDS_SCHEMA);
+
+        g_signal_connect (G_OBJECT (chooser->priv->sound_settings),
+                          "changed",
+                          G_CALLBACK (on_key_changed),
+                          chooser);
+
+        str = g_strdup_printf ("<b>%s</b>", _("C_hoose an alert sound:"));
+        chooser->priv->selection_box = box = gtk_frame_new (str);
+        g_free (str);
+
+        label = gtk_frame_get_label_widget (GTK_FRAME (box));
+        gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
+        gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+        gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
+
+        gtk_box_pack_start (GTK_BOX (chooser), box, TRUE, TRUE, 6);
+
+        chooser->priv->treeview = create_alert_treeview (chooser);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->treeview);
+
+        scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+        gtk_widget_set_hexpand (scrolled_window, TRUE);
+        gtk_widget_set_vexpand (scrolled_window, TRUE);
+        gtk_widget_set_margin_top (scrolled_window, 6);
+
+        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+                                        GTK_POLICY_NEVER,
+                                        GTK_POLICY_AUTOMATIC);
+        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
+                                             GTK_SHADOW_IN);
+
+        gtk_container_add (GTK_CONTAINER (scrolled_window), chooser->priv->treeview);
+        gtk_container_add (GTK_CONTAINER (box), scrolled_window);
+
+        chooser->priv->click_feedback_button = gtk_check_button_new_with_mnemonic (_("Enable _window and button sounds"));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY));
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->click_feedback_button,
+                            FALSE, FALSE, 0);
+
+        g_signal_connect (G_OBJECT (chooser->priv->click_feedback_button),
+                          "toggled",
+                          G_CALLBACK (on_click_feedback_toggled),
+                          chooser);
+
+        setup_theme_selector (chooser);
+        update_theme (chooser);
+
+        setup_list_size_constraint (scrolled_window, chooser->priv->treeview);
+}
+
+static void
+gvc_sound_theme_chooser_dispose (GObject *object)
+{
+        GvcSoundThemeChooser *chooser;
+
+        chooser = GVC_SOUND_THEME_CHOOSER (object);
+
+        g_clear_object (&chooser->priv->sound_settings);
+
+        G_OBJECT_CLASS (gvc_sound_theme_chooser_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_sound_theme_chooser_new (void)
+{
+        return g_object_new (GVC_TYPE_SOUND_THEME_CHOOSER,
+                                "spacing", 6,
+                                "orientation", GTK_ORIENTATION_VERTICAL,
+                                NULL);
+}
+
+
+
+ + + diff --git a/2020-04-21-012601-6120-cppcheck@11fc77a34034_travis/2.html b/2020-04-21-012601-6120-cppcheck@11fc77a34034_travis/2.html new file mode 100644 index 0000000..bacfabb --- /dev/null +++ b/2020-04-21-012601-6120-cppcheck@11fc77a34034_travis/2.html @@ -0,0 +1,1110 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <canberra.h>
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-speaker-test.h"
+#include "gvc-utils.h"
+
+struct _GvcSpeakerTestPrivate
+{
+        GArray           *controls;
+        ca_context       *canberra;
+        MateMixerStream  *stream;
+};
+
+enum {
+        PROP_0,
+        PROP_STREAM,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_speaker_test_dispose    (GObject             *object);
+static void gvc_speaker_test_finalize   (GObject             *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSpeakerTest, gvc_speaker_test, GTK_TYPE_GRID)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+typedef struct {
+        MateMixerChannelPosition position;
+        guint left;
+        guint top;
+} TablePosition;
+
+static const TablePosition positions[] = {
+        /* Position, X, Y */
+        { MATE_MIXER_CHANNEL_FRONT_LEFT, 0, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_LEFT_CENTER, 1, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_CENTER, 2, 0, },
+        { MATE_MIXER_CHANNEL_MONO, 2, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT_CENTER, 3, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT, 4, 0, },
+        { MATE_MIXER_CHANNEL_SIDE_LEFT, 0, 1, },
+        { MATE_MIXER_CHANNEL_SIDE_RIGHT, 4, 1, },
+        { MATE_MIXER_CHANNEL_BACK_LEFT, 0, 2, },
+        { MATE_MIXER_CHANNEL_BACK_CENTER, 2, 2, },
+        { MATE_MIXER_CHANNEL_BACK_RIGHT, 4, 2, },
+        { MATE_MIXER_CHANNEL_LFE, 3, 2 }
+};
+
+MateMixerStream *
+gvc_speaker_test_get_stream (GvcSpeakerTest *test)
+{
+        g_return_val_if_fail (GVC_IS_SPEAKER_TEST (test), NULL);
+
+        return test->priv->stream;
+}
+
+static void
+gvc_speaker_test_set_stream (GvcSpeakerTest *test, MateMixerStream *stream)
+{
+        MateMixerStreamControl *control;
+        const gchar            *name;
+        guint                   i;
+
+        name = mate_mixer_stream_get_name (stream);
+        control = mate_mixer_stream_get_default_control (stream);
+
+        ca_context_change_device (test->priv->canberra, name);
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                gboolean has_position =
+                        mate_mixer_stream_control_has_channel_position (control, positions[i].position);
+
+                gtk_widget_set_visible (g_array_index (test->priv->controls, GtkWidget *, i),
+                                        has_position);
+        }
+
+        test->priv->stream = g_object_ref (stream);
+}
+
+static void
+gvc_speaker_test_set_property (GObject       *object,
+                               guint          prop_id,
+                               const GValue  *value,
+                               GParamSpec    *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                gvc_speaker_test_set_stream (self, g_value_get_object (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_get_property (GObject     *object,
+                               guint        prop_id,
+                               GValue      *value,
+                               GParamSpec  *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                g_value_set_object (value, self->priv->stream);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_class_init (GvcSpeakerTestClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose  = gvc_speaker_test_dispose;
+        object_class->finalize = gvc_speaker_test_finalize;
+        object_class->set_property = gvc_speaker_test_set_property;
+        object_class->get_property = gvc_speaker_test_get_property;
+
+        properties[PROP_STREAM] =
+                g_param_spec_object ("stream",
+                                     "Stream",
+                                     "MateMixer stream",
+                                     MATE_MIXER_TYPE_STREAM,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+}
+
+static const gchar *
+sound_name (MateMixerChannelPosition position)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return "audio-channel-front-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return "audio-channel-front-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return "audio-channel-front-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return "audio-channel-rear-left";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return "audio-channel-rear-right";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return "audio-channel-rear-center";
+        case MATE_MIXER_CHANNEL_LFE:
+                return "audio-channel-lfe";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return "audio-channel-side-left";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return "audio-channel-side-right";
+        default:
+                return NULL;
+        }
+}
+
+static const gchar *
+icon_name (MateMixerChannelPosition position, gboolean playing)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return playing
+                        ? "audio-speaker-left-testing"
+                        : "audio-speaker-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return playing
+                        ? "audio-speaker-right-testing"
+                        : "audio-speaker-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return playing
+                        ? "audio-speaker-center-testing"
+                        : "audio-speaker-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return playing
+                        ? "audio-speaker-left-back-testing"
+                        : "audio-speaker-left-back";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return playing
+                        ? "audio-speaker-right-back-testing"
+                        : "audio-speaker-right-back";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return playing
+                        ? "audio-speaker-center-back-testing"
+                        : "audio-speaker-center-back";
+        case MATE_MIXER_CHANNEL_LFE:
+                return playing
+                        ? "audio-subwoofer-testing"
+                        : "audio-subwoofer";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return playing
+                        ? "audio-speaker-left-side-testing"
+                        : "audio-speaker-left-side";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return playing
+                        ? "audio-speaker-right-side-testing"
+                        : "audio-speaker-right-side";
+        default:
+                return NULL;
+        }
+}
+
+static void
+update_button (GtkWidget *control)
+{
+        GtkWidget *button;
+        GtkWidget *image;
+        gboolean   playing;
+        MateMixerChannelPosition position;
+
+        button = g_object_get_data (G_OBJECT (control), "button");
+        image  = g_object_get_data (G_OBJECT (control), "image");
+
+        position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+        playing  = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        gtk_button_set_label (GTK_BUTTON (button), playing ? _("Stop") : _("Test"));
+
+        gtk_image_set_from_icon_name (GTK_IMAGE (image),
+                                      icon_name (position, playing),
+                                      GTK_ICON_SIZE_DIALOG);
+}
+
+static gboolean
+idle_cb (GtkWidget *control)
+{
+        if (control != NULL) {
+                /* This is called in the background thread, hence forward to main thread
+                 * via idle callback */
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+
+                update_button (control);
+        }
+        return FALSE;
+}
+
+static void
+finish_cb (ca_context *c, uint32_t id, int error_code, void *userdata)
+{
+        GtkWidget *control = (GtkWidget *) userdata;
+
+        if (error_code == CA_ERROR_DESTROYED || control == NULL)
+                return;
+
+        g_idle_add ((GSourceFunc) idle_cb, control);
+}
+
+static void
+on_test_button_clicked (GtkButton *button, GtkWidget *control)
+{
+        gboolean    playing;
+        ca_context *canberra;
+
+        canberra = g_object_get_data (G_OBJECT (control), "canberra");
+
+        ca_context_cancel (canberra, 1);
+
+        playing = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        if (playing) {
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        } else {
+                MateMixerChannelPosition position;
+                const gchar *name;
+                ca_proplist *proplist;
+
+                position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+
+                ca_proplist_create (&proplist);
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_ROLE, "test");
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_NAME,
+                                  gvc_channel_position_to_pretty_string (position));
+                ca_proplist_sets (proplist,
+                                  CA_PROP_CANBERRA_FORCE_CHANNEL,
+                                  gvc_channel_position_to_pulse_string (position));
+
+                ca_proplist_sets (proplist, CA_PROP_CANBERRA_ENABLE, "1");
+
+                name = sound_name (position);
+                if (name != NULL) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, name);
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, "audio-test-signal");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets(proplist, CA_PROP_EVENT_ID, "bell-window-system");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (playing));
+        }
+
+        update_button (control);
+}
+
+static GtkWidget *
+create_control (ca_context *canberra, MateMixerChannelPosition position)
+{
+        GtkWidget   *control;
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *image;
+        GtkWidget   *test_button;
+        const gchar *name;
+
+        control = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+        box     = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        g_object_set_data (G_OBJECT (control), "position", GINT_TO_POINTER (position));
+        g_object_set_data (G_OBJECT (control), "canberra", canberra);
+
+        name = icon_name (position, FALSE);
+        if (name == NULL)
+                name = "audio-volume-medium";
+
+        image = gtk_image_new_from_icon_name (name, GTK_ICON_SIZE_DIALOG);
+        g_object_set_data (G_OBJECT (control), "image", image);
+        gtk_box_pack_start (GTK_BOX (control), image, FALSE, FALSE, 0);
+
+        label = gtk_label_new (gvc_channel_position_to_pretty_string (position));
+        gtk_box_pack_start (GTK_BOX (control), label, FALSE, FALSE, 0);
+
+        test_button = gtk_button_new_with_label (_("Test"));
+        g_signal_connect (G_OBJECT (test_button),
+                          "clicked",
+                          G_CALLBACK (on_test_button_clicked),
+                          control);
+
+        g_object_set_data (G_OBJECT (control), "button", test_button);
+
+        gtk_box_pack_start (GTK_BOX (box), test_button, TRUE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (control), box, FALSE, FALSE, 0);
+
+        gtk_widget_show_all (control);
+
+        return control;
+}
+
+static void
+create_controls (GvcSpeakerTest *test)
+{
+        guint i;
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                GtkWidget *control = create_control (test->priv->canberra, positions[i].position);
+
+                gtk_grid_attach (GTK_GRID (test),
+                                 control,
+                                 positions[i].left,
+                                 positions[i].top,
+                                 1, 1);
+                g_array_insert_val (test->priv->controls, i, control);
+        }
+}
+
+static void
+gvc_speaker_test_init (GvcSpeakerTest *test)
+{
+        GtkWidget *face;
+
+        test->priv = gvc_speaker_test_get_instance_private (test);
+
+        gtk_container_set_border_width (GTK_CONTAINER (test), 12);
+
+        face = gtk_image_new_from_icon_name ("face-smile", GTK_ICON_SIZE_DIALOG);
+
+        gtk_grid_attach (GTK_GRID (test),
+                         face,
+                         1, 1,
+                         3, 1);
+
+
+        gtk_grid_set_baseline_row (GTK_GRID (test), 1);
+        gtk_widget_show (face);
+
+        ca_context_create (&test->priv->canberra);
+
+        /* The test sounds are played for a single channel, set up using the
+         * FORCE_CHANNEL property of libcanberra; this property is only supported
+         * in the PulseAudio backend, so avoid other backends completely */
+        ca_context_set_driver (test->priv->canberra, "pulse");
+
+        ca_context_change_props (test->priv->canberra,
+                                 CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+                                 CA_PROP_APPLICATION_NAME, _("Volume Control"),
+                                 CA_PROP_APPLICATION_VERSION, VERSION,
+                                 CA_PROP_APPLICATION_ICON_NAME, "multimedia-volume-control",
+                                 NULL);
+
+        test->priv->controls = g_array_new (FALSE, FALSE, sizeof (GtkWidget *));
+
+        create_controls (test);
+}
+
+static void
+gvc_speaker_test_dispose (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        g_clear_object (&test->priv->stream);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->dispose (object);
+}
+
+static void
+gvc_speaker_test_finalize (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        ca_context_destroy (test->priv->canberra);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->finalize (object);
+}
+
+GtkWidget *
+gvc_speaker_test_new (MateMixerStream *stream)
+{
+        GObject *test;
+
+        g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL);
+
+        test = g_object_new (GVC_TYPE_SPEAKER_TEST,
+                             "row-spacing", 6,
+                             "column-spacing", 6,
+                             "row-homogeneous", TRUE,
+                             "column-homogeneous", TRUE,
+                             "stream", stream,
+                             NULL);
+
+        return GTK_WIDGET (test);
+}
+
+
+
+ + + diff --git a/2020-04-21-012601-6120-cppcheck@11fc77a34034_travis/index.html b/2020-04-21-012601-6120-cppcheck@11fc77a34034_travis/index.html new file mode 100644 index 0000000..59baeb0 --- /dev/null +++ b/2020-04-21-012601-6120-cppcheck@11fc77a34034_travis/index.html @@ -0,0 +1,108 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
mate-volume-control/gvc-combo-box.c
70unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
mate-volume-control/gvc-sound-theme-chooser.c
735ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
746ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
758ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
mate-volume-control/gvc-speaker-test.c
53unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+ + + diff --git a/2020-04-21-012601-6120-cppcheck@11fc77a34034_travis/stats.html b/2020-04-21-012601-6120-cppcheck@11fc77a34034_travis/stats.html new file mode 100644 index 0000000..3fb6add --- /dev/null +++ b/2020-04-21-012601-6120-cppcheck@11fc77a34034_travis/stats.html @@ -0,0 +1,93 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+

Top 10 files for error severity, total findings: 2
+   1  mate-volume-control/gvc-speaker-test.c
+   1  mate-volume-control/gvc-combo-box.c
+

+

Top 10 files for information severity, total findings: 3
+   3  mate-volume-control/gvc-sound-theme-chooser.c
+

+ +
+ + + diff --git a/2020-04-21-012601-6120-cppcheck@11fc77a34034_travis/style.css b/2020-04-21-012601-6120-cppcheck@11fc77a34034_travis/style.css new file mode 100644 index 0000000..c39571c --- /dev/null +++ b/2020-04-21-012601-6120-cppcheck@11fc77a34034_travis/style.css @@ -0,0 +1,149 @@ + +body { + font: 13px Arial, Verdana, Sans-Serif; + margin: 0; + width: auto; +} + +h1 { + margin: 10px; +} + +#footer > p { + margin: 4px; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + border: 1px dotted black; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #B6B6B4; +} + +.inconclusive2 { + background-color: #B6B6B4; + border: 1px dotted black; + display: inline-block; + margin-left: 4px; +} + +div.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +div.verbose div.content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid black; + background-color: #FFFFCC; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +#header { + border-bottom: thin solid #aaa; +} + +#menu { + float: left; + margin-top: 5px; + text-align: left; + width: 150px; + /*height: 75%;*/ + position: fixed; + overflow: auto; + z-index: 1; +} + +#menu_index { + float: left; + margin-top: 5px; + padding-left: 5px; + text-align: left; + width: 300px; + /*height: 75%;*/ + position: fixed; + overflow: auto; + z-index: 1; +} + +#menu > a { + display: block; + margin-left: 10px; + font: 12px; + z-index: 1; +} + +#filename { + margin-left: 10px; + font: 12px; + z-index: 1; +} + +.highlighttable { + background-color:white; + z-index: 10; + position: relative; + margin: -10 px; +} + +#content { + background-color: white; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + float: left; + margin: 5px; + margin-left: 10px; + padding: 0 10px 10px 10px; + width: 80%; + padding-left: 150px; +} + +#content_index { + background-color: white; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + float: left; + margin: 5px; + margin-left: 10px; + padding: 0 10px 10px 10px; + width: 80%; + padding-left: 300px; +} + +.linenos { + border-right: thin solid #aaa; + color: lightgray; + padding-right: 6px; +} + +#footer { + border-top: thin solid #aaa; + clear: both; + font-size: 90%; + margin-top: 5px; +} + +#footer ul { + list-style-type: none; + padding-left: 0; +} diff --git a/2020-04-21-013643-7310-cppcheck@85e50bb1e8b0_master/0.html b/2020-04-21-013643-7310-cppcheck@85e50bb1e8b0_master/0.html new file mode 100644 index 0000000..e262ed0 --- /dev/null +++ b/2020-04-21-013643-7310-cppcheck@85e50bb1e8b0_master/0.html @@ -0,0 +1,1038 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-combo-box.h"
+
+struct _GvcComboBoxPrivate
+{
+        GtkWidget       *drop_box;
+        GtkWidget       *start_box;
+        GtkWidget       *end_box;
+        GtkWidget       *label;
+        GtkWidget       *button;
+        GtkTreeModel    *model;
+        GtkWidget       *combobox;
+        MateMixerSwitch *swtch;
+};
+
+enum {
+        COL_NAME,
+        COL_HUMAN_NAME,
+        NUM_COLS
+};
+
+enum {
+        CHANGING,
+        BUTTON_CLICKED,
+        LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+enum {
+        PROP_0,
+        PROP_SWITCH,
+        PROP_LABEL,
+        PROP_SHOW_BUTTON,
+        PROP_BUTTON_LABEL,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_combo_box_dispose    (GObject          *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcComboBox, gvc_combo_box, GTK_TYPE_BOX)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+MateMixerSwitch *
+gvc_combo_box_get_switch (GvcComboBox *combobox)
+{
+        g_return_val_if_fail (GVC_IS_COMBO_BOX (combobox), NULL);
+
+        return combobox->priv->swtch;
+}
+
+void
+gvc_combo_box_set_size_group (GvcComboBox  *combobox,
+                              GtkSizeGroup *group,
+                              gboolean      symmetric)
+{
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (GTK_IS_SIZE_GROUP (group));
+
+        if (group != NULL) {
+                gtk_size_group_add_widget (group, combobox->priv->start_box);
+                if (symmetric == TRUE)
+                        gtk_size_group_add_widget (group, combobox->priv->end_box);
+        }
+        gtk_widget_queue_draw (GTK_WIDGET (combobox));
+}
+
+static void
+on_switch_active_option_notify (MateMixerSwitch *swtch,
+                                GParamSpec      *pspec,
+                                GvcComboBox     *combobox)
+{
+        GtkTreeIter            iter;
+        MateMixerSwitchOption *active;
+        gboolean               cont;
+        const gchar           *name;
+
+        active = mate_mixer_switch_get_active_option (swtch);
+        if (G_UNLIKELY (active == NULL)) {
+                g_warn_if_reached ();
+                return;
+        }
+
+        /* Select the newly activated switch option in the combo box */
+        name = mate_mixer_switch_option_get_name (active);
+        cont = gtk_tree_model_get_iter_first (combobox->priv->model, &iter);
+        while (cont == TRUE) {
+                gchar *current;
+
+                gtk_tree_model_get (combobox->priv->model, &iter,
+                                    COL_NAME, &current,
+                                    -1);
+                if (g_strcmp0 (name, current) == 0) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox), &iter);
+                        g_free (current);
+                        return;
+                }
+                g_free (current);
+
+                cont = gtk_tree_model_iter_next (combobox->priv->model, &iter);
+        }
+        g_warning ("Could not find switch option '%s' in combo box", name);
+}
+
+static void
+gvc_combo_box_set_switch (GvcComboBox *combobox, MateMixerSwitch *swtch)
+{
+        MateMixerSwitchOption *active;
+        const GList           *options;
+
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (MATE_MIXER_IS_SWITCH (swtch));
+
+        combobox->priv->swtch = g_object_ref (swtch);
+
+        active  = mate_mixer_switch_get_active_option (swtch);
+        options = mate_mixer_switch_list_options (swtch);
+        while (options != NULL) {
+                GtkTreeIter            iter;
+                MateMixerSwitchOption *option = MATE_MIXER_SWITCH_OPTION (options->data);
+
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (combobox->priv->model),
+                                                   &iter,
+                                                   G_MAXINT,
+                                                   COL_NAME,
+                                                   mate_mixer_switch_option_get_name (option),
+                                                   COL_HUMAN_NAME,
+                                                   mate_mixer_switch_option_get_label (option),
+                                                   -1);
+
+                /* Select the currently active option of the switch */
+                if (option == active) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox),
+                                                       &iter);
+                }
+                options = options->next;
+        }
+
+        g_signal_connect (G_OBJECT (swtch),
+                          "notify::active-option",
+                          G_CALLBACK (on_switch_active_option_notify),
+                          combobox);
+}
+
+static void
+gvc_combo_box_set_property (GObject       *object,
+                            guint          prop_id,
+                            const GValue  *value,
+                            GParamSpec    *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                gvc_combo_box_set_switch (self, g_value_get_object (value));
+                break;
+        case PROP_LABEL:
+                gtk_label_set_text_with_mnemonic (GTK_LABEL (self->priv->label), g_value_get_string (value));
+                break;
+        case PROP_BUTTON_LABEL:
+                gtk_button_set_label (GTK_BUTTON (self->priv->button), g_value_get_string (value));
+                break;
+        case PROP_SHOW_BUTTON:
+                gtk_widget_set_visible (self->priv->button, g_value_get_boolean (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_get_property (GObject     *object,
+                            guint        prop_id,
+                            GValue      *value,
+                            GParamSpec  *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                g_value_set_object (value, self->priv->swtch);
+                break;
+        case PROP_LABEL:
+                g_value_set_string (value, gtk_label_get_text (GTK_LABEL (self->priv->label)));
+                break;
+        case PROP_BUTTON_LABEL:
+                g_value_set_string (value, gtk_button_get_label (GTK_BUTTON (self->priv->button)));
+                break;
+        case PROP_SHOW_BUTTON:
+                g_value_set_boolean (value, gtk_widget_get_visible (self->priv->button));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_class_init (GvcComboBoxClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_combo_box_dispose;
+        object_class->set_property = gvc_combo_box_set_property;
+        object_class->get_property = gvc_combo_box_get_property;
+
+        properties[PROP_SWITCH] =
+                g_param_spec_object ("switch",
+                                     "switch",
+                                     "The MateMixerSwitch",
+                                     MATE_MIXER_TYPE_SWITCH,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_LABEL] =
+                g_param_spec_string ("label",
+                                     "label",
+                                     "The combo box label",
+                                     _("_Profile:"),
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_SHOW_BUTTON] =
+                g_param_spec_boolean ("show-button",
+                                      "show-button",
+                                      "Whether to show the button",
+                                      FALSE,
+                                      G_PARAM_READWRITE |
+                                      G_PARAM_CONSTRUCT |
+                                      G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_BUTTON_LABEL] =
+                g_param_spec_string ("button-label",
+                                     "button-label",
+                                     "The button's label",
+                                     "",
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+
+        signals[CHANGING] =
+                g_signal_new ("changing",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, changing),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__OBJECT,
+                              G_TYPE_NONE,
+                              1,
+                              MATE_MIXER_TYPE_SWITCH_OPTION);
+
+        signals[BUTTON_CLICKED] =
+                g_signal_new ("button-clicked",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, button_clicked),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
+}
+
+static void
+on_combo_box_changed (GtkComboBox *widget, GvcComboBox *combobox)
+{
+        GtkTreeIter            iter;
+        gchar                 *name;
+        MateMixerSwitchOption *option;
+
+        if (G_UNLIKELY (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter) == FALSE))
+                return;
+
+        gtk_tree_model_get (combobox->priv->model, &iter,
+                            COL_NAME, &name,
+                            -1);
+
+        option = mate_mixer_switch_get_option (combobox->priv->swtch, name);
+        if (G_UNLIKELY (option == NULL)) {
+                g_warn_if_reached ();
+                g_free (name);
+                return;
+        }
+
+        /* Inform that we are about to change the active option of the switch */
+        g_signal_emit (combobox, signals[CHANGING], 0, option);
+
+        mate_mixer_switch_set_active_option (combobox->priv->swtch, option);
+        g_free (name);
+}
+
+static void
+on_combo_box_button_clicked (GtkButton *button, GvcComboBox *combobox)
+{
+        /* The meaning of the button is defined by the owner, so only notify
+         * when it is clicked on */
+        g_signal_emit (combobox, signals[BUTTON_CLICKED], 0);
+}
+
+static void
+gvc_combo_box_init (GvcComboBox *combobox)
+{
+        GtkWidget       *frame;
+        GtkCellRenderer *renderer;
+
+        frame = gtk_frame_new (NULL);
+        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
+
+        combobox->priv = gvc_combo_box_get_instance_private (combobox);
+
+        combobox->priv->model = GTK_TREE_MODEL (gtk_list_store_new (NUM_COLS,
+                                                                    G_TYPE_STRING,
+                                                                    G_TYPE_STRING));
+
+        combobox->priv->combobox = gtk_combo_box_new_with_model (combobox->priv->model);
+
+        combobox->priv->label = gtk_label_new (NULL);
+
+        gtk_label_set_xalign (GTK_LABEL (combobox->priv->label), 0.0);
+        gtk_label_set_yalign (GTK_LABEL (combobox->priv->label), 0.5);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (combobox->priv->label),
+                                       combobox->priv->combobox);
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                    renderer,
+                                    FALSE);
+        gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                       renderer,
+                                       "text",
+                                       COL_HUMAN_NAME);
+
+        combobox->priv->drop_box  = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->start_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->end_box   = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+        /* Make sure the combo box does not get too long on long profile names */
+        g_object_set (G_OBJECT (renderer),
+                      "ellipsize",
+                      PANGO_ELLIPSIZE_END,
+                      NULL);
+
+        gtk_combo_box_set_popup_fixed_width (GTK_COMBO_BOX (combobox->priv->combobox), FALSE);
+
+        gtk_box_pack_start (GTK_BOX (combobox),
+                            frame,
+                            TRUE, TRUE, 0);
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->start_box,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->start_box),
+                            combobox->priv->label,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->combobox,
+                            TRUE, TRUE, 0);
+
+        combobox->priv->button = gtk_button_new_with_label ("");
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->button,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->end_box,
+                            FALSE, FALSE, 0);
+
+        gtk_container_add (GTK_CONTAINER (frame), combobox->priv->drop_box);
+
+        g_signal_connect (G_OBJECT (combobox->priv->combobox),
+                          "changed",
+                          G_CALLBACK (on_combo_box_changed),
+                          combobox);
+        g_signal_connect (G_OBJECT (combobox->priv->button),
+                          "clicked",
+                          G_CALLBACK (on_combo_box_button_clicked),
+                          combobox);
+
+        gtk_widget_set_no_show_all (combobox->priv->button, TRUE);
+        gtk_widget_show_all (frame);
+}
+
+static void
+gvc_combo_box_dispose (GObject *object)
+{
+        GvcComboBox *combobox;
+
+        combobox = GVC_COMBO_BOX (object);
+
+        if (G_LIKELY (combobox->priv->swtch != NULL)) {
+                g_signal_handlers_disconnect_by_func (G_OBJECT (combobox->priv->swtch),
+                                                      G_CALLBACK (on_switch_active_option_notify),
+                                                      combobox);
+                g_clear_object (&combobox->priv->swtch);
+        }
+
+        g_clear_object (&combobox->priv->model);
+
+        G_OBJECT_CLASS (gvc_combo_box_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_combo_box_new (MateMixerSwitch *swtch, const gchar *label)
+{
+        return g_object_new (GVC_TYPE_COMBO_BOX,
+                             "switch", swtch,
+                             "label", label,
+                             "orientation", GTK_ORIENTATION_HORIZONTAL,
+                             NULL);
+}
+
+
+
+ + + diff --git a/2020-04-21-013643-7310-cppcheck@85e50bb1e8b0_master/1.html b/2020-04-21-013643-7310-cppcheck@85e50bb1e8b0_master/1.html new file mode 100644 index 0000000..67179f2 --- /dev/null +++ b/2020-04-21-013643-7310-cppcheck@85e50bb1e8b0_master/1.html @@ -0,0 +1,2368 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
+ * Copyright (C) 2008 William Jon McCann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <utime.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+#include <canberra-gtk.h>
+#include <libxml/tree.h>
+
+#include "gvc-sound-theme-chooser.h"
+#include "sound-theme-file-utils.h"
+
+struct GvcSoundThemeChooserPrivate
+{
+        GtkWidget *combo_box;
+        GtkWidget *treeview;
+        GtkWidget *theme_box;
+        GtkWidget *selection_box;
+        GtkWidget *click_feedback_button;
+        GSettings *sound_settings;
+};
+
+static void     gvc_sound_theme_chooser_dispose   (GObject            *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSoundThemeChooser, gvc_sound_theme_chooser, GTK_TYPE_BOX)
+
+#define KEY_SOUNDS_SCHEMA          "org.mate.sound"
+#define EVENT_SOUNDS_KEY           "event-sounds"
+#define INPUT_SOUNDS_KEY           "input-feedback-sounds"
+#define SOUND_THEME_KEY            "theme-name"
+
+#define DEFAULT_ALERT_ID        "__default"
+#define CUSTOM_THEME_NAME       "__custom"
+#define NO_SOUNDS_THEME_NAME    "__no_sounds"
+
+enum {
+        THEME_DISPLAY_COL,
+        THEME_IDENTIFIER_COL,
+        THEME_PARENT_ID_COL,
+        THEME_NUM_COLS
+};
+
+enum {
+        ALERT_DISPLAY_COL,
+        ALERT_IDENTIFIER_COL,
+        ALERT_SOUND_TYPE_COL,
+        ALERT_ACTIVE_COL,
+        ALERT_NUM_COLS
+};
+
+enum {
+        SOUND_TYPE_UNSET,
+        SOUND_TYPE_OFF,
+        SOUND_TYPE_DEFAULT_FROM_THEME,
+        SOUND_TYPE_BUILTIN,
+        SOUND_TYPE_CUSTOM
+};
+
+static void
+on_combobox_changed (GtkComboBox          *widget,
+                     GvcSoundThemeChooser *chooser)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        char         *theme_name;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &theme_name, -1);
+
+        g_assert (theme_name != NULL);
+
+        /* It is necessary to update the theme name before any other setting as
+         * the "changed" notification will reload the contents of the widget */
+        g_settings_set_string (chooser->priv->sound_settings, SOUND_THEME_KEY, theme_name);
+
+        /* special case for no sounds */
+        if (strcmp (theme_name, NO_SOUNDS_THEME_NAME) == 0) {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, FALSE);
+                return;
+        } else {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, TRUE);
+        }
+
+        g_free (theme_name);
+
+        /* FIXME: reset alert model */
+}
+
+static char *
+load_index_theme_name (const char *index,
+                       char      **parent)
+{
+        GKeyFile *file;
+        char *indexname = NULL;
+        gboolean hidden;
+
+        file = g_key_file_new ();
+        if (g_key_file_load_from_file (file, index, G_KEY_FILE_KEEP_TRANSLATIONS, NULL) == FALSE) {
+                g_key_file_free (file);
+                return NULL;
+        }
+        /* Don't add hidden themes to the list */
+        hidden = g_key_file_get_boolean (file, "Sound Theme", "Hidden", NULL);
+        if (!hidden) {
+                indexname = g_key_file_get_locale_string (file,
+                                                          "Sound Theme",
+                                                          "Name",
+                                                          NULL,
+                                                          NULL);
+
+                /* Save the parent theme, if there's one */
+                if (parent != NULL) {
+                        *parent = g_key_file_get_string (file,
+                                                         "Sound Theme",
+                                                         "Inherits",
+                                                         NULL);
+                }
+        }
+
+        g_key_file_free (file);
+        return indexname;
+}
+
+static void
+sound_theme_in_dir (GHashTable *hash,
+                    const char *dir)
+{
+        GDir *d;
+        const char *name;
+
+        d = g_dir_open (dir, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *dirname, *index, *indexname;
+
+                /* Look for directories */
+                dirname = g_build_filename (dir, name, NULL);
+                if (g_file_test (dirname, G_FILE_TEST_IS_DIR) == FALSE) {
+                        g_free (dirname);
+                        continue;
+                }
+
+                /* Look for index files */
+                index = g_build_filename (dirname, "index.theme", NULL);
+                g_free (dirname);
+
+                /* Check the name of the theme in the index.theme file */
+                indexname = load_index_theme_name (index, NULL);
+                g_free (index);
+                if (indexname == NULL) {
+                        continue;
+                }
+
+                g_hash_table_insert (hash, g_strdup (name), indexname);
+        }
+
+        g_dir_close (d);
+}
+
+static void
+add_theme_to_store (const char   *key,
+                    const char   *value,
+                    GtkListStore *store)
+{
+        char *parent;
+
+        parent = NULL;
+
+        /* Get the parent, if we're checking the custom theme */
+        if (strcmp (key, CUSTOM_THEME_NAME) == 0) {
+                char *name, *path;
+
+                path = custom_theme_dir_path ("index.theme");
+                name = load_index_theme_name (path, &parent);
+                g_free (name);
+                g_free (path);
+        }
+        gtk_list_store_insert_with_values (store, NULL, G_MAXINT,
+                                           THEME_DISPLAY_COL, value,
+                                           THEME_IDENTIFIER_COL, key,
+                                           THEME_PARENT_ID_COL, parent,
+                                           -1);
+        g_free (parent);
+}
+
+static void
+set_combox_for_theme_name (GvcSoundThemeChooser *chooser,
+                           const char           *name)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        gboolean      found;
+
+        /* If the name is empty, use "freedesktop" */
+        if (name == NULL || *name == '\0') {
+                name = "freedesktop";
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+        if (gtk_tree_model_get_iter_first (model, &iter) == FALSE) {
+                return;
+        }
+
+        do {
+                char *value;
+
+                gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &value, -1);
+                found = (value != NULL && strcmp (value, name) == 0);
+                g_free (value);
+
+        } while (!found && gtk_tree_model_iter_next (model, &iter));
+
+        /* When we can't find the theme we need to set, try to set the default
+         * one "freedesktop" */
+        if (found) {
+                gtk_combo_box_set_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter);
+        } else if (strcmp (name, "freedesktop") != 0) {
+                g_debug ("not found, falling back to fdo");
+                set_combox_for_theme_name (chooser, "freedesktop");
+        }
+}
+
+static void
+set_input_feedback_enabled (GvcSoundThemeChooser *chooser,
+                            gboolean              enabled)
+{
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      enabled);
+}
+
+static void
+setup_theme_selector (GvcSoundThemeChooser *chooser)
+{
+        GHashTable           *hash;
+        GtkListStore         *store;
+        GtkCellRenderer      *renderer;
+        const char * const   *data_dirs;
+        const char           *data_dir;
+        char                 *dir;
+        guint                 i;
+
+        /* Add the theme names and their display name to a hash table,
+         * makes it easy to avoid duplicate themes */
+        hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+        data_dirs = g_get_system_data_dirs ();
+        for (i = 0; data_dirs[i] != NULL; i++) {
+                dir = g_build_filename (data_dirs[i], "sounds", NULL);
+                sound_theme_in_dir (hash, dir);
+                g_free (dir);
+        }
+
+        data_dir = g_get_user_data_dir ();
+        dir = g_build_filename (data_dir, "sounds", NULL);
+        sound_theme_in_dir (hash, dir);
+        g_free (dir);
+
+        /* If there isn't at least one theme, make everything
+         * insensitive, LAME! */
+        if (g_hash_table_size (hash) == 0) {
+                gtk_widget_set_sensitive (GTK_WIDGET (chooser), FALSE);
+                g_warning ("Bad setup, install the freedesktop sound theme");
+                g_hash_table_destroy (hash);
+                return;
+        }
+
+        /* Setup the tree model, 3 columns:
+         * - internal theme name/directory
+         * - display theme name
+         * - the internal id for the parent theme, used for the custom theme */
+        store = gtk_list_store_new (THEME_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING);
+
+        /* Add the themes to a combobox */
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           THEME_DISPLAY_COL, _("No sounds"),
+                                           THEME_IDENTIFIER_COL, "__no_sounds",
+                                           THEME_PARENT_ID_COL, NULL,
+                                           -1);
+        g_hash_table_foreach (hash, (GHFunc) add_theme_to_store, store);
+        g_hash_table_destroy (hash);
+
+        /* Set the display */
+        gtk_combo_box_set_model (GTK_COMBO_BOX (chooser->priv->combo_box),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                    renderer,
+                                    TRUE);
+        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                        renderer,
+                                        "text", THEME_DISPLAY_COL,
+                                        NULL);
+
+        g_signal_connect (G_OBJECT (chooser->priv->combo_box),
+                          "changed",
+                          G_CALLBACK (on_combobox_changed),
+                          chooser);
+}
+
+#define GVC_SOUND_SOUND    (xmlChar *) "sound"
+#define GVC_SOUND_NAME     (xmlChar *) "name"
+#define GVC_SOUND_FILENAME (xmlChar *) "filename"
+
+/* Adapted from yelp-toc-pager.c */
+static xmlChar *
+xml_get_and_trim_names (xmlNodePtr node)
+{
+        xmlNodePtr cur;
+        xmlChar *keep_lang = NULL;
+        xmlChar *value;
+        int j, keep_pri = INT_MAX;
+
+        const gchar * const * langs = g_get_language_names ();
+
+        value = NULL;
+
+        for (cur = node->children; cur; cur = cur->next) {
+                if (! xmlStrcmp (cur->name, GVC_SOUND_NAME)) {
+                        xmlChar *cur_lang = NULL;
+                        int cur_pri = INT_MAX;
+
+                        cur_lang = xmlNodeGetLang (cur);
+
+                        if (cur_lang) {
+                                for (j = 0; langs[j]; j++) {
+                                        if (g_str_equal (cur_lang, langs[j])) {
+                                                cur_pri = j;
+                                                break;
+                                        }
+                                }
+                        } else {
+                                cur_pri = INT_MAX - 1;
+                        }
+
+                        if (cur_pri <= keep_pri) {
+                                if (keep_lang)
+                                        xmlFree (keep_lang);
+                                if (value)
+                                        xmlFree (value);
+
+                                value = xmlNodeGetContent (cur);
+
+                                keep_lang = cur_lang;
+                                keep_pri = cur_pri;
+                        } else {
+                                if (cur_lang)
+                                        xmlFree (cur_lang);
+                        }
+                }
+        }
+
+        /* Delete all GVC_SOUND_NAME nodes */
+        cur = node->children;
+        while (cur) {
+                xmlNodePtr this = cur;
+                cur = cur->next;
+                if (! xmlStrcmp (this->name, GVC_SOUND_NAME)) {
+                        xmlUnlinkNode (this);
+                        xmlFreeNode (this);
+                }
+        }
+
+        return value;
+}
+
+static void
+populate_model_from_node (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          xmlNodePtr            node)
+{
+        xmlNodePtr child;
+        xmlChar   *filename;
+        xmlChar   *name;
+
+        filename = NULL;
+        name = xml_get_and_trim_names (node);
+        for (child = node->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+
+                if (xmlStrcmp (child->name, GVC_SOUND_FILENAME) == 0) {
+                        filename = xmlNodeGetContent (child);
+                } else if (xmlStrcmp (child->name, GVC_SOUND_NAME) == 0) {
+                        /* EH? should have been trimmed */
+                }
+        }
+
+        if (filename != NULL && name != NULL) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   ALERT_IDENTIFIER_COL, filename,
+                                                   ALERT_DISPLAY_COL, name,
+                                                   ALERT_SOUND_TYPE_COL, _("Built-in"),
+                                                   ALERT_ACTIVE_COL, FALSE,
+                                                   -1);
+        }
+
+        xmlFree (filename);
+        xmlFree (name);
+}
+
+static void
+populate_model_from_file (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          const char           *filename)
+{
+        xmlDocPtr  doc;
+        xmlNodePtr root;
+        xmlNodePtr child;
+        gboolean   exists;
+
+        exists = g_file_test (filename, G_FILE_TEST_EXISTS);
+        if (! exists) {
+                return;
+        }
+
+        doc = xmlParseFile (filename);
+        if (doc == NULL) {
+                return;
+        }
+
+        root = xmlDocGetRootElement (doc);
+
+        for (child = root->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+                if (xmlStrcmp (child->name, GVC_SOUND_SOUND) != 0) {
+                        continue;
+                }
+
+                populate_model_from_node (chooser, model, child);
+        }
+
+        xmlFreeDoc (doc);
+}
+
+static void
+populate_model_from_dir (GvcSoundThemeChooser *chooser,
+                         GtkTreeModel         *model,
+                         const char           *dirname)
+{
+        GDir       *d;
+        const char *name;
+
+        d = g_dir_open (dirname, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *path;
+
+                if (! g_str_has_suffix (name, ".xml")) {
+                        continue;
+                }
+
+                path = g_build_filename (dirname, name, NULL);
+                populate_model_from_file (chooser, model, path);
+                g_free (path);
+        }
+
+        g_dir_close (d);
+}
+
+static gboolean
+save_alert_sounds (GvcSoundThemeChooser  *chooser,
+                   const char            *id)
+{
+        const char *sounds[3] = { "bell-terminal", "bell-window-system", NULL };
+        char *path;
+
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+        } else {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+                add_custom_file (sounds, id);
+        }
+
+        /* And poke the directory so the theme gets updated */
+        path = custom_theme_dir_path (NULL);
+        if (utime (path, NULL) != 0) {
+                g_warning ("Failed to update mtime for directory '%s': %s",
+                           path, g_strerror (errno));
+        }
+        g_free (path);
+
+        return FALSE;
+}
+
+
+static void
+update_alert_model (GvcSoundThemeChooser  *chooser,
+                    const char            *id)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        gtk_tree_model_get_iter_first (model, &iter);
+        do {
+                gboolean toggled;
+                char    *this_id;
+
+                gtk_tree_model_get (model, &iter,
+                                    ALERT_IDENTIFIER_COL, &this_id,
+                                    -1);
+
+                if (strcmp (this_id, id) == 0) {
+                        toggled = TRUE;
+                } else {
+                        toggled = FALSE;
+                }
+                g_free (this_id);
+
+                gtk_list_store_set (GTK_LIST_STORE (model),
+                                    &iter,
+                                    ALERT_ACTIVE_COL, toggled,
+                                    -1);
+        } while (gtk_tree_model_iter_next (model, &iter));
+}
+
+static void
+update_alert (GvcSoundThemeChooser *chooser,
+              const char           *alert_id)
+{
+        GtkTreeModel *theme_model;
+        GtkTreeIter   iter;
+        char         *theme;
+        char         *parent;
+        gboolean      is_custom;
+        gboolean      is_default;
+        gboolean      add_custom;
+        gboolean      remove_custom;
+
+        theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        /* Get the current theme's name, and set the parent */
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        gtk_tree_model_get (theme_model, &iter,
+                            THEME_IDENTIFIER_COL, &theme,
+                            THEME_IDENTIFIER_COL, &parent,
+                            -1);
+        is_custom = strcmp (theme, CUSTOM_THEME_NAME) == 0;
+        is_default = strcmp (alert_id, DEFAULT_ALERT_ID) == 0;
+
+        /* So a few possibilities:
+         * 1. Named theme, default alert selected: noop
+         * 2. Named theme, alternate alert selected: create new custom with sound
+         * 3. Custom theme, default alert selected: remove sound and possibly custom
+         * 4. Custom theme, alternate alert selected: update custom sound
+         */
+        add_custom = FALSE;
+        remove_custom = FALSE;
+        if (! is_custom && is_default) {
+                /* remove custom just in case */
+                remove_custom = TRUE;
+        } else if (! is_custom && ! is_default) {
+                create_custom_theme (parent);
+                save_alert_sounds (chooser, alert_id);
+                add_custom = TRUE;
+        } else if (is_custom && is_default) {
+                save_alert_sounds (chooser, alert_id);
+                /* after removing files check if it is empty */
+                if (custom_theme_dir_is_empty ()) {
+                        remove_custom = TRUE;
+                }
+        } else if (is_custom && ! is_default) {
+                save_alert_sounds (chooser, alert_id);
+        }
+
+        if (add_custom) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (theme_model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   THEME_DISPLAY_COL, _("Custom"),
+                                                   THEME_IDENTIFIER_COL, CUSTOM_THEME_NAME,
+                                                   THEME_PARENT_ID_COL, theme,
+                                                   -1);
+                set_combox_for_theme_name (chooser, CUSTOM_THEME_NAME);
+        } else if (remove_custom) {
+                gtk_tree_model_get_iter_first (theme_model, &iter);
+                do {
+                        char *this_parent;
+
+                        gtk_tree_model_get (theme_model, &iter,
+                                            THEME_PARENT_ID_COL, &this_parent,
+                                            -1);
+                        if (this_parent != NULL && strcmp (this_parent, CUSTOM_THEME_NAME) != 0) {
+                                g_free (this_parent);
+                                gtk_list_store_remove (GTK_LIST_STORE (theme_model), &iter);
+                                break;
+                        }
+                        g_free (this_parent);
+                } while (gtk_tree_model_iter_next (theme_model, &iter));
+
+                delete_custom_theme_dir ();
+
+                set_combox_for_theme_name (chooser, parent);
+        }
+
+        update_alert_model (chooser, alert_id);
+
+        g_free (theme);
+        g_free (parent);
+}
+
+static void
+on_alert_toggled (GtkCellRendererToggle *renderer,
+                  char                  *path_str,
+                  GvcSoundThemeChooser  *chooser)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreePath  *path;
+        gboolean      toggled;
+        char         *id;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        path = gtk_tree_path_new_from_string (path_str);
+        gtk_tree_model_get_iter (model, &iter, path);
+        gtk_tree_path_free (path);
+
+        id = NULL;
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            ALERT_ACTIVE_COL, &toggled,
+                            -1);
+
+        toggled ^= 1;
+        if (toggled) {
+                update_alert (chooser, id);
+        }
+
+        g_free (id);
+}
+
+static void
+play_preview_for_path (GvcSoundThemeChooser *chooser, GtkTreePath *path)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreeIter   theme_iter;
+        gchar        *id = NULL;
+        gchar        *parent_theme = NULL;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        if (gtk_tree_model_get_iter (model, &iter, path) == FALSE)
+                return;
+
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            -1);
+        if (id == NULL)
+                return;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &theme_iter)) {
+                GtkTreeModel *theme_model;
+                gchar        *theme_id = NULL;
+                gchar        *parent_id = NULL;
+
+                theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+                gtk_tree_model_get (theme_model, &theme_iter,
+                                    THEME_IDENTIFIER_COL, &theme_id,
+                                    THEME_PARENT_ID_COL, &parent_id, -1);
+                if (theme_id && strcmp (theme_id, CUSTOM_THEME_NAME) == 0)
+                        parent_theme = g_strdup (parent_id);
+
+                g_free (theme_id);
+                g_free (parent_id);
+        }
+
+        /* special case: for the default item on custom themes
+         * play the alert for the parent theme */
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                if (parent_theme != NULL) {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_CANBERRA_XDG_THEME_NAME, parent_theme,
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                } else {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                }
+        } else {
+                ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                        CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                        CA_PROP_MEDIA_FILENAME, id,
+                                        CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                        CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                        CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                        CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                        NULL);
+
+        }
+        g_free (parent_theme);
+        g_free (id);
+}
+
+static void
+on_treeview_row_activated (GtkTreeView          *treeview,
+                           GtkTreePath          *path,
+                           GtkTreeViewColumn    *column,
+                           GvcSoundThemeChooser *chooser)
+{
+        play_preview_for_path (chooser, path);
+}
+
+static void
+on_treeview_selection_changed (GtkTreeSelection     *selection,
+                               GvcSoundThemeChooser *chooser)
+{
+        GList        *paths;
+        GtkTreeModel *model;
+        GtkTreePath  *path;
+
+        if (chooser->priv->treeview == NULL)
+                return;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        paths = gtk_tree_selection_get_selected_rows (selection, &model);
+        if (paths == NULL)
+                return;
+
+        path = paths->data;
+        play_preview_for_path (chooser, path);
+
+        g_list_foreach (paths, (GFunc)gtk_tree_path_free, NULL);
+        g_list_free (paths);
+}
+
+static GtkWidget *
+create_alert_treeview (GvcSoundThemeChooser *chooser)
+{
+        GtkListStore         *store;
+        GtkWidget            *treeview;
+        GtkCellRenderer      *renderer;
+        GtkTreeViewColumn    *column;
+        GtkTreeSelection     *selection;
+
+        treeview = gtk_tree_view_new ();
+
+        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
+        g_signal_connect (G_OBJECT (treeview),
+                          "row-activated",
+                          G_CALLBACK (on_treeview_row_activated),
+                          chooser);
+
+        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+        gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+        g_signal_connect (G_OBJECT (selection),
+                          "changed",
+                          G_CALLBACK (on_treeview_selection_changed),
+                          chooser);
+
+        /* Setup the tree model, 3 columns:
+         * - display name
+         * - sound id
+         * - sound type
+         */
+        store = gtk_list_store_new (ALERT_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_BOOLEAN);
+
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           ALERT_IDENTIFIER_COL, DEFAULT_ALERT_ID,
+                                           ALERT_DISPLAY_COL, _("Default"),
+                                           ALERT_SOUND_TYPE_COL, _("From theme"),
+                                           ALERT_ACTIVE_COL, TRUE,
+                                           -1);
+
+        populate_model_from_dir (chooser, GTK_TREE_MODEL (store), SOUND_SET_DIR);
+
+        gtk_tree_view_set_model (GTK_TREE_VIEW (treeview),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_toggle_new ();
+        gtk_cell_renderer_toggle_set_radio (GTK_CELL_RENDERER_TOGGLE (renderer), TRUE);
+
+        column = gtk_tree_view_column_new_with_attributes (NULL,
+                                                           renderer,
+                                                           "active", ALERT_ACTIVE_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+        g_signal_connect (renderer,
+                          "toggled",
+                          G_CALLBACK (on_alert_toggled),
+                          chooser);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Name"),
+                                                           renderer,
+                                                           "text", ALERT_DISPLAY_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Type"),
+                                                           renderer,
+                                                           "text", ALERT_SOUND_TYPE_COL,
+                                                           NULL);
+
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        return treeview;
+}
+
+static int
+get_file_type (const char *sound_name,
+               char      **linked_name)
+{
+        char *name, *filename;
+
+        *linked_name = NULL;
+
+        name = g_strdup_printf ("%s.disabled", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_REGULAR) != FALSE) {
+                g_free (filename);
+                return SOUND_TYPE_OFF;
+        }
+        g_free (filename);
+
+        /* We only check for .ogg files because those are the
+         * only ones we create */
+        name = g_strdup_printf ("%s.ogg", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_SYMLINK) != FALSE) {
+                *linked_name = g_file_read_link (filename, NULL);
+                g_free (filename);
+                return SOUND_TYPE_CUSTOM;
+        }
+        g_free (filename);
+
+        return SOUND_TYPE_BUILTIN;
+}
+
+static void
+update_alerts_from_theme_name (GvcSoundThemeChooser *chooser,
+                               const gchar          *name)
+{
+        if (strcmp (name, CUSTOM_THEME_NAME) != 0) {
+                /* reset alert to default */
+                update_alert (chooser, DEFAULT_ALERT_ID);
+        } else {
+                int   sound_type;
+                char *linkname;
+
+                linkname = NULL;
+                sound_type = get_file_type ("bell-terminal", &linkname);
+                g_debug ("Found link: %s", linkname);
+                if (sound_type == SOUND_TYPE_CUSTOM) {
+                        update_alert (chooser, linkname);
+                }
+        }
+}
+
+static void
+update_theme (GvcSoundThemeChooser *chooser)
+{
+        char        *theme_name;
+        gboolean     events_enabled;
+        gboolean     feedback_enabled;
+
+        feedback_enabled = g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY);
+        set_input_feedback_enabled (chooser, feedback_enabled);
+
+        events_enabled = g_settings_get_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY);
+        if (events_enabled) {
+                theme_name = g_settings_get_string (chooser->priv->sound_settings, SOUND_THEME_KEY);
+        } else {
+                theme_name = g_strdup (NO_SOUNDS_THEME_NAME);
+        }
+
+        gtk_widget_set_sensitive (chooser->priv->selection_box, events_enabled);
+        gtk_widget_set_sensitive (chooser->priv->click_feedback_button, events_enabled);
+
+        set_combox_for_theme_name (chooser, theme_name);
+
+        update_alerts_from_theme_name (chooser, theme_name);
+
+        g_free (theme_name);
+}
+
+static void
+gvc_sound_theme_chooser_class_init (GvcSoundThemeChooserClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_sound_theme_chooser_dispose;
+}
+
+static void
+on_click_feedback_toggled (GtkToggleButton      *button,
+                           GvcSoundThemeChooser *chooser)
+{
+        gboolean enabled;
+
+        enabled = gtk_toggle_button_get_active (button);
+
+        g_settings_set_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY, enabled);
+}
+
+static void
+on_key_changed (GSettings            *settings,
+                gchar                *key,
+                GvcSoundThemeChooser *chooser)
+{
+        if (!strcmp (key, EVENT_SOUNDS_KEY) ||
+            !strcmp (key, SOUND_THEME_KEY) ||
+            !strcmp (key, INPUT_SOUNDS_KEY))
+                update_theme (chooser);
+}
+
+static void
+setup_list_size_constraint (GtkWidget *widget,
+                            GtkWidget *to_size)
+{
+        GtkRequisition req;
+        gint           sc_height;
+        int            max_height;
+
+        /* Constrain height to be the tree height up to a max */
+        gdk_window_get_geometry (gdk_screen_get_root_window (gtk_widget_get_screen (widget)),
+                                 NULL, NULL, NULL, &sc_height);
+
+        max_height = sc_height / 4;
+
+        // XXX this doesn't work
+        gtk_widget_get_preferred_size (to_size, NULL, &req);
+
+        gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (widget),
+                                                    MIN (req.height, max_height));
+}
+
+static void
+gvc_sound_theme_chooser_init (GvcSoundThemeChooser *chooser)
+{
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *scrolled_window;
+        gchar       *str;
+
+        chooser->priv = gvc_sound_theme_chooser_get_instance_private (chooser);
+
+        chooser->priv->theme_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->theme_box, FALSE, FALSE, 0);
+
+        label = gtk_label_new_with_mnemonic (_("Sound _theme:"));
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), label, FALSE, FALSE, 0);
+        chooser->priv->combo_box = gtk_combo_box_new ();
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), chooser->priv->combo_box, FALSE, FALSE, 6);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->combo_box);
+
+        chooser->priv->sound_settings = g_settings_new (KEY_SOUNDS_SCHEMA);
+
+        g_signal_connect (G_OBJECT (chooser->priv->sound_settings),
+                          "changed",
+                          G_CALLBACK (on_key_changed),
+                          chooser);
+
+        str = g_strdup_printf ("<b>%s</b>", _("C_hoose an alert sound:"));
+        chooser->priv->selection_box = box = gtk_frame_new (str);
+        g_free (str);
+
+        label = gtk_frame_get_label_widget (GTK_FRAME (box));
+        gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
+        gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+        gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
+
+        gtk_box_pack_start (GTK_BOX (chooser), box, TRUE, TRUE, 6);
+
+        chooser->priv->treeview = create_alert_treeview (chooser);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->treeview);
+
+        scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+        gtk_widget_set_hexpand (scrolled_window, TRUE);
+        gtk_widget_set_vexpand (scrolled_window, TRUE);
+        gtk_widget_set_margin_top (scrolled_window, 6);
+
+        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+                                        GTK_POLICY_NEVER,
+                                        GTK_POLICY_AUTOMATIC);
+        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
+                                             GTK_SHADOW_IN);
+
+        gtk_container_add (GTK_CONTAINER (scrolled_window), chooser->priv->treeview);
+        gtk_container_add (GTK_CONTAINER (box), scrolled_window);
+
+        chooser->priv->click_feedback_button = gtk_check_button_new_with_mnemonic (_("Enable _window and button sounds"));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY));
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->click_feedback_button,
+                            FALSE, FALSE, 0);
+
+        g_signal_connect (G_OBJECT (chooser->priv->click_feedback_button),
+                          "toggled",
+                          G_CALLBACK (on_click_feedback_toggled),
+                          chooser);
+
+        setup_theme_selector (chooser);
+        update_theme (chooser);
+
+        setup_list_size_constraint (scrolled_window, chooser->priv->treeview);
+}
+
+static void
+gvc_sound_theme_chooser_dispose (GObject *object)
+{
+        GvcSoundThemeChooser *chooser;
+
+        chooser = GVC_SOUND_THEME_CHOOSER (object);
+
+        g_clear_object (&chooser->priv->sound_settings);
+
+        G_OBJECT_CLASS (gvc_sound_theme_chooser_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_sound_theme_chooser_new (void)
+{
+        return g_object_new (GVC_TYPE_SOUND_THEME_CHOOSER,
+                                "spacing", 6,
+                                "orientation", GTK_ORIENTATION_VERTICAL,
+                                NULL);
+}
+
+
+
+ + + diff --git a/2020-04-21-013643-7310-cppcheck@85e50bb1e8b0_master/2.html b/2020-04-21-013643-7310-cppcheck@85e50bb1e8b0_master/2.html new file mode 100644 index 0000000..bacfabb --- /dev/null +++ b/2020-04-21-013643-7310-cppcheck@85e50bb1e8b0_master/2.html @@ -0,0 +1,1110 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <canberra.h>
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-speaker-test.h"
+#include "gvc-utils.h"
+
+struct _GvcSpeakerTestPrivate
+{
+        GArray           *controls;
+        ca_context       *canberra;
+        MateMixerStream  *stream;
+};
+
+enum {
+        PROP_0,
+        PROP_STREAM,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_speaker_test_dispose    (GObject             *object);
+static void gvc_speaker_test_finalize   (GObject             *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSpeakerTest, gvc_speaker_test, GTK_TYPE_GRID)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+typedef struct {
+        MateMixerChannelPosition position;
+        guint left;
+        guint top;
+} TablePosition;
+
+static const TablePosition positions[] = {
+        /* Position, X, Y */
+        { MATE_MIXER_CHANNEL_FRONT_LEFT, 0, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_LEFT_CENTER, 1, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_CENTER, 2, 0, },
+        { MATE_MIXER_CHANNEL_MONO, 2, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT_CENTER, 3, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT, 4, 0, },
+        { MATE_MIXER_CHANNEL_SIDE_LEFT, 0, 1, },
+        { MATE_MIXER_CHANNEL_SIDE_RIGHT, 4, 1, },
+        { MATE_MIXER_CHANNEL_BACK_LEFT, 0, 2, },
+        { MATE_MIXER_CHANNEL_BACK_CENTER, 2, 2, },
+        { MATE_MIXER_CHANNEL_BACK_RIGHT, 4, 2, },
+        { MATE_MIXER_CHANNEL_LFE, 3, 2 }
+};
+
+MateMixerStream *
+gvc_speaker_test_get_stream (GvcSpeakerTest *test)
+{
+        g_return_val_if_fail (GVC_IS_SPEAKER_TEST (test), NULL);
+
+        return test->priv->stream;
+}
+
+static void
+gvc_speaker_test_set_stream (GvcSpeakerTest *test, MateMixerStream *stream)
+{
+        MateMixerStreamControl *control;
+        const gchar            *name;
+        guint                   i;
+
+        name = mate_mixer_stream_get_name (stream);
+        control = mate_mixer_stream_get_default_control (stream);
+
+        ca_context_change_device (test->priv->canberra, name);
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                gboolean has_position =
+                        mate_mixer_stream_control_has_channel_position (control, positions[i].position);
+
+                gtk_widget_set_visible (g_array_index (test->priv->controls, GtkWidget *, i),
+                                        has_position);
+        }
+
+        test->priv->stream = g_object_ref (stream);
+}
+
+static void
+gvc_speaker_test_set_property (GObject       *object,
+                               guint          prop_id,
+                               const GValue  *value,
+                               GParamSpec    *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                gvc_speaker_test_set_stream (self, g_value_get_object (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_get_property (GObject     *object,
+                               guint        prop_id,
+                               GValue      *value,
+                               GParamSpec  *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                g_value_set_object (value, self->priv->stream);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_class_init (GvcSpeakerTestClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose  = gvc_speaker_test_dispose;
+        object_class->finalize = gvc_speaker_test_finalize;
+        object_class->set_property = gvc_speaker_test_set_property;
+        object_class->get_property = gvc_speaker_test_get_property;
+
+        properties[PROP_STREAM] =
+                g_param_spec_object ("stream",
+                                     "Stream",
+                                     "MateMixer stream",
+                                     MATE_MIXER_TYPE_STREAM,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+}
+
+static const gchar *
+sound_name (MateMixerChannelPosition position)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return "audio-channel-front-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return "audio-channel-front-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return "audio-channel-front-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return "audio-channel-rear-left";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return "audio-channel-rear-right";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return "audio-channel-rear-center";
+        case MATE_MIXER_CHANNEL_LFE:
+                return "audio-channel-lfe";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return "audio-channel-side-left";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return "audio-channel-side-right";
+        default:
+                return NULL;
+        }
+}
+
+static const gchar *
+icon_name (MateMixerChannelPosition position, gboolean playing)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return playing
+                        ? "audio-speaker-left-testing"
+                        : "audio-speaker-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return playing
+                        ? "audio-speaker-right-testing"
+                        : "audio-speaker-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return playing
+                        ? "audio-speaker-center-testing"
+                        : "audio-speaker-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return playing
+                        ? "audio-speaker-left-back-testing"
+                        : "audio-speaker-left-back";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return playing
+                        ? "audio-speaker-right-back-testing"
+                        : "audio-speaker-right-back";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return playing
+                        ? "audio-speaker-center-back-testing"
+                        : "audio-speaker-center-back";
+        case MATE_MIXER_CHANNEL_LFE:
+                return playing
+                        ? "audio-subwoofer-testing"
+                        : "audio-subwoofer";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return playing
+                        ? "audio-speaker-left-side-testing"
+                        : "audio-speaker-left-side";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return playing
+                        ? "audio-speaker-right-side-testing"
+                        : "audio-speaker-right-side";
+        default:
+                return NULL;
+        }
+}
+
+static void
+update_button (GtkWidget *control)
+{
+        GtkWidget *button;
+        GtkWidget *image;
+        gboolean   playing;
+        MateMixerChannelPosition position;
+
+        button = g_object_get_data (G_OBJECT (control), "button");
+        image  = g_object_get_data (G_OBJECT (control), "image");
+
+        position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+        playing  = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        gtk_button_set_label (GTK_BUTTON (button), playing ? _("Stop") : _("Test"));
+
+        gtk_image_set_from_icon_name (GTK_IMAGE (image),
+                                      icon_name (position, playing),
+                                      GTK_ICON_SIZE_DIALOG);
+}
+
+static gboolean
+idle_cb (GtkWidget *control)
+{
+        if (control != NULL) {
+                /* This is called in the background thread, hence forward to main thread
+                 * via idle callback */
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+
+                update_button (control);
+        }
+        return FALSE;
+}
+
+static void
+finish_cb (ca_context *c, uint32_t id, int error_code, void *userdata)
+{
+        GtkWidget *control = (GtkWidget *) userdata;
+
+        if (error_code == CA_ERROR_DESTROYED || control == NULL)
+                return;
+
+        g_idle_add ((GSourceFunc) idle_cb, control);
+}
+
+static void
+on_test_button_clicked (GtkButton *button, GtkWidget *control)
+{
+        gboolean    playing;
+        ca_context *canberra;
+
+        canberra = g_object_get_data (G_OBJECT (control), "canberra");
+
+        ca_context_cancel (canberra, 1);
+
+        playing = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        if (playing) {
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        } else {
+                MateMixerChannelPosition position;
+                const gchar *name;
+                ca_proplist *proplist;
+
+                position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+
+                ca_proplist_create (&proplist);
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_ROLE, "test");
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_NAME,
+                                  gvc_channel_position_to_pretty_string (position));
+                ca_proplist_sets (proplist,
+                                  CA_PROP_CANBERRA_FORCE_CHANNEL,
+                                  gvc_channel_position_to_pulse_string (position));
+
+                ca_proplist_sets (proplist, CA_PROP_CANBERRA_ENABLE, "1");
+
+                name = sound_name (position);
+                if (name != NULL) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, name);
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, "audio-test-signal");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets(proplist, CA_PROP_EVENT_ID, "bell-window-system");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (playing));
+        }
+
+        update_button (control);
+}
+
+static GtkWidget *
+create_control (ca_context *canberra, MateMixerChannelPosition position)
+{
+        GtkWidget   *control;
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *image;
+        GtkWidget   *test_button;
+        const gchar *name;
+
+        control = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+        box     = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        g_object_set_data (G_OBJECT (control), "position", GINT_TO_POINTER (position));
+        g_object_set_data (G_OBJECT (control), "canberra", canberra);
+
+        name = icon_name (position, FALSE);
+        if (name == NULL)
+                name = "audio-volume-medium";
+
+        image = gtk_image_new_from_icon_name (name, GTK_ICON_SIZE_DIALOG);
+        g_object_set_data (G_OBJECT (control), "image", image);
+        gtk_box_pack_start (GTK_BOX (control), image, FALSE, FALSE, 0);
+
+        label = gtk_label_new (gvc_channel_position_to_pretty_string (position));
+        gtk_box_pack_start (GTK_BOX (control), label, FALSE, FALSE, 0);
+
+        test_button = gtk_button_new_with_label (_("Test"));
+        g_signal_connect (G_OBJECT (test_button),
+                          "clicked",
+                          G_CALLBACK (on_test_button_clicked),
+                          control);
+
+        g_object_set_data (G_OBJECT (control), "button", test_button);
+
+        gtk_box_pack_start (GTK_BOX (box), test_button, TRUE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (control), box, FALSE, FALSE, 0);
+
+        gtk_widget_show_all (control);
+
+        return control;
+}
+
+static void
+create_controls (GvcSpeakerTest *test)
+{
+        guint i;
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                GtkWidget *control = create_control (test->priv->canberra, positions[i].position);
+
+                gtk_grid_attach (GTK_GRID (test),
+                                 control,
+                                 positions[i].left,
+                                 positions[i].top,
+                                 1, 1);
+                g_array_insert_val (test->priv->controls, i, control);
+        }
+}
+
+static void
+gvc_speaker_test_init (GvcSpeakerTest *test)
+{
+        GtkWidget *face;
+
+        test->priv = gvc_speaker_test_get_instance_private (test);
+
+        gtk_container_set_border_width (GTK_CONTAINER (test), 12);
+
+        face = gtk_image_new_from_icon_name ("face-smile", GTK_ICON_SIZE_DIALOG);
+
+        gtk_grid_attach (GTK_GRID (test),
+                         face,
+                         1, 1,
+                         3, 1);
+
+
+        gtk_grid_set_baseline_row (GTK_GRID (test), 1);
+        gtk_widget_show (face);
+
+        ca_context_create (&test->priv->canberra);
+
+        /* The test sounds are played for a single channel, set up using the
+         * FORCE_CHANNEL property of libcanberra; this property is only supported
+         * in the PulseAudio backend, so avoid other backends completely */
+        ca_context_set_driver (test->priv->canberra, "pulse");
+
+        ca_context_change_props (test->priv->canberra,
+                                 CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+                                 CA_PROP_APPLICATION_NAME, _("Volume Control"),
+                                 CA_PROP_APPLICATION_VERSION, VERSION,
+                                 CA_PROP_APPLICATION_ICON_NAME, "multimedia-volume-control",
+                                 NULL);
+
+        test->priv->controls = g_array_new (FALSE, FALSE, sizeof (GtkWidget *));
+
+        create_controls (test);
+}
+
+static void
+gvc_speaker_test_dispose (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        g_clear_object (&test->priv->stream);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->dispose (object);
+}
+
+static void
+gvc_speaker_test_finalize (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        ca_context_destroy (test->priv->canberra);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->finalize (object);
+}
+
+GtkWidget *
+gvc_speaker_test_new (MateMixerStream *stream)
+{
+        GObject *test;
+
+        g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL);
+
+        test = g_object_new (GVC_TYPE_SPEAKER_TEST,
+                             "row-spacing", 6,
+                             "column-spacing", 6,
+                             "row-homogeneous", TRUE,
+                             "column-homogeneous", TRUE,
+                             "stream", stream,
+                             NULL);
+
+        return GTK_WIDGET (test);
+}
+
+
+
+ + + diff --git a/2020-04-21-013643-7310-cppcheck@85e50bb1e8b0_master/index.html b/2020-04-21-013643-7310-cppcheck@85e50bb1e8b0_master/index.html new file mode 100644 index 0000000..59baeb0 --- /dev/null +++ b/2020-04-21-013643-7310-cppcheck@85e50bb1e8b0_master/index.html @@ -0,0 +1,108 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
mate-volume-control/gvc-combo-box.c
70unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
mate-volume-control/gvc-sound-theme-chooser.c
735ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
746ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
758ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
mate-volume-control/gvc-speaker-test.c
53unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+ + + diff --git a/2020-04-21-013643-7310-cppcheck@85e50bb1e8b0_master/stats.html b/2020-04-21-013643-7310-cppcheck@85e50bb1e8b0_master/stats.html new file mode 100644 index 0000000..3fb6add --- /dev/null +++ b/2020-04-21-013643-7310-cppcheck@85e50bb1e8b0_master/stats.html @@ -0,0 +1,93 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+

Top 10 files for error severity, total findings: 2
+   1  mate-volume-control/gvc-speaker-test.c
+   1  mate-volume-control/gvc-combo-box.c
+

+

Top 10 files for information severity, total findings: 3
+   3  mate-volume-control/gvc-sound-theme-chooser.c
+

+ +
+ + + diff --git a/2020-04-21-013643-7310-cppcheck@85e50bb1e8b0_master/style.css b/2020-04-21-013643-7310-cppcheck@85e50bb1e8b0_master/style.css new file mode 100644 index 0000000..c39571c --- /dev/null +++ b/2020-04-21-013643-7310-cppcheck@85e50bb1e8b0_master/style.css @@ -0,0 +1,149 @@ + +body { + font: 13px Arial, Verdana, Sans-Serif; + margin: 0; + width: auto; +} + +h1 { + margin: 10px; +} + +#footer > p { + margin: 4px; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + border: 1px dotted black; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #B6B6B4; +} + +.inconclusive2 { + background-color: #B6B6B4; + border: 1px dotted black; + display: inline-block; + margin-left: 4px; +} + +div.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +div.verbose div.content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid black; + background-color: #FFFFCC; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +#header { + border-bottom: thin solid #aaa; +} + +#menu { + float: left; + margin-top: 5px; + text-align: left; + width: 150px; + /*height: 75%;*/ + position: fixed; + overflow: auto; + z-index: 1; +} + +#menu_index { + float: left; + margin-top: 5px; + padding-left: 5px; + text-align: left; + width: 300px; + /*height: 75%;*/ + position: fixed; + overflow: auto; + z-index: 1; +} + +#menu > a { + display: block; + margin-left: 10px; + font: 12px; + z-index: 1; +} + +#filename { + margin-left: 10px; + font: 12px; + z-index: 1; +} + +.highlighttable { + background-color:white; + z-index: 10; + position: relative; + margin: -10 px; +} + +#content { + background-color: white; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + float: left; + margin: 5px; + margin-left: 10px; + padding: 0 10px 10px 10px; + width: 80%; + padding-left: 150px; +} + +#content_index { + background-color: white; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + float: left; + margin: 5px; + margin-left: 10px; + padding: 0 10px 10px 10px; + width: 80%; + padding-left: 300px; +} + +.linenos { + border-right: thin solid #aaa; + color: lightgray; + padding-right: 6px; +} + +#footer { + border-top: thin solid #aaa; + clear: both; + font-size: 90%; + margin-top: 5px; +} + +#footer ul { + list-style-type: none; + padding-left: 0; +} diff --git a/2020-04-25-161832-9866-cppcheck@0de220f56e3d_master/0.html b/2020-04-25-161832-9866-cppcheck@0de220f56e3d_master/0.html new file mode 100644 index 0000000..e262ed0 --- /dev/null +++ b/2020-04-25-161832-9866-cppcheck@0de220f56e3d_master/0.html @@ -0,0 +1,1038 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-combo-box.h"
+
+struct _GvcComboBoxPrivate
+{
+        GtkWidget       *drop_box;
+        GtkWidget       *start_box;
+        GtkWidget       *end_box;
+        GtkWidget       *label;
+        GtkWidget       *button;
+        GtkTreeModel    *model;
+        GtkWidget       *combobox;
+        MateMixerSwitch *swtch;
+};
+
+enum {
+        COL_NAME,
+        COL_HUMAN_NAME,
+        NUM_COLS
+};
+
+enum {
+        CHANGING,
+        BUTTON_CLICKED,
+        LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+enum {
+        PROP_0,
+        PROP_SWITCH,
+        PROP_LABEL,
+        PROP_SHOW_BUTTON,
+        PROP_BUTTON_LABEL,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_combo_box_dispose    (GObject          *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcComboBox, gvc_combo_box, GTK_TYPE_BOX)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+MateMixerSwitch *
+gvc_combo_box_get_switch (GvcComboBox *combobox)
+{
+        g_return_val_if_fail (GVC_IS_COMBO_BOX (combobox), NULL);
+
+        return combobox->priv->swtch;
+}
+
+void
+gvc_combo_box_set_size_group (GvcComboBox  *combobox,
+                              GtkSizeGroup *group,
+                              gboolean      symmetric)
+{
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (GTK_IS_SIZE_GROUP (group));
+
+        if (group != NULL) {
+                gtk_size_group_add_widget (group, combobox->priv->start_box);
+                if (symmetric == TRUE)
+                        gtk_size_group_add_widget (group, combobox->priv->end_box);
+        }
+        gtk_widget_queue_draw (GTK_WIDGET (combobox));
+}
+
+static void
+on_switch_active_option_notify (MateMixerSwitch *swtch,
+                                GParamSpec      *pspec,
+                                GvcComboBox     *combobox)
+{
+        GtkTreeIter            iter;
+        MateMixerSwitchOption *active;
+        gboolean               cont;
+        const gchar           *name;
+
+        active = mate_mixer_switch_get_active_option (swtch);
+        if (G_UNLIKELY (active == NULL)) {
+                g_warn_if_reached ();
+                return;
+        }
+
+        /* Select the newly activated switch option in the combo box */
+        name = mate_mixer_switch_option_get_name (active);
+        cont = gtk_tree_model_get_iter_first (combobox->priv->model, &iter);
+        while (cont == TRUE) {
+                gchar *current;
+
+                gtk_tree_model_get (combobox->priv->model, &iter,
+                                    COL_NAME, &current,
+                                    -1);
+                if (g_strcmp0 (name, current) == 0) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox), &iter);
+                        g_free (current);
+                        return;
+                }
+                g_free (current);
+
+                cont = gtk_tree_model_iter_next (combobox->priv->model, &iter);
+        }
+        g_warning ("Could not find switch option '%s' in combo box", name);
+}
+
+static void
+gvc_combo_box_set_switch (GvcComboBox *combobox, MateMixerSwitch *swtch)
+{
+        MateMixerSwitchOption *active;
+        const GList           *options;
+
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (MATE_MIXER_IS_SWITCH (swtch));
+
+        combobox->priv->swtch = g_object_ref (swtch);
+
+        active  = mate_mixer_switch_get_active_option (swtch);
+        options = mate_mixer_switch_list_options (swtch);
+        while (options != NULL) {
+                GtkTreeIter            iter;
+                MateMixerSwitchOption *option = MATE_MIXER_SWITCH_OPTION (options->data);
+
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (combobox->priv->model),
+                                                   &iter,
+                                                   G_MAXINT,
+                                                   COL_NAME,
+                                                   mate_mixer_switch_option_get_name (option),
+                                                   COL_HUMAN_NAME,
+                                                   mate_mixer_switch_option_get_label (option),
+                                                   -1);
+
+                /* Select the currently active option of the switch */
+                if (option == active) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox),
+                                                       &iter);
+                }
+                options = options->next;
+        }
+
+        g_signal_connect (G_OBJECT (swtch),
+                          "notify::active-option",
+                          G_CALLBACK (on_switch_active_option_notify),
+                          combobox);
+}
+
+static void
+gvc_combo_box_set_property (GObject       *object,
+                            guint          prop_id,
+                            const GValue  *value,
+                            GParamSpec    *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                gvc_combo_box_set_switch (self, g_value_get_object (value));
+                break;
+        case PROP_LABEL:
+                gtk_label_set_text_with_mnemonic (GTK_LABEL (self->priv->label), g_value_get_string (value));
+                break;
+        case PROP_BUTTON_LABEL:
+                gtk_button_set_label (GTK_BUTTON (self->priv->button), g_value_get_string (value));
+                break;
+        case PROP_SHOW_BUTTON:
+                gtk_widget_set_visible (self->priv->button, g_value_get_boolean (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_get_property (GObject     *object,
+                            guint        prop_id,
+                            GValue      *value,
+                            GParamSpec  *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                g_value_set_object (value, self->priv->swtch);
+                break;
+        case PROP_LABEL:
+                g_value_set_string (value, gtk_label_get_text (GTK_LABEL (self->priv->label)));
+                break;
+        case PROP_BUTTON_LABEL:
+                g_value_set_string (value, gtk_button_get_label (GTK_BUTTON (self->priv->button)));
+                break;
+        case PROP_SHOW_BUTTON:
+                g_value_set_boolean (value, gtk_widget_get_visible (self->priv->button));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_class_init (GvcComboBoxClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_combo_box_dispose;
+        object_class->set_property = gvc_combo_box_set_property;
+        object_class->get_property = gvc_combo_box_get_property;
+
+        properties[PROP_SWITCH] =
+                g_param_spec_object ("switch",
+                                     "switch",
+                                     "The MateMixerSwitch",
+                                     MATE_MIXER_TYPE_SWITCH,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_LABEL] =
+                g_param_spec_string ("label",
+                                     "label",
+                                     "The combo box label",
+                                     _("_Profile:"),
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_SHOW_BUTTON] =
+                g_param_spec_boolean ("show-button",
+                                      "show-button",
+                                      "Whether to show the button",
+                                      FALSE,
+                                      G_PARAM_READWRITE |
+                                      G_PARAM_CONSTRUCT |
+                                      G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_BUTTON_LABEL] =
+                g_param_spec_string ("button-label",
+                                     "button-label",
+                                     "The button's label",
+                                     "",
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+
+        signals[CHANGING] =
+                g_signal_new ("changing",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, changing),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__OBJECT,
+                              G_TYPE_NONE,
+                              1,
+                              MATE_MIXER_TYPE_SWITCH_OPTION);
+
+        signals[BUTTON_CLICKED] =
+                g_signal_new ("button-clicked",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, button_clicked),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
+}
+
+static void
+on_combo_box_changed (GtkComboBox *widget, GvcComboBox *combobox)
+{
+        GtkTreeIter            iter;
+        gchar                 *name;
+        MateMixerSwitchOption *option;
+
+        if (G_UNLIKELY (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter) == FALSE))
+                return;
+
+        gtk_tree_model_get (combobox->priv->model, &iter,
+                            COL_NAME, &name,
+                            -1);
+
+        option = mate_mixer_switch_get_option (combobox->priv->swtch, name);
+        if (G_UNLIKELY (option == NULL)) {
+                g_warn_if_reached ();
+                g_free (name);
+                return;
+        }
+
+        /* Inform that we are about to change the active option of the switch */
+        g_signal_emit (combobox, signals[CHANGING], 0, option);
+
+        mate_mixer_switch_set_active_option (combobox->priv->swtch, option);
+        g_free (name);
+}
+
+static void
+on_combo_box_button_clicked (GtkButton *button, GvcComboBox *combobox)
+{
+        /* The meaning of the button is defined by the owner, so only notify
+         * when it is clicked on */
+        g_signal_emit (combobox, signals[BUTTON_CLICKED], 0);
+}
+
+static void
+gvc_combo_box_init (GvcComboBox *combobox)
+{
+        GtkWidget       *frame;
+        GtkCellRenderer *renderer;
+
+        frame = gtk_frame_new (NULL);
+        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
+
+        combobox->priv = gvc_combo_box_get_instance_private (combobox);
+
+        combobox->priv->model = GTK_TREE_MODEL (gtk_list_store_new (NUM_COLS,
+                                                                    G_TYPE_STRING,
+                                                                    G_TYPE_STRING));
+
+        combobox->priv->combobox = gtk_combo_box_new_with_model (combobox->priv->model);
+
+        combobox->priv->label = gtk_label_new (NULL);
+
+        gtk_label_set_xalign (GTK_LABEL (combobox->priv->label), 0.0);
+        gtk_label_set_yalign (GTK_LABEL (combobox->priv->label), 0.5);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (combobox->priv->label),
+                                       combobox->priv->combobox);
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                    renderer,
+                                    FALSE);
+        gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                       renderer,
+                                       "text",
+                                       COL_HUMAN_NAME);
+
+        combobox->priv->drop_box  = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->start_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->end_box   = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+        /* Make sure the combo box does not get too long on long profile names */
+        g_object_set (G_OBJECT (renderer),
+                      "ellipsize",
+                      PANGO_ELLIPSIZE_END,
+                      NULL);
+
+        gtk_combo_box_set_popup_fixed_width (GTK_COMBO_BOX (combobox->priv->combobox), FALSE);
+
+        gtk_box_pack_start (GTK_BOX (combobox),
+                            frame,
+                            TRUE, TRUE, 0);
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->start_box,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->start_box),
+                            combobox->priv->label,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->combobox,
+                            TRUE, TRUE, 0);
+
+        combobox->priv->button = gtk_button_new_with_label ("");
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->button,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->end_box,
+                            FALSE, FALSE, 0);
+
+        gtk_container_add (GTK_CONTAINER (frame), combobox->priv->drop_box);
+
+        g_signal_connect (G_OBJECT (combobox->priv->combobox),
+                          "changed",
+                          G_CALLBACK (on_combo_box_changed),
+                          combobox);
+        g_signal_connect (G_OBJECT (combobox->priv->button),
+                          "clicked",
+                          G_CALLBACK (on_combo_box_button_clicked),
+                          combobox);
+
+        gtk_widget_set_no_show_all (combobox->priv->button, TRUE);
+        gtk_widget_show_all (frame);
+}
+
+static void
+gvc_combo_box_dispose (GObject *object)
+{
+        GvcComboBox *combobox;
+
+        combobox = GVC_COMBO_BOX (object);
+
+        if (G_LIKELY (combobox->priv->swtch != NULL)) {
+                g_signal_handlers_disconnect_by_func (G_OBJECT (combobox->priv->swtch),
+                                                      G_CALLBACK (on_switch_active_option_notify),
+                                                      combobox);
+                g_clear_object (&combobox->priv->swtch);
+        }
+
+        g_clear_object (&combobox->priv->model);
+
+        G_OBJECT_CLASS (gvc_combo_box_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_combo_box_new (MateMixerSwitch *swtch, const gchar *label)
+{
+        return g_object_new (GVC_TYPE_COMBO_BOX,
+                             "switch", swtch,
+                             "label", label,
+                             "orientation", GTK_ORIENTATION_HORIZONTAL,
+                             NULL);
+}
+
+
+
+ + + diff --git a/2020-04-25-161832-9866-cppcheck@0de220f56e3d_master/1.html b/2020-04-25-161832-9866-cppcheck@0de220f56e3d_master/1.html new file mode 100644 index 0000000..67179f2 --- /dev/null +++ b/2020-04-25-161832-9866-cppcheck@0de220f56e3d_master/1.html @@ -0,0 +1,2368 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
+ * Copyright (C) 2008 William Jon McCann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <utime.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+#include <canberra-gtk.h>
+#include <libxml/tree.h>
+
+#include "gvc-sound-theme-chooser.h"
+#include "sound-theme-file-utils.h"
+
+struct GvcSoundThemeChooserPrivate
+{
+        GtkWidget *combo_box;
+        GtkWidget *treeview;
+        GtkWidget *theme_box;
+        GtkWidget *selection_box;
+        GtkWidget *click_feedback_button;
+        GSettings *sound_settings;
+};
+
+static void     gvc_sound_theme_chooser_dispose   (GObject            *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSoundThemeChooser, gvc_sound_theme_chooser, GTK_TYPE_BOX)
+
+#define KEY_SOUNDS_SCHEMA          "org.mate.sound"
+#define EVENT_SOUNDS_KEY           "event-sounds"
+#define INPUT_SOUNDS_KEY           "input-feedback-sounds"
+#define SOUND_THEME_KEY            "theme-name"
+
+#define DEFAULT_ALERT_ID        "__default"
+#define CUSTOM_THEME_NAME       "__custom"
+#define NO_SOUNDS_THEME_NAME    "__no_sounds"
+
+enum {
+        THEME_DISPLAY_COL,
+        THEME_IDENTIFIER_COL,
+        THEME_PARENT_ID_COL,
+        THEME_NUM_COLS
+};
+
+enum {
+        ALERT_DISPLAY_COL,
+        ALERT_IDENTIFIER_COL,
+        ALERT_SOUND_TYPE_COL,
+        ALERT_ACTIVE_COL,
+        ALERT_NUM_COLS
+};
+
+enum {
+        SOUND_TYPE_UNSET,
+        SOUND_TYPE_OFF,
+        SOUND_TYPE_DEFAULT_FROM_THEME,
+        SOUND_TYPE_BUILTIN,
+        SOUND_TYPE_CUSTOM
+};
+
+static void
+on_combobox_changed (GtkComboBox          *widget,
+                     GvcSoundThemeChooser *chooser)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        char         *theme_name;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &theme_name, -1);
+
+        g_assert (theme_name != NULL);
+
+        /* It is necessary to update the theme name before any other setting as
+         * the "changed" notification will reload the contents of the widget */
+        g_settings_set_string (chooser->priv->sound_settings, SOUND_THEME_KEY, theme_name);
+
+        /* special case for no sounds */
+        if (strcmp (theme_name, NO_SOUNDS_THEME_NAME) == 0) {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, FALSE);
+                return;
+        } else {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, TRUE);
+        }
+
+        g_free (theme_name);
+
+        /* FIXME: reset alert model */
+}
+
+static char *
+load_index_theme_name (const char *index,
+                       char      **parent)
+{
+        GKeyFile *file;
+        char *indexname = NULL;
+        gboolean hidden;
+
+        file = g_key_file_new ();
+        if (g_key_file_load_from_file (file, index, G_KEY_FILE_KEEP_TRANSLATIONS, NULL) == FALSE) {
+                g_key_file_free (file);
+                return NULL;
+        }
+        /* Don't add hidden themes to the list */
+        hidden = g_key_file_get_boolean (file, "Sound Theme", "Hidden", NULL);
+        if (!hidden) {
+                indexname = g_key_file_get_locale_string (file,
+                                                          "Sound Theme",
+                                                          "Name",
+                                                          NULL,
+                                                          NULL);
+
+                /* Save the parent theme, if there's one */
+                if (parent != NULL) {
+                        *parent = g_key_file_get_string (file,
+                                                         "Sound Theme",
+                                                         "Inherits",
+                                                         NULL);
+                }
+        }
+
+        g_key_file_free (file);
+        return indexname;
+}
+
+static void
+sound_theme_in_dir (GHashTable *hash,
+                    const char *dir)
+{
+        GDir *d;
+        const char *name;
+
+        d = g_dir_open (dir, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *dirname, *index, *indexname;
+
+                /* Look for directories */
+                dirname = g_build_filename (dir, name, NULL);
+                if (g_file_test (dirname, G_FILE_TEST_IS_DIR) == FALSE) {
+                        g_free (dirname);
+                        continue;
+                }
+
+                /* Look for index files */
+                index = g_build_filename (dirname, "index.theme", NULL);
+                g_free (dirname);
+
+                /* Check the name of the theme in the index.theme file */
+                indexname = load_index_theme_name (index, NULL);
+                g_free (index);
+                if (indexname == NULL) {
+                        continue;
+                }
+
+                g_hash_table_insert (hash, g_strdup (name), indexname);
+        }
+
+        g_dir_close (d);
+}
+
+static void
+add_theme_to_store (const char   *key,
+                    const char   *value,
+                    GtkListStore *store)
+{
+        char *parent;
+
+        parent = NULL;
+
+        /* Get the parent, if we're checking the custom theme */
+        if (strcmp (key, CUSTOM_THEME_NAME) == 0) {
+                char *name, *path;
+
+                path = custom_theme_dir_path ("index.theme");
+                name = load_index_theme_name (path, &parent);
+                g_free (name);
+                g_free (path);
+        }
+        gtk_list_store_insert_with_values (store, NULL, G_MAXINT,
+                                           THEME_DISPLAY_COL, value,
+                                           THEME_IDENTIFIER_COL, key,
+                                           THEME_PARENT_ID_COL, parent,
+                                           -1);
+        g_free (parent);
+}
+
+static void
+set_combox_for_theme_name (GvcSoundThemeChooser *chooser,
+                           const char           *name)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        gboolean      found;
+
+        /* If the name is empty, use "freedesktop" */
+        if (name == NULL || *name == '\0') {
+                name = "freedesktop";
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+        if (gtk_tree_model_get_iter_first (model, &iter) == FALSE) {
+                return;
+        }
+
+        do {
+                char *value;
+
+                gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &value, -1);
+                found = (value != NULL && strcmp (value, name) == 0);
+                g_free (value);
+
+        } while (!found && gtk_tree_model_iter_next (model, &iter));
+
+        /* When we can't find the theme we need to set, try to set the default
+         * one "freedesktop" */
+        if (found) {
+                gtk_combo_box_set_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter);
+        } else if (strcmp (name, "freedesktop") != 0) {
+                g_debug ("not found, falling back to fdo");
+                set_combox_for_theme_name (chooser, "freedesktop");
+        }
+}
+
+static void
+set_input_feedback_enabled (GvcSoundThemeChooser *chooser,
+                            gboolean              enabled)
+{
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      enabled);
+}
+
+static void
+setup_theme_selector (GvcSoundThemeChooser *chooser)
+{
+        GHashTable           *hash;
+        GtkListStore         *store;
+        GtkCellRenderer      *renderer;
+        const char * const   *data_dirs;
+        const char           *data_dir;
+        char                 *dir;
+        guint                 i;
+
+        /* Add the theme names and their display name to a hash table,
+         * makes it easy to avoid duplicate themes */
+        hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+        data_dirs = g_get_system_data_dirs ();
+        for (i = 0; data_dirs[i] != NULL; i++) {
+                dir = g_build_filename (data_dirs[i], "sounds", NULL);
+                sound_theme_in_dir (hash, dir);
+                g_free (dir);
+        }
+
+        data_dir = g_get_user_data_dir ();
+        dir = g_build_filename (data_dir, "sounds", NULL);
+        sound_theme_in_dir (hash, dir);
+        g_free (dir);
+
+        /* If there isn't at least one theme, make everything
+         * insensitive, LAME! */
+        if (g_hash_table_size (hash) == 0) {
+                gtk_widget_set_sensitive (GTK_WIDGET (chooser), FALSE);
+                g_warning ("Bad setup, install the freedesktop sound theme");
+                g_hash_table_destroy (hash);
+                return;
+        }
+
+        /* Setup the tree model, 3 columns:
+         * - internal theme name/directory
+         * - display theme name
+         * - the internal id for the parent theme, used for the custom theme */
+        store = gtk_list_store_new (THEME_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING);
+
+        /* Add the themes to a combobox */
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           THEME_DISPLAY_COL, _("No sounds"),
+                                           THEME_IDENTIFIER_COL, "__no_sounds",
+                                           THEME_PARENT_ID_COL, NULL,
+                                           -1);
+        g_hash_table_foreach (hash, (GHFunc) add_theme_to_store, store);
+        g_hash_table_destroy (hash);
+
+        /* Set the display */
+        gtk_combo_box_set_model (GTK_COMBO_BOX (chooser->priv->combo_box),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                    renderer,
+                                    TRUE);
+        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                        renderer,
+                                        "text", THEME_DISPLAY_COL,
+                                        NULL);
+
+        g_signal_connect (G_OBJECT (chooser->priv->combo_box),
+                          "changed",
+                          G_CALLBACK (on_combobox_changed),
+                          chooser);
+}
+
+#define GVC_SOUND_SOUND    (xmlChar *) "sound"
+#define GVC_SOUND_NAME     (xmlChar *) "name"
+#define GVC_SOUND_FILENAME (xmlChar *) "filename"
+
+/* Adapted from yelp-toc-pager.c */
+static xmlChar *
+xml_get_and_trim_names (xmlNodePtr node)
+{
+        xmlNodePtr cur;
+        xmlChar *keep_lang = NULL;
+        xmlChar *value;
+        int j, keep_pri = INT_MAX;
+
+        const gchar * const * langs = g_get_language_names ();
+
+        value = NULL;
+
+        for (cur = node->children; cur; cur = cur->next) {
+                if (! xmlStrcmp (cur->name, GVC_SOUND_NAME)) {
+                        xmlChar *cur_lang = NULL;
+                        int cur_pri = INT_MAX;
+
+                        cur_lang = xmlNodeGetLang (cur);
+
+                        if (cur_lang) {
+                                for (j = 0; langs[j]; j++) {
+                                        if (g_str_equal (cur_lang, langs[j])) {
+                                                cur_pri = j;
+                                                break;
+                                        }
+                                }
+                        } else {
+                                cur_pri = INT_MAX - 1;
+                        }
+
+                        if (cur_pri <= keep_pri) {
+                                if (keep_lang)
+                                        xmlFree (keep_lang);
+                                if (value)
+                                        xmlFree (value);
+
+                                value = xmlNodeGetContent (cur);
+
+                                keep_lang = cur_lang;
+                                keep_pri = cur_pri;
+                        } else {
+                                if (cur_lang)
+                                        xmlFree (cur_lang);
+                        }
+                }
+        }
+
+        /* Delete all GVC_SOUND_NAME nodes */
+        cur = node->children;
+        while (cur) {
+                xmlNodePtr this = cur;
+                cur = cur->next;
+                if (! xmlStrcmp (this->name, GVC_SOUND_NAME)) {
+                        xmlUnlinkNode (this);
+                        xmlFreeNode (this);
+                }
+        }
+
+        return value;
+}
+
+static void
+populate_model_from_node (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          xmlNodePtr            node)
+{
+        xmlNodePtr child;
+        xmlChar   *filename;
+        xmlChar   *name;
+
+        filename = NULL;
+        name = xml_get_and_trim_names (node);
+        for (child = node->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+
+                if (xmlStrcmp (child->name, GVC_SOUND_FILENAME) == 0) {
+                        filename = xmlNodeGetContent (child);
+                } else if (xmlStrcmp (child->name, GVC_SOUND_NAME) == 0) {
+                        /* EH? should have been trimmed */
+                }
+        }
+
+        if (filename != NULL && name != NULL) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   ALERT_IDENTIFIER_COL, filename,
+                                                   ALERT_DISPLAY_COL, name,
+                                                   ALERT_SOUND_TYPE_COL, _("Built-in"),
+                                                   ALERT_ACTIVE_COL, FALSE,
+                                                   -1);
+        }
+
+        xmlFree (filename);
+        xmlFree (name);
+}
+
+static void
+populate_model_from_file (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          const char           *filename)
+{
+        xmlDocPtr  doc;
+        xmlNodePtr root;
+        xmlNodePtr child;
+        gboolean   exists;
+
+        exists = g_file_test (filename, G_FILE_TEST_EXISTS);
+        if (! exists) {
+                return;
+        }
+
+        doc = xmlParseFile (filename);
+        if (doc == NULL) {
+                return;
+        }
+
+        root = xmlDocGetRootElement (doc);
+
+        for (child = root->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+                if (xmlStrcmp (child->name, GVC_SOUND_SOUND) != 0) {
+                        continue;
+                }
+
+                populate_model_from_node (chooser, model, child);
+        }
+
+        xmlFreeDoc (doc);
+}
+
+static void
+populate_model_from_dir (GvcSoundThemeChooser *chooser,
+                         GtkTreeModel         *model,
+                         const char           *dirname)
+{
+        GDir       *d;
+        const char *name;
+
+        d = g_dir_open (dirname, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *path;
+
+                if (! g_str_has_suffix (name, ".xml")) {
+                        continue;
+                }
+
+                path = g_build_filename (dirname, name, NULL);
+                populate_model_from_file (chooser, model, path);
+                g_free (path);
+        }
+
+        g_dir_close (d);
+}
+
+static gboolean
+save_alert_sounds (GvcSoundThemeChooser  *chooser,
+                   const char            *id)
+{
+        const char *sounds[3] = { "bell-terminal", "bell-window-system", NULL };
+        char *path;
+
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+        } else {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+                add_custom_file (sounds, id);
+        }
+
+        /* And poke the directory so the theme gets updated */
+        path = custom_theme_dir_path (NULL);
+        if (utime (path, NULL) != 0) {
+                g_warning ("Failed to update mtime for directory '%s': %s",
+                           path, g_strerror (errno));
+        }
+        g_free (path);
+
+        return FALSE;
+}
+
+
+static void
+update_alert_model (GvcSoundThemeChooser  *chooser,
+                    const char            *id)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        gtk_tree_model_get_iter_first (model, &iter);
+        do {
+                gboolean toggled;
+                char    *this_id;
+
+                gtk_tree_model_get (model, &iter,
+                                    ALERT_IDENTIFIER_COL, &this_id,
+                                    -1);
+
+                if (strcmp (this_id, id) == 0) {
+                        toggled = TRUE;
+                } else {
+                        toggled = FALSE;
+                }
+                g_free (this_id);
+
+                gtk_list_store_set (GTK_LIST_STORE (model),
+                                    &iter,
+                                    ALERT_ACTIVE_COL, toggled,
+                                    -1);
+        } while (gtk_tree_model_iter_next (model, &iter));
+}
+
+static void
+update_alert (GvcSoundThemeChooser *chooser,
+              const char           *alert_id)
+{
+        GtkTreeModel *theme_model;
+        GtkTreeIter   iter;
+        char         *theme;
+        char         *parent;
+        gboolean      is_custom;
+        gboolean      is_default;
+        gboolean      add_custom;
+        gboolean      remove_custom;
+
+        theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        /* Get the current theme's name, and set the parent */
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        gtk_tree_model_get (theme_model, &iter,
+                            THEME_IDENTIFIER_COL, &theme,
+                            THEME_IDENTIFIER_COL, &parent,
+                            -1);
+        is_custom = strcmp (theme, CUSTOM_THEME_NAME) == 0;
+        is_default = strcmp (alert_id, DEFAULT_ALERT_ID) == 0;
+
+        /* So a few possibilities:
+         * 1. Named theme, default alert selected: noop
+         * 2. Named theme, alternate alert selected: create new custom with sound
+         * 3. Custom theme, default alert selected: remove sound and possibly custom
+         * 4. Custom theme, alternate alert selected: update custom sound
+         */
+        add_custom = FALSE;
+        remove_custom = FALSE;
+        if (! is_custom && is_default) {
+                /* remove custom just in case */
+                remove_custom = TRUE;
+        } else if (! is_custom && ! is_default) {
+                create_custom_theme (parent);
+                save_alert_sounds (chooser, alert_id);
+                add_custom = TRUE;
+        } else if (is_custom && is_default) {
+                save_alert_sounds (chooser, alert_id);
+                /* after removing files check if it is empty */
+                if (custom_theme_dir_is_empty ()) {
+                        remove_custom = TRUE;
+                }
+        } else if (is_custom && ! is_default) {
+                save_alert_sounds (chooser, alert_id);
+        }
+
+        if (add_custom) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (theme_model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   THEME_DISPLAY_COL, _("Custom"),
+                                                   THEME_IDENTIFIER_COL, CUSTOM_THEME_NAME,
+                                                   THEME_PARENT_ID_COL, theme,
+                                                   -1);
+                set_combox_for_theme_name (chooser, CUSTOM_THEME_NAME);
+        } else if (remove_custom) {
+                gtk_tree_model_get_iter_first (theme_model, &iter);
+                do {
+                        char *this_parent;
+
+                        gtk_tree_model_get (theme_model, &iter,
+                                            THEME_PARENT_ID_COL, &this_parent,
+                                            -1);
+                        if (this_parent != NULL && strcmp (this_parent, CUSTOM_THEME_NAME) != 0) {
+                                g_free (this_parent);
+                                gtk_list_store_remove (GTK_LIST_STORE (theme_model), &iter);
+                                break;
+                        }
+                        g_free (this_parent);
+                } while (gtk_tree_model_iter_next (theme_model, &iter));
+
+                delete_custom_theme_dir ();
+
+                set_combox_for_theme_name (chooser, parent);
+        }
+
+        update_alert_model (chooser, alert_id);
+
+        g_free (theme);
+        g_free (parent);
+}
+
+static void
+on_alert_toggled (GtkCellRendererToggle *renderer,
+                  char                  *path_str,
+                  GvcSoundThemeChooser  *chooser)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreePath  *path;
+        gboolean      toggled;
+        char         *id;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        path = gtk_tree_path_new_from_string (path_str);
+        gtk_tree_model_get_iter (model, &iter, path);
+        gtk_tree_path_free (path);
+
+        id = NULL;
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            ALERT_ACTIVE_COL, &toggled,
+                            -1);
+
+        toggled ^= 1;
+        if (toggled) {
+                update_alert (chooser, id);
+        }
+
+        g_free (id);
+}
+
+static void
+play_preview_for_path (GvcSoundThemeChooser *chooser, GtkTreePath *path)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreeIter   theme_iter;
+        gchar        *id = NULL;
+        gchar        *parent_theme = NULL;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        if (gtk_tree_model_get_iter (model, &iter, path) == FALSE)
+                return;
+
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            -1);
+        if (id == NULL)
+                return;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &theme_iter)) {
+                GtkTreeModel *theme_model;
+                gchar        *theme_id = NULL;
+                gchar        *parent_id = NULL;
+
+                theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+                gtk_tree_model_get (theme_model, &theme_iter,
+                                    THEME_IDENTIFIER_COL, &theme_id,
+                                    THEME_PARENT_ID_COL, &parent_id, -1);
+                if (theme_id && strcmp (theme_id, CUSTOM_THEME_NAME) == 0)
+                        parent_theme = g_strdup (parent_id);
+
+                g_free (theme_id);
+                g_free (parent_id);
+        }
+
+        /* special case: for the default item on custom themes
+         * play the alert for the parent theme */
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                if (parent_theme != NULL) {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_CANBERRA_XDG_THEME_NAME, parent_theme,
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                } else {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                }
+        } else {
+                ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                        CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                        CA_PROP_MEDIA_FILENAME, id,
+                                        CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                        CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                        CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                        CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                        NULL);
+
+        }
+        g_free (parent_theme);
+        g_free (id);
+}
+
+static void
+on_treeview_row_activated (GtkTreeView          *treeview,
+                           GtkTreePath          *path,
+                           GtkTreeViewColumn    *column,
+                           GvcSoundThemeChooser *chooser)
+{
+        play_preview_for_path (chooser, path);
+}
+
+static void
+on_treeview_selection_changed (GtkTreeSelection     *selection,
+                               GvcSoundThemeChooser *chooser)
+{
+        GList        *paths;
+        GtkTreeModel *model;
+        GtkTreePath  *path;
+
+        if (chooser->priv->treeview == NULL)
+                return;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        paths = gtk_tree_selection_get_selected_rows (selection, &model);
+        if (paths == NULL)
+                return;
+
+        path = paths->data;
+        play_preview_for_path (chooser, path);
+
+        g_list_foreach (paths, (GFunc)gtk_tree_path_free, NULL);
+        g_list_free (paths);
+}
+
+static GtkWidget *
+create_alert_treeview (GvcSoundThemeChooser *chooser)
+{
+        GtkListStore         *store;
+        GtkWidget            *treeview;
+        GtkCellRenderer      *renderer;
+        GtkTreeViewColumn    *column;
+        GtkTreeSelection     *selection;
+
+        treeview = gtk_tree_view_new ();
+
+        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
+        g_signal_connect (G_OBJECT (treeview),
+                          "row-activated",
+                          G_CALLBACK (on_treeview_row_activated),
+                          chooser);
+
+        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+        gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+        g_signal_connect (G_OBJECT (selection),
+                          "changed",
+                          G_CALLBACK (on_treeview_selection_changed),
+                          chooser);
+
+        /* Setup the tree model, 3 columns:
+         * - display name
+         * - sound id
+         * - sound type
+         */
+        store = gtk_list_store_new (ALERT_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_BOOLEAN);
+
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           ALERT_IDENTIFIER_COL, DEFAULT_ALERT_ID,
+                                           ALERT_DISPLAY_COL, _("Default"),
+                                           ALERT_SOUND_TYPE_COL, _("From theme"),
+                                           ALERT_ACTIVE_COL, TRUE,
+                                           -1);
+
+        populate_model_from_dir (chooser, GTK_TREE_MODEL (store), SOUND_SET_DIR);
+
+        gtk_tree_view_set_model (GTK_TREE_VIEW (treeview),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_toggle_new ();
+        gtk_cell_renderer_toggle_set_radio (GTK_CELL_RENDERER_TOGGLE (renderer), TRUE);
+
+        column = gtk_tree_view_column_new_with_attributes (NULL,
+                                                           renderer,
+                                                           "active", ALERT_ACTIVE_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+        g_signal_connect (renderer,
+                          "toggled",
+                          G_CALLBACK (on_alert_toggled),
+                          chooser);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Name"),
+                                                           renderer,
+                                                           "text", ALERT_DISPLAY_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Type"),
+                                                           renderer,
+                                                           "text", ALERT_SOUND_TYPE_COL,
+                                                           NULL);
+
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        return treeview;
+}
+
+static int
+get_file_type (const char *sound_name,
+               char      **linked_name)
+{
+        char *name, *filename;
+
+        *linked_name = NULL;
+
+        name = g_strdup_printf ("%s.disabled", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_REGULAR) != FALSE) {
+                g_free (filename);
+                return SOUND_TYPE_OFF;
+        }
+        g_free (filename);
+
+        /* We only check for .ogg files because those are the
+         * only ones we create */
+        name = g_strdup_printf ("%s.ogg", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_SYMLINK) != FALSE) {
+                *linked_name = g_file_read_link (filename, NULL);
+                g_free (filename);
+                return SOUND_TYPE_CUSTOM;
+        }
+        g_free (filename);
+
+        return SOUND_TYPE_BUILTIN;
+}
+
+static void
+update_alerts_from_theme_name (GvcSoundThemeChooser *chooser,
+                               const gchar          *name)
+{
+        if (strcmp (name, CUSTOM_THEME_NAME) != 0) {
+                /* reset alert to default */
+                update_alert (chooser, DEFAULT_ALERT_ID);
+        } else {
+                int   sound_type;
+                char *linkname;
+
+                linkname = NULL;
+                sound_type = get_file_type ("bell-terminal", &linkname);
+                g_debug ("Found link: %s", linkname);
+                if (sound_type == SOUND_TYPE_CUSTOM) {
+                        update_alert (chooser, linkname);
+                }
+        }
+}
+
+static void
+update_theme (GvcSoundThemeChooser *chooser)
+{
+        char        *theme_name;
+        gboolean     events_enabled;
+        gboolean     feedback_enabled;
+
+        feedback_enabled = g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY);
+        set_input_feedback_enabled (chooser, feedback_enabled);
+
+        events_enabled = g_settings_get_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY);
+        if (events_enabled) {
+                theme_name = g_settings_get_string (chooser->priv->sound_settings, SOUND_THEME_KEY);
+        } else {
+                theme_name = g_strdup (NO_SOUNDS_THEME_NAME);
+        }
+
+        gtk_widget_set_sensitive (chooser->priv->selection_box, events_enabled);
+        gtk_widget_set_sensitive (chooser->priv->click_feedback_button, events_enabled);
+
+        set_combox_for_theme_name (chooser, theme_name);
+
+        update_alerts_from_theme_name (chooser, theme_name);
+
+        g_free (theme_name);
+}
+
+static void
+gvc_sound_theme_chooser_class_init (GvcSoundThemeChooserClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_sound_theme_chooser_dispose;
+}
+
+static void
+on_click_feedback_toggled (GtkToggleButton      *button,
+                           GvcSoundThemeChooser *chooser)
+{
+        gboolean enabled;
+
+        enabled = gtk_toggle_button_get_active (button);
+
+        g_settings_set_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY, enabled);
+}
+
+static void
+on_key_changed (GSettings            *settings,
+                gchar                *key,
+                GvcSoundThemeChooser *chooser)
+{
+        if (!strcmp (key, EVENT_SOUNDS_KEY) ||
+            !strcmp (key, SOUND_THEME_KEY) ||
+            !strcmp (key, INPUT_SOUNDS_KEY))
+                update_theme (chooser);
+}
+
+static void
+setup_list_size_constraint (GtkWidget *widget,
+                            GtkWidget *to_size)
+{
+        GtkRequisition req;
+        gint           sc_height;
+        int            max_height;
+
+        /* Constrain height to be the tree height up to a max */
+        gdk_window_get_geometry (gdk_screen_get_root_window (gtk_widget_get_screen (widget)),
+                                 NULL, NULL, NULL, &sc_height);
+
+        max_height = sc_height / 4;
+
+        // XXX this doesn't work
+        gtk_widget_get_preferred_size (to_size, NULL, &req);
+
+        gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (widget),
+                                                    MIN (req.height, max_height));
+}
+
+static void
+gvc_sound_theme_chooser_init (GvcSoundThemeChooser *chooser)
+{
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *scrolled_window;
+        gchar       *str;
+
+        chooser->priv = gvc_sound_theme_chooser_get_instance_private (chooser);
+
+        chooser->priv->theme_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->theme_box, FALSE, FALSE, 0);
+
+        label = gtk_label_new_with_mnemonic (_("Sound _theme:"));
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), label, FALSE, FALSE, 0);
+        chooser->priv->combo_box = gtk_combo_box_new ();
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), chooser->priv->combo_box, FALSE, FALSE, 6);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->combo_box);
+
+        chooser->priv->sound_settings = g_settings_new (KEY_SOUNDS_SCHEMA);
+
+        g_signal_connect (G_OBJECT (chooser->priv->sound_settings),
+                          "changed",
+                          G_CALLBACK (on_key_changed),
+                          chooser);
+
+        str = g_strdup_printf ("<b>%s</b>", _("C_hoose an alert sound:"));
+        chooser->priv->selection_box = box = gtk_frame_new (str);
+        g_free (str);
+
+        label = gtk_frame_get_label_widget (GTK_FRAME (box));
+        gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
+        gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+        gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
+
+        gtk_box_pack_start (GTK_BOX (chooser), box, TRUE, TRUE, 6);
+
+        chooser->priv->treeview = create_alert_treeview (chooser);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->treeview);
+
+        scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+        gtk_widget_set_hexpand (scrolled_window, TRUE);
+        gtk_widget_set_vexpand (scrolled_window, TRUE);
+        gtk_widget_set_margin_top (scrolled_window, 6);
+
+        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+                                        GTK_POLICY_NEVER,
+                                        GTK_POLICY_AUTOMATIC);
+        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
+                                             GTK_SHADOW_IN);
+
+        gtk_container_add (GTK_CONTAINER (scrolled_window), chooser->priv->treeview);
+        gtk_container_add (GTK_CONTAINER (box), scrolled_window);
+
+        chooser->priv->click_feedback_button = gtk_check_button_new_with_mnemonic (_("Enable _window and button sounds"));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY));
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->click_feedback_button,
+                            FALSE, FALSE, 0);
+
+        g_signal_connect (G_OBJECT (chooser->priv->click_feedback_button),
+                          "toggled",
+                          G_CALLBACK (on_click_feedback_toggled),
+                          chooser);
+
+        setup_theme_selector (chooser);
+        update_theme (chooser);
+
+        setup_list_size_constraint (scrolled_window, chooser->priv->treeview);
+}
+
+static void
+gvc_sound_theme_chooser_dispose (GObject *object)
+{
+        GvcSoundThemeChooser *chooser;
+
+        chooser = GVC_SOUND_THEME_CHOOSER (object);
+
+        g_clear_object (&chooser->priv->sound_settings);
+
+        G_OBJECT_CLASS (gvc_sound_theme_chooser_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_sound_theme_chooser_new (void)
+{
+        return g_object_new (GVC_TYPE_SOUND_THEME_CHOOSER,
+                                "spacing", 6,
+                                "orientation", GTK_ORIENTATION_VERTICAL,
+                                NULL);
+}
+
+
+
+ + + diff --git a/2020-04-25-161832-9866-cppcheck@0de220f56e3d_master/2.html b/2020-04-25-161832-9866-cppcheck@0de220f56e3d_master/2.html new file mode 100644 index 0000000..bacfabb --- /dev/null +++ b/2020-04-25-161832-9866-cppcheck@0de220f56e3d_master/2.html @@ -0,0 +1,1110 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <canberra.h>
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-speaker-test.h"
+#include "gvc-utils.h"
+
+struct _GvcSpeakerTestPrivate
+{
+        GArray           *controls;
+        ca_context       *canberra;
+        MateMixerStream  *stream;
+};
+
+enum {
+        PROP_0,
+        PROP_STREAM,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_speaker_test_dispose    (GObject             *object);
+static void gvc_speaker_test_finalize   (GObject             *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSpeakerTest, gvc_speaker_test, GTK_TYPE_GRID)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+typedef struct {
+        MateMixerChannelPosition position;
+        guint left;
+        guint top;
+} TablePosition;
+
+static const TablePosition positions[] = {
+        /* Position, X, Y */
+        { MATE_MIXER_CHANNEL_FRONT_LEFT, 0, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_LEFT_CENTER, 1, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_CENTER, 2, 0, },
+        { MATE_MIXER_CHANNEL_MONO, 2, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT_CENTER, 3, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT, 4, 0, },
+        { MATE_MIXER_CHANNEL_SIDE_LEFT, 0, 1, },
+        { MATE_MIXER_CHANNEL_SIDE_RIGHT, 4, 1, },
+        { MATE_MIXER_CHANNEL_BACK_LEFT, 0, 2, },
+        { MATE_MIXER_CHANNEL_BACK_CENTER, 2, 2, },
+        { MATE_MIXER_CHANNEL_BACK_RIGHT, 4, 2, },
+        { MATE_MIXER_CHANNEL_LFE, 3, 2 }
+};
+
+MateMixerStream *
+gvc_speaker_test_get_stream (GvcSpeakerTest *test)
+{
+        g_return_val_if_fail (GVC_IS_SPEAKER_TEST (test), NULL);
+
+        return test->priv->stream;
+}
+
+static void
+gvc_speaker_test_set_stream (GvcSpeakerTest *test, MateMixerStream *stream)
+{
+        MateMixerStreamControl *control;
+        const gchar            *name;
+        guint                   i;
+
+        name = mate_mixer_stream_get_name (stream);
+        control = mate_mixer_stream_get_default_control (stream);
+
+        ca_context_change_device (test->priv->canberra, name);
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                gboolean has_position =
+                        mate_mixer_stream_control_has_channel_position (control, positions[i].position);
+
+                gtk_widget_set_visible (g_array_index (test->priv->controls, GtkWidget *, i),
+                                        has_position);
+        }
+
+        test->priv->stream = g_object_ref (stream);
+}
+
+static void
+gvc_speaker_test_set_property (GObject       *object,
+                               guint          prop_id,
+                               const GValue  *value,
+                               GParamSpec    *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                gvc_speaker_test_set_stream (self, g_value_get_object (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_get_property (GObject     *object,
+                               guint        prop_id,
+                               GValue      *value,
+                               GParamSpec  *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                g_value_set_object (value, self->priv->stream);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_class_init (GvcSpeakerTestClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose  = gvc_speaker_test_dispose;
+        object_class->finalize = gvc_speaker_test_finalize;
+        object_class->set_property = gvc_speaker_test_set_property;
+        object_class->get_property = gvc_speaker_test_get_property;
+
+        properties[PROP_STREAM] =
+                g_param_spec_object ("stream",
+                                     "Stream",
+                                     "MateMixer stream",
+                                     MATE_MIXER_TYPE_STREAM,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+}
+
+static const gchar *
+sound_name (MateMixerChannelPosition position)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return "audio-channel-front-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return "audio-channel-front-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return "audio-channel-front-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return "audio-channel-rear-left";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return "audio-channel-rear-right";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return "audio-channel-rear-center";
+        case MATE_MIXER_CHANNEL_LFE:
+                return "audio-channel-lfe";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return "audio-channel-side-left";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return "audio-channel-side-right";
+        default:
+                return NULL;
+        }
+}
+
+static const gchar *
+icon_name (MateMixerChannelPosition position, gboolean playing)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return playing
+                        ? "audio-speaker-left-testing"
+                        : "audio-speaker-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return playing
+                        ? "audio-speaker-right-testing"
+                        : "audio-speaker-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return playing
+                        ? "audio-speaker-center-testing"
+                        : "audio-speaker-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return playing
+                        ? "audio-speaker-left-back-testing"
+                        : "audio-speaker-left-back";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return playing
+                        ? "audio-speaker-right-back-testing"
+                        : "audio-speaker-right-back";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return playing
+                        ? "audio-speaker-center-back-testing"
+                        : "audio-speaker-center-back";
+        case MATE_MIXER_CHANNEL_LFE:
+                return playing
+                        ? "audio-subwoofer-testing"
+                        : "audio-subwoofer";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return playing
+                        ? "audio-speaker-left-side-testing"
+                        : "audio-speaker-left-side";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return playing
+                        ? "audio-speaker-right-side-testing"
+                        : "audio-speaker-right-side";
+        default:
+                return NULL;
+        }
+}
+
+static void
+update_button (GtkWidget *control)
+{
+        GtkWidget *button;
+        GtkWidget *image;
+        gboolean   playing;
+        MateMixerChannelPosition position;
+
+        button = g_object_get_data (G_OBJECT (control), "button");
+        image  = g_object_get_data (G_OBJECT (control), "image");
+
+        position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+        playing  = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        gtk_button_set_label (GTK_BUTTON (button), playing ? _("Stop") : _("Test"));
+
+        gtk_image_set_from_icon_name (GTK_IMAGE (image),
+                                      icon_name (position, playing),
+                                      GTK_ICON_SIZE_DIALOG);
+}
+
+static gboolean
+idle_cb (GtkWidget *control)
+{
+        if (control != NULL) {
+                /* This is called in the background thread, hence forward to main thread
+                 * via idle callback */
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+
+                update_button (control);
+        }
+        return FALSE;
+}
+
+static void
+finish_cb (ca_context *c, uint32_t id, int error_code, void *userdata)
+{
+        GtkWidget *control = (GtkWidget *) userdata;
+
+        if (error_code == CA_ERROR_DESTROYED || control == NULL)
+                return;
+
+        g_idle_add ((GSourceFunc) idle_cb, control);
+}
+
+static void
+on_test_button_clicked (GtkButton *button, GtkWidget *control)
+{
+        gboolean    playing;
+        ca_context *canberra;
+
+        canberra = g_object_get_data (G_OBJECT (control), "canberra");
+
+        ca_context_cancel (canberra, 1);
+
+        playing = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        if (playing) {
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        } else {
+                MateMixerChannelPosition position;
+                const gchar *name;
+                ca_proplist *proplist;
+
+                position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+
+                ca_proplist_create (&proplist);
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_ROLE, "test");
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_NAME,
+                                  gvc_channel_position_to_pretty_string (position));
+                ca_proplist_sets (proplist,
+                                  CA_PROP_CANBERRA_FORCE_CHANNEL,
+                                  gvc_channel_position_to_pulse_string (position));
+
+                ca_proplist_sets (proplist, CA_PROP_CANBERRA_ENABLE, "1");
+
+                name = sound_name (position);
+                if (name != NULL) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, name);
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, "audio-test-signal");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets(proplist, CA_PROP_EVENT_ID, "bell-window-system");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (playing));
+        }
+
+        update_button (control);
+}
+
+static GtkWidget *
+create_control (ca_context *canberra, MateMixerChannelPosition position)
+{
+        GtkWidget   *control;
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *image;
+        GtkWidget   *test_button;
+        const gchar *name;
+
+        control = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+        box     = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        g_object_set_data (G_OBJECT (control), "position", GINT_TO_POINTER (position));
+        g_object_set_data (G_OBJECT (control), "canberra", canberra);
+
+        name = icon_name (position, FALSE);
+        if (name == NULL)
+                name = "audio-volume-medium";
+
+        image = gtk_image_new_from_icon_name (name, GTK_ICON_SIZE_DIALOG);
+        g_object_set_data (G_OBJECT (control), "image", image);
+        gtk_box_pack_start (GTK_BOX (control), image, FALSE, FALSE, 0);
+
+        label = gtk_label_new (gvc_channel_position_to_pretty_string (position));
+        gtk_box_pack_start (GTK_BOX (control), label, FALSE, FALSE, 0);
+
+        test_button = gtk_button_new_with_label (_("Test"));
+        g_signal_connect (G_OBJECT (test_button),
+                          "clicked",
+                          G_CALLBACK (on_test_button_clicked),
+                          control);
+
+        g_object_set_data (G_OBJECT (control), "button", test_button);
+
+        gtk_box_pack_start (GTK_BOX (box), test_button, TRUE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (control), box, FALSE, FALSE, 0);
+
+        gtk_widget_show_all (control);
+
+        return control;
+}
+
+static void
+create_controls (GvcSpeakerTest *test)
+{
+        guint i;
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                GtkWidget *control = create_control (test->priv->canberra, positions[i].position);
+
+                gtk_grid_attach (GTK_GRID (test),
+                                 control,
+                                 positions[i].left,
+                                 positions[i].top,
+                                 1, 1);
+                g_array_insert_val (test->priv->controls, i, control);
+        }
+}
+
+static void
+gvc_speaker_test_init (GvcSpeakerTest *test)
+{
+        GtkWidget *face;
+
+        test->priv = gvc_speaker_test_get_instance_private (test);
+
+        gtk_container_set_border_width (GTK_CONTAINER (test), 12);
+
+        face = gtk_image_new_from_icon_name ("face-smile", GTK_ICON_SIZE_DIALOG);
+
+        gtk_grid_attach (GTK_GRID (test),
+                         face,
+                         1, 1,
+                         3, 1);
+
+
+        gtk_grid_set_baseline_row (GTK_GRID (test), 1);
+        gtk_widget_show (face);
+
+        ca_context_create (&test->priv->canberra);
+
+        /* The test sounds are played for a single channel, set up using the
+         * FORCE_CHANNEL property of libcanberra; this property is only supported
+         * in the PulseAudio backend, so avoid other backends completely */
+        ca_context_set_driver (test->priv->canberra, "pulse");
+
+        ca_context_change_props (test->priv->canberra,
+                                 CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+                                 CA_PROP_APPLICATION_NAME, _("Volume Control"),
+                                 CA_PROP_APPLICATION_VERSION, VERSION,
+                                 CA_PROP_APPLICATION_ICON_NAME, "multimedia-volume-control",
+                                 NULL);
+
+        test->priv->controls = g_array_new (FALSE, FALSE, sizeof (GtkWidget *));
+
+        create_controls (test);
+}
+
+static void
+gvc_speaker_test_dispose (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        g_clear_object (&test->priv->stream);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->dispose (object);
+}
+
+static void
+gvc_speaker_test_finalize (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        ca_context_destroy (test->priv->canberra);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->finalize (object);
+}
+
+GtkWidget *
+gvc_speaker_test_new (MateMixerStream *stream)
+{
+        GObject *test;
+
+        g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL);
+
+        test = g_object_new (GVC_TYPE_SPEAKER_TEST,
+                             "row-spacing", 6,
+                             "column-spacing", 6,
+                             "row-homogeneous", TRUE,
+                             "column-homogeneous", TRUE,
+                             "stream", stream,
+                             NULL);
+
+        return GTK_WIDGET (test);
+}
+
+
+
+ + + diff --git a/2020-04-25-161832-9866-cppcheck@0de220f56e3d_master/index.html b/2020-04-25-161832-9866-cppcheck@0de220f56e3d_master/index.html new file mode 100644 index 0000000..59baeb0 --- /dev/null +++ b/2020-04-25-161832-9866-cppcheck@0de220f56e3d_master/index.html @@ -0,0 +1,108 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
mate-volume-control/gvc-combo-box.c
70unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
mate-volume-control/gvc-sound-theme-chooser.c
735ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
746ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
758ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
mate-volume-control/gvc-speaker-test.c
53unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+ + + diff --git a/2020-04-25-161832-9866-cppcheck@0de220f56e3d_master/stats.html b/2020-04-25-161832-9866-cppcheck@0de220f56e3d_master/stats.html new file mode 100644 index 0000000..3fb6add --- /dev/null +++ b/2020-04-25-161832-9866-cppcheck@0de220f56e3d_master/stats.html @@ -0,0 +1,93 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+

Top 10 files for error severity, total findings: 2
+   1  mate-volume-control/gvc-speaker-test.c
+   1  mate-volume-control/gvc-combo-box.c
+

+

Top 10 files for information severity, total findings: 3
+   3  mate-volume-control/gvc-sound-theme-chooser.c
+

+ +
+ + + diff --git a/2020-04-25-161832-9866-cppcheck@0de220f56e3d_master/style.css b/2020-04-25-161832-9866-cppcheck@0de220f56e3d_master/style.css new file mode 100644 index 0000000..c39571c --- /dev/null +++ b/2020-04-25-161832-9866-cppcheck@0de220f56e3d_master/style.css @@ -0,0 +1,149 @@ + +body { + font: 13px Arial, Verdana, Sans-Serif; + margin: 0; + width: auto; +} + +h1 { + margin: 10px; +} + +#footer > p { + margin: 4px; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + border: 1px dotted black; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #B6B6B4; +} + +.inconclusive2 { + background-color: #B6B6B4; + border: 1px dotted black; + display: inline-block; + margin-left: 4px; +} + +div.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +div.verbose div.content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid black; + background-color: #FFFFCC; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +#header { + border-bottom: thin solid #aaa; +} + +#menu { + float: left; + margin-top: 5px; + text-align: left; + width: 150px; + /*height: 75%;*/ + position: fixed; + overflow: auto; + z-index: 1; +} + +#menu_index { + float: left; + margin-top: 5px; + padding-left: 5px; + text-align: left; + width: 300px; + /*height: 75%;*/ + position: fixed; + overflow: auto; + z-index: 1; +} + +#menu > a { + display: block; + margin-left: 10px; + font: 12px; + z-index: 1; +} + +#filename { + margin-left: 10px; + font: 12px; + z-index: 1; +} + +.highlighttable { + background-color:white; + z-index: 10; + position: relative; + margin: -10 px; +} + +#content { + background-color: white; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + float: left; + margin: 5px; + margin-left: 10px; + padding: 0 10px 10px 10px; + width: 80%; + padding-left: 150px; +} + +#content_index { + background-color: white; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + float: left; + margin: 5px; + margin-left: 10px; + padding: 0 10px 10px 10px; + width: 80%; + padding-left: 300px; +} + +.linenos { + border-right: thin solid #aaa; + color: lightgray; + padding-right: 6px; +} + +#footer { + border-top: thin solid #aaa; + clear: both; + font-size: 90%; + margin-top: 5px; +} + +#footer ul { + list-style-type: none; + padding-left: 0; +} diff --git a/2020-06-17-120043-0378-cppcheck@7a8fcf3b18bf_master/0.html b/2020-06-17-120043-0378-cppcheck@7a8fcf3b18bf_master/0.html new file mode 100644 index 0000000..e262ed0 --- /dev/null +++ b/2020-06-17-120043-0378-cppcheck@7a8fcf3b18bf_master/0.html @@ -0,0 +1,1038 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-combo-box.h"
+
+struct _GvcComboBoxPrivate
+{
+        GtkWidget       *drop_box;
+        GtkWidget       *start_box;
+        GtkWidget       *end_box;
+        GtkWidget       *label;
+        GtkWidget       *button;
+        GtkTreeModel    *model;
+        GtkWidget       *combobox;
+        MateMixerSwitch *swtch;
+};
+
+enum {
+        COL_NAME,
+        COL_HUMAN_NAME,
+        NUM_COLS
+};
+
+enum {
+        CHANGING,
+        BUTTON_CLICKED,
+        LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+enum {
+        PROP_0,
+        PROP_SWITCH,
+        PROP_LABEL,
+        PROP_SHOW_BUTTON,
+        PROP_BUTTON_LABEL,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_combo_box_dispose    (GObject          *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcComboBox, gvc_combo_box, GTK_TYPE_BOX)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+MateMixerSwitch *
+gvc_combo_box_get_switch (GvcComboBox *combobox)
+{
+        g_return_val_if_fail (GVC_IS_COMBO_BOX (combobox), NULL);
+
+        return combobox->priv->swtch;
+}
+
+void
+gvc_combo_box_set_size_group (GvcComboBox  *combobox,
+                              GtkSizeGroup *group,
+                              gboolean      symmetric)
+{
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (GTK_IS_SIZE_GROUP (group));
+
+        if (group != NULL) {
+                gtk_size_group_add_widget (group, combobox->priv->start_box);
+                if (symmetric == TRUE)
+                        gtk_size_group_add_widget (group, combobox->priv->end_box);
+        }
+        gtk_widget_queue_draw (GTK_WIDGET (combobox));
+}
+
+static void
+on_switch_active_option_notify (MateMixerSwitch *swtch,
+                                GParamSpec      *pspec,
+                                GvcComboBox     *combobox)
+{
+        GtkTreeIter            iter;
+        MateMixerSwitchOption *active;
+        gboolean               cont;
+        const gchar           *name;
+
+        active = mate_mixer_switch_get_active_option (swtch);
+        if (G_UNLIKELY (active == NULL)) {
+                g_warn_if_reached ();
+                return;
+        }
+
+        /* Select the newly activated switch option in the combo box */
+        name = mate_mixer_switch_option_get_name (active);
+        cont = gtk_tree_model_get_iter_first (combobox->priv->model, &iter);
+        while (cont == TRUE) {
+                gchar *current;
+
+                gtk_tree_model_get (combobox->priv->model, &iter,
+                                    COL_NAME, &current,
+                                    -1);
+                if (g_strcmp0 (name, current) == 0) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox), &iter);
+                        g_free (current);
+                        return;
+                }
+                g_free (current);
+
+                cont = gtk_tree_model_iter_next (combobox->priv->model, &iter);
+        }
+        g_warning ("Could not find switch option '%s' in combo box", name);
+}
+
+static void
+gvc_combo_box_set_switch (GvcComboBox *combobox, MateMixerSwitch *swtch)
+{
+        MateMixerSwitchOption *active;
+        const GList           *options;
+
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (MATE_MIXER_IS_SWITCH (swtch));
+
+        combobox->priv->swtch = g_object_ref (swtch);
+
+        active  = mate_mixer_switch_get_active_option (swtch);
+        options = mate_mixer_switch_list_options (swtch);
+        while (options != NULL) {
+                GtkTreeIter            iter;
+                MateMixerSwitchOption *option = MATE_MIXER_SWITCH_OPTION (options->data);
+
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (combobox->priv->model),
+                                                   &iter,
+                                                   G_MAXINT,
+                                                   COL_NAME,
+                                                   mate_mixer_switch_option_get_name (option),
+                                                   COL_HUMAN_NAME,
+                                                   mate_mixer_switch_option_get_label (option),
+                                                   -1);
+
+                /* Select the currently active option of the switch */
+                if (option == active) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox),
+                                                       &iter);
+                }
+                options = options->next;
+        }
+
+        g_signal_connect (G_OBJECT (swtch),
+                          "notify::active-option",
+                          G_CALLBACK (on_switch_active_option_notify),
+                          combobox);
+}
+
+static void
+gvc_combo_box_set_property (GObject       *object,
+                            guint          prop_id,
+                            const GValue  *value,
+                            GParamSpec    *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                gvc_combo_box_set_switch (self, g_value_get_object (value));
+                break;
+        case PROP_LABEL:
+                gtk_label_set_text_with_mnemonic (GTK_LABEL (self->priv->label), g_value_get_string (value));
+                break;
+        case PROP_BUTTON_LABEL:
+                gtk_button_set_label (GTK_BUTTON (self->priv->button), g_value_get_string (value));
+                break;
+        case PROP_SHOW_BUTTON:
+                gtk_widget_set_visible (self->priv->button, g_value_get_boolean (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_get_property (GObject     *object,
+                            guint        prop_id,
+                            GValue      *value,
+                            GParamSpec  *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                g_value_set_object (value, self->priv->swtch);
+                break;
+        case PROP_LABEL:
+                g_value_set_string (value, gtk_label_get_text (GTK_LABEL (self->priv->label)));
+                break;
+        case PROP_BUTTON_LABEL:
+                g_value_set_string (value, gtk_button_get_label (GTK_BUTTON (self->priv->button)));
+                break;
+        case PROP_SHOW_BUTTON:
+                g_value_set_boolean (value, gtk_widget_get_visible (self->priv->button));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_class_init (GvcComboBoxClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_combo_box_dispose;
+        object_class->set_property = gvc_combo_box_set_property;
+        object_class->get_property = gvc_combo_box_get_property;
+
+        properties[PROP_SWITCH] =
+                g_param_spec_object ("switch",
+                                     "switch",
+                                     "The MateMixerSwitch",
+                                     MATE_MIXER_TYPE_SWITCH,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_LABEL] =
+                g_param_spec_string ("label",
+                                     "label",
+                                     "The combo box label",
+                                     _("_Profile:"),
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_SHOW_BUTTON] =
+                g_param_spec_boolean ("show-button",
+                                      "show-button",
+                                      "Whether to show the button",
+                                      FALSE,
+                                      G_PARAM_READWRITE |
+                                      G_PARAM_CONSTRUCT |
+                                      G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_BUTTON_LABEL] =
+                g_param_spec_string ("button-label",
+                                     "button-label",
+                                     "The button's label",
+                                     "",
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+
+        signals[CHANGING] =
+                g_signal_new ("changing",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, changing),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__OBJECT,
+                              G_TYPE_NONE,
+                              1,
+                              MATE_MIXER_TYPE_SWITCH_OPTION);
+
+        signals[BUTTON_CLICKED] =
+                g_signal_new ("button-clicked",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, button_clicked),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
+}
+
+static void
+on_combo_box_changed (GtkComboBox *widget, GvcComboBox *combobox)
+{
+        GtkTreeIter            iter;
+        gchar                 *name;
+        MateMixerSwitchOption *option;
+
+        if (G_UNLIKELY (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter) == FALSE))
+                return;
+
+        gtk_tree_model_get (combobox->priv->model, &iter,
+                            COL_NAME, &name,
+                            -1);
+
+        option = mate_mixer_switch_get_option (combobox->priv->swtch, name);
+        if (G_UNLIKELY (option == NULL)) {
+                g_warn_if_reached ();
+                g_free (name);
+                return;
+        }
+
+        /* Inform that we are about to change the active option of the switch */
+        g_signal_emit (combobox, signals[CHANGING], 0, option);
+
+        mate_mixer_switch_set_active_option (combobox->priv->swtch, option);
+        g_free (name);
+}
+
+static void
+on_combo_box_button_clicked (GtkButton *button, GvcComboBox *combobox)
+{
+        /* The meaning of the button is defined by the owner, so only notify
+         * when it is clicked on */
+        g_signal_emit (combobox, signals[BUTTON_CLICKED], 0);
+}
+
+static void
+gvc_combo_box_init (GvcComboBox *combobox)
+{
+        GtkWidget       *frame;
+        GtkCellRenderer *renderer;
+
+        frame = gtk_frame_new (NULL);
+        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
+
+        combobox->priv = gvc_combo_box_get_instance_private (combobox);
+
+        combobox->priv->model = GTK_TREE_MODEL (gtk_list_store_new (NUM_COLS,
+                                                                    G_TYPE_STRING,
+                                                                    G_TYPE_STRING));
+
+        combobox->priv->combobox = gtk_combo_box_new_with_model (combobox->priv->model);
+
+        combobox->priv->label = gtk_label_new (NULL);
+
+        gtk_label_set_xalign (GTK_LABEL (combobox->priv->label), 0.0);
+        gtk_label_set_yalign (GTK_LABEL (combobox->priv->label), 0.5);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (combobox->priv->label),
+                                       combobox->priv->combobox);
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                    renderer,
+                                    FALSE);
+        gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                       renderer,
+                                       "text",
+                                       COL_HUMAN_NAME);
+
+        combobox->priv->drop_box  = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->start_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->end_box   = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+        /* Make sure the combo box does not get too long on long profile names */
+        g_object_set (G_OBJECT (renderer),
+                      "ellipsize",
+                      PANGO_ELLIPSIZE_END,
+                      NULL);
+
+        gtk_combo_box_set_popup_fixed_width (GTK_COMBO_BOX (combobox->priv->combobox), FALSE);
+
+        gtk_box_pack_start (GTK_BOX (combobox),
+                            frame,
+                            TRUE, TRUE, 0);
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->start_box,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->start_box),
+                            combobox->priv->label,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->combobox,
+                            TRUE, TRUE, 0);
+
+        combobox->priv->button = gtk_button_new_with_label ("");
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->button,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->end_box,
+                            FALSE, FALSE, 0);
+
+        gtk_container_add (GTK_CONTAINER (frame), combobox->priv->drop_box);
+
+        g_signal_connect (G_OBJECT (combobox->priv->combobox),
+                          "changed",
+                          G_CALLBACK (on_combo_box_changed),
+                          combobox);
+        g_signal_connect (G_OBJECT (combobox->priv->button),
+                          "clicked",
+                          G_CALLBACK (on_combo_box_button_clicked),
+                          combobox);
+
+        gtk_widget_set_no_show_all (combobox->priv->button, TRUE);
+        gtk_widget_show_all (frame);
+}
+
+static void
+gvc_combo_box_dispose (GObject *object)
+{
+        GvcComboBox *combobox;
+
+        combobox = GVC_COMBO_BOX (object);
+
+        if (G_LIKELY (combobox->priv->swtch != NULL)) {
+                g_signal_handlers_disconnect_by_func (G_OBJECT (combobox->priv->swtch),
+                                                      G_CALLBACK (on_switch_active_option_notify),
+                                                      combobox);
+                g_clear_object (&combobox->priv->swtch);
+        }
+
+        g_clear_object (&combobox->priv->model);
+
+        G_OBJECT_CLASS (gvc_combo_box_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_combo_box_new (MateMixerSwitch *swtch, const gchar *label)
+{
+        return g_object_new (GVC_TYPE_COMBO_BOX,
+                             "switch", swtch,
+                             "label", label,
+                             "orientation", GTK_ORIENTATION_HORIZONTAL,
+                             NULL);
+}
+
+
+
+ + + diff --git a/2020-06-17-120043-0378-cppcheck@7a8fcf3b18bf_master/1.html b/2020-06-17-120043-0378-cppcheck@7a8fcf3b18bf_master/1.html new file mode 100644 index 0000000..67179f2 --- /dev/null +++ b/2020-06-17-120043-0378-cppcheck@7a8fcf3b18bf_master/1.html @@ -0,0 +1,2368 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
+ * Copyright (C) 2008 William Jon McCann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <utime.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+#include <canberra-gtk.h>
+#include <libxml/tree.h>
+
+#include "gvc-sound-theme-chooser.h"
+#include "sound-theme-file-utils.h"
+
+struct GvcSoundThemeChooserPrivate
+{
+        GtkWidget *combo_box;
+        GtkWidget *treeview;
+        GtkWidget *theme_box;
+        GtkWidget *selection_box;
+        GtkWidget *click_feedback_button;
+        GSettings *sound_settings;
+};
+
+static void     gvc_sound_theme_chooser_dispose   (GObject            *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSoundThemeChooser, gvc_sound_theme_chooser, GTK_TYPE_BOX)
+
+#define KEY_SOUNDS_SCHEMA          "org.mate.sound"
+#define EVENT_SOUNDS_KEY           "event-sounds"
+#define INPUT_SOUNDS_KEY           "input-feedback-sounds"
+#define SOUND_THEME_KEY            "theme-name"
+
+#define DEFAULT_ALERT_ID        "__default"
+#define CUSTOM_THEME_NAME       "__custom"
+#define NO_SOUNDS_THEME_NAME    "__no_sounds"
+
+enum {
+        THEME_DISPLAY_COL,
+        THEME_IDENTIFIER_COL,
+        THEME_PARENT_ID_COL,
+        THEME_NUM_COLS
+};
+
+enum {
+        ALERT_DISPLAY_COL,
+        ALERT_IDENTIFIER_COL,
+        ALERT_SOUND_TYPE_COL,
+        ALERT_ACTIVE_COL,
+        ALERT_NUM_COLS
+};
+
+enum {
+        SOUND_TYPE_UNSET,
+        SOUND_TYPE_OFF,
+        SOUND_TYPE_DEFAULT_FROM_THEME,
+        SOUND_TYPE_BUILTIN,
+        SOUND_TYPE_CUSTOM
+};
+
+static void
+on_combobox_changed (GtkComboBox          *widget,
+                     GvcSoundThemeChooser *chooser)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        char         *theme_name;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &theme_name, -1);
+
+        g_assert (theme_name != NULL);
+
+        /* It is necessary to update the theme name before any other setting as
+         * the "changed" notification will reload the contents of the widget */
+        g_settings_set_string (chooser->priv->sound_settings, SOUND_THEME_KEY, theme_name);
+
+        /* special case for no sounds */
+        if (strcmp (theme_name, NO_SOUNDS_THEME_NAME) == 0) {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, FALSE);
+                return;
+        } else {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, TRUE);
+        }
+
+        g_free (theme_name);
+
+        /* FIXME: reset alert model */
+}
+
+static char *
+load_index_theme_name (const char *index,
+                       char      **parent)
+{
+        GKeyFile *file;
+        char *indexname = NULL;
+        gboolean hidden;
+
+        file = g_key_file_new ();
+        if (g_key_file_load_from_file (file, index, G_KEY_FILE_KEEP_TRANSLATIONS, NULL) == FALSE) {
+                g_key_file_free (file);
+                return NULL;
+        }
+        /* Don't add hidden themes to the list */
+        hidden = g_key_file_get_boolean (file, "Sound Theme", "Hidden", NULL);
+        if (!hidden) {
+                indexname = g_key_file_get_locale_string (file,
+                                                          "Sound Theme",
+                                                          "Name",
+                                                          NULL,
+                                                          NULL);
+
+                /* Save the parent theme, if there's one */
+                if (parent != NULL) {
+                        *parent = g_key_file_get_string (file,
+                                                         "Sound Theme",
+                                                         "Inherits",
+                                                         NULL);
+                }
+        }
+
+        g_key_file_free (file);
+        return indexname;
+}
+
+static void
+sound_theme_in_dir (GHashTable *hash,
+                    const char *dir)
+{
+        GDir *d;
+        const char *name;
+
+        d = g_dir_open (dir, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *dirname, *index, *indexname;
+
+                /* Look for directories */
+                dirname = g_build_filename (dir, name, NULL);
+                if (g_file_test (dirname, G_FILE_TEST_IS_DIR) == FALSE) {
+                        g_free (dirname);
+                        continue;
+                }
+
+                /* Look for index files */
+                index = g_build_filename (dirname, "index.theme", NULL);
+                g_free (dirname);
+
+                /* Check the name of the theme in the index.theme file */
+                indexname = load_index_theme_name (index, NULL);
+                g_free (index);
+                if (indexname == NULL) {
+                        continue;
+                }
+
+                g_hash_table_insert (hash, g_strdup (name), indexname);
+        }
+
+        g_dir_close (d);
+}
+
+static void
+add_theme_to_store (const char   *key,
+                    const char   *value,
+                    GtkListStore *store)
+{
+        char *parent;
+
+        parent = NULL;
+
+        /* Get the parent, if we're checking the custom theme */
+        if (strcmp (key, CUSTOM_THEME_NAME) == 0) {
+                char *name, *path;
+
+                path = custom_theme_dir_path ("index.theme");
+                name = load_index_theme_name (path, &parent);
+                g_free (name);
+                g_free (path);
+        }
+        gtk_list_store_insert_with_values (store, NULL, G_MAXINT,
+                                           THEME_DISPLAY_COL, value,
+                                           THEME_IDENTIFIER_COL, key,
+                                           THEME_PARENT_ID_COL, parent,
+                                           -1);
+        g_free (parent);
+}
+
+static void
+set_combox_for_theme_name (GvcSoundThemeChooser *chooser,
+                           const char           *name)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        gboolean      found;
+
+        /* If the name is empty, use "freedesktop" */
+        if (name == NULL || *name == '\0') {
+                name = "freedesktop";
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+        if (gtk_tree_model_get_iter_first (model, &iter) == FALSE) {
+                return;
+        }
+
+        do {
+                char *value;
+
+                gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &value, -1);
+                found = (value != NULL && strcmp (value, name) == 0);
+                g_free (value);
+
+        } while (!found && gtk_tree_model_iter_next (model, &iter));
+
+        /* When we can't find the theme we need to set, try to set the default
+         * one "freedesktop" */
+        if (found) {
+                gtk_combo_box_set_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter);
+        } else if (strcmp (name, "freedesktop") != 0) {
+                g_debug ("not found, falling back to fdo");
+                set_combox_for_theme_name (chooser, "freedesktop");
+        }
+}
+
+static void
+set_input_feedback_enabled (GvcSoundThemeChooser *chooser,
+                            gboolean              enabled)
+{
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      enabled);
+}
+
+static void
+setup_theme_selector (GvcSoundThemeChooser *chooser)
+{
+        GHashTable           *hash;
+        GtkListStore         *store;
+        GtkCellRenderer      *renderer;
+        const char * const   *data_dirs;
+        const char           *data_dir;
+        char                 *dir;
+        guint                 i;
+
+        /* Add the theme names and their display name to a hash table,
+         * makes it easy to avoid duplicate themes */
+        hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+        data_dirs = g_get_system_data_dirs ();
+        for (i = 0; data_dirs[i] != NULL; i++) {
+                dir = g_build_filename (data_dirs[i], "sounds", NULL);
+                sound_theme_in_dir (hash, dir);
+                g_free (dir);
+        }
+
+        data_dir = g_get_user_data_dir ();
+        dir = g_build_filename (data_dir, "sounds", NULL);
+        sound_theme_in_dir (hash, dir);
+        g_free (dir);
+
+        /* If there isn't at least one theme, make everything
+         * insensitive, LAME! */
+        if (g_hash_table_size (hash) == 0) {
+                gtk_widget_set_sensitive (GTK_WIDGET (chooser), FALSE);
+                g_warning ("Bad setup, install the freedesktop sound theme");
+                g_hash_table_destroy (hash);
+                return;
+        }
+
+        /* Setup the tree model, 3 columns:
+         * - internal theme name/directory
+         * - display theme name
+         * - the internal id for the parent theme, used for the custom theme */
+        store = gtk_list_store_new (THEME_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING);
+
+        /* Add the themes to a combobox */
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           THEME_DISPLAY_COL, _("No sounds"),
+                                           THEME_IDENTIFIER_COL, "__no_sounds",
+                                           THEME_PARENT_ID_COL, NULL,
+                                           -1);
+        g_hash_table_foreach (hash, (GHFunc) add_theme_to_store, store);
+        g_hash_table_destroy (hash);
+
+        /* Set the display */
+        gtk_combo_box_set_model (GTK_COMBO_BOX (chooser->priv->combo_box),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                    renderer,
+                                    TRUE);
+        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                        renderer,
+                                        "text", THEME_DISPLAY_COL,
+                                        NULL);
+
+        g_signal_connect (G_OBJECT (chooser->priv->combo_box),
+                          "changed",
+                          G_CALLBACK (on_combobox_changed),
+                          chooser);
+}
+
+#define GVC_SOUND_SOUND    (xmlChar *) "sound"
+#define GVC_SOUND_NAME     (xmlChar *) "name"
+#define GVC_SOUND_FILENAME (xmlChar *) "filename"
+
+/* Adapted from yelp-toc-pager.c */
+static xmlChar *
+xml_get_and_trim_names (xmlNodePtr node)
+{
+        xmlNodePtr cur;
+        xmlChar *keep_lang = NULL;
+        xmlChar *value;
+        int j, keep_pri = INT_MAX;
+
+        const gchar * const * langs = g_get_language_names ();
+
+        value = NULL;
+
+        for (cur = node->children; cur; cur = cur->next) {
+                if (! xmlStrcmp (cur->name, GVC_SOUND_NAME)) {
+                        xmlChar *cur_lang = NULL;
+                        int cur_pri = INT_MAX;
+
+                        cur_lang = xmlNodeGetLang (cur);
+
+                        if (cur_lang) {
+                                for (j = 0; langs[j]; j++) {
+                                        if (g_str_equal (cur_lang, langs[j])) {
+                                                cur_pri = j;
+                                                break;
+                                        }
+                                }
+                        } else {
+                                cur_pri = INT_MAX - 1;
+                        }
+
+                        if (cur_pri <= keep_pri) {
+                                if (keep_lang)
+                                        xmlFree (keep_lang);
+                                if (value)
+                                        xmlFree (value);
+
+                                value = xmlNodeGetContent (cur);
+
+                                keep_lang = cur_lang;
+                                keep_pri = cur_pri;
+                        } else {
+                                if (cur_lang)
+                                        xmlFree (cur_lang);
+                        }
+                }
+        }
+
+        /* Delete all GVC_SOUND_NAME nodes */
+        cur = node->children;
+        while (cur) {
+                xmlNodePtr this = cur;
+                cur = cur->next;
+                if (! xmlStrcmp (this->name, GVC_SOUND_NAME)) {
+                        xmlUnlinkNode (this);
+                        xmlFreeNode (this);
+                }
+        }
+
+        return value;
+}
+
+static void
+populate_model_from_node (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          xmlNodePtr            node)
+{
+        xmlNodePtr child;
+        xmlChar   *filename;
+        xmlChar   *name;
+
+        filename = NULL;
+        name = xml_get_and_trim_names (node);
+        for (child = node->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+
+                if (xmlStrcmp (child->name, GVC_SOUND_FILENAME) == 0) {
+                        filename = xmlNodeGetContent (child);
+                } else if (xmlStrcmp (child->name, GVC_SOUND_NAME) == 0) {
+                        /* EH? should have been trimmed */
+                }
+        }
+
+        if (filename != NULL && name != NULL) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   ALERT_IDENTIFIER_COL, filename,
+                                                   ALERT_DISPLAY_COL, name,
+                                                   ALERT_SOUND_TYPE_COL, _("Built-in"),
+                                                   ALERT_ACTIVE_COL, FALSE,
+                                                   -1);
+        }
+
+        xmlFree (filename);
+        xmlFree (name);
+}
+
+static void
+populate_model_from_file (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          const char           *filename)
+{
+        xmlDocPtr  doc;
+        xmlNodePtr root;
+        xmlNodePtr child;
+        gboolean   exists;
+
+        exists = g_file_test (filename, G_FILE_TEST_EXISTS);
+        if (! exists) {
+                return;
+        }
+
+        doc = xmlParseFile (filename);
+        if (doc == NULL) {
+                return;
+        }
+
+        root = xmlDocGetRootElement (doc);
+
+        for (child = root->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+                if (xmlStrcmp (child->name, GVC_SOUND_SOUND) != 0) {
+                        continue;
+                }
+
+                populate_model_from_node (chooser, model, child);
+        }
+
+        xmlFreeDoc (doc);
+}
+
+static void
+populate_model_from_dir (GvcSoundThemeChooser *chooser,
+                         GtkTreeModel         *model,
+                         const char           *dirname)
+{
+        GDir       *d;
+        const char *name;
+
+        d = g_dir_open (dirname, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *path;
+
+                if (! g_str_has_suffix (name, ".xml")) {
+                        continue;
+                }
+
+                path = g_build_filename (dirname, name, NULL);
+                populate_model_from_file (chooser, model, path);
+                g_free (path);
+        }
+
+        g_dir_close (d);
+}
+
+static gboolean
+save_alert_sounds (GvcSoundThemeChooser  *chooser,
+                   const char            *id)
+{
+        const char *sounds[3] = { "bell-terminal", "bell-window-system", NULL };
+        char *path;
+
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+        } else {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+                add_custom_file (sounds, id);
+        }
+
+        /* And poke the directory so the theme gets updated */
+        path = custom_theme_dir_path (NULL);
+        if (utime (path, NULL) != 0) {
+                g_warning ("Failed to update mtime for directory '%s': %s",
+                           path, g_strerror (errno));
+        }
+        g_free (path);
+
+        return FALSE;
+}
+
+
+static void
+update_alert_model (GvcSoundThemeChooser  *chooser,
+                    const char            *id)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        gtk_tree_model_get_iter_first (model, &iter);
+        do {
+                gboolean toggled;
+                char    *this_id;
+
+                gtk_tree_model_get (model, &iter,
+                                    ALERT_IDENTIFIER_COL, &this_id,
+                                    -1);
+
+                if (strcmp (this_id, id) == 0) {
+                        toggled = TRUE;
+                } else {
+                        toggled = FALSE;
+                }
+                g_free (this_id);
+
+                gtk_list_store_set (GTK_LIST_STORE (model),
+                                    &iter,
+                                    ALERT_ACTIVE_COL, toggled,
+                                    -1);
+        } while (gtk_tree_model_iter_next (model, &iter));
+}
+
+static void
+update_alert (GvcSoundThemeChooser *chooser,
+              const char           *alert_id)
+{
+        GtkTreeModel *theme_model;
+        GtkTreeIter   iter;
+        char         *theme;
+        char         *parent;
+        gboolean      is_custom;
+        gboolean      is_default;
+        gboolean      add_custom;
+        gboolean      remove_custom;
+
+        theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        /* Get the current theme's name, and set the parent */
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        gtk_tree_model_get (theme_model, &iter,
+                            THEME_IDENTIFIER_COL, &theme,
+                            THEME_IDENTIFIER_COL, &parent,
+                            -1);
+        is_custom = strcmp (theme, CUSTOM_THEME_NAME) == 0;
+        is_default = strcmp (alert_id, DEFAULT_ALERT_ID) == 0;
+
+        /* So a few possibilities:
+         * 1. Named theme, default alert selected: noop
+         * 2. Named theme, alternate alert selected: create new custom with sound
+         * 3. Custom theme, default alert selected: remove sound and possibly custom
+         * 4. Custom theme, alternate alert selected: update custom sound
+         */
+        add_custom = FALSE;
+        remove_custom = FALSE;
+        if (! is_custom && is_default) {
+                /* remove custom just in case */
+                remove_custom = TRUE;
+        } else if (! is_custom && ! is_default) {
+                create_custom_theme (parent);
+                save_alert_sounds (chooser, alert_id);
+                add_custom = TRUE;
+        } else if (is_custom && is_default) {
+                save_alert_sounds (chooser, alert_id);
+                /* after removing files check if it is empty */
+                if (custom_theme_dir_is_empty ()) {
+                        remove_custom = TRUE;
+                }
+        } else if (is_custom && ! is_default) {
+                save_alert_sounds (chooser, alert_id);
+        }
+
+        if (add_custom) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (theme_model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   THEME_DISPLAY_COL, _("Custom"),
+                                                   THEME_IDENTIFIER_COL, CUSTOM_THEME_NAME,
+                                                   THEME_PARENT_ID_COL, theme,
+                                                   -1);
+                set_combox_for_theme_name (chooser, CUSTOM_THEME_NAME);
+        } else if (remove_custom) {
+                gtk_tree_model_get_iter_first (theme_model, &iter);
+                do {
+                        char *this_parent;
+
+                        gtk_tree_model_get (theme_model, &iter,
+                                            THEME_PARENT_ID_COL, &this_parent,
+                                            -1);
+                        if (this_parent != NULL && strcmp (this_parent, CUSTOM_THEME_NAME) != 0) {
+                                g_free (this_parent);
+                                gtk_list_store_remove (GTK_LIST_STORE (theme_model), &iter);
+                                break;
+                        }
+                        g_free (this_parent);
+                } while (gtk_tree_model_iter_next (theme_model, &iter));
+
+                delete_custom_theme_dir ();
+
+                set_combox_for_theme_name (chooser, parent);
+        }
+
+        update_alert_model (chooser, alert_id);
+
+        g_free (theme);
+        g_free (parent);
+}
+
+static void
+on_alert_toggled (GtkCellRendererToggle *renderer,
+                  char                  *path_str,
+                  GvcSoundThemeChooser  *chooser)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreePath  *path;
+        gboolean      toggled;
+        char         *id;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        path = gtk_tree_path_new_from_string (path_str);
+        gtk_tree_model_get_iter (model, &iter, path);
+        gtk_tree_path_free (path);
+
+        id = NULL;
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            ALERT_ACTIVE_COL, &toggled,
+                            -1);
+
+        toggled ^= 1;
+        if (toggled) {
+                update_alert (chooser, id);
+        }
+
+        g_free (id);
+}
+
+static void
+play_preview_for_path (GvcSoundThemeChooser *chooser, GtkTreePath *path)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreeIter   theme_iter;
+        gchar        *id = NULL;
+        gchar        *parent_theme = NULL;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        if (gtk_tree_model_get_iter (model, &iter, path) == FALSE)
+                return;
+
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            -1);
+        if (id == NULL)
+                return;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &theme_iter)) {
+                GtkTreeModel *theme_model;
+                gchar        *theme_id = NULL;
+                gchar        *parent_id = NULL;
+
+                theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+                gtk_tree_model_get (theme_model, &theme_iter,
+                                    THEME_IDENTIFIER_COL, &theme_id,
+                                    THEME_PARENT_ID_COL, &parent_id, -1);
+                if (theme_id && strcmp (theme_id, CUSTOM_THEME_NAME) == 0)
+                        parent_theme = g_strdup (parent_id);
+
+                g_free (theme_id);
+                g_free (parent_id);
+        }
+
+        /* special case: for the default item on custom themes
+         * play the alert for the parent theme */
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                if (parent_theme != NULL) {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_CANBERRA_XDG_THEME_NAME, parent_theme,
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                } else {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                }
+        } else {
+                ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                        CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                        CA_PROP_MEDIA_FILENAME, id,
+                                        CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                        CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                        CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                        CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                        NULL);
+
+        }
+        g_free (parent_theme);
+        g_free (id);
+}
+
+static void
+on_treeview_row_activated (GtkTreeView          *treeview,
+                           GtkTreePath          *path,
+                           GtkTreeViewColumn    *column,
+                           GvcSoundThemeChooser *chooser)
+{
+        play_preview_for_path (chooser, path);
+}
+
+static void
+on_treeview_selection_changed (GtkTreeSelection     *selection,
+                               GvcSoundThemeChooser *chooser)
+{
+        GList        *paths;
+        GtkTreeModel *model;
+        GtkTreePath  *path;
+
+        if (chooser->priv->treeview == NULL)
+                return;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        paths = gtk_tree_selection_get_selected_rows (selection, &model);
+        if (paths == NULL)
+                return;
+
+        path = paths->data;
+        play_preview_for_path (chooser, path);
+
+        g_list_foreach (paths, (GFunc)gtk_tree_path_free, NULL);
+        g_list_free (paths);
+}
+
+static GtkWidget *
+create_alert_treeview (GvcSoundThemeChooser *chooser)
+{
+        GtkListStore         *store;
+        GtkWidget            *treeview;
+        GtkCellRenderer      *renderer;
+        GtkTreeViewColumn    *column;
+        GtkTreeSelection     *selection;
+
+        treeview = gtk_tree_view_new ();
+
+        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
+        g_signal_connect (G_OBJECT (treeview),
+                          "row-activated",
+                          G_CALLBACK (on_treeview_row_activated),
+                          chooser);
+
+        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+        gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+        g_signal_connect (G_OBJECT (selection),
+                          "changed",
+                          G_CALLBACK (on_treeview_selection_changed),
+                          chooser);
+
+        /* Setup the tree model, 3 columns:
+         * - display name
+         * - sound id
+         * - sound type
+         */
+        store = gtk_list_store_new (ALERT_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_BOOLEAN);
+
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           ALERT_IDENTIFIER_COL, DEFAULT_ALERT_ID,
+                                           ALERT_DISPLAY_COL, _("Default"),
+                                           ALERT_SOUND_TYPE_COL, _("From theme"),
+                                           ALERT_ACTIVE_COL, TRUE,
+                                           -1);
+
+        populate_model_from_dir (chooser, GTK_TREE_MODEL (store), SOUND_SET_DIR);
+
+        gtk_tree_view_set_model (GTK_TREE_VIEW (treeview),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_toggle_new ();
+        gtk_cell_renderer_toggle_set_radio (GTK_CELL_RENDERER_TOGGLE (renderer), TRUE);
+
+        column = gtk_tree_view_column_new_with_attributes (NULL,
+                                                           renderer,
+                                                           "active", ALERT_ACTIVE_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+        g_signal_connect (renderer,
+                          "toggled",
+                          G_CALLBACK (on_alert_toggled),
+                          chooser);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Name"),
+                                                           renderer,
+                                                           "text", ALERT_DISPLAY_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Type"),
+                                                           renderer,
+                                                           "text", ALERT_SOUND_TYPE_COL,
+                                                           NULL);
+
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        return treeview;
+}
+
+static int
+get_file_type (const char *sound_name,
+               char      **linked_name)
+{
+        char *name, *filename;
+
+        *linked_name = NULL;
+
+        name = g_strdup_printf ("%s.disabled", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_REGULAR) != FALSE) {
+                g_free (filename);
+                return SOUND_TYPE_OFF;
+        }
+        g_free (filename);
+
+        /* We only check for .ogg files because those are the
+         * only ones we create */
+        name = g_strdup_printf ("%s.ogg", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_SYMLINK) != FALSE) {
+                *linked_name = g_file_read_link (filename, NULL);
+                g_free (filename);
+                return SOUND_TYPE_CUSTOM;
+        }
+        g_free (filename);
+
+        return SOUND_TYPE_BUILTIN;
+}
+
+static void
+update_alerts_from_theme_name (GvcSoundThemeChooser *chooser,
+                               const gchar          *name)
+{
+        if (strcmp (name, CUSTOM_THEME_NAME) != 0) {
+                /* reset alert to default */
+                update_alert (chooser, DEFAULT_ALERT_ID);
+        } else {
+                int   sound_type;
+                char *linkname;
+
+                linkname = NULL;
+                sound_type = get_file_type ("bell-terminal", &linkname);
+                g_debug ("Found link: %s", linkname);
+                if (sound_type == SOUND_TYPE_CUSTOM) {
+                        update_alert (chooser, linkname);
+                }
+        }
+}
+
+static void
+update_theme (GvcSoundThemeChooser *chooser)
+{
+        char        *theme_name;
+        gboolean     events_enabled;
+        gboolean     feedback_enabled;
+
+        feedback_enabled = g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY);
+        set_input_feedback_enabled (chooser, feedback_enabled);
+
+        events_enabled = g_settings_get_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY);
+        if (events_enabled) {
+                theme_name = g_settings_get_string (chooser->priv->sound_settings, SOUND_THEME_KEY);
+        } else {
+                theme_name = g_strdup (NO_SOUNDS_THEME_NAME);
+        }
+
+        gtk_widget_set_sensitive (chooser->priv->selection_box, events_enabled);
+        gtk_widget_set_sensitive (chooser->priv->click_feedback_button, events_enabled);
+
+        set_combox_for_theme_name (chooser, theme_name);
+
+        update_alerts_from_theme_name (chooser, theme_name);
+
+        g_free (theme_name);
+}
+
+static void
+gvc_sound_theme_chooser_class_init (GvcSoundThemeChooserClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_sound_theme_chooser_dispose;
+}
+
+static void
+on_click_feedback_toggled (GtkToggleButton      *button,
+                           GvcSoundThemeChooser *chooser)
+{
+        gboolean enabled;
+
+        enabled = gtk_toggle_button_get_active (button);
+
+        g_settings_set_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY, enabled);
+}
+
+static void
+on_key_changed (GSettings            *settings,
+                gchar                *key,
+                GvcSoundThemeChooser *chooser)
+{
+        if (!strcmp (key, EVENT_SOUNDS_KEY) ||
+            !strcmp (key, SOUND_THEME_KEY) ||
+            !strcmp (key, INPUT_SOUNDS_KEY))
+                update_theme (chooser);
+}
+
+static void
+setup_list_size_constraint (GtkWidget *widget,
+                            GtkWidget *to_size)
+{
+        GtkRequisition req;
+        gint           sc_height;
+        int            max_height;
+
+        /* Constrain height to be the tree height up to a max */
+        gdk_window_get_geometry (gdk_screen_get_root_window (gtk_widget_get_screen (widget)),
+                                 NULL, NULL, NULL, &sc_height);
+
+        max_height = sc_height / 4;
+
+        // XXX this doesn't work
+        gtk_widget_get_preferred_size (to_size, NULL, &req);
+
+        gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (widget),
+                                                    MIN (req.height, max_height));
+}
+
+static void
+gvc_sound_theme_chooser_init (GvcSoundThemeChooser *chooser)
+{
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *scrolled_window;
+        gchar       *str;
+
+        chooser->priv = gvc_sound_theme_chooser_get_instance_private (chooser);
+
+        chooser->priv->theme_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->theme_box, FALSE, FALSE, 0);
+
+        label = gtk_label_new_with_mnemonic (_("Sound _theme:"));
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), label, FALSE, FALSE, 0);
+        chooser->priv->combo_box = gtk_combo_box_new ();
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), chooser->priv->combo_box, FALSE, FALSE, 6);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->combo_box);
+
+        chooser->priv->sound_settings = g_settings_new (KEY_SOUNDS_SCHEMA);
+
+        g_signal_connect (G_OBJECT (chooser->priv->sound_settings),
+                          "changed",
+                          G_CALLBACK (on_key_changed),
+                          chooser);
+
+        str = g_strdup_printf ("<b>%s</b>", _("C_hoose an alert sound:"));
+        chooser->priv->selection_box = box = gtk_frame_new (str);
+        g_free (str);
+
+        label = gtk_frame_get_label_widget (GTK_FRAME (box));
+        gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
+        gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+        gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
+
+        gtk_box_pack_start (GTK_BOX (chooser), box, TRUE, TRUE, 6);
+
+        chooser->priv->treeview = create_alert_treeview (chooser);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->treeview);
+
+        scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+        gtk_widget_set_hexpand (scrolled_window, TRUE);
+        gtk_widget_set_vexpand (scrolled_window, TRUE);
+        gtk_widget_set_margin_top (scrolled_window, 6);
+
+        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+                                        GTK_POLICY_NEVER,
+                                        GTK_POLICY_AUTOMATIC);
+        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
+                                             GTK_SHADOW_IN);
+
+        gtk_container_add (GTK_CONTAINER (scrolled_window), chooser->priv->treeview);
+        gtk_container_add (GTK_CONTAINER (box), scrolled_window);
+
+        chooser->priv->click_feedback_button = gtk_check_button_new_with_mnemonic (_("Enable _window and button sounds"));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY));
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->click_feedback_button,
+                            FALSE, FALSE, 0);
+
+        g_signal_connect (G_OBJECT (chooser->priv->click_feedback_button),
+                          "toggled",
+                          G_CALLBACK (on_click_feedback_toggled),
+                          chooser);
+
+        setup_theme_selector (chooser);
+        update_theme (chooser);
+
+        setup_list_size_constraint (scrolled_window, chooser->priv->treeview);
+}
+
+static void
+gvc_sound_theme_chooser_dispose (GObject *object)
+{
+        GvcSoundThemeChooser *chooser;
+
+        chooser = GVC_SOUND_THEME_CHOOSER (object);
+
+        g_clear_object (&chooser->priv->sound_settings);
+
+        G_OBJECT_CLASS (gvc_sound_theme_chooser_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_sound_theme_chooser_new (void)
+{
+        return g_object_new (GVC_TYPE_SOUND_THEME_CHOOSER,
+                                "spacing", 6,
+                                "orientation", GTK_ORIENTATION_VERTICAL,
+                                NULL);
+}
+
+
+
+ + + diff --git a/2020-06-17-120043-0378-cppcheck@7a8fcf3b18bf_master/2.html b/2020-06-17-120043-0378-cppcheck@7a8fcf3b18bf_master/2.html new file mode 100644 index 0000000..bacfabb --- /dev/null +++ b/2020-06-17-120043-0378-cppcheck@7a8fcf3b18bf_master/2.html @@ -0,0 +1,1110 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <canberra.h>
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-speaker-test.h"
+#include "gvc-utils.h"
+
+struct _GvcSpeakerTestPrivate
+{
+        GArray           *controls;
+        ca_context       *canberra;
+        MateMixerStream  *stream;
+};
+
+enum {
+        PROP_0,
+        PROP_STREAM,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_speaker_test_dispose    (GObject             *object);
+static void gvc_speaker_test_finalize   (GObject             *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSpeakerTest, gvc_speaker_test, GTK_TYPE_GRID)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+typedef struct {
+        MateMixerChannelPosition position;
+        guint left;
+        guint top;
+} TablePosition;
+
+static const TablePosition positions[] = {
+        /* Position, X, Y */
+        { MATE_MIXER_CHANNEL_FRONT_LEFT, 0, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_LEFT_CENTER, 1, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_CENTER, 2, 0, },
+        { MATE_MIXER_CHANNEL_MONO, 2, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT_CENTER, 3, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT, 4, 0, },
+        { MATE_MIXER_CHANNEL_SIDE_LEFT, 0, 1, },
+        { MATE_MIXER_CHANNEL_SIDE_RIGHT, 4, 1, },
+        { MATE_MIXER_CHANNEL_BACK_LEFT, 0, 2, },
+        { MATE_MIXER_CHANNEL_BACK_CENTER, 2, 2, },
+        { MATE_MIXER_CHANNEL_BACK_RIGHT, 4, 2, },
+        { MATE_MIXER_CHANNEL_LFE, 3, 2 }
+};
+
+MateMixerStream *
+gvc_speaker_test_get_stream (GvcSpeakerTest *test)
+{
+        g_return_val_if_fail (GVC_IS_SPEAKER_TEST (test), NULL);
+
+        return test->priv->stream;
+}
+
+static void
+gvc_speaker_test_set_stream (GvcSpeakerTest *test, MateMixerStream *stream)
+{
+        MateMixerStreamControl *control;
+        const gchar            *name;
+        guint                   i;
+
+        name = mate_mixer_stream_get_name (stream);
+        control = mate_mixer_stream_get_default_control (stream);
+
+        ca_context_change_device (test->priv->canberra, name);
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                gboolean has_position =
+                        mate_mixer_stream_control_has_channel_position (control, positions[i].position);
+
+                gtk_widget_set_visible (g_array_index (test->priv->controls, GtkWidget *, i),
+                                        has_position);
+        }
+
+        test->priv->stream = g_object_ref (stream);
+}
+
+static void
+gvc_speaker_test_set_property (GObject       *object,
+                               guint          prop_id,
+                               const GValue  *value,
+                               GParamSpec    *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                gvc_speaker_test_set_stream (self, g_value_get_object (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_get_property (GObject     *object,
+                               guint        prop_id,
+                               GValue      *value,
+                               GParamSpec  *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                g_value_set_object (value, self->priv->stream);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_class_init (GvcSpeakerTestClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose  = gvc_speaker_test_dispose;
+        object_class->finalize = gvc_speaker_test_finalize;
+        object_class->set_property = gvc_speaker_test_set_property;
+        object_class->get_property = gvc_speaker_test_get_property;
+
+        properties[PROP_STREAM] =
+                g_param_spec_object ("stream",
+                                     "Stream",
+                                     "MateMixer stream",
+                                     MATE_MIXER_TYPE_STREAM,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+}
+
+static const gchar *
+sound_name (MateMixerChannelPosition position)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return "audio-channel-front-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return "audio-channel-front-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return "audio-channel-front-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return "audio-channel-rear-left";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return "audio-channel-rear-right";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return "audio-channel-rear-center";
+        case MATE_MIXER_CHANNEL_LFE:
+                return "audio-channel-lfe";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return "audio-channel-side-left";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return "audio-channel-side-right";
+        default:
+                return NULL;
+        }
+}
+
+static const gchar *
+icon_name (MateMixerChannelPosition position, gboolean playing)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return playing
+                        ? "audio-speaker-left-testing"
+                        : "audio-speaker-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return playing
+                        ? "audio-speaker-right-testing"
+                        : "audio-speaker-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return playing
+                        ? "audio-speaker-center-testing"
+                        : "audio-speaker-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return playing
+                        ? "audio-speaker-left-back-testing"
+                        : "audio-speaker-left-back";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return playing
+                        ? "audio-speaker-right-back-testing"
+                        : "audio-speaker-right-back";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return playing
+                        ? "audio-speaker-center-back-testing"
+                        : "audio-speaker-center-back";
+        case MATE_MIXER_CHANNEL_LFE:
+                return playing
+                        ? "audio-subwoofer-testing"
+                        : "audio-subwoofer";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return playing
+                        ? "audio-speaker-left-side-testing"
+                        : "audio-speaker-left-side";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return playing
+                        ? "audio-speaker-right-side-testing"
+                        : "audio-speaker-right-side";
+        default:
+                return NULL;
+        }
+}
+
+static void
+update_button (GtkWidget *control)
+{
+        GtkWidget *button;
+        GtkWidget *image;
+        gboolean   playing;
+        MateMixerChannelPosition position;
+
+        button = g_object_get_data (G_OBJECT (control), "button");
+        image  = g_object_get_data (G_OBJECT (control), "image");
+
+        position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+        playing  = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        gtk_button_set_label (GTK_BUTTON (button), playing ? _("Stop") : _("Test"));
+
+        gtk_image_set_from_icon_name (GTK_IMAGE (image),
+                                      icon_name (position, playing),
+                                      GTK_ICON_SIZE_DIALOG);
+}
+
+static gboolean
+idle_cb (GtkWidget *control)
+{
+        if (control != NULL) {
+                /* This is called in the background thread, hence forward to main thread
+                 * via idle callback */
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+
+                update_button (control);
+        }
+        return FALSE;
+}
+
+static void
+finish_cb (ca_context *c, uint32_t id, int error_code, void *userdata)
+{
+        GtkWidget *control = (GtkWidget *) userdata;
+
+        if (error_code == CA_ERROR_DESTROYED || control == NULL)
+                return;
+
+        g_idle_add ((GSourceFunc) idle_cb, control);
+}
+
+static void
+on_test_button_clicked (GtkButton *button, GtkWidget *control)
+{
+        gboolean    playing;
+        ca_context *canberra;
+
+        canberra = g_object_get_data (G_OBJECT (control), "canberra");
+
+        ca_context_cancel (canberra, 1);
+
+        playing = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        if (playing) {
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        } else {
+                MateMixerChannelPosition position;
+                const gchar *name;
+                ca_proplist *proplist;
+
+                position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+
+                ca_proplist_create (&proplist);
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_ROLE, "test");
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_NAME,
+                                  gvc_channel_position_to_pretty_string (position));
+                ca_proplist_sets (proplist,
+                                  CA_PROP_CANBERRA_FORCE_CHANNEL,
+                                  gvc_channel_position_to_pulse_string (position));
+
+                ca_proplist_sets (proplist, CA_PROP_CANBERRA_ENABLE, "1");
+
+                name = sound_name (position);
+                if (name != NULL) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, name);
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, "audio-test-signal");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets(proplist, CA_PROP_EVENT_ID, "bell-window-system");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (playing));
+        }
+
+        update_button (control);
+}
+
+static GtkWidget *
+create_control (ca_context *canberra, MateMixerChannelPosition position)
+{
+        GtkWidget   *control;
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *image;
+        GtkWidget   *test_button;
+        const gchar *name;
+
+        control = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+        box     = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        g_object_set_data (G_OBJECT (control), "position", GINT_TO_POINTER (position));
+        g_object_set_data (G_OBJECT (control), "canberra", canberra);
+
+        name = icon_name (position, FALSE);
+        if (name == NULL)
+                name = "audio-volume-medium";
+
+        image = gtk_image_new_from_icon_name (name, GTK_ICON_SIZE_DIALOG);
+        g_object_set_data (G_OBJECT (control), "image", image);
+        gtk_box_pack_start (GTK_BOX (control), image, FALSE, FALSE, 0);
+
+        label = gtk_label_new (gvc_channel_position_to_pretty_string (position));
+        gtk_box_pack_start (GTK_BOX (control), label, FALSE, FALSE, 0);
+
+        test_button = gtk_button_new_with_label (_("Test"));
+        g_signal_connect (G_OBJECT (test_button),
+                          "clicked",
+                          G_CALLBACK (on_test_button_clicked),
+                          control);
+
+        g_object_set_data (G_OBJECT (control), "button", test_button);
+
+        gtk_box_pack_start (GTK_BOX (box), test_button, TRUE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (control), box, FALSE, FALSE, 0);
+
+        gtk_widget_show_all (control);
+
+        return control;
+}
+
+static void
+create_controls (GvcSpeakerTest *test)
+{
+        guint i;
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                GtkWidget *control = create_control (test->priv->canberra, positions[i].position);
+
+                gtk_grid_attach (GTK_GRID (test),
+                                 control,
+                                 positions[i].left,
+                                 positions[i].top,
+                                 1, 1);
+                g_array_insert_val (test->priv->controls, i, control);
+        }
+}
+
+static void
+gvc_speaker_test_init (GvcSpeakerTest *test)
+{
+        GtkWidget *face;
+
+        test->priv = gvc_speaker_test_get_instance_private (test);
+
+        gtk_container_set_border_width (GTK_CONTAINER (test), 12);
+
+        face = gtk_image_new_from_icon_name ("face-smile", GTK_ICON_SIZE_DIALOG);
+
+        gtk_grid_attach (GTK_GRID (test),
+                         face,
+                         1, 1,
+                         3, 1);
+
+
+        gtk_grid_set_baseline_row (GTK_GRID (test), 1);
+        gtk_widget_show (face);
+
+        ca_context_create (&test->priv->canberra);
+
+        /* The test sounds are played for a single channel, set up using the
+         * FORCE_CHANNEL property of libcanberra; this property is only supported
+         * in the PulseAudio backend, so avoid other backends completely */
+        ca_context_set_driver (test->priv->canberra, "pulse");
+
+        ca_context_change_props (test->priv->canberra,
+                                 CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+                                 CA_PROP_APPLICATION_NAME, _("Volume Control"),
+                                 CA_PROP_APPLICATION_VERSION, VERSION,
+                                 CA_PROP_APPLICATION_ICON_NAME, "multimedia-volume-control",
+                                 NULL);
+
+        test->priv->controls = g_array_new (FALSE, FALSE, sizeof (GtkWidget *));
+
+        create_controls (test);
+}
+
+static void
+gvc_speaker_test_dispose (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        g_clear_object (&test->priv->stream);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->dispose (object);
+}
+
+static void
+gvc_speaker_test_finalize (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        ca_context_destroy (test->priv->canberra);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->finalize (object);
+}
+
+GtkWidget *
+gvc_speaker_test_new (MateMixerStream *stream)
+{
+        GObject *test;
+
+        g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL);
+
+        test = g_object_new (GVC_TYPE_SPEAKER_TEST,
+                             "row-spacing", 6,
+                             "column-spacing", 6,
+                             "row-homogeneous", TRUE,
+                             "column-homogeneous", TRUE,
+                             "stream", stream,
+                             NULL);
+
+        return GTK_WIDGET (test);
+}
+
+
+
+ + + diff --git a/2020-06-17-120043-0378-cppcheck@7a8fcf3b18bf_master/index.html b/2020-06-17-120043-0378-cppcheck@7a8fcf3b18bf_master/index.html new file mode 100644 index 0000000..59baeb0 --- /dev/null +++ b/2020-06-17-120043-0378-cppcheck@7a8fcf3b18bf_master/index.html @@ -0,0 +1,108 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
mate-volume-control/gvc-combo-box.c
70unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
mate-volume-control/gvc-sound-theme-chooser.c
735ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
746ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
758ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
mate-volume-control/gvc-speaker-test.c
53unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+ + + diff --git a/2020-06-17-120043-0378-cppcheck@7a8fcf3b18bf_master/stats.html b/2020-06-17-120043-0378-cppcheck@7a8fcf3b18bf_master/stats.html new file mode 100644 index 0000000..3fb6add --- /dev/null +++ b/2020-06-17-120043-0378-cppcheck@7a8fcf3b18bf_master/stats.html @@ -0,0 +1,93 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+

Top 10 files for error severity, total findings: 2
+   1  mate-volume-control/gvc-speaker-test.c
+   1  mate-volume-control/gvc-combo-box.c
+

+

Top 10 files for information severity, total findings: 3
+   3  mate-volume-control/gvc-sound-theme-chooser.c
+

+ +
+ + + diff --git a/2020-06-17-120043-0378-cppcheck@7a8fcf3b18bf_master/style.css b/2020-06-17-120043-0378-cppcheck@7a8fcf3b18bf_master/style.css new file mode 100644 index 0000000..c39571c --- /dev/null +++ b/2020-06-17-120043-0378-cppcheck@7a8fcf3b18bf_master/style.css @@ -0,0 +1,149 @@ + +body { + font: 13px Arial, Verdana, Sans-Serif; + margin: 0; + width: auto; +} + +h1 { + margin: 10px; +} + +#footer > p { + margin: 4px; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + border: 1px dotted black; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #B6B6B4; +} + +.inconclusive2 { + background-color: #B6B6B4; + border: 1px dotted black; + display: inline-block; + margin-left: 4px; +} + +div.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +div.verbose div.content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid black; + background-color: #FFFFCC; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +#header { + border-bottom: thin solid #aaa; +} + +#menu { + float: left; + margin-top: 5px; + text-align: left; + width: 150px; + /*height: 75%;*/ + position: fixed; + overflow: auto; + z-index: 1; +} + +#menu_index { + float: left; + margin-top: 5px; + padding-left: 5px; + text-align: left; + width: 300px; + /*height: 75%;*/ + position: fixed; + overflow: auto; + z-index: 1; +} + +#menu > a { + display: block; + margin-left: 10px; + font: 12px; + z-index: 1; +} + +#filename { + margin-left: 10px; + font: 12px; + z-index: 1; +} + +.highlighttable { + background-color:white; + z-index: 10; + position: relative; + margin: -10 px; +} + +#content { + background-color: white; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + float: left; + margin: 5px; + margin-left: 10px; + padding: 0 10px 10px 10px; + width: 80%; + padding-left: 150px; +} + +#content_index { + background-color: white; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + float: left; + margin: 5px; + margin-left: 10px; + padding: 0 10px 10px 10px; + width: 80%; + padding-left: 300px; +} + +.linenos { + border-right: thin solid #aaa; + color: lightgray; + padding-right: 6px; +} + +#footer { + border-top: thin solid #aaa; + clear: both; + font-size: 90%; + margin-top: 5px; +} + +#footer ul { + list-style-type: none; + padding-left: 0; +} diff --git a/2020-06-22-145654-0244-cppcheck@3eda50f90193_travis-ci/0.html b/2020-06-22-145654-0244-cppcheck@3eda50f90193_travis-ci/0.html new file mode 100644 index 0000000..e262ed0 --- /dev/null +++ b/2020-06-22-145654-0244-cppcheck@3eda50f90193_travis-ci/0.html @@ -0,0 +1,1038 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-combo-box.h"
+
+struct _GvcComboBoxPrivate
+{
+        GtkWidget       *drop_box;
+        GtkWidget       *start_box;
+        GtkWidget       *end_box;
+        GtkWidget       *label;
+        GtkWidget       *button;
+        GtkTreeModel    *model;
+        GtkWidget       *combobox;
+        MateMixerSwitch *swtch;
+};
+
+enum {
+        COL_NAME,
+        COL_HUMAN_NAME,
+        NUM_COLS
+};
+
+enum {
+        CHANGING,
+        BUTTON_CLICKED,
+        LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+enum {
+        PROP_0,
+        PROP_SWITCH,
+        PROP_LABEL,
+        PROP_SHOW_BUTTON,
+        PROP_BUTTON_LABEL,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_combo_box_dispose    (GObject          *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcComboBox, gvc_combo_box, GTK_TYPE_BOX)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+MateMixerSwitch *
+gvc_combo_box_get_switch (GvcComboBox *combobox)
+{
+        g_return_val_if_fail (GVC_IS_COMBO_BOX (combobox), NULL);
+
+        return combobox->priv->swtch;
+}
+
+void
+gvc_combo_box_set_size_group (GvcComboBox  *combobox,
+                              GtkSizeGroup *group,
+                              gboolean      symmetric)
+{
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (GTK_IS_SIZE_GROUP (group));
+
+        if (group != NULL) {
+                gtk_size_group_add_widget (group, combobox->priv->start_box);
+                if (symmetric == TRUE)
+                        gtk_size_group_add_widget (group, combobox->priv->end_box);
+        }
+        gtk_widget_queue_draw (GTK_WIDGET (combobox));
+}
+
+static void
+on_switch_active_option_notify (MateMixerSwitch *swtch,
+                                GParamSpec      *pspec,
+                                GvcComboBox     *combobox)
+{
+        GtkTreeIter            iter;
+        MateMixerSwitchOption *active;
+        gboolean               cont;
+        const gchar           *name;
+
+        active = mate_mixer_switch_get_active_option (swtch);
+        if (G_UNLIKELY (active == NULL)) {
+                g_warn_if_reached ();
+                return;
+        }
+
+        /* Select the newly activated switch option in the combo box */
+        name = mate_mixer_switch_option_get_name (active);
+        cont = gtk_tree_model_get_iter_first (combobox->priv->model, &iter);
+        while (cont == TRUE) {
+                gchar *current;
+
+                gtk_tree_model_get (combobox->priv->model, &iter,
+                                    COL_NAME, &current,
+                                    -1);
+                if (g_strcmp0 (name, current) == 0) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox), &iter);
+                        g_free (current);
+                        return;
+                }
+                g_free (current);
+
+                cont = gtk_tree_model_iter_next (combobox->priv->model, &iter);
+        }
+        g_warning ("Could not find switch option '%s' in combo box", name);
+}
+
+static void
+gvc_combo_box_set_switch (GvcComboBox *combobox, MateMixerSwitch *swtch)
+{
+        MateMixerSwitchOption *active;
+        const GList           *options;
+
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (MATE_MIXER_IS_SWITCH (swtch));
+
+        combobox->priv->swtch = g_object_ref (swtch);
+
+        active  = mate_mixer_switch_get_active_option (swtch);
+        options = mate_mixer_switch_list_options (swtch);
+        while (options != NULL) {
+                GtkTreeIter            iter;
+                MateMixerSwitchOption *option = MATE_MIXER_SWITCH_OPTION (options->data);
+
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (combobox->priv->model),
+                                                   &iter,
+                                                   G_MAXINT,
+                                                   COL_NAME,
+                                                   mate_mixer_switch_option_get_name (option),
+                                                   COL_HUMAN_NAME,
+                                                   mate_mixer_switch_option_get_label (option),
+                                                   -1);
+
+                /* Select the currently active option of the switch */
+                if (option == active) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox),
+                                                       &iter);
+                }
+                options = options->next;
+        }
+
+        g_signal_connect (G_OBJECT (swtch),
+                          "notify::active-option",
+                          G_CALLBACK (on_switch_active_option_notify),
+                          combobox);
+}
+
+static void
+gvc_combo_box_set_property (GObject       *object,
+                            guint          prop_id,
+                            const GValue  *value,
+                            GParamSpec    *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                gvc_combo_box_set_switch (self, g_value_get_object (value));
+                break;
+        case PROP_LABEL:
+                gtk_label_set_text_with_mnemonic (GTK_LABEL (self->priv->label), g_value_get_string (value));
+                break;
+        case PROP_BUTTON_LABEL:
+                gtk_button_set_label (GTK_BUTTON (self->priv->button), g_value_get_string (value));
+                break;
+        case PROP_SHOW_BUTTON:
+                gtk_widget_set_visible (self->priv->button, g_value_get_boolean (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_get_property (GObject     *object,
+                            guint        prop_id,
+                            GValue      *value,
+                            GParamSpec  *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                g_value_set_object (value, self->priv->swtch);
+                break;
+        case PROP_LABEL:
+                g_value_set_string (value, gtk_label_get_text (GTK_LABEL (self->priv->label)));
+                break;
+        case PROP_BUTTON_LABEL:
+                g_value_set_string (value, gtk_button_get_label (GTK_BUTTON (self->priv->button)));
+                break;
+        case PROP_SHOW_BUTTON:
+                g_value_set_boolean (value, gtk_widget_get_visible (self->priv->button));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_class_init (GvcComboBoxClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_combo_box_dispose;
+        object_class->set_property = gvc_combo_box_set_property;
+        object_class->get_property = gvc_combo_box_get_property;
+
+        properties[PROP_SWITCH] =
+                g_param_spec_object ("switch",
+                                     "switch",
+                                     "The MateMixerSwitch",
+                                     MATE_MIXER_TYPE_SWITCH,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_LABEL] =
+                g_param_spec_string ("label",
+                                     "label",
+                                     "The combo box label",
+                                     _("_Profile:"),
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_SHOW_BUTTON] =
+                g_param_spec_boolean ("show-button",
+                                      "show-button",
+                                      "Whether to show the button",
+                                      FALSE,
+                                      G_PARAM_READWRITE |
+                                      G_PARAM_CONSTRUCT |
+                                      G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_BUTTON_LABEL] =
+                g_param_spec_string ("button-label",
+                                     "button-label",
+                                     "The button's label",
+                                     "",
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+
+        signals[CHANGING] =
+                g_signal_new ("changing",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, changing),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__OBJECT,
+                              G_TYPE_NONE,
+                              1,
+                              MATE_MIXER_TYPE_SWITCH_OPTION);
+
+        signals[BUTTON_CLICKED] =
+                g_signal_new ("button-clicked",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, button_clicked),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
+}
+
+static void
+on_combo_box_changed (GtkComboBox *widget, GvcComboBox *combobox)
+{
+        GtkTreeIter            iter;
+        gchar                 *name;
+        MateMixerSwitchOption *option;
+
+        if (G_UNLIKELY (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter) == FALSE))
+                return;
+
+        gtk_tree_model_get (combobox->priv->model, &iter,
+                            COL_NAME, &name,
+                            -1);
+
+        option = mate_mixer_switch_get_option (combobox->priv->swtch, name);
+        if (G_UNLIKELY (option == NULL)) {
+                g_warn_if_reached ();
+                g_free (name);
+                return;
+        }
+
+        /* Inform that we are about to change the active option of the switch */
+        g_signal_emit (combobox, signals[CHANGING], 0, option);
+
+        mate_mixer_switch_set_active_option (combobox->priv->swtch, option);
+        g_free (name);
+}
+
+static void
+on_combo_box_button_clicked (GtkButton *button, GvcComboBox *combobox)
+{
+        /* The meaning of the button is defined by the owner, so only notify
+         * when it is clicked on */
+        g_signal_emit (combobox, signals[BUTTON_CLICKED], 0);
+}
+
+static void
+gvc_combo_box_init (GvcComboBox *combobox)
+{
+        GtkWidget       *frame;
+        GtkCellRenderer *renderer;
+
+        frame = gtk_frame_new (NULL);
+        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
+
+        combobox->priv = gvc_combo_box_get_instance_private (combobox);
+
+        combobox->priv->model = GTK_TREE_MODEL (gtk_list_store_new (NUM_COLS,
+                                                                    G_TYPE_STRING,
+                                                                    G_TYPE_STRING));
+
+        combobox->priv->combobox = gtk_combo_box_new_with_model (combobox->priv->model);
+
+        combobox->priv->label = gtk_label_new (NULL);
+
+        gtk_label_set_xalign (GTK_LABEL (combobox->priv->label), 0.0);
+        gtk_label_set_yalign (GTK_LABEL (combobox->priv->label), 0.5);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (combobox->priv->label),
+                                       combobox->priv->combobox);
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                    renderer,
+                                    FALSE);
+        gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                       renderer,
+                                       "text",
+                                       COL_HUMAN_NAME);
+
+        combobox->priv->drop_box  = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->start_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->end_box   = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+        /* Make sure the combo box does not get too long on long profile names */
+        g_object_set (G_OBJECT (renderer),
+                      "ellipsize",
+                      PANGO_ELLIPSIZE_END,
+                      NULL);
+
+        gtk_combo_box_set_popup_fixed_width (GTK_COMBO_BOX (combobox->priv->combobox), FALSE);
+
+        gtk_box_pack_start (GTK_BOX (combobox),
+                            frame,
+                            TRUE, TRUE, 0);
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->start_box,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->start_box),
+                            combobox->priv->label,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->combobox,
+                            TRUE, TRUE, 0);
+
+        combobox->priv->button = gtk_button_new_with_label ("");
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->button,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->end_box,
+                            FALSE, FALSE, 0);
+
+        gtk_container_add (GTK_CONTAINER (frame), combobox->priv->drop_box);
+
+        g_signal_connect (G_OBJECT (combobox->priv->combobox),
+                          "changed",
+                          G_CALLBACK (on_combo_box_changed),
+                          combobox);
+        g_signal_connect (G_OBJECT (combobox->priv->button),
+                          "clicked",
+                          G_CALLBACK (on_combo_box_button_clicked),
+                          combobox);
+
+        gtk_widget_set_no_show_all (combobox->priv->button, TRUE);
+        gtk_widget_show_all (frame);
+}
+
+static void
+gvc_combo_box_dispose (GObject *object)
+{
+        GvcComboBox *combobox;
+
+        combobox = GVC_COMBO_BOX (object);
+
+        if (G_LIKELY (combobox->priv->swtch != NULL)) {
+                g_signal_handlers_disconnect_by_func (G_OBJECT (combobox->priv->swtch),
+                                                      G_CALLBACK (on_switch_active_option_notify),
+                                                      combobox);
+                g_clear_object (&combobox->priv->swtch);
+        }
+
+        g_clear_object (&combobox->priv->model);
+
+        G_OBJECT_CLASS (gvc_combo_box_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_combo_box_new (MateMixerSwitch *swtch, const gchar *label)
+{
+        return g_object_new (GVC_TYPE_COMBO_BOX,
+                             "switch", swtch,
+                             "label", label,
+                             "orientation", GTK_ORIENTATION_HORIZONTAL,
+                             NULL);
+}
+
+
+
+ + + diff --git a/2020-06-22-145654-0244-cppcheck@3eda50f90193_travis-ci/1.html b/2020-06-22-145654-0244-cppcheck@3eda50f90193_travis-ci/1.html new file mode 100644 index 0000000..67179f2 --- /dev/null +++ b/2020-06-22-145654-0244-cppcheck@3eda50f90193_travis-ci/1.html @@ -0,0 +1,2368 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
+ * Copyright (C) 2008 William Jon McCann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <utime.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+#include <canberra-gtk.h>
+#include <libxml/tree.h>
+
+#include "gvc-sound-theme-chooser.h"
+#include "sound-theme-file-utils.h"
+
+struct GvcSoundThemeChooserPrivate
+{
+        GtkWidget *combo_box;
+        GtkWidget *treeview;
+        GtkWidget *theme_box;
+        GtkWidget *selection_box;
+        GtkWidget *click_feedback_button;
+        GSettings *sound_settings;
+};
+
+static void     gvc_sound_theme_chooser_dispose   (GObject            *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSoundThemeChooser, gvc_sound_theme_chooser, GTK_TYPE_BOX)
+
+#define KEY_SOUNDS_SCHEMA          "org.mate.sound"
+#define EVENT_SOUNDS_KEY           "event-sounds"
+#define INPUT_SOUNDS_KEY           "input-feedback-sounds"
+#define SOUND_THEME_KEY            "theme-name"
+
+#define DEFAULT_ALERT_ID        "__default"
+#define CUSTOM_THEME_NAME       "__custom"
+#define NO_SOUNDS_THEME_NAME    "__no_sounds"
+
+enum {
+        THEME_DISPLAY_COL,
+        THEME_IDENTIFIER_COL,
+        THEME_PARENT_ID_COL,
+        THEME_NUM_COLS
+};
+
+enum {
+        ALERT_DISPLAY_COL,
+        ALERT_IDENTIFIER_COL,
+        ALERT_SOUND_TYPE_COL,
+        ALERT_ACTIVE_COL,
+        ALERT_NUM_COLS
+};
+
+enum {
+        SOUND_TYPE_UNSET,
+        SOUND_TYPE_OFF,
+        SOUND_TYPE_DEFAULT_FROM_THEME,
+        SOUND_TYPE_BUILTIN,
+        SOUND_TYPE_CUSTOM
+};
+
+static void
+on_combobox_changed (GtkComboBox          *widget,
+                     GvcSoundThemeChooser *chooser)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        char         *theme_name;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &theme_name, -1);
+
+        g_assert (theme_name != NULL);
+
+        /* It is necessary to update the theme name before any other setting as
+         * the "changed" notification will reload the contents of the widget */
+        g_settings_set_string (chooser->priv->sound_settings, SOUND_THEME_KEY, theme_name);
+
+        /* special case for no sounds */
+        if (strcmp (theme_name, NO_SOUNDS_THEME_NAME) == 0) {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, FALSE);
+                return;
+        } else {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, TRUE);
+        }
+
+        g_free (theme_name);
+
+        /* FIXME: reset alert model */
+}
+
+static char *
+load_index_theme_name (const char *index,
+                       char      **parent)
+{
+        GKeyFile *file;
+        char *indexname = NULL;
+        gboolean hidden;
+
+        file = g_key_file_new ();
+        if (g_key_file_load_from_file (file, index, G_KEY_FILE_KEEP_TRANSLATIONS, NULL) == FALSE) {
+                g_key_file_free (file);
+                return NULL;
+        }
+        /* Don't add hidden themes to the list */
+        hidden = g_key_file_get_boolean (file, "Sound Theme", "Hidden", NULL);
+        if (!hidden) {
+                indexname = g_key_file_get_locale_string (file,
+                                                          "Sound Theme",
+                                                          "Name",
+                                                          NULL,
+                                                          NULL);
+
+                /* Save the parent theme, if there's one */
+                if (parent != NULL) {
+                        *parent = g_key_file_get_string (file,
+                                                         "Sound Theme",
+                                                         "Inherits",
+                                                         NULL);
+                }
+        }
+
+        g_key_file_free (file);
+        return indexname;
+}
+
+static void
+sound_theme_in_dir (GHashTable *hash,
+                    const char *dir)
+{
+        GDir *d;
+        const char *name;
+
+        d = g_dir_open (dir, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *dirname, *index, *indexname;
+
+                /* Look for directories */
+                dirname = g_build_filename (dir, name, NULL);
+                if (g_file_test (dirname, G_FILE_TEST_IS_DIR) == FALSE) {
+                        g_free (dirname);
+                        continue;
+                }
+
+                /* Look for index files */
+                index = g_build_filename (dirname, "index.theme", NULL);
+                g_free (dirname);
+
+                /* Check the name of the theme in the index.theme file */
+                indexname = load_index_theme_name (index, NULL);
+                g_free (index);
+                if (indexname == NULL) {
+                        continue;
+                }
+
+                g_hash_table_insert (hash, g_strdup (name), indexname);
+        }
+
+        g_dir_close (d);
+}
+
+static void
+add_theme_to_store (const char   *key,
+                    const char   *value,
+                    GtkListStore *store)
+{
+        char *parent;
+
+        parent = NULL;
+
+        /* Get the parent, if we're checking the custom theme */
+        if (strcmp (key, CUSTOM_THEME_NAME) == 0) {
+                char *name, *path;
+
+                path = custom_theme_dir_path ("index.theme");
+                name = load_index_theme_name (path, &parent);
+                g_free (name);
+                g_free (path);
+        }
+        gtk_list_store_insert_with_values (store, NULL, G_MAXINT,
+                                           THEME_DISPLAY_COL, value,
+                                           THEME_IDENTIFIER_COL, key,
+                                           THEME_PARENT_ID_COL, parent,
+                                           -1);
+        g_free (parent);
+}
+
+static void
+set_combox_for_theme_name (GvcSoundThemeChooser *chooser,
+                           const char           *name)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        gboolean      found;
+
+        /* If the name is empty, use "freedesktop" */
+        if (name == NULL || *name == '\0') {
+                name = "freedesktop";
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+        if (gtk_tree_model_get_iter_first (model, &iter) == FALSE) {
+                return;
+        }
+
+        do {
+                char *value;
+
+                gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &value, -1);
+                found = (value != NULL && strcmp (value, name) == 0);
+                g_free (value);
+
+        } while (!found && gtk_tree_model_iter_next (model, &iter));
+
+        /* When we can't find the theme we need to set, try to set the default
+         * one "freedesktop" */
+        if (found) {
+                gtk_combo_box_set_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter);
+        } else if (strcmp (name, "freedesktop") != 0) {
+                g_debug ("not found, falling back to fdo");
+                set_combox_for_theme_name (chooser, "freedesktop");
+        }
+}
+
+static void
+set_input_feedback_enabled (GvcSoundThemeChooser *chooser,
+                            gboolean              enabled)
+{
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      enabled);
+}
+
+static void
+setup_theme_selector (GvcSoundThemeChooser *chooser)
+{
+        GHashTable           *hash;
+        GtkListStore         *store;
+        GtkCellRenderer      *renderer;
+        const char * const   *data_dirs;
+        const char           *data_dir;
+        char                 *dir;
+        guint                 i;
+
+        /* Add the theme names and their display name to a hash table,
+         * makes it easy to avoid duplicate themes */
+        hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+        data_dirs = g_get_system_data_dirs ();
+        for (i = 0; data_dirs[i] != NULL; i++) {
+                dir = g_build_filename (data_dirs[i], "sounds", NULL);
+                sound_theme_in_dir (hash, dir);
+                g_free (dir);
+        }
+
+        data_dir = g_get_user_data_dir ();
+        dir = g_build_filename (data_dir, "sounds", NULL);
+        sound_theme_in_dir (hash, dir);
+        g_free (dir);
+
+        /* If there isn't at least one theme, make everything
+         * insensitive, LAME! */
+        if (g_hash_table_size (hash) == 0) {
+                gtk_widget_set_sensitive (GTK_WIDGET (chooser), FALSE);
+                g_warning ("Bad setup, install the freedesktop sound theme");
+                g_hash_table_destroy (hash);
+                return;
+        }
+
+        /* Setup the tree model, 3 columns:
+         * - internal theme name/directory
+         * - display theme name
+         * - the internal id for the parent theme, used for the custom theme */
+        store = gtk_list_store_new (THEME_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING);
+
+        /* Add the themes to a combobox */
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           THEME_DISPLAY_COL, _("No sounds"),
+                                           THEME_IDENTIFIER_COL, "__no_sounds",
+                                           THEME_PARENT_ID_COL, NULL,
+                                           -1);
+        g_hash_table_foreach (hash, (GHFunc) add_theme_to_store, store);
+        g_hash_table_destroy (hash);
+
+        /* Set the display */
+        gtk_combo_box_set_model (GTK_COMBO_BOX (chooser->priv->combo_box),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                    renderer,
+                                    TRUE);
+        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                        renderer,
+                                        "text", THEME_DISPLAY_COL,
+                                        NULL);
+
+        g_signal_connect (G_OBJECT (chooser->priv->combo_box),
+                          "changed",
+                          G_CALLBACK (on_combobox_changed),
+                          chooser);
+}
+
+#define GVC_SOUND_SOUND    (xmlChar *) "sound"
+#define GVC_SOUND_NAME     (xmlChar *) "name"
+#define GVC_SOUND_FILENAME (xmlChar *) "filename"
+
+/* Adapted from yelp-toc-pager.c */
+static xmlChar *
+xml_get_and_trim_names (xmlNodePtr node)
+{
+        xmlNodePtr cur;
+        xmlChar *keep_lang = NULL;
+        xmlChar *value;
+        int j, keep_pri = INT_MAX;
+
+        const gchar * const * langs = g_get_language_names ();
+
+        value = NULL;
+
+        for (cur = node->children; cur; cur = cur->next) {
+                if (! xmlStrcmp (cur->name, GVC_SOUND_NAME)) {
+                        xmlChar *cur_lang = NULL;
+                        int cur_pri = INT_MAX;
+
+                        cur_lang = xmlNodeGetLang (cur);
+
+                        if (cur_lang) {
+                                for (j = 0; langs[j]; j++) {
+                                        if (g_str_equal (cur_lang, langs[j])) {
+                                                cur_pri = j;
+                                                break;
+                                        }
+                                }
+                        } else {
+                                cur_pri = INT_MAX - 1;
+                        }
+
+                        if (cur_pri <= keep_pri) {
+                                if (keep_lang)
+                                        xmlFree (keep_lang);
+                                if (value)
+                                        xmlFree (value);
+
+                                value = xmlNodeGetContent (cur);
+
+                                keep_lang = cur_lang;
+                                keep_pri = cur_pri;
+                        } else {
+                                if (cur_lang)
+                                        xmlFree (cur_lang);
+                        }
+                }
+        }
+
+        /* Delete all GVC_SOUND_NAME nodes */
+        cur = node->children;
+        while (cur) {
+                xmlNodePtr this = cur;
+                cur = cur->next;
+                if (! xmlStrcmp (this->name, GVC_SOUND_NAME)) {
+                        xmlUnlinkNode (this);
+                        xmlFreeNode (this);
+                }
+        }
+
+        return value;
+}
+
+static void
+populate_model_from_node (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          xmlNodePtr            node)
+{
+        xmlNodePtr child;
+        xmlChar   *filename;
+        xmlChar   *name;
+
+        filename = NULL;
+        name = xml_get_and_trim_names (node);
+        for (child = node->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+
+                if (xmlStrcmp (child->name, GVC_SOUND_FILENAME) == 0) {
+                        filename = xmlNodeGetContent (child);
+                } else if (xmlStrcmp (child->name, GVC_SOUND_NAME) == 0) {
+                        /* EH? should have been trimmed */
+                }
+        }
+
+        if (filename != NULL && name != NULL) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   ALERT_IDENTIFIER_COL, filename,
+                                                   ALERT_DISPLAY_COL, name,
+                                                   ALERT_SOUND_TYPE_COL, _("Built-in"),
+                                                   ALERT_ACTIVE_COL, FALSE,
+                                                   -1);
+        }
+
+        xmlFree (filename);
+        xmlFree (name);
+}
+
+static void
+populate_model_from_file (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          const char           *filename)
+{
+        xmlDocPtr  doc;
+        xmlNodePtr root;
+        xmlNodePtr child;
+        gboolean   exists;
+
+        exists = g_file_test (filename, G_FILE_TEST_EXISTS);
+        if (! exists) {
+                return;
+        }
+
+        doc = xmlParseFile (filename);
+        if (doc == NULL) {
+                return;
+        }
+
+        root = xmlDocGetRootElement (doc);
+
+        for (child = root->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+                if (xmlStrcmp (child->name, GVC_SOUND_SOUND) != 0) {
+                        continue;
+                }
+
+                populate_model_from_node (chooser, model, child);
+        }
+
+        xmlFreeDoc (doc);
+}
+
+static void
+populate_model_from_dir (GvcSoundThemeChooser *chooser,
+                         GtkTreeModel         *model,
+                         const char           *dirname)
+{
+        GDir       *d;
+        const char *name;
+
+        d = g_dir_open (dirname, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *path;
+
+                if (! g_str_has_suffix (name, ".xml")) {
+                        continue;
+                }
+
+                path = g_build_filename (dirname, name, NULL);
+                populate_model_from_file (chooser, model, path);
+                g_free (path);
+        }
+
+        g_dir_close (d);
+}
+
+static gboolean
+save_alert_sounds (GvcSoundThemeChooser  *chooser,
+                   const char            *id)
+{
+        const char *sounds[3] = { "bell-terminal", "bell-window-system", NULL };
+        char *path;
+
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+        } else {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+                add_custom_file (sounds, id);
+        }
+
+        /* And poke the directory so the theme gets updated */
+        path = custom_theme_dir_path (NULL);
+        if (utime (path, NULL) != 0) {
+                g_warning ("Failed to update mtime for directory '%s': %s",
+                           path, g_strerror (errno));
+        }
+        g_free (path);
+
+        return FALSE;
+}
+
+
+static void
+update_alert_model (GvcSoundThemeChooser  *chooser,
+                    const char            *id)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        gtk_tree_model_get_iter_first (model, &iter);
+        do {
+                gboolean toggled;
+                char    *this_id;
+
+                gtk_tree_model_get (model, &iter,
+                                    ALERT_IDENTIFIER_COL, &this_id,
+                                    -1);
+
+                if (strcmp (this_id, id) == 0) {
+                        toggled = TRUE;
+                } else {
+                        toggled = FALSE;
+                }
+                g_free (this_id);
+
+                gtk_list_store_set (GTK_LIST_STORE (model),
+                                    &iter,
+                                    ALERT_ACTIVE_COL, toggled,
+                                    -1);
+        } while (gtk_tree_model_iter_next (model, &iter));
+}
+
+static void
+update_alert (GvcSoundThemeChooser *chooser,
+              const char           *alert_id)
+{
+        GtkTreeModel *theme_model;
+        GtkTreeIter   iter;
+        char         *theme;
+        char         *parent;
+        gboolean      is_custom;
+        gboolean      is_default;
+        gboolean      add_custom;
+        gboolean      remove_custom;
+
+        theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        /* Get the current theme's name, and set the parent */
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        gtk_tree_model_get (theme_model, &iter,
+                            THEME_IDENTIFIER_COL, &theme,
+                            THEME_IDENTIFIER_COL, &parent,
+                            -1);
+        is_custom = strcmp (theme, CUSTOM_THEME_NAME) == 0;
+        is_default = strcmp (alert_id, DEFAULT_ALERT_ID) == 0;
+
+        /* So a few possibilities:
+         * 1. Named theme, default alert selected: noop
+         * 2. Named theme, alternate alert selected: create new custom with sound
+         * 3. Custom theme, default alert selected: remove sound and possibly custom
+         * 4. Custom theme, alternate alert selected: update custom sound
+         */
+        add_custom = FALSE;
+        remove_custom = FALSE;
+        if (! is_custom && is_default) {
+                /* remove custom just in case */
+                remove_custom = TRUE;
+        } else if (! is_custom && ! is_default) {
+                create_custom_theme (parent);
+                save_alert_sounds (chooser, alert_id);
+                add_custom = TRUE;
+        } else if (is_custom && is_default) {
+                save_alert_sounds (chooser, alert_id);
+                /* after removing files check if it is empty */
+                if (custom_theme_dir_is_empty ()) {
+                        remove_custom = TRUE;
+                }
+        } else if (is_custom && ! is_default) {
+                save_alert_sounds (chooser, alert_id);
+        }
+
+        if (add_custom) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (theme_model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   THEME_DISPLAY_COL, _("Custom"),
+                                                   THEME_IDENTIFIER_COL, CUSTOM_THEME_NAME,
+                                                   THEME_PARENT_ID_COL, theme,
+                                                   -1);
+                set_combox_for_theme_name (chooser, CUSTOM_THEME_NAME);
+        } else if (remove_custom) {
+                gtk_tree_model_get_iter_first (theme_model, &iter);
+                do {
+                        char *this_parent;
+
+                        gtk_tree_model_get (theme_model, &iter,
+                                            THEME_PARENT_ID_COL, &this_parent,
+                                            -1);
+                        if (this_parent != NULL && strcmp (this_parent, CUSTOM_THEME_NAME) != 0) {
+                                g_free (this_parent);
+                                gtk_list_store_remove (GTK_LIST_STORE (theme_model), &iter);
+                                break;
+                        }
+                        g_free (this_parent);
+                } while (gtk_tree_model_iter_next (theme_model, &iter));
+
+                delete_custom_theme_dir ();
+
+                set_combox_for_theme_name (chooser, parent);
+        }
+
+        update_alert_model (chooser, alert_id);
+
+        g_free (theme);
+        g_free (parent);
+}
+
+static void
+on_alert_toggled (GtkCellRendererToggle *renderer,
+                  char                  *path_str,
+                  GvcSoundThemeChooser  *chooser)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreePath  *path;
+        gboolean      toggled;
+        char         *id;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        path = gtk_tree_path_new_from_string (path_str);
+        gtk_tree_model_get_iter (model, &iter, path);
+        gtk_tree_path_free (path);
+
+        id = NULL;
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            ALERT_ACTIVE_COL, &toggled,
+                            -1);
+
+        toggled ^= 1;
+        if (toggled) {
+                update_alert (chooser, id);
+        }
+
+        g_free (id);
+}
+
+static void
+play_preview_for_path (GvcSoundThemeChooser *chooser, GtkTreePath *path)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreeIter   theme_iter;
+        gchar        *id = NULL;
+        gchar        *parent_theme = NULL;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        if (gtk_tree_model_get_iter (model, &iter, path) == FALSE)
+                return;
+
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            -1);
+        if (id == NULL)
+                return;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &theme_iter)) {
+                GtkTreeModel *theme_model;
+                gchar        *theme_id = NULL;
+                gchar        *parent_id = NULL;
+
+                theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+                gtk_tree_model_get (theme_model, &theme_iter,
+                                    THEME_IDENTIFIER_COL, &theme_id,
+                                    THEME_PARENT_ID_COL, &parent_id, -1);
+                if (theme_id && strcmp (theme_id, CUSTOM_THEME_NAME) == 0)
+                        parent_theme = g_strdup (parent_id);
+
+                g_free (theme_id);
+                g_free (parent_id);
+        }
+
+        /* special case: for the default item on custom themes
+         * play the alert for the parent theme */
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                if (parent_theme != NULL) {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_CANBERRA_XDG_THEME_NAME, parent_theme,
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                } else {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                }
+        } else {
+                ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                        CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                        CA_PROP_MEDIA_FILENAME, id,
+                                        CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                        CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                        CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                        CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                        NULL);
+
+        }
+        g_free (parent_theme);
+        g_free (id);
+}
+
+static void
+on_treeview_row_activated (GtkTreeView          *treeview,
+                           GtkTreePath          *path,
+                           GtkTreeViewColumn    *column,
+                           GvcSoundThemeChooser *chooser)
+{
+        play_preview_for_path (chooser, path);
+}
+
+static void
+on_treeview_selection_changed (GtkTreeSelection     *selection,
+                               GvcSoundThemeChooser *chooser)
+{
+        GList        *paths;
+        GtkTreeModel *model;
+        GtkTreePath  *path;
+
+        if (chooser->priv->treeview == NULL)
+                return;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        paths = gtk_tree_selection_get_selected_rows (selection, &model);
+        if (paths == NULL)
+                return;
+
+        path = paths->data;
+        play_preview_for_path (chooser, path);
+
+        g_list_foreach (paths, (GFunc)gtk_tree_path_free, NULL);
+        g_list_free (paths);
+}
+
+static GtkWidget *
+create_alert_treeview (GvcSoundThemeChooser *chooser)
+{
+        GtkListStore         *store;
+        GtkWidget            *treeview;
+        GtkCellRenderer      *renderer;
+        GtkTreeViewColumn    *column;
+        GtkTreeSelection     *selection;
+
+        treeview = gtk_tree_view_new ();
+
+        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
+        g_signal_connect (G_OBJECT (treeview),
+                          "row-activated",
+                          G_CALLBACK (on_treeview_row_activated),
+                          chooser);
+
+        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+        gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+        g_signal_connect (G_OBJECT (selection),
+                          "changed",
+                          G_CALLBACK (on_treeview_selection_changed),
+                          chooser);
+
+        /* Setup the tree model, 3 columns:
+         * - display name
+         * - sound id
+         * - sound type
+         */
+        store = gtk_list_store_new (ALERT_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_BOOLEAN);
+
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           ALERT_IDENTIFIER_COL, DEFAULT_ALERT_ID,
+                                           ALERT_DISPLAY_COL, _("Default"),
+                                           ALERT_SOUND_TYPE_COL, _("From theme"),
+                                           ALERT_ACTIVE_COL, TRUE,
+                                           -1);
+
+        populate_model_from_dir (chooser, GTK_TREE_MODEL (store), SOUND_SET_DIR);
+
+        gtk_tree_view_set_model (GTK_TREE_VIEW (treeview),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_toggle_new ();
+        gtk_cell_renderer_toggle_set_radio (GTK_CELL_RENDERER_TOGGLE (renderer), TRUE);
+
+        column = gtk_tree_view_column_new_with_attributes (NULL,
+                                                           renderer,
+                                                           "active", ALERT_ACTIVE_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+        g_signal_connect (renderer,
+                          "toggled",
+                          G_CALLBACK (on_alert_toggled),
+                          chooser);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Name"),
+                                                           renderer,
+                                                           "text", ALERT_DISPLAY_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Type"),
+                                                           renderer,
+                                                           "text", ALERT_SOUND_TYPE_COL,
+                                                           NULL);
+
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        return treeview;
+}
+
+static int
+get_file_type (const char *sound_name,
+               char      **linked_name)
+{
+        char *name, *filename;
+
+        *linked_name = NULL;
+
+        name = g_strdup_printf ("%s.disabled", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_REGULAR) != FALSE) {
+                g_free (filename);
+                return SOUND_TYPE_OFF;
+        }
+        g_free (filename);
+
+        /* We only check for .ogg files because those are the
+         * only ones we create */
+        name = g_strdup_printf ("%s.ogg", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_SYMLINK) != FALSE) {
+                *linked_name = g_file_read_link (filename, NULL);
+                g_free (filename);
+                return SOUND_TYPE_CUSTOM;
+        }
+        g_free (filename);
+
+        return SOUND_TYPE_BUILTIN;
+}
+
+static void
+update_alerts_from_theme_name (GvcSoundThemeChooser *chooser,
+                               const gchar          *name)
+{
+        if (strcmp (name, CUSTOM_THEME_NAME) != 0) {
+                /* reset alert to default */
+                update_alert (chooser, DEFAULT_ALERT_ID);
+        } else {
+                int   sound_type;
+                char *linkname;
+
+                linkname = NULL;
+                sound_type = get_file_type ("bell-terminal", &linkname);
+                g_debug ("Found link: %s", linkname);
+                if (sound_type == SOUND_TYPE_CUSTOM) {
+                        update_alert (chooser, linkname);
+                }
+        }
+}
+
+static void
+update_theme (GvcSoundThemeChooser *chooser)
+{
+        char        *theme_name;
+        gboolean     events_enabled;
+        gboolean     feedback_enabled;
+
+        feedback_enabled = g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY);
+        set_input_feedback_enabled (chooser, feedback_enabled);
+
+        events_enabled = g_settings_get_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY);
+        if (events_enabled) {
+                theme_name = g_settings_get_string (chooser->priv->sound_settings, SOUND_THEME_KEY);
+        } else {
+                theme_name = g_strdup (NO_SOUNDS_THEME_NAME);
+        }
+
+        gtk_widget_set_sensitive (chooser->priv->selection_box, events_enabled);
+        gtk_widget_set_sensitive (chooser->priv->click_feedback_button, events_enabled);
+
+        set_combox_for_theme_name (chooser, theme_name);
+
+        update_alerts_from_theme_name (chooser, theme_name);
+
+        g_free (theme_name);
+}
+
+static void
+gvc_sound_theme_chooser_class_init (GvcSoundThemeChooserClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_sound_theme_chooser_dispose;
+}
+
+static void
+on_click_feedback_toggled (GtkToggleButton      *button,
+                           GvcSoundThemeChooser *chooser)
+{
+        gboolean enabled;
+
+        enabled = gtk_toggle_button_get_active (button);
+
+        g_settings_set_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY, enabled);
+}
+
+static void
+on_key_changed (GSettings            *settings,
+                gchar                *key,
+                GvcSoundThemeChooser *chooser)
+{
+        if (!strcmp (key, EVENT_SOUNDS_KEY) ||
+            !strcmp (key, SOUND_THEME_KEY) ||
+            !strcmp (key, INPUT_SOUNDS_KEY))
+                update_theme (chooser);
+}
+
+static void
+setup_list_size_constraint (GtkWidget *widget,
+                            GtkWidget *to_size)
+{
+        GtkRequisition req;
+        gint           sc_height;
+        int            max_height;
+
+        /* Constrain height to be the tree height up to a max */
+        gdk_window_get_geometry (gdk_screen_get_root_window (gtk_widget_get_screen (widget)),
+                                 NULL, NULL, NULL, &sc_height);
+
+        max_height = sc_height / 4;
+
+        // XXX this doesn't work
+        gtk_widget_get_preferred_size (to_size, NULL, &req);
+
+        gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (widget),
+                                                    MIN (req.height, max_height));
+}
+
+static void
+gvc_sound_theme_chooser_init (GvcSoundThemeChooser *chooser)
+{
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *scrolled_window;
+        gchar       *str;
+
+        chooser->priv = gvc_sound_theme_chooser_get_instance_private (chooser);
+
+        chooser->priv->theme_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->theme_box, FALSE, FALSE, 0);
+
+        label = gtk_label_new_with_mnemonic (_("Sound _theme:"));
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), label, FALSE, FALSE, 0);
+        chooser->priv->combo_box = gtk_combo_box_new ();
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), chooser->priv->combo_box, FALSE, FALSE, 6);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->combo_box);
+
+        chooser->priv->sound_settings = g_settings_new (KEY_SOUNDS_SCHEMA);
+
+        g_signal_connect (G_OBJECT (chooser->priv->sound_settings),
+                          "changed",
+                          G_CALLBACK (on_key_changed),
+                          chooser);
+
+        str = g_strdup_printf ("<b>%s</b>", _("C_hoose an alert sound:"));
+        chooser->priv->selection_box = box = gtk_frame_new (str);
+        g_free (str);
+
+        label = gtk_frame_get_label_widget (GTK_FRAME (box));
+        gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
+        gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+        gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
+
+        gtk_box_pack_start (GTK_BOX (chooser), box, TRUE, TRUE, 6);
+
+        chooser->priv->treeview = create_alert_treeview (chooser);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->treeview);
+
+        scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+        gtk_widget_set_hexpand (scrolled_window, TRUE);
+        gtk_widget_set_vexpand (scrolled_window, TRUE);
+        gtk_widget_set_margin_top (scrolled_window, 6);
+
+        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+                                        GTK_POLICY_NEVER,
+                                        GTK_POLICY_AUTOMATIC);
+        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
+                                             GTK_SHADOW_IN);
+
+        gtk_container_add (GTK_CONTAINER (scrolled_window), chooser->priv->treeview);
+        gtk_container_add (GTK_CONTAINER (box), scrolled_window);
+
+        chooser->priv->click_feedback_button = gtk_check_button_new_with_mnemonic (_("Enable _window and button sounds"));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY));
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->click_feedback_button,
+                            FALSE, FALSE, 0);
+
+        g_signal_connect (G_OBJECT (chooser->priv->click_feedback_button),
+                          "toggled",
+                          G_CALLBACK (on_click_feedback_toggled),
+                          chooser);
+
+        setup_theme_selector (chooser);
+        update_theme (chooser);
+
+        setup_list_size_constraint (scrolled_window, chooser->priv->treeview);
+}
+
+static void
+gvc_sound_theme_chooser_dispose (GObject *object)
+{
+        GvcSoundThemeChooser *chooser;
+
+        chooser = GVC_SOUND_THEME_CHOOSER (object);
+
+        g_clear_object (&chooser->priv->sound_settings);
+
+        G_OBJECT_CLASS (gvc_sound_theme_chooser_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_sound_theme_chooser_new (void)
+{
+        return g_object_new (GVC_TYPE_SOUND_THEME_CHOOSER,
+                                "spacing", 6,
+                                "orientation", GTK_ORIENTATION_VERTICAL,
+                                NULL);
+}
+
+
+
+ + + diff --git a/2020-06-22-145654-0244-cppcheck@3eda50f90193_travis-ci/2.html b/2020-06-22-145654-0244-cppcheck@3eda50f90193_travis-ci/2.html new file mode 100644 index 0000000..bacfabb --- /dev/null +++ b/2020-06-22-145654-0244-cppcheck@3eda50f90193_travis-ci/2.html @@ -0,0 +1,1110 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <canberra.h>
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-speaker-test.h"
+#include "gvc-utils.h"
+
+struct _GvcSpeakerTestPrivate
+{
+        GArray           *controls;
+        ca_context       *canberra;
+        MateMixerStream  *stream;
+};
+
+enum {
+        PROP_0,
+        PROP_STREAM,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_speaker_test_dispose    (GObject             *object);
+static void gvc_speaker_test_finalize   (GObject             *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSpeakerTest, gvc_speaker_test, GTK_TYPE_GRID)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+typedef struct {
+        MateMixerChannelPosition position;
+        guint left;
+        guint top;
+} TablePosition;
+
+static const TablePosition positions[] = {
+        /* Position, X, Y */
+        { MATE_MIXER_CHANNEL_FRONT_LEFT, 0, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_LEFT_CENTER, 1, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_CENTER, 2, 0, },
+        { MATE_MIXER_CHANNEL_MONO, 2, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT_CENTER, 3, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT, 4, 0, },
+        { MATE_MIXER_CHANNEL_SIDE_LEFT, 0, 1, },
+        { MATE_MIXER_CHANNEL_SIDE_RIGHT, 4, 1, },
+        { MATE_MIXER_CHANNEL_BACK_LEFT, 0, 2, },
+        { MATE_MIXER_CHANNEL_BACK_CENTER, 2, 2, },
+        { MATE_MIXER_CHANNEL_BACK_RIGHT, 4, 2, },
+        { MATE_MIXER_CHANNEL_LFE, 3, 2 }
+};
+
+MateMixerStream *
+gvc_speaker_test_get_stream (GvcSpeakerTest *test)
+{
+        g_return_val_if_fail (GVC_IS_SPEAKER_TEST (test), NULL);
+
+        return test->priv->stream;
+}
+
+static void
+gvc_speaker_test_set_stream (GvcSpeakerTest *test, MateMixerStream *stream)
+{
+        MateMixerStreamControl *control;
+        const gchar            *name;
+        guint                   i;
+
+        name = mate_mixer_stream_get_name (stream);
+        control = mate_mixer_stream_get_default_control (stream);
+
+        ca_context_change_device (test->priv->canberra, name);
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                gboolean has_position =
+                        mate_mixer_stream_control_has_channel_position (control, positions[i].position);
+
+                gtk_widget_set_visible (g_array_index (test->priv->controls, GtkWidget *, i),
+                                        has_position);
+        }
+
+        test->priv->stream = g_object_ref (stream);
+}
+
+static void
+gvc_speaker_test_set_property (GObject       *object,
+                               guint          prop_id,
+                               const GValue  *value,
+                               GParamSpec    *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                gvc_speaker_test_set_stream (self, g_value_get_object (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_get_property (GObject     *object,
+                               guint        prop_id,
+                               GValue      *value,
+                               GParamSpec  *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                g_value_set_object (value, self->priv->stream);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_class_init (GvcSpeakerTestClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose  = gvc_speaker_test_dispose;
+        object_class->finalize = gvc_speaker_test_finalize;
+        object_class->set_property = gvc_speaker_test_set_property;
+        object_class->get_property = gvc_speaker_test_get_property;
+
+        properties[PROP_STREAM] =
+                g_param_spec_object ("stream",
+                                     "Stream",
+                                     "MateMixer stream",
+                                     MATE_MIXER_TYPE_STREAM,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+}
+
+static const gchar *
+sound_name (MateMixerChannelPosition position)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return "audio-channel-front-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return "audio-channel-front-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return "audio-channel-front-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return "audio-channel-rear-left";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return "audio-channel-rear-right";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return "audio-channel-rear-center";
+        case MATE_MIXER_CHANNEL_LFE:
+                return "audio-channel-lfe";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return "audio-channel-side-left";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return "audio-channel-side-right";
+        default:
+                return NULL;
+        }
+}
+
+static const gchar *
+icon_name (MateMixerChannelPosition position, gboolean playing)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return playing
+                        ? "audio-speaker-left-testing"
+                        : "audio-speaker-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return playing
+                        ? "audio-speaker-right-testing"
+                        : "audio-speaker-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return playing
+                        ? "audio-speaker-center-testing"
+                        : "audio-speaker-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return playing
+                        ? "audio-speaker-left-back-testing"
+                        : "audio-speaker-left-back";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return playing
+                        ? "audio-speaker-right-back-testing"
+                        : "audio-speaker-right-back";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return playing
+                        ? "audio-speaker-center-back-testing"
+                        : "audio-speaker-center-back";
+        case MATE_MIXER_CHANNEL_LFE:
+                return playing
+                        ? "audio-subwoofer-testing"
+                        : "audio-subwoofer";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return playing
+                        ? "audio-speaker-left-side-testing"
+                        : "audio-speaker-left-side";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return playing
+                        ? "audio-speaker-right-side-testing"
+                        : "audio-speaker-right-side";
+        default:
+                return NULL;
+        }
+}
+
+static void
+update_button (GtkWidget *control)
+{
+        GtkWidget *button;
+        GtkWidget *image;
+        gboolean   playing;
+        MateMixerChannelPosition position;
+
+        button = g_object_get_data (G_OBJECT (control), "button");
+        image  = g_object_get_data (G_OBJECT (control), "image");
+
+        position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+        playing  = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        gtk_button_set_label (GTK_BUTTON (button), playing ? _("Stop") : _("Test"));
+
+        gtk_image_set_from_icon_name (GTK_IMAGE (image),
+                                      icon_name (position, playing),
+                                      GTK_ICON_SIZE_DIALOG);
+}
+
+static gboolean
+idle_cb (GtkWidget *control)
+{
+        if (control != NULL) {
+                /* This is called in the background thread, hence forward to main thread
+                 * via idle callback */
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+
+                update_button (control);
+        }
+        return FALSE;
+}
+
+static void
+finish_cb (ca_context *c, uint32_t id, int error_code, void *userdata)
+{
+        GtkWidget *control = (GtkWidget *) userdata;
+
+        if (error_code == CA_ERROR_DESTROYED || control == NULL)
+                return;
+
+        g_idle_add ((GSourceFunc) idle_cb, control);
+}
+
+static void
+on_test_button_clicked (GtkButton *button, GtkWidget *control)
+{
+        gboolean    playing;
+        ca_context *canberra;
+
+        canberra = g_object_get_data (G_OBJECT (control), "canberra");
+
+        ca_context_cancel (canberra, 1);
+
+        playing = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        if (playing) {
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        } else {
+                MateMixerChannelPosition position;
+                const gchar *name;
+                ca_proplist *proplist;
+
+                position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+
+                ca_proplist_create (&proplist);
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_ROLE, "test");
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_NAME,
+                                  gvc_channel_position_to_pretty_string (position));
+                ca_proplist_sets (proplist,
+                                  CA_PROP_CANBERRA_FORCE_CHANNEL,
+                                  gvc_channel_position_to_pulse_string (position));
+
+                ca_proplist_sets (proplist, CA_PROP_CANBERRA_ENABLE, "1");
+
+                name = sound_name (position);
+                if (name != NULL) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, name);
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, "audio-test-signal");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets(proplist, CA_PROP_EVENT_ID, "bell-window-system");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (playing));
+        }
+
+        update_button (control);
+}
+
+static GtkWidget *
+create_control (ca_context *canberra, MateMixerChannelPosition position)
+{
+        GtkWidget   *control;
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *image;
+        GtkWidget   *test_button;
+        const gchar *name;
+
+        control = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+        box     = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        g_object_set_data (G_OBJECT (control), "position", GINT_TO_POINTER (position));
+        g_object_set_data (G_OBJECT (control), "canberra", canberra);
+
+        name = icon_name (position, FALSE);
+        if (name == NULL)
+                name = "audio-volume-medium";
+
+        image = gtk_image_new_from_icon_name (name, GTK_ICON_SIZE_DIALOG);
+        g_object_set_data (G_OBJECT (control), "image", image);
+        gtk_box_pack_start (GTK_BOX (control), image, FALSE, FALSE, 0);
+
+        label = gtk_label_new (gvc_channel_position_to_pretty_string (position));
+        gtk_box_pack_start (GTK_BOX (control), label, FALSE, FALSE, 0);
+
+        test_button = gtk_button_new_with_label (_("Test"));
+        g_signal_connect (G_OBJECT (test_button),
+                          "clicked",
+                          G_CALLBACK (on_test_button_clicked),
+                          control);
+
+        g_object_set_data (G_OBJECT (control), "button", test_button);
+
+        gtk_box_pack_start (GTK_BOX (box), test_button, TRUE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (control), box, FALSE, FALSE, 0);
+
+        gtk_widget_show_all (control);
+
+        return control;
+}
+
+static void
+create_controls (GvcSpeakerTest *test)
+{
+        guint i;
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                GtkWidget *control = create_control (test->priv->canberra, positions[i].position);
+
+                gtk_grid_attach (GTK_GRID (test),
+                                 control,
+                                 positions[i].left,
+                                 positions[i].top,
+                                 1, 1);
+                g_array_insert_val (test->priv->controls, i, control);
+        }
+}
+
+static void
+gvc_speaker_test_init (GvcSpeakerTest *test)
+{
+        GtkWidget *face;
+
+        test->priv = gvc_speaker_test_get_instance_private (test);
+
+        gtk_container_set_border_width (GTK_CONTAINER (test), 12);
+
+        face = gtk_image_new_from_icon_name ("face-smile", GTK_ICON_SIZE_DIALOG);
+
+        gtk_grid_attach (GTK_GRID (test),
+                         face,
+                         1, 1,
+                         3, 1);
+
+
+        gtk_grid_set_baseline_row (GTK_GRID (test), 1);
+        gtk_widget_show (face);
+
+        ca_context_create (&test->priv->canberra);
+
+        /* The test sounds are played for a single channel, set up using the
+         * FORCE_CHANNEL property of libcanberra; this property is only supported
+         * in the PulseAudio backend, so avoid other backends completely */
+        ca_context_set_driver (test->priv->canberra, "pulse");
+
+        ca_context_change_props (test->priv->canberra,
+                                 CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+                                 CA_PROP_APPLICATION_NAME, _("Volume Control"),
+                                 CA_PROP_APPLICATION_VERSION, VERSION,
+                                 CA_PROP_APPLICATION_ICON_NAME, "multimedia-volume-control",
+                                 NULL);
+
+        test->priv->controls = g_array_new (FALSE, FALSE, sizeof (GtkWidget *));
+
+        create_controls (test);
+}
+
+static void
+gvc_speaker_test_dispose (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        g_clear_object (&test->priv->stream);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->dispose (object);
+}
+
+static void
+gvc_speaker_test_finalize (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        ca_context_destroy (test->priv->canberra);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->finalize (object);
+}
+
+GtkWidget *
+gvc_speaker_test_new (MateMixerStream *stream)
+{
+        GObject *test;
+
+        g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL);
+
+        test = g_object_new (GVC_TYPE_SPEAKER_TEST,
+                             "row-spacing", 6,
+                             "column-spacing", 6,
+                             "row-homogeneous", TRUE,
+                             "column-homogeneous", TRUE,
+                             "stream", stream,
+                             NULL);
+
+        return GTK_WIDGET (test);
+}
+
+
+
+ + + diff --git a/2020-06-22-145654-0244-cppcheck@3eda50f90193_travis-ci/index.html b/2020-06-22-145654-0244-cppcheck@3eda50f90193_travis-ci/index.html new file mode 100644 index 0000000..59baeb0 --- /dev/null +++ b/2020-06-22-145654-0244-cppcheck@3eda50f90193_travis-ci/index.html @@ -0,0 +1,108 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
mate-volume-control/gvc-combo-box.c
70unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
mate-volume-control/gvc-sound-theme-chooser.c
735ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
746ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
758ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
mate-volume-control/gvc-speaker-test.c
53unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+ + + diff --git a/2020-06-22-145654-0244-cppcheck@3eda50f90193_travis-ci/stats.html b/2020-06-22-145654-0244-cppcheck@3eda50f90193_travis-ci/stats.html new file mode 100644 index 0000000..3fb6add --- /dev/null +++ b/2020-06-22-145654-0244-cppcheck@3eda50f90193_travis-ci/stats.html @@ -0,0 +1,93 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+

Top 10 files for error severity, total findings: 2
+   1  mate-volume-control/gvc-speaker-test.c
+   1  mate-volume-control/gvc-combo-box.c
+

+

Top 10 files for information severity, total findings: 3
+   3  mate-volume-control/gvc-sound-theme-chooser.c
+

+ +
+ + + diff --git a/2020-06-22-145654-0244-cppcheck@3eda50f90193_travis-ci/style.css b/2020-06-22-145654-0244-cppcheck@3eda50f90193_travis-ci/style.css new file mode 100644 index 0000000..c39571c --- /dev/null +++ b/2020-06-22-145654-0244-cppcheck@3eda50f90193_travis-ci/style.css @@ -0,0 +1,149 @@ + +body { + font: 13px Arial, Verdana, Sans-Serif; + margin: 0; + width: auto; +} + +h1 { + margin: 10px; +} + +#footer > p { + margin: 4px; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + border: 1px dotted black; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #B6B6B4; +} + +.inconclusive2 { + background-color: #B6B6B4; + border: 1px dotted black; + display: inline-block; + margin-left: 4px; +} + +div.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +div.verbose div.content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid black; + background-color: #FFFFCC; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +#header { + border-bottom: thin solid #aaa; +} + +#menu { + float: left; + margin-top: 5px; + text-align: left; + width: 150px; + /*height: 75%;*/ + position: fixed; + overflow: auto; + z-index: 1; +} + +#menu_index { + float: left; + margin-top: 5px; + padding-left: 5px; + text-align: left; + width: 300px; + /*height: 75%;*/ + position: fixed; + overflow: auto; + z-index: 1; +} + +#menu > a { + display: block; + margin-left: 10px; + font: 12px; + z-index: 1; +} + +#filename { + margin-left: 10px; + font: 12px; + z-index: 1; +} + +.highlighttable { + background-color:white; + z-index: 10; + position: relative; + margin: -10 px; +} + +#content { + background-color: white; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + float: left; + margin: 5px; + margin-left: 10px; + padding: 0 10px 10px 10px; + width: 80%; + padding-left: 150px; +} + +#content_index { + background-color: white; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + float: left; + margin: 5px; + margin-left: 10px; + padding: 0 10px 10px 10px; + width: 80%; + padding-left: 300px; +} + +.linenos { + border-right: thin solid #aaa; + color: lightgray; + padding-right: 6px; +} + +#footer { + border-top: thin solid #aaa; + clear: both; + font-size: 90%; + margin-top: 5px; +} + +#footer ul { + list-style-type: none; + padding-left: 0; +} diff --git a/2020-06-26-095009-5434-cppcheck@7f8975cc6d8d_master/0.html b/2020-06-26-095009-5434-cppcheck@7f8975cc6d8d_master/0.html new file mode 100644 index 0000000..e262ed0 --- /dev/null +++ b/2020-06-26-095009-5434-cppcheck@7f8975cc6d8d_master/0.html @@ -0,0 +1,1038 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-combo-box.h"
+
+struct _GvcComboBoxPrivate
+{
+        GtkWidget       *drop_box;
+        GtkWidget       *start_box;
+        GtkWidget       *end_box;
+        GtkWidget       *label;
+        GtkWidget       *button;
+        GtkTreeModel    *model;
+        GtkWidget       *combobox;
+        MateMixerSwitch *swtch;
+};
+
+enum {
+        COL_NAME,
+        COL_HUMAN_NAME,
+        NUM_COLS
+};
+
+enum {
+        CHANGING,
+        BUTTON_CLICKED,
+        LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+enum {
+        PROP_0,
+        PROP_SWITCH,
+        PROP_LABEL,
+        PROP_SHOW_BUTTON,
+        PROP_BUTTON_LABEL,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_combo_box_dispose    (GObject          *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcComboBox, gvc_combo_box, GTK_TYPE_BOX)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+MateMixerSwitch *
+gvc_combo_box_get_switch (GvcComboBox *combobox)
+{
+        g_return_val_if_fail (GVC_IS_COMBO_BOX (combobox), NULL);
+
+        return combobox->priv->swtch;
+}
+
+void
+gvc_combo_box_set_size_group (GvcComboBox  *combobox,
+                              GtkSizeGroup *group,
+                              gboolean      symmetric)
+{
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (GTK_IS_SIZE_GROUP (group));
+
+        if (group != NULL) {
+                gtk_size_group_add_widget (group, combobox->priv->start_box);
+                if (symmetric == TRUE)
+                        gtk_size_group_add_widget (group, combobox->priv->end_box);
+        }
+        gtk_widget_queue_draw (GTK_WIDGET (combobox));
+}
+
+static void
+on_switch_active_option_notify (MateMixerSwitch *swtch,
+                                GParamSpec      *pspec,
+                                GvcComboBox     *combobox)
+{
+        GtkTreeIter            iter;
+        MateMixerSwitchOption *active;
+        gboolean               cont;
+        const gchar           *name;
+
+        active = mate_mixer_switch_get_active_option (swtch);
+        if (G_UNLIKELY (active == NULL)) {
+                g_warn_if_reached ();
+                return;
+        }
+
+        /* Select the newly activated switch option in the combo box */
+        name = mate_mixer_switch_option_get_name (active);
+        cont = gtk_tree_model_get_iter_first (combobox->priv->model, &iter);
+        while (cont == TRUE) {
+                gchar *current;
+
+                gtk_tree_model_get (combobox->priv->model, &iter,
+                                    COL_NAME, &current,
+                                    -1);
+                if (g_strcmp0 (name, current) == 0) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox), &iter);
+                        g_free (current);
+                        return;
+                }
+                g_free (current);
+
+                cont = gtk_tree_model_iter_next (combobox->priv->model, &iter);
+        }
+        g_warning ("Could not find switch option '%s' in combo box", name);
+}
+
+static void
+gvc_combo_box_set_switch (GvcComboBox *combobox, MateMixerSwitch *swtch)
+{
+        MateMixerSwitchOption *active;
+        const GList           *options;
+
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (MATE_MIXER_IS_SWITCH (swtch));
+
+        combobox->priv->swtch = g_object_ref (swtch);
+
+        active  = mate_mixer_switch_get_active_option (swtch);
+        options = mate_mixer_switch_list_options (swtch);
+        while (options != NULL) {
+                GtkTreeIter            iter;
+                MateMixerSwitchOption *option = MATE_MIXER_SWITCH_OPTION (options->data);
+
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (combobox->priv->model),
+                                                   &iter,
+                                                   G_MAXINT,
+                                                   COL_NAME,
+                                                   mate_mixer_switch_option_get_name (option),
+                                                   COL_HUMAN_NAME,
+                                                   mate_mixer_switch_option_get_label (option),
+                                                   -1);
+
+                /* Select the currently active option of the switch */
+                if (option == active) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox),
+                                                       &iter);
+                }
+                options = options->next;
+        }
+
+        g_signal_connect (G_OBJECT (swtch),
+                          "notify::active-option",
+                          G_CALLBACK (on_switch_active_option_notify),
+                          combobox);
+}
+
+static void
+gvc_combo_box_set_property (GObject       *object,
+                            guint          prop_id,
+                            const GValue  *value,
+                            GParamSpec    *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                gvc_combo_box_set_switch (self, g_value_get_object (value));
+                break;
+        case PROP_LABEL:
+                gtk_label_set_text_with_mnemonic (GTK_LABEL (self->priv->label), g_value_get_string (value));
+                break;
+        case PROP_BUTTON_LABEL:
+                gtk_button_set_label (GTK_BUTTON (self->priv->button), g_value_get_string (value));
+                break;
+        case PROP_SHOW_BUTTON:
+                gtk_widget_set_visible (self->priv->button, g_value_get_boolean (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_get_property (GObject     *object,
+                            guint        prop_id,
+                            GValue      *value,
+                            GParamSpec  *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                g_value_set_object (value, self->priv->swtch);
+                break;
+        case PROP_LABEL:
+                g_value_set_string (value, gtk_label_get_text (GTK_LABEL (self->priv->label)));
+                break;
+        case PROP_BUTTON_LABEL:
+                g_value_set_string (value, gtk_button_get_label (GTK_BUTTON (self->priv->button)));
+                break;
+        case PROP_SHOW_BUTTON:
+                g_value_set_boolean (value, gtk_widget_get_visible (self->priv->button));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_class_init (GvcComboBoxClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_combo_box_dispose;
+        object_class->set_property = gvc_combo_box_set_property;
+        object_class->get_property = gvc_combo_box_get_property;
+
+        properties[PROP_SWITCH] =
+                g_param_spec_object ("switch",
+                                     "switch",
+                                     "The MateMixerSwitch",
+                                     MATE_MIXER_TYPE_SWITCH,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_LABEL] =
+                g_param_spec_string ("label",
+                                     "label",
+                                     "The combo box label",
+                                     _("_Profile:"),
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_SHOW_BUTTON] =
+                g_param_spec_boolean ("show-button",
+                                      "show-button",
+                                      "Whether to show the button",
+                                      FALSE,
+                                      G_PARAM_READWRITE |
+                                      G_PARAM_CONSTRUCT |
+                                      G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_BUTTON_LABEL] =
+                g_param_spec_string ("button-label",
+                                     "button-label",
+                                     "The button's label",
+                                     "",
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+
+        signals[CHANGING] =
+                g_signal_new ("changing",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, changing),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__OBJECT,
+                              G_TYPE_NONE,
+                              1,
+                              MATE_MIXER_TYPE_SWITCH_OPTION);
+
+        signals[BUTTON_CLICKED] =
+                g_signal_new ("button-clicked",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, button_clicked),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
+}
+
+static void
+on_combo_box_changed (GtkComboBox *widget, GvcComboBox *combobox)
+{
+        GtkTreeIter            iter;
+        gchar                 *name;
+        MateMixerSwitchOption *option;
+
+        if (G_UNLIKELY (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter) == FALSE))
+                return;
+
+        gtk_tree_model_get (combobox->priv->model, &iter,
+                            COL_NAME, &name,
+                            -1);
+
+        option = mate_mixer_switch_get_option (combobox->priv->swtch, name);
+        if (G_UNLIKELY (option == NULL)) {
+                g_warn_if_reached ();
+                g_free (name);
+                return;
+        }
+
+        /* Inform that we are about to change the active option of the switch */
+        g_signal_emit (combobox, signals[CHANGING], 0, option);
+
+        mate_mixer_switch_set_active_option (combobox->priv->swtch, option);
+        g_free (name);
+}
+
+static void
+on_combo_box_button_clicked (GtkButton *button, GvcComboBox *combobox)
+{
+        /* The meaning of the button is defined by the owner, so only notify
+         * when it is clicked on */
+        g_signal_emit (combobox, signals[BUTTON_CLICKED], 0);
+}
+
+static void
+gvc_combo_box_init (GvcComboBox *combobox)
+{
+        GtkWidget       *frame;
+        GtkCellRenderer *renderer;
+
+        frame = gtk_frame_new (NULL);
+        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
+
+        combobox->priv = gvc_combo_box_get_instance_private (combobox);
+
+        combobox->priv->model = GTK_TREE_MODEL (gtk_list_store_new (NUM_COLS,
+                                                                    G_TYPE_STRING,
+                                                                    G_TYPE_STRING));
+
+        combobox->priv->combobox = gtk_combo_box_new_with_model (combobox->priv->model);
+
+        combobox->priv->label = gtk_label_new (NULL);
+
+        gtk_label_set_xalign (GTK_LABEL (combobox->priv->label), 0.0);
+        gtk_label_set_yalign (GTK_LABEL (combobox->priv->label), 0.5);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (combobox->priv->label),
+                                       combobox->priv->combobox);
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                    renderer,
+                                    FALSE);
+        gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                       renderer,
+                                       "text",
+                                       COL_HUMAN_NAME);
+
+        combobox->priv->drop_box  = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->start_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->end_box   = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+        /* Make sure the combo box does not get too long on long profile names */
+        g_object_set (G_OBJECT (renderer),
+                      "ellipsize",
+                      PANGO_ELLIPSIZE_END,
+                      NULL);
+
+        gtk_combo_box_set_popup_fixed_width (GTK_COMBO_BOX (combobox->priv->combobox), FALSE);
+
+        gtk_box_pack_start (GTK_BOX (combobox),
+                            frame,
+                            TRUE, TRUE, 0);
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->start_box,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->start_box),
+                            combobox->priv->label,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->combobox,
+                            TRUE, TRUE, 0);
+
+        combobox->priv->button = gtk_button_new_with_label ("");
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->button,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->end_box,
+                            FALSE, FALSE, 0);
+
+        gtk_container_add (GTK_CONTAINER (frame), combobox->priv->drop_box);
+
+        g_signal_connect (G_OBJECT (combobox->priv->combobox),
+                          "changed",
+                          G_CALLBACK (on_combo_box_changed),
+                          combobox);
+        g_signal_connect (G_OBJECT (combobox->priv->button),
+                          "clicked",
+                          G_CALLBACK (on_combo_box_button_clicked),
+                          combobox);
+
+        gtk_widget_set_no_show_all (combobox->priv->button, TRUE);
+        gtk_widget_show_all (frame);
+}
+
+static void
+gvc_combo_box_dispose (GObject *object)
+{
+        GvcComboBox *combobox;
+
+        combobox = GVC_COMBO_BOX (object);
+
+        if (G_LIKELY (combobox->priv->swtch != NULL)) {
+                g_signal_handlers_disconnect_by_func (G_OBJECT (combobox->priv->swtch),
+                                                      G_CALLBACK (on_switch_active_option_notify),
+                                                      combobox);
+                g_clear_object (&combobox->priv->swtch);
+        }
+
+        g_clear_object (&combobox->priv->model);
+
+        G_OBJECT_CLASS (gvc_combo_box_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_combo_box_new (MateMixerSwitch *swtch, const gchar *label)
+{
+        return g_object_new (GVC_TYPE_COMBO_BOX,
+                             "switch", swtch,
+                             "label", label,
+                             "orientation", GTK_ORIENTATION_HORIZONTAL,
+                             NULL);
+}
+
+
+
+ + + diff --git a/2020-06-26-095009-5434-cppcheck@7f8975cc6d8d_master/1.html b/2020-06-26-095009-5434-cppcheck@7f8975cc6d8d_master/1.html new file mode 100644 index 0000000..67179f2 --- /dev/null +++ b/2020-06-26-095009-5434-cppcheck@7f8975cc6d8d_master/1.html @@ -0,0 +1,2368 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
+ * Copyright (C) 2008 William Jon McCann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <utime.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+#include <canberra-gtk.h>
+#include <libxml/tree.h>
+
+#include "gvc-sound-theme-chooser.h"
+#include "sound-theme-file-utils.h"
+
+struct GvcSoundThemeChooserPrivate
+{
+        GtkWidget *combo_box;
+        GtkWidget *treeview;
+        GtkWidget *theme_box;
+        GtkWidget *selection_box;
+        GtkWidget *click_feedback_button;
+        GSettings *sound_settings;
+};
+
+static void     gvc_sound_theme_chooser_dispose   (GObject            *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSoundThemeChooser, gvc_sound_theme_chooser, GTK_TYPE_BOX)
+
+#define KEY_SOUNDS_SCHEMA          "org.mate.sound"
+#define EVENT_SOUNDS_KEY           "event-sounds"
+#define INPUT_SOUNDS_KEY           "input-feedback-sounds"
+#define SOUND_THEME_KEY            "theme-name"
+
+#define DEFAULT_ALERT_ID        "__default"
+#define CUSTOM_THEME_NAME       "__custom"
+#define NO_SOUNDS_THEME_NAME    "__no_sounds"
+
+enum {
+        THEME_DISPLAY_COL,
+        THEME_IDENTIFIER_COL,
+        THEME_PARENT_ID_COL,
+        THEME_NUM_COLS
+};
+
+enum {
+        ALERT_DISPLAY_COL,
+        ALERT_IDENTIFIER_COL,
+        ALERT_SOUND_TYPE_COL,
+        ALERT_ACTIVE_COL,
+        ALERT_NUM_COLS
+};
+
+enum {
+        SOUND_TYPE_UNSET,
+        SOUND_TYPE_OFF,
+        SOUND_TYPE_DEFAULT_FROM_THEME,
+        SOUND_TYPE_BUILTIN,
+        SOUND_TYPE_CUSTOM
+};
+
+static void
+on_combobox_changed (GtkComboBox          *widget,
+                     GvcSoundThemeChooser *chooser)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        char         *theme_name;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &theme_name, -1);
+
+        g_assert (theme_name != NULL);
+
+        /* It is necessary to update the theme name before any other setting as
+         * the "changed" notification will reload the contents of the widget */
+        g_settings_set_string (chooser->priv->sound_settings, SOUND_THEME_KEY, theme_name);
+
+        /* special case for no sounds */
+        if (strcmp (theme_name, NO_SOUNDS_THEME_NAME) == 0) {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, FALSE);
+                return;
+        } else {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, TRUE);
+        }
+
+        g_free (theme_name);
+
+        /* FIXME: reset alert model */
+}
+
+static char *
+load_index_theme_name (const char *index,
+                       char      **parent)
+{
+        GKeyFile *file;
+        char *indexname = NULL;
+        gboolean hidden;
+
+        file = g_key_file_new ();
+        if (g_key_file_load_from_file (file, index, G_KEY_FILE_KEEP_TRANSLATIONS, NULL) == FALSE) {
+                g_key_file_free (file);
+                return NULL;
+        }
+        /* Don't add hidden themes to the list */
+        hidden = g_key_file_get_boolean (file, "Sound Theme", "Hidden", NULL);
+        if (!hidden) {
+                indexname = g_key_file_get_locale_string (file,
+                                                          "Sound Theme",
+                                                          "Name",
+                                                          NULL,
+                                                          NULL);
+
+                /* Save the parent theme, if there's one */
+                if (parent != NULL) {
+                        *parent = g_key_file_get_string (file,
+                                                         "Sound Theme",
+                                                         "Inherits",
+                                                         NULL);
+                }
+        }
+
+        g_key_file_free (file);
+        return indexname;
+}
+
+static void
+sound_theme_in_dir (GHashTable *hash,
+                    const char *dir)
+{
+        GDir *d;
+        const char *name;
+
+        d = g_dir_open (dir, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *dirname, *index, *indexname;
+
+                /* Look for directories */
+                dirname = g_build_filename (dir, name, NULL);
+                if (g_file_test (dirname, G_FILE_TEST_IS_DIR) == FALSE) {
+                        g_free (dirname);
+                        continue;
+                }
+
+                /* Look for index files */
+                index = g_build_filename (dirname, "index.theme", NULL);
+                g_free (dirname);
+
+                /* Check the name of the theme in the index.theme file */
+                indexname = load_index_theme_name (index, NULL);
+                g_free (index);
+                if (indexname == NULL) {
+                        continue;
+                }
+
+                g_hash_table_insert (hash, g_strdup (name), indexname);
+        }
+
+        g_dir_close (d);
+}
+
+static void
+add_theme_to_store (const char   *key,
+                    const char   *value,
+                    GtkListStore *store)
+{
+        char *parent;
+
+        parent = NULL;
+
+        /* Get the parent, if we're checking the custom theme */
+        if (strcmp (key, CUSTOM_THEME_NAME) == 0) {
+                char *name, *path;
+
+                path = custom_theme_dir_path ("index.theme");
+                name = load_index_theme_name (path, &parent);
+                g_free (name);
+                g_free (path);
+        }
+        gtk_list_store_insert_with_values (store, NULL, G_MAXINT,
+                                           THEME_DISPLAY_COL, value,
+                                           THEME_IDENTIFIER_COL, key,
+                                           THEME_PARENT_ID_COL, parent,
+                                           -1);
+        g_free (parent);
+}
+
+static void
+set_combox_for_theme_name (GvcSoundThemeChooser *chooser,
+                           const char           *name)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        gboolean      found;
+
+        /* If the name is empty, use "freedesktop" */
+        if (name == NULL || *name == '\0') {
+                name = "freedesktop";
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+        if (gtk_tree_model_get_iter_first (model, &iter) == FALSE) {
+                return;
+        }
+
+        do {
+                char *value;
+
+                gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &value, -1);
+                found = (value != NULL && strcmp (value, name) == 0);
+                g_free (value);
+
+        } while (!found && gtk_tree_model_iter_next (model, &iter));
+
+        /* When we can't find the theme we need to set, try to set the default
+         * one "freedesktop" */
+        if (found) {
+                gtk_combo_box_set_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter);
+        } else if (strcmp (name, "freedesktop") != 0) {
+                g_debug ("not found, falling back to fdo");
+                set_combox_for_theme_name (chooser, "freedesktop");
+        }
+}
+
+static void
+set_input_feedback_enabled (GvcSoundThemeChooser *chooser,
+                            gboolean              enabled)
+{
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      enabled);
+}
+
+static void
+setup_theme_selector (GvcSoundThemeChooser *chooser)
+{
+        GHashTable           *hash;
+        GtkListStore         *store;
+        GtkCellRenderer      *renderer;
+        const char * const   *data_dirs;
+        const char           *data_dir;
+        char                 *dir;
+        guint                 i;
+
+        /* Add the theme names and their display name to a hash table,
+         * makes it easy to avoid duplicate themes */
+        hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+        data_dirs = g_get_system_data_dirs ();
+        for (i = 0; data_dirs[i] != NULL; i++) {
+                dir = g_build_filename (data_dirs[i], "sounds", NULL);
+                sound_theme_in_dir (hash, dir);
+                g_free (dir);
+        }
+
+        data_dir = g_get_user_data_dir ();
+        dir = g_build_filename (data_dir, "sounds", NULL);
+        sound_theme_in_dir (hash, dir);
+        g_free (dir);
+
+        /* If there isn't at least one theme, make everything
+         * insensitive, LAME! */
+        if (g_hash_table_size (hash) == 0) {
+                gtk_widget_set_sensitive (GTK_WIDGET (chooser), FALSE);
+                g_warning ("Bad setup, install the freedesktop sound theme");
+                g_hash_table_destroy (hash);
+                return;
+        }
+
+        /* Setup the tree model, 3 columns:
+         * - internal theme name/directory
+         * - display theme name
+         * - the internal id for the parent theme, used for the custom theme */
+        store = gtk_list_store_new (THEME_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING);
+
+        /* Add the themes to a combobox */
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           THEME_DISPLAY_COL, _("No sounds"),
+                                           THEME_IDENTIFIER_COL, "__no_sounds",
+                                           THEME_PARENT_ID_COL, NULL,
+                                           -1);
+        g_hash_table_foreach (hash, (GHFunc) add_theme_to_store, store);
+        g_hash_table_destroy (hash);
+
+        /* Set the display */
+        gtk_combo_box_set_model (GTK_COMBO_BOX (chooser->priv->combo_box),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                    renderer,
+                                    TRUE);
+        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                        renderer,
+                                        "text", THEME_DISPLAY_COL,
+                                        NULL);
+
+        g_signal_connect (G_OBJECT (chooser->priv->combo_box),
+                          "changed",
+                          G_CALLBACK (on_combobox_changed),
+                          chooser);
+}
+
+#define GVC_SOUND_SOUND    (xmlChar *) "sound"
+#define GVC_SOUND_NAME     (xmlChar *) "name"
+#define GVC_SOUND_FILENAME (xmlChar *) "filename"
+
+/* Adapted from yelp-toc-pager.c */
+static xmlChar *
+xml_get_and_trim_names (xmlNodePtr node)
+{
+        xmlNodePtr cur;
+        xmlChar *keep_lang = NULL;
+        xmlChar *value;
+        int j, keep_pri = INT_MAX;
+
+        const gchar * const * langs = g_get_language_names ();
+
+        value = NULL;
+
+        for (cur = node->children; cur; cur = cur->next) {
+                if (! xmlStrcmp (cur->name, GVC_SOUND_NAME)) {
+                        xmlChar *cur_lang = NULL;
+                        int cur_pri = INT_MAX;
+
+                        cur_lang = xmlNodeGetLang (cur);
+
+                        if (cur_lang) {
+                                for (j = 0; langs[j]; j++) {
+                                        if (g_str_equal (cur_lang, langs[j])) {
+                                                cur_pri = j;
+                                                break;
+                                        }
+                                }
+                        } else {
+                                cur_pri = INT_MAX - 1;
+                        }
+
+                        if (cur_pri <= keep_pri) {
+                                if (keep_lang)
+                                        xmlFree (keep_lang);
+                                if (value)
+                                        xmlFree (value);
+
+                                value = xmlNodeGetContent (cur);
+
+                                keep_lang = cur_lang;
+                                keep_pri = cur_pri;
+                        } else {
+                                if (cur_lang)
+                                        xmlFree (cur_lang);
+                        }
+                }
+        }
+
+        /* Delete all GVC_SOUND_NAME nodes */
+        cur = node->children;
+        while (cur) {
+                xmlNodePtr this = cur;
+                cur = cur->next;
+                if (! xmlStrcmp (this->name, GVC_SOUND_NAME)) {
+                        xmlUnlinkNode (this);
+                        xmlFreeNode (this);
+                }
+        }
+
+        return value;
+}
+
+static void
+populate_model_from_node (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          xmlNodePtr            node)
+{
+        xmlNodePtr child;
+        xmlChar   *filename;
+        xmlChar   *name;
+
+        filename = NULL;
+        name = xml_get_and_trim_names (node);
+        for (child = node->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+
+                if (xmlStrcmp (child->name, GVC_SOUND_FILENAME) == 0) {
+                        filename = xmlNodeGetContent (child);
+                } else if (xmlStrcmp (child->name, GVC_SOUND_NAME) == 0) {
+                        /* EH? should have been trimmed */
+                }
+        }
+
+        if (filename != NULL && name != NULL) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   ALERT_IDENTIFIER_COL, filename,
+                                                   ALERT_DISPLAY_COL, name,
+                                                   ALERT_SOUND_TYPE_COL, _("Built-in"),
+                                                   ALERT_ACTIVE_COL, FALSE,
+                                                   -1);
+        }
+
+        xmlFree (filename);
+        xmlFree (name);
+}
+
+static void
+populate_model_from_file (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          const char           *filename)
+{
+        xmlDocPtr  doc;
+        xmlNodePtr root;
+        xmlNodePtr child;
+        gboolean   exists;
+
+        exists = g_file_test (filename, G_FILE_TEST_EXISTS);
+        if (! exists) {
+                return;
+        }
+
+        doc = xmlParseFile (filename);
+        if (doc == NULL) {
+                return;
+        }
+
+        root = xmlDocGetRootElement (doc);
+
+        for (child = root->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+                if (xmlStrcmp (child->name, GVC_SOUND_SOUND) != 0) {
+                        continue;
+                }
+
+                populate_model_from_node (chooser, model, child);
+        }
+
+        xmlFreeDoc (doc);
+}
+
+static void
+populate_model_from_dir (GvcSoundThemeChooser *chooser,
+                         GtkTreeModel         *model,
+                         const char           *dirname)
+{
+        GDir       *d;
+        const char *name;
+
+        d = g_dir_open (dirname, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *path;
+
+                if (! g_str_has_suffix (name, ".xml")) {
+                        continue;
+                }
+
+                path = g_build_filename (dirname, name, NULL);
+                populate_model_from_file (chooser, model, path);
+                g_free (path);
+        }
+
+        g_dir_close (d);
+}
+
+static gboolean
+save_alert_sounds (GvcSoundThemeChooser  *chooser,
+                   const char            *id)
+{
+        const char *sounds[3] = { "bell-terminal", "bell-window-system", NULL };
+        char *path;
+
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+        } else {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+                add_custom_file (sounds, id);
+        }
+
+        /* And poke the directory so the theme gets updated */
+        path = custom_theme_dir_path (NULL);
+        if (utime (path, NULL) != 0) {
+                g_warning ("Failed to update mtime for directory '%s': %s",
+                           path, g_strerror (errno));
+        }
+        g_free (path);
+
+        return FALSE;
+}
+
+
+static void
+update_alert_model (GvcSoundThemeChooser  *chooser,
+                    const char            *id)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        gtk_tree_model_get_iter_first (model, &iter);
+        do {
+                gboolean toggled;
+                char    *this_id;
+
+                gtk_tree_model_get (model, &iter,
+                                    ALERT_IDENTIFIER_COL, &this_id,
+                                    -1);
+
+                if (strcmp (this_id, id) == 0) {
+                        toggled = TRUE;
+                } else {
+                        toggled = FALSE;
+                }
+                g_free (this_id);
+
+                gtk_list_store_set (GTK_LIST_STORE (model),
+                                    &iter,
+                                    ALERT_ACTIVE_COL, toggled,
+                                    -1);
+        } while (gtk_tree_model_iter_next (model, &iter));
+}
+
+static void
+update_alert (GvcSoundThemeChooser *chooser,
+              const char           *alert_id)
+{
+        GtkTreeModel *theme_model;
+        GtkTreeIter   iter;
+        char         *theme;
+        char         *parent;
+        gboolean      is_custom;
+        gboolean      is_default;
+        gboolean      add_custom;
+        gboolean      remove_custom;
+
+        theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        /* Get the current theme's name, and set the parent */
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        gtk_tree_model_get (theme_model, &iter,
+                            THEME_IDENTIFIER_COL, &theme,
+                            THEME_IDENTIFIER_COL, &parent,
+                            -1);
+        is_custom = strcmp (theme, CUSTOM_THEME_NAME) == 0;
+        is_default = strcmp (alert_id, DEFAULT_ALERT_ID) == 0;
+
+        /* So a few possibilities:
+         * 1. Named theme, default alert selected: noop
+         * 2. Named theme, alternate alert selected: create new custom with sound
+         * 3. Custom theme, default alert selected: remove sound and possibly custom
+         * 4. Custom theme, alternate alert selected: update custom sound
+         */
+        add_custom = FALSE;
+        remove_custom = FALSE;
+        if (! is_custom && is_default) {
+                /* remove custom just in case */
+                remove_custom = TRUE;
+        } else if (! is_custom && ! is_default) {
+                create_custom_theme (parent);
+                save_alert_sounds (chooser, alert_id);
+                add_custom = TRUE;
+        } else if (is_custom && is_default) {
+                save_alert_sounds (chooser, alert_id);
+                /* after removing files check if it is empty */
+                if (custom_theme_dir_is_empty ()) {
+                        remove_custom = TRUE;
+                }
+        } else if (is_custom && ! is_default) {
+                save_alert_sounds (chooser, alert_id);
+        }
+
+        if (add_custom) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (theme_model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   THEME_DISPLAY_COL, _("Custom"),
+                                                   THEME_IDENTIFIER_COL, CUSTOM_THEME_NAME,
+                                                   THEME_PARENT_ID_COL, theme,
+                                                   -1);
+                set_combox_for_theme_name (chooser, CUSTOM_THEME_NAME);
+        } else if (remove_custom) {
+                gtk_tree_model_get_iter_first (theme_model, &iter);
+                do {
+                        char *this_parent;
+
+                        gtk_tree_model_get (theme_model, &iter,
+                                            THEME_PARENT_ID_COL, &this_parent,
+                                            -1);
+                        if (this_parent != NULL && strcmp (this_parent, CUSTOM_THEME_NAME) != 0) {
+                                g_free (this_parent);
+                                gtk_list_store_remove (GTK_LIST_STORE (theme_model), &iter);
+                                break;
+                        }
+                        g_free (this_parent);
+                } while (gtk_tree_model_iter_next (theme_model, &iter));
+
+                delete_custom_theme_dir ();
+
+                set_combox_for_theme_name (chooser, parent);
+        }
+
+        update_alert_model (chooser, alert_id);
+
+        g_free (theme);
+        g_free (parent);
+}
+
+static void
+on_alert_toggled (GtkCellRendererToggle *renderer,
+                  char                  *path_str,
+                  GvcSoundThemeChooser  *chooser)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreePath  *path;
+        gboolean      toggled;
+        char         *id;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        path = gtk_tree_path_new_from_string (path_str);
+        gtk_tree_model_get_iter (model, &iter, path);
+        gtk_tree_path_free (path);
+
+        id = NULL;
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            ALERT_ACTIVE_COL, &toggled,
+                            -1);
+
+        toggled ^= 1;
+        if (toggled) {
+                update_alert (chooser, id);
+        }
+
+        g_free (id);
+}
+
+static void
+play_preview_for_path (GvcSoundThemeChooser *chooser, GtkTreePath *path)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreeIter   theme_iter;
+        gchar        *id = NULL;
+        gchar        *parent_theme = NULL;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        if (gtk_tree_model_get_iter (model, &iter, path) == FALSE)
+                return;
+
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            -1);
+        if (id == NULL)
+                return;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &theme_iter)) {
+                GtkTreeModel *theme_model;
+                gchar        *theme_id = NULL;
+                gchar        *parent_id = NULL;
+
+                theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+                gtk_tree_model_get (theme_model, &theme_iter,
+                                    THEME_IDENTIFIER_COL, &theme_id,
+                                    THEME_PARENT_ID_COL, &parent_id, -1);
+                if (theme_id && strcmp (theme_id, CUSTOM_THEME_NAME) == 0)
+                        parent_theme = g_strdup (parent_id);
+
+                g_free (theme_id);
+                g_free (parent_id);
+        }
+
+        /* special case: for the default item on custom themes
+         * play the alert for the parent theme */
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                if (parent_theme != NULL) {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_CANBERRA_XDG_THEME_NAME, parent_theme,
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                } else {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                }
+        } else {
+                ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                        CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                        CA_PROP_MEDIA_FILENAME, id,
+                                        CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                        CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                        CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                        CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                        NULL);
+
+        }
+        g_free (parent_theme);
+        g_free (id);
+}
+
+static void
+on_treeview_row_activated (GtkTreeView          *treeview,
+                           GtkTreePath          *path,
+                           GtkTreeViewColumn    *column,
+                           GvcSoundThemeChooser *chooser)
+{
+        play_preview_for_path (chooser, path);
+}
+
+static void
+on_treeview_selection_changed (GtkTreeSelection     *selection,
+                               GvcSoundThemeChooser *chooser)
+{
+        GList        *paths;
+        GtkTreeModel *model;
+        GtkTreePath  *path;
+
+        if (chooser->priv->treeview == NULL)
+                return;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        paths = gtk_tree_selection_get_selected_rows (selection, &model);
+        if (paths == NULL)
+                return;
+
+        path = paths->data;
+        play_preview_for_path (chooser, path);
+
+        g_list_foreach (paths, (GFunc)gtk_tree_path_free, NULL);
+        g_list_free (paths);
+}
+
+static GtkWidget *
+create_alert_treeview (GvcSoundThemeChooser *chooser)
+{
+        GtkListStore         *store;
+        GtkWidget            *treeview;
+        GtkCellRenderer      *renderer;
+        GtkTreeViewColumn    *column;
+        GtkTreeSelection     *selection;
+
+        treeview = gtk_tree_view_new ();
+
+        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
+        g_signal_connect (G_OBJECT (treeview),
+                          "row-activated",
+                          G_CALLBACK (on_treeview_row_activated),
+                          chooser);
+
+        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+        gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+        g_signal_connect (G_OBJECT (selection),
+                          "changed",
+                          G_CALLBACK (on_treeview_selection_changed),
+                          chooser);
+
+        /* Setup the tree model, 3 columns:
+         * - display name
+         * - sound id
+         * - sound type
+         */
+        store = gtk_list_store_new (ALERT_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_BOOLEAN);
+
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           ALERT_IDENTIFIER_COL, DEFAULT_ALERT_ID,
+                                           ALERT_DISPLAY_COL, _("Default"),
+                                           ALERT_SOUND_TYPE_COL, _("From theme"),
+                                           ALERT_ACTIVE_COL, TRUE,
+                                           -1);
+
+        populate_model_from_dir (chooser, GTK_TREE_MODEL (store), SOUND_SET_DIR);
+
+        gtk_tree_view_set_model (GTK_TREE_VIEW (treeview),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_toggle_new ();
+        gtk_cell_renderer_toggle_set_radio (GTK_CELL_RENDERER_TOGGLE (renderer), TRUE);
+
+        column = gtk_tree_view_column_new_with_attributes (NULL,
+                                                           renderer,
+                                                           "active", ALERT_ACTIVE_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+        g_signal_connect (renderer,
+                          "toggled",
+                          G_CALLBACK (on_alert_toggled),
+                          chooser);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Name"),
+                                                           renderer,
+                                                           "text", ALERT_DISPLAY_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Type"),
+                                                           renderer,
+                                                           "text", ALERT_SOUND_TYPE_COL,
+                                                           NULL);
+
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        return treeview;
+}
+
+static int
+get_file_type (const char *sound_name,
+               char      **linked_name)
+{
+        char *name, *filename;
+
+        *linked_name = NULL;
+
+        name = g_strdup_printf ("%s.disabled", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_REGULAR) != FALSE) {
+                g_free (filename);
+                return SOUND_TYPE_OFF;
+        }
+        g_free (filename);
+
+        /* We only check for .ogg files because those are the
+         * only ones we create */
+        name = g_strdup_printf ("%s.ogg", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_SYMLINK) != FALSE) {
+                *linked_name = g_file_read_link (filename, NULL);
+                g_free (filename);
+                return SOUND_TYPE_CUSTOM;
+        }
+        g_free (filename);
+
+        return SOUND_TYPE_BUILTIN;
+}
+
+static void
+update_alerts_from_theme_name (GvcSoundThemeChooser *chooser,
+                               const gchar          *name)
+{
+        if (strcmp (name, CUSTOM_THEME_NAME) != 0) {
+                /* reset alert to default */
+                update_alert (chooser, DEFAULT_ALERT_ID);
+        } else {
+                int   sound_type;
+                char *linkname;
+
+                linkname = NULL;
+                sound_type = get_file_type ("bell-terminal", &linkname);
+                g_debug ("Found link: %s", linkname);
+                if (sound_type == SOUND_TYPE_CUSTOM) {
+                        update_alert (chooser, linkname);
+                }
+        }
+}
+
+static void
+update_theme (GvcSoundThemeChooser *chooser)
+{
+        char        *theme_name;
+        gboolean     events_enabled;
+        gboolean     feedback_enabled;
+
+        feedback_enabled = g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY);
+        set_input_feedback_enabled (chooser, feedback_enabled);
+
+        events_enabled = g_settings_get_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY);
+        if (events_enabled) {
+                theme_name = g_settings_get_string (chooser->priv->sound_settings, SOUND_THEME_KEY);
+        } else {
+                theme_name = g_strdup (NO_SOUNDS_THEME_NAME);
+        }
+
+        gtk_widget_set_sensitive (chooser->priv->selection_box, events_enabled);
+        gtk_widget_set_sensitive (chooser->priv->click_feedback_button, events_enabled);
+
+        set_combox_for_theme_name (chooser, theme_name);
+
+        update_alerts_from_theme_name (chooser, theme_name);
+
+        g_free (theme_name);
+}
+
+static void
+gvc_sound_theme_chooser_class_init (GvcSoundThemeChooserClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_sound_theme_chooser_dispose;
+}
+
+static void
+on_click_feedback_toggled (GtkToggleButton      *button,
+                           GvcSoundThemeChooser *chooser)
+{
+        gboolean enabled;
+
+        enabled = gtk_toggle_button_get_active (button);
+
+        g_settings_set_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY, enabled);
+}
+
+static void
+on_key_changed (GSettings            *settings,
+                gchar                *key,
+                GvcSoundThemeChooser *chooser)
+{
+        if (!strcmp (key, EVENT_SOUNDS_KEY) ||
+            !strcmp (key, SOUND_THEME_KEY) ||
+            !strcmp (key, INPUT_SOUNDS_KEY))
+                update_theme (chooser);
+}
+
+static void
+setup_list_size_constraint (GtkWidget *widget,
+                            GtkWidget *to_size)
+{
+        GtkRequisition req;
+        gint           sc_height;
+        int            max_height;
+
+        /* Constrain height to be the tree height up to a max */
+        gdk_window_get_geometry (gdk_screen_get_root_window (gtk_widget_get_screen (widget)),
+                                 NULL, NULL, NULL, &sc_height);
+
+        max_height = sc_height / 4;
+
+        // XXX this doesn't work
+        gtk_widget_get_preferred_size (to_size, NULL, &req);
+
+        gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (widget),
+                                                    MIN (req.height, max_height));
+}
+
+static void
+gvc_sound_theme_chooser_init (GvcSoundThemeChooser *chooser)
+{
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *scrolled_window;
+        gchar       *str;
+
+        chooser->priv = gvc_sound_theme_chooser_get_instance_private (chooser);
+
+        chooser->priv->theme_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->theme_box, FALSE, FALSE, 0);
+
+        label = gtk_label_new_with_mnemonic (_("Sound _theme:"));
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), label, FALSE, FALSE, 0);
+        chooser->priv->combo_box = gtk_combo_box_new ();
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), chooser->priv->combo_box, FALSE, FALSE, 6);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->combo_box);
+
+        chooser->priv->sound_settings = g_settings_new (KEY_SOUNDS_SCHEMA);
+
+        g_signal_connect (G_OBJECT (chooser->priv->sound_settings),
+                          "changed",
+                          G_CALLBACK (on_key_changed),
+                          chooser);
+
+        str = g_strdup_printf ("<b>%s</b>", _("C_hoose an alert sound:"));
+        chooser->priv->selection_box = box = gtk_frame_new (str);
+        g_free (str);
+
+        label = gtk_frame_get_label_widget (GTK_FRAME (box));
+        gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
+        gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+        gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
+
+        gtk_box_pack_start (GTK_BOX (chooser), box, TRUE, TRUE, 6);
+
+        chooser->priv->treeview = create_alert_treeview (chooser);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->treeview);
+
+        scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+        gtk_widget_set_hexpand (scrolled_window, TRUE);
+        gtk_widget_set_vexpand (scrolled_window, TRUE);
+        gtk_widget_set_margin_top (scrolled_window, 6);
+
+        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+                                        GTK_POLICY_NEVER,
+                                        GTK_POLICY_AUTOMATIC);
+        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
+                                             GTK_SHADOW_IN);
+
+        gtk_container_add (GTK_CONTAINER (scrolled_window), chooser->priv->treeview);
+        gtk_container_add (GTK_CONTAINER (box), scrolled_window);
+
+        chooser->priv->click_feedback_button = gtk_check_button_new_with_mnemonic (_("Enable _window and button sounds"));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY));
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->click_feedback_button,
+                            FALSE, FALSE, 0);
+
+        g_signal_connect (G_OBJECT (chooser->priv->click_feedback_button),
+                          "toggled",
+                          G_CALLBACK (on_click_feedback_toggled),
+                          chooser);
+
+        setup_theme_selector (chooser);
+        update_theme (chooser);
+
+        setup_list_size_constraint (scrolled_window, chooser->priv->treeview);
+}
+
+static void
+gvc_sound_theme_chooser_dispose (GObject *object)
+{
+        GvcSoundThemeChooser *chooser;
+
+        chooser = GVC_SOUND_THEME_CHOOSER (object);
+
+        g_clear_object (&chooser->priv->sound_settings);
+
+        G_OBJECT_CLASS (gvc_sound_theme_chooser_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_sound_theme_chooser_new (void)
+{
+        return g_object_new (GVC_TYPE_SOUND_THEME_CHOOSER,
+                                "spacing", 6,
+                                "orientation", GTK_ORIENTATION_VERTICAL,
+                                NULL);
+}
+
+
+
+ + + diff --git a/2020-06-26-095009-5434-cppcheck@7f8975cc6d8d_master/2.html b/2020-06-26-095009-5434-cppcheck@7f8975cc6d8d_master/2.html new file mode 100644 index 0000000..bacfabb --- /dev/null +++ b/2020-06-26-095009-5434-cppcheck@7f8975cc6d8d_master/2.html @@ -0,0 +1,1110 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <canberra.h>
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-speaker-test.h"
+#include "gvc-utils.h"
+
+struct _GvcSpeakerTestPrivate
+{
+        GArray           *controls;
+        ca_context       *canberra;
+        MateMixerStream  *stream;
+};
+
+enum {
+        PROP_0,
+        PROP_STREAM,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_speaker_test_dispose    (GObject             *object);
+static void gvc_speaker_test_finalize   (GObject             *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSpeakerTest, gvc_speaker_test, GTK_TYPE_GRID)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+typedef struct {
+        MateMixerChannelPosition position;
+        guint left;
+        guint top;
+} TablePosition;
+
+static const TablePosition positions[] = {
+        /* Position, X, Y */
+        { MATE_MIXER_CHANNEL_FRONT_LEFT, 0, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_LEFT_CENTER, 1, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_CENTER, 2, 0, },
+        { MATE_MIXER_CHANNEL_MONO, 2, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT_CENTER, 3, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT, 4, 0, },
+        { MATE_MIXER_CHANNEL_SIDE_LEFT, 0, 1, },
+        { MATE_MIXER_CHANNEL_SIDE_RIGHT, 4, 1, },
+        { MATE_MIXER_CHANNEL_BACK_LEFT, 0, 2, },
+        { MATE_MIXER_CHANNEL_BACK_CENTER, 2, 2, },
+        { MATE_MIXER_CHANNEL_BACK_RIGHT, 4, 2, },
+        { MATE_MIXER_CHANNEL_LFE, 3, 2 }
+};
+
+MateMixerStream *
+gvc_speaker_test_get_stream (GvcSpeakerTest *test)
+{
+        g_return_val_if_fail (GVC_IS_SPEAKER_TEST (test), NULL);
+
+        return test->priv->stream;
+}
+
+static void
+gvc_speaker_test_set_stream (GvcSpeakerTest *test, MateMixerStream *stream)
+{
+        MateMixerStreamControl *control;
+        const gchar            *name;
+        guint                   i;
+
+        name = mate_mixer_stream_get_name (stream);
+        control = mate_mixer_stream_get_default_control (stream);
+
+        ca_context_change_device (test->priv->canberra, name);
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                gboolean has_position =
+                        mate_mixer_stream_control_has_channel_position (control, positions[i].position);
+
+                gtk_widget_set_visible (g_array_index (test->priv->controls, GtkWidget *, i),
+                                        has_position);
+        }
+
+        test->priv->stream = g_object_ref (stream);
+}
+
+static void
+gvc_speaker_test_set_property (GObject       *object,
+                               guint          prop_id,
+                               const GValue  *value,
+                               GParamSpec    *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                gvc_speaker_test_set_stream (self, g_value_get_object (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_get_property (GObject     *object,
+                               guint        prop_id,
+                               GValue      *value,
+                               GParamSpec  *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                g_value_set_object (value, self->priv->stream);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_class_init (GvcSpeakerTestClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose  = gvc_speaker_test_dispose;
+        object_class->finalize = gvc_speaker_test_finalize;
+        object_class->set_property = gvc_speaker_test_set_property;
+        object_class->get_property = gvc_speaker_test_get_property;
+
+        properties[PROP_STREAM] =
+                g_param_spec_object ("stream",
+                                     "Stream",
+                                     "MateMixer stream",
+                                     MATE_MIXER_TYPE_STREAM,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+}
+
+static const gchar *
+sound_name (MateMixerChannelPosition position)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return "audio-channel-front-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return "audio-channel-front-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return "audio-channel-front-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return "audio-channel-rear-left";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return "audio-channel-rear-right";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return "audio-channel-rear-center";
+        case MATE_MIXER_CHANNEL_LFE:
+                return "audio-channel-lfe";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return "audio-channel-side-left";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return "audio-channel-side-right";
+        default:
+                return NULL;
+        }
+}
+
+static const gchar *
+icon_name (MateMixerChannelPosition position, gboolean playing)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return playing
+                        ? "audio-speaker-left-testing"
+                        : "audio-speaker-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return playing
+                        ? "audio-speaker-right-testing"
+                        : "audio-speaker-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return playing
+                        ? "audio-speaker-center-testing"
+                        : "audio-speaker-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return playing
+                        ? "audio-speaker-left-back-testing"
+                        : "audio-speaker-left-back";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return playing
+                        ? "audio-speaker-right-back-testing"
+                        : "audio-speaker-right-back";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return playing
+                        ? "audio-speaker-center-back-testing"
+                        : "audio-speaker-center-back";
+        case MATE_MIXER_CHANNEL_LFE:
+                return playing
+                        ? "audio-subwoofer-testing"
+                        : "audio-subwoofer";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return playing
+                        ? "audio-speaker-left-side-testing"
+                        : "audio-speaker-left-side";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return playing
+                        ? "audio-speaker-right-side-testing"
+                        : "audio-speaker-right-side";
+        default:
+                return NULL;
+        }
+}
+
+static void
+update_button (GtkWidget *control)
+{
+        GtkWidget *button;
+        GtkWidget *image;
+        gboolean   playing;
+        MateMixerChannelPosition position;
+
+        button = g_object_get_data (G_OBJECT (control), "button");
+        image  = g_object_get_data (G_OBJECT (control), "image");
+
+        position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+        playing  = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        gtk_button_set_label (GTK_BUTTON (button), playing ? _("Stop") : _("Test"));
+
+        gtk_image_set_from_icon_name (GTK_IMAGE (image),
+                                      icon_name (position, playing),
+                                      GTK_ICON_SIZE_DIALOG);
+}
+
+static gboolean
+idle_cb (GtkWidget *control)
+{
+        if (control != NULL) {
+                /* This is called in the background thread, hence forward to main thread
+                 * via idle callback */
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+
+                update_button (control);
+        }
+        return FALSE;
+}
+
+static void
+finish_cb (ca_context *c, uint32_t id, int error_code, void *userdata)
+{
+        GtkWidget *control = (GtkWidget *) userdata;
+
+        if (error_code == CA_ERROR_DESTROYED || control == NULL)
+                return;
+
+        g_idle_add ((GSourceFunc) idle_cb, control);
+}
+
+static void
+on_test_button_clicked (GtkButton *button, GtkWidget *control)
+{
+        gboolean    playing;
+        ca_context *canberra;
+
+        canberra = g_object_get_data (G_OBJECT (control), "canberra");
+
+        ca_context_cancel (canberra, 1);
+
+        playing = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        if (playing) {
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        } else {
+                MateMixerChannelPosition position;
+                const gchar *name;
+                ca_proplist *proplist;
+
+                position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+
+                ca_proplist_create (&proplist);
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_ROLE, "test");
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_NAME,
+                                  gvc_channel_position_to_pretty_string (position));
+                ca_proplist_sets (proplist,
+                                  CA_PROP_CANBERRA_FORCE_CHANNEL,
+                                  gvc_channel_position_to_pulse_string (position));
+
+                ca_proplist_sets (proplist, CA_PROP_CANBERRA_ENABLE, "1");
+
+                name = sound_name (position);
+                if (name != NULL) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, name);
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, "audio-test-signal");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets(proplist, CA_PROP_EVENT_ID, "bell-window-system");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (playing));
+        }
+
+        update_button (control);
+}
+
+static GtkWidget *
+create_control (ca_context *canberra, MateMixerChannelPosition position)
+{
+        GtkWidget   *control;
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *image;
+        GtkWidget   *test_button;
+        const gchar *name;
+
+        control = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+        box     = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        g_object_set_data (G_OBJECT (control), "position", GINT_TO_POINTER (position));
+        g_object_set_data (G_OBJECT (control), "canberra", canberra);
+
+        name = icon_name (position, FALSE);
+        if (name == NULL)
+                name = "audio-volume-medium";
+
+        image = gtk_image_new_from_icon_name (name, GTK_ICON_SIZE_DIALOG);
+        g_object_set_data (G_OBJECT (control), "image", image);
+        gtk_box_pack_start (GTK_BOX (control), image, FALSE, FALSE, 0);
+
+        label = gtk_label_new (gvc_channel_position_to_pretty_string (position));
+        gtk_box_pack_start (GTK_BOX (control), label, FALSE, FALSE, 0);
+
+        test_button = gtk_button_new_with_label (_("Test"));
+        g_signal_connect (G_OBJECT (test_button),
+                          "clicked",
+                          G_CALLBACK (on_test_button_clicked),
+                          control);
+
+        g_object_set_data (G_OBJECT (control), "button", test_button);
+
+        gtk_box_pack_start (GTK_BOX (box), test_button, TRUE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (control), box, FALSE, FALSE, 0);
+
+        gtk_widget_show_all (control);
+
+        return control;
+}
+
+static void
+create_controls (GvcSpeakerTest *test)
+{
+        guint i;
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                GtkWidget *control = create_control (test->priv->canberra, positions[i].position);
+
+                gtk_grid_attach (GTK_GRID (test),
+                                 control,
+                                 positions[i].left,
+                                 positions[i].top,
+                                 1, 1);
+                g_array_insert_val (test->priv->controls, i, control);
+        }
+}
+
+static void
+gvc_speaker_test_init (GvcSpeakerTest *test)
+{
+        GtkWidget *face;
+
+        test->priv = gvc_speaker_test_get_instance_private (test);
+
+        gtk_container_set_border_width (GTK_CONTAINER (test), 12);
+
+        face = gtk_image_new_from_icon_name ("face-smile", GTK_ICON_SIZE_DIALOG);
+
+        gtk_grid_attach (GTK_GRID (test),
+                         face,
+                         1, 1,
+                         3, 1);
+
+
+        gtk_grid_set_baseline_row (GTK_GRID (test), 1);
+        gtk_widget_show (face);
+
+        ca_context_create (&test->priv->canberra);
+
+        /* The test sounds are played for a single channel, set up using the
+         * FORCE_CHANNEL property of libcanberra; this property is only supported
+         * in the PulseAudio backend, so avoid other backends completely */
+        ca_context_set_driver (test->priv->canberra, "pulse");
+
+        ca_context_change_props (test->priv->canberra,
+                                 CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+                                 CA_PROP_APPLICATION_NAME, _("Volume Control"),
+                                 CA_PROP_APPLICATION_VERSION, VERSION,
+                                 CA_PROP_APPLICATION_ICON_NAME, "multimedia-volume-control",
+                                 NULL);
+
+        test->priv->controls = g_array_new (FALSE, FALSE, sizeof (GtkWidget *));
+
+        create_controls (test);
+}
+
+static void
+gvc_speaker_test_dispose (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        g_clear_object (&test->priv->stream);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->dispose (object);
+}
+
+static void
+gvc_speaker_test_finalize (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        ca_context_destroy (test->priv->canberra);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->finalize (object);
+}
+
+GtkWidget *
+gvc_speaker_test_new (MateMixerStream *stream)
+{
+        GObject *test;
+
+        g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL);
+
+        test = g_object_new (GVC_TYPE_SPEAKER_TEST,
+                             "row-spacing", 6,
+                             "column-spacing", 6,
+                             "row-homogeneous", TRUE,
+                             "column-homogeneous", TRUE,
+                             "stream", stream,
+                             NULL);
+
+        return GTK_WIDGET (test);
+}
+
+
+
+ + + diff --git a/2020-06-26-095009-5434-cppcheck@7f8975cc6d8d_master/index.html b/2020-06-26-095009-5434-cppcheck@7f8975cc6d8d_master/index.html new file mode 100644 index 0000000..59baeb0 --- /dev/null +++ b/2020-06-26-095009-5434-cppcheck@7f8975cc6d8d_master/index.html @@ -0,0 +1,108 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
mate-volume-control/gvc-combo-box.c
70unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
mate-volume-control/gvc-sound-theme-chooser.c
735ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
746ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
758ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
mate-volume-control/gvc-speaker-test.c
53unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+ + + diff --git a/2020-06-26-095009-5434-cppcheck@7f8975cc6d8d_master/stats.html b/2020-06-26-095009-5434-cppcheck@7f8975cc6d8d_master/stats.html new file mode 100644 index 0000000..3fb6add --- /dev/null +++ b/2020-06-26-095009-5434-cppcheck@7f8975cc6d8d_master/stats.html @@ -0,0 +1,93 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+

Top 10 files for error severity, total findings: 2
+   1  mate-volume-control/gvc-speaker-test.c
+   1  mate-volume-control/gvc-combo-box.c
+

+

Top 10 files for information severity, total findings: 3
+   3  mate-volume-control/gvc-sound-theme-chooser.c
+

+ +
+ + + diff --git a/2020-06-26-095009-5434-cppcheck@7f8975cc6d8d_master/style.css b/2020-06-26-095009-5434-cppcheck@7f8975cc6d8d_master/style.css new file mode 100644 index 0000000..c39571c --- /dev/null +++ b/2020-06-26-095009-5434-cppcheck@7f8975cc6d8d_master/style.css @@ -0,0 +1,149 @@ + +body { + font: 13px Arial, Verdana, Sans-Serif; + margin: 0; + width: auto; +} + +h1 { + margin: 10px; +} + +#footer > p { + margin: 4px; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + border: 1px dotted black; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #B6B6B4; +} + +.inconclusive2 { + background-color: #B6B6B4; + border: 1px dotted black; + display: inline-block; + margin-left: 4px; +} + +div.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +div.verbose div.content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid black; + background-color: #FFFFCC; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +#header { + border-bottom: thin solid #aaa; +} + +#menu { + float: left; + margin-top: 5px; + text-align: left; + width: 150px; + /*height: 75%;*/ + position: fixed; + overflow: auto; + z-index: 1; +} + +#menu_index { + float: left; + margin-top: 5px; + padding-left: 5px; + text-align: left; + width: 300px; + /*height: 75%;*/ + position: fixed; + overflow: auto; + z-index: 1; +} + +#menu > a { + display: block; + margin-left: 10px; + font: 12px; + z-index: 1; +} + +#filename { + margin-left: 10px; + font: 12px; + z-index: 1; +} + +.highlighttable { + background-color:white; + z-index: 10; + position: relative; + margin: -10 px; +} + +#content { + background-color: white; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + float: left; + margin: 5px; + margin-left: 10px; + padding: 0 10px 10px 10px; + width: 80%; + padding-left: 150px; +} + +#content_index { + background-color: white; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + float: left; + margin: 5px; + margin-left: 10px; + padding: 0 10px 10px 10px; + width: 80%; + padding-left: 300px; +} + +.linenos { + border-right: thin solid #aaa; + color: lightgray; + padding-right: 6px; +} + +#footer { + border-top: thin solid #aaa; + clear: both; + font-size: 90%; + margin-top: 5px; +} + +#footer ul { + list-style-type: none; + padding-left: 0; +} diff --git a/2020-06-29-181100-6971-cppcheck@ea7fcb89ced5_on_notebook_scroll_event/0.html b/2020-06-29-181100-6971-cppcheck@ea7fcb89ced5_on_notebook_scroll_event/0.html new file mode 100644 index 0000000..e262ed0 --- /dev/null +++ b/2020-06-29-181100-6971-cppcheck@ea7fcb89ced5_on_notebook_scroll_event/0.html @@ -0,0 +1,1038 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-combo-box.h"
+
+struct _GvcComboBoxPrivate
+{
+        GtkWidget       *drop_box;
+        GtkWidget       *start_box;
+        GtkWidget       *end_box;
+        GtkWidget       *label;
+        GtkWidget       *button;
+        GtkTreeModel    *model;
+        GtkWidget       *combobox;
+        MateMixerSwitch *swtch;
+};
+
+enum {
+        COL_NAME,
+        COL_HUMAN_NAME,
+        NUM_COLS
+};
+
+enum {
+        CHANGING,
+        BUTTON_CLICKED,
+        LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+enum {
+        PROP_0,
+        PROP_SWITCH,
+        PROP_LABEL,
+        PROP_SHOW_BUTTON,
+        PROP_BUTTON_LABEL,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_combo_box_dispose    (GObject          *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcComboBox, gvc_combo_box, GTK_TYPE_BOX)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+MateMixerSwitch *
+gvc_combo_box_get_switch (GvcComboBox *combobox)
+{
+        g_return_val_if_fail (GVC_IS_COMBO_BOX (combobox), NULL);
+
+        return combobox->priv->swtch;
+}
+
+void
+gvc_combo_box_set_size_group (GvcComboBox  *combobox,
+                              GtkSizeGroup *group,
+                              gboolean      symmetric)
+{
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (GTK_IS_SIZE_GROUP (group));
+
+        if (group != NULL) {
+                gtk_size_group_add_widget (group, combobox->priv->start_box);
+                if (symmetric == TRUE)
+                        gtk_size_group_add_widget (group, combobox->priv->end_box);
+        }
+        gtk_widget_queue_draw (GTK_WIDGET (combobox));
+}
+
+static void
+on_switch_active_option_notify (MateMixerSwitch *swtch,
+                                GParamSpec      *pspec,
+                                GvcComboBox     *combobox)
+{
+        GtkTreeIter            iter;
+        MateMixerSwitchOption *active;
+        gboolean               cont;
+        const gchar           *name;
+
+        active = mate_mixer_switch_get_active_option (swtch);
+        if (G_UNLIKELY (active == NULL)) {
+                g_warn_if_reached ();
+                return;
+        }
+
+        /* Select the newly activated switch option in the combo box */
+        name = mate_mixer_switch_option_get_name (active);
+        cont = gtk_tree_model_get_iter_first (combobox->priv->model, &iter);
+        while (cont == TRUE) {
+                gchar *current;
+
+                gtk_tree_model_get (combobox->priv->model, &iter,
+                                    COL_NAME, &current,
+                                    -1);
+                if (g_strcmp0 (name, current) == 0) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox), &iter);
+                        g_free (current);
+                        return;
+                }
+                g_free (current);
+
+                cont = gtk_tree_model_iter_next (combobox->priv->model, &iter);
+        }
+        g_warning ("Could not find switch option '%s' in combo box", name);
+}
+
+static void
+gvc_combo_box_set_switch (GvcComboBox *combobox, MateMixerSwitch *swtch)
+{
+        MateMixerSwitchOption *active;
+        const GList           *options;
+
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (MATE_MIXER_IS_SWITCH (swtch));
+
+        combobox->priv->swtch = g_object_ref (swtch);
+
+        active  = mate_mixer_switch_get_active_option (swtch);
+        options = mate_mixer_switch_list_options (swtch);
+        while (options != NULL) {
+                GtkTreeIter            iter;
+                MateMixerSwitchOption *option = MATE_MIXER_SWITCH_OPTION (options->data);
+
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (combobox->priv->model),
+                                                   &iter,
+                                                   G_MAXINT,
+                                                   COL_NAME,
+                                                   mate_mixer_switch_option_get_name (option),
+                                                   COL_HUMAN_NAME,
+                                                   mate_mixer_switch_option_get_label (option),
+                                                   -1);
+
+                /* Select the currently active option of the switch */
+                if (option == active) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox),
+                                                       &iter);
+                }
+                options = options->next;
+        }
+
+        g_signal_connect (G_OBJECT (swtch),
+                          "notify::active-option",
+                          G_CALLBACK (on_switch_active_option_notify),
+                          combobox);
+}
+
+static void
+gvc_combo_box_set_property (GObject       *object,
+                            guint          prop_id,
+                            const GValue  *value,
+                            GParamSpec    *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                gvc_combo_box_set_switch (self, g_value_get_object (value));
+                break;
+        case PROP_LABEL:
+                gtk_label_set_text_with_mnemonic (GTK_LABEL (self->priv->label), g_value_get_string (value));
+                break;
+        case PROP_BUTTON_LABEL:
+                gtk_button_set_label (GTK_BUTTON (self->priv->button), g_value_get_string (value));
+                break;
+        case PROP_SHOW_BUTTON:
+                gtk_widget_set_visible (self->priv->button, g_value_get_boolean (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_get_property (GObject     *object,
+                            guint        prop_id,
+                            GValue      *value,
+                            GParamSpec  *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                g_value_set_object (value, self->priv->swtch);
+                break;
+        case PROP_LABEL:
+                g_value_set_string (value, gtk_label_get_text (GTK_LABEL (self->priv->label)));
+                break;
+        case PROP_BUTTON_LABEL:
+                g_value_set_string (value, gtk_button_get_label (GTK_BUTTON (self->priv->button)));
+                break;
+        case PROP_SHOW_BUTTON:
+                g_value_set_boolean (value, gtk_widget_get_visible (self->priv->button));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_class_init (GvcComboBoxClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_combo_box_dispose;
+        object_class->set_property = gvc_combo_box_set_property;
+        object_class->get_property = gvc_combo_box_get_property;
+
+        properties[PROP_SWITCH] =
+                g_param_spec_object ("switch",
+                                     "switch",
+                                     "The MateMixerSwitch",
+                                     MATE_MIXER_TYPE_SWITCH,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_LABEL] =
+                g_param_spec_string ("label",
+                                     "label",
+                                     "The combo box label",
+                                     _("_Profile:"),
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_SHOW_BUTTON] =
+                g_param_spec_boolean ("show-button",
+                                      "show-button",
+                                      "Whether to show the button",
+                                      FALSE,
+                                      G_PARAM_READWRITE |
+                                      G_PARAM_CONSTRUCT |
+                                      G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_BUTTON_LABEL] =
+                g_param_spec_string ("button-label",
+                                     "button-label",
+                                     "The button's label",
+                                     "",
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+
+        signals[CHANGING] =
+                g_signal_new ("changing",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, changing),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__OBJECT,
+                              G_TYPE_NONE,
+                              1,
+                              MATE_MIXER_TYPE_SWITCH_OPTION);
+
+        signals[BUTTON_CLICKED] =
+                g_signal_new ("button-clicked",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, button_clicked),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
+}
+
+static void
+on_combo_box_changed (GtkComboBox *widget, GvcComboBox *combobox)
+{
+        GtkTreeIter            iter;
+        gchar                 *name;
+        MateMixerSwitchOption *option;
+
+        if (G_UNLIKELY (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter) == FALSE))
+                return;
+
+        gtk_tree_model_get (combobox->priv->model, &iter,
+                            COL_NAME, &name,
+                            -1);
+
+        option = mate_mixer_switch_get_option (combobox->priv->swtch, name);
+        if (G_UNLIKELY (option == NULL)) {
+                g_warn_if_reached ();
+                g_free (name);
+                return;
+        }
+
+        /* Inform that we are about to change the active option of the switch */
+        g_signal_emit (combobox, signals[CHANGING], 0, option);
+
+        mate_mixer_switch_set_active_option (combobox->priv->swtch, option);
+        g_free (name);
+}
+
+static void
+on_combo_box_button_clicked (GtkButton *button, GvcComboBox *combobox)
+{
+        /* The meaning of the button is defined by the owner, so only notify
+         * when it is clicked on */
+        g_signal_emit (combobox, signals[BUTTON_CLICKED], 0);
+}
+
+static void
+gvc_combo_box_init (GvcComboBox *combobox)
+{
+        GtkWidget       *frame;
+        GtkCellRenderer *renderer;
+
+        frame = gtk_frame_new (NULL);
+        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
+
+        combobox->priv = gvc_combo_box_get_instance_private (combobox);
+
+        combobox->priv->model = GTK_TREE_MODEL (gtk_list_store_new (NUM_COLS,
+                                                                    G_TYPE_STRING,
+                                                                    G_TYPE_STRING));
+
+        combobox->priv->combobox = gtk_combo_box_new_with_model (combobox->priv->model);
+
+        combobox->priv->label = gtk_label_new (NULL);
+
+        gtk_label_set_xalign (GTK_LABEL (combobox->priv->label), 0.0);
+        gtk_label_set_yalign (GTK_LABEL (combobox->priv->label), 0.5);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (combobox->priv->label),
+                                       combobox->priv->combobox);
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                    renderer,
+                                    FALSE);
+        gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                       renderer,
+                                       "text",
+                                       COL_HUMAN_NAME);
+
+        combobox->priv->drop_box  = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->start_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->end_box   = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+        /* Make sure the combo box does not get too long on long profile names */
+        g_object_set (G_OBJECT (renderer),
+                      "ellipsize",
+                      PANGO_ELLIPSIZE_END,
+                      NULL);
+
+        gtk_combo_box_set_popup_fixed_width (GTK_COMBO_BOX (combobox->priv->combobox), FALSE);
+
+        gtk_box_pack_start (GTK_BOX (combobox),
+                            frame,
+                            TRUE, TRUE, 0);
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->start_box,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->start_box),
+                            combobox->priv->label,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->combobox,
+                            TRUE, TRUE, 0);
+
+        combobox->priv->button = gtk_button_new_with_label ("");
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->button,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->end_box,
+                            FALSE, FALSE, 0);
+
+        gtk_container_add (GTK_CONTAINER (frame), combobox->priv->drop_box);
+
+        g_signal_connect (G_OBJECT (combobox->priv->combobox),
+                          "changed",
+                          G_CALLBACK (on_combo_box_changed),
+                          combobox);
+        g_signal_connect (G_OBJECT (combobox->priv->button),
+                          "clicked",
+                          G_CALLBACK (on_combo_box_button_clicked),
+                          combobox);
+
+        gtk_widget_set_no_show_all (combobox->priv->button, TRUE);
+        gtk_widget_show_all (frame);
+}
+
+static void
+gvc_combo_box_dispose (GObject *object)
+{
+        GvcComboBox *combobox;
+
+        combobox = GVC_COMBO_BOX (object);
+
+        if (G_LIKELY (combobox->priv->swtch != NULL)) {
+                g_signal_handlers_disconnect_by_func (G_OBJECT (combobox->priv->swtch),
+                                                      G_CALLBACK (on_switch_active_option_notify),
+                                                      combobox);
+                g_clear_object (&combobox->priv->swtch);
+        }
+
+        g_clear_object (&combobox->priv->model);
+
+        G_OBJECT_CLASS (gvc_combo_box_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_combo_box_new (MateMixerSwitch *swtch, const gchar *label)
+{
+        return g_object_new (GVC_TYPE_COMBO_BOX,
+                             "switch", swtch,
+                             "label", label,
+                             "orientation", GTK_ORIENTATION_HORIZONTAL,
+                             NULL);
+}
+
+
+
+ + + diff --git a/2020-06-29-181100-6971-cppcheck@ea7fcb89ced5_on_notebook_scroll_event/1.html b/2020-06-29-181100-6971-cppcheck@ea7fcb89ced5_on_notebook_scroll_event/1.html new file mode 100644 index 0000000..67179f2 --- /dev/null +++ b/2020-06-29-181100-6971-cppcheck@ea7fcb89ced5_on_notebook_scroll_event/1.html @@ -0,0 +1,2368 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
+ * Copyright (C) 2008 William Jon McCann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <utime.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+#include <canberra-gtk.h>
+#include <libxml/tree.h>
+
+#include "gvc-sound-theme-chooser.h"
+#include "sound-theme-file-utils.h"
+
+struct GvcSoundThemeChooserPrivate
+{
+        GtkWidget *combo_box;
+        GtkWidget *treeview;
+        GtkWidget *theme_box;
+        GtkWidget *selection_box;
+        GtkWidget *click_feedback_button;
+        GSettings *sound_settings;
+};
+
+static void     gvc_sound_theme_chooser_dispose   (GObject            *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSoundThemeChooser, gvc_sound_theme_chooser, GTK_TYPE_BOX)
+
+#define KEY_SOUNDS_SCHEMA          "org.mate.sound"
+#define EVENT_SOUNDS_KEY           "event-sounds"
+#define INPUT_SOUNDS_KEY           "input-feedback-sounds"
+#define SOUND_THEME_KEY            "theme-name"
+
+#define DEFAULT_ALERT_ID        "__default"
+#define CUSTOM_THEME_NAME       "__custom"
+#define NO_SOUNDS_THEME_NAME    "__no_sounds"
+
+enum {
+        THEME_DISPLAY_COL,
+        THEME_IDENTIFIER_COL,
+        THEME_PARENT_ID_COL,
+        THEME_NUM_COLS
+};
+
+enum {
+        ALERT_DISPLAY_COL,
+        ALERT_IDENTIFIER_COL,
+        ALERT_SOUND_TYPE_COL,
+        ALERT_ACTIVE_COL,
+        ALERT_NUM_COLS
+};
+
+enum {
+        SOUND_TYPE_UNSET,
+        SOUND_TYPE_OFF,
+        SOUND_TYPE_DEFAULT_FROM_THEME,
+        SOUND_TYPE_BUILTIN,
+        SOUND_TYPE_CUSTOM
+};
+
+static void
+on_combobox_changed (GtkComboBox          *widget,
+                     GvcSoundThemeChooser *chooser)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        char         *theme_name;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &theme_name, -1);
+
+        g_assert (theme_name != NULL);
+
+        /* It is necessary to update the theme name before any other setting as
+         * the "changed" notification will reload the contents of the widget */
+        g_settings_set_string (chooser->priv->sound_settings, SOUND_THEME_KEY, theme_name);
+
+        /* special case for no sounds */
+        if (strcmp (theme_name, NO_SOUNDS_THEME_NAME) == 0) {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, FALSE);
+                return;
+        } else {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, TRUE);
+        }
+
+        g_free (theme_name);
+
+        /* FIXME: reset alert model */
+}
+
+static char *
+load_index_theme_name (const char *index,
+                       char      **parent)
+{
+        GKeyFile *file;
+        char *indexname = NULL;
+        gboolean hidden;
+
+        file = g_key_file_new ();
+        if (g_key_file_load_from_file (file, index, G_KEY_FILE_KEEP_TRANSLATIONS, NULL) == FALSE) {
+                g_key_file_free (file);
+                return NULL;
+        }
+        /* Don't add hidden themes to the list */
+        hidden = g_key_file_get_boolean (file, "Sound Theme", "Hidden", NULL);
+        if (!hidden) {
+                indexname = g_key_file_get_locale_string (file,
+                                                          "Sound Theme",
+                                                          "Name",
+                                                          NULL,
+                                                          NULL);
+
+                /* Save the parent theme, if there's one */
+                if (parent != NULL) {
+                        *parent = g_key_file_get_string (file,
+                                                         "Sound Theme",
+                                                         "Inherits",
+                                                         NULL);
+                }
+        }
+
+        g_key_file_free (file);
+        return indexname;
+}
+
+static void
+sound_theme_in_dir (GHashTable *hash,
+                    const char *dir)
+{
+        GDir *d;
+        const char *name;
+
+        d = g_dir_open (dir, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *dirname, *index, *indexname;
+
+                /* Look for directories */
+                dirname = g_build_filename (dir, name, NULL);
+                if (g_file_test (dirname, G_FILE_TEST_IS_DIR) == FALSE) {
+                        g_free (dirname);
+                        continue;
+                }
+
+                /* Look for index files */
+                index = g_build_filename (dirname, "index.theme", NULL);
+                g_free (dirname);
+
+                /* Check the name of the theme in the index.theme file */
+                indexname = load_index_theme_name (index, NULL);
+                g_free (index);
+                if (indexname == NULL) {
+                        continue;
+                }
+
+                g_hash_table_insert (hash, g_strdup (name), indexname);
+        }
+
+        g_dir_close (d);
+}
+
+static void
+add_theme_to_store (const char   *key,
+                    const char   *value,
+                    GtkListStore *store)
+{
+        char *parent;
+
+        parent = NULL;
+
+        /* Get the parent, if we're checking the custom theme */
+        if (strcmp (key, CUSTOM_THEME_NAME) == 0) {
+                char *name, *path;
+
+                path = custom_theme_dir_path ("index.theme");
+                name = load_index_theme_name (path, &parent);
+                g_free (name);
+                g_free (path);
+        }
+        gtk_list_store_insert_with_values (store, NULL, G_MAXINT,
+                                           THEME_DISPLAY_COL, value,
+                                           THEME_IDENTIFIER_COL, key,
+                                           THEME_PARENT_ID_COL, parent,
+                                           -1);
+        g_free (parent);
+}
+
+static void
+set_combox_for_theme_name (GvcSoundThemeChooser *chooser,
+                           const char           *name)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        gboolean      found;
+
+        /* If the name is empty, use "freedesktop" */
+        if (name == NULL || *name == '\0') {
+                name = "freedesktop";
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+        if (gtk_tree_model_get_iter_first (model, &iter) == FALSE) {
+                return;
+        }
+
+        do {
+                char *value;
+
+                gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &value, -1);
+                found = (value != NULL && strcmp (value, name) == 0);
+                g_free (value);
+
+        } while (!found && gtk_tree_model_iter_next (model, &iter));
+
+        /* When we can't find the theme we need to set, try to set the default
+         * one "freedesktop" */
+        if (found) {
+                gtk_combo_box_set_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter);
+        } else if (strcmp (name, "freedesktop") != 0) {
+                g_debug ("not found, falling back to fdo");
+                set_combox_for_theme_name (chooser, "freedesktop");
+        }
+}
+
+static void
+set_input_feedback_enabled (GvcSoundThemeChooser *chooser,
+                            gboolean              enabled)
+{
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      enabled);
+}
+
+static void
+setup_theme_selector (GvcSoundThemeChooser *chooser)
+{
+        GHashTable           *hash;
+        GtkListStore         *store;
+        GtkCellRenderer      *renderer;
+        const char * const   *data_dirs;
+        const char           *data_dir;
+        char                 *dir;
+        guint                 i;
+
+        /* Add the theme names and their display name to a hash table,
+         * makes it easy to avoid duplicate themes */
+        hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+        data_dirs = g_get_system_data_dirs ();
+        for (i = 0; data_dirs[i] != NULL; i++) {
+                dir = g_build_filename (data_dirs[i], "sounds", NULL);
+                sound_theme_in_dir (hash, dir);
+                g_free (dir);
+        }
+
+        data_dir = g_get_user_data_dir ();
+        dir = g_build_filename (data_dir, "sounds", NULL);
+        sound_theme_in_dir (hash, dir);
+        g_free (dir);
+
+        /* If there isn't at least one theme, make everything
+         * insensitive, LAME! */
+        if (g_hash_table_size (hash) == 0) {
+                gtk_widget_set_sensitive (GTK_WIDGET (chooser), FALSE);
+                g_warning ("Bad setup, install the freedesktop sound theme");
+                g_hash_table_destroy (hash);
+                return;
+        }
+
+        /* Setup the tree model, 3 columns:
+         * - internal theme name/directory
+         * - display theme name
+         * - the internal id for the parent theme, used for the custom theme */
+        store = gtk_list_store_new (THEME_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING);
+
+        /* Add the themes to a combobox */
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           THEME_DISPLAY_COL, _("No sounds"),
+                                           THEME_IDENTIFIER_COL, "__no_sounds",
+                                           THEME_PARENT_ID_COL, NULL,
+                                           -1);
+        g_hash_table_foreach (hash, (GHFunc) add_theme_to_store, store);
+        g_hash_table_destroy (hash);
+
+        /* Set the display */
+        gtk_combo_box_set_model (GTK_COMBO_BOX (chooser->priv->combo_box),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                    renderer,
+                                    TRUE);
+        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                        renderer,
+                                        "text", THEME_DISPLAY_COL,
+                                        NULL);
+
+        g_signal_connect (G_OBJECT (chooser->priv->combo_box),
+                          "changed",
+                          G_CALLBACK (on_combobox_changed),
+                          chooser);
+}
+
+#define GVC_SOUND_SOUND    (xmlChar *) "sound"
+#define GVC_SOUND_NAME     (xmlChar *) "name"
+#define GVC_SOUND_FILENAME (xmlChar *) "filename"
+
+/* Adapted from yelp-toc-pager.c */
+static xmlChar *
+xml_get_and_trim_names (xmlNodePtr node)
+{
+        xmlNodePtr cur;
+        xmlChar *keep_lang = NULL;
+        xmlChar *value;
+        int j, keep_pri = INT_MAX;
+
+        const gchar * const * langs = g_get_language_names ();
+
+        value = NULL;
+
+        for (cur = node->children; cur; cur = cur->next) {
+                if (! xmlStrcmp (cur->name, GVC_SOUND_NAME)) {
+                        xmlChar *cur_lang = NULL;
+                        int cur_pri = INT_MAX;
+
+                        cur_lang = xmlNodeGetLang (cur);
+
+                        if (cur_lang) {
+                                for (j = 0; langs[j]; j++) {
+                                        if (g_str_equal (cur_lang, langs[j])) {
+                                                cur_pri = j;
+                                                break;
+                                        }
+                                }
+                        } else {
+                                cur_pri = INT_MAX - 1;
+                        }
+
+                        if (cur_pri <= keep_pri) {
+                                if (keep_lang)
+                                        xmlFree (keep_lang);
+                                if (value)
+                                        xmlFree (value);
+
+                                value = xmlNodeGetContent (cur);
+
+                                keep_lang = cur_lang;
+                                keep_pri = cur_pri;
+                        } else {
+                                if (cur_lang)
+                                        xmlFree (cur_lang);
+                        }
+                }
+        }
+
+        /* Delete all GVC_SOUND_NAME nodes */
+        cur = node->children;
+        while (cur) {
+                xmlNodePtr this = cur;
+                cur = cur->next;
+                if (! xmlStrcmp (this->name, GVC_SOUND_NAME)) {
+                        xmlUnlinkNode (this);
+                        xmlFreeNode (this);
+                }
+        }
+
+        return value;
+}
+
+static void
+populate_model_from_node (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          xmlNodePtr            node)
+{
+        xmlNodePtr child;
+        xmlChar   *filename;
+        xmlChar   *name;
+
+        filename = NULL;
+        name = xml_get_and_trim_names (node);
+        for (child = node->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+
+                if (xmlStrcmp (child->name, GVC_SOUND_FILENAME) == 0) {
+                        filename = xmlNodeGetContent (child);
+                } else if (xmlStrcmp (child->name, GVC_SOUND_NAME) == 0) {
+                        /* EH? should have been trimmed */
+                }
+        }
+
+        if (filename != NULL && name != NULL) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   ALERT_IDENTIFIER_COL, filename,
+                                                   ALERT_DISPLAY_COL, name,
+                                                   ALERT_SOUND_TYPE_COL, _("Built-in"),
+                                                   ALERT_ACTIVE_COL, FALSE,
+                                                   -1);
+        }
+
+        xmlFree (filename);
+        xmlFree (name);
+}
+
+static void
+populate_model_from_file (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          const char           *filename)
+{
+        xmlDocPtr  doc;
+        xmlNodePtr root;
+        xmlNodePtr child;
+        gboolean   exists;
+
+        exists = g_file_test (filename, G_FILE_TEST_EXISTS);
+        if (! exists) {
+                return;
+        }
+
+        doc = xmlParseFile (filename);
+        if (doc == NULL) {
+                return;
+        }
+
+        root = xmlDocGetRootElement (doc);
+
+        for (child = root->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+                if (xmlStrcmp (child->name, GVC_SOUND_SOUND) != 0) {
+                        continue;
+                }
+
+                populate_model_from_node (chooser, model, child);
+        }
+
+        xmlFreeDoc (doc);
+}
+
+static void
+populate_model_from_dir (GvcSoundThemeChooser *chooser,
+                         GtkTreeModel         *model,
+                         const char           *dirname)
+{
+        GDir       *d;
+        const char *name;
+
+        d = g_dir_open (dirname, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *path;
+
+                if (! g_str_has_suffix (name, ".xml")) {
+                        continue;
+                }
+
+                path = g_build_filename (dirname, name, NULL);
+                populate_model_from_file (chooser, model, path);
+                g_free (path);
+        }
+
+        g_dir_close (d);
+}
+
+static gboolean
+save_alert_sounds (GvcSoundThemeChooser  *chooser,
+                   const char            *id)
+{
+        const char *sounds[3] = { "bell-terminal", "bell-window-system", NULL };
+        char *path;
+
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+        } else {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+                add_custom_file (sounds, id);
+        }
+
+        /* And poke the directory so the theme gets updated */
+        path = custom_theme_dir_path (NULL);
+        if (utime (path, NULL) != 0) {
+                g_warning ("Failed to update mtime for directory '%s': %s",
+                           path, g_strerror (errno));
+        }
+        g_free (path);
+
+        return FALSE;
+}
+
+
+static void
+update_alert_model (GvcSoundThemeChooser  *chooser,
+                    const char            *id)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        gtk_tree_model_get_iter_first (model, &iter);
+        do {
+                gboolean toggled;
+                char    *this_id;
+
+                gtk_tree_model_get (model, &iter,
+                                    ALERT_IDENTIFIER_COL, &this_id,
+                                    -1);
+
+                if (strcmp (this_id, id) == 0) {
+                        toggled = TRUE;
+                } else {
+                        toggled = FALSE;
+                }
+                g_free (this_id);
+
+                gtk_list_store_set (GTK_LIST_STORE (model),
+                                    &iter,
+                                    ALERT_ACTIVE_COL, toggled,
+                                    -1);
+        } while (gtk_tree_model_iter_next (model, &iter));
+}
+
+static void
+update_alert (GvcSoundThemeChooser *chooser,
+              const char           *alert_id)
+{
+        GtkTreeModel *theme_model;
+        GtkTreeIter   iter;
+        char         *theme;
+        char         *parent;
+        gboolean      is_custom;
+        gboolean      is_default;
+        gboolean      add_custom;
+        gboolean      remove_custom;
+
+        theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        /* Get the current theme's name, and set the parent */
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        gtk_tree_model_get (theme_model, &iter,
+                            THEME_IDENTIFIER_COL, &theme,
+                            THEME_IDENTIFIER_COL, &parent,
+                            -1);
+        is_custom = strcmp (theme, CUSTOM_THEME_NAME) == 0;
+        is_default = strcmp (alert_id, DEFAULT_ALERT_ID) == 0;
+
+        /* So a few possibilities:
+         * 1. Named theme, default alert selected: noop
+         * 2. Named theme, alternate alert selected: create new custom with sound
+         * 3. Custom theme, default alert selected: remove sound and possibly custom
+         * 4. Custom theme, alternate alert selected: update custom sound
+         */
+        add_custom = FALSE;
+        remove_custom = FALSE;
+        if (! is_custom && is_default) {
+                /* remove custom just in case */
+                remove_custom = TRUE;
+        } else if (! is_custom && ! is_default) {
+                create_custom_theme (parent);
+                save_alert_sounds (chooser, alert_id);
+                add_custom = TRUE;
+        } else if (is_custom && is_default) {
+                save_alert_sounds (chooser, alert_id);
+                /* after removing files check if it is empty */
+                if (custom_theme_dir_is_empty ()) {
+                        remove_custom = TRUE;
+                }
+        } else if (is_custom && ! is_default) {
+                save_alert_sounds (chooser, alert_id);
+        }
+
+        if (add_custom) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (theme_model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   THEME_DISPLAY_COL, _("Custom"),
+                                                   THEME_IDENTIFIER_COL, CUSTOM_THEME_NAME,
+                                                   THEME_PARENT_ID_COL, theme,
+                                                   -1);
+                set_combox_for_theme_name (chooser, CUSTOM_THEME_NAME);
+        } else if (remove_custom) {
+                gtk_tree_model_get_iter_first (theme_model, &iter);
+                do {
+                        char *this_parent;
+
+                        gtk_tree_model_get (theme_model, &iter,
+                                            THEME_PARENT_ID_COL, &this_parent,
+                                            -1);
+                        if (this_parent != NULL && strcmp (this_parent, CUSTOM_THEME_NAME) != 0) {
+                                g_free (this_parent);
+                                gtk_list_store_remove (GTK_LIST_STORE (theme_model), &iter);
+                                break;
+                        }
+                        g_free (this_parent);
+                } while (gtk_tree_model_iter_next (theme_model, &iter));
+
+                delete_custom_theme_dir ();
+
+                set_combox_for_theme_name (chooser, parent);
+        }
+
+        update_alert_model (chooser, alert_id);
+
+        g_free (theme);
+        g_free (parent);
+}
+
+static void
+on_alert_toggled (GtkCellRendererToggle *renderer,
+                  char                  *path_str,
+                  GvcSoundThemeChooser  *chooser)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreePath  *path;
+        gboolean      toggled;
+        char         *id;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        path = gtk_tree_path_new_from_string (path_str);
+        gtk_tree_model_get_iter (model, &iter, path);
+        gtk_tree_path_free (path);
+
+        id = NULL;
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            ALERT_ACTIVE_COL, &toggled,
+                            -1);
+
+        toggled ^= 1;
+        if (toggled) {
+                update_alert (chooser, id);
+        }
+
+        g_free (id);
+}
+
+static void
+play_preview_for_path (GvcSoundThemeChooser *chooser, GtkTreePath *path)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreeIter   theme_iter;
+        gchar        *id = NULL;
+        gchar        *parent_theme = NULL;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        if (gtk_tree_model_get_iter (model, &iter, path) == FALSE)
+                return;
+
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            -1);
+        if (id == NULL)
+                return;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &theme_iter)) {
+                GtkTreeModel *theme_model;
+                gchar        *theme_id = NULL;
+                gchar        *parent_id = NULL;
+
+                theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+                gtk_tree_model_get (theme_model, &theme_iter,
+                                    THEME_IDENTIFIER_COL, &theme_id,
+                                    THEME_PARENT_ID_COL, &parent_id, -1);
+                if (theme_id && strcmp (theme_id, CUSTOM_THEME_NAME) == 0)
+                        parent_theme = g_strdup (parent_id);
+
+                g_free (theme_id);
+                g_free (parent_id);
+        }
+
+        /* special case: for the default item on custom themes
+         * play the alert for the parent theme */
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                if (parent_theme != NULL) {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_CANBERRA_XDG_THEME_NAME, parent_theme,
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                } else {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                }
+        } else {
+                ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                        CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                        CA_PROP_MEDIA_FILENAME, id,
+                                        CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                        CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                        CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                        CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                        NULL);
+
+        }
+        g_free (parent_theme);
+        g_free (id);
+}
+
+static void
+on_treeview_row_activated (GtkTreeView          *treeview,
+                           GtkTreePath          *path,
+                           GtkTreeViewColumn    *column,
+                           GvcSoundThemeChooser *chooser)
+{
+        play_preview_for_path (chooser, path);
+}
+
+static void
+on_treeview_selection_changed (GtkTreeSelection     *selection,
+                               GvcSoundThemeChooser *chooser)
+{
+        GList        *paths;
+        GtkTreeModel *model;
+        GtkTreePath  *path;
+
+        if (chooser->priv->treeview == NULL)
+                return;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        paths = gtk_tree_selection_get_selected_rows (selection, &model);
+        if (paths == NULL)
+                return;
+
+        path = paths->data;
+        play_preview_for_path (chooser, path);
+
+        g_list_foreach (paths, (GFunc)gtk_tree_path_free, NULL);
+        g_list_free (paths);
+}
+
+static GtkWidget *
+create_alert_treeview (GvcSoundThemeChooser *chooser)
+{
+        GtkListStore         *store;
+        GtkWidget            *treeview;
+        GtkCellRenderer      *renderer;
+        GtkTreeViewColumn    *column;
+        GtkTreeSelection     *selection;
+
+        treeview = gtk_tree_view_new ();
+
+        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
+        g_signal_connect (G_OBJECT (treeview),
+                          "row-activated",
+                          G_CALLBACK (on_treeview_row_activated),
+                          chooser);
+
+        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+        gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+        g_signal_connect (G_OBJECT (selection),
+                          "changed",
+                          G_CALLBACK (on_treeview_selection_changed),
+                          chooser);
+
+        /* Setup the tree model, 3 columns:
+         * - display name
+         * - sound id
+         * - sound type
+         */
+        store = gtk_list_store_new (ALERT_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_BOOLEAN);
+
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           ALERT_IDENTIFIER_COL, DEFAULT_ALERT_ID,
+                                           ALERT_DISPLAY_COL, _("Default"),
+                                           ALERT_SOUND_TYPE_COL, _("From theme"),
+                                           ALERT_ACTIVE_COL, TRUE,
+                                           -1);
+
+        populate_model_from_dir (chooser, GTK_TREE_MODEL (store), SOUND_SET_DIR);
+
+        gtk_tree_view_set_model (GTK_TREE_VIEW (treeview),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_toggle_new ();
+        gtk_cell_renderer_toggle_set_radio (GTK_CELL_RENDERER_TOGGLE (renderer), TRUE);
+
+        column = gtk_tree_view_column_new_with_attributes (NULL,
+                                                           renderer,
+                                                           "active", ALERT_ACTIVE_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+        g_signal_connect (renderer,
+                          "toggled",
+                          G_CALLBACK (on_alert_toggled),
+                          chooser);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Name"),
+                                                           renderer,
+                                                           "text", ALERT_DISPLAY_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Type"),
+                                                           renderer,
+                                                           "text", ALERT_SOUND_TYPE_COL,
+                                                           NULL);
+
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        return treeview;
+}
+
+static int
+get_file_type (const char *sound_name,
+               char      **linked_name)
+{
+        char *name, *filename;
+
+        *linked_name = NULL;
+
+        name = g_strdup_printf ("%s.disabled", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_REGULAR) != FALSE) {
+                g_free (filename);
+                return SOUND_TYPE_OFF;
+        }
+        g_free (filename);
+
+        /* We only check for .ogg files because those are the
+         * only ones we create */
+        name = g_strdup_printf ("%s.ogg", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_SYMLINK) != FALSE) {
+                *linked_name = g_file_read_link (filename, NULL);
+                g_free (filename);
+                return SOUND_TYPE_CUSTOM;
+        }
+        g_free (filename);
+
+        return SOUND_TYPE_BUILTIN;
+}
+
+static void
+update_alerts_from_theme_name (GvcSoundThemeChooser *chooser,
+                               const gchar          *name)
+{
+        if (strcmp (name, CUSTOM_THEME_NAME) != 0) {
+                /* reset alert to default */
+                update_alert (chooser, DEFAULT_ALERT_ID);
+        } else {
+                int   sound_type;
+                char *linkname;
+
+                linkname = NULL;
+                sound_type = get_file_type ("bell-terminal", &linkname);
+                g_debug ("Found link: %s", linkname);
+                if (sound_type == SOUND_TYPE_CUSTOM) {
+                        update_alert (chooser, linkname);
+                }
+        }
+}
+
+static void
+update_theme (GvcSoundThemeChooser *chooser)
+{
+        char        *theme_name;
+        gboolean     events_enabled;
+        gboolean     feedback_enabled;
+
+        feedback_enabled = g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY);
+        set_input_feedback_enabled (chooser, feedback_enabled);
+
+        events_enabled = g_settings_get_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY);
+        if (events_enabled) {
+                theme_name = g_settings_get_string (chooser->priv->sound_settings, SOUND_THEME_KEY);
+        } else {
+                theme_name = g_strdup (NO_SOUNDS_THEME_NAME);
+        }
+
+        gtk_widget_set_sensitive (chooser->priv->selection_box, events_enabled);
+        gtk_widget_set_sensitive (chooser->priv->click_feedback_button, events_enabled);
+
+        set_combox_for_theme_name (chooser, theme_name);
+
+        update_alerts_from_theme_name (chooser, theme_name);
+
+        g_free (theme_name);
+}
+
+static void
+gvc_sound_theme_chooser_class_init (GvcSoundThemeChooserClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_sound_theme_chooser_dispose;
+}
+
+static void
+on_click_feedback_toggled (GtkToggleButton      *button,
+                           GvcSoundThemeChooser *chooser)
+{
+        gboolean enabled;
+
+        enabled = gtk_toggle_button_get_active (button);
+
+        g_settings_set_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY, enabled);
+}
+
+static void
+on_key_changed (GSettings            *settings,
+                gchar                *key,
+                GvcSoundThemeChooser *chooser)
+{
+        if (!strcmp (key, EVENT_SOUNDS_KEY) ||
+            !strcmp (key, SOUND_THEME_KEY) ||
+            !strcmp (key, INPUT_SOUNDS_KEY))
+                update_theme (chooser);
+}
+
+static void
+setup_list_size_constraint (GtkWidget *widget,
+                            GtkWidget *to_size)
+{
+        GtkRequisition req;
+        gint           sc_height;
+        int            max_height;
+
+        /* Constrain height to be the tree height up to a max */
+        gdk_window_get_geometry (gdk_screen_get_root_window (gtk_widget_get_screen (widget)),
+                                 NULL, NULL, NULL, &sc_height);
+
+        max_height = sc_height / 4;
+
+        // XXX this doesn't work
+        gtk_widget_get_preferred_size (to_size, NULL, &req);
+
+        gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (widget),
+                                                    MIN (req.height, max_height));
+}
+
+static void
+gvc_sound_theme_chooser_init (GvcSoundThemeChooser *chooser)
+{
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *scrolled_window;
+        gchar       *str;
+
+        chooser->priv = gvc_sound_theme_chooser_get_instance_private (chooser);
+
+        chooser->priv->theme_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->theme_box, FALSE, FALSE, 0);
+
+        label = gtk_label_new_with_mnemonic (_("Sound _theme:"));
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), label, FALSE, FALSE, 0);
+        chooser->priv->combo_box = gtk_combo_box_new ();
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), chooser->priv->combo_box, FALSE, FALSE, 6);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->combo_box);
+
+        chooser->priv->sound_settings = g_settings_new (KEY_SOUNDS_SCHEMA);
+
+        g_signal_connect (G_OBJECT (chooser->priv->sound_settings),
+                          "changed",
+                          G_CALLBACK (on_key_changed),
+                          chooser);
+
+        str = g_strdup_printf ("<b>%s</b>", _("C_hoose an alert sound:"));
+        chooser->priv->selection_box = box = gtk_frame_new (str);
+        g_free (str);
+
+        label = gtk_frame_get_label_widget (GTK_FRAME (box));
+        gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
+        gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+        gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
+
+        gtk_box_pack_start (GTK_BOX (chooser), box, TRUE, TRUE, 6);
+
+        chooser->priv->treeview = create_alert_treeview (chooser);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->treeview);
+
+        scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+        gtk_widget_set_hexpand (scrolled_window, TRUE);
+        gtk_widget_set_vexpand (scrolled_window, TRUE);
+        gtk_widget_set_margin_top (scrolled_window, 6);
+
+        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+                                        GTK_POLICY_NEVER,
+                                        GTK_POLICY_AUTOMATIC);
+        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
+                                             GTK_SHADOW_IN);
+
+        gtk_container_add (GTK_CONTAINER (scrolled_window), chooser->priv->treeview);
+        gtk_container_add (GTK_CONTAINER (box), scrolled_window);
+
+        chooser->priv->click_feedback_button = gtk_check_button_new_with_mnemonic (_("Enable _window and button sounds"));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY));
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->click_feedback_button,
+                            FALSE, FALSE, 0);
+
+        g_signal_connect (G_OBJECT (chooser->priv->click_feedback_button),
+                          "toggled",
+                          G_CALLBACK (on_click_feedback_toggled),
+                          chooser);
+
+        setup_theme_selector (chooser);
+        update_theme (chooser);
+
+        setup_list_size_constraint (scrolled_window, chooser->priv->treeview);
+}
+
+static void
+gvc_sound_theme_chooser_dispose (GObject *object)
+{
+        GvcSoundThemeChooser *chooser;
+
+        chooser = GVC_SOUND_THEME_CHOOSER (object);
+
+        g_clear_object (&chooser->priv->sound_settings);
+
+        G_OBJECT_CLASS (gvc_sound_theme_chooser_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_sound_theme_chooser_new (void)
+{
+        return g_object_new (GVC_TYPE_SOUND_THEME_CHOOSER,
+                                "spacing", 6,
+                                "orientation", GTK_ORIENTATION_VERTICAL,
+                                NULL);
+}
+
+
+
+ + + diff --git a/2020-06-29-181100-6971-cppcheck@ea7fcb89ced5_on_notebook_scroll_event/2.html b/2020-06-29-181100-6971-cppcheck@ea7fcb89ced5_on_notebook_scroll_event/2.html new file mode 100644 index 0000000..bacfabb --- /dev/null +++ b/2020-06-29-181100-6971-cppcheck@ea7fcb89ced5_on_notebook_scroll_event/2.html @@ -0,0 +1,1110 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <canberra.h>
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-speaker-test.h"
+#include "gvc-utils.h"
+
+struct _GvcSpeakerTestPrivate
+{
+        GArray           *controls;
+        ca_context       *canberra;
+        MateMixerStream  *stream;
+};
+
+enum {
+        PROP_0,
+        PROP_STREAM,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_speaker_test_dispose    (GObject             *object);
+static void gvc_speaker_test_finalize   (GObject             *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSpeakerTest, gvc_speaker_test, GTK_TYPE_GRID)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+typedef struct {
+        MateMixerChannelPosition position;
+        guint left;
+        guint top;
+} TablePosition;
+
+static const TablePosition positions[] = {
+        /* Position, X, Y */
+        { MATE_MIXER_CHANNEL_FRONT_LEFT, 0, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_LEFT_CENTER, 1, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_CENTER, 2, 0, },
+        { MATE_MIXER_CHANNEL_MONO, 2, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT_CENTER, 3, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT, 4, 0, },
+        { MATE_MIXER_CHANNEL_SIDE_LEFT, 0, 1, },
+        { MATE_MIXER_CHANNEL_SIDE_RIGHT, 4, 1, },
+        { MATE_MIXER_CHANNEL_BACK_LEFT, 0, 2, },
+        { MATE_MIXER_CHANNEL_BACK_CENTER, 2, 2, },
+        { MATE_MIXER_CHANNEL_BACK_RIGHT, 4, 2, },
+        { MATE_MIXER_CHANNEL_LFE, 3, 2 }
+};
+
+MateMixerStream *
+gvc_speaker_test_get_stream (GvcSpeakerTest *test)
+{
+        g_return_val_if_fail (GVC_IS_SPEAKER_TEST (test), NULL);
+
+        return test->priv->stream;
+}
+
+static void
+gvc_speaker_test_set_stream (GvcSpeakerTest *test, MateMixerStream *stream)
+{
+        MateMixerStreamControl *control;
+        const gchar            *name;
+        guint                   i;
+
+        name = mate_mixer_stream_get_name (stream);
+        control = mate_mixer_stream_get_default_control (stream);
+
+        ca_context_change_device (test->priv->canberra, name);
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                gboolean has_position =
+                        mate_mixer_stream_control_has_channel_position (control, positions[i].position);
+
+                gtk_widget_set_visible (g_array_index (test->priv->controls, GtkWidget *, i),
+                                        has_position);
+        }
+
+        test->priv->stream = g_object_ref (stream);
+}
+
+static void
+gvc_speaker_test_set_property (GObject       *object,
+                               guint          prop_id,
+                               const GValue  *value,
+                               GParamSpec    *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                gvc_speaker_test_set_stream (self, g_value_get_object (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_get_property (GObject     *object,
+                               guint        prop_id,
+                               GValue      *value,
+                               GParamSpec  *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                g_value_set_object (value, self->priv->stream);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_class_init (GvcSpeakerTestClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose  = gvc_speaker_test_dispose;
+        object_class->finalize = gvc_speaker_test_finalize;
+        object_class->set_property = gvc_speaker_test_set_property;
+        object_class->get_property = gvc_speaker_test_get_property;
+
+        properties[PROP_STREAM] =
+                g_param_spec_object ("stream",
+                                     "Stream",
+                                     "MateMixer stream",
+                                     MATE_MIXER_TYPE_STREAM,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+}
+
+static const gchar *
+sound_name (MateMixerChannelPosition position)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return "audio-channel-front-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return "audio-channel-front-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return "audio-channel-front-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return "audio-channel-rear-left";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return "audio-channel-rear-right";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return "audio-channel-rear-center";
+        case MATE_MIXER_CHANNEL_LFE:
+                return "audio-channel-lfe";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return "audio-channel-side-left";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return "audio-channel-side-right";
+        default:
+                return NULL;
+        }
+}
+
+static const gchar *
+icon_name (MateMixerChannelPosition position, gboolean playing)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return playing
+                        ? "audio-speaker-left-testing"
+                        : "audio-speaker-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return playing
+                        ? "audio-speaker-right-testing"
+                        : "audio-speaker-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return playing
+                        ? "audio-speaker-center-testing"
+                        : "audio-speaker-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return playing
+                        ? "audio-speaker-left-back-testing"
+                        : "audio-speaker-left-back";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return playing
+                        ? "audio-speaker-right-back-testing"
+                        : "audio-speaker-right-back";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return playing
+                        ? "audio-speaker-center-back-testing"
+                        : "audio-speaker-center-back";
+        case MATE_MIXER_CHANNEL_LFE:
+                return playing
+                        ? "audio-subwoofer-testing"
+                        : "audio-subwoofer";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return playing
+                        ? "audio-speaker-left-side-testing"
+                        : "audio-speaker-left-side";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return playing
+                        ? "audio-speaker-right-side-testing"
+                        : "audio-speaker-right-side";
+        default:
+                return NULL;
+        }
+}
+
+static void
+update_button (GtkWidget *control)
+{
+        GtkWidget *button;
+        GtkWidget *image;
+        gboolean   playing;
+        MateMixerChannelPosition position;
+
+        button = g_object_get_data (G_OBJECT (control), "button");
+        image  = g_object_get_data (G_OBJECT (control), "image");
+
+        position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+        playing  = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        gtk_button_set_label (GTK_BUTTON (button), playing ? _("Stop") : _("Test"));
+
+        gtk_image_set_from_icon_name (GTK_IMAGE (image),
+                                      icon_name (position, playing),
+                                      GTK_ICON_SIZE_DIALOG);
+}
+
+static gboolean
+idle_cb (GtkWidget *control)
+{
+        if (control != NULL) {
+                /* This is called in the background thread, hence forward to main thread
+                 * via idle callback */
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+
+                update_button (control);
+        }
+        return FALSE;
+}
+
+static void
+finish_cb (ca_context *c, uint32_t id, int error_code, void *userdata)
+{
+        GtkWidget *control = (GtkWidget *) userdata;
+
+        if (error_code == CA_ERROR_DESTROYED || control == NULL)
+                return;
+
+        g_idle_add ((GSourceFunc) idle_cb, control);
+}
+
+static void
+on_test_button_clicked (GtkButton *button, GtkWidget *control)
+{
+        gboolean    playing;
+        ca_context *canberra;
+
+        canberra = g_object_get_data (G_OBJECT (control), "canberra");
+
+        ca_context_cancel (canberra, 1);
+
+        playing = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        if (playing) {
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        } else {
+                MateMixerChannelPosition position;
+                const gchar *name;
+                ca_proplist *proplist;
+
+                position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+
+                ca_proplist_create (&proplist);
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_ROLE, "test");
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_NAME,
+                                  gvc_channel_position_to_pretty_string (position));
+                ca_proplist_sets (proplist,
+                                  CA_PROP_CANBERRA_FORCE_CHANNEL,
+                                  gvc_channel_position_to_pulse_string (position));
+
+                ca_proplist_sets (proplist, CA_PROP_CANBERRA_ENABLE, "1");
+
+                name = sound_name (position);
+                if (name != NULL) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, name);
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, "audio-test-signal");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets(proplist, CA_PROP_EVENT_ID, "bell-window-system");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (playing));
+        }
+
+        update_button (control);
+}
+
+static GtkWidget *
+create_control (ca_context *canberra, MateMixerChannelPosition position)
+{
+        GtkWidget   *control;
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *image;
+        GtkWidget   *test_button;
+        const gchar *name;
+
+        control = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+        box     = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        g_object_set_data (G_OBJECT (control), "position", GINT_TO_POINTER (position));
+        g_object_set_data (G_OBJECT (control), "canberra", canberra);
+
+        name = icon_name (position, FALSE);
+        if (name == NULL)
+                name = "audio-volume-medium";
+
+        image = gtk_image_new_from_icon_name (name, GTK_ICON_SIZE_DIALOG);
+        g_object_set_data (G_OBJECT (control), "image", image);
+        gtk_box_pack_start (GTK_BOX (control), image, FALSE, FALSE, 0);
+
+        label = gtk_label_new (gvc_channel_position_to_pretty_string (position));
+        gtk_box_pack_start (GTK_BOX (control), label, FALSE, FALSE, 0);
+
+        test_button = gtk_button_new_with_label (_("Test"));
+        g_signal_connect (G_OBJECT (test_button),
+                          "clicked",
+                          G_CALLBACK (on_test_button_clicked),
+                          control);
+
+        g_object_set_data (G_OBJECT (control), "button", test_button);
+
+        gtk_box_pack_start (GTK_BOX (box), test_button, TRUE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (control), box, FALSE, FALSE, 0);
+
+        gtk_widget_show_all (control);
+
+        return control;
+}
+
+static void
+create_controls (GvcSpeakerTest *test)
+{
+        guint i;
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                GtkWidget *control = create_control (test->priv->canberra, positions[i].position);
+
+                gtk_grid_attach (GTK_GRID (test),
+                                 control,
+                                 positions[i].left,
+                                 positions[i].top,
+                                 1, 1);
+                g_array_insert_val (test->priv->controls, i, control);
+        }
+}
+
+static void
+gvc_speaker_test_init (GvcSpeakerTest *test)
+{
+        GtkWidget *face;
+
+        test->priv = gvc_speaker_test_get_instance_private (test);
+
+        gtk_container_set_border_width (GTK_CONTAINER (test), 12);
+
+        face = gtk_image_new_from_icon_name ("face-smile", GTK_ICON_SIZE_DIALOG);
+
+        gtk_grid_attach (GTK_GRID (test),
+                         face,
+                         1, 1,
+                         3, 1);
+
+
+        gtk_grid_set_baseline_row (GTK_GRID (test), 1);
+        gtk_widget_show (face);
+
+        ca_context_create (&test->priv->canberra);
+
+        /* The test sounds are played for a single channel, set up using the
+         * FORCE_CHANNEL property of libcanberra; this property is only supported
+         * in the PulseAudio backend, so avoid other backends completely */
+        ca_context_set_driver (test->priv->canberra, "pulse");
+
+        ca_context_change_props (test->priv->canberra,
+                                 CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+                                 CA_PROP_APPLICATION_NAME, _("Volume Control"),
+                                 CA_PROP_APPLICATION_VERSION, VERSION,
+                                 CA_PROP_APPLICATION_ICON_NAME, "multimedia-volume-control",
+                                 NULL);
+
+        test->priv->controls = g_array_new (FALSE, FALSE, sizeof (GtkWidget *));
+
+        create_controls (test);
+}
+
+static void
+gvc_speaker_test_dispose (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        g_clear_object (&test->priv->stream);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->dispose (object);
+}
+
+static void
+gvc_speaker_test_finalize (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        ca_context_destroy (test->priv->canberra);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->finalize (object);
+}
+
+GtkWidget *
+gvc_speaker_test_new (MateMixerStream *stream)
+{
+        GObject *test;
+
+        g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL);
+
+        test = g_object_new (GVC_TYPE_SPEAKER_TEST,
+                             "row-spacing", 6,
+                             "column-spacing", 6,
+                             "row-homogeneous", TRUE,
+                             "column-homogeneous", TRUE,
+                             "stream", stream,
+                             NULL);
+
+        return GTK_WIDGET (test);
+}
+
+
+
+ + + diff --git a/2020-06-29-181100-6971-cppcheck@ea7fcb89ced5_on_notebook_scroll_event/index.html b/2020-06-29-181100-6971-cppcheck@ea7fcb89ced5_on_notebook_scroll_event/index.html new file mode 100644 index 0000000..59baeb0 --- /dev/null +++ b/2020-06-29-181100-6971-cppcheck@ea7fcb89ced5_on_notebook_scroll_event/index.html @@ -0,0 +1,108 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
mate-volume-control/gvc-combo-box.c
70unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
mate-volume-control/gvc-sound-theme-chooser.c
735ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
746ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
758ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
mate-volume-control/gvc-speaker-test.c
53unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+ + + diff --git a/2020-06-29-181100-6971-cppcheck@ea7fcb89ced5_on_notebook_scroll_event/stats.html b/2020-06-29-181100-6971-cppcheck@ea7fcb89ced5_on_notebook_scroll_event/stats.html new file mode 100644 index 0000000..3fb6add --- /dev/null +++ b/2020-06-29-181100-6971-cppcheck@ea7fcb89ced5_on_notebook_scroll_event/stats.html @@ -0,0 +1,93 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+

Top 10 files for error severity, total findings: 2
+   1  mate-volume-control/gvc-speaker-test.c
+   1  mate-volume-control/gvc-combo-box.c
+

+

Top 10 files for information severity, total findings: 3
+   3  mate-volume-control/gvc-sound-theme-chooser.c
+

+ +
+ + + diff --git a/2020-06-29-181100-6971-cppcheck@ea7fcb89ced5_on_notebook_scroll_event/style.css b/2020-06-29-181100-6971-cppcheck@ea7fcb89ced5_on_notebook_scroll_event/style.css new file mode 100644 index 0000000..c39571c --- /dev/null +++ b/2020-06-29-181100-6971-cppcheck@ea7fcb89ced5_on_notebook_scroll_event/style.css @@ -0,0 +1,149 @@ + +body { + font: 13px Arial, Verdana, Sans-Serif; + margin: 0; + width: auto; +} + +h1 { + margin: 10px; +} + +#footer > p { + margin: 4px; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + border: 1px dotted black; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #B6B6B4; +} + +.inconclusive2 { + background-color: #B6B6B4; + border: 1px dotted black; + display: inline-block; + margin-left: 4px; +} + +div.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +div.verbose div.content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid black; + background-color: #FFFFCC; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +#header { + border-bottom: thin solid #aaa; +} + +#menu { + float: left; + margin-top: 5px; + text-align: left; + width: 150px; + /*height: 75%;*/ + position: fixed; + overflow: auto; + z-index: 1; +} + +#menu_index { + float: left; + margin-top: 5px; + padding-left: 5px; + text-align: left; + width: 300px; + /*height: 75%;*/ + position: fixed; + overflow: auto; + z-index: 1; +} + +#menu > a { + display: block; + margin-left: 10px; + font: 12px; + z-index: 1; +} + +#filename { + margin-left: 10px; + font: 12px; + z-index: 1; +} + +.highlighttable { + background-color:white; + z-index: 10; + position: relative; + margin: -10 px; +} + +#content { + background-color: white; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + float: left; + margin: 5px; + margin-left: 10px; + padding: 0 10px 10px 10px; + width: 80%; + padding-left: 150px; +} + +#content_index { + background-color: white; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + float: left; + margin: 5px; + margin-left: 10px; + padding: 0 10px 10px 10px; + width: 80%; + padding-left: 300px; +} + +.linenos { + border-right: thin solid #aaa; + color: lightgray; + padding-right: 6px; +} + +#footer { + border-top: thin solid #aaa; + clear: both; + font-size: 90%; + margin-top: 5px; +} + +#footer ul { + list-style-type: none; + padding-left: 0; +} diff --git a/2020-06-29-181553-0160-cppcheck@7993c4636f49_on_notebook_scroll_event/0.html b/2020-06-29-181553-0160-cppcheck@7993c4636f49_on_notebook_scroll_event/0.html new file mode 100644 index 0000000..e262ed0 --- /dev/null +++ b/2020-06-29-181553-0160-cppcheck@7993c4636f49_on_notebook_scroll_event/0.html @@ -0,0 +1,1038 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-combo-box.h"
+
+struct _GvcComboBoxPrivate
+{
+        GtkWidget       *drop_box;
+        GtkWidget       *start_box;
+        GtkWidget       *end_box;
+        GtkWidget       *label;
+        GtkWidget       *button;
+        GtkTreeModel    *model;
+        GtkWidget       *combobox;
+        MateMixerSwitch *swtch;
+};
+
+enum {
+        COL_NAME,
+        COL_HUMAN_NAME,
+        NUM_COLS
+};
+
+enum {
+        CHANGING,
+        BUTTON_CLICKED,
+        LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+enum {
+        PROP_0,
+        PROP_SWITCH,
+        PROP_LABEL,
+        PROP_SHOW_BUTTON,
+        PROP_BUTTON_LABEL,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_combo_box_dispose    (GObject          *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcComboBox, gvc_combo_box, GTK_TYPE_BOX)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+MateMixerSwitch *
+gvc_combo_box_get_switch (GvcComboBox *combobox)
+{
+        g_return_val_if_fail (GVC_IS_COMBO_BOX (combobox), NULL);
+
+        return combobox->priv->swtch;
+}
+
+void
+gvc_combo_box_set_size_group (GvcComboBox  *combobox,
+                              GtkSizeGroup *group,
+                              gboolean      symmetric)
+{
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (GTK_IS_SIZE_GROUP (group));
+
+        if (group != NULL) {
+                gtk_size_group_add_widget (group, combobox->priv->start_box);
+                if (symmetric == TRUE)
+                        gtk_size_group_add_widget (group, combobox->priv->end_box);
+        }
+        gtk_widget_queue_draw (GTK_WIDGET (combobox));
+}
+
+static void
+on_switch_active_option_notify (MateMixerSwitch *swtch,
+                                GParamSpec      *pspec,
+                                GvcComboBox     *combobox)
+{
+        GtkTreeIter            iter;
+        MateMixerSwitchOption *active;
+        gboolean               cont;
+        const gchar           *name;
+
+        active = mate_mixer_switch_get_active_option (swtch);
+        if (G_UNLIKELY (active == NULL)) {
+                g_warn_if_reached ();
+                return;
+        }
+
+        /* Select the newly activated switch option in the combo box */
+        name = mate_mixer_switch_option_get_name (active);
+        cont = gtk_tree_model_get_iter_first (combobox->priv->model, &iter);
+        while (cont == TRUE) {
+                gchar *current;
+
+                gtk_tree_model_get (combobox->priv->model, &iter,
+                                    COL_NAME, &current,
+                                    -1);
+                if (g_strcmp0 (name, current) == 0) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox), &iter);
+                        g_free (current);
+                        return;
+                }
+                g_free (current);
+
+                cont = gtk_tree_model_iter_next (combobox->priv->model, &iter);
+        }
+        g_warning ("Could not find switch option '%s' in combo box", name);
+}
+
+static void
+gvc_combo_box_set_switch (GvcComboBox *combobox, MateMixerSwitch *swtch)
+{
+        MateMixerSwitchOption *active;
+        const GList           *options;
+
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (MATE_MIXER_IS_SWITCH (swtch));
+
+        combobox->priv->swtch = g_object_ref (swtch);
+
+        active  = mate_mixer_switch_get_active_option (swtch);
+        options = mate_mixer_switch_list_options (swtch);
+        while (options != NULL) {
+                GtkTreeIter            iter;
+                MateMixerSwitchOption *option = MATE_MIXER_SWITCH_OPTION (options->data);
+
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (combobox->priv->model),
+                                                   &iter,
+                                                   G_MAXINT,
+                                                   COL_NAME,
+                                                   mate_mixer_switch_option_get_name (option),
+                                                   COL_HUMAN_NAME,
+                                                   mate_mixer_switch_option_get_label (option),
+                                                   -1);
+
+                /* Select the currently active option of the switch */
+                if (option == active) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox),
+                                                       &iter);
+                }
+                options = options->next;
+        }
+
+        g_signal_connect (G_OBJECT (swtch),
+                          "notify::active-option",
+                          G_CALLBACK (on_switch_active_option_notify),
+                          combobox);
+}
+
+static void
+gvc_combo_box_set_property (GObject       *object,
+                            guint          prop_id,
+                            const GValue  *value,
+                            GParamSpec    *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                gvc_combo_box_set_switch (self, g_value_get_object (value));
+                break;
+        case PROP_LABEL:
+                gtk_label_set_text_with_mnemonic (GTK_LABEL (self->priv->label), g_value_get_string (value));
+                break;
+        case PROP_BUTTON_LABEL:
+                gtk_button_set_label (GTK_BUTTON (self->priv->button), g_value_get_string (value));
+                break;
+        case PROP_SHOW_BUTTON:
+                gtk_widget_set_visible (self->priv->button, g_value_get_boolean (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_get_property (GObject     *object,
+                            guint        prop_id,
+                            GValue      *value,
+                            GParamSpec  *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                g_value_set_object (value, self->priv->swtch);
+                break;
+        case PROP_LABEL:
+                g_value_set_string (value, gtk_label_get_text (GTK_LABEL (self->priv->label)));
+                break;
+        case PROP_BUTTON_LABEL:
+                g_value_set_string (value, gtk_button_get_label (GTK_BUTTON (self->priv->button)));
+                break;
+        case PROP_SHOW_BUTTON:
+                g_value_set_boolean (value, gtk_widget_get_visible (self->priv->button));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_class_init (GvcComboBoxClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_combo_box_dispose;
+        object_class->set_property = gvc_combo_box_set_property;
+        object_class->get_property = gvc_combo_box_get_property;
+
+        properties[PROP_SWITCH] =
+                g_param_spec_object ("switch",
+                                     "switch",
+                                     "The MateMixerSwitch",
+                                     MATE_MIXER_TYPE_SWITCH,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_LABEL] =
+                g_param_spec_string ("label",
+                                     "label",
+                                     "The combo box label",
+                                     _("_Profile:"),
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_SHOW_BUTTON] =
+                g_param_spec_boolean ("show-button",
+                                      "show-button",
+                                      "Whether to show the button",
+                                      FALSE,
+                                      G_PARAM_READWRITE |
+                                      G_PARAM_CONSTRUCT |
+                                      G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_BUTTON_LABEL] =
+                g_param_spec_string ("button-label",
+                                     "button-label",
+                                     "The button's label",
+                                     "",
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+
+        signals[CHANGING] =
+                g_signal_new ("changing",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, changing),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__OBJECT,
+                              G_TYPE_NONE,
+                              1,
+                              MATE_MIXER_TYPE_SWITCH_OPTION);
+
+        signals[BUTTON_CLICKED] =
+                g_signal_new ("button-clicked",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, button_clicked),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
+}
+
+static void
+on_combo_box_changed (GtkComboBox *widget, GvcComboBox *combobox)
+{
+        GtkTreeIter            iter;
+        gchar                 *name;
+        MateMixerSwitchOption *option;
+
+        if (G_UNLIKELY (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter) == FALSE))
+                return;
+
+        gtk_tree_model_get (combobox->priv->model, &iter,
+                            COL_NAME, &name,
+                            -1);
+
+        option = mate_mixer_switch_get_option (combobox->priv->swtch, name);
+        if (G_UNLIKELY (option == NULL)) {
+                g_warn_if_reached ();
+                g_free (name);
+                return;
+        }
+
+        /* Inform that we are about to change the active option of the switch */
+        g_signal_emit (combobox, signals[CHANGING], 0, option);
+
+        mate_mixer_switch_set_active_option (combobox->priv->swtch, option);
+        g_free (name);
+}
+
+static void
+on_combo_box_button_clicked (GtkButton *button, GvcComboBox *combobox)
+{
+        /* The meaning of the button is defined by the owner, so only notify
+         * when it is clicked on */
+        g_signal_emit (combobox, signals[BUTTON_CLICKED], 0);
+}
+
+static void
+gvc_combo_box_init (GvcComboBox *combobox)
+{
+        GtkWidget       *frame;
+        GtkCellRenderer *renderer;
+
+        frame = gtk_frame_new (NULL);
+        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
+
+        combobox->priv = gvc_combo_box_get_instance_private (combobox);
+
+        combobox->priv->model = GTK_TREE_MODEL (gtk_list_store_new (NUM_COLS,
+                                                                    G_TYPE_STRING,
+                                                                    G_TYPE_STRING));
+
+        combobox->priv->combobox = gtk_combo_box_new_with_model (combobox->priv->model);
+
+        combobox->priv->label = gtk_label_new (NULL);
+
+        gtk_label_set_xalign (GTK_LABEL (combobox->priv->label), 0.0);
+        gtk_label_set_yalign (GTK_LABEL (combobox->priv->label), 0.5);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (combobox->priv->label),
+                                       combobox->priv->combobox);
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                    renderer,
+                                    FALSE);
+        gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                       renderer,
+                                       "text",
+                                       COL_HUMAN_NAME);
+
+        combobox->priv->drop_box  = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->start_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->end_box   = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+        /* Make sure the combo box does not get too long on long profile names */
+        g_object_set (G_OBJECT (renderer),
+                      "ellipsize",
+                      PANGO_ELLIPSIZE_END,
+                      NULL);
+
+        gtk_combo_box_set_popup_fixed_width (GTK_COMBO_BOX (combobox->priv->combobox), FALSE);
+
+        gtk_box_pack_start (GTK_BOX (combobox),
+                            frame,
+                            TRUE, TRUE, 0);
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->start_box,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->start_box),
+                            combobox->priv->label,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->combobox,
+                            TRUE, TRUE, 0);
+
+        combobox->priv->button = gtk_button_new_with_label ("");
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->button,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->end_box,
+                            FALSE, FALSE, 0);
+
+        gtk_container_add (GTK_CONTAINER (frame), combobox->priv->drop_box);
+
+        g_signal_connect (G_OBJECT (combobox->priv->combobox),
+                          "changed",
+                          G_CALLBACK (on_combo_box_changed),
+                          combobox);
+        g_signal_connect (G_OBJECT (combobox->priv->button),
+                          "clicked",
+                          G_CALLBACK (on_combo_box_button_clicked),
+                          combobox);
+
+        gtk_widget_set_no_show_all (combobox->priv->button, TRUE);
+        gtk_widget_show_all (frame);
+}
+
+static void
+gvc_combo_box_dispose (GObject *object)
+{
+        GvcComboBox *combobox;
+
+        combobox = GVC_COMBO_BOX (object);
+
+        if (G_LIKELY (combobox->priv->swtch != NULL)) {
+                g_signal_handlers_disconnect_by_func (G_OBJECT (combobox->priv->swtch),
+                                                      G_CALLBACK (on_switch_active_option_notify),
+                                                      combobox);
+                g_clear_object (&combobox->priv->swtch);
+        }
+
+        g_clear_object (&combobox->priv->model);
+
+        G_OBJECT_CLASS (gvc_combo_box_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_combo_box_new (MateMixerSwitch *swtch, const gchar *label)
+{
+        return g_object_new (GVC_TYPE_COMBO_BOX,
+                             "switch", swtch,
+                             "label", label,
+                             "orientation", GTK_ORIENTATION_HORIZONTAL,
+                             NULL);
+}
+
+
+
+ + + diff --git a/2020-06-29-181553-0160-cppcheck@7993c4636f49_on_notebook_scroll_event/1.html b/2020-06-29-181553-0160-cppcheck@7993c4636f49_on_notebook_scroll_event/1.html new file mode 100644 index 0000000..67179f2 --- /dev/null +++ b/2020-06-29-181553-0160-cppcheck@7993c4636f49_on_notebook_scroll_event/1.html @@ -0,0 +1,2368 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
+ * Copyright (C) 2008 William Jon McCann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <utime.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+#include <canberra-gtk.h>
+#include <libxml/tree.h>
+
+#include "gvc-sound-theme-chooser.h"
+#include "sound-theme-file-utils.h"
+
+struct GvcSoundThemeChooserPrivate
+{
+        GtkWidget *combo_box;
+        GtkWidget *treeview;
+        GtkWidget *theme_box;
+        GtkWidget *selection_box;
+        GtkWidget *click_feedback_button;
+        GSettings *sound_settings;
+};
+
+static void     gvc_sound_theme_chooser_dispose   (GObject            *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSoundThemeChooser, gvc_sound_theme_chooser, GTK_TYPE_BOX)
+
+#define KEY_SOUNDS_SCHEMA          "org.mate.sound"
+#define EVENT_SOUNDS_KEY           "event-sounds"
+#define INPUT_SOUNDS_KEY           "input-feedback-sounds"
+#define SOUND_THEME_KEY            "theme-name"
+
+#define DEFAULT_ALERT_ID        "__default"
+#define CUSTOM_THEME_NAME       "__custom"
+#define NO_SOUNDS_THEME_NAME    "__no_sounds"
+
+enum {
+        THEME_DISPLAY_COL,
+        THEME_IDENTIFIER_COL,
+        THEME_PARENT_ID_COL,
+        THEME_NUM_COLS
+};
+
+enum {
+        ALERT_DISPLAY_COL,
+        ALERT_IDENTIFIER_COL,
+        ALERT_SOUND_TYPE_COL,
+        ALERT_ACTIVE_COL,
+        ALERT_NUM_COLS
+};
+
+enum {
+        SOUND_TYPE_UNSET,
+        SOUND_TYPE_OFF,
+        SOUND_TYPE_DEFAULT_FROM_THEME,
+        SOUND_TYPE_BUILTIN,
+        SOUND_TYPE_CUSTOM
+};
+
+static void
+on_combobox_changed (GtkComboBox          *widget,
+                     GvcSoundThemeChooser *chooser)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        char         *theme_name;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &theme_name, -1);
+
+        g_assert (theme_name != NULL);
+
+        /* It is necessary to update the theme name before any other setting as
+         * the "changed" notification will reload the contents of the widget */
+        g_settings_set_string (chooser->priv->sound_settings, SOUND_THEME_KEY, theme_name);
+
+        /* special case for no sounds */
+        if (strcmp (theme_name, NO_SOUNDS_THEME_NAME) == 0) {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, FALSE);
+                return;
+        } else {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, TRUE);
+        }
+
+        g_free (theme_name);
+
+        /* FIXME: reset alert model */
+}
+
+static char *
+load_index_theme_name (const char *index,
+                       char      **parent)
+{
+        GKeyFile *file;
+        char *indexname = NULL;
+        gboolean hidden;
+
+        file = g_key_file_new ();
+        if (g_key_file_load_from_file (file, index, G_KEY_FILE_KEEP_TRANSLATIONS, NULL) == FALSE) {
+                g_key_file_free (file);
+                return NULL;
+        }
+        /* Don't add hidden themes to the list */
+        hidden = g_key_file_get_boolean (file, "Sound Theme", "Hidden", NULL);
+        if (!hidden) {
+                indexname = g_key_file_get_locale_string (file,
+                                                          "Sound Theme",
+                                                          "Name",
+                                                          NULL,
+                                                          NULL);
+
+                /* Save the parent theme, if there's one */
+                if (parent != NULL) {
+                        *parent = g_key_file_get_string (file,
+                                                         "Sound Theme",
+                                                         "Inherits",
+                                                         NULL);
+                }
+        }
+
+        g_key_file_free (file);
+        return indexname;
+}
+
+static void
+sound_theme_in_dir (GHashTable *hash,
+                    const char *dir)
+{
+        GDir *d;
+        const char *name;
+
+        d = g_dir_open (dir, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *dirname, *index, *indexname;
+
+                /* Look for directories */
+                dirname = g_build_filename (dir, name, NULL);
+                if (g_file_test (dirname, G_FILE_TEST_IS_DIR) == FALSE) {
+                        g_free (dirname);
+                        continue;
+                }
+
+                /* Look for index files */
+                index = g_build_filename (dirname, "index.theme", NULL);
+                g_free (dirname);
+
+                /* Check the name of the theme in the index.theme file */
+                indexname = load_index_theme_name (index, NULL);
+                g_free (index);
+                if (indexname == NULL) {
+                        continue;
+                }
+
+                g_hash_table_insert (hash, g_strdup (name), indexname);
+        }
+
+        g_dir_close (d);
+}
+
+static void
+add_theme_to_store (const char   *key,
+                    const char   *value,
+                    GtkListStore *store)
+{
+        char *parent;
+
+        parent = NULL;
+
+        /* Get the parent, if we're checking the custom theme */
+        if (strcmp (key, CUSTOM_THEME_NAME) == 0) {
+                char *name, *path;
+
+                path = custom_theme_dir_path ("index.theme");
+                name = load_index_theme_name (path, &parent);
+                g_free (name);
+                g_free (path);
+        }
+        gtk_list_store_insert_with_values (store, NULL, G_MAXINT,
+                                           THEME_DISPLAY_COL, value,
+                                           THEME_IDENTIFIER_COL, key,
+                                           THEME_PARENT_ID_COL, parent,
+                                           -1);
+        g_free (parent);
+}
+
+static void
+set_combox_for_theme_name (GvcSoundThemeChooser *chooser,
+                           const char           *name)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        gboolean      found;
+
+        /* If the name is empty, use "freedesktop" */
+        if (name == NULL || *name == '\0') {
+                name = "freedesktop";
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+        if (gtk_tree_model_get_iter_first (model, &iter) == FALSE) {
+                return;
+        }
+
+        do {
+                char *value;
+
+                gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &value, -1);
+                found = (value != NULL && strcmp (value, name) == 0);
+                g_free (value);
+
+        } while (!found && gtk_tree_model_iter_next (model, &iter));
+
+        /* When we can't find the theme we need to set, try to set the default
+         * one "freedesktop" */
+        if (found) {
+                gtk_combo_box_set_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter);
+        } else if (strcmp (name, "freedesktop") != 0) {
+                g_debug ("not found, falling back to fdo");
+                set_combox_for_theme_name (chooser, "freedesktop");
+        }
+}
+
+static void
+set_input_feedback_enabled (GvcSoundThemeChooser *chooser,
+                            gboolean              enabled)
+{
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      enabled);
+}
+
+static void
+setup_theme_selector (GvcSoundThemeChooser *chooser)
+{
+        GHashTable           *hash;
+        GtkListStore         *store;
+        GtkCellRenderer      *renderer;
+        const char * const   *data_dirs;
+        const char           *data_dir;
+        char                 *dir;
+        guint                 i;
+
+        /* Add the theme names and their display name to a hash table,
+         * makes it easy to avoid duplicate themes */
+        hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+        data_dirs = g_get_system_data_dirs ();
+        for (i = 0; data_dirs[i] != NULL; i++) {
+                dir = g_build_filename (data_dirs[i], "sounds", NULL);
+                sound_theme_in_dir (hash, dir);
+                g_free (dir);
+        }
+
+        data_dir = g_get_user_data_dir ();
+        dir = g_build_filename (data_dir, "sounds", NULL);
+        sound_theme_in_dir (hash, dir);
+        g_free (dir);
+
+        /* If there isn't at least one theme, make everything
+         * insensitive, LAME! */
+        if (g_hash_table_size (hash) == 0) {
+                gtk_widget_set_sensitive (GTK_WIDGET (chooser), FALSE);
+                g_warning ("Bad setup, install the freedesktop sound theme");
+                g_hash_table_destroy (hash);
+                return;
+        }
+
+        /* Setup the tree model, 3 columns:
+         * - internal theme name/directory
+         * - display theme name
+         * - the internal id for the parent theme, used for the custom theme */
+        store = gtk_list_store_new (THEME_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING);
+
+        /* Add the themes to a combobox */
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           THEME_DISPLAY_COL, _("No sounds"),
+                                           THEME_IDENTIFIER_COL, "__no_sounds",
+                                           THEME_PARENT_ID_COL, NULL,
+                                           -1);
+        g_hash_table_foreach (hash, (GHFunc) add_theme_to_store, store);
+        g_hash_table_destroy (hash);
+
+        /* Set the display */
+        gtk_combo_box_set_model (GTK_COMBO_BOX (chooser->priv->combo_box),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                    renderer,
+                                    TRUE);
+        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                        renderer,
+                                        "text", THEME_DISPLAY_COL,
+                                        NULL);
+
+        g_signal_connect (G_OBJECT (chooser->priv->combo_box),
+                          "changed",
+                          G_CALLBACK (on_combobox_changed),
+                          chooser);
+}
+
+#define GVC_SOUND_SOUND    (xmlChar *) "sound"
+#define GVC_SOUND_NAME     (xmlChar *) "name"
+#define GVC_SOUND_FILENAME (xmlChar *) "filename"
+
+/* Adapted from yelp-toc-pager.c */
+static xmlChar *
+xml_get_and_trim_names (xmlNodePtr node)
+{
+        xmlNodePtr cur;
+        xmlChar *keep_lang = NULL;
+        xmlChar *value;
+        int j, keep_pri = INT_MAX;
+
+        const gchar * const * langs = g_get_language_names ();
+
+        value = NULL;
+
+        for (cur = node->children; cur; cur = cur->next) {
+                if (! xmlStrcmp (cur->name, GVC_SOUND_NAME)) {
+                        xmlChar *cur_lang = NULL;
+                        int cur_pri = INT_MAX;
+
+                        cur_lang = xmlNodeGetLang (cur);
+
+                        if (cur_lang) {
+                                for (j = 0; langs[j]; j++) {
+                                        if (g_str_equal (cur_lang, langs[j])) {
+                                                cur_pri = j;
+                                                break;
+                                        }
+                                }
+                        } else {
+                                cur_pri = INT_MAX - 1;
+                        }
+
+                        if (cur_pri <= keep_pri) {
+                                if (keep_lang)
+                                        xmlFree (keep_lang);
+                                if (value)
+                                        xmlFree (value);
+
+                                value = xmlNodeGetContent (cur);
+
+                                keep_lang = cur_lang;
+                                keep_pri = cur_pri;
+                        } else {
+                                if (cur_lang)
+                                        xmlFree (cur_lang);
+                        }
+                }
+        }
+
+        /* Delete all GVC_SOUND_NAME nodes */
+        cur = node->children;
+        while (cur) {
+                xmlNodePtr this = cur;
+                cur = cur->next;
+                if (! xmlStrcmp (this->name, GVC_SOUND_NAME)) {
+                        xmlUnlinkNode (this);
+                        xmlFreeNode (this);
+                }
+        }
+
+        return value;
+}
+
+static void
+populate_model_from_node (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          xmlNodePtr            node)
+{
+        xmlNodePtr child;
+        xmlChar   *filename;
+        xmlChar   *name;
+
+        filename = NULL;
+        name = xml_get_and_trim_names (node);
+        for (child = node->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+
+                if (xmlStrcmp (child->name, GVC_SOUND_FILENAME) == 0) {
+                        filename = xmlNodeGetContent (child);
+                } else if (xmlStrcmp (child->name, GVC_SOUND_NAME) == 0) {
+                        /* EH? should have been trimmed */
+                }
+        }
+
+        if (filename != NULL && name != NULL) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   ALERT_IDENTIFIER_COL, filename,
+                                                   ALERT_DISPLAY_COL, name,
+                                                   ALERT_SOUND_TYPE_COL, _("Built-in"),
+                                                   ALERT_ACTIVE_COL, FALSE,
+                                                   -1);
+        }
+
+        xmlFree (filename);
+        xmlFree (name);
+}
+
+static void
+populate_model_from_file (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          const char           *filename)
+{
+        xmlDocPtr  doc;
+        xmlNodePtr root;
+        xmlNodePtr child;
+        gboolean   exists;
+
+        exists = g_file_test (filename, G_FILE_TEST_EXISTS);
+        if (! exists) {
+                return;
+        }
+
+        doc = xmlParseFile (filename);
+        if (doc == NULL) {
+                return;
+        }
+
+        root = xmlDocGetRootElement (doc);
+
+        for (child = root->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+                if (xmlStrcmp (child->name, GVC_SOUND_SOUND) != 0) {
+                        continue;
+                }
+
+                populate_model_from_node (chooser, model, child);
+        }
+
+        xmlFreeDoc (doc);
+}
+
+static void
+populate_model_from_dir (GvcSoundThemeChooser *chooser,
+                         GtkTreeModel         *model,
+                         const char           *dirname)
+{
+        GDir       *d;
+        const char *name;
+
+        d = g_dir_open (dirname, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *path;
+
+                if (! g_str_has_suffix (name, ".xml")) {
+                        continue;
+                }
+
+                path = g_build_filename (dirname, name, NULL);
+                populate_model_from_file (chooser, model, path);
+                g_free (path);
+        }
+
+        g_dir_close (d);
+}
+
+static gboolean
+save_alert_sounds (GvcSoundThemeChooser  *chooser,
+                   const char            *id)
+{
+        const char *sounds[3] = { "bell-terminal", "bell-window-system", NULL };
+        char *path;
+
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+        } else {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+                add_custom_file (sounds, id);
+        }
+
+        /* And poke the directory so the theme gets updated */
+        path = custom_theme_dir_path (NULL);
+        if (utime (path, NULL) != 0) {
+                g_warning ("Failed to update mtime for directory '%s': %s",
+                           path, g_strerror (errno));
+        }
+        g_free (path);
+
+        return FALSE;
+}
+
+
+static void
+update_alert_model (GvcSoundThemeChooser  *chooser,
+                    const char            *id)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        gtk_tree_model_get_iter_first (model, &iter);
+        do {
+                gboolean toggled;
+                char    *this_id;
+
+                gtk_tree_model_get (model, &iter,
+                                    ALERT_IDENTIFIER_COL, &this_id,
+                                    -1);
+
+                if (strcmp (this_id, id) == 0) {
+                        toggled = TRUE;
+                } else {
+                        toggled = FALSE;
+                }
+                g_free (this_id);
+
+                gtk_list_store_set (GTK_LIST_STORE (model),
+                                    &iter,
+                                    ALERT_ACTIVE_COL, toggled,
+                                    -1);
+        } while (gtk_tree_model_iter_next (model, &iter));
+}
+
+static void
+update_alert (GvcSoundThemeChooser *chooser,
+              const char           *alert_id)
+{
+        GtkTreeModel *theme_model;
+        GtkTreeIter   iter;
+        char         *theme;
+        char         *parent;
+        gboolean      is_custom;
+        gboolean      is_default;
+        gboolean      add_custom;
+        gboolean      remove_custom;
+
+        theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        /* Get the current theme's name, and set the parent */
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        gtk_tree_model_get (theme_model, &iter,
+                            THEME_IDENTIFIER_COL, &theme,
+                            THEME_IDENTIFIER_COL, &parent,
+                            -1);
+        is_custom = strcmp (theme, CUSTOM_THEME_NAME) == 0;
+        is_default = strcmp (alert_id, DEFAULT_ALERT_ID) == 0;
+
+        /* So a few possibilities:
+         * 1. Named theme, default alert selected: noop
+         * 2. Named theme, alternate alert selected: create new custom with sound
+         * 3. Custom theme, default alert selected: remove sound and possibly custom
+         * 4. Custom theme, alternate alert selected: update custom sound
+         */
+        add_custom = FALSE;
+        remove_custom = FALSE;
+        if (! is_custom && is_default) {
+                /* remove custom just in case */
+                remove_custom = TRUE;
+        } else if (! is_custom && ! is_default) {
+                create_custom_theme (parent);
+                save_alert_sounds (chooser, alert_id);
+                add_custom = TRUE;
+        } else if (is_custom && is_default) {
+                save_alert_sounds (chooser, alert_id);
+                /* after removing files check if it is empty */
+                if (custom_theme_dir_is_empty ()) {
+                        remove_custom = TRUE;
+                }
+        } else if (is_custom && ! is_default) {
+                save_alert_sounds (chooser, alert_id);
+        }
+
+        if (add_custom) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (theme_model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   THEME_DISPLAY_COL, _("Custom"),
+                                                   THEME_IDENTIFIER_COL, CUSTOM_THEME_NAME,
+                                                   THEME_PARENT_ID_COL, theme,
+                                                   -1);
+                set_combox_for_theme_name (chooser, CUSTOM_THEME_NAME);
+        } else if (remove_custom) {
+                gtk_tree_model_get_iter_first (theme_model, &iter);
+                do {
+                        char *this_parent;
+
+                        gtk_tree_model_get (theme_model, &iter,
+                                            THEME_PARENT_ID_COL, &this_parent,
+                                            -1);
+                        if (this_parent != NULL && strcmp (this_parent, CUSTOM_THEME_NAME) != 0) {
+                                g_free (this_parent);
+                                gtk_list_store_remove (GTK_LIST_STORE (theme_model), &iter);
+                                break;
+                        }
+                        g_free (this_parent);
+                } while (gtk_tree_model_iter_next (theme_model, &iter));
+
+                delete_custom_theme_dir ();
+
+                set_combox_for_theme_name (chooser, parent);
+        }
+
+        update_alert_model (chooser, alert_id);
+
+        g_free (theme);
+        g_free (parent);
+}
+
+static void
+on_alert_toggled (GtkCellRendererToggle *renderer,
+                  char                  *path_str,
+                  GvcSoundThemeChooser  *chooser)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreePath  *path;
+        gboolean      toggled;
+        char         *id;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        path = gtk_tree_path_new_from_string (path_str);
+        gtk_tree_model_get_iter (model, &iter, path);
+        gtk_tree_path_free (path);
+
+        id = NULL;
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            ALERT_ACTIVE_COL, &toggled,
+                            -1);
+
+        toggled ^= 1;
+        if (toggled) {
+                update_alert (chooser, id);
+        }
+
+        g_free (id);
+}
+
+static void
+play_preview_for_path (GvcSoundThemeChooser *chooser, GtkTreePath *path)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreeIter   theme_iter;
+        gchar        *id = NULL;
+        gchar        *parent_theme = NULL;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        if (gtk_tree_model_get_iter (model, &iter, path) == FALSE)
+                return;
+
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            -1);
+        if (id == NULL)
+                return;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &theme_iter)) {
+                GtkTreeModel *theme_model;
+                gchar        *theme_id = NULL;
+                gchar        *parent_id = NULL;
+
+                theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+                gtk_tree_model_get (theme_model, &theme_iter,
+                                    THEME_IDENTIFIER_COL, &theme_id,
+                                    THEME_PARENT_ID_COL, &parent_id, -1);
+                if (theme_id && strcmp (theme_id, CUSTOM_THEME_NAME) == 0)
+                        parent_theme = g_strdup (parent_id);
+
+                g_free (theme_id);
+                g_free (parent_id);
+        }
+
+        /* special case: for the default item on custom themes
+         * play the alert for the parent theme */
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                if (parent_theme != NULL) {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_CANBERRA_XDG_THEME_NAME, parent_theme,
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                } else {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                }
+        } else {
+                ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                        CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                        CA_PROP_MEDIA_FILENAME, id,
+                                        CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                        CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                        CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                        CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                        NULL);
+
+        }
+        g_free (parent_theme);
+        g_free (id);
+}
+
+static void
+on_treeview_row_activated (GtkTreeView          *treeview,
+                           GtkTreePath          *path,
+                           GtkTreeViewColumn    *column,
+                           GvcSoundThemeChooser *chooser)
+{
+        play_preview_for_path (chooser, path);
+}
+
+static void
+on_treeview_selection_changed (GtkTreeSelection     *selection,
+                               GvcSoundThemeChooser *chooser)
+{
+        GList        *paths;
+        GtkTreeModel *model;
+        GtkTreePath  *path;
+
+        if (chooser->priv->treeview == NULL)
+                return;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        paths = gtk_tree_selection_get_selected_rows (selection, &model);
+        if (paths == NULL)
+                return;
+
+        path = paths->data;
+        play_preview_for_path (chooser, path);
+
+        g_list_foreach (paths, (GFunc)gtk_tree_path_free, NULL);
+        g_list_free (paths);
+}
+
+static GtkWidget *
+create_alert_treeview (GvcSoundThemeChooser *chooser)
+{
+        GtkListStore         *store;
+        GtkWidget            *treeview;
+        GtkCellRenderer      *renderer;
+        GtkTreeViewColumn    *column;
+        GtkTreeSelection     *selection;
+
+        treeview = gtk_tree_view_new ();
+
+        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
+        g_signal_connect (G_OBJECT (treeview),
+                          "row-activated",
+                          G_CALLBACK (on_treeview_row_activated),
+                          chooser);
+
+        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+        gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+        g_signal_connect (G_OBJECT (selection),
+                          "changed",
+                          G_CALLBACK (on_treeview_selection_changed),
+                          chooser);
+
+        /* Setup the tree model, 3 columns:
+         * - display name
+         * - sound id
+         * - sound type
+         */
+        store = gtk_list_store_new (ALERT_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_BOOLEAN);
+
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           ALERT_IDENTIFIER_COL, DEFAULT_ALERT_ID,
+                                           ALERT_DISPLAY_COL, _("Default"),
+                                           ALERT_SOUND_TYPE_COL, _("From theme"),
+                                           ALERT_ACTIVE_COL, TRUE,
+                                           -1);
+
+        populate_model_from_dir (chooser, GTK_TREE_MODEL (store), SOUND_SET_DIR);
+
+        gtk_tree_view_set_model (GTK_TREE_VIEW (treeview),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_toggle_new ();
+        gtk_cell_renderer_toggle_set_radio (GTK_CELL_RENDERER_TOGGLE (renderer), TRUE);
+
+        column = gtk_tree_view_column_new_with_attributes (NULL,
+                                                           renderer,
+                                                           "active", ALERT_ACTIVE_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+        g_signal_connect (renderer,
+                          "toggled",
+                          G_CALLBACK (on_alert_toggled),
+                          chooser);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Name"),
+                                                           renderer,
+                                                           "text", ALERT_DISPLAY_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Type"),
+                                                           renderer,
+                                                           "text", ALERT_SOUND_TYPE_COL,
+                                                           NULL);
+
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        return treeview;
+}
+
+static int
+get_file_type (const char *sound_name,
+               char      **linked_name)
+{
+        char *name, *filename;
+
+        *linked_name = NULL;
+
+        name = g_strdup_printf ("%s.disabled", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_REGULAR) != FALSE) {
+                g_free (filename);
+                return SOUND_TYPE_OFF;
+        }
+        g_free (filename);
+
+        /* We only check for .ogg files because those are the
+         * only ones we create */
+        name = g_strdup_printf ("%s.ogg", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_SYMLINK) != FALSE) {
+                *linked_name = g_file_read_link (filename, NULL);
+                g_free (filename);
+                return SOUND_TYPE_CUSTOM;
+        }
+        g_free (filename);
+
+        return SOUND_TYPE_BUILTIN;
+}
+
+static void
+update_alerts_from_theme_name (GvcSoundThemeChooser *chooser,
+                               const gchar          *name)
+{
+        if (strcmp (name, CUSTOM_THEME_NAME) != 0) {
+                /* reset alert to default */
+                update_alert (chooser, DEFAULT_ALERT_ID);
+        } else {
+                int   sound_type;
+                char *linkname;
+
+                linkname = NULL;
+                sound_type = get_file_type ("bell-terminal", &linkname);
+                g_debug ("Found link: %s", linkname);
+                if (sound_type == SOUND_TYPE_CUSTOM) {
+                        update_alert (chooser, linkname);
+                }
+        }
+}
+
+static void
+update_theme (GvcSoundThemeChooser *chooser)
+{
+        char        *theme_name;
+        gboolean     events_enabled;
+        gboolean     feedback_enabled;
+
+        feedback_enabled = g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY);
+        set_input_feedback_enabled (chooser, feedback_enabled);
+
+        events_enabled = g_settings_get_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY);
+        if (events_enabled) {
+                theme_name = g_settings_get_string (chooser->priv->sound_settings, SOUND_THEME_KEY);
+        } else {
+                theme_name = g_strdup (NO_SOUNDS_THEME_NAME);
+        }
+
+        gtk_widget_set_sensitive (chooser->priv->selection_box, events_enabled);
+        gtk_widget_set_sensitive (chooser->priv->click_feedback_button, events_enabled);
+
+        set_combox_for_theme_name (chooser, theme_name);
+
+        update_alerts_from_theme_name (chooser, theme_name);
+
+        g_free (theme_name);
+}
+
+static void
+gvc_sound_theme_chooser_class_init (GvcSoundThemeChooserClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_sound_theme_chooser_dispose;
+}
+
+static void
+on_click_feedback_toggled (GtkToggleButton      *button,
+                           GvcSoundThemeChooser *chooser)
+{
+        gboolean enabled;
+
+        enabled = gtk_toggle_button_get_active (button);
+
+        g_settings_set_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY, enabled);
+}
+
+static void
+on_key_changed (GSettings            *settings,
+                gchar                *key,
+                GvcSoundThemeChooser *chooser)
+{
+        if (!strcmp (key, EVENT_SOUNDS_KEY) ||
+            !strcmp (key, SOUND_THEME_KEY) ||
+            !strcmp (key, INPUT_SOUNDS_KEY))
+                update_theme (chooser);
+}
+
+static void
+setup_list_size_constraint (GtkWidget *widget,
+                            GtkWidget *to_size)
+{
+        GtkRequisition req;
+        gint           sc_height;
+        int            max_height;
+
+        /* Constrain height to be the tree height up to a max */
+        gdk_window_get_geometry (gdk_screen_get_root_window (gtk_widget_get_screen (widget)),
+                                 NULL, NULL, NULL, &sc_height);
+
+        max_height = sc_height / 4;
+
+        // XXX this doesn't work
+        gtk_widget_get_preferred_size (to_size, NULL, &req);
+
+        gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (widget),
+                                                    MIN (req.height, max_height));
+}
+
+static void
+gvc_sound_theme_chooser_init (GvcSoundThemeChooser *chooser)
+{
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *scrolled_window;
+        gchar       *str;
+
+        chooser->priv = gvc_sound_theme_chooser_get_instance_private (chooser);
+
+        chooser->priv->theme_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->theme_box, FALSE, FALSE, 0);
+
+        label = gtk_label_new_with_mnemonic (_("Sound _theme:"));
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), label, FALSE, FALSE, 0);
+        chooser->priv->combo_box = gtk_combo_box_new ();
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), chooser->priv->combo_box, FALSE, FALSE, 6);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->combo_box);
+
+        chooser->priv->sound_settings = g_settings_new (KEY_SOUNDS_SCHEMA);
+
+        g_signal_connect (G_OBJECT (chooser->priv->sound_settings),
+                          "changed",
+                          G_CALLBACK (on_key_changed),
+                          chooser);
+
+        str = g_strdup_printf ("<b>%s</b>", _("C_hoose an alert sound:"));
+        chooser->priv->selection_box = box = gtk_frame_new (str);
+        g_free (str);
+
+        label = gtk_frame_get_label_widget (GTK_FRAME (box));
+        gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
+        gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+        gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
+
+        gtk_box_pack_start (GTK_BOX (chooser), box, TRUE, TRUE, 6);
+
+        chooser->priv->treeview = create_alert_treeview (chooser);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->treeview);
+
+        scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+        gtk_widget_set_hexpand (scrolled_window, TRUE);
+        gtk_widget_set_vexpand (scrolled_window, TRUE);
+        gtk_widget_set_margin_top (scrolled_window, 6);
+
+        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+                                        GTK_POLICY_NEVER,
+                                        GTK_POLICY_AUTOMATIC);
+        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
+                                             GTK_SHADOW_IN);
+
+        gtk_container_add (GTK_CONTAINER (scrolled_window), chooser->priv->treeview);
+        gtk_container_add (GTK_CONTAINER (box), scrolled_window);
+
+        chooser->priv->click_feedback_button = gtk_check_button_new_with_mnemonic (_("Enable _window and button sounds"));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY));
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->click_feedback_button,
+                            FALSE, FALSE, 0);
+
+        g_signal_connect (G_OBJECT (chooser->priv->click_feedback_button),
+                          "toggled",
+                          G_CALLBACK (on_click_feedback_toggled),
+                          chooser);
+
+        setup_theme_selector (chooser);
+        update_theme (chooser);
+
+        setup_list_size_constraint (scrolled_window, chooser->priv->treeview);
+}
+
+static void
+gvc_sound_theme_chooser_dispose (GObject *object)
+{
+        GvcSoundThemeChooser *chooser;
+
+        chooser = GVC_SOUND_THEME_CHOOSER (object);
+
+        g_clear_object (&chooser->priv->sound_settings);
+
+        G_OBJECT_CLASS (gvc_sound_theme_chooser_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_sound_theme_chooser_new (void)
+{
+        return g_object_new (GVC_TYPE_SOUND_THEME_CHOOSER,
+                                "spacing", 6,
+                                "orientation", GTK_ORIENTATION_VERTICAL,
+                                NULL);
+}
+
+
+
+ + + diff --git a/2020-06-29-181553-0160-cppcheck@7993c4636f49_on_notebook_scroll_event/2.html b/2020-06-29-181553-0160-cppcheck@7993c4636f49_on_notebook_scroll_event/2.html new file mode 100644 index 0000000..bacfabb --- /dev/null +++ b/2020-06-29-181553-0160-cppcheck@7993c4636f49_on_notebook_scroll_event/2.html @@ -0,0 +1,1110 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <canberra.h>
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-speaker-test.h"
+#include "gvc-utils.h"
+
+struct _GvcSpeakerTestPrivate
+{
+        GArray           *controls;
+        ca_context       *canberra;
+        MateMixerStream  *stream;
+};
+
+enum {
+        PROP_0,
+        PROP_STREAM,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_speaker_test_dispose    (GObject             *object);
+static void gvc_speaker_test_finalize   (GObject             *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSpeakerTest, gvc_speaker_test, GTK_TYPE_GRID)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+typedef struct {
+        MateMixerChannelPosition position;
+        guint left;
+        guint top;
+} TablePosition;
+
+static const TablePosition positions[] = {
+        /* Position, X, Y */
+        { MATE_MIXER_CHANNEL_FRONT_LEFT, 0, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_LEFT_CENTER, 1, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_CENTER, 2, 0, },
+        { MATE_MIXER_CHANNEL_MONO, 2, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT_CENTER, 3, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT, 4, 0, },
+        { MATE_MIXER_CHANNEL_SIDE_LEFT, 0, 1, },
+        { MATE_MIXER_CHANNEL_SIDE_RIGHT, 4, 1, },
+        { MATE_MIXER_CHANNEL_BACK_LEFT, 0, 2, },
+        { MATE_MIXER_CHANNEL_BACK_CENTER, 2, 2, },
+        { MATE_MIXER_CHANNEL_BACK_RIGHT, 4, 2, },
+        { MATE_MIXER_CHANNEL_LFE, 3, 2 }
+};
+
+MateMixerStream *
+gvc_speaker_test_get_stream (GvcSpeakerTest *test)
+{
+        g_return_val_if_fail (GVC_IS_SPEAKER_TEST (test), NULL);
+
+        return test->priv->stream;
+}
+
+static void
+gvc_speaker_test_set_stream (GvcSpeakerTest *test, MateMixerStream *stream)
+{
+        MateMixerStreamControl *control;
+        const gchar            *name;
+        guint                   i;
+
+        name = mate_mixer_stream_get_name (stream);
+        control = mate_mixer_stream_get_default_control (stream);
+
+        ca_context_change_device (test->priv->canberra, name);
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                gboolean has_position =
+                        mate_mixer_stream_control_has_channel_position (control, positions[i].position);
+
+                gtk_widget_set_visible (g_array_index (test->priv->controls, GtkWidget *, i),
+                                        has_position);
+        }
+
+        test->priv->stream = g_object_ref (stream);
+}
+
+static void
+gvc_speaker_test_set_property (GObject       *object,
+                               guint          prop_id,
+                               const GValue  *value,
+                               GParamSpec    *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                gvc_speaker_test_set_stream (self, g_value_get_object (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_get_property (GObject     *object,
+                               guint        prop_id,
+                               GValue      *value,
+                               GParamSpec  *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                g_value_set_object (value, self->priv->stream);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_class_init (GvcSpeakerTestClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose  = gvc_speaker_test_dispose;
+        object_class->finalize = gvc_speaker_test_finalize;
+        object_class->set_property = gvc_speaker_test_set_property;
+        object_class->get_property = gvc_speaker_test_get_property;
+
+        properties[PROP_STREAM] =
+                g_param_spec_object ("stream",
+                                     "Stream",
+                                     "MateMixer stream",
+                                     MATE_MIXER_TYPE_STREAM,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+}
+
+static const gchar *
+sound_name (MateMixerChannelPosition position)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return "audio-channel-front-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return "audio-channel-front-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return "audio-channel-front-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return "audio-channel-rear-left";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return "audio-channel-rear-right";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return "audio-channel-rear-center";
+        case MATE_MIXER_CHANNEL_LFE:
+                return "audio-channel-lfe";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return "audio-channel-side-left";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return "audio-channel-side-right";
+        default:
+                return NULL;
+        }
+}
+
+static const gchar *
+icon_name (MateMixerChannelPosition position, gboolean playing)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return playing
+                        ? "audio-speaker-left-testing"
+                        : "audio-speaker-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return playing
+                        ? "audio-speaker-right-testing"
+                        : "audio-speaker-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return playing
+                        ? "audio-speaker-center-testing"
+                        : "audio-speaker-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return playing
+                        ? "audio-speaker-left-back-testing"
+                        : "audio-speaker-left-back";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return playing
+                        ? "audio-speaker-right-back-testing"
+                        : "audio-speaker-right-back";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return playing
+                        ? "audio-speaker-center-back-testing"
+                        : "audio-speaker-center-back";
+        case MATE_MIXER_CHANNEL_LFE:
+                return playing
+                        ? "audio-subwoofer-testing"
+                        : "audio-subwoofer";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return playing
+                        ? "audio-speaker-left-side-testing"
+                        : "audio-speaker-left-side";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return playing
+                        ? "audio-speaker-right-side-testing"
+                        : "audio-speaker-right-side";
+        default:
+                return NULL;
+        }
+}
+
+static void
+update_button (GtkWidget *control)
+{
+        GtkWidget *button;
+        GtkWidget *image;
+        gboolean   playing;
+        MateMixerChannelPosition position;
+
+        button = g_object_get_data (G_OBJECT (control), "button");
+        image  = g_object_get_data (G_OBJECT (control), "image");
+
+        position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+        playing  = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        gtk_button_set_label (GTK_BUTTON (button), playing ? _("Stop") : _("Test"));
+
+        gtk_image_set_from_icon_name (GTK_IMAGE (image),
+                                      icon_name (position, playing),
+                                      GTK_ICON_SIZE_DIALOG);
+}
+
+static gboolean
+idle_cb (GtkWidget *control)
+{
+        if (control != NULL) {
+                /* This is called in the background thread, hence forward to main thread
+                 * via idle callback */
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+
+                update_button (control);
+        }
+        return FALSE;
+}
+
+static void
+finish_cb (ca_context *c, uint32_t id, int error_code, void *userdata)
+{
+        GtkWidget *control = (GtkWidget *) userdata;
+
+        if (error_code == CA_ERROR_DESTROYED || control == NULL)
+                return;
+
+        g_idle_add ((GSourceFunc) idle_cb, control);
+}
+
+static void
+on_test_button_clicked (GtkButton *button, GtkWidget *control)
+{
+        gboolean    playing;
+        ca_context *canberra;
+
+        canberra = g_object_get_data (G_OBJECT (control), "canberra");
+
+        ca_context_cancel (canberra, 1);
+
+        playing = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        if (playing) {
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        } else {
+                MateMixerChannelPosition position;
+                const gchar *name;
+                ca_proplist *proplist;
+
+                position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+
+                ca_proplist_create (&proplist);
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_ROLE, "test");
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_NAME,
+                                  gvc_channel_position_to_pretty_string (position));
+                ca_proplist_sets (proplist,
+                                  CA_PROP_CANBERRA_FORCE_CHANNEL,
+                                  gvc_channel_position_to_pulse_string (position));
+
+                ca_proplist_sets (proplist, CA_PROP_CANBERRA_ENABLE, "1");
+
+                name = sound_name (position);
+                if (name != NULL) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, name);
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, "audio-test-signal");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets(proplist, CA_PROP_EVENT_ID, "bell-window-system");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (playing));
+        }
+
+        update_button (control);
+}
+
+static GtkWidget *
+create_control (ca_context *canberra, MateMixerChannelPosition position)
+{
+        GtkWidget   *control;
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *image;
+        GtkWidget   *test_button;
+        const gchar *name;
+
+        control = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+        box     = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        g_object_set_data (G_OBJECT (control), "position", GINT_TO_POINTER (position));
+        g_object_set_data (G_OBJECT (control), "canberra", canberra);
+
+        name = icon_name (position, FALSE);
+        if (name == NULL)
+                name = "audio-volume-medium";
+
+        image = gtk_image_new_from_icon_name (name, GTK_ICON_SIZE_DIALOG);
+        g_object_set_data (G_OBJECT (control), "image", image);
+        gtk_box_pack_start (GTK_BOX (control), image, FALSE, FALSE, 0);
+
+        label = gtk_label_new (gvc_channel_position_to_pretty_string (position));
+        gtk_box_pack_start (GTK_BOX (control), label, FALSE, FALSE, 0);
+
+        test_button = gtk_button_new_with_label (_("Test"));
+        g_signal_connect (G_OBJECT (test_button),
+                          "clicked",
+                          G_CALLBACK (on_test_button_clicked),
+                          control);
+
+        g_object_set_data (G_OBJECT (control), "button", test_button);
+
+        gtk_box_pack_start (GTK_BOX (box), test_button, TRUE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (control), box, FALSE, FALSE, 0);
+
+        gtk_widget_show_all (control);
+
+        return control;
+}
+
+static void
+create_controls (GvcSpeakerTest *test)
+{
+        guint i;
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                GtkWidget *control = create_control (test->priv->canberra, positions[i].position);
+
+                gtk_grid_attach (GTK_GRID (test),
+                                 control,
+                                 positions[i].left,
+                                 positions[i].top,
+                                 1, 1);
+                g_array_insert_val (test->priv->controls, i, control);
+        }
+}
+
+static void
+gvc_speaker_test_init (GvcSpeakerTest *test)
+{
+        GtkWidget *face;
+
+        test->priv = gvc_speaker_test_get_instance_private (test);
+
+        gtk_container_set_border_width (GTK_CONTAINER (test), 12);
+
+        face = gtk_image_new_from_icon_name ("face-smile", GTK_ICON_SIZE_DIALOG);
+
+        gtk_grid_attach (GTK_GRID (test),
+                         face,
+                         1, 1,
+                         3, 1);
+
+
+        gtk_grid_set_baseline_row (GTK_GRID (test), 1);
+        gtk_widget_show (face);
+
+        ca_context_create (&test->priv->canberra);
+
+        /* The test sounds are played for a single channel, set up using the
+         * FORCE_CHANNEL property of libcanberra; this property is only supported
+         * in the PulseAudio backend, so avoid other backends completely */
+        ca_context_set_driver (test->priv->canberra, "pulse");
+
+        ca_context_change_props (test->priv->canberra,
+                                 CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+                                 CA_PROP_APPLICATION_NAME, _("Volume Control"),
+                                 CA_PROP_APPLICATION_VERSION, VERSION,
+                                 CA_PROP_APPLICATION_ICON_NAME, "multimedia-volume-control",
+                                 NULL);
+
+        test->priv->controls = g_array_new (FALSE, FALSE, sizeof (GtkWidget *));
+
+        create_controls (test);
+}
+
+static void
+gvc_speaker_test_dispose (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        g_clear_object (&test->priv->stream);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->dispose (object);
+}
+
+static void
+gvc_speaker_test_finalize (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        ca_context_destroy (test->priv->canberra);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->finalize (object);
+}
+
+GtkWidget *
+gvc_speaker_test_new (MateMixerStream *stream)
+{
+        GObject *test;
+
+        g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL);
+
+        test = g_object_new (GVC_TYPE_SPEAKER_TEST,
+                             "row-spacing", 6,
+                             "column-spacing", 6,
+                             "row-homogeneous", TRUE,
+                             "column-homogeneous", TRUE,
+                             "stream", stream,
+                             NULL);
+
+        return GTK_WIDGET (test);
+}
+
+
+
+ + + diff --git a/2020-06-29-181553-0160-cppcheck@7993c4636f49_on_notebook_scroll_event/index.html b/2020-06-29-181553-0160-cppcheck@7993c4636f49_on_notebook_scroll_event/index.html new file mode 100644 index 0000000..59baeb0 --- /dev/null +++ b/2020-06-29-181553-0160-cppcheck@7993c4636f49_on_notebook_scroll_event/index.html @@ -0,0 +1,108 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
mate-volume-control/gvc-combo-box.c
70unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
mate-volume-control/gvc-sound-theme-chooser.c
735ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
746ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
758ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
mate-volume-control/gvc-speaker-test.c
53unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+ + + diff --git a/2020-06-29-181553-0160-cppcheck@7993c4636f49_on_notebook_scroll_event/stats.html b/2020-06-29-181553-0160-cppcheck@7993c4636f49_on_notebook_scroll_event/stats.html new file mode 100644 index 0000000..3fb6add --- /dev/null +++ b/2020-06-29-181553-0160-cppcheck@7993c4636f49_on_notebook_scroll_event/stats.html @@ -0,0 +1,93 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+

Top 10 files for error severity, total findings: 2
+   1  mate-volume-control/gvc-speaker-test.c
+   1  mate-volume-control/gvc-combo-box.c
+

+

Top 10 files for information severity, total findings: 3
+   3  mate-volume-control/gvc-sound-theme-chooser.c
+

+ +
+ + + diff --git a/2020-06-29-181553-0160-cppcheck@7993c4636f49_on_notebook_scroll_event/style.css b/2020-06-29-181553-0160-cppcheck@7993c4636f49_on_notebook_scroll_event/style.css new file mode 100644 index 0000000..c39571c --- /dev/null +++ b/2020-06-29-181553-0160-cppcheck@7993c4636f49_on_notebook_scroll_event/style.css @@ -0,0 +1,149 @@ + +body { + font: 13px Arial, Verdana, Sans-Serif; + margin: 0; + width: auto; +} + +h1 { + margin: 10px; +} + +#footer > p { + margin: 4px; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + border: 1px dotted black; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #B6B6B4; +} + +.inconclusive2 { + background-color: #B6B6B4; + border: 1px dotted black; + display: inline-block; + margin-left: 4px; +} + +div.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +div.verbose div.content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid black; + background-color: #FFFFCC; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +#header { + border-bottom: thin solid #aaa; +} + +#menu { + float: left; + margin-top: 5px; + text-align: left; + width: 150px; + /*height: 75%;*/ + position: fixed; + overflow: auto; + z-index: 1; +} + +#menu_index { + float: left; + margin-top: 5px; + padding-left: 5px; + text-align: left; + width: 300px; + /*height: 75%;*/ + position: fixed; + overflow: auto; + z-index: 1; +} + +#menu > a { + display: block; + margin-left: 10px; + font: 12px; + z-index: 1; +} + +#filename { + margin-left: 10px; + font: 12px; + z-index: 1; +} + +.highlighttable { + background-color:white; + z-index: 10; + position: relative; + margin: -10 px; +} + +#content { + background-color: white; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + float: left; + margin: 5px; + margin-left: 10px; + padding: 0 10px 10px 10px; + width: 80%; + padding-left: 150px; +} + +#content_index { + background-color: white; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + float: left; + margin: 5px; + margin-left: 10px; + padding: 0 10px 10px 10px; + width: 80%; + padding-left: 300px; +} + +.linenos { + border-right: thin solid #aaa; + color: lightgray; + padding-right: 6px; +} + +#footer { + border-top: thin solid #aaa; + clear: both; + font-size: 90%; + margin-top: 5px; +} + +#footer ul { + list-style-type: none; + padding-left: 0; +} diff --git a/2020-07-08-164015-4803-cppcheck@5ba75b44b5f8_master/0.html b/2020-07-08-164015-4803-cppcheck@5ba75b44b5f8_master/0.html new file mode 100644 index 0000000..e262ed0 --- /dev/null +++ b/2020-07-08-164015-4803-cppcheck@5ba75b44b5f8_master/0.html @@ -0,0 +1,1038 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-combo-box.h"
+
+struct _GvcComboBoxPrivate
+{
+        GtkWidget       *drop_box;
+        GtkWidget       *start_box;
+        GtkWidget       *end_box;
+        GtkWidget       *label;
+        GtkWidget       *button;
+        GtkTreeModel    *model;
+        GtkWidget       *combobox;
+        MateMixerSwitch *swtch;
+};
+
+enum {
+        COL_NAME,
+        COL_HUMAN_NAME,
+        NUM_COLS
+};
+
+enum {
+        CHANGING,
+        BUTTON_CLICKED,
+        LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+enum {
+        PROP_0,
+        PROP_SWITCH,
+        PROP_LABEL,
+        PROP_SHOW_BUTTON,
+        PROP_BUTTON_LABEL,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_combo_box_dispose    (GObject          *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcComboBox, gvc_combo_box, GTK_TYPE_BOX)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+MateMixerSwitch *
+gvc_combo_box_get_switch (GvcComboBox *combobox)
+{
+        g_return_val_if_fail (GVC_IS_COMBO_BOX (combobox), NULL);
+
+        return combobox->priv->swtch;
+}
+
+void
+gvc_combo_box_set_size_group (GvcComboBox  *combobox,
+                              GtkSizeGroup *group,
+                              gboolean      symmetric)
+{
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (GTK_IS_SIZE_GROUP (group));
+
+        if (group != NULL) {
+                gtk_size_group_add_widget (group, combobox->priv->start_box);
+                if (symmetric == TRUE)
+                        gtk_size_group_add_widget (group, combobox->priv->end_box);
+        }
+        gtk_widget_queue_draw (GTK_WIDGET (combobox));
+}
+
+static void
+on_switch_active_option_notify (MateMixerSwitch *swtch,
+                                GParamSpec      *pspec,
+                                GvcComboBox     *combobox)
+{
+        GtkTreeIter            iter;
+        MateMixerSwitchOption *active;
+        gboolean               cont;
+        const gchar           *name;
+
+        active = mate_mixer_switch_get_active_option (swtch);
+        if (G_UNLIKELY (active == NULL)) {
+                g_warn_if_reached ();
+                return;
+        }
+
+        /* Select the newly activated switch option in the combo box */
+        name = mate_mixer_switch_option_get_name (active);
+        cont = gtk_tree_model_get_iter_first (combobox->priv->model, &iter);
+        while (cont == TRUE) {
+                gchar *current;
+
+                gtk_tree_model_get (combobox->priv->model, &iter,
+                                    COL_NAME, &current,
+                                    -1);
+                if (g_strcmp0 (name, current) == 0) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox), &iter);
+                        g_free (current);
+                        return;
+                }
+                g_free (current);
+
+                cont = gtk_tree_model_iter_next (combobox->priv->model, &iter);
+        }
+        g_warning ("Could not find switch option '%s' in combo box", name);
+}
+
+static void
+gvc_combo_box_set_switch (GvcComboBox *combobox, MateMixerSwitch *swtch)
+{
+        MateMixerSwitchOption *active;
+        const GList           *options;
+
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (MATE_MIXER_IS_SWITCH (swtch));
+
+        combobox->priv->swtch = g_object_ref (swtch);
+
+        active  = mate_mixer_switch_get_active_option (swtch);
+        options = mate_mixer_switch_list_options (swtch);
+        while (options != NULL) {
+                GtkTreeIter            iter;
+                MateMixerSwitchOption *option = MATE_MIXER_SWITCH_OPTION (options->data);
+
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (combobox->priv->model),
+                                                   &iter,
+                                                   G_MAXINT,
+                                                   COL_NAME,
+                                                   mate_mixer_switch_option_get_name (option),
+                                                   COL_HUMAN_NAME,
+                                                   mate_mixer_switch_option_get_label (option),
+                                                   -1);
+
+                /* Select the currently active option of the switch */
+                if (option == active) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox),
+                                                       &iter);
+                }
+                options = options->next;
+        }
+
+        g_signal_connect (G_OBJECT (swtch),
+                          "notify::active-option",
+                          G_CALLBACK (on_switch_active_option_notify),
+                          combobox);
+}
+
+static void
+gvc_combo_box_set_property (GObject       *object,
+                            guint          prop_id,
+                            const GValue  *value,
+                            GParamSpec    *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                gvc_combo_box_set_switch (self, g_value_get_object (value));
+                break;
+        case PROP_LABEL:
+                gtk_label_set_text_with_mnemonic (GTK_LABEL (self->priv->label), g_value_get_string (value));
+                break;
+        case PROP_BUTTON_LABEL:
+                gtk_button_set_label (GTK_BUTTON (self->priv->button), g_value_get_string (value));
+                break;
+        case PROP_SHOW_BUTTON:
+                gtk_widget_set_visible (self->priv->button, g_value_get_boolean (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_get_property (GObject     *object,
+                            guint        prop_id,
+                            GValue      *value,
+                            GParamSpec  *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                g_value_set_object (value, self->priv->swtch);
+                break;
+        case PROP_LABEL:
+                g_value_set_string (value, gtk_label_get_text (GTK_LABEL (self->priv->label)));
+                break;
+        case PROP_BUTTON_LABEL:
+                g_value_set_string (value, gtk_button_get_label (GTK_BUTTON (self->priv->button)));
+                break;
+        case PROP_SHOW_BUTTON:
+                g_value_set_boolean (value, gtk_widget_get_visible (self->priv->button));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_class_init (GvcComboBoxClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_combo_box_dispose;
+        object_class->set_property = gvc_combo_box_set_property;
+        object_class->get_property = gvc_combo_box_get_property;
+
+        properties[PROP_SWITCH] =
+                g_param_spec_object ("switch",
+                                     "switch",
+                                     "The MateMixerSwitch",
+                                     MATE_MIXER_TYPE_SWITCH,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_LABEL] =
+                g_param_spec_string ("label",
+                                     "label",
+                                     "The combo box label",
+                                     _("_Profile:"),
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_SHOW_BUTTON] =
+                g_param_spec_boolean ("show-button",
+                                      "show-button",
+                                      "Whether to show the button",
+                                      FALSE,
+                                      G_PARAM_READWRITE |
+                                      G_PARAM_CONSTRUCT |
+                                      G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_BUTTON_LABEL] =
+                g_param_spec_string ("button-label",
+                                     "button-label",
+                                     "The button's label",
+                                     "",
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+
+        signals[CHANGING] =
+                g_signal_new ("changing",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, changing),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__OBJECT,
+                              G_TYPE_NONE,
+                              1,
+                              MATE_MIXER_TYPE_SWITCH_OPTION);
+
+        signals[BUTTON_CLICKED] =
+                g_signal_new ("button-clicked",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, button_clicked),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
+}
+
+static void
+on_combo_box_changed (GtkComboBox *widget, GvcComboBox *combobox)
+{
+        GtkTreeIter            iter;
+        gchar                 *name;
+        MateMixerSwitchOption *option;
+
+        if (G_UNLIKELY (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter) == FALSE))
+                return;
+
+        gtk_tree_model_get (combobox->priv->model, &iter,
+                            COL_NAME, &name,
+                            -1);
+
+        option = mate_mixer_switch_get_option (combobox->priv->swtch, name);
+        if (G_UNLIKELY (option == NULL)) {
+                g_warn_if_reached ();
+                g_free (name);
+                return;
+        }
+
+        /* Inform that we are about to change the active option of the switch */
+        g_signal_emit (combobox, signals[CHANGING], 0, option);
+
+        mate_mixer_switch_set_active_option (combobox->priv->swtch, option);
+        g_free (name);
+}
+
+static void
+on_combo_box_button_clicked (GtkButton *button, GvcComboBox *combobox)
+{
+        /* The meaning of the button is defined by the owner, so only notify
+         * when it is clicked on */
+        g_signal_emit (combobox, signals[BUTTON_CLICKED], 0);
+}
+
+static void
+gvc_combo_box_init (GvcComboBox *combobox)
+{
+        GtkWidget       *frame;
+        GtkCellRenderer *renderer;
+
+        frame = gtk_frame_new (NULL);
+        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
+
+        combobox->priv = gvc_combo_box_get_instance_private (combobox);
+
+        combobox->priv->model = GTK_TREE_MODEL (gtk_list_store_new (NUM_COLS,
+                                                                    G_TYPE_STRING,
+                                                                    G_TYPE_STRING));
+
+        combobox->priv->combobox = gtk_combo_box_new_with_model (combobox->priv->model);
+
+        combobox->priv->label = gtk_label_new (NULL);
+
+        gtk_label_set_xalign (GTK_LABEL (combobox->priv->label), 0.0);
+        gtk_label_set_yalign (GTK_LABEL (combobox->priv->label), 0.5);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (combobox->priv->label),
+                                       combobox->priv->combobox);
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                    renderer,
+                                    FALSE);
+        gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                       renderer,
+                                       "text",
+                                       COL_HUMAN_NAME);
+
+        combobox->priv->drop_box  = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->start_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->end_box   = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+        /* Make sure the combo box does not get too long on long profile names */
+        g_object_set (G_OBJECT (renderer),
+                      "ellipsize",
+                      PANGO_ELLIPSIZE_END,
+                      NULL);
+
+        gtk_combo_box_set_popup_fixed_width (GTK_COMBO_BOX (combobox->priv->combobox), FALSE);
+
+        gtk_box_pack_start (GTK_BOX (combobox),
+                            frame,
+                            TRUE, TRUE, 0);
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->start_box,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->start_box),
+                            combobox->priv->label,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->combobox,
+                            TRUE, TRUE, 0);
+
+        combobox->priv->button = gtk_button_new_with_label ("");
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->button,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->end_box,
+                            FALSE, FALSE, 0);
+
+        gtk_container_add (GTK_CONTAINER (frame), combobox->priv->drop_box);
+
+        g_signal_connect (G_OBJECT (combobox->priv->combobox),
+                          "changed",
+                          G_CALLBACK (on_combo_box_changed),
+                          combobox);
+        g_signal_connect (G_OBJECT (combobox->priv->button),
+                          "clicked",
+                          G_CALLBACK (on_combo_box_button_clicked),
+                          combobox);
+
+        gtk_widget_set_no_show_all (combobox->priv->button, TRUE);
+        gtk_widget_show_all (frame);
+}
+
+static void
+gvc_combo_box_dispose (GObject *object)
+{
+        GvcComboBox *combobox;
+
+        combobox = GVC_COMBO_BOX (object);
+
+        if (G_LIKELY (combobox->priv->swtch != NULL)) {
+                g_signal_handlers_disconnect_by_func (G_OBJECT (combobox->priv->swtch),
+                                                      G_CALLBACK (on_switch_active_option_notify),
+                                                      combobox);
+                g_clear_object (&combobox->priv->swtch);
+        }
+
+        g_clear_object (&combobox->priv->model);
+
+        G_OBJECT_CLASS (gvc_combo_box_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_combo_box_new (MateMixerSwitch *swtch, const gchar *label)
+{
+        return g_object_new (GVC_TYPE_COMBO_BOX,
+                             "switch", swtch,
+                             "label", label,
+                             "orientation", GTK_ORIENTATION_HORIZONTAL,
+                             NULL);
+}
+
+
+
+ + + diff --git a/2020-07-08-164015-4803-cppcheck@5ba75b44b5f8_master/1.html b/2020-07-08-164015-4803-cppcheck@5ba75b44b5f8_master/1.html new file mode 100644 index 0000000..67179f2 --- /dev/null +++ b/2020-07-08-164015-4803-cppcheck@5ba75b44b5f8_master/1.html @@ -0,0 +1,2368 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
+ * Copyright (C) 2008 William Jon McCann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <utime.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+#include <canberra-gtk.h>
+#include <libxml/tree.h>
+
+#include "gvc-sound-theme-chooser.h"
+#include "sound-theme-file-utils.h"
+
+struct GvcSoundThemeChooserPrivate
+{
+        GtkWidget *combo_box;
+        GtkWidget *treeview;
+        GtkWidget *theme_box;
+        GtkWidget *selection_box;
+        GtkWidget *click_feedback_button;
+        GSettings *sound_settings;
+};
+
+static void     gvc_sound_theme_chooser_dispose   (GObject            *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSoundThemeChooser, gvc_sound_theme_chooser, GTK_TYPE_BOX)
+
+#define KEY_SOUNDS_SCHEMA          "org.mate.sound"
+#define EVENT_SOUNDS_KEY           "event-sounds"
+#define INPUT_SOUNDS_KEY           "input-feedback-sounds"
+#define SOUND_THEME_KEY            "theme-name"
+
+#define DEFAULT_ALERT_ID        "__default"
+#define CUSTOM_THEME_NAME       "__custom"
+#define NO_SOUNDS_THEME_NAME    "__no_sounds"
+
+enum {
+        THEME_DISPLAY_COL,
+        THEME_IDENTIFIER_COL,
+        THEME_PARENT_ID_COL,
+        THEME_NUM_COLS
+};
+
+enum {
+        ALERT_DISPLAY_COL,
+        ALERT_IDENTIFIER_COL,
+        ALERT_SOUND_TYPE_COL,
+        ALERT_ACTIVE_COL,
+        ALERT_NUM_COLS
+};
+
+enum {
+        SOUND_TYPE_UNSET,
+        SOUND_TYPE_OFF,
+        SOUND_TYPE_DEFAULT_FROM_THEME,
+        SOUND_TYPE_BUILTIN,
+        SOUND_TYPE_CUSTOM
+};
+
+static void
+on_combobox_changed (GtkComboBox          *widget,
+                     GvcSoundThemeChooser *chooser)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        char         *theme_name;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &theme_name, -1);
+
+        g_assert (theme_name != NULL);
+
+        /* It is necessary to update the theme name before any other setting as
+         * the "changed" notification will reload the contents of the widget */
+        g_settings_set_string (chooser->priv->sound_settings, SOUND_THEME_KEY, theme_name);
+
+        /* special case for no sounds */
+        if (strcmp (theme_name, NO_SOUNDS_THEME_NAME) == 0) {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, FALSE);
+                return;
+        } else {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, TRUE);
+        }
+
+        g_free (theme_name);
+
+        /* FIXME: reset alert model */
+}
+
+static char *
+load_index_theme_name (const char *index,
+                       char      **parent)
+{
+        GKeyFile *file;
+        char *indexname = NULL;
+        gboolean hidden;
+
+        file = g_key_file_new ();
+        if (g_key_file_load_from_file (file, index, G_KEY_FILE_KEEP_TRANSLATIONS, NULL) == FALSE) {
+                g_key_file_free (file);
+                return NULL;
+        }
+        /* Don't add hidden themes to the list */
+        hidden = g_key_file_get_boolean (file, "Sound Theme", "Hidden", NULL);
+        if (!hidden) {
+                indexname = g_key_file_get_locale_string (file,
+                                                          "Sound Theme",
+                                                          "Name",
+                                                          NULL,
+                                                          NULL);
+
+                /* Save the parent theme, if there's one */
+                if (parent != NULL) {
+                        *parent = g_key_file_get_string (file,
+                                                         "Sound Theme",
+                                                         "Inherits",
+                                                         NULL);
+                }
+        }
+
+        g_key_file_free (file);
+        return indexname;
+}
+
+static void
+sound_theme_in_dir (GHashTable *hash,
+                    const char *dir)
+{
+        GDir *d;
+        const char *name;
+
+        d = g_dir_open (dir, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *dirname, *index, *indexname;
+
+                /* Look for directories */
+                dirname = g_build_filename (dir, name, NULL);
+                if (g_file_test (dirname, G_FILE_TEST_IS_DIR) == FALSE) {
+                        g_free (dirname);
+                        continue;
+                }
+
+                /* Look for index files */
+                index = g_build_filename (dirname, "index.theme", NULL);
+                g_free (dirname);
+
+                /* Check the name of the theme in the index.theme file */
+                indexname = load_index_theme_name (index, NULL);
+                g_free (index);
+                if (indexname == NULL) {
+                        continue;
+                }
+
+                g_hash_table_insert (hash, g_strdup (name), indexname);
+        }
+
+        g_dir_close (d);
+}
+
+static void
+add_theme_to_store (const char   *key,
+                    const char   *value,
+                    GtkListStore *store)
+{
+        char *parent;
+
+        parent = NULL;
+
+        /* Get the parent, if we're checking the custom theme */
+        if (strcmp (key, CUSTOM_THEME_NAME) == 0) {
+                char *name, *path;
+
+                path = custom_theme_dir_path ("index.theme");
+                name = load_index_theme_name (path, &parent);
+                g_free (name);
+                g_free (path);
+        }
+        gtk_list_store_insert_with_values (store, NULL, G_MAXINT,
+                                           THEME_DISPLAY_COL, value,
+                                           THEME_IDENTIFIER_COL, key,
+                                           THEME_PARENT_ID_COL, parent,
+                                           -1);
+        g_free (parent);
+}
+
+static void
+set_combox_for_theme_name (GvcSoundThemeChooser *chooser,
+                           const char           *name)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        gboolean      found;
+
+        /* If the name is empty, use "freedesktop" */
+        if (name == NULL || *name == '\0') {
+                name = "freedesktop";
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+        if (gtk_tree_model_get_iter_first (model, &iter) == FALSE) {
+                return;
+        }
+
+        do {
+                char *value;
+
+                gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &value, -1);
+                found = (value != NULL && strcmp (value, name) == 0);
+                g_free (value);
+
+        } while (!found && gtk_tree_model_iter_next (model, &iter));
+
+        /* When we can't find the theme we need to set, try to set the default
+         * one "freedesktop" */
+        if (found) {
+                gtk_combo_box_set_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter);
+        } else if (strcmp (name, "freedesktop") != 0) {
+                g_debug ("not found, falling back to fdo");
+                set_combox_for_theme_name (chooser, "freedesktop");
+        }
+}
+
+static void
+set_input_feedback_enabled (GvcSoundThemeChooser *chooser,
+                            gboolean              enabled)
+{
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      enabled);
+}
+
+static void
+setup_theme_selector (GvcSoundThemeChooser *chooser)
+{
+        GHashTable           *hash;
+        GtkListStore         *store;
+        GtkCellRenderer      *renderer;
+        const char * const   *data_dirs;
+        const char           *data_dir;
+        char                 *dir;
+        guint                 i;
+
+        /* Add the theme names and their display name to a hash table,
+         * makes it easy to avoid duplicate themes */
+        hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+        data_dirs = g_get_system_data_dirs ();
+        for (i = 0; data_dirs[i] != NULL; i++) {
+                dir = g_build_filename (data_dirs[i], "sounds", NULL);
+                sound_theme_in_dir (hash, dir);
+                g_free (dir);
+        }
+
+        data_dir = g_get_user_data_dir ();
+        dir = g_build_filename (data_dir, "sounds", NULL);
+        sound_theme_in_dir (hash, dir);
+        g_free (dir);
+
+        /* If there isn't at least one theme, make everything
+         * insensitive, LAME! */
+        if (g_hash_table_size (hash) == 0) {
+                gtk_widget_set_sensitive (GTK_WIDGET (chooser), FALSE);
+                g_warning ("Bad setup, install the freedesktop sound theme");
+                g_hash_table_destroy (hash);
+                return;
+        }
+
+        /* Setup the tree model, 3 columns:
+         * - internal theme name/directory
+         * - display theme name
+         * - the internal id for the parent theme, used for the custom theme */
+        store = gtk_list_store_new (THEME_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING);
+
+        /* Add the themes to a combobox */
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           THEME_DISPLAY_COL, _("No sounds"),
+                                           THEME_IDENTIFIER_COL, "__no_sounds",
+                                           THEME_PARENT_ID_COL, NULL,
+                                           -1);
+        g_hash_table_foreach (hash, (GHFunc) add_theme_to_store, store);
+        g_hash_table_destroy (hash);
+
+        /* Set the display */
+        gtk_combo_box_set_model (GTK_COMBO_BOX (chooser->priv->combo_box),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                    renderer,
+                                    TRUE);
+        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                        renderer,
+                                        "text", THEME_DISPLAY_COL,
+                                        NULL);
+
+        g_signal_connect (G_OBJECT (chooser->priv->combo_box),
+                          "changed",
+                          G_CALLBACK (on_combobox_changed),
+                          chooser);
+}
+
+#define GVC_SOUND_SOUND    (xmlChar *) "sound"
+#define GVC_SOUND_NAME     (xmlChar *) "name"
+#define GVC_SOUND_FILENAME (xmlChar *) "filename"
+
+/* Adapted from yelp-toc-pager.c */
+static xmlChar *
+xml_get_and_trim_names (xmlNodePtr node)
+{
+        xmlNodePtr cur;
+        xmlChar *keep_lang = NULL;
+        xmlChar *value;
+        int j, keep_pri = INT_MAX;
+
+        const gchar * const * langs = g_get_language_names ();
+
+        value = NULL;
+
+        for (cur = node->children; cur; cur = cur->next) {
+                if (! xmlStrcmp (cur->name, GVC_SOUND_NAME)) {
+                        xmlChar *cur_lang = NULL;
+                        int cur_pri = INT_MAX;
+
+                        cur_lang = xmlNodeGetLang (cur);
+
+                        if (cur_lang) {
+                                for (j = 0; langs[j]; j++) {
+                                        if (g_str_equal (cur_lang, langs[j])) {
+                                                cur_pri = j;
+                                                break;
+                                        }
+                                }
+                        } else {
+                                cur_pri = INT_MAX - 1;
+                        }
+
+                        if (cur_pri <= keep_pri) {
+                                if (keep_lang)
+                                        xmlFree (keep_lang);
+                                if (value)
+                                        xmlFree (value);
+
+                                value = xmlNodeGetContent (cur);
+
+                                keep_lang = cur_lang;
+                                keep_pri = cur_pri;
+                        } else {
+                                if (cur_lang)
+                                        xmlFree (cur_lang);
+                        }
+                }
+        }
+
+        /* Delete all GVC_SOUND_NAME nodes */
+        cur = node->children;
+        while (cur) {
+                xmlNodePtr this = cur;
+                cur = cur->next;
+                if (! xmlStrcmp (this->name, GVC_SOUND_NAME)) {
+                        xmlUnlinkNode (this);
+                        xmlFreeNode (this);
+                }
+        }
+
+        return value;
+}
+
+static void
+populate_model_from_node (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          xmlNodePtr            node)
+{
+        xmlNodePtr child;
+        xmlChar   *filename;
+        xmlChar   *name;
+
+        filename = NULL;
+        name = xml_get_and_trim_names (node);
+        for (child = node->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+
+                if (xmlStrcmp (child->name, GVC_SOUND_FILENAME) == 0) {
+                        filename = xmlNodeGetContent (child);
+                } else if (xmlStrcmp (child->name, GVC_SOUND_NAME) == 0) {
+                        /* EH? should have been trimmed */
+                }
+        }
+
+        if (filename != NULL && name != NULL) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   ALERT_IDENTIFIER_COL, filename,
+                                                   ALERT_DISPLAY_COL, name,
+                                                   ALERT_SOUND_TYPE_COL, _("Built-in"),
+                                                   ALERT_ACTIVE_COL, FALSE,
+                                                   -1);
+        }
+
+        xmlFree (filename);
+        xmlFree (name);
+}
+
+static void
+populate_model_from_file (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          const char           *filename)
+{
+        xmlDocPtr  doc;
+        xmlNodePtr root;
+        xmlNodePtr child;
+        gboolean   exists;
+
+        exists = g_file_test (filename, G_FILE_TEST_EXISTS);
+        if (! exists) {
+                return;
+        }
+
+        doc = xmlParseFile (filename);
+        if (doc == NULL) {
+                return;
+        }
+
+        root = xmlDocGetRootElement (doc);
+
+        for (child = root->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+                if (xmlStrcmp (child->name, GVC_SOUND_SOUND) != 0) {
+                        continue;
+                }
+
+                populate_model_from_node (chooser, model, child);
+        }
+
+        xmlFreeDoc (doc);
+}
+
+static void
+populate_model_from_dir (GvcSoundThemeChooser *chooser,
+                         GtkTreeModel         *model,
+                         const char           *dirname)
+{
+        GDir       *d;
+        const char *name;
+
+        d = g_dir_open (dirname, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *path;
+
+                if (! g_str_has_suffix (name, ".xml")) {
+                        continue;
+                }
+
+                path = g_build_filename (dirname, name, NULL);
+                populate_model_from_file (chooser, model, path);
+                g_free (path);
+        }
+
+        g_dir_close (d);
+}
+
+static gboolean
+save_alert_sounds (GvcSoundThemeChooser  *chooser,
+                   const char            *id)
+{
+        const char *sounds[3] = { "bell-terminal", "bell-window-system", NULL };
+        char *path;
+
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+        } else {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+                add_custom_file (sounds, id);
+        }
+
+        /* And poke the directory so the theme gets updated */
+        path = custom_theme_dir_path (NULL);
+        if (utime (path, NULL) != 0) {
+                g_warning ("Failed to update mtime for directory '%s': %s",
+                           path, g_strerror (errno));
+        }
+        g_free (path);
+
+        return FALSE;
+}
+
+
+static void
+update_alert_model (GvcSoundThemeChooser  *chooser,
+                    const char            *id)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        gtk_tree_model_get_iter_first (model, &iter);
+        do {
+                gboolean toggled;
+                char    *this_id;
+
+                gtk_tree_model_get (model, &iter,
+                                    ALERT_IDENTIFIER_COL, &this_id,
+                                    -1);
+
+                if (strcmp (this_id, id) == 0) {
+                        toggled = TRUE;
+                } else {
+                        toggled = FALSE;
+                }
+                g_free (this_id);
+
+                gtk_list_store_set (GTK_LIST_STORE (model),
+                                    &iter,
+                                    ALERT_ACTIVE_COL, toggled,
+                                    -1);
+        } while (gtk_tree_model_iter_next (model, &iter));
+}
+
+static void
+update_alert (GvcSoundThemeChooser *chooser,
+              const char           *alert_id)
+{
+        GtkTreeModel *theme_model;
+        GtkTreeIter   iter;
+        char         *theme;
+        char         *parent;
+        gboolean      is_custom;
+        gboolean      is_default;
+        gboolean      add_custom;
+        gboolean      remove_custom;
+
+        theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        /* Get the current theme's name, and set the parent */
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        gtk_tree_model_get (theme_model, &iter,
+                            THEME_IDENTIFIER_COL, &theme,
+                            THEME_IDENTIFIER_COL, &parent,
+                            -1);
+        is_custom = strcmp (theme, CUSTOM_THEME_NAME) == 0;
+        is_default = strcmp (alert_id, DEFAULT_ALERT_ID) == 0;
+
+        /* So a few possibilities:
+         * 1. Named theme, default alert selected: noop
+         * 2. Named theme, alternate alert selected: create new custom with sound
+         * 3. Custom theme, default alert selected: remove sound and possibly custom
+         * 4. Custom theme, alternate alert selected: update custom sound
+         */
+        add_custom = FALSE;
+        remove_custom = FALSE;
+        if (! is_custom && is_default) {
+                /* remove custom just in case */
+                remove_custom = TRUE;
+        } else if (! is_custom && ! is_default) {
+                create_custom_theme (parent);
+                save_alert_sounds (chooser, alert_id);
+                add_custom = TRUE;
+        } else if (is_custom && is_default) {
+                save_alert_sounds (chooser, alert_id);
+                /* after removing files check if it is empty */
+                if (custom_theme_dir_is_empty ()) {
+                        remove_custom = TRUE;
+                }
+        } else if (is_custom && ! is_default) {
+                save_alert_sounds (chooser, alert_id);
+        }
+
+        if (add_custom) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (theme_model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   THEME_DISPLAY_COL, _("Custom"),
+                                                   THEME_IDENTIFIER_COL, CUSTOM_THEME_NAME,
+                                                   THEME_PARENT_ID_COL, theme,
+                                                   -1);
+                set_combox_for_theme_name (chooser, CUSTOM_THEME_NAME);
+        } else if (remove_custom) {
+                gtk_tree_model_get_iter_first (theme_model, &iter);
+                do {
+                        char *this_parent;
+
+                        gtk_tree_model_get (theme_model, &iter,
+                                            THEME_PARENT_ID_COL, &this_parent,
+                                            -1);
+                        if (this_parent != NULL && strcmp (this_parent, CUSTOM_THEME_NAME) != 0) {
+                                g_free (this_parent);
+                                gtk_list_store_remove (GTK_LIST_STORE (theme_model), &iter);
+                                break;
+                        }
+                        g_free (this_parent);
+                } while (gtk_tree_model_iter_next (theme_model, &iter));
+
+                delete_custom_theme_dir ();
+
+                set_combox_for_theme_name (chooser, parent);
+        }
+
+        update_alert_model (chooser, alert_id);
+
+        g_free (theme);
+        g_free (parent);
+}
+
+static void
+on_alert_toggled (GtkCellRendererToggle *renderer,
+                  char                  *path_str,
+                  GvcSoundThemeChooser  *chooser)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreePath  *path;
+        gboolean      toggled;
+        char         *id;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        path = gtk_tree_path_new_from_string (path_str);
+        gtk_tree_model_get_iter (model, &iter, path);
+        gtk_tree_path_free (path);
+
+        id = NULL;
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            ALERT_ACTIVE_COL, &toggled,
+                            -1);
+
+        toggled ^= 1;
+        if (toggled) {
+                update_alert (chooser, id);
+        }
+
+        g_free (id);
+}
+
+static void
+play_preview_for_path (GvcSoundThemeChooser *chooser, GtkTreePath *path)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreeIter   theme_iter;
+        gchar        *id = NULL;
+        gchar        *parent_theme = NULL;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        if (gtk_tree_model_get_iter (model, &iter, path) == FALSE)
+                return;
+
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            -1);
+        if (id == NULL)
+                return;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &theme_iter)) {
+                GtkTreeModel *theme_model;
+                gchar        *theme_id = NULL;
+                gchar        *parent_id = NULL;
+
+                theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+                gtk_tree_model_get (theme_model, &theme_iter,
+                                    THEME_IDENTIFIER_COL, &theme_id,
+                                    THEME_PARENT_ID_COL, &parent_id, -1);
+                if (theme_id && strcmp (theme_id, CUSTOM_THEME_NAME) == 0)
+                        parent_theme = g_strdup (parent_id);
+
+                g_free (theme_id);
+                g_free (parent_id);
+        }
+
+        /* special case: for the default item on custom themes
+         * play the alert for the parent theme */
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                if (parent_theme != NULL) {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_CANBERRA_XDG_THEME_NAME, parent_theme,
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                } else {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                }
+        } else {
+                ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                        CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                        CA_PROP_MEDIA_FILENAME, id,
+                                        CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                        CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                        CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                        CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                        NULL);
+
+        }
+        g_free (parent_theme);
+        g_free (id);
+}
+
+static void
+on_treeview_row_activated (GtkTreeView          *treeview,
+                           GtkTreePath          *path,
+                           GtkTreeViewColumn    *column,
+                           GvcSoundThemeChooser *chooser)
+{
+        play_preview_for_path (chooser, path);
+}
+
+static void
+on_treeview_selection_changed (GtkTreeSelection     *selection,
+                               GvcSoundThemeChooser *chooser)
+{
+        GList        *paths;
+        GtkTreeModel *model;
+        GtkTreePath  *path;
+
+        if (chooser->priv->treeview == NULL)
+                return;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        paths = gtk_tree_selection_get_selected_rows (selection, &model);
+        if (paths == NULL)
+                return;
+
+        path = paths->data;
+        play_preview_for_path (chooser, path);
+
+        g_list_foreach (paths, (GFunc)gtk_tree_path_free, NULL);
+        g_list_free (paths);
+}
+
+static GtkWidget *
+create_alert_treeview (GvcSoundThemeChooser *chooser)
+{
+        GtkListStore         *store;
+        GtkWidget            *treeview;
+        GtkCellRenderer      *renderer;
+        GtkTreeViewColumn    *column;
+        GtkTreeSelection     *selection;
+
+        treeview = gtk_tree_view_new ();
+
+        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
+        g_signal_connect (G_OBJECT (treeview),
+                          "row-activated",
+                          G_CALLBACK (on_treeview_row_activated),
+                          chooser);
+
+        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+        gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+        g_signal_connect (G_OBJECT (selection),
+                          "changed",
+                          G_CALLBACK (on_treeview_selection_changed),
+                          chooser);
+
+        /* Setup the tree model, 3 columns:
+         * - display name
+         * - sound id
+         * - sound type
+         */
+        store = gtk_list_store_new (ALERT_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_BOOLEAN);
+
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           ALERT_IDENTIFIER_COL, DEFAULT_ALERT_ID,
+                                           ALERT_DISPLAY_COL, _("Default"),
+                                           ALERT_SOUND_TYPE_COL, _("From theme"),
+                                           ALERT_ACTIVE_COL, TRUE,
+                                           -1);
+
+        populate_model_from_dir (chooser, GTK_TREE_MODEL (store), SOUND_SET_DIR);
+
+        gtk_tree_view_set_model (GTK_TREE_VIEW (treeview),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_toggle_new ();
+        gtk_cell_renderer_toggle_set_radio (GTK_CELL_RENDERER_TOGGLE (renderer), TRUE);
+
+        column = gtk_tree_view_column_new_with_attributes (NULL,
+                                                           renderer,
+                                                           "active", ALERT_ACTIVE_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+        g_signal_connect (renderer,
+                          "toggled",
+                          G_CALLBACK (on_alert_toggled),
+                          chooser);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Name"),
+                                                           renderer,
+                                                           "text", ALERT_DISPLAY_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Type"),
+                                                           renderer,
+                                                           "text", ALERT_SOUND_TYPE_COL,
+                                                           NULL);
+
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        return treeview;
+}
+
+static int
+get_file_type (const char *sound_name,
+               char      **linked_name)
+{
+        char *name, *filename;
+
+        *linked_name = NULL;
+
+        name = g_strdup_printf ("%s.disabled", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_REGULAR) != FALSE) {
+                g_free (filename);
+                return SOUND_TYPE_OFF;
+        }
+        g_free (filename);
+
+        /* We only check for .ogg files because those are the
+         * only ones we create */
+        name = g_strdup_printf ("%s.ogg", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_SYMLINK) != FALSE) {
+                *linked_name = g_file_read_link (filename, NULL);
+                g_free (filename);
+                return SOUND_TYPE_CUSTOM;
+        }
+        g_free (filename);
+
+        return SOUND_TYPE_BUILTIN;
+}
+
+static void
+update_alerts_from_theme_name (GvcSoundThemeChooser *chooser,
+                               const gchar          *name)
+{
+        if (strcmp (name, CUSTOM_THEME_NAME) != 0) {
+                /* reset alert to default */
+                update_alert (chooser, DEFAULT_ALERT_ID);
+        } else {
+                int   sound_type;
+                char *linkname;
+
+                linkname = NULL;
+                sound_type = get_file_type ("bell-terminal", &linkname);
+                g_debug ("Found link: %s", linkname);
+                if (sound_type == SOUND_TYPE_CUSTOM) {
+                        update_alert (chooser, linkname);
+                }
+        }
+}
+
+static void
+update_theme (GvcSoundThemeChooser *chooser)
+{
+        char        *theme_name;
+        gboolean     events_enabled;
+        gboolean     feedback_enabled;
+
+        feedback_enabled = g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY);
+        set_input_feedback_enabled (chooser, feedback_enabled);
+
+        events_enabled = g_settings_get_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY);
+        if (events_enabled) {
+                theme_name = g_settings_get_string (chooser->priv->sound_settings, SOUND_THEME_KEY);
+        } else {
+                theme_name = g_strdup (NO_SOUNDS_THEME_NAME);
+        }
+
+        gtk_widget_set_sensitive (chooser->priv->selection_box, events_enabled);
+        gtk_widget_set_sensitive (chooser->priv->click_feedback_button, events_enabled);
+
+        set_combox_for_theme_name (chooser, theme_name);
+
+        update_alerts_from_theme_name (chooser, theme_name);
+
+        g_free (theme_name);
+}
+
+static void
+gvc_sound_theme_chooser_class_init (GvcSoundThemeChooserClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_sound_theme_chooser_dispose;
+}
+
+static void
+on_click_feedback_toggled (GtkToggleButton      *button,
+                           GvcSoundThemeChooser *chooser)
+{
+        gboolean enabled;
+
+        enabled = gtk_toggle_button_get_active (button);
+
+        g_settings_set_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY, enabled);
+}
+
+static void
+on_key_changed (GSettings            *settings,
+                gchar                *key,
+                GvcSoundThemeChooser *chooser)
+{
+        if (!strcmp (key, EVENT_SOUNDS_KEY) ||
+            !strcmp (key, SOUND_THEME_KEY) ||
+            !strcmp (key, INPUT_SOUNDS_KEY))
+                update_theme (chooser);
+}
+
+static void
+setup_list_size_constraint (GtkWidget *widget,
+                            GtkWidget *to_size)
+{
+        GtkRequisition req;
+        gint           sc_height;
+        int            max_height;
+
+        /* Constrain height to be the tree height up to a max */
+        gdk_window_get_geometry (gdk_screen_get_root_window (gtk_widget_get_screen (widget)),
+                                 NULL, NULL, NULL, &sc_height);
+
+        max_height = sc_height / 4;
+
+        // XXX this doesn't work
+        gtk_widget_get_preferred_size (to_size, NULL, &req);
+
+        gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (widget),
+                                                    MIN (req.height, max_height));
+}
+
+static void
+gvc_sound_theme_chooser_init (GvcSoundThemeChooser *chooser)
+{
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *scrolled_window;
+        gchar       *str;
+
+        chooser->priv = gvc_sound_theme_chooser_get_instance_private (chooser);
+
+        chooser->priv->theme_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->theme_box, FALSE, FALSE, 0);
+
+        label = gtk_label_new_with_mnemonic (_("Sound _theme:"));
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), label, FALSE, FALSE, 0);
+        chooser->priv->combo_box = gtk_combo_box_new ();
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), chooser->priv->combo_box, FALSE, FALSE, 6);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->combo_box);
+
+        chooser->priv->sound_settings = g_settings_new (KEY_SOUNDS_SCHEMA);
+
+        g_signal_connect (G_OBJECT (chooser->priv->sound_settings),
+                          "changed",
+                          G_CALLBACK (on_key_changed),
+                          chooser);
+
+        str = g_strdup_printf ("<b>%s</b>", _("C_hoose an alert sound:"));
+        chooser->priv->selection_box = box = gtk_frame_new (str);
+        g_free (str);
+
+        label = gtk_frame_get_label_widget (GTK_FRAME (box));
+        gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
+        gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+        gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
+
+        gtk_box_pack_start (GTK_BOX (chooser), box, TRUE, TRUE, 6);
+
+        chooser->priv->treeview = create_alert_treeview (chooser);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->treeview);
+
+        scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+        gtk_widget_set_hexpand (scrolled_window, TRUE);
+        gtk_widget_set_vexpand (scrolled_window, TRUE);
+        gtk_widget_set_margin_top (scrolled_window, 6);
+
+        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+                                        GTK_POLICY_NEVER,
+                                        GTK_POLICY_AUTOMATIC);
+        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
+                                             GTK_SHADOW_IN);
+
+        gtk_container_add (GTK_CONTAINER (scrolled_window), chooser->priv->treeview);
+        gtk_container_add (GTK_CONTAINER (box), scrolled_window);
+
+        chooser->priv->click_feedback_button = gtk_check_button_new_with_mnemonic (_("Enable _window and button sounds"));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY));
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->click_feedback_button,
+                            FALSE, FALSE, 0);
+
+        g_signal_connect (G_OBJECT (chooser->priv->click_feedback_button),
+                          "toggled",
+                          G_CALLBACK (on_click_feedback_toggled),
+                          chooser);
+
+        setup_theme_selector (chooser);
+        update_theme (chooser);
+
+        setup_list_size_constraint (scrolled_window, chooser->priv->treeview);
+}
+
+static void
+gvc_sound_theme_chooser_dispose (GObject *object)
+{
+        GvcSoundThemeChooser *chooser;
+
+        chooser = GVC_SOUND_THEME_CHOOSER (object);
+
+        g_clear_object (&chooser->priv->sound_settings);
+
+        G_OBJECT_CLASS (gvc_sound_theme_chooser_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_sound_theme_chooser_new (void)
+{
+        return g_object_new (GVC_TYPE_SOUND_THEME_CHOOSER,
+                                "spacing", 6,
+                                "orientation", GTK_ORIENTATION_VERTICAL,
+                                NULL);
+}
+
+
+
+ + + diff --git a/2020-07-08-164015-4803-cppcheck@5ba75b44b5f8_master/2.html b/2020-07-08-164015-4803-cppcheck@5ba75b44b5f8_master/2.html new file mode 100644 index 0000000..bacfabb --- /dev/null +++ b/2020-07-08-164015-4803-cppcheck@5ba75b44b5f8_master/2.html @@ -0,0 +1,1110 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <canberra.h>
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-speaker-test.h"
+#include "gvc-utils.h"
+
+struct _GvcSpeakerTestPrivate
+{
+        GArray           *controls;
+        ca_context       *canberra;
+        MateMixerStream  *stream;
+};
+
+enum {
+        PROP_0,
+        PROP_STREAM,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_speaker_test_dispose    (GObject             *object);
+static void gvc_speaker_test_finalize   (GObject             *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSpeakerTest, gvc_speaker_test, GTK_TYPE_GRID)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+typedef struct {
+        MateMixerChannelPosition position;
+        guint left;
+        guint top;
+} TablePosition;
+
+static const TablePosition positions[] = {
+        /* Position, X, Y */
+        { MATE_MIXER_CHANNEL_FRONT_LEFT, 0, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_LEFT_CENTER, 1, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_CENTER, 2, 0, },
+        { MATE_MIXER_CHANNEL_MONO, 2, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT_CENTER, 3, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT, 4, 0, },
+        { MATE_MIXER_CHANNEL_SIDE_LEFT, 0, 1, },
+        { MATE_MIXER_CHANNEL_SIDE_RIGHT, 4, 1, },
+        { MATE_MIXER_CHANNEL_BACK_LEFT, 0, 2, },
+        { MATE_MIXER_CHANNEL_BACK_CENTER, 2, 2, },
+        { MATE_MIXER_CHANNEL_BACK_RIGHT, 4, 2, },
+        { MATE_MIXER_CHANNEL_LFE, 3, 2 }
+};
+
+MateMixerStream *
+gvc_speaker_test_get_stream (GvcSpeakerTest *test)
+{
+        g_return_val_if_fail (GVC_IS_SPEAKER_TEST (test), NULL);
+
+        return test->priv->stream;
+}
+
+static void
+gvc_speaker_test_set_stream (GvcSpeakerTest *test, MateMixerStream *stream)
+{
+        MateMixerStreamControl *control;
+        const gchar            *name;
+        guint                   i;
+
+        name = mate_mixer_stream_get_name (stream);
+        control = mate_mixer_stream_get_default_control (stream);
+
+        ca_context_change_device (test->priv->canberra, name);
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                gboolean has_position =
+                        mate_mixer_stream_control_has_channel_position (control, positions[i].position);
+
+                gtk_widget_set_visible (g_array_index (test->priv->controls, GtkWidget *, i),
+                                        has_position);
+        }
+
+        test->priv->stream = g_object_ref (stream);
+}
+
+static void
+gvc_speaker_test_set_property (GObject       *object,
+                               guint          prop_id,
+                               const GValue  *value,
+                               GParamSpec    *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                gvc_speaker_test_set_stream (self, g_value_get_object (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_get_property (GObject     *object,
+                               guint        prop_id,
+                               GValue      *value,
+                               GParamSpec  *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                g_value_set_object (value, self->priv->stream);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_class_init (GvcSpeakerTestClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose  = gvc_speaker_test_dispose;
+        object_class->finalize = gvc_speaker_test_finalize;
+        object_class->set_property = gvc_speaker_test_set_property;
+        object_class->get_property = gvc_speaker_test_get_property;
+
+        properties[PROP_STREAM] =
+                g_param_spec_object ("stream",
+                                     "Stream",
+                                     "MateMixer stream",
+                                     MATE_MIXER_TYPE_STREAM,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+}
+
+static const gchar *
+sound_name (MateMixerChannelPosition position)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return "audio-channel-front-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return "audio-channel-front-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return "audio-channel-front-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return "audio-channel-rear-left";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return "audio-channel-rear-right";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return "audio-channel-rear-center";
+        case MATE_MIXER_CHANNEL_LFE:
+                return "audio-channel-lfe";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return "audio-channel-side-left";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return "audio-channel-side-right";
+        default:
+                return NULL;
+        }
+}
+
+static const gchar *
+icon_name (MateMixerChannelPosition position, gboolean playing)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return playing
+                        ? "audio-speaker-left-testing"
+                        : "audio-speaker-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return playing
+                        ? "audio-speaker-right-testing"
+                        : "audio-speaker-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return playing
+                        ? "audio-speaker-center-testing"
+                        : "audio-speaker-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return playing
+                        ? "audio-speaker-left-back-testing"
+                        : "audio-speaker-left-back";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return playing
+                        ? "audio-speaker-right-back-testing"
+                        : "audio-speaker-right-back";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return playing
+                        ? "audio-speaker-center-back-testing"
+                        : "audio-speaker-center-back";
+        case MATE_MIXER_CHANNEL_LFE:
+                return playing
+                        ? "audio-subwoofer-testing"
+                        : "audio-subwoofer";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return playing
+                        ? "audio-speaker-left-side-testing"
+                        : "audio-speaker-left-side";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return playing
+                        ? "audio-speaker-right-side-testing"
+                        : "audio-speaker-right-side";
+        default:
+                return NULL;
+        }
+}
+
+static void
+update_button (GtkWidget *control)
+{
+        GtkWidget *button;
+        GtkWidget *image;
+        gboolean   playing;
+        MateMixerChannelPosition position;
+
+        button = g_object_get_data (G_OBJECT (control), "button");
+        image  = g_object_get_data (G_OBJECT (control), "image");
+
+        position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+        playing  = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        gtk_button_set_label (GTK_BUTTON (button), playing ? _("Stop") : _("Test"));
+
+        gtk_image_set_from_icon_name (GTK_IMAGE (image),
+                                      icon_name (position, playing),
+                                      GTK_ICON_SIZE_DIALOG);
+}
+
+static gboolean
+idle_cb (GtkWidget *control)
+{
+        if (control != NULL) {
+                /* This is called in the background thread, hence forward to main thread
+                 * via idle callback */
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+
+                update_button (control);
+        }
+        return FALSE;
+}
+
+static void
+finish_cb (ca_context *c, uint32_t id, int error_code, void *userdata)
+{
+        GtkWidget *control = (GtkWidget *) userdata;
+
+        if (error_code == CA_ERROR_DESTROYED || control == NULL)
+                return;
+
+        g_idle_add ((GSourceFunc) idle_cb, control);
+}
+
+static void
+on_test_button_clicked (GtkButton *button, GtkWidget *control)
+{
+        gboolean    playing;
+        ca_context *canberra;
+
+        canberra = g_object_get_data (G_OBJECT (control), "canberra");
+
+        ca_context_cancel (canberra, 1);
+
+        playing = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        if (playing) {
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        } else {
+                MateMixerChannelPosition position;
+                const gchar *name;
+                ca_proplist *proplist;
+
+                position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+
+                ca_proplist_create (&proplist);
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_ROLE, "test");
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_NAME,
+                                  gvc_channel_position_to_pretty_string (position));
+                ca_proplist_sets (proplist,
+                                  CA_PROP_CANBERRA_FORCE_CHANNEL,
+                                  gvc_channel_position_to_pulse_string (position));
+
+                ca_proplist_sets (proplist, CA_PROP_CANBERRA_ENABLE, "1");
+
+                name = sound_name (position);
+                if (name != NULL) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, name);
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, "audio-test-signal");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets(proplist, CA_PROP_EVENT_ID, "bell-window-system");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (playing));
+        }
+
+        update_button (control);
+}
+
+static GtkWidget *
+create_control (ca_context *canberra, MateMixerChannelPosition position)
+{
+        GtkWidget   *control;
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *image;
+        GtkWidget   *test_button;
+        const gchar *name;
+
+        control = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+        box     = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        g_object_set_data (G_OBJECT (control), "position", GINT_TO_POINTER (position));
+        g_object_set_data (G_OBJECT (control), "canberra", canberra);
+
+        name = icon_name (position, FALSE);
+        if (name == NULL)
+                name = "audio-volume-medium";
+
+        image = gtk_image_new_from_icon_name (name, GTK_ICON_SIZE_DIALOG);
+        g_object_set_data (G_OBJECT (control), "image", image);
+        gtk_box_pack_start (GTK_BOX (control), image, FALSE, FALSE, 0);
+
+        label = gtk_label_new (gvc_channel_position_to_pretty_string (position));
+        gtk_box_pack_start (GTK_BOX (control), label, FALSE, FALSE, 0);
+
+        test_button = gtk_button_new_with_label (_("Test"));
+        g_signal_connect (G_OBJECT (test_button),
+                          "clicked",
+                          G_CALLBACK (on_test_button_clicked),
+                          control);
+
+        g_object_set_data (G_OBJECT (control), "button", test_button);
+
+        gtk_box_pack_start (GTK_BOX (box), test_button, TRUE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (control), box, FALSE, FALSE, 0);
+
+        gtk_widget_show_all (control);
+
+        return control;
+}
+
+static void
+create_controls (GvcSpeakerTest *test)
+{
+        guint i;
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                GtkWidget *control = create_control (test->priv->canberra, positions[i].position);
+
+                gtk_grid_attach (GTK_GRID (test),
+                                 control,
+                                 positions[i].left,
+                                 positions[i].top,
+                                 1, 1);
+                g_array_insert_val (test->priv->controls, i, control);
+        }
+}
+
+static void
+gvc_speaker_test_init (GvcSpeakerTest *test)
+{
+        GtkWidget *face;
+
+        test->priv = gvc_speaker_test_get_instance_private (test);
+
+        gtk_container_set_border_width (GTK_CONTAINER (test), 12);
+
+        face = gtk_image_new_from_icon_name ("face-smile", GTK_ICON_SIZE_DIALOG);
+
+        gtk_grid_attach (GTK_GRID (test),
+                         face,
+                         1, 1,
+                         3, 1);
+
+
+        gtk_grid_set_baseline_row (GTK_GRID (test), 1);
+        gtk_widget_show (face);
+
+        ca_context_create (&test->priv->canberra);
+
+        /* The test sounds are played for a single channel, set up using the
+         * FORCE_CHANNEL property of libcanberra; this property is only supported
+         * in the PulseAudio backend, so avoid other backends completely */
+        ca_context_set_driver (test->priv->canberra, "pulse");
+
+        ca_context_change_props (test->priv->canberra,
+                                 CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+                                 CA_PROP_APPLICATION_NAME, _("Volume Control"),
+                                 CA_PROP_APPLICATION_VERSION, VERSION,
+                                 CA_PROP_APPLICATION_ICON_NAME, "multimedia-volume-control",
+                                 NULL);
+
+        test->priv->controls = g_array_new (FALSE, FALSE, sizeof (GtkWidget *));
+
+        create_controls (test);
+}
+
+static void
+gvc_speaker_test_dispose (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        g_clear_object (&test->priv->stream);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->dispose (object);
+}
+
+static void
+gvc_speaker_test_finalize (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        ca_context_destroy (test->priv->canberra);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->finalize (object);
+}
+
+GtkWidget *
+gvc_speaker_test_new (MateMixerStream *stream)
+{
+        GObject *test;
+
+        g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL);
+
+        test = g_object_new (GVC_TYPE_SPEAKER_TEST,
+                             "row-spacing", 6,
+                             "column-spacing", 6,
+                             "row-homogeneous", TRUE,
+                             "column-homogeneous", TRUE,
+                             "stream", stream,
+                             NULL);
+
+        return GTK_WIDGET (test);
+}
+
+
+
+ + + diff --git a/2020-07-08-164015-4803-cppcheck@5ba75b44b5f8_master/index.html b/2020-07-08-164015-4803-cppcheck@5ba75b44b5f8_master/index.html new file mode 100644 index 0000000..59baeb0 --- /dev/null +++ b/2020-07-08-164015-4803-cppcheck@5ba75b44b5f8_master/index.html @@ -0,0 +1,108 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
mate-volume-control/gvc-combo-box.c
70unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
mate-volume-control/gvc-sound-theme-chooser.c
735ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
746ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
758ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
mate-volume-control/gvc-speaker-test.c
53unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+ + + diff --git a/2020-07-08-164015-4803-cppcheck@5ba75b44b5f8_master/stats.html b/2020-07-08-164015-4803-cppcheck@5ba75b44b5f8_master/stats.html new file mode 100644 index 0000000..3fb6add --- /dev/null +++ b/2020-07-08-164015-4803-cppcheck@5ba75b44b5f8_master/stats.html @@ -0,0 +1,93 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+

Top 10 files for error severity, total findings: 2
+   1  mate-volume-control/gvc-speaker-test.c
+   1  mate-volume-control/gvc-combo-box.c
+

+

Top 10 files for information severity, total findings: 3
+   3  mate-volume-control/gvc-sound-theme-chooser.c
+

+ +
+ + + diff --git a/2020-07-08-164015-4803-cppcheck@5ba75b44b5f8_master/style.css b/2020-07-08-164015-4803-cppcheck@5ba75b44b5f8_master/style.css new file mode 100644 index 0000000..c39571c --- /dev/null +++ b/2020-07-08-164015-4803-cppcheck@5ba75b44b5f8_master/style.css @@ -0,0 +1,149 @@ + +body { + font: 13px Arial, Verdana, Sans-Serif; + margin: 0; + width: auto; +} + +h1 { + margin: 10px; +} + +#footer > p { + margin: 4px; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + border: 1px dotted black; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #B6B6B4; +} + +.inconclusive2 { + background-color: #B6B6B4; + border: 1px dotted black; + display: inline-block; + margin-left: 4px; +} + +div.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +div.verbose div.content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid black; + background-color: #FFFFCC; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +#header { + border-bottom: thin solid #aaa; +} + +#menu { + float: left; + margin-top: 5px; + text-align: left; + width: 150px; + /*height: 75%;*/ + position: fixed; + overflow: auto; + z-index: 1; +} + +#menu_index { + float: left; + margin-top: 5px; + padding-left: 5px; + text-align: left; + width: 300px; + /*height: 75%;*/ + position: fixed; + overflow: auto; + z-index: 1; +} + +#menu > a { + display: block; + margin-left: 10px; + font: 12px; + z-index: 1; +} + +#filename { + margin-left: 10px; + font: 12px; + z-index: 1; +} + +.highlighttable { + background-color:white; + z-index: 10; + position: relative; + margin: -10 px; +} + +#content { + background-color: white; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + float: left; + margin: 5px; + margin-left: 10px; + padding: 0 10px 10px 10px; + width: 80%; + padding-left: 150px; +} + +#content_index { + background-color: white; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + float: left; + margin: 5px; + margin-left: 10px; + padding: 0 10px 10px 10px; + width: 80%; + padding-left: 300px; +} + +.linenos { + border-right: thin solid #aaa; + color: lightgray; + padding-right: 6px; +} + +#footer { + border-top: thin solid #aaa; + clear: both; + font-size: 90%; + margin-top: 5px; +} + +#footer ul { + list-style-type: none; + padding-left: 0; +} diff --git a/2020-07-11-174721-5648-cppcheck@b755fd7fe3c4_master/0.html b/2020-07-11-174721-5648-cppcheck@b755fd7fe3c4_master/0.html new file mode 100644 index 0000000..e262ed0 --- /dev/null +++ b/2020-07-11-174721-5648-cppcheck@b755fd7fe3c4_master/0.html @@ -0,0 +1,1038 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-combo-box.h"
+
+struct _GvcComboBoxPrivate
+{
+        GtkWidget       *drop_box;
+        GtkWidget       *start_box;
+        GtkWidget       *end_box;
+        GtkWidget       *label;
+        GtkWidget       *button;
+        GtkTreeModel    *model;
+        GtkWidget       *combobox;
+        MateMixerSwitch *swtch;
+};
+
+enum {
+        COL_NAME,
+        COL_HUMAN_NAME,
+        NUM_COLS
+};
+
+enum {
+        CHANGING,
+        BUTTON_CLICKED,
+        LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+enum {
+        PROP_0,
+        PROP_SWITCH,
+        PROP_LABEL,
+        PROP_SHOW_BUTTON,
+        PROP_BUTTON_LABEL,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_combo_box_dispose    (GObject          *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcComboBox, gvc_combo_box, GTK_TYPE_BOX)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+MateMixerSwitch *
+gvc_combo_box_get_switch (GvcComboBox *combobox)
+{
+        g_return_val_if_fail (GVC_IS_COMBO_BOX (combobox), NULL);
+
+        return combobox->priv->swtch;
+}
+
+void
+gvc_combo_box_set_size_group (GvcComboBox  *combobox,
+                              GtkSizeGroup *group,
+                              gboolean      symmetric)
+{
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (GTK_IS_SIZE_GROUP (group));
+
+        if (group != NULL) {
+                gtk_size_group_add_widget (group, combobox->priv->start_box);
+                if (symmetric == TRUE)
+                        gtk_size_group_add_widget (group, combobox->priv->end_box);
+        }
+        gtk_widget_queue_draw (GTK_WIDGET (combobox));
+}
+
+static void
+on_switch_active_option_notify (MateMixerSwitch *swtch,
+                                GParamSpec      *pspec,
+                                GvcComboBox     *combobox)
+{
+        GtkTreeIter            iter;
+        MateMixerSwitchOption *active;
+        gboolean               cont;
+        const gchar           *name;
+
+        active = mate_mixer_switch_get_active_option (swtch);
+        if (G_UNLIKELY (active == NULL)) {
+                g_warn_if_reached ();
+                return;
+        }
+
+        /* Select the newly activated switch option in the combo box */
+        name = mate_mixer_switch_option_get_name (active);
+        cont = gtk_tree_model_get_iter_first (combobox->priv->model, &iter);
+        while (cont == TRUE) {
+                gchar *current;
+
+                gtk_tree_model_get (combobox->priv->model, &iter,
+                                    COL_NAME, &current,
+                                    -1);
+                if (g_strcmp0 (name, current) == 0) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox), &iter);
+                        g_free (current);
+                        return;
+                }
+                g_free (current);
+
+                cont = gtk_tree_model_iter_next (combobox->priv->model, &iter);
+        }
+        g_warning ("Could not find switch option '%s' in combo box", name);
+}
+
+static void
+gvc_combo_box_set_switch (GvcComboBox *combobox, MateMixerSwitch *swtch)
+{
+        MateMixerSwitchOption *active;
+        const GList           *options;
+
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (MATE_MIXER_IS_SWITCH (swtch));
+
+        combobox->priv->swtch = g_object_ref (swtch);
+
+        active  = mate_mixer_switch_get_active_option (swtch);
+        options = mate_mixer_switch_list_options (swtch);
+        while (options != NULL) {
+                GtkTreeIter            iter;
+                MateMixerSwitchOption *option = MATE_MIXER_SWITCH_OPTION (options->data);
+
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (combobox->priv->model),
+                                                   &iter,
+                                                   G_MAXINT,
+                                                   COL_NAME,
+                                                   mate_mixer_switch_option_get_name (option),
+                                                   COL_HUMAN_NAME,
+                                                   mate_mixer_switch_option_get_label (option),
+                                                   -1);
+
+                /* Select the currently active option of the switch */
+                if (option == active) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox),
+                                                       &iter);
+                }
+                options = options->next;
+        }
+
+        g_signal_connect (G_OBJECT (swtch),
+                          "notify::active-option",
+                          G_CALLBACK (on_switch_active_option_notify),
+                          combobox);
+}
+
+static void
+gvc_combo_box_set_property (GObject       *object,
+                            guint          prop_id,
+                            const GValue  *value,
+                            GParamSpec    *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                gvc_combo_box_set_switch (self, g_value_get_object (value));
+                break;
+        case PROP_LABEL:
+                gtk_label_set_text_with_mnemonic (GTK_LABEL (self->priv->label), g_value_get_string (value));
+                break;
+        case PROP_BUTTON_LABEL:
+                gtk_button_set_label (GTK_BUTTON (self->priv->button), g_value_get_string (value));
+                break;
+        case PROP_SHOW_BUTTON:
+                gtk_widget_set_visible (self->priv->button, g_value_get_boolean (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_get_property (GObject     *object,
+                            guint        prop_id,
+                            GValue      *value,
+                            GParamSpec  *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                g_value_set_object (value, self->priv->swtch);
+                break;
+        case PROP_LABEL:
+                g_value_set_string (value, gtk_label_get_text (GTK_LABEL (self->priv->label)));
+                break;
+        case PROP_BUTTON_LABEL:
+                g_value_set_string (value, gtk_button_get_label (GTK_BUTTON (self->priv->button)));
+                break;
+        case PROP_SHOW_BUTTON:
+                g_value_set_boolean (value, gtk_widget_get_visible (self->priv->button));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_class_init (GvcComboBoxClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_combo_box_dispose;
+        object_class->set_property = gvc_combo_box_set_property;
+        object_class->get_property = gvc_combo_box_get_property;
+
+        properties[PROP_SWITCH] =
+                g_param_spec_object ("switch",
+                                     "switch",
+                                     "The MateMixerSwitch",
+                                     MATE_MIXER_TYPE_SWITCH,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_LABEL] =
+                g_param_spec_string ("label",
+                                     "label",
+                                     "The combo box label",
+                                     _("_Profile:"),
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_SHOW_BUTTON] =
+                g_param_spec_boolean ("show-button",
+                                      "show-button",
+                                      "Whether to show the button",
+                                      FALSE,
+                                      G_PARAM_READWRITE |
+                                      G_PARAM_CONSTRUCT |
+                                      G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_BUTTON_LABEL] =
+                g_param_spec_string ("button-label",
+                                     "button-label",
+                                     "The button's label",
+                                     "",
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+
+        signals[CHANGING] =
+                g_signal_new ("changing",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, changing),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__OBJECT,
+                              G_TYPE_NONE,
+                              1,
+                              MATE_MIXER_TYPE_SWITCH_OPTION);
+
+        signals[BUTTON_CLICKED] =
+                g_signal_new ("button-clicked",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, button_clicked),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
+}
+
+static void
+on_combo_box_changed (GtkComboBox *widget, GvcComboBox *combobox)
+{
+        GtkTreeIter            iter;
+        gchar                 *name;
+        MateMixerSwitchOption *option;
+
+        if (G_UNLIKELY (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter) == FALSE))
+                return;
+
+        gtk_tree_model_get (combobox->priv->model, &iter,
+                            COL_NAME, &name,
+                            -1);
+
+        option = mate_mixer_switch_get_option (combobox->priv->swtch, name);
+        if (G_UNLIKELY (option == NULL)) {
+                g_warn_if_reached ();
+                g_free (name);
+                return;
+        }
+
+        /* Inform that we are about to change the active option of the switch */
+        g_signal_emit (combobox, signals[CHANGING], 0, option);
+
+        mate_mixer_switch_set_active_option (combobox->priv->swtch, option);
+        g_free (name);
+}
+
+static void
+on_combo_box_button_clicked (GtkButton *button, GvcComboBox *combobox)
+{
+        /* The meaning of the button is defined by the owner, so only notify
+         * when it is clicked on */
+        g_signal_emit (combobox, signals[BUTTON_CLICKED], 0);
+}
+
+static void
+gvc_combo_box_init (GvcComboBox *combobox)
+{
+        GtkWidget       *frame;
+        GtkCellRenderer *renderer;
+
+        frame = gtk_frame_new (NULL);
+        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
+
+        combobox->priv = gvc_combo_box_get_instance_private (combobox);
+
+        combobox->priv->model = GTK_TREE_MODEL (gtk_list_store_new (NUM_COLS,
+                                                                    G_TYPE_STRING,
+                                                                    G_TYPE_STRING));
+
+        combobox->priv->combobox = gtk_combo_box_new_with_model (combobox->priv->model);
+
+        combobox->priv->label = gtk_label_new (NULL);
+
+        gtk_label_set_xalign (GTK_LABEL (combobox->priv->label), 0.0);
+        gtk_label_set_yalign (GTK_LABEL (combobox->priv->label), 0.5);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (combobox->priv->label),
+                                       combobox->priv->combobox);
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                    renderer,
+                                    FALSE);
+        gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                       renderer,
+                                       "text",
+                                       COL_HUMAN_NAME);
+
+        combobox->priv->drop_box  = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->start_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->end_box   = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+        /* Make sure the combo box does not get too long on long profile names */
+        g_object_set (G_OBJECT (renderer),
+                      "ellipsize",
+                      PANGO_ELLIPSIZE_END,
+                      NULL);
+
+        gtk_combo_box_set_popup_fixed_width (GTK_COMBO_BOX (combobox->priv->combobox), FALSE);
+
+        gtk_box_pack_start (GTK_BOX (combobox),
+                            frame,
+                            TRUE, TRUE, 0);
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->start_box,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->start_box),
+                            combobox->priv->label,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->combobox,
+                            TRUE, TRUE, 0);
+
+        combobox->priv->button = gtk_button_new_with_label ("");
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->button,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->end_box,
+                            FALSE, FALSE, 0);
+
+        gtk_container_add (GTK_CONTAINER (frame), combobox->priv->drop_box);
+
+        g_signal_connect (G_OBJECT (combobox->priv->combobox),
+                          "changed",
+                          G_CALLBACK (on_combo_box_changed),
+                          combobox);
+        g_signal_connect (G_OBJECT (combobox->priv->button),
+                          "clicked",
+                          G_CALLBACK (on_combo_box_button_clicked),
+                          combobox);
+
+        gtk_widget_set_no_show_all (combobox->priv->button, TRUE);
+        gtk_widget_show_all (frame);
+}
+
+static void
+gvc_combo_box_dispose (GObject *object)
+{
+        GvcComboBox *combobox;
+
+        combobox = GVC_COMBO_BOX (object);
+
+        if (G_LIKELY (combobox->priv->swtch != NULL)) {
+                g_signal_handlers_disconnect_by_func (G_OBJECT (combobox->priv->swtch),
+                                                      G_CALLBACK (on_switch_active_option_notify),
+                                                      combobox);
+                g_clear_object (&combobox->priv->swtch);
+        }
+
+        g_clear_object (&combobox->priv->model);
+
+        G_OBJECT_CLASS (gvc_combo_box_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_combo_box_new (MateMixerSwitch *swtch, const gchar *label)
+{
+        return g_object_new (GVC_TYPE_COMBO_BOX,
+                             "switch", swtch,
+                             "label", label,
+                             "orientation", GTK_ORIENTATION_HORIZONTAL,
+                             NULL);
+}
+
+
+
+ + + diff --git a/2020-07-11-174721-5648-cppcheck@b755fd7fe3c4_master/1.html b/2020-07-11-174721-5648-cppcheck@b755fd7fe3c4_master/1.html new file mode 100644 index 0000000..67179f2 --- /dev/null +++ b/2020-07-11-174721-5648-cppcheck@b755fd7fe3c4_master/1.html @@ -0,0 +1,2368 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
+ * Copyright (C) 2008 William Jon McCann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <utime.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+#include <canberra-gtk.h>
+#include <libxml/tree.h>
+
+#include "gvc-sound-theme-chooser.h"
+#include "sound-theme-file-utils.h"
+
+struct GvcSoundThemeChooserPrivate
+{
+        GtkWidget *combo_box;
+        GtkWidget *treeview;
+        GtkWidget *theme_box;
+        GtkWidget *selection_box;
+        GtkWidget *click_feedback_button;
+        GSettings *sound_settings;
+};
+
+static void     gvc_sound_theme_chooser_dispose   (GObject            *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSoundThemeChooser, gvc_sound_theme_chooser, GTK_TYPE_BOX)
+
+#define KEY_SOUNDS_SCHEMA          "org.mate.sound"
+#define EVENT_SOUNDS_KEY           "event-sounds"
+#define INPUT_SOUNDS_KEY           "input-feedback-sounds"
+#define SOUND_THEME_KEY            "theme-name"
+
+#define DEFAULT_ALERT_ID        "__default"
+#define CUSTOM_THEME_NAME       "__custom"
+#define NO_SOUNDS_THEME_NAME    "__no_sounds"
+
+enum {
+        THEME_DISPLAY_COL,
+        THEME_IDENTIFIER_COL,
+        THEME_PARENT_ID_COL,
+        THEME_NUM_COLS
+};
+
+enum {
+        ALERT_DISPLAY_COL,
+        ALERT_IDENTIFIER_COL,
+        ALERT_SOUND_TYPE_COL,
+        ALERT_ACTIVE_COL,
+        ALERT_NUM_COLS
+};
+
+enum {
+        SOUND_TYPE_UNSET,
+        SOUND_TYPE_OFF,
+        SOUND_TYPE_DEFAULT_FROM_THEME,
+        SOUND_TYPE_BUILTIN,
+        SOUND_TYPE_CUSTOM
+};
+
+static void
+on_combobox_changed (GtkComboBox          *widget,
+                     GvcSoundThemeChooser *chooser)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        char         *theme_name;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &theme_name, -1);
+
+        g_assert (theme_name != NULL);
+
+        /* It is necessary to update the theme name before any other setting as
+         * the "changed" notification will reload the contents of the widget */
+        g_settings_set_string (chooser->priv->sound_settings, SOUND_THEME_KEY, theme_name);
+
+        /* special case for no sounds */
+        if (strcmp (theme_name, NO_SOUNDS_THEME_NAME) == 0) {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, FALSE);
+                return;
+        } else {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, TRUE);
+        }
+
+        g_free (theme_name);
+
+        /* FIXME: reset alert model */
+}
+
+static char *
+load_index_theme_name (const char *index,
+                       char      **parent)
+{
+        GKeyFile *file;
+        char *indexname = NULL;
+        gboolean hidden;
+
+        file = g_key_file_new ();
+        if (g_key_file_load_from_file (file, index, G_KEY_FILE_KEEP_TRANSLATIONS, NULL) == FALSE) {
+                g_key_file_free (file);
+                return NULL;
+        }
+        /* Don't add hidden themes to the list */
+        hidden = g_key_file_get_boolean (file, "Sound Theme", "Hidden", NULL);
+        if (!hidden) {
+                indexname = g_key_file_get_locale_string (file,
+                                                          "Sound Theme",
+                                                          "Name",
+                                                          NULL,
+                                                          NULL);
+
+                /* Save the parent theme, if there's one */
+                if (parent != NULL) {
+                        *parent = g_key_file_get_string (file,
+                                                         "Sound Theme",
+                                                         "Inherits",
+                                                         NULL);
+                }
+        }
+
+        g_key_file_free (file);
+        return indexname;
+}
+
+static void
+sound_theme_in_dir (GHashTable *hash,
+                    const char *dir)
+{
+        GDir *d;
+        const char *name;
+
+        d = g_dir_open (dir, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *dirname, *index, *indexname;
+
+                /* Look for directories */
+                dirname = g_build_filename (dir, name, NULL);
+                if (g_file_test (dirname, G_FILE_TEST_IS_DIR) == FALSE) {
+                        g_free (dirname);
+                        continue;
+                }
+
+                /* Look for index files */
+                index = g_build_filename (dirname, "index.theme", NULL);
+                g_free (dirname);
+
+                /* Check the name of the theme in the index.theme file */
+                indexname = load_index_theme_name (index, NULL);
+                g_free (index);
+                if (indexname == NULL) {
+                        continue;
+                }
+
+                g_hash_table_insert (hash, g_strdup (name), indexname);
+        }
+
+        g_dir_close (d);
+}
+
+static void
+add_theme_to_store (const char   *key,
+                    const char   *value,
+                    GtkListStore *store)
+{
+        char *parent;
+
+        parent = NULL;
+
+        /* Get the parent, if we're checking the custom theme */
+        if (strcmp (key, CUSTOM_THEME_NAME) == 0) {
+                char *name, *path;
+
+                path = custom_theme_dir_path ("index.theme");
+                name = load_index_theme_name (path, &parent);
+                g_free (name);
+                g_free (path);
+        }
+        gtk_list_store_insert_with_values (store, NULL, G_MAXINT,
+                                           THEME_DISPLAY_COL, value,
+                                           THEME_IDENTIFIER_COL, key,
+                                           THEME_PARENT_ID_COL, parent,
+                                           -1);
+        g_free (parent);
+}
+
+static void
+set_combox_for_theme_name (GvcSoundThemeChooser *chooser,
+                           const char           *name)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        gboolean      found;
+
+        /* If the name is empty, use "freedesktop" */
+        if (name == NULL || *name == '\0') {
+                name = "freedesktop";
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+        if (gtk_tree_model_get_iter_first (model, &iter) == FALSE) {
+                return;
+        }
+
+        do {
+                char *value;
+
+                gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &value, -1);
+                found = (value != NULL && strcmp (value, name) == 0);
+                g_free (value);
+
+        } while (!found && gtk_tree_model_iter_next (model, &iter));
+
+        /* When we can't find the theme we need to set, try to set the default
+         * one "freedesktop" */
+        if (found) {
+                gtk_combo_box_set_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter);
+        } else if (strcmp (name, "freedesktop") != 0) {
+                g_debug ("not found, falling back to fdo");
+                set_combox_for_theme_name (chooser, "freedesktop");
+        }
+}
+
+static void
+set_input_feedback_enabled (GvcSoundThemeChooser *chooser,
+                            gboolean              enabled)
+{
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      enabled);
+}
+
+static void
+setup_theme_selector (GvcSoundThemeChooser *chooser)
+{
+        GHashTable           *hash;
+        GtkListStore         *store;
+        GtkCellRenderer      *renderer;
+        const char * const   *data_dirs;
+        const char           *data_dir;
+        char                 *dir;
+        guint                 i;
+
+        /* Add the theme names and their display name to a hash table,
+         * makes it easy to avoid duplicate themes */
+        hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+        data_dirs = g_get_system_data_dirs ();
+        for (i = 0; data_dirs[i] != NULL; i++) {
+                dir = g_build_filename (data_dirs[i], "sounds", NULL);
+                sound_theme_in_dir (hash, dir);
+                g_free (dir);
+        }
+
+        data_dir = g_get_user_data_dir ();
+        dir = g_build_filename (data_dir, "sounds", NULL);
+        sound_theme_in_dir (hash, dir);
+        g_free (dir);
+
+        /* If there isn't at least one theme, make everything
+         * insensitive, LAME! */
+        if (g_hash_table_size (hash) == 0) {
+                gtk_widget_set_sensitive (GTK_WIDGET (chooser), FALSE);
+                g_warning ("Bad setup, install the freedesktop sound theme");
+                g_hash_table_destroy (hash);
+                return;
+        }
+
+        /* Setup the tree model, 3 columns:
+         * - internal theme name/directory
+         * - display theme name
+         * - the internal id for the parent theme, used for the custom theme */
+        store = gtk_list_store_new (THEME_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING);
+
+        /* Add the themes to a combobox */
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           THEME_DISPLAY_COL, _("No sounds"),
+                                           THEME_IDENTIFIER_COL, "__no_sounds",
+                                           THEME_PARENT_ID_COL, NULL,
+                                           -1);
+        g_hash_table_foreach (hash, (GHFunc) add_theme_to_store, store);
+        g_hash_table_destroy (hash);
+
+        /* Set the display */
+        gtk_combo_box_set_model (GTK_COMBO_BOX (chooser->priv->combo_box),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                    renderer,
+                                    TRUE);
+        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                        renderer,
+                                        "text", THEME_DISPLAY_COL,
+                                        NULL);
+
+        g_signal_connect (G_OBJECT (chooser->priv->combo_box),
+                          "changed",
+                          G_CALLBACK (on_combobox_changed),
+                          chooser);
+}
+
+#define GVC_SOUND_SOUND    (xmlChar *) "sound"
+#define GVC_SOUND_NAME     (xmlChar *) "name"
+#define GVC_SOUND_FILENAME (xmlChar *) "filename"
+
+/* Adapted from yelp-toc-pager.c */
+static xmlChar *
+xml_get_and_trim_names (xmlNodePtr node)
+{
+        xmlNodePtr cur;
+        xmlChar *keep_lang = NULL;
+        xmlChar *value;
+        int j, keep_pri = INT_MAX;
+
+        const gchar * const * langs = g_get_language_names ();
+
+        value = NULL;
+
+        for (cur = node->children; cur; cur = cur->next) {
+                if (! xmlStrcmp (cur->name, GVC_SOUND_NAME)) {
+                        xmlChar *cur_lang = NULL;
+                        int cur_pri = INT_MAX;
+
+                        cur_lang = xmlNodeGetLang (cur);
+
+                        if (cur_lang) {
+                                for (j = 0; langs[j]; j++) {
+                                        if (g_str_equal (cur_lang, langs[j])) {
+                                                cur_pri = j;
+                                                break;
+                                        }
+                                }
+                        } else {
+                                cur_pri = INT_MAX - 1;
+                        }
+
+                        if (cur_pri <= keep_pri) {
+                                if (keep_lang)
+                                        xmlFree (keep_lang);
+                                if (value)
+                                        xmlFree (value);
+
+                                value = xmlNodeGetContent (cur);
+
+                                keep_lang = cur_lang;
+                                keep_pri = cur_pri;
+                        } else {
+                                if (cur_lang)
+                                        xmlFree (cur_lang);
+                        }
+                }
+        }
+
+        /* Delete all GVC_SOUND_NAME nodes */
+        cur = node->children;
+        while (cur) {
+                xmlNodePtr this = cur;
+                cur = cur->next;
+                if (! xmlStrcmp (this->name, GVC_SOUND_NAME)) {
+                        xmlUnlinkNode (this);
+                        xmlFreeNode (this);
+                }
+        }
+
+        return value;
+}
+
+static void
+populate_model_from_node (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          xmlNodePtr            node)
+{
+        xmlNodePtr child;
+        xmlChar   *filename;
+        xmlChar   *name;
+
+        filename = NULL;
+        name = xml_get_and_trim_names (node);
+        for (child = node->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+
+                if (xmlStrcmp (child->name, GVC_SOUND_FILENAME) == 0) {
+                        filename = xmlNodeGetContent (child);
+                } else if (xmlStrcmp (child->name, GVC_SOUND_NAME) == 0) {
+                        /* EH? should have been trimmed */
+                }
+        }
+
+        if (filename != NULL && name != NULL) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   ALERT_IDENTIFIER_COL, filename,
+                                                   ALERT_DISPLAY_COL, name,
+                                                   ALERT_SOUND_TYPE_COL, _("Built-in"),
+                                                   ALERT_ACTIVE_COL, FALSE,
+                                                   -1);
+        }
+
+        xmlFree (filename);
+        xmlFree (name);
+}
+
+static void
+populate_model_from_file (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          const char           *filename)
+{
+        xmlDocPtr  doc;
+        xmlNodePtr root;
+        xmlNodePtr child;
+        gboolean   exists;
+
+        exists = g_file_test (filename, G_FILE_TEST_EXISTS);
+        if (! exists) {
+                return;
+        }
+
+        doc = xmlParseFile (filename);
+        if (doc == NULL) {
+                return;
+        }
+
+        root = xmlDocGetRootElement (doc);
+
+        for (child = root->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+                if (xmlStrcmp (child->name, GVC_SOUND_SOUND) != 0) {
+                        continue;
+                }
+
+                populate_model_from_node (chooser, model, child);
+        }
+
+        xmlFreeDoc (doc);
+}
+
+static void
+populate_model_from_dir (GvcSoundThemeChooser *chooser,
+                         GtkTreeModel         *model,
+                         const char           *dirname)
+{
+        GDir       *d;
+        const char *name;
+
+        d = g_dir_open (dirname, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *path;
+
+                if (! g_str_has_suffix (name, ".xml")) {
+                        continue;
+                }
+
+                path = g_build_filename (dirname, name, NULL);
+                populate_model_from_file (chooser, model, path);
+                g_free (path);
+        }
+
+        g_dir_close (d);
+}
+
+static gboolean
+save_alert_sounds (GvcSoundThemeChooser  *chooser,
+                   const char            *id)
+{
+        const char *sounds[3] = { "bell-terminal", "bell-window-system", NULL };
+        char *path;
+
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+        } else {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+                add_custom_file (sounds, id);
+        }
+
+        /* And poke the directory so the theme gets updated */
+        path = custom_theme_dir_path (NULL);
+        if (utime (path, NULL) != 0) {
+                g_warning ("Failed to update mtime for directory '%s': %s",
+                           path, g_strerror (errno));
+        }
+        g_free (path);
+
+        return FALSE;
+}
+
+
+static void
+update_alert_model (GvcSoundThemeChooser  *chooser,
+                    const char            *id)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        gtk_tree_model_get_iter_first (model, &iter);
+        do {
+                gboolean toggled;
+                char    *this_id;
+
+                gtk_tree_model_get (model, &iter,
+                                    ALERT_IDENTIFIER_COL, &this_id,
+                                    -1);
+
+                if (strcmp (this_id, id) == 0) {
+                        toggled = TRUE;
+                } else {
+                        toggled = FALSE;
+                }
+                g_free (this_id);
+
+                gtk_list_store_set (GTK_LIST_STORE (model),
+                                    &iter,
+                                    ALERT_ACTIVE_COL, toggled,
+                                    -1);
+        } while (gtk_tree_model_iter_next (model, &iter));
+}
+
+static void
+update_alert (GvcSoundThemeChooser *chooser,
+              const char           *alert_id)
+{
+        GtkTreeModel *theme_model;
+        GtkTreeIter   iter;
+        char         *theme;
+        char         *parent;
+        gboolean      is_custom;
+        gboolean      is_default;
+        gboolean      add_custom;
+        gboolean      remove_custom;
+
+        theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        /* Get the current theme's name, and set the parent */
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        gtk_tree_model_get (theme_model, &iter,
+                            THEME_IDENTIFIER_COL, &theme,
+                            THEME_IDENTIFIER_COL, &parent,
+                            -1);
+        is_custom = strcmp (theme, CUSTOM_THEME_NAME) == 0;
+        is_default = strcmp (alert_id, DEFAULT_ALERT_ID) == 0;
+
+        /* So a few possibilities:
+         * 1. Named theme, default alert selected: noop
+         * 2. Named theme, alternate alert selected: create new custom with sound
+         * 3. Custom theme, default alert selected: remove sound and possibly custom
+         * 4. Custom theme, alternate alert selected: update custom sound
+         */
+        add_custom = FALSE;
+        remove_custom = FALSE;
+        if (! is_custom && is_default) {
+                /* remove custom just in case */
+                remove_custom = TRUE;
+        } else if (! is_custom && ! is_default) {
+                create_custom_theme (parent);
+                save_alert_sounds (chooser, alert_id);
+                add_custom = TRUE;
+        } else if (is_custom && is_default) {
+                save_alert_sounds (chooser, alert_id);
+                /* after removing files check if it is empty */
+                if (custom_theme_dir_is_empty ()) {
+                        remove_custom = TRUE;
+                }
+        } else if (is_custom && ! is_default) {
+                save_alert_sounds (chooser, alert_id);
+        }
+
+        if (add_custom) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (theme_model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   THEME_DISPLAY_COL, _("Custom"),
+                                                   THEME_IDENTIFIER_COL, CUSTOM_THEME_NAME,
+                                                   THEME_PARENT_ID_COL, theme,
+                                                   -1);
+                set_combox_for_theme_name (chooser, CUSTOM_THEME_NAME);
+        } else if (remove_custom) {
+                gtk_tree_model_get_iter_first (theme_model, &iter);
+                do {
+                        char *this_parent;
+
+                        gtk_tree_model_get (theme_model, &iter,
+                                            THEME_PARENT_ID_COL, &this_parent,
+                                            -1);
+                        if (this_parent != NULL && strcmp (this_parent, CUSTOM_THEME_NAME) != 0) {
+                                g_free (this_parent);
+                                gtk_list_store_remove (GTK_LIST_STORE (theme_model), &iter);
+                                break;
+                        }
+                        g_free (this_parent);
+                } while (gtk_tree_model_iter_next (theme_model, &iter));
+
+                delete_custom_theme_dir ();
+
+                set_combox_for_theme_name (chooser, parent);
+        }
+
+        update_alert_model (chooser, alert_id);
+
+        g_free (theme);
+        g_free (parent);
+}
+
+static void
+on_alert_toggled (GtkCellRendererToggle *renderer,
+                  char                  *path_str,
+                  GvcSoundThemeChooser  *chooser)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreePath  *path;
+        gboolean      toggled;
+        char         *id;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        path = gtk_tree_path_new_from_string (path_str);
+        gtk_tree_model_get_iter (model, &iter, path);
+        gtk_tree_path_free (path);
+
+        id = NULL;
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            ALERT_ACTIVE_COL, &toggled,
+                            -1);
+
+        toggled ^= 1;
+        if (toggled) {
+                update_alert (chooser, id);
+        }
+
+        g_free (id);
+}
+
+static void
+play_preview_for_path (GvcSoundThemeChooser *chooser, GtkTreePath *path)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreeIter   theme_iter;
+        gchar        *id = NULL;
+        gchar        *parent_theme = NULL;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        if (gtk_tree_model_get_iter (model, &iter, path) == FALSE)
+                return;
+
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            -1);
+        if (id == NULL)
+                return;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &theme_iter)) {
+                GtkTreeModel *theme_model;
+                gchar        *theme_id = NULL;
+                gchar        *parent_id = NULL;
+
+                theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+                gtk_tree_model_get (theme_model, &theme_iter,
+                                    THEME_IDENTIFIER_COL, &theme_id,
+                                    THEME_PARENT_ID_COL, &parent_id, -1);
+                if (theme_id && strcmp (theme_id, CUSTOM_THEME_NAME) == 0)
+                        parent_theme = g_strdup (parent_id);
+
+                g_free (theme_id);
+                g_free (parent_id);
+        }
+
+        /* special case: for the default item on custom themes
+         * play the alert for the parent theme */
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                if (parent_theme != NULL) {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_CANBERRA_XDG_THEME_NAME, parent_theme,
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                } else {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                }
+        } else {
+                ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                        CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                        CA_PROP_MEDIA_FILENAME, id,
+                                        CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                        CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                        CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                        CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                        NULL);
+
+        }
+        g_free (parent_theme);
+        g_free (id);
+}
+
+static void
+on_treeview_row_activated (GtkTreeView          *treeview,
+                           GtkTreePath          *path,
+                           GtkTreeViewColumn    *column,
+                           GvcSoundThemeChooser *chooser)
+{
+        play_preview_for_path (chooser, path);
+}
+
+static void
+on_treeview_selection_changed (GtkTreeSelection     *selection,
+                               GvcSoundThemeChooser *chooser)
+{
+        GList        *paths;
+        GtkTreeModel *model;
+        GtkTreePath  *path;
+
+        if (chooser->priv->treeview == NULL)
+                return;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        paths = gtk_tree_selection_get_selected_rows (selection, &model);
+        if (paths == NULL)
+                return;
+
+        path = paths->data;
+        play_preview_for_path (chooser, path);
+
+        g_list_foreach (paths, (GFunc)gtk_tree_path_free, NULL);
+        g_list_free (paths);
+}
+
+static GtkWidget *
+create_alert_treeview (GvcSoundThemeChooser *chooser)
+{
+        GtkListStore         *store;
+        GtkWidget            *treeview;
+        GtkCellRenderer      *renderer;
+        GtkTreeViewColumn    *column;
+        GtkTreeSelection     *selection;
+
+        treeview = gtk_tree_view_new ();
+
+        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
+        g_signal_connect (G_OBJECT (treeview),
+                          "row-activated",
+                          G_CALLBACK (on_treeview_row_activated),
+                          chooser);
+
+        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+        gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+        g_signal_connect (G_OBJECT (selection),
+                          "changed",
+                          G_CALLBACK (on_treeview_selection_changed),
+                          chooser);
+
+        /* Setup the tree model, 3 columns:
+         * - display name
+         * - sound id
+         * - sound type
+         */
+        store = gtk_list_store_new (ALERT_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_BOOLEAN);
+
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           ALERT_IDENTIFIER_COL, DEFAULT_ALERT_ID,
+                                           ALERT_DISPLAY_COL, _("Default"),
+                                           ALERT_SOUND_TYPE_COL, _("From theme"),
+                                           ALERT_ACTIVE_COL, TRUE,
+                                           -1);
+
+        populate_model_from_dir (chooser, GTK_TREE_MODEL (store), SOUND_SET_DIR);
+
+        gtk_tree_view_set_model (GTK_TREE_VIEW (treeview),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_toggle_new ();
+        gtk_cell_renderer_toggle_set_radio (GTK_CELL_RENDERER_TOGGLE (renderer), TRUE);
+
+        column = gtk_tree_view_column_new_with_attributes (NULL,
+                                                           renderer,
+                                                           "active", ALERT_ACTIVE_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+        g_signal_connect (renderer,
+                          "toggled",
+                          G_CALLBACK (on_alert_toggled),
+                          chooser);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Name"),
+                                                           renderer,
+                                                           "text", ALERT_DISPLAY_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Type"),
+                                                           renderer,
+                                                           "text", ALERT_SOUND_TYPE_COL,
+                                                           NULL);
+
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        return treeview;
+}
+
+static int
+get_file_type (const char *sound_name,
+               char      **linked_name)
+{
+        char *name, *filename;
+
+        *linked_name = NULL;
+
+        name = g_strdup_printf ("%s.disabled", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_REGULAR) != FALSE) {
+                g_free (filename);
+                return SOUND_TYPE_OFF;
+        }
+        g_free (filename);
+
+        /* We only check for .ogg files because those are the
+         * only ones we create */
+        name = g_strdup_printf ("%s.ogg", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_SYMLINK) != FALSE) {
+                *linked_name = g_file_read_link (filename, NULL);
+                g_free (filename);
+                return SOUND_TYPE_CUSTOM;
+        }
+        g_free (filename);
+
+        return SOUND_TYPE_BUILTIN;
+}
+
+static void
+update_alerts_from_theme_name (GvcSoundThemeChooser *chooser,
+                               const gchar          *name)
+{
+        if (strcmp (name, CUSTOM_THEME_NAME) != 0) {
+                /* reset alert to default */
+                update_alert (chooser, DEFAULT_ALERT_ID);
+        } else {
+                int   sound_type;
+                char *linkname;
+
+                linkname = NULL;
+                sound_type = get_file_type ("bell-terminal", &linkname);
+                g_debug ("Found link: %s", linkname);
+                if (sound_type == SOUND_TYPE_CUSTOM) {
+                        update_alert (chooser, linkname);
+                }
+        }
+}
+
+static void
+update_theme (GvcSoundThemeChooser *chooser)
+{
+        char        *theme_name;
+        gboolean     events_enabled;
+        gboolean     feedback_enabled;
+
+        feedback_enabled = g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY);
+        set_input_feedback_enabled (chooser, feedback_enabled);
+
+        events_enabled = g_settings_get_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY);
+        if (events_enabled) {
+                theme_name = g_settings_get_string (chooser->priv->sound_settings, SOUND_THEME_KEY);
+        } else {
+                theme_name = g_strdup (NO_SOUNDS_THEME_NAME);
+        }
+
+        gtk_widget_set_sensitive (chooser->priv->selection_box, events_enabled);
+        gtk_widget_set_sensitive (chooser->priv->click_feedback_button, events_enabled);
+
+        set_combox_for_theme_name (chooser, theme_name);
+
+        update_alerts_from_theme_name (chooser, theme_name);
+
+        g_free (theme_name);
+}
+
+static void
+gvc_sound_theme_chooser_class_init (GvcSoundThemeChooserClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_sound_theme_chooser_dispose;
+}
+
+static void
+on_click_feedback_toggled (GtkToggleButton      *button,
+                           GvcSoundThemeChooser *chooser)
+{
+        gboolean enabled;
+
+        enabled = gtk_toggle_button_get_active (button);
+
+        g_settings_set_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY, enabled);
+}
+
+static void
+on_key_changed (GSettings            *settings,
+                gchar                *key,
+                GvcSoundThemeChooser *chooser)
+{
+        if (!strcmp (key, EVENT_SOUNDS_KEY) ||
+            !strcmp (key, SOUND_THEME_KEY) ||
+            !strcmp (key, INPUT_SOUNDS_KEY))
+                update_theme (chooser);
+}
+
+static void
+setup_list_size_constraint (GtkWidget *widget,
+                            GtkWidget *to_size)
+{
+        GtkRequisition req;
+        gint           sc_height;
+        int            max_height;
+
+        /* Constrain height to be the tree height up to a max */
+        gdk_window_get_geometry (gdk_screen_get_root_window (gtk_widget_get_screen (widget)),
+                                 NULL, NULL, NULL, &sc_height);
+
+        max_height = sc_height / 4;
+
+        // XXX this doesn't work
+        gtk_widget_get_preferred_size (to_size, NULL, &req);
+
+        gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (widget),
+                                                    MIN (req.height, max_height));
+}
+
+static void
+gvc_sound_theme_chooser_init (GvcSoundThemeChooser *chooser)
+{
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *scrolled_window;
+        gchar       *str;
+
+        chooser->priv = gvc_sound_theme_chooser_get_instance_private (chooser);
+
+        chooser->priv->theme_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->theme_box, FALSE, FALSE, 0);
+
+        label = gtk_label_new_with_mnemonic (_("Sound _theme:"));
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), label, FALSE, FALSE, 0);
+        chooser->priv->combo_box = gtk_combo_box_new ();
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), chooser->priv->combo_box, FALSE, FALSE, 6);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->combo_box);
+
+        chooser->priv->sound_settings = g_settings_new (KEY_SOUNDS_SCHEMA);
+
+        g_signal_connect (G_OBJECT (chooser->priv->sound_settings),
+                          "changed",
+                          G_CALLBACK (on_key_changed),
+                          chooser);
+
+        str = g_strdup_printf ("<b>%s</b>", _("C_hoose an alert sound:"));
+        chooser->priv->selection_box = box = gtk_frame_new (str);
+        g_free (str);
+
+        label = gtk_frame_get_label_widget (GTK_FRAME (box));
+        gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
+        gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+        gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
+
+        gtk_box_pack_start (GTK_BOX (chooser), box, TRUE, TRUE, 6);
+
+        chooser->priv->treeview = create_alert_treeview (chooser);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->treeview);
+
+        scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+        gtk_widget_set_hexpand (scrolled_window, TRUE);
+        gtk_widget_set_vexpand (scrolled_window, TRUE);
+        gtk_widget_set_margin_top (scrolled_window, 6);
+
+        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+                                        GTK_POLICY_NEVER,
+                                        GTK_POLICY_AUTOMATIC);
+        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
+                                             GTK_SHADOW_IN);
+
+        gtk_container_add (GTK_CONTAINER (scrolled_window), chooser->priv->treeview);
+        gtk_container_add (GTK_CONTAINER (box), scrolled_window);
+
+        chooser->priv->click_feedback_button = gtk_check_button_new_with_mnemonic (_("Enable _window and button sounds"));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY));
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->click_feedback_button,
+                            FALSE, FALSE, 0);
+
+        g_signal_connect (G_OBJECT (chooser->priv->click_feedback_button),
+                          "toggled",
+                          G_CALLBACK (on_click_feedback_toggled),
+                          chooser);
+
+        setup_theme_selector (chooser);
+        update_theme (chooser);
+
+        setup_list_size_constraint (scrolled_window, chooser->priv->treeview);
+}
+
+static void
+gvc_sound_theme_chooser_dispose (GObject *object)
+{
+        GvcSoundThemeChooser *chooser;
+
+        chooser = GVC_SOUND_THEME_CHOOSER (object);
+
+        g_clear_object (&chooser->priv->sound_settings);
+
+        G_OBJECT_CLASS (gvc_sound_theme_chooser_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_sound_theme_chooser_new (void)
+{
+        return g_object_new (GVC_TYPE_SOUND_THEME_CHOOSER,
+                                "spacing", 6,
+                                "orientation", GTK_ORIENTATION_VERTICAL,
+                                NULL);
+}
+
+
+
+ + + diff --git a/2020-07-11-174721-5648-cppcheck@b755fd7fe3c4_master/2.html b/2020-07-11-174721-5648-cppcheck@b755fd7fe3c4_master/2.html new file mode 100644 index 0000000..bacfabb --- /dev/null +++ b/2020-07-11-174721-5648-cppcheck@b755fd7fe3c4_master/2.html @@ -0,0 +1,1110 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <canberra.h>
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-speaker-test.h"
+#include "gvc-utils.h"
+
+struct _GvcSpeakerTestPrivate
+{
+        GArray           *controls;
+        ca_context       *canberra;
+        MateMixerStream  *stream;
+};
+
+enum {
+        PROP_0,
+        PROP_STREAM,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_speaker_test_dispose    (GObject             *object);
+static void gvc_speaker_test_finalize   (GObject             *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSpeakerTest, gvc_speaker_test, GTK_TYPE_GRID)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+typedef struct {
+        MateMixerChannelPosition position;
+        guint left;
+        guint top;
+} TablePosition;
+
+static const TablePosition positions[] = {
+        /* Position, X, Y */
+        { MATE_MIXER_CHANNEL_FRONT_LEFT, 0, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_LEFT_CENTER, 1, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_CENTER, 2, 0, },
+        { MATE_MIXER_CHANNEL_MONO, 2, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT_CENTER, 3, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT, 4, 0, },
+        { MATE_MIXER_CHANNEL_SIDE_LEFT, 0, 1, },
+        { MATE_MIXER_CHANNEL_SIDE_RIGHT, 4, 1, },
+        { MATE_MIXER_CHANNEL_BACK_LEFT, 0, 2, },
+        { MATE_MIXER_CHANNEL_BACK_CENTER, 2, 2, },
+        { MATE_MIXER_CHANNEL_BACK_RIGHT, 4, 2, },
+        { MATE_MIXER_CHANNEL_LFE, 3, 2 }
+};
+
+MateMixerStream *
+gvc_speaker_test_get_stream (GvcSpeakerTest *test)
+{
+        g_return_val_if_fail (GVC_IS_SPEAKER_TEST (test), NULL);
+
+        return test->priv->stream;
+}
+
+static void
+gvc_speaker_test_set_stream (GvcSpeakerTest *test, MateMixerStream *stream)
+{
+        MateMixerStreamControl *control;
+        const gchar            *name;
+        guint                   i;
+
+        name = mate_mixer_stream_get_name (stream);
+        control = mate_mixer_stream_get_default_control (stream);
+
+        ca_context_change_device (test->priv->canberra, name);
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                gboolean has_position =
+                        mate_mixer_stream_control_has_channel_position (control, positions[i].position);
+
+                gtk_widget_set_visible (g_array_index (test->priv->controls, GtkWidget *, i),
+                                        has_position);
+        }
+
+        test->priv->stream = g_object_ref (stream);
+}
+
+static void
+gvc_speaker_test_set_property (GObject       *object,
+                               guint          prop_id,
+                               const GValue  *value,
+                               GParamSpec    *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                gvc_speaker_test_set_stream (self, g_value_get_object (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_get_property (GObject     *object,
+                               guint        prop_id,
+                               GValue      *value,
+                               GParamSpec  *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                g_value_set_object (value, self->priv->stream);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_class_init (GvcSpeakerTestClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose  = gvc_speaker_test_dispose;
+        object_class->finalize = gvc_speaker_test_finalize;
+        object_class->set_property = gvc_speaker_test_set_property;
+        object_class->get_property = gvc_speaker_test_get_property;
+
+        properties[PROP_STREAM] =
+                g_param_spec_object ("stream",
+                                     "Stream",
+                                     "MateMixer stream",
+                                     MATE_MIXER_TYPE_STREAM,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+}
+
+static const gchar *
+sound_name (MateMixerChannelPosition position)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return "audio-channel-front-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return "audio-channel-front-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return "audio-channel-front-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return "audio-channel-rear-left";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return "audio-channel-rear-right";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return "audio-channel-rear-center";
+        case MATE_MIXER_CHANNEL_LFE:
+                return "audio-channel-lfe";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return "audio-channel-side-left";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return "audio-channel-side-right";
+        default:
+                return NULL;
+        }
+}
+
+static const gchar *
+icon_name (MateMixerChannelPosition position, gboolean playing)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return playing
+                        ? "audio-speaker-left-testing"
+                        : "audio-speaker-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return playing
+                        ? "audio-speaker-right-testing"
+                        : "audio-speaker-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return playing
+                        ? "audio-speaker-center-testing"
+                        : "audio-speaker-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return playing
+                        ? "audio-speaker-left-back-testing"
+                        : "audio-speaker-left-back";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return playing
+                        ? "audio-speaker-right-back-testing"
+                        : "audio-speaker-right-back";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return playing
+                        ? "audio-speaker-center-back-testing"
+                        : "audio-speaker-center-back";
+        case MATE_MIXER_CHANNEL_LFE:
+                return playing
+                        ? "audio-subwoofer-testing"
+                        : "audio-subwoofer";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return playing
+                        ? "audio-speaker-left-side-testing"
+                        : "audio-speaker-left-side";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return playing
+                        ? "audio-speaker-right-side-testing"
+                        : "audio-speaker-right-side";
+        default:
+                return NULL;
+        }
+}
+
+static void
+update_button (GtkWidget *control)
+{
+        GtkWidget *button;
+        GtkWidget *image;
+        gboolean   playing;
+        MateMixerChannelPosition position;
+
+        button = g_object_get_data (G_OBJECT (control), "button");
+        image  = g_object_get_data (G_OBJECT (control), "image");
+
+        position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+        playing  = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        gtk_button_set_label (GTK_BUTTON (button), playing ? _("Stop") : _("Test"));
+
+        gtk_image_set_from_icon_name (GTK_IMAGE (image),
+                                      icon_name (position, playing),
+                                      GTK_ICON_SIZE_DIALOG);
+}
+
+static gboolean
+idle_cb (GtkWidget *control)
+{
+        if (control != NULL) {
+                /* This is called in the background thread, hence forward to main thread
+                 * via idle callback */
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+
+                update_button (control);
+        }
+        return FALSE;
+}
+
+static void
+finish_cb (ca_context *c, uint32_t id, int error_code, void *userdata)
+{
+        GtkWidget *control = (GtkWidget *) userdata;
+
+        if (error_code == CA_ERROR_DESTROYED || control == NULL)
+                return;
+
+        g_idle_add ((GSourceFunc) idle_cb, control);
+}
+
+static void
+on_test_button_clicked (GtkButton *button, GtkWidget *control)
+{
+        gboolean    playing;
+        ca_context *canberra;
+
+        canberra = g_object_get_data (G_OBJECT (control), "canberra");
+
+        ca_context_cancel (canberra, 1);
+
+        playing = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        if (playing) {
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        } else {
+                MateMixerChannelPosition position;
+                const gchar *name;
+                ca_proplist *proplist;
+
+                position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+
+                ca_proplist_create (&proplist);
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_ROLE, "test");
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_NAME,
+                                  gvc_channel_position_to_pretty_string (position));
+                ca_proplist_sets (proplist,
+                                  CA_PROP_CANBERRA_FORCE_CHANNEL,
+                                  gvc_channel_position_to_pulse_string (position));
+
+                ca_proplist_sets (proplist, CA_PROP_CANBERRA_ENABLE, "1");
+
+                name = sound_name (position);
+                if (name != NULL) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, name);
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, "audio-test-signal");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets(proplist, CA_PROP_EVENT_ID, "bell-window-system");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (playing));
+        }
+
+        update_button (control);
+}
+
+static GtkWidget *
+create_control (ca_context *canberra, MateMixerChannelPosition position)
+{
+        GtkWidget   *control;
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *image;
+        GtkWidget   *test_button;
+        const gchar *name;
+
+        control = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+        box     = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        g_object_set_data (G_OBJECT (control), "position", GINT_TO_POINTER (position));
+        g_object_set_data (G_OBJECT (control), "canberra", canberra);
+
+        name = icon_name (position, FALSE);
+        if (name == NULL)
+                name = "audio-volume-medium";
+
+        image = gtk_image_new_from_icon_name (name, GTK_ICON_SIZE_DIALOG);
+        g_object_set_data (G_OBJECT (control), "image", image);
+        gtk_box_pack_start (GTK_BOX (control), image, FALSE, FALSE, 0);
+
+        label = gtk_label_new (gvc_channel_position_to_pretty_string (position));
+        gtk_box_pack_start (GTK_BOX (control), label, FALSE, FALSE, 0);
+
+        test_button = gtk_button_new_with_label (_("Test"));
+        g_signal_connect (G_OBJECT (test_button),
+                          "clicked",
+                          G_CALLBACK (on_test_button_clicked),
+                          control);
+
+        g_object_set_data (G_OBJECT (control), "button", test_button);
+
+        gtk_box_pack_start (GTK_BOX (box), test_button, TRUE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (control), box, FALSE, FALSE, 0);
+
+        gtk_widget_show_all (control);
+
+        return control;
+}
+
+static void
+create_controls (GvcSpeakerTest *test)
+{
+        guint i;
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                GtkWidget *control = create_control (test->priv->canberra, positions[i].position);
+
+                gtk_grid_attach (GTK_GRID (test),
+                                 control,
+                                 positions[i].left,
+                                 positions[i].top,
+                                 1, 1);
+                g_array_insert_val (test->priv->controls, i, control);
+        }
+}
+
+static void
+gvc_speaker_test_init (GvcSpeakerTest *test)
+{
+        GtkWidget *face;
+
+        test->priv = gvc_speaker_test_get_instance_private (test);
+
+        gtk_container_set_border_width (GTK_CONTAINER (test), 12);
+
+        face = gtk_image_new_from_icon_name ("face-smile", GTK_ICON_SIZE_DIALOG);
+
+        gtk_grid_attach (GTK_GRID (test),
+                         face,
+                         1, 1,
+                         3, 1);
+
+
+        gtk_grid_set_baseline_row (GTK_GRID (test), 1);
+        gtk_widget_show (face);
+
+        ca_context_create (&test->priv->canberra);
+
+        /* The test sounds are played for a single channel, set up using the
+         * FORCE_CHANNEL property of libcanberra; this property is only supported
+         * in the PulseAudio backend, so avoid other backends completely */
+        ca_context_set_driver (test->priv->canberra, "pulse");
+
+        ca_context_change_props (test->priv->canberra,
+                                 CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+                                 CA_PROP_APPLICATION_NAME, _("Volume Control"),
+                                 CA_PROP_APPLICATION_VERSION, VERSION,
+                                 CA_PROP_APPLICATION_ICON_NAME, "multimedia-volume-control",
+                                 NULL);
+
+        test->priv->controls = g_array_new (FALSE, FALSE, sizeof (GtkWidget *));
+
+        create_controls (test);
+}
+
+static void
+gvc_speaker_test_dispose (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        g_clear_object (&test->priv->stream);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->dispose (object);
+}
+
+static void
+gvc_speaker_test_finalize (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        ca_context_destroy (test->priv->canberra);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->finalize (object);
+}
+
+GtkWidget *
+gvc_speaker_test_new (MateMixerStream *stream)
+{
+        GObject *test;
+
+        g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL);
+
+        test = g_object_new (GVC_TYPE_SPEAKER_TEST,
+                             "row-spacing", 6,
+                             "column-spacing", 6,
+                             "row-homogeneous", TRUE,
+                             "column-homogeneous", TRUE,
+                             "stream", stream,
+                             NULL);
+
+        return GTK_WIDGET (test);
+}
+
+
+
+ + + diff --git a/2020-07-11-174721-5648-cppcheck@b755fd7fe3c4_master/index.html b/2020-07-11-174721-5648-cppcheck@b755fd7fe3c4_master/index.html new file mode 100644 index 0000000..59baeb0 --- /dev/null +++ b/2020-07-11-174721-5648-cppcheck@b755fd7fe3c4_master/index.html @@ -0,0 +1,108 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
mate-volume-control/gvc-combo-box.c
70unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
mate-volume-control/gvc-sound-theme-chooser.c
735ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
746ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
758ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
mate-volume-control/gvc-speaker-test.c
53unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+ + + diff --git a/2020-07-11-174721-5648-cppcheck@b755fd7fe3c4_master/stats.html b/2020-07-11-174721-5648-cppcheck@b755fd7fe3c4_master/stats.html new file mode 100644 index 0000000..3fb6add --- /dev/null +++ b/2020-07-11-174721-5648-cppcheck@b755fd7fe3c4_master/stats.html @@ -0,0 +1,93 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + + +
+

Top 10 files for error severity, total findings: 2
+   1  mate-volume-control/gvc-speaker-test.c
+   1  mate-volume-control/gvc-combo-box.c
+

+

Top 10 files for information severity, total findings: 3
+   3  mate-volume-control/gvc-sound-theme-chooser.c
+

+ +
+ + + diff --git a/2020-07-11-174721-5648-cppcheck@b755fd7fe3c4_master/style.css b/2020-07-11-174721-5648-cppcheck@b755fd7fe3c4_master/style.css new file mode 100644 index 0000000..c39571c --- /dev/null +++ b/2020-07-11-174721-5648-cppcheck@b755fd7fe3c4_master/style.css @@ -0,0 +1,149 @@ + +body { + font: 13px Arial, Verdana, Sans-Serif; + margin: 0; + width: auto; +} + +h1 { + margin: 10px; +} + +#footer > p { + margin: 4px; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + border: 1px dotted black; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #B6B6B4; +} + +.inconclusive2 { + background-color: #B6B6B4; + border: 1px dotted black; + display: inline-block; + margin-left: 4px; +} + +div.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +div.verbose div.content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid black; + background-color: #FFFFCC; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +#header { + border-bottom: thin solid #aaa; +} + +#menu { + float: left; + margin-top: 5px; + text-align: left; + width: 150px; + /*height: 75%;*/ + position: fixed; + overflow: auto; + z-index: 1; +} + +#menu_index { + float: left; + margin-top: 5px; + padding-left: 5px; + text-align: left; + width: 300px; + /*height: 75%;*/ + position: fixed; + overflow: auto; + z-index: 1; +} + +#menu > a { + display: block; + margin-left: 10px; + font: 12px; + z-index: 1; +} + +#filename { + margin-left: 10px; + font: 12px; + z-index: 1; +} + +.highlighttable { + background-color:white; + z-index: 10; + position: relative; + margin: -10 px; +} + +#content { + background-color: white; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + float: left; + margin: 5px; + margin-left: 10px; + padding: 0 10px 10px 10px; + width: 80%; + padding-left: 150px; +} + +#content_index { + background-color: white; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + float: left; + margin: 5px; + margin-left: 10px; + padding: 0 10px 10px 10px; + width: 80%; + padding-left: 300px; +} + +.linenos { + border-right: thin solid #aaa; + color: lightgray; + padding-right: 6px; +} + +#footer { + border-top: thin solid #aaa; + clear: both; + font-size: 90%; + margin-top: 5px; +} + +#footer ul { + list-style-type: none; + padding-left: 0; +} diff --git a/2020-08-14-155418-9073-cppcheck@acc599546ad3_master/0.html b/2020-08-14-155418-9073-cppcheck@acc599546ad3_master/0.html new file mode 100644 index 0000000..5bf183e --- /dev/null +++ b/2020-08-14-155418-9073-cppcheck@acc599546ad3_master/0.html @@ -0,0 +1,1054 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + +
+ +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-combo-box.h"
+
+struct _GvcComboBoxPrivate
+{
+        GtkWidget       *drop_box;
+        GtkWidget       *start_box;
+        GtkWidget       *end_box;
+        GtkWidget       *label;
+        GtkWidget       *button;
+        GtkTreeModel    *model;
+        GtkWidget       *combobox;
+        MateMixerSwitch *swtch;
+};
+
+enum {
+        COL_NAME,
+        COL_HUMAN_NAME,
+        NUM_COLS
+};
+
+enum {
+        CHANGING,
+        BUTTON_CLICKED,
+        LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+enum {
+        PROP_0,
+        PROP_SWITCH,
+        PROP_LABEL,
+        PROP_SHOW_BUTTON,
+        PROP_BUTTON_LABEL,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_combo_box_dispose    (GObject          *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcComboBox, gvc_combo_box, GTK_TYPE_BOX)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+MateMixerSwitch *
+gvc_combo_box_get_switch (GvcComboBox *combobox)
+{
+        g_return_val_if_fail (GVC_IS_COMBO_BOX (combobox), NULL);
+
+        return combobox->priv->swtch;
+}
+
+void
+gvc_combo_box_set_size_group (GvcComboBox  *combobox,
+                              GtkSizeGroup *group,
+                              gboolean      symmetric)
+{
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (GTK_IS_SIZE_GROUP (group));
+
+        if (group != NULL) {
+                gtk_size_group_add_widget (group, combobox->priv->start_box);
+                if (symmetric == TRUE)
+                        gtk_size_group_add_widget (group, combobox->priv->end_box);
+        }
+        gtk_widget_queue_draw (GTK_WIDGET (combobox));
+}
+
+static void
+on_switch_active_option_notify (MateMixerSwitch *swtch,
+                                GParamSpec      *pspec,
+                                GvcComboBox     *combobox)
+{
+        GtkTreeIter            iter;
+        MateMixerSwitchOption *active;
+        gboolean               cont;
+        const gchar           *name;
+
+        active = mate_mixer_switch_get_active_option (swtch);
+        if (G_UNLIKELY (active == NULL)) {
+                g_warn_if_reached ();
+                return;
+        }
+
+        /* Select the newly activated switch option in the combo box */
+        name = mate_mixer_switch_option_get_name (active);
+        cont = gtk_tree_model_get_iter_first (combobox->priv->model, &iter);
+        while (cont == TRUE) {
+                gchar *current;
+
+                gtk_tree_model_get (combobox->priv->model, &iter,
+                                    COL_NAME, &current,
+                                    -1);
+                if (g_strcmp0 (name, current) == 0) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox), &iter);
+                        g_free (current);
+                        return;
+                }
+                g_free (current);
+
+                cont = gtk_tree_model_iter_next (combobox->priv->model, &iter);
+        }
+        g_warning ("Could not find switch option '%s' in combo box", name);
+}
+
+static void
+gvc_combo_box_set_switch (GvcComboBox *combobox, MateMixerSwitch *swtch)
+{
+        MateMixerSwitchOption *active;
+        const GList           *options;
+
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (MATE_MIXER_IS_SWITCH (swtch));
+
+        combobox->priv->swtch = g_object_ref (swtch);
+
+        active  = mate_mixer_switch_get_active_option (swtch);
+        options = mate_mixer_switch_list_options (swtch);
+        while (options != NULL) {
+                GtkTreeIter            iter;
+                MateMixerSwitchOption *option = MATE_MIXER_SWITCH_OPTION (options->data);
+
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (combobox->priv->model),
+                                                   &iter,
+                                                   G_MAXINT,
+                                                   COL_NAME,
+                                                   mate_mixer_switch_option_get_name (option),
+                                                   COL_HUMAN_NAME,
+                                                   mate_mixer_switch_option_get_label (option),
+                                                   -1);
+
+                /* Select the currently active option of the switch */
+                if (option == active) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox),
+                                                       &iter);
+                }
+                options = options->next;
+        }
+
+        g_signal_connect (G_OBJECT (swtch),
+                          "notify::active-option",
+                          G_CALLBACK (on_switch_active_option_notify),
+                          combobox);
+}
+
+static void
+gvc_combo_box_set_property (GObject       *object,
+                            guint          prop_id,
+                            const GValue  *value,
+                            GParamSpec    *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                gvc_combo_box_set_switch (self, g_value_get_object (value));
+                break;
+        case PROP_LABEL:
+                gtk_label_set_text_with_mnemonic (GTK_LABEL (self->priv->label), g_value_get_string (value));
+                break;
+        case PROP_BUTTON_LABEL:
+                gtk_button_set_label (GTK_BUTTON (self->priv->button), g_value_get_string (value));
+                break;
+        case PROP_SHOW_BUTTON:
+                gtk_widget_set_visible (self->priv->button, g_value_get_boolean (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_get_property (GObject     *object,
+                            guint        prop_id,
+                            GValue      *value,
+                            GParamSpec  *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                g_value_set_object (value, self->priv->swtch);
+                break;
+        case PROP_LABEL:
+                g_value_set_string (value, gtk_label_get_text (GTK_LABEL (self->priv->label)));
+                break;
+        case PROP_BUTTON_LABEL:
+                g_value_set_string (value, gtk_button_get_label (GTK_BUTTON (self->priv->button)));
+                break;
+        case PROP_SHOW_BUTTON:
+                g_value_set_boolean (value, gtk_widget_get_visible (self->priv->button));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_class_init (GvcComboBoxClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_combo_box_dispose;
+        object_class->set_property = gvc_combo_box_set_property;
+        object_class->get_property = gvc_combo_box_get_property;
+
+        properties[PROP_SWITCH] =
+                g_param_spec_object ("switch",
+                                     "switch",
+                                     "The MateMixerSwitch",
+                                     MATE_MIXER_TYPE_SWITCH,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_LABEL] =
+                g_param_spec_string ("label",
+                                     "label",
+                                     "The combo box label",
+                                     _("_Profile:"),
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_SHOW_BUTTON] =
+                g_param_spec_boolean ("show-button",
+                                      "show-button",
+                                      "Whether to show the button",
+                                      FALSE,
+                                      G_PARAM_READWRITE |
+                                      G_PARAM_CONSTRUCT |
+                                      G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_BUTTON_LABEL] =
+                g_param_spec_string ("button-label",
+                                     "button-label",
+                                     "The button's label",
+                                     "",
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+
+        signals[CHANGING] =
+                g_signal_new ("changing",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, changing),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__OBJECT,
+                              G_TYPE_NONE,
+                              1,
+                              MATE_MIXER_TYPE_SWITCH_OPTION);
+
+        signals[BUTTON_CLICKED] =
+                g_signal_new ("button-clicked",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, button_clicked),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
+}
+
+static void
+on_combo_box_changed (GtkComboBox *widget, GvcComboBox *combobox)
+{
+        GtkTreeIter            iter;
+        gchar                 *name;
+        MateMixerSwitchOption *option;
+
+        if (G_UNLIKELY (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter) == FALSE))
+                return;
+
+        gtk_tree_model_get (combobox->priv->model, &iter,
+                            COL_NAME, &name,
+                            -1);
+
+        option = mate_mixer_switch_get_option (combobox->priv->swtch, name);
+        if (G_UNLIKELY (option == NULL)) {
+                g_warn_if_reached ();
+                g_free (name);
+                return;
+        }
+
+        /* Inform that we are about to change the active option of the switch */
+        g_signal_emit (combobox, signals[CHANGING], 0, option);
+
+        mate_mixer_switch_set_active_option (combobox->priv->swtch, option);
+        g_free (name);
+}
+
+static void
+on_combo_box_button_clicked (GtkButton *button, GvcComboBox *combobox)
+{
+        /* The meaning of the button is defined by the owner, so only notify
+         * when it is clicked on */
+        g_signal_emit (combobox, signals[BUTTON_CLICKED], 0);
+}
+
+static void
+gvc_combo_box_init (GvcComboBox *combobox)
+{
+        GtkWidget       *frame;
+        GtkCellRenderer *renderer;
+
+        frame = gtk_frame_new (NULL);
+        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
+
+        combobox->priv = gvc_combo_box_get_instance_private (combobox);
+
+        combobox->priv->model = GTK_TREE_MODEL (gtk_list_store_new (NUM_COLS,
+                                                                    G_TYPE_STRING,
+                                                                    G_TYPE_STRING));
+
+        combobox->priv->combobox = gtk_combo_box_new_with_model (combobox->priv->model);
+
+        combobox->priv->label = gtk_label_new (NULL);
+
+        gtk_label_set_xalign (GTK_LABEL (combobox->priv->label), 0.0);
+        gtk_label_set_yalign (GTK_LABEL (combobox->priv->label), 0.5);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (combobox->priv->label),
+                                       combobox->priv->combobox);
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                    renderer,
+                                    FALSE);
+        gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                       renderer,
+                                       "text",
+                                       COL_HUMAN_NAME);
+
+        combobox->priv->drop_box  = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->start_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->end_box   = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+        /* Make sure the combo box does not get too long on long profile names */
+        g_object_set (G_OBJECT (renderer),
+                      "ellipsize",
+                      PANGO_ELLIPSIZE_END,
+                      NULL);
+
+        gtk_combo_box_set_popup_fixed_width (GTK_COMBO_BOX (combobox->priv->combobox), FALSE);
+
+        gtk_box_pack_start (GTK_BOX (combobox),
+                            frame,
+                            TRUE, TRUE, 0);
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->start_box,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->start_box),
+                            combobox->priv->label,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->combobox,
+                            TRUE, TRUE, 0);
+
+        combobox->priv->button = gtk_button_new_with_label ("");
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->button,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->end_box,
+                            FALSE, FALSE, 0);
+
+        gtk_container_add (GTK_CONTAINER (frame), combobox->priv->drop_box);
+
+        g_signal_connect (G_OBJECT (combobox->priv->combobox),
+                          "changed",
+                          G_CALLBACK (on_combo_box_changed),
+                          combobox);
+        g_signal_connect (G_OBJECT (combobox->priv->button),
+                          "clicked",
+                          G_CALLBACK (on_combo_box_button_clicked),
+                          combobox);
+
+        gtk_widget_set_no_show_all (combobox->priv->button, TRUE);
+        gtk_widget_show_all (frame);
+}
+
+static void
+gvc_combo_box_dispose (GObject *object)
+{
+        GvcComboBox *combobox;
+
+        combobox = GVC_COMBO_BOX (object);
+
+        if (G_LIKELY (combobox->priv->swtch != NULL)) {
+                g_signal_handlers_disconnect_by_func (G_OBJECT (combobox->priv->swtch),
+                                                      G_CALLBACK (on_switch_active_option_notify),
+                                                      combobox);
+                g_clear_object (&combobox->priv->swtch);
+        }
+
+        g_clear_object (&combobox->priv->model);
+
+        G_OBJECT_CLASS (gvc_combo_box_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_combo_box_new (MateMixerSwitch *swtch, const gchar *label)
+{
+        return g_object_new (GVC_TYPE_COMBO_BOX,
+                             "switch", swtch,
+                             "label", label,
+                             "orientation", GTK_ORIENTATION_HORIZONTAL,
+                             NULL);
+}
+
+
+
+
+ + + diff --git a/2020-08-14-155418-9073-cppcheck@acc599546ad3_master/1.html b/2020-08-14-155418-9073-cppcheck@acc599546ad3_master/1.html new file mode 100644 index 0000000..9fd449d --- /dev/null +++ b/2020-08-14-155418-9073-cppcheck@acc599546ad3_master/1.html @@ -0,0 +1,2384 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + +
+ +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
+ * Copyright (C) 2008 William Jon McCann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <utime.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+#include <canberra-gtk.h>
+#include <libxml/tree.h>
+
+#include "gvc-sound-theme-chooser.h"
+#include "sound-theme-file-utils.h"
+
+struct GvcSoundThemeChooserPrivate
+{
+        GtkWidget *combo_box;
+        GtkWidget *treeview;
+        GtkWidget *theme_box;
+        GtkWidget *selection_box;
+        GtkWidget *click_feedback_button;
+        GSettings *sound_settings;
+};
+
+static void     gvc_sound_theme_chooser_dispose   (GObject            *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSoundThemeChooser, gvc_sound_theme_chooser, GTK_TYPE_BOX)
+
+#define KEY_SOUNDS_SCHEMA          "org.mate.sound"
+#define EVENT_SOUNDS_KEY           "event-sounds"
+#define INPUT_SOUNDS_KEY           "input-feedback-sounds"
+#define SOUND_THEME_KEY            "theme-name"
+
+#define DEFAULT_ALERT_ID        "__default"
+#define CUSTOM_THEME_NAME       "__custom"
+#define NO_SOUNDS_THEME_NAME    "__no_sounds"
+
+enum {
+        THEME_DISPLAY_COL,
+        THEME_IDENTIFIER_COL,
+        THEME_PARENT_ID_COL,
+        THEME_NUM_COLS
+};
+
+enum {
+        ALERT_DISPLAY_COL,
+        ALERT_IDENTIFIER_COL,
+        ALERT_SOUND_TYPE_COL,
+        ALERT_ACTIVE_COL,
+        ALERT_NUM_COLS
+};
+
+enum {
+        SOUND_TYPE_UNSET,
+        SOUND_TYPE_OFF,
+        SOUND_TYPE_DEFAULT_FROM_THEME,
+        SOUND_TYPE_BUILTIN,
+        SOUND_TYPE_CUSTOM
+};
+
+static void
+on_combobox_changed (GtkComboBox          *widget,
+                     GvcSoundThemeChooser *chooser)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        char         *theme_name;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &theme_name, -1);
+
+        g_assert (theme_name != NULL);
+
+        /* It is necessary to update the theme name before any other setting as
+         * the "changed" notification will reload the contents of the widget */
+        g_settings_set_string (chooser->priv->sound_settings, SOUND_THEME_KEY, theme_name);
+
+        /* special case for no sounds */
+        if (strcmp (theme_name, NO_SOUNDS_THEME_NAME) == 0) {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, FALSE);
+                return;
+        } else {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, TRUE);
+        }
+
+        g_free (theme_name);
+
+        /* FIXME: reset alert model */
+}
+
+static char *
+load_index_theme_name (const char *index,
+                       char      **parent)
+{
+        GKeyFile *file;
+        char *indexname = NULL;
+        gboolean hidden;
+
+        file = g_key_file_new ();
+        if (g_key_file_load_from_file (file, index, G_KEY_FILE_KEEP_TRANSLATIONS, NULL) == FALSE) {
+                g_key_file_free (file);
+                return NULL;
+        }
+        /* Don't add hidden themes to the list */
+        hidden = g_key_file_get_boolean (file, "Sound Theme", "Hidden", NULL);
+        if (!hidden) {
+                indexname = g_key_file_get_locale_string (file,
+                                                          "Sound Theme",
+                                                          "Name",
+                                                          NULL,
+                                                          NULL);
+
+                /* Save the parent theme, if there's one */
+                if (parent != NULL) {
+                        *parent = g_key_file_get_string (file,
+                                                         "Sound Theme",
+                                                         "Inherits",
+                                                         NULL);
+                }
+        }
+
+        g_key_file_free (file);
+        return indexname;
+}
+
+static void
+sound_theme_in_dir (GHashTable *hash,
+                    const char *dir)
+{
+        GDir *d;
+        const char *name;
+
+        d = g_dir_open (dir, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *dirname, *index, *indexname;
+
+                /* Look for directories */
+                dirname = g_build_filename (dir, name, NULL);
+                if (g_file_test (dirname, G_FILE_TEST_IS_DIR) == FALSE) {
+                        g_free (dirname);
+                        continue;
+                }
+
+                /* Look for index files */
+                index = g_build_filename (dirname, "index.theme", NULL);
+                g_free (dirname);
+
+                /* Check the name of the theme in the index.theme file */
+                indexname = load_index_theme_name (index, NULL);
+                g_free (index);
+                if (indexname == NULL) {
+                        continue;
+                }
+
+                g_hash_table_insert (hash, g_strdup (name), indexname);
+        }
+
+        g_dir_close (d);
+}
+
+static void
+add_theme_to_store (const char   *key,
+                    const char   *value,
+                    GtkListStore *store)
+{
+        char *parent;
+
+        parent = NULL;
+
+        /* Get the parent, if we're checking the custom theme */
+        if (strcmp (key, CUSTOM_THEME_NAME) == 0) {
+                char *name, *path;
+
+                path = custom_theme_dir_path ("index.theme");
+                name = load_index_theme_name (path, &parent);
+                g_free (name);
+                g_free (path);
+        }
+        gtk_list_store_insert_with_values (store, NULL, G_MAXINT,
+                                           THEME_DISPLAY_COL, value,
+                                           THEME_IDENTIFIER_COL, key,
+                                           THEME_PARENT_ID_COL, parent,
+                                           -1);
+        g_free (parent);
+}
+
+static void
+set_combox_for_theme_name (GvcSoundThemeChooser *chooser,
+                           const char           *name)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        gboolean      found;
+
+        /* If the name is empty, use "freedesktop" */
+        if (name == NULL || *name == '\0') {
+                name = "freedesktop";
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+        if (gtk_tree_model_get_iter_first (model, &iter) == FALSE) {
+                return;
+        }
+
+        do {
+                char *value;
+
+                gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &value, -1);
+                found = (value != NULL && strcmp (value, name) == 0);
+                g_free (value);
+
+        } while (!found && gtk_tree_model_iter_next (model, &iter));
+
+        /* When we can't find the theme we need to set, try to set the default
+         * one "freedesktop" */
+        if (found) {
+                gtk_combo_box_set_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter);
+        } else if (strcmp (name, "freedesktop") != 0) {
+                g_debug ("not found, falling back to fdo");
+                set_combox_for_theme_name (chooser, "freedesktop");
+        }
+}
+
+static void
+set_input_feedback_enabled (GvcSoundThemeChooser *chooser,
+                            gboolean              enabled)
+{
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      enabled);
+}
+
+static void
+setup_theme_selector (GvcSoundThemeChooser *chooser)
+{
+        GHashTable           *hash;
+        GtkListStore         *store;
+        GtkCellRenderer      *renderer;
+        const char * const   *data_dirs;
+        const char           *data_dir;
+        char                 *dir;
+        guint                 i;
+
+        /* Add the theme names and their display name to a hash table,
+         * makes it easy to avoid duplicate themes */
+        hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+        data_dirs = g_get_system_data_dirs ();
+        for (i = 0; data_dirs[i] != NULL; i++) {
+                dir = g_build_filename (data_dirs[i], "sounds", NULL);
+                sound_theme_in_dir (hash, dir);
+                g_free (dir);
+        }
+
+        data_dir = g_get_user_data_dir ();
+        dir = g_build_filename (data_dir, "sounds", NULL);
+        sound_theme_in_dir (hash, dir);
+        g_free (dir);
+
+        /* If there isn't at least one theme, make everything
+         * insensitive, LAME! */
+        if (g_hash_table_size (hash) == 0) {
+                gtk_widget_set_sensitive (GTK_WIDGET (chooser), FALSE);
+                g_warning ("Bad setup, install the freedesktop sound theme");
+                g_hash_table_destroy (hash);
+                return;
+        }
+
+        /* Setup the tree model, 3 columns:
+         * - internal theme name/directory
+         * - display theme name
+         * - the internal id for the parent theme, used for the custom theme */
+        store = gtk_list_store_new (THEME_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING);
+
+        /* Add the themes to a combobox */
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           THEME_DISPLAY_COL, _("No sounds"),
+                                           THEME_IDENTIFIER_COL, "__no_sounds",
+                                           THEME_PARENT_ID_COL, NULL,
+                                           -1);
+        g_hash_table_foreach (hash, (GHFunc) add_theme_to_store, store);
+        g_hash_table_destroy (hash);
+
+        /* Set the display */
+        gtk_combo_box_set_model (GTK_COMBO_BOX (chooser->priv->combo_box),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                    renderer,
+                                    TRUE);
+        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                        renderer,
+                                        "text", THEME_DISPLAY_COL,
+                                        NULL);
+
+        g_signal_connect (G_OBJECT (chooser->priv->combo_box),
+                          "changed",
+                          G_CALLBACK (on_combobox_changed),
+                          chooser);
+}
+
+#define GVC_SOUND_SOUND    (xmlChar *) "sound"
+#define GVC_SOUND_NAME     (xmlChar *) "name"
+#define GVC_SOUND_FILENAME (xmlChar *) "filename"
+
+/* Adapted from yelp-toc-pager.c */
+static xmlChar *
+xml_get_and_trim_names (xmlNodePtr node)
+{
+        xmlNodePtr cur;
+        xmlChar *keep_lang = NULL;
+        xmlChar *value;
+        int j, keep_pri = INT_MAX;
+
+        const gchar * const * langs = g_get_language_names ();
+
+        value = NULL;
+
+        for (cur = node->children; cur; cur = cur->next) {
+                if (! xmlStrcmp (cur->name, GVC_SOUND_NAME)) {
+                        xmlChar *cur_lang = NULL;
+                        int cur_pri = INT_MAX;
+
+                        cur_lang = xmlNodeGetLang (cur);
+
+                        if (cur_lang) {
+                                for (j = 0; langs[j]; j++) {
+                                        if (g_str_equal (cur_lang, langs[j])) {
+                                                cur_pri = j;
+                                                break;
+                                        }
+                                }
+                        } else {
+                                cur_pri = INT_MAX - 1;
+                        }
+
+                        if (cur_pri <= keep_pri) {
+                                if (keep_lang)
+                                        xmlFree (keep_lang);
+                                if (value)
+                                        xmlFree (value);
+
+                                value = xmlNodeGetContent (cur);
+
+                                keep_lang = cur_lang;
+                                keep_pri = cur_pri;
+                        } else {
+                                if (cur_lang)
+                                        xmlFree (cur_lang);
+                        }
+                }
+        }
+
+        /* Delete all GVC_SOUND_NAME nodes */
+        cur = node->children;
+        while (cur) {
+                xmlNodePtr this = cur;
+                cur = cur->next;
+                if (! xmlStrcmp (this->name, GVC_SOUND_NAME)) {
+                        xmlUnlinkNode (this);
+                        xmlFreeNode (this);
+                }
+        }
+
+        return value;
+}
+
+static void
+populate_model_from_node (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          xmlNodePtr            node)
+{
+        xmlNodePtr child;
+        xmlChar   *filename;
+        xmlChar   *name;
+
+        filename = NULL;
+        name = xml_get_and_trim_names (node);
+        for (child = node->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+
+                if (xmlStrcmp (child->name, GVC_SOUND_FILENAME) == 0) {
+                        filename = xmlNodeGetContent (child);
+                } else if (xmlStrcmp (child->name, GVC_SOUND_NAME) == 0) {
+                        /* EH? should have been trimmed */
+                }
+        }
+
+        if (filename != NULL && name != NULL) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   ALERT_IDENTIFIER_COL, filename,
+                                                   ALERT_DISPLAY_COL, name,
+                                                   ALERT_SOUND_TYPE_COL, _("Built-in"),
+                                                   ALERT_ACTIVE_COL, FALSE,
+                                                   -1);
+        }
+
+        xmlFree (filename);
+        xmlFree (name);
+}
+
+static void
+populate_model_from_file (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          const char           *filename)
+{
+        xmlDocPtr  doc;
+        xmlNodePtr root;
+        xmlNodePtr child;
+        gboolean   exists;
+
+        exists = g_file_test (filename, G_FILE_TEST_EXISTS);
+        if (! exists) {
+                return;
+        }
+
+        doc = xmlParseFile (filename);
+        if (doc == NULL) {
+                return;
+        }
+
+        root = xmlDocGetRootElement (doc);
+
+        for (child = root->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+                if (xmlStrcmp (child->name, GVC_SOUND_SOUND) != 0) {
+                        continue;
+                }
+
+                populate_model_from_node (chooser, model, child);
+        }
+
+        xmlFreeDoc (doc);
+}
+
+static void
+populate_model_from_dir (GvcSoundThemeChooser *chooser,
+                         GtkTreeModel         *model,
+                         const char           *dirname)
+{
+        GDir       *d;
+        const char *name;
+
+        d = g_dir_open (dirname, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *path;
+
+                if (! g_str_has_suffix (name, ".xml")) {
+                        continue;
+                }
+
+                path = g_build_filename (dirname, name, NULL);
+                populate_model_from_file (chooser, model, path);
+                g_free (path);
+        }
+
+        g_dir_close (d);
+}
+
+static gboolean
+save_alert_sounds (GvcSoundThemeChooser  *chooser,
+                   const char            *id)
+{
+        const char *sounds[3] = { "bell-terminal", "bell-window-system", NULL };
+        char *path;
+
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+        } else {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+                add_custom_file (sounds, id);
+        }
+
+        /* And poke the directory so the theme gets updated */
+        path = custom_theme_dir_path (NULL);
+        if (utime (path, NULL) != 0) {
+                g_warning ("Failed to update mtime for directory '%s': %s",
+                           path, g_strerror (errno));
+        }
+        g_free (path);
+
+        return FALSE;
+}
+
+
+static void
+update_alert_model (GvcSoundThemeChooser  *chooser,
+                    const char            *id)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        gtk_tree_model_get_iter_first (model, &iter);
+        do {
+                gboolean toggled;
+                char    *this_id;
+
+                gtk_tree_model_get (model, &iter,
+                                    ALERT_IDENTIFIER_COL, &this_id,
+                                    -1);
+
+                if (strcmp (this_id, id) == 0) {
+                        toggled = TRUE;
+                } else {
+                        toggled = FALSE;
+                }
+                g_free (this_id);
+
+                gtk_list_store_set (GTK_LIST_STORE (model),
+                                    &iter,
+                                    ALERT_ACTIVE_COL, toggled,
+                                    -1);
+        } while (gtk_tree_model_iter_next (model, &iter));
+}
+
+static void
+update_alert (GvcSoundThemeChooser *chooser,
+              const char           *alert_id)
+{
+        GtkTreeModel *theme_model;
+        GtkTreeIter   iter;
+        char         *theme;
+        char         *parent;
+        gboolean      is_custom;
+        gboolean      is_default;
+        gboolean      add_custom;
+        gboolean      remove_custom;
+
+        theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        /* Get the current theme's name, and set the parent */
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        gtk_tree_model_get (theme_model, &iter,
+                            THEME_IDENTIFIER_COL, &theme,
+                            THEME_IDENTIFIER_COL, &parent,
+                            -1);
+        is_custom = strcmp (theme, CUSTOM_THEME_NAME) == 0;
+        is_default = strcmp (alert_id, DEFAULT_ALERT_ID) == 0;
+
+        /* So a few possibilities:
+         * 1. Named theme, default alert selected: noop
+         * 2. Named theme, alternate alert selected: create new custom with sound
+         * 3. Custom theme, default alert selected: remove sound and possibly custom
+         * 4. Custom theme, alternate alert selected: update custom sound
+         */
+        add_custom = FALSE;
+        remove_custom = FALSE;
+        if (! is_custom && is_default) {
+                /* remove custom just in case */
+                remove_custom = TRUE;
+        } else if (! is_custom && ! is_default) {
+                create_custom_theme (parent);
+                save_alert_sounds (chooser, alert_id);
+                add_custom = TRUE;
+        } else if (is_custom && is_default) {
+                save_alert_sounds (chooser, alert_id);
+                /* after removing files check if it is empty */
+                if (custom_theme_dir_is_empty ()) {
+                        remove_custom = TRUE;
+                }
+        } else if (is_custom && ! is_default) {
+                save_alert_sounds (chooser, alert_id);
+        }
+
+        if (add_custom) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (theme_model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   THEME_DISPLAY_COL, _("Custom"),
+                                                   THEME_IDENTIFIER_COL, CUSTOM_THEME_NAME,
+                                                   THEME_PARENT_ID_COL, theme,
+                                                   -1);
+                set_combox_for_theme_name (chooser, CUSTOM_THEME_NAME);
+        } else if (remove_custom) {
+                gtk_tree_model_get_iter_first (theme_model, &iter);
+                do {
+                        char *this_parent;
+
+                        gtk_tree_model_get (theme_model, &iter,
+                                            THEME_PARENT_ID_COL, &this_parent,
+                                            -1);
+                        if (this_parent != NULL && strcmp (this_parent, CUSTOM_THEME_NAME) != 0) {
+                                g_free (this_parent);
+                                gtk_list_store_remove (GTK_LIST_STORE (theme_model), &iter);
+                                break;
+                        }
+                        g_free (this_parent);
+                } while (gtk_tree_model_iter_next (theme_model, &iter));
+
+                delete_custom_theme_dir ();
+
+                set_combox_for_theme_name (chooser, parent);
+        }
+
+        update_alert_model (chooser, alert_id);
+
+        g_free (theme);
+        g_free (parent);
+}
+
+static void
+on_alert_toggled (GtkCellRendererToggle *renderer,
+                  char                  *path_str,
+                  GvcSoundThemeChooser  *chooser)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreePath  *path;
+        gboolean      toggled;
+        char         *id;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        path = gtk_tree_path_new_from_string (path_str);
+        gtk_tree_model_get_iter (model, &iter, path);
+        gtk_tree_path_free (path);
+
+        id = NULL;
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            ALERT_ACTIVE_COL, &toggled,
+                            -1);
+
+        toggled ^= 1;
+        if (toggled) {
+                update_alert (chooser, id);
+        }
+
+        g_free (id);
+}
+
+static void
+play_preview_for_path (GvcSoundThemeChooser *chooser, GtkTreePath *path)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreeIter   theme_iter;
+        gchar        *id = NULL;
+        gchar        *parent_theme = NULL;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        if (gtk_tree_model_get_iter (model, &iter, path) == FALSE)
+                return;
+
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            -1);
+        if (id == NULL)
+                return;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &theme_iter)) {
+                GtkTreeModel *theme_model;
+                gchar        *theme_id = NULL;
+                gchar        *parent_id = NULL;
+
+                theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+                gtk_tree_model_get (theme_model, &theme_iter,
+                                    THEME_IDENTIFIER_COL, &theme_id,
+                                    THEME_PARENT_ID_COL, &parent_id, -1);
+                if (theme_id && strcmp (theme_id, CUSTOM_THEME_NAME) == 0)
+                        parent_theme = g_strdup (parent_id);
+
+                g_free (theme_id);
+                g_free (parent_id);
+        }
+
+        /* special case: for the default item on custom themes
+         * play the alert for the parent theme */
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                if (parent_theme != NULL) {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_CANBERRA_XDG_THEME_NAME, parent_theme,
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                } else {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                }
+        } else {
+                ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                        CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                        CA_PROP_MEDIA_FILENAME, id,
+                                        CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                        CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                        CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                        CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                        NULL);
+
+        }
+        g_free (parent_theme);
+        g_free (id);
+}
+
+static void
+on_treeview_row_activated (GtkTreeView          *treeview,
+                           GtkTreePath          *path,
+                           GtkTreeViewColumn    *column,
+                           GvcSoundThemeChooser *chooser)
+{
+        play_preview_for_path (chooser, path);
+}
+
+static void
+on_treeview_selection_changed (GtkTreeSelection     *selection,
+                               GvcSoundThemeChooser *chooser)
+{
+        GList        *paths;
+        GtkTreeModel *model;
+        GtkTreePath  *path;
+
+        if (chooser->priv->treeview == NULL)
+                return;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        paths = gtk_tree_selection_get_selected_rows (selection, &model);
+        if (paths == NULL)
+                return;
+
+        path = paths->data;
+        play_preview_for_path (chooser, path);
+
+        g_list_foreach (paths, (GFunc)gtk_tree_path_free, NULL);
+        g_list_free (paths);
+}
+
+static GtkWidget *
+create_alert_treeview (GvcSoundThemeChooser *chooser)
+{
+        GtkListStore         *store;
+        GtkWidget            *treeview;
+        GtkCellRenderer      *renderer;
+        GtkTreeViewColumn    *column;
+        GtkTreeSelection     *selection;
+
+        treeview = gtk_tree_view_new ();
+
+        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
+        g_signal_connect (G_OBJECT (treeview),
+                          "row-activated",
+                          G_CALLBACK (on_treeview_row_activated),
+                          chooser);
+
+        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+        gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+        g_signal_connect (G_OBJECT (selection),
+                          "changed",
+                          G_CALLBACK (on_treeview_selection_changed),
+                          chooser);
+
+        /* Setup the tree model, 3 columns:
+         * - display name
+         * - sound id
+         * - sound type
+         */
+        store = gtk_list_store_new (ALERT_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_BOOLEAN);
+
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           ALERT_IDENTIFIER_COL, DEFAULT_ALERT_ID,
+                                           ALERT_DISPLAY_COL, _("Default"),
+                                           ALERT_SOUND_TYPE_COL, _("From theme"),
+                                           ALERT_ACTIVE_COL, TRUE,
+                                           -1);
+
+        populate_model_from_dir (chooser, GTK_TREE_MODEL (store), SOUND_SET_DIR);
+
+        gtk_tree_view_set_model (GTK_TREE_VIEW (treeview),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_toggle_new ();
+        gtk_cell_renderer_toggle_set_radio (GTK_CELL_RENDERER_TOGGLE (renderer), TRUE);
+
+        column = gtk_tree_view_column_new_with_attributes (NULL,
+                                                           renderer,
+                                                           "active", ALERT_ACTIVE_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+        g_signal_connect (renderer,
+                          "toggled",
+                          G_CALLBACK (on_alert_toggled),
+                          chooser);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Name"),
+                                                           renderer,
+                                                           "text", ALERT_DISPLAY_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Type"),
+                                                           renderer,
+                                                           "text", ALERT_SOUND_TYPE_COL,
+                                                           NULL);
+
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        return treeview;
+}
+
+static int
+get_file_type (const char *sound_name,
+               char      **linked_name)
+{
+        char *name, *filename;
+
+        *linked_name = NULL;
+
+        name = g_strdup_printf ("%s.disabled", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_REGULAR) != FALSE) {
+                g_free (filename);
+                return SOUND_TYPE_OFF;
+        }
+        g_free (filename);
+
+        /* We only check for .ogg files because those are the
+         * only ones we create */
+        name = g_strdup_printf ("%s.ogg", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_SYMLINK) != FALSE) {
+                *linked_name = g_file_read_link (filename, NULL);
+                g_free (filename);
+                return SOUND_TYPE_CUSTOM;
+        }
+        g_free (filename);
+
+        return SOUND_TYPE_BUILTIN;
+}
+
+static void
+update_alerts_from_theme_name (GvcSoundThemeChooser *chooser,
+                               const gchar          *name)
+{
+        if (strcmp (name, CUSTOM_THEME_NAME) != 0) {
+                /* reset alert to default */
+                update_alert (chooser, DEFAULT_ALERT_ID);
+        } else {
+                int   sound_type;
+                char *linkname;
+
+                linkname = NULL;
+                sound_type = get_file_type ("bell-terminal", &linkname);
+                g_debug ("Found link: %s", linkname);
+                if (sound_type == SOUND_TYPE_CUSTOM) {
+                        update_alert (chooser, linkname);
+                }
+        }
+}
+
+static void
+update_theme (GvcSoundThemeChooser *chooser)
+{
+        char        *theme_name;
+        gboolean     events_enabled;
+        gboolean     feedback_enabled;
+
+        feedback_enabled = g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY);
+        set_input_feedback_enabled (chooser, feedback_enabled);
+
+        events_enabled = g_settings_get_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY);
+        if (events_enabled) {
+                theme_name = g_settings_get_string (chooser->priv->sound_settings, SOUND_THEME_KEY);
+        } else {
+                theme_name = g_strdup (NO_SOUNDS_THEME_NAME);
+        }
+
+        gtk_widget_set_sensitive (chooser->priv->selection_box, events_enabled);
+        gtk_widget_set_sensitive (chooser->priv->click_feedback_button, events_enabled);
+
+        set_combox_for_theme_name (chooser, theme_name);
+
+        update_alerts_from_theme_name (chooser, theme_name);
+
+        g_free (theme_name);
+}
+
+static void
+gvc_sound_theme_chooser_class_init (GvcSoundThemeChooserClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_sound_theme_chooser_dispose;
+}
+
+static void
+on_click_feedback_toggled (GtkToggleButton      *button,
+                           GvcSoundThemeChooser *chooser)
+{
+        gboolean enabled;
+
+        enabled = gtk_toggle_button_get_active (button);
+
+        g_settings_set_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY, enabled);
+}
+
+static void
+on_key_changed (GSettings            *settings,
+                gchar                *key,
+                GvcSoundThemeChooser *chooser)
+{
+        if (!strcmp (key, EVENT_SOUNDS_KEY) ||
+            !strcmp (key, SOUND_THEME_KEY) ||
+            !strcmp (key, INPUT_SOUNDS_KEY))
+                update_theme (chooser);
+}
+
+static void
+setup_list_size_constraint (GtkWidget *widget,
+                            GtkWidget *to_size)
+{
+        GtkRequisition req;
+        gint           sc_height;
+        int            max_height;
+
+        /* Constrain height to be the tree height up to a max */
+        gdk_window_get_geometry (gdk_screen_get_root_window (gtk_widget_get_screen (widget)),
+                                 NULL, NULL, NULL, &sc_height);
+
+        max_height = sc_height / 4;
+
+        // XXX this doesn't work
+        gtk_widget_get_preferred_size (to_size, NULL, &req);
+
+        gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (widget),
+                                                    MIN (req.height, max_height));
+}
+
+static void
+gvc_sound_theme_chooser_init (GvcSoundThemeChooser *chooser)
+{
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *scrolled_window;
+        gchar       *str;
+
+        chooser->priv = gvc_sound_theme_chooser_get_instance_private (chooser);
+
+        chooser->priv->theme_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->theme_box, FALSE, FALSE, 0);
+
+        label = gtk_label_new_with_mnemonic (_("Sound _theme:"));
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), label, FALSE, FALSE, 0);
+        chooser->priv->combo_box = gtk_combo_box_new ();
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), chooser->priv->combo_box, FALSE, FALSE, 6);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->combo_box);
+
+        chooser->priv->sound_settings = g_settings_new (KEY_SOUNDS_SCHEMA);
+
+        g_signal_connect (G_OBJECT (chooser->priv->sound_settings),
+                          "changed",
+                          G_CALLBACK (on_key_changed),
+                          chooser);
+
+        str = g_strdup_printf ("<b>%s</b>", _("C_hoose an alert sound:"));
+        chooser->priv->selection_box = box = gtk_frame_new (str);
+        g_free (str);
+
+        label = gtk_frame_get_label_widget (GTK_FRAME (box));
+        gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
+        gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+        gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
+
+        gtk_box_pack_start (GTK_BOX (chooser), box, TRUE, TRUE, 6);
+
+        chooser->priv->treeview = create_alert_treeview (chooser);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->treeview);
+
+        scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+        gtk_widget_set_hexpand (scrolled_window, TRUE);
+        gtk_widget_set_vexpand (scrolled_window, TRUE);
+        gtk_widget_set_margin_top (scrolled_window, 6);
+
+        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+                                        GTK_POLICY_NEVER,
+                                        GTK_POLICY_AUTOMATIC);
+        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
+                                             GTK_SHADOW_IN);
+
+        gtk_container_add (GTK_CONTAINER (scrolled_window), chooser->priv->treeview);
+        gtk_container_add (GTK_CONTAINER (box), scrolled_window);
+
+        chooser->priv->click_feedback_button = gtk_check_button_new_with_mnemonic (_("Enable _window and button sounds"));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY));
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->click_feedback_button,
+                            FALSE, FALSE, 0);
+
+        g_signal_connect (G_OBJECT (chooser->priv->click_feedback_button),
+                          "toggled",
+                          G_CALLBACK (on_click_feedback_toggled),
+                          chooser);
+
+        setup_theme_selector (chooser);
+        update_theme (chooser);
+
+        setup_list_size_constraint (scrolled_window, chooser->priv->treeview);
+}
+
+static void
+gvc_sound_theme_chooser_dispose (GObject *object)
+{
+        GvcSoundThemeChooser *chooser;
+
+        chooser = GVC_SOUND_THEME_CHOOSER (object);
+
+        g_clear_object (&chooser->priv->sound_settings);
+
+        G_OBJECT_CLASS (gvc_sound_theme_chooser_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_sound_theme_chooser_new (void)
+{
+        return g_object_new (GVC_TYPE_SOUND_THEME_CHOOSER,
+                                "spacing", 6,
+                                "orientation", GTK_ORIENTATION_VERTICAL,
+                                NULL);
+}
+
+
+
+
+ + + diff --git a/2020-08-14-155418-9073-cppcheck@acc599546ad3_master/2.html b/2020-08-14-155418-9073-cppcheck@acc599546ad3_master/2.html new file mode 100644 index 0000000..64940b3 --- /dev/null +++ b/2020-08-14-155418-9073-cppcheck@acc599546ad3_master/2.html @@ -0,0 +1,1126 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + +
+ +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <canberra.h>
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-speaker-test.h"
+#include "gvc-utils.h"
+
+struct _GvcSpeakerTestPrivate
+{
+        GArray           *controls;
+        ca_context       *canberra;
+        MateMixerStream  *stream;
+};
+
+enum {
+        PROP_0,
+        PROP_STREAM,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_speaker_test_dispose    (GObject             *object);
+static void gvc_speaker_test_finalize   (GObject             *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSpeakerTest, gvc_speaker_test, GTK_TYPE_GRID)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+typedef struct {
+        MateMixerChannelPosition position;
+        guint left;
+        guint top;
+} TablePosition;
+
+static const TablePosition positions[] = {
+        /* Position, X, Y */
+        { MATE_MIXER_CHANNEL_FRONT_LEFT, 0, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_LEFT_CENTER, 1, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_CENTER, 2, 0, },
+        { MATE_MIXER_CHANNEL_MONO, 2, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT_CENTER, 3, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT, 4, 0, },
+        { MATE_MIXER_CHANNEL_SIDE_LEFT, 0, 1, },
+        { MATE_MIXER_CHANNEL_SIDE_RIGHT, 4, 1, },
+        { MATE_MIXER_CHANNEL_BACK_LEFT, 0, 2, },
+        { MATE_MIXER_CHANNEL_BACK_CENTER, 2, 2, },
+        { MATE_MIXER_CHANNEL_BACK_RIGHT, 4, 2, },
+        { MATE_MIXER_CHANNEL_LFE, 3, 2 }
+};
+
+MateMixerStream *
+gvc_speaker_test_get_stream (GvcSpeakerTest *test)
+{
+        g_return_val_if_fail (GVC_IS_SPEAKER_TEST (test), NULL);
+
+        return test->priv->stream;
+}
+
+static void
+gvc_speaker_test_set_stream (GvcSpeakerTest *test, MateMixerStream *stream)
+{
+        MateMixerStreamControl *control;
+        const gchar            *name;
+        guint                   i;
+
+        name = mate_mixer_stream_get_name (stream);
+        control = mate_mixer_stream_get_default_control (stream);
+
+        ca_context_change_device (test->priv->canberra, name);
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                gboolean has_position =
+                        mate_mixer_stream_control_has_channel_position (control, positions[i].position);
+
+                gtk_widget_set_visible (g_array_index (test->priv->controls, GtkWidget *, i),
+                                        has_position);
+        }
+
+        test->priv->stream = g_object_ref (stream);
+}
+
+static void
+gvc_speaker_test_set_property (GObject       *object,
+                               guint          prop_id,
+                               const GValue  *value,
+                               GParamSpec    *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                gvc_speaker_test_set_stream (self, g_value_get_object (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_get_property (GObject     *object,
+                               guint        prop_id,
+                               GValue      *value,
+                               GParamSpec  *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                g_value_set_object (value, self->priv->stream);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_class_init (GvcSpeakerTestClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose  = gvc_speaker_test_dispose;
+        object_class->finalize = gvc_speaker_test_finalize;
+        object_class->set_property = gvc_speaker_test_set_property;
+        object_class->get_property = gvc_speaker_test_get_property;
+
+        properties[PROP_STREAM] =
+                g_param_spec_object ("stream",
+                                     "Stream",
+                                     "MateMixer stream",
+                                     MATE_MIXER_TYPE_STREAM,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+}
+
+static const gchar *
+sound_name (MateMixerChannelPosition position)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return "audio-channel-front-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return "audio-channel-front-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return "audio-channel-front-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return "audio-channel-rear-left";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return "audio-channel-rear-right";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return "audio-channel-rear-center";
+        case MATE_MIXER_CHANNEL_LFE:
+                return "audio-channel-lfe";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return "audio-channel-side-left";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return "audio-channel-side-right";
+        default:
+                return NULL;
+        }
+}
+
+static const gchar *
+icon_name (MateMixerChannelPosition position, gboolean playing)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return playing
+                        ? "audio-speaker-left-testing"
+                        : "audio-speaker-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return playing
+                        ? "audio-speaker-right-testing"
+                        : "audio-speaker-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return playing
+                        ? "audio-speaker-center-testing"
+                        : "audio-speaker-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return playing
+                        ? "audio-speaker-left-back-testing"
+                        : "audio-speaker-left-back";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return playing
+                        ? "audio-speaker-right-back-testing"
+                        : "audio-speaker-right-back";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return playing
+                        ? "audio-speaker-center-back-testing"
+                        : "audio-speaker-center-back";
+        case MATE_MIXER_CHANNEL_LFE:
+                return playing
+                        ? "audio-subwoofer-testing"
+                        : "audio-subwoofer";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return playing
+                        ? "audio-speaker-left-side-testing"
+                        : "audio-speaker-left-side";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return playing
+                        ? "audio-speaker-right-side-testing"
+                        : "audio-speaker-right-side";
+        default:
+                return NULL;
+        }
+}
+
+static void
+update_button (GtkWidget *control)
+{
+        GtkWidget *button;
+        GtkWidget *image;
+        gboolean   playing;
+        MateMixerChannelPosition position;
+
+        button = g_object_get_data (G_OBJECT (control), "button");
+        image  = g_object_get_data (G_OBJECT (control), "image");
+
+        position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+        playing  = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        gtk_button_set_label (GTK_BUTTON (button), playing ? _("Stop") : _("Test"));
+
+        gtk_image_set_from_icon_name (GTK_IMAGE (image),
+                                      icon_name (position, playing),
+                                      GTK_ICON_SIZE_DIALOG);
+}
+
+static gboolean
+idle_cb (GtkWidget *control)
+{
+        if (control != NULL) {
+                /* This is called in the background thread, hence forward to main thread
+                 * via idle callback */
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+
+                update_button (control);
+        }
+        return FALSE;
+}
+
+static void
+finish_cb (ca_context *c, uint32_t id, int error_code, void *userdata)
+{
+        GtkWidget *control = (GtkWidget *) userdata;
+
+        if (error_code == CA_ERROR_DESTROYED || control == NULL)
+                return;
+
+        g_idle_add ((GSourceFunc) idle_cb, control);
+}
+
+static void
+on_test_button_clicked (GtkButton *button, GtkWidget *control)
+{
+        gboolean    playing;
+        ca_context *canberra;
+
+        canberra = g_object_get_data (G_OBJECT (control), "canberra");
+
+        ca_context_cancel (canberra, 1);
+
+        playing = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        if (playing) {
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        } else {
+                MateMixerChannelPosition position;
+                const gchar *name;
+                ca_proplist *proplist;
+
+                position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+
+                ca_proplist_create (&proplist);
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_ROLE, "test");
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_NAME,
+                                  gvc_channel_position_to_pretty_string (position));
+                ca_proplist_sets (proplist,
+                                  CA_PROP_CANBERRA_FORCE_CHANNEL,
+                                  gvc_channel_position_to_pulse_string (position));
+
+                ca_proplist_sets (proplist, CA_PROP_CANBERRA_ENABLE, "1");
+
+                name = sound_name (position);
+                if (name != NULL) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, name);
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, "audio-test-signal");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets(proplist, CA_PROP_EVENT_ID, "bell-window-system");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (playing));
+        }
+
+        update_button (control);
+}
+
+static GtkWidget *
+create_control (ca_context *canberra, MateMixerChannelPosition position)
+{
+        GtkWidget   *control;
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *image;
+        GtkWidget   *test_button;
+        const gchar *name;
+
+        control = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+        box     = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        g_object_set_data (G_OBJECT (control), "position", GINT_TO_POINTER (position));
+        g_object_set_data (G_OBJECT (control), "canberra", canberra);
+
+        name = icon_name (position, FALSE);
+        if (name == NULL)
+                name = "audio-volume-medium";
+
+        image = gtk_image_new_from_icon_name (name, GTK_ICON_SIZE_DIALOG);
+        g_object_set_data (G_OBJECT (control), "image", image);
+        gtk_box_pack_start (GTK_BOX (control), image, FALSE, FALSE, 0);
+
+        label = gtk_label_new (gvc_channel_position_to_pretty_string (position));
+        gtk_box_pack_start (GTK_BOX (control), label, FALSE, FALSE, 0);
+
+        test_button = gtk_button_new_with_label (_("Test"));
+        g_signal_connect (G_OBJECT (test_button),
+                          "clicked",
+                          G_CALLBACK (on_test_button_clicked),
+                          control);
+
+        g_object_set_data (G_OBJECT (control), "button", test_button);
+
+        gtk_box_pack_start (GTK_BOX (box), test_button, TRUE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (control), box, FALSE, FALSE, 0);
+
+        gtk_widget_show_all (control);
+
+        return control;
+}
+
+static void
+create_controls (GvcSpeakerTest *test)
+{
+        guint i;
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                GtkWidget *control = create_control (test->priv->canberra, positions[i].position);
+
+                gtk_grid_attach (GTK_GRID (test),
+                                 control,
+                                 positions[i].left,
+                                 positions[i].top,
+                                 1, 1);
+                g_array_insert_val (test->priv->controls, i, control);
+        }
+}
+
+static void
+gvc_speaker_test_init (GvcSpeakerTest *test)
+{
+        GtkWidget *face;
+
+        test->priv = gvc_speaker_test_get_instance_private (test);
+
+        gtk_container_set_border_width (GTK_CONTAINER (test), 12);
+
+        face = gtk_image_new_from_icon_name ("face-smile", GTK_ICON_SIZE_DIALOG);
+
+        gtk_grid_attach (GTK_GRID (test),
+                         face,
+                         1, 1,
+                         3, 1);
+
+
+        gtk_grid_set_baseline_row (GTK_GRID (test), 1);
+        gtk_widget_show (face);
+
+        ca_context_create (&test->priv->canberra);
+
+        /* The test sounds are played for a single channel, set up using the
+         * FORCE_CHANNEL property of libcanberra; this property is only supported
+         * in the PulseAudio backend, so avoid other backends completely */
+        ca_context_set_driver (test->priv->canberra, "pulse");
+
+        ca_context_change_props (test->priv->canberra,
+                                 CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+                                 CA_PROP_APPLICATION_NAME, _("Volume Control"),
+                                 CA_PROP_APPLICATION_VERSION, VERSION,
+                                 CA_PROP_APPLICATION_ICON_NAME, "multimedia-volume-control",
+                                 NULL);
+
+        test->priv->controls = g_array_new (FALSE, FALSE, sizeof (GtkWidget *));
+
+        create_controls (test);
+}
+
+static void
+gvc_speaker_test_dispose (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        g_clear_object (&test->priv->stream);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->dispose (object);
+}
+
+static void
+gvc_speaker_test_finalize (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        ca_context_destroy (test->priv->canberra);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->finalize (object);
+}
+
+GtkWidget *
+gvc_speaker_test_new (MateMixerStream *stream)
+{
+        GObject *test;
+
+        g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL);
+
+        test = g_object_new (GVC_TYPE_SPEAKER_TEST,
+                             "row-spacing", 6,
+                             "column-spacing", 6,
+                             "row-homogeneous", TRUE,
+                             "column-homogeneous", TRUE,
+                             "stream", stream,
+                             NULL);
+
+        return GTK_WIDGET (test);
+}
+
+
+
+
+ + + diff --git a/2020-08-14-155418-9073-cppcheck@acc599546ad3_master/index.html b/2020-08-14-155418-9073-cppcheck@acc599546ad3_master/index.html new file mode 100644 index 0000000..235f646 --- /dev/null +++ b/2020-08-14-155418-9073-cppcheck@acc599546ad3_master/index.html @@ -0,0 +1,124 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + +
+ +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
mate-volume-control/gvc-combo-box.c
70unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
mate-volume-control/gvc-sound-theme-chooser.c
735ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
746ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
758ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
mate-volume-control/gvc-speaker-test.c
53unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+
+ + + diff --git a/2020-08-14-155418-9073-cppcheck@acc599546ad3_master/stats.html b/2020-08-14-155418-9073-cppcheck@acc599546ad3_master/stats.html new file mode 100644 index 0000000..6eb8706 --- /dev/null +++ b/2020-08-14-155418-9073-cppcheck@acc599546ad3_master/stats.html @@ -0,0 +1,109 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + +
+ +
+

Top 10 files for error severity, total findings: 2
+   1  mate-volume-control/gvc-speaker-test.c
+   1  mate-volume-control/gvc-combo-box.c
+

+

Top 10 files for information severity, total findings: 3
+   3  mate-volume-control/gvc-sound-theme-chooser.c
+

+ +
+
+ + + diff --git a/2020-08-14-155418-9073-cppcheck@acc599546ad3_master/style.css b/2020-08-14-155418-9073-cppcheck@acc599546ad3_master/style.css new file mode 100644 index 0000000..07125f4 --- /dev/null +++ b/2020-08-14-155418-9073-cppcheck@acc599546ad3_master/style.css @@ -0,0 +1,137 @@ + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; + font-size: 13px; + line-height: 1.5; + margin: 0; + width: auto; +} + +h1 { + margin: 10px; +} + +.header { + border-bottom: thin solid #aaa; +} + +.footer { + border-top: thin solid #aaa; + font-size: 90%; + margin-top: 5px; +} + +.footer ul { + list-style-type: none; + padding-left: 0; +} + +.footer > p { + margin: 4px; +} + +.wrapper { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; +} + +#menu, +#menu_index { + text-align: left; + width: 350px; + height: 90vh; + min-height: 200px; + overflow: auto; + position: -webkit-sticky; + position: sticky; + top: 0; + padding: 0 15px 15px 15px; +} + +#menu > a { + display: block; + margin-left: 10px; + font-size: 12px; + z-index: 1; +} + +#content, +#content_index { + background-color: #fff; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + padding: 0 15px 15px 15px; + width: calc(100% - 350px); + height: 100%; + overflow-x: auto; +} + +#filename { + margin-left: 10px; + font-size: 12px; + z-index: 1; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #b6b6b4; +} + +.inconclusive2 { + background-color: #b6b6b4; + display: inline-block; + margin-left: 4px; +} + +.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +.verbose .content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid #000; + background-color: #ffffcc; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +.highlighttable { + background-color: #fff; + z-index: 10; + position: relative; + margin: -10px; +} + +.linenos { + border-right: thin solid #aaa; + color: #d3d3d3; + padding-right: 6px; +} + +.d-none { + display: none; +} diff --git a/2020-08-18-164117-7831-cppcheck@af4178682b21_master/0.html b/2020-08-18-164117-7831-cppcheck@af4178682b21_master/0.html new file mode 100644 index 0000000..5bf183e --- /dev/null +++ b/2020-08-18-164117-7831-cppcheck@af4178682b21_master/0.html @@ -0,0 +1,1054 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + +
+ +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-combo-box.h"
+
+struct _GvcComboBoxPrivate
+{
+        GtkWidget       *drop_box;
+        GtkWidget       *start_box;
+        GtkWidget       *end_box;
+        GtkWidget       *label;
+        GtkWidget       *button;
+        GtkTreeModel    *model;
+        GtkWidget       *combobox;
+        MateMixerSwitch *swtch;
+};
+
+enum {
+        COL_NAME,
+        COL_HUMAN_NAME,
+        NUM_COLS
+};
+
+enum {
+        CHANGING,
+        BUTTON_CLICKED,
+        LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+enum {
+        PROP_0,
+        PROP_SWITCH,
+        PROP_LABEL,
+        PROP_SHOW_BUTTON,
+        PROP_BUTTON_LABEL,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_combo_box_dispose    (GObject          *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcComboBox, gvc_combo_box, GTK_TYPE_BOX)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+MateMixerSwitch *
+gvc_combo_box_get_switch (GvcComboBox *combobox)
+{
+        g_return_val_if_fail (GVC_IS_COMBO_BOX (combobox), NULL);
+
+        return combobox->priv->swtch;
+}
+
+void
+gvc_combo_box_set_size_group (GvcComboBox  *combobox,
+                              GtkSizeGroup *group,
+                              gboolean      symmetric)
+{
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (GTK_IS_SIZE_GROUP (group));
+
+        if (group != NULL) {
+                gtk_size_group_add_widget (group, combobox->priv->start_box);
+                if (symmetric == TRUE)
+                        gtk_size_group_add_widget (group, combobox->priv->end_box);
+        }
+        gtk_widget_queue_draw (GTK_WIDGET (combobox));
+}
+
+static void
+on_switch_active_option_notify (MateMixerSwitch *swtch,
+                                GParamSpec      *pspec,
+                                GvcComboBox     *combobox)
+{
+        GtkTreeIter            iter;
+        MateMixerSwitchOption *active;
+        gboolean               cont;
+        const gchar           *name;
+
+        active = mate_mixer_switch_get_active_option (swtch);
+        if (G_UNLIKELY (active == NULL)) {
+                g_warn_if_reached ();
+                return;
+        }
+
+        /* Select the newly activated switch option in the combo box */
+        name = mate_mixer_switch_option_get_name (active);
+        cont = gtk_tree_model_get_iter_first (combobox->priv->model, &iter);
+        while (cont == TRUE) {
+                gchar *current;
+
+                gtk_tree_model_get (combobox->priv->model, &iter,
+                                    COL_NAME, &current,
+                                    -1);
+                if (g_strcmp0 (name, current) == 0) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox), &iter);
+                        g_free (current);
+                        return;
+                }
+                g_free (current);
+
+                cont = gtk_tree_model_iter_next (combobox->priv->model, &iter);
+        }
+        g_warning ("Could not find switch option '%s' in combo box", name);
+}
+
+static void
+gvc_combo_box_set_switch (GvcComboBox *combobox, MateMixerSwitch *swtch)
+{
+        MateMixerSwitchOption *active;
+        const GList           *options;
+
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (MATE_MIXER_IS_SWITCH (swtch));
+
+        combobox->priv->swtch = g_object_ref (swtch);
+
+        active  = mate_mixer_switch_get_active_option (swtch);
+        options = mate_mixer_switch_list_options (swtch);
+        while (options != NULL) {
+                GtkTreeIter            iter;
+                MateMixerSwitchOption *option = MATE_MIXER_SWITCH_OPTION (options->data);
+
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (combobox->priv->model),
+                                                   &iter,
+                                                   G_MAXINT,
+                                                   COL_NAME,
+                                                   mate_mixer_switch_option_get_name (option),
+                                                   COL_HUMAN_NAME,
+                                                   mate_mixer_switch_option_get_label (option),
+                                                   -1);
+
+                /* Select the currently active option of the switch */
+                if (option == active) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox),
+                                                       &iter);
+                }
+                options = options->next;
+        }
+
+        g_signal_connect (G_OBJECT (swtch),
+                          "notify::active-option",
+                          G_CALLBACK (on_switch_active_option_notify),
+                          combobox);
+}
+
+static void
+gvc_combo_box_set_property (GObject       *object,
+                            guint          prop_id,
+                            const GValue  *value,
+                            GParamSpec    *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                gvc_combo_box_set_switch (self, g_value_get_object (value));
+                break;
+        case PROP_LABEL:
+                gtk_label_set_text_with_mnemonic (GTK_LABEL (self->priv->label), g_value_get_string (value));
+                break;
+        case PROP_BUTTON_LABEL:
+                gtk_button_set_label (GTK_BUTTON (self->priv->button), g_value_get_string (value));
+                break;
+        case PROP_SHOW_BUTTON:
+                gtk_widget_set_visible (self->priv->button, g_value_get_boolean (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_get_property (GObject     *object,
+                            guint        prop_id,
+                            GValue      *value,
+                            GParamSpec  *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                g_value_set_object (value, self->priv->swtch);
+                break;
+        case PROP_LABEL:
+                g_value_set_string (value, gtk_label_get_text (GTK_LABEL (self->priv->label)));
+                break;
+        case PROP_BUTTON_LABEL:
+                g_value_set_string (value, gtk_button_get_label (GTK_BUTTON (self->priv->button)));
+                break;
+        case PROP_SHOW_BUTTON:
+                g_value_set_boolean (value, gtk_widget_get_visible (self->priv->button));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_class_init (GvcComboBoxClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_combo_box_dispose;
+        object_class->set_property = gvc_combo_box_set_property;
+        object_class->get_property = gvc_combo_box_get_property;
+
+        properties[PROP_SWITCH] =
+                g_param_spec_object ("switch",
+                                     "switch",
+                                     "The MateMixerSwitch",
+                                     MATE_MIXER_TYPE_SWITCH,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_LABEL] =
+                g_param_spec_string ("label",
+                                     "label",
+                                     "The combo box label",
+                                     _("_Profile:"),
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_SHOW_BUTTON] =
+                g_param_spec_boolean ("show-button",
+                                      "show-button",
+                                      "Whether to show the button",
+                                      FALSE,
+                                      G_PARAM_READWRITE |
+                                      G_PARAM_CONSTRUCT |
+                                      G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_BUTTON_LABEL] =
+                g_param_spec_string ("button-label",
+                                     "button-label",
+                                     "The button's label",
+                                     "",
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+
+        signals[CHANGING] =
+                g_signal_new ("changing",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, changing),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__OBJECT,
+                              G_TYPE_NONE,
+                              1,
+                              MATE_MIXER_TYPE_SWITCH_OPTION);
+
+        signals[BUTTON_CLICKED] =
+                g_signal_new ("button-clicked",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, button_clicked),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
+}
+
+static void
+on_combo_box_changed (GtkComboBox *widget, GvcComboBox *combobox)
+{
+        GtkTreeIter            iter;
+        gchar                 *name;
+        MateMixerSwitchOption *option;
+
+        if (G_UNLIKELY (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter) == FALSE))
+                return;
+
+        gtk_tree_model_get (combobox->priv->model, &iter,
+                            COL_NAME, &name,
+                            -1);
+
+        option = mate_mixer_switch_get_option (combobox->priv->swtch, name);
+        if (G_UNLIKELY (option == NULL)) {
+                g_warn_if_reached ();
+                g_free (name);
+                return;
+        }
+
+        /* Inform that we are about to change the active option of the switch */
+        g_signal_emit (combobox, signals[CHANGING], 0, option);
+
+        mate_mixer_switch_set_active_option (combobox->priv->swtch, option);
+        g_free (name);
+}
+
+static void
+on_combo_box_button_clicked (GtkButton *button, GvcComboBox *combobox)
+{
+        /* The meaning of the button is defined by the owner, so only notify
+         * when it is clicked on */
+        g_signal_emit (combobox, signals[BUTTON_CLICKED], 0);
+}
+
+static void
+gvc_combo_box_init (GvcComboBox *combobox)
+{
+        GtkWidget       *frame;
+        GtkCellRenderer *renderer;
+
+        frame = gtk_frame_new (NULL);
+        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
+
+        combobox->priv = gvc_combo_box_get_instance_private (combobox);
+
+        combobox->priv->model = GTK_TREE_MODEL (gtk_list_store_new (NUM_COLS,
+                                                                    G_TYPE_STRING,
+                                                                    G_TYPE_STRING));
+
+        combobox->priv->combobox = gtk_combo_box_new_with_model (combobox->priv->model);
+
+        combobox->priv->label = gtk_label_new (NULL);
+
+        gtk_label_set_xalign (GTK_LABEL (combobox->priv->label), 0.0);
+        gtk_label_set_yalign (GTK_LABEL (combobox->priv->label), 0.5);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (combobox->priv->label),
+                                       combobox->priv->combobox);
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                    renderer,
+                                    FALSE);
+        gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                       renderer,
+                                       "text",
+                                       COL_HUMAN_NAME);
+
+        combobox->priv->drop_box  = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->start_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->end_box   = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+        /* Make sure the combo box does not get too long on long profile names */
+        g_object_set (G_OBJECT (renderer),
+                      "ellipsize",
+                      PANGO_ELLIPSIZE_END,
+                      NULL);
+
+        gtk_combo_box_set_popup_fixed_width (GTK_COMBO_BOX (combobox->priv->combobox), FALSE);
+
+        gtk_box_pack_start (GTK_BOX (combobox),
+                            frame,
+                            TRUE, TRUE, 0);
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->start_box,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->start_box),
+                            combobox->priv->label,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->combobox,
+                            TRUE, TRUE, 0);
+
+        combobox->priv->button = gtk_button_new_with_label ("");
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->button,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->end_box,
+                            FALSE, FALSE, 0);
+
+        gtk_container_add (GTK_CONTAINER (frame), combobox->priv->drop_box);
+
+        g_signal_connect (G_OBJECT (combobox->priv->combobox),
+                          "changed",
+                          G_CALLBACK (on_combo_box_changed),
+                          combobox);
+        g_signal_connect (G_OBJECT (combobox->priv->button),
+                          "clicked",
+                          G_CALLBACK (on_combo_box_button_clicked),
+                          combobox);
+
+        gtk_widget_set_no_show_all (combobox->priv->button, TRUE);
+        gtk_widget_show_all (frame);
+}
+
+static void
+gvc_combo_box_dispose (GObject *object)
+{
+        GvcComboBox *combobox;
+
+        combobox = GVC_COMBO_BOX (object);
+
+        if (G_LIKELY (combobox->priv->swtch != NULL)) {
+                g_signal_handlers_disconnect_by_func (G_OBJECT (combobox->priv->swtch),
+                                                      G_CALLBACK (on_switch_active_option_notify),
+                                                      combobox);
+                g_clear_object (&combobox->priv->swtch);
+        }
+
+        g_clear_object (&combobox->priv->model);
+
+        G_OBJECT_CLASS (gvc_combo_box_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_combo_box_new (MateMixerSwitch *swtch, const gchar *label)
+{
+        return g_object_new (GVC_TYPE_COMBO_BOX,
+                             "switch", swtch,
+                             "label", label,
+                             "orientation", GTK_ORIENTATION_HORIZONTAL,
+                             NULL);
+}
+
+
+
+
+ + + diff --git a/2020-08-18-164117-7831-cppcheck@af4178682b21_master/1.html b/2020-08-18-164117-7831-cppcheck@af4178682b21_master/1.html new file mode 100644 index 0000000..9fd449d --- /dev/null +++ b/2020-08-18-164117-7831-cppcheck@af4178682b21_master/1.html @@ -0,0 +1,2384 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + +
+ +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
+ * Copyright (C) 2008 William Jon McCann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <utime.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+#include <canberra-gtk.h>
+#include <libxml/tree.h>
+
+#include "gvc-sound-theme-chooser.h"
+#include "sound-theme-file-utils.h"
+
+struct GvcSoundThemeChooserPrivate
+{
+        GtkWidget *combo_box;
+        GtkWidget *treeview;
+        GtkWidget *theme_box;
+        GtkWidget *selection_box;
+        GtkWidget *click_feedback_button;
+        GSettings *sound_settings;
+};
+
+static void     gvc_sound_theme_chooser_dispose   (GObject            *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSoundThemeChooser, gvc_sound_theme_chooser, GTK_TYPE_BOX)
+
+#define KEY_SOUNDS_SCHEMA          "org.mate.sound"
+#define EVENT_SOUNDS_KEY           "event-sounds"
+#define INPUT_SOUNDS_KEY           "input-feedback-sounds"
+#define SOUND_THEME_KEY            "theme-name"
+
+#define DEFAULT_ALERT_ID        "__default"
+#define CUSTOM_THEME_NAME       "__custom"
+#define NO_SOUNDS_THEME_NAME    "__no_sounds"
+
+enum {
+        THEME_DISPLAY_COL,
+        THEME_IDENTIFIER_COL,
+        THEME_PARENT_ID_COL,
+        THEME_NUM_COLS
+};
+
+enum {
+        ALERT_DISPLAY_COL,
+        ALERT_IDENTIFIER_COL,
+        ALERT_SOUND_TYPE_COL,
+        ALERT_ACTIVE_COL,
+        ALERT_NUM_COLS
+};
+
+enum {
+        SOUND_TYPE_UNSET,
+        SOUND_TYPE_OFF,
+        SOUND_TYPE_DEFAULT_FROM_THEME,
+        SOUND_TYPE_BUILTIN,
+        SOUND_TYPE_CUSTOM
+};
+
+static void
+on_combobox_changed (GtkComboBox          *widget,
+                     GvcSoundThemeChooser *chooser)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        char         *theme_name;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &theme_name, -1);
+
+        g_assert (theme_name != NULL);
+
+        /* It is necessary to update the theme name before any other setting as
+         * the "changed" notification will reload the contents of the widget */
+        g_settings_set_string (chooser->priv->sound_settings, SOUND_THEME_KEY, theme_name);
+
+        /* special case for no sounds */
+        if (strcmp (theme_name, NO_SOUNDS_THEME_NAME) == 0) {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, FALSE);
+                return;
+        } else {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, TRUE);
+        }
+
+        g_free (theme_name);
+
+        /* FIXME: reset alert model */
+}
+
+static char *
+load_index_theme_name (const char *index,
+                       char      **parent)
+{
+        GKeyFile *file;
+        char *indexname = NULL;
+        gboolean hidden;
+
+        file = g_key_file_new ();
+        if (g_key_file_load_from_file (file, index, G_KEY_FILE_KEEP_TRANSLATIONS, NULL) == FALSE) {
+                g_key_file_free (file);
+                return NULL;
+        }
+        /* Don't add hidden themes to the list */
+        hidden = g_key_file_get_boolean (file, "Sound Theme", "Hidden", NULL);
+        if (!hidden) {
+                indexname = g_key_file_get_locale_string (file,
+                                                          "Sound Theme",
+                                                          "Name",
+                                                          NULL,
+                                                          NULL);
+
+                /* Save the parent theme, if there's one */
+                if (parent != NULL) {
+                        *parent = g_key_file_get_string (file,
+                                                         "Sound Theme",
+                                                         "Inherits",
+                                                         NULL);
+                }
+        }
+
+        g_key_file_free (file);
+        return indexname;
+}
+
+static void
+sound_theme_in_dir (GHashTable *hash,
+                    const char *dir)
+{
+        GDir *d;
+        const char *name;
+
+        d = g_dir_open (dir, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *dirname, *index, *indexname;
+
+                /* Look for directories */
+                dirname = g_build_filename (dir, name, NULL);
+                if (g_file_test (dirname, G_FILE_TEST_IS_DIR) == FALSE) {
+                        g_free (dirname);
+                        continue;
+                }
+
+                /* Look for index files */
+                index = g_build_filename (dirname, "index.theme", NULL);
+                g_free (dirname);
+
+                /* Check the name of the theme in the index.theme file */
+                indexname = load_index_theme_name (index, NULL);
+                g_free (index);
+                if (indexname == NULL) {
+                        continue;
+                }
+
+                g_hash_table_insert (hash, g_strdup (name), indexname);
+        }
+
+        g_dir_close (d);
+}
+
+static void
+add_theme_to_store (const char   *key,
+                    const char   *value,
+                    GtkListStore *store)
+{
+        char *parent;
+
+        parent = NULL;
+
+        /* Get the parent, if we're checking the custom theme */
+        if (strcmp (key, CUSTOM_THEME_NAME) == 0) {
+                char *name, *path;
+
+                path = custom_theme_dir_path ("index.theme");
+                name = load_index_theme_name (path, &parent);
+                g_free (name);
+                g_free (path);
+        }
+        gtk_list_store_insert_with_values (store, NULL, G_MAXINT,
+                                           THEME_DISPLAY_COL, value,
+                                           THEME_IDENTIFIER_COL, key,
+                                           THEME_PARENT_ID_COL, parent,
+                                           -1);
+        g_free (parent);
+}
+
+static void
+set_combox_for_theme_name (GvcSoundThemeChooser *chooser,
+                           const char           *name)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        gboolean      found;
+
+        /* If the name is empty, use "freedesktop" */
+        if (name == NULL || *name == '\0') {
+                name = "freedesktop";
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+        if (gtk_tree_model_get_iter_first (model, &iter) == FALSE) {
+                return;
+        }
+
+        do {
+                char *value;
+
+                gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &value, -1);
+                found = (value != NULL && strcmp (value, name) == 0);
+                g_free (value);
+
+        } while (!found && gtk_tree_model_iter_next (model, &iter));
+
+        /* When we can't find the theme we need to set, try to set the default
+         * one "freedesktop" */
+        if (found) {
+                gtk_combo_box_set_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter);
+        } else if (strcmp (name, "freedesktop") != 0) {
+                g_debug ("not found, falling back to fdo");
+                set_combox_for_theme_name (chooser, "freedesktop");
+        }
+}
+
+static void
+set_input_feedback_enabled (GvcSoundThemeChooser *chooser,
+                            gboolean              enabled)
+{
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      enabled);
+}
+
+static void
+setup_theme_selector (GvcSoundThemeChooser *chooser)
+{
+        GHashTable           *hash;
+        GtkListStore         *store;
+        GtkCellRenderer      *renderer;
+        const char * const   *data_dirs;
+        const char           *data_dir;
+        char                 *dir;
+        guint                 i;
+
+        /* Add the theme names and their display name to a hash table,
+         * makes it easy to avoid duplicate themes */
+        hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+        data_dirs = g_get_system_data_dirs ();
+        for (i = 0; data_dirs[i] != NULL; i++) {
+                dir = g_build_filename (data_dirs[i], "sounds", NULL);
+                sound_theme_in_dir (hash, dir);
+                g_free (dir);
+        }
+
+        data_dir = g_get_user_data_dir ();
+        dir = g_build_filename (data_dir, "sounds", NULL);
+        sound_theme_in_dir (hash, dir);
+        g_free (dir);
+
+        /* If there isn't at least one theme, make everything
+         * insensitive, LAME! */
+        if (g_hash_table_size (hash) == 0) {
+                gtk_widget_set_sensitive (GTK_WIDGET (chooser), FALSE);
+                g_warning ("Bad setup, install the freedesktop sound theme");
+                g_hash_table_destroy (hash);
+                return;
+        }
+
+        /* Setup the tree model, 3 columns:
+         * - internal theme name/directory
+         * - display theme name
+         * - the internal id for the parent theme, used for the custom theme */
+        store = gtk_list_store_new (THEME_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING);
+
+        /* Add the themes to a combobox */
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           THEME_DISPLAY_COL, _("No sounds"),
+                                           THEME_IDENTIFIER_COL, "__no_sounds",
+                                           THEME_PARENT_ID_COL, NULL,
+                                           -1);
+        g_hash_table_foreach (hash, (GHFunc) add_theme_to_store, store);
+        g_hash_table_destroy (hash);
+
+        /* Set the display */
+        gtk_combo_box_set_model (GTK_COMBO_BOX (chooser->priv->combo_box),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                    renderer,
+                                    TRUE);
+        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                        renderer,
+                                        "text", THEME_DISPLAY_COL,
+                                        NULL);
+
+        g_signal_connect (G_OBJECT (chooser->priv->combo_box),
+                          "changed",
+                          G_CALLBACK (on_combobox_changed),
+                          chooser);
+}
+
+#define GVC_SOUND_SOUND    (xmlChar *) "sound"
+#define GVC_SOUND_NAME     (xmlChar *) "name"
+#define GVC_SOUND_FILENAME (xmlChar *) "filename"
+
+/* Adapted from yelp-toc-pager.c */
+static xmlChar *
+xml_get_and_trim_names (xmlNodePtr node)
+{
+        xmlNodePtr cur;
+        xmlChar *keep_lang = NULL;
+        xmlChar *value;
+        int j, keep_pri = INT_MAX;
+
+        const gchar * const * langs = g_get_language_names ();
+
+        value = NULL;
+
+        for (cur = node->children; cur; cur = cur->next) {
+                if (! xmlStrcmp (cur->name, GVC_SOUND_NAME)) {
+                        xmlChar *cur_lang = NULL;
+                        int cur_pri = INT_MAX;
+
+                        cur_lang = xmlNodeGetLang (cur);
+
+                        if (cur_lang) {
+                                for (j = 0; langs[j]; j++) {
+                                        if (g_str_equal (cur_lang, langs[j])) {
+                                                cur_pri = j;
+                                                break;
+                                        }
+                                }
+                        } else {
+                                cur_pri = INT_MAX - 1;
+                        }
+
+                        if (cur_pri <= keep_pri) {
+                                if (keep_lang)
+                                        xmlFree (keep_lang);
+                                if (value)
+                                        xmlFree (value);
+
+                                value = xmlNodeGetContent (cur);
+
+                                keep_lang = cur_lang;
+                                keep_pri = cur_pri;
+                        } else {
+                                if (cur_lang)
+                                        xmlFree (cur_lang);
+                        }
+                }
+        }
+
+        /* Delete all GVC_SOUND_NAME nodes */
+        cur = node->children;
+        while (cur) {
+                xmlNodePtr this = cur;
+                cur = cur->next;
+                if (! xmlStrcmp (this->name, GVC_SOUND_NAME)) {
+                        xmlUnlinkNode (this);
+                        xmlFreeNode (this);
+                }
+        }
+
+        return value;
+}
+
+static void
+populate_model_from_node (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          xmlNodePtr            node)
+{
+        xmlNodePtr child;
+        xmlChar   *filename;
+        xmlChar   *name;
+
+        filename = NULL;
+        name = xml_get_and_trim_names (node);
+        for (child = node->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+
+                if (xmlStrcmp (child->name, GVC_SOUND_FILENAME) == 0) {
+                        filename = xmlNodeGetContent (child);
+                } else if (xmlStrcmp (child->name, GVC_SOUND_NAME) == 0) {
+                        /* EH? should have been trimmed */
+                }
+        }
+
+        if (filename != NULL && name != NULL) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   ALERT_IDENTIFIER_COL, filename,
+                                                   ALERT_DISPLAY_COL, name,
+                                                   ALERT_SOUND_TYPE_COL, _("Built-in"),
+                                                   ALERT_ACTIVE_COL, FALSE,
+                                                   -1);
+        }
+
+        xmlFree (filename);
+        xmlFree (name);
+}
+
+static void
+populate_model_from_file (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          const char           *filename)
+{
+        xmlDocPtr  doc;
+        xmlNodePtr root;
+        xmlNodePtr child;
+        gboolean   exists;
+
+        exists = g_file_test (filename, G_FILE_TEST_EXISTS);
+        if (! exists) {
+                return;
+        }
+
+        doc = xmlParseFile (filename);
+        if (doc == NULL) {
+                return;
+        }
+
+        root = xmlDocGetRootElement (doc);
+
+        for (child = root->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+                if (xmlStrcmp (child->name, GVC_SOUND_SOUND) != 0) {
+                        continue;
+                }
+
+                populate_model_from_node (chooser, model, child);
+        }
+
+        xmlFreeDoc (doc);
+}
+
+static void
+populate_model_from_dir (GvcSoundThemeChooser *chooser,
+                         GtkTreeModel         *model,
+                         const char           *dirname)
+{
+        GDir       *d;
+        const char *name;
+
+        d = g_dir_open (dirname, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *path;
+
+                if (! g_str_has_suffix (name, ".xml")) {
+                        continue;
+                }
+
+                path = g_build_filename (dirname, name, NULL);
+                populate_model_from_file (chooser, model, path);
+                g_free (path);
+        }
+
+        g_dir_close (d);
+}
+
+static gboolean
+save_alert_sounds (GvcSoundThemeChooser  *chooser,
+                   const char            *id)
+{
+        const char *sounds[3] = { "bell-terminal", "bell-window-system", NULL };
+        char *path;
+
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+        } else {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+                add_custom_file (sounds, id);
+        }
+
+        /* And poke the directory so the theme gets updated */
+        path = custom_theme_dir_path (NULL);
+        if (utime (path, NULL) != 0) {
+                g_warning ("Failed to update mtime for directory '%s': %s",
+                           path, g_strerror (errno));
+        }
+        g_free (path);
+
+        return FALSE;
+}
+
+
+static void
+update_alert_model (GvcSoundThemeChooser  *chooser,
+                    const char            *id)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        gtk_tree_model_get_iter_first (model, &iter);
+        do {
+                gboolean toggled;
+                char    *this_id;
+
+                gtk_tree_model_get (model, &iter,
+                                    ALERT_IDENTIFIER_COL, &this_id,
+                                    -1);
+
+                if (strcmp (this_id, id) == 0) {
+                        toggled = TRUE;
+                } else {
+                        toggled = FALSE;
+                }
+                g_free (this_id);
+
+                gtk_list_store_set (GTK_LIST_STORE (model),
+                                    &iter,
+                                    ALERT_ACTIVE_COL, toggled,
+                                    -1);
+        } while (gtk_tree_model_iter_next (model, &iter));
+}
+
+static void
+update_alert (GvcSoundThemeChooser *chooser,
+              const char           *alert_id)
+{
+        GtkTreeModel *theme_model;
+        GtkTreeIter   iter;
+        char         *theme;
+        char         *parent;
+        gboolean      is_custom;
+        gboolean      is_default;
+        gboolean      add_custom;
+        gboolean      remove_custom;
+
+        theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        /* Get the current theme's name, and set the parent */
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        gtk_tree_model_get (theme_model, &iter,
+                            THEME_IDENTIFIER_COL, &theme,
+                            THEME_IDENTIFIER_COL, &parent,
+                            -1);
+        is_custom = strcmp (theme, CUSTOM_THEME_NAME) == 0;
+        is_default = strcmp (alert_id, DEFAULT_ALERT_ID) == 0;
+
+        /* So a few possibilities:
+         * 1. Named theme, default alert selected: noop
+         * 2. Named theme, alternate alert selected: create new custom with sound
+         * 3. Custom theme, default alert selected: remove sound and possibly custom
+         * 4. Custom theme, alternate alert selected: update custom sound
+         */
+        add_custom = FALSE;
+        remove_custom = FALSE;
+        if (! is_custom && is_default) {
+                /* remove custom just in case */
+                remove_custom = TRUE;
+        } else if (! is_custom && ! is_default) {
+                create_custom_theme (parent);
+                save_alert_sounds (chooser, alert_id);
+                add_custom = TRUE;
+        } else if (is_custom && is_default) {
+                save_alert_sounds (chooser, alert_id);
+                /* after removing files check if it is empty */
+                if (custom_theme_dir_is_empty ()) {
+                        remove_custom = TRUE;
+                }
+        } else if (is_custom && ! is_default) {
+                save_alert_sounds (chooser, alert_id);
+        }
+
+        if (add_custom) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (theme_model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   THEME_DISPLAY_COL, _("Custom"),
+                                                   THEME_IDENTIFIER_COL, CUSTOM_THEME_NAME,
+                                                   THEME_PARENT_ID_COL, theme,
+                                                   -1);
+                set_combox_for_theme_name (chooser, CUSTOM_THEME_NAME);
+        } else if (remove_custom) {
+                gtk_tree_model_get_iter_first (theme_model, &iter);
+                do {
+                        char *this_parent;
+
+                        gtk_tree_model_get (theme_model, &iter,
+                                            THEME_PARENT_ID_COL, &this_parent,
+                                            -1);
+                        if (this_parent != NULL && strcmp (this_parent, CUSTOM_THEME_NAME) != 0) {
+                                g_free (this_parent);
+                                gtk_list_store_remove (GTK_LIST_STORE (theme_model), &iter);
+                                break;
+                        }
+                        g_free (this_parent);
+                } while (gtk_tree_model_iter_next (theme_model, &iter));
+
+                delete_custom_theme_dir ();
+
+                set_combox_for_theme_name (chooser, parent);
+        }
+
+        update_alert_model (chooser, alert_id);
+
+        g_free (theme);
+        g_free (parent);
+}
+
+static void
+on_alert_toggled (GtkCellRendererToggle *renderer,
+                  char                  *path_str,
+                  GvcSoundThemeChooser  *chooser)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreePath  *path;
+        gboolean      toggled;
+        char         *id;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        path = gtk_tree_path_new_from_string (path_str);
+        gtk_tree_model_get_iter (model, &iter, path);
+        gtk_tree_path_free (path);
+
+        id = NULL;
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            ALERT_ACTIVE_COL, &toggled,
+                            -1);
+
+        toggled ^= 1;
+        if (toggled) {
+                update_alert (chooser, id);
+        }
+
+        g_free (id);
+}
+
+static void
+play_preview_for_path (GvcSoundThemeChooser *chooser, GtkTreePath *path)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreeIter   theme_iter;
+        gchar        *id = NULL;
+        gchar        *parent_theme = NULL;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        if (gtk_tree_model_get_iter (model, &iter, path) == FALSE)
+                return;
+
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            -1);
+        if (id == NULL)
+                return;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &theme_iter)) {
+                GtkTreeModel *theme_model;
+                gchar        *theme_id = NULL;
+                gchar        *parent_id = NULL;
+
+                theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+                gtk_tree_model_get (theme_model, &theme_iter,
+                                    THEME_IDENTIFIER_COL, &theme_id,
+                                    THEME_PARENT_ID_COL, &parent_id, -1);
+                if (theme_id && strcmp (theme_id, CUSTOM_THEME_NAME) == 0)
+                        parent_theme = g_strdup (parent_id);
+
+                g_free (theme_id);
+                g_free (parent_id);
+        }
+
+        /* special case: for the default item on custom themes
+         * play the alert for the parent theme */
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                if (parent_theme != NULL) {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_CANBERRA_XDG_THEME_NAME, parent_theme,
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                } else {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                }
+        } else {
+                ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                        CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                        CA_PROP_MEDIA_FILENAME, id,
+                                        CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                        CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                        CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                        CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                        NULL);
+
+        }
+        g_free (parent_theme);
+        g_free (id);
+}
+
+static void
+on_treeview_row_activated (GtkTreeView          *treeview,
+                           GtkTreePath          *path,
+                           GtkTreeViewColumn    *column,
+                           GvcSoundThemeChooser *chooser)
+{
+        play_preview_for_path (chooser, path);
+}
+
+static void
+on_treeview_selection_changed (GtkTreeSelection     *selection,
+                               GvcSoundThemeChooser *chooser)
+{
+        GList        *paths;
+        GtkTreeModel *model;
+        GtkTreePath  *path;
+
+        if (chooser->priv->treeview == NULL)
+                return;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        paths = gtk_tree_selection_get_selected_rows (selection, &model);
+        if (paths == NULL)
+                return;
+
+        path = paths->data;
+        play_preview_for_path (chooser, path);
+
+        g_list_foreach (paths, (GFunc)gtk_tree_path_free, NULL);
+        g_list_free (paths);
+}
+
+static GtkWidget *
+create_alert_treeview (GvcSoundThemeChooser *chooser)
+{
+        GtkListStore         *store;
+        GtkWidget            *treeview;
+        GtkCellRenderer      *renderer;
+        GtkTreeViewColumn    *column;
+        GtkTreeSelection     *selection;
+
+        treeview = gtk_tree_view_new ();
+
+        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
+        g_signal_connect (G_OBJECT (treeview),
+                          "row-activated",
+                          G_CALLBACK (on_treeview_row_activated),
+                          chooser);
+
+        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+        gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+        g_signal_connect (G_OBJECT (selection),
+                          "changed",
+                          G_CALLBACK (on_treeview_selection_changed),
+                          chooser);
+
+        /* Setup the tree model, 3 columns:
+         * - display name
+         * - sound id
+         * - sound type
+         */
+        store = gtk_list_store_new (ALERT_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_BOOLEAN);
+
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           ALERT_IDENTIFIER_COL, DEFAULT_ALERT_ID,
+                                           ALERT_DISPLAY_COL, _("Default"),
+                                           ALERT_SOUND_TYPE_COL, _("From theme"),
+                                           ALERT_ACTIVE_COL, TRUE,
+                                           -1);
+
+        populate_model_from_dir (chooser, GTK_TREE_MODEL (store), SOUND_SET_DIR);
+
+        gtk_tree_view_set_model (GTK_TREE_VIEW (treeview),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_toggle_new ();
+        gtk_cell_renderer_toggle_set_radio (GTK_CELL_RENDERER_TOGGLE (renderer), TRUE);
+
+        column = gtk_tree_view_column_new_with_attributes (NULL,
+                                                           renderer,
+                                                           "active", ALERT_ACTIVE_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+        g_signal_connect (renderer,
+                          "toggled",
+                          G_CALLBACK (on_alert_toggled),
+                          chooser);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Name"),
+                                                           renderer,
+                                                           "text", ALERT_DISPLAY_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Type"),
+                                                           renderer,
+                                                           "text", ALERT_SOUND_TYPE_COL,
+                                                           NULL);
+
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        return treeview;
+}
+
+static int
+get_file_type (const char *sound_name,
+               char      **linked_name)
+{
+        char *name, *filename;
+
+        *linked_name = NULL;
+
+        name = g_strdup_printf ("%s.disabled", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_REGULAR) != FALSE) {
+                g_free (filename);
+                return SOUND_TYPE_OFF;
+        }
+        g_free (filename);
+
+        /* We only check for .ogg files because those are the
+         * only ones we create */
+        name = g_strdup_printf ("%s.ogg", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_SYMLINK) != FALSE) {
+                *linked_name = g_file_read_link (filename, NULL);
+                g_free (filename);
+                return SOUND_TYPE_CUSTOM;
+        }
+        g_free (filename);
+
+        return SOUND_TYPE_BUILTIN;
+}
+
+static void
+update_alerts_from_theme_name (GvcSoundThemeChooser *chooser,
+                               const gchar          *name)
+{
+        if (strcmp (name, CUSTOM_THEME_NAME) != 0) {
+                /* reset alert to default */
+                update_alert (chooser, DEFAULT_ALERT_ID);
+        } else {
+                int   sound_type;
+                char *linkname;
+
+                linkname = NULL;
+                sound_type = get_file_type ("bell-terminal", &linkname);
+                g_debug ("Found link: %s", linkname);
+                if (sound_type == SOUND_TYPE_CUSTOM) {
+                        update_alert (chooser, linkname);
+                }
+        }
+}
+
+static void
+update_theme (GvcSoundThemeChooser *chooser)
+{
+        char        *theme_name;
+        gboolean     events_enabled;
+        gboolean     feedback_enabled;
+
+        feedback_enabled = g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY);
+        set_input_feedback_enabled (chooser, feedback_enabled);
+
+        events_enabled = g_settings_get_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY);
+        if (events_enabled) {
+                theme_name = g_settings_get_string (chooser->priv->sound_settings, SOUND_THEME_KEY);
+        } else {
+                theme_name = g_strdup (NO_SOUNDS_THEME_NAME);
+        }
+
+        gtk_widget_set_sensitive (chooser->priv->selection_box, events_enabled);
+        gtk_widget_set_sensitive (chooser->priv->click_feedback_button, events_enabled);
+
+        set_combox_for_theme_name (chooser, theme_name);
+
+        update_alerts_from_theme_name (chooser, theme_name);
+
+        g_free (theme_name);
+}
+
+static void
+gvc_sound_theme_chooser_class_init (GvcSoundThemeChooserClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_sound_theme_chooser_dispose;
+}
+
+static void
+on_click_feedback_toggled (GtkToggleButton      *button,
+                           GvcSoundThemeChooser *chooser)
+{
+        gboolean enabled;
+
+        enabled = gtk_toggle_button_get_active (button);
+
+        g_settings_set_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY, enabled);
+}
+
+static void
+on_key_changed (GSettings            *settings,
+                gchar                *key,
+                GvcSoundThemeChooser *chooser)
+{
+        if (!strcmp (key, EVENT_SOUNDS_KEY) ||
+            !strcmp (key, SOUND_THEME_KEY) ||
+            !strcmp (key, INPUT_SOUNDS_KEY))
+                update_theme (chooser);
+}
+
+static void
+setup_list_size_constraint (GtkWidget *widget,
+                            GtkWidget *to_size)
+{
+        GtkRequisition req;
+        gint           sc_height;
+        int            max_height;
+
+        /* Constrain height to be the tree height up to a max */
+        gdk_window_get_geometry (gdk_screen_get_root_window (gtk_widget_get_screen (widget)),
+                                 NULL, NULL, NULL, &sc_height);
+
+        max_height = sc_height / 4;
+
+        // XXX this doesn't work
+        gtk_widget_get_preferred_size (to_size, NULL, &req);
+
+        gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (widget),
+                                                    MIN (req.height, max_height));
+}
+
+static void
+gvc_sound_theme_chooser_init (GvcSoundThemeChooser *chooser)
+{
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *scrolled_window;
+        gchar       *str;
+
+        chooser->priv = gvc_sound_theme_chooser_get_instance_private (chooser);
+
+        chooser->priv->theme_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->theme_box, FALSE, FALSE, 0);
+
+        label = gtk_label_new_with_mnemonic (_("Sound _theme:"));
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), label, FALSE, FALSE, 0);
+        chooser->priv->combo_box = gtk_combo_box_new ();
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), chooser->priv->combo_box, FALSE, FALSE, 6);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->combo_box);
+
+        chooser->priv->sound_settings = g_settings_new (KEY_SOUNDS_SCHEMA);
+
+        g_signal_connect (G_OBJECT (chooser->priv->sound_settings),
+                          "changed",
+                          G_CALLBACK (on_key_changed),
+                          chooser);
+
+        str = g_strdup_printf ("<b>%s</b>", _("C_hoose an alert sound:"));
+        chooser->priv->selection_box = box = gtk_frame_new (str);
+        g_free (str);
+
+        label = gtk_frame_get_label_widget (GTK_FRAME (box));
+        gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
+        gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+        gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
+
+        gtk_box_pack_start (GTK_BOX (chooser), box, TRUE, TRUE, 6);
+
+        chooser->priv->treeview = create_alert_treeview (chooser);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->treeview);
+
+        scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+        gtk_widget_set_hexpand (scrolled_window, TRUE);
+        gtk_widget_set_vexpand (scrolled_window, TRUE);
+        gtk_widget_set_margin_top (scrolled_window, 6);
+
+        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+                                        GTK_POLICY_NEVER,
+                                        GTK_POLICY_AUTOMATIC);
+        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
+                                             GTK_SHADOW_IN);
+
+        gtk_container_add (GTK_CONTAINER (scrolled_window), chooser->priv->treeview);
+        gtk_container_add (GTK_CONTAINER (box), scrolled_window);
+
+        chooser->priv->click_feedback_button = gtk_check_button_new_with_mnemonic (_("Enable _window and button sounds"));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY));
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->click_feedback_button,
+                            FALSE, FALSE, 0);
+
+        g_signal_connect (G_OBJECT (chooser->priv->click_feedback_button),
+                          "toggled",
+                          G_CALLBACK (on_click_feedback_toggled),
+                          chooser);
+
+        setup_theme_selector (chooser);
+        update_theme (chooser);
+
+        setup_list_size_constraint (scrolled_window, chooser->priv->treeview);
+}
+
+static void
+gvc_sound_theme_chooser_dispose (GObject *object)
+{
+        GvcSoundThemeChooser *chooser;
+
+        chooser = GVC_SOUND_THEME_CHOOSER (object);
+
+        g_clear_object (&chooser->priv->sound_settings);
+
+        G_OBJECT_CLASS (gvc_sound_theme_chooser_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_sound_theme_chooser_new (void)
+{
+        return g_object_new (GVC_TYPE_SOUND_THEME_CHOOSER,
+                                "spacing", 6,
+                                "orientation", GTK_ORIENTATION_VERTICAL,
+                                NULL);
+}
+
+
+
+
+ + + diff --git a/2020-08-18-164117-7831-cppcheck@af4178682b21_master/2.html b/2020-08-18-164117-7831-cppcheck@af4178682b21_master/2.html new file mode 100644 index 0000000..64940b3 --- /dev/null +++ b/2020-08-18-164117-7831-cppcheck@af4178682b21_master/2.html @@ -0,0 +1,1126 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + +
+ +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <canberra.h>
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-speaker-test.h"
+#include "gvc-utils.h"
+
+struct _GvcSpeakerTestPrivate
+{
+        GArray           *controls;
+        ca_context       *canberra;
+        MateMixerStream  *stream;
+};
+
+enum {
+        PROP_0,
+        PROP_STREAM,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_speaker_test_dispose    (GObject             *object);
+static void gvc_speaker_test_finalize   (GObject             *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSpeakerTest, gvc_speaker_test, GTK_TYPE_GRID)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+typedef struct {
+        MateMixerChannelPosition position;
+        guint left;
+        guint top;
+} TablePosition;
+
+static const TablePosition positions[] = {
+        /* Position, X, Y */
+        { MATE_MIXER_CHANNEL_FRONT_LEFT, 0, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_LEFT_CENTER, 1, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_CENTER, 2, 0, },
+        { MATE_MIXER_CHANNEL_MONO, 2, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT_CENTER, 3, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT, 4, 0, },
+        { MATE_MIXER_CHANNEL_SIDE_LEFT, 0, 1, },
+        { MATE_MIXER_CHANNEL_SIDE_RIGHT, 4, 1, },
+        { MATE_MIXER_CHANNEL_BACK_LEFT, 0, 2, },
+        { MATE_MIXER_CHANNEL_BACK_CENTER, 2, 2, },
+        { MATE_MIXER_CHANNEL_BACK_RIGHT, 4, 2, },
+        { MATE_MIXER_CHANNEL_LFE, 3, 2 }
+};
+
+MateMixerStream *
+gvc_speaker_test_get_stream (GvcSpeakerTest *test)
+{
+        g_return_val_if_fail (GVC_IS_SPEAKER_TEST (test), NULL);
+
+        return test->priv->stream;
+}
+
+static void
+gvc_speaker_test_set_stream (GvcSpeakerTest *test, MateMixerStream *stream)
+{
+        MateMixerStreamControl *control;
+        const gchar            *name;
+        guint                   i;
+
+        name = mate_mixer_stream_get_name (stream);
+        control = mate_mixer_stream_get_default_control (stream);
+
+        ca_context_change_device (test->priv->canberra, name);
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                gboolean has_position =
+                        mate_mixer_stream_control_has_channel_position (control, positions[i].position);
+
+                gtk_widget_set_visible (g_array_index (test->priv->controls, GtkWidget *, i),
+                                        has_position);
+        }
+
+        test->priv->stream = g_object_ref (stream);
+}
+
+static void
+gvc_speaker_test_set_property (GObject       *object,
+                               guint          prop_id,
+                               const GValue  *value,
+                               GParamSpec    *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                gvc_speaker_test_set_stream (self, g_value_get_object (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_get_property (GObject     *object,
+                               guint        prop_id,
+                               GValue      *value,
+                               GParamSpec  *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                g_value_set_object (value, self->priv->stream);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_class_init (GvcSpeakerTestClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose  = gvc_speaker_test_dispose;
+        object_class->finalize = gvc_speaker_test_finalize;
+        object_class->set_property = gvc_speaker_test_set_property;
+        object_class->get_property = gvc_speaker_test_get_property;
+
+        properties[PROP_STREAM] =
+                g_param_spec_object ("stream",
+                                     "Stream",
+                                     "MateMixer stream",
+                                     MATE_MIXER_TYPE_STREAM,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+}
+
+static const gchar *
+sound_name (MateMixerChannelPosition position)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return "audio-channel-front-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return "audio-channel-front-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return "audio-channel-front-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return "audio-channel-rear-left";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return "audio-channel-rear-right";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return "audio-channel-rear-center";
+        case MATE_MIXER_CHANNEL_LFE:
+                return "audio-channel-lfe";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return "audio-channel-side-left";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return "audio-channel-side-right";
+        default:
+                return NULL;
+        }
+}
+
+static const gchar *
+icon_name (MateMixerChannelPosition position, gboolean playing)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return playing
+                        ? "audio-speaker-left-testing"
+                        : "audio-speaker-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return playing
+                        ? "audio-speaker-right-testing"
+                        : "audio-speaker-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return playing
+                        ? "audio-speaker-center-testing"
+                        : "audio-speaker-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return playing
+                        ? "audio-speaker-left-back-testing"
+                        : "audio-speaker-left-back";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return playing
+                        ? "audio-speaker-right-back-testing"
+                        : "audio-speaker-right-back";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return playing
+                        ? "audio-speaker-center-back-testing"
+                        : "audio-speaker-center-back";
+        case MATE_MIXER_CHANNEL_LFE:
+                return playing
+                        ? "audio-subwoofer-testing"
+                        : "audio-subwoofer";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return playing
+                        ? "audio-speaker-left-side-testing"
+                        : "audio-speaker-left-side";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return playing
+                        ? "audio-speaker-right-side-testing"
+                        : "audio-speaker-right-side";
+        default:
+                return NULL;
+        }
+}
+
+static void
+update_button (GtkWidget *control)
+{
+        GtkWidget *button;
+        GtkWidget *image;
+        gboolean   playing;
+        MateMixerChannelPosition position;
+
+        button = g_object_get_data (G_OBJECT (control), "button");
+        image  = g_object_get_data (G_OBJECT (control), "image");
+
+        position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+        playing  = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        gtk_button_set_label (GTK_BUTTON (button), playing ? _("Stop") : _("Test"));
+
+        gtk_image_set_from_icon_name (GTK_IMAGE (image),
+                                      icon_name (position, playing),
+                                      GTK_ICON_SIZE_DIALOG);
+}
+
+static gboolean
+idle_cb (GtkWidget *control)
+{
+        if (control != NULL) {
+                /* This is called in the background thread, hence forward to main thread
+                 * via idle callback */
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+
+                update_button (control);
+        }
+        return FALSE;
+}
+
+static void
+finish_cb (ca_context *c, uint32_t id, int error_code, void *userdata)
+{
+        GtkWidget *control = (GtkWidget *) userdata;
+
+        if (error_code == CA_ERROR_DESTROYED || control == NULL)
+                return;
+
+        g_idle_add ((GSourceFunc) idle_cb, control);
+}
+
+static void
+on_test_button_clicked (GtkButton *button, GtkWidget *control)
+{
+        gboolean    playing;
+        ca_context *canberra;
+
+        canberra = g_object_get_data (G_OBJECT (control), "canberra");
+
+        ca_context_cancel (canberra, 1);
+
+        playing = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        if (playing) {
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        } else {
+                MateMixerChannelPosition position;
+                const gchar *name;
+                ca_proplist *proplist;
+
+                position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+
+                ca_proplist_create (&proplist);
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_ROLE, "test");
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_NAME,
+                                  gvc_channel_position_to_pretty_string (position));
+                ca_proplist_sets (proplist,
+                                  CA_PROP_CANBERRA_FORCE_CHANNEL,
+                                  gvc_channel_position_to_pulse_string (position));
+
+                ca_proplist_sets (proplist, CA_PROP_CANBERRA_ENABLE, "1");
+
+                name = sound_name (position);
+                if (name != NULL) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, name);
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, "audio-test-signal");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets(proplist, CA_PROP_EVENT_ID, "bell-window-system");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (playing));
+        }
+
+        update_button (control);
+}
+
+static GtkWidget *
+create_control (ca_context *canberra, MateMixerChannelPosition position)
+{
+        GtkWidget   *control;
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *image;
+        GtkWidget   *test_button;
+        const gchar *name;
+
+        control = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+        box     = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        g_object_set_data (G_OBJECT (control), "position", GINT_TO_POINTER (position));
+        g_object_set_data (G_OBJECT (control), "canberra", canberra);
+
+        name = icon_name (position, FALSE);
+        if (name == NULL)
+                name = "audio-volume-medium";
+
+        image = gtk_image_new_from_icon_name (name, GTK_ICON_SIZE_DIALOG);
+        g_object_set_data (G_OBJECT (control), "image", image);
+        gtk_box_pack_start (GTK_BOX (control), image, FALSE, FALSE, 0);
+
+        label = gtk_label_new (gvc_channel_position_to_pretty_string (position));
+        gtk_box_pack_start (GTK_BOX (control), label, FALSE, FALSE, 0);
+
+        test_button = gtk_button_new_with_label (_("Test"));
+        g_signal_connect (G_OBJECT (test_button),
+                          "clicked",
+                          G_CALLBACK (on_test_button_clicked),
+                          control);
+
+        g_object_set_data (G_OBJECT (control), "button", test_button);
+
+        gtk_box_pack_start (GTK_BOX (box), test_button, TRUE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (control), box, FALSE, FALSE, 0);
+
+        gtk_widget_show_all (control);
+
+        return control;
+}
+
+static void
+create_controls (GvcSpeakerTest *test)
+{
+        guint i;
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                GtkWidget *control = create_control (test->priv->canberra, positions[i].position);
+
+                gtk_grid_attach (GTK_GRID (test),
+                                 control,
+                                 positions[i].left,
+                                 positions[i].top,
+                                 1, 1);
+                g_array_insert_val (test->priv->controls, i, control);
+        }
+}
+
+static void
+gvc_speaker_test_init (GvcSpeakerTest *test)
+{
+        GtkWidget *face;
+
+        test->priv = gvc_speaker_test_get_instance_private (test);
+
+        gtk_container_set_border_width (GTK_CONTAINER (test), 12);
+
+        face = gtk_image_new_from_icon_name ("face-smile", GTK_ICON_SIZE_DIALOG);
+
+        gtk_grid_attach (GTK_GRID (test),
+                         face,
+                         1, 1,
+                         3, 1);
+
+
+        gtk_grid_set_baseline_row (GTK_GRID (test), 1);
+        gtk_widget_show (face);
+
+        ca_context_create (&test->priv->canberra);
+
+        /* The test sounds are played for a single channel, set up using the
+         * FORCE_CHANNEL property of libcanberra; this property is only supported
+         * in the PulseAudio backend, so avoid other backends completely */
+        ca_context_set_driver (test->priv->canberra, "pulse");
+
+        ca_context_change_props (test->priv->canberra,
+                                 CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+                                 CA_PROP_APPLICATION_NAME, _("Volume Control"),
+                                 CA_PROP_APPLICATION_VERSION, VERSION,
+                                 CA_PROP_APPLICATION_ICON_NAME, "multimedia-volume-control",
+                                 NULL);
+
+        test->priv->controls = g_array_new (FALSE, FALSE, sizeof (GtkWidget *));
+
+        create_controls (test);
+}
+
+static void
+gvc_speaker_test_dispose (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        g_clear_object (&test->priv->stream);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->dispose (object);
+}
+
+static void
+gvc_speaker_test_finalize (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        ca_context_destroy (test->priv->canberra);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->finalize (object);
+}
+
+GtkWidget *
+gvc_speaker_test_new (MateMixerStream *stream)
+{
+        GObject *test;
+
+        g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL);
+
+        test = g_object_new (GVC_TYPE_SPEAKER_TEST,
+                             "row-spacing", 6,
+                             "column-spacing", 6,
+                             "row-homogeneous", TRUE,
+                             "column-homogeneous", TRUE,
+                             "stream", stream,
+                             NULL);
+
+        return GTK_WIDGET (test);
+}
+
+
+
+
+ + + diff --git a/2020-08-18-164117-7831-cppcheck@af4178682b21_master/index.html b/2020-08-18-164117-7831-cppcheck@af4178682b21_master/index.html new file mode 100644 index 0000000..235f646 --- /dev/null +++ b/2020-08-18-164117-7831-cppcheck@af4178682b21_master/index.html @@ -0,0 +1,124 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + +
+ +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
mate-volume-control/gvc-combo-box.c
70unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
mate-volume-control/gvc-sound-theme-chooser.c
735ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
746ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
758ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
mate-volume-control/gvc-speaker-test.c
53unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+
+ + + diff --git a/2020-08-18-164117-7831-cppcheck@af4178682b21_master/stats.html b/2020-08-18-164117-7831-cppcheck@af4178682b21_master/stats.html new file mode 100644 index 0000000..6eb8706 --- /dev/null +++ b/2020-08-18-164117-7831-cppcheck@af4178682b21_master/stats.html @@ -0,0 +1,109 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + +
+ +
+

Top 10 files for error severity, total findings: 2
+   1  mate-volume-control/gvc-speaker-test.c
+   1  mate-volume-control/gvc-combo-box.c
+

+

Top 10 files for information severity, total findings: 3
+   3  mate-volume-control/gvc-sound-theme-chooser.c
+

+ +
+
+ + + diff --git a/2020-08-18-164117-7831-cppcheck@af4178682b21_master/style.css b/2020-08-18-164117-7831-cppcheck@af4178682b21_master/style.css new file mode 100644 index 0000000..07125f4 --- /dev/null +++ b/2020-08-18-164117-7831-cppcheck@af4178682b21_master/style.css @@ -0,0 +1,137 @@ + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; + font-size: 13px; + line-height: 1.5; + margin: 0; + width: auto; +} + +h1 { + margin: 10px; +} + +.header { + border-bottom: thin solid #aaa; +} + +.footer { + border-top: thin solid #aaa; + font-size: 90%; + margin-top: 5px; +} + +.footer ul { + list-style-type: none; + padding-left: 0; +} + +.footer > p { + margin: 4px; +} + +.wrapper { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; +} + +#menu, +#menu_index { + text-align: left; + width: 350px; + height: 90vh; + min-height: 200px; + overflow: auto; + position: -webkit-sticky; + position: sticky; + top: 0; + padding: 0 15px 15px 15px; +} + +#menu > a { + display: block; + margin-left: 10px; + font-size: 12px; + z-index: 1; +} + +#content, +#content_index { + background-color: #fff; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + padding: 0 15px 15px 15px; + width: calc(100% - 350px); + height: 100%; + overflow-x: auto; +} + +#filename { + margin-left: 10px; + font-size: 12px; + z-index: 1; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #b6b6b4; +} + +.inconclusive2 { + background-color: #b6b6b4; + display: inline-block; + margin-left: 4px; +} + +.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +.verbose .content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid #000; + background-color: #ffffcc; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +.highlighttable { + background-color: #fff; + z-index: 10; + position: relative; + margin: -10px; +} + +.linenos { + border-right: thin solid #aaa; + color: #d3d3d3; + padding-right: 6px; +} + +.d-none { + display: none; +} diff --git a/2020-08-18-170145-8061-cppcheck@c82f5feb6c8f_master/0.html b/2020-08-18-170145-8061-cppcheck@c82f5feb6c8f_master/0.html new file mode 100644 index 0000000..5bf183e --- /dev/null +++ b/2020-08-18-170145-8061-cppcheck@c82f5feb6c8f_master/0.html @@ -0,0 +1,1054 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + +
+ +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-combo-box.h"
+
+struct _GvcComboBoxPrivate
+{
+        GtkWidget       *drop_box;
+        GtkWidget       *start_box;
+        GtkWidget       *end_box;
+        GtkWidget       *label;
+        GtkWidget       *button;
+        GtkTreeModel    *model;
+        GtkWidget       *combobox;
+        MateMixerSwitch *swtch;
+};
+
+enum {
+        COL_NAME,
+        COL_HUMAN_NAME,
+        NUM_COLS
+};
+
+enum {
+        CHANGING,
+        BUTTON_CLICKED,
+        LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+enum {
+        PROP_0,
+        PROP_SWITCH,
+        PROP_LABEL,
+        PROP_SHOW_BUTTON,
+        PROP_BUTTON_LABEL,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_combo_box_dispose    (GObject          *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcComboBox, gvc_combo_box, GTK_TYPE_BOX)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+MateMixerSwitch *
+gvc_combo_box_get_switch (GvcComboBox *combobox)
+{
+        g_return_val_if_fail (GVC_IS_COMBO_BOX (combobox), NULL);
+
+        return combobox->priv->swtch;
+}
+
+void
+gvc_combo_box_set_size_group (GvcComboBox  *combobox,
+                              GtkSizeGroup *group,
+                              gboolean      symmetric)
+{
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (GTK_IS_SIZE_GROUP (group));
+
+        if (group != NULL) {
+                gtk_size_group_add_widget (group, combobox->priv->start_box);
+                if (symmetric == TRUE)
+                        gtk_size_group_add_widget (group, combobox->priv->end_box);
+        }
+        gtk_widget_queue_draw (GTK_WIDGET (combobox));
+}
+
+static void
+on_switch_active_option_notify (MateMixerSwitch *swtch,
+                                GParamSpec      *pspec,
+                                GvcComboBox     *combobox)
+{
+        GtkTreeIter            iter;
+        MateMixerSwitchOption *active;
+        gboolean               cont;
+        const gchar           *name;
+
+        active = mate_mixer_switch_get_active_option (swtch);
+        if (G_UNLIKELY (active == NULL)) {
+                g_warn_if_reached ();
+                return;
+        }
+
+        /* Select the newly activated switch option in the combo box */
+        name = mate_mixer_switch_option_get_name (active);
+        cont = gtk_tree_model_get_iter_first (combobox->priv->model, &iter);
+        while (cont == TRUE) {
+                gchar *current;
+
+                gtk_tree_model_get (combobox->priv->model, &iter,
+                                    COL_NAME, &current,
+                                    -1);
+                if (g_strcmp0 (name, current) == 0) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox), &iter);
+                        g_free (current);
+                        return;
+                }
+                g_free (current);
+
+                cont = gtk_tree_model_iter_next (combobox->priv->model, &iter);
+        }
+        g_warning ("Could not find switch option '%s' in combo box", name);
+}
+
+static void
+gvc_combo_box_set_switch (GvcComboBox *combobox, MateMixerSwitch *swtch)
+{
+        MateMixerSwitchOption *active;
+        const GList           *options;
+
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (MATE_MIXER_IS_SWITCH (swtch));
+
+        combobox->priv->swtch = g_object_ref (swtch);
+
+        active  = mate_mixer_switch_get_active_option (swtch);
+        options = mate_mixer_switch_list_options (swtch);
+        while (options != NULL) {
+                GtkTreeIter            iter;
+                MateMixerSwitchOption *option = MATE_MIXER_SWITCH_OPTION (options->data);
+
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (combobox->priv->model),
+                                                   &iter,
+                                                   G_MAXINT,
+                                                   COL_NAME,
+                                                   mate_mixer_switch_option_get_name (option),
+                                                   COL_HUMAN_NAME,
+                                                   mate_mixer_switch_option_get_label (option),
+                                                   -1);
+
+                /* Select the currently active option of the switch */
+                if (option == active) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox),
+                                                       &iter);
+                }
+                options = options->next;
+        }
+
+        g_signal_connect (G_OBJECT (swtch),
+                          "notify::active-option",
+                          G_CALLBACK (on_switch_active_option_notify),
+                          combobox);
+}
+
+static void
+gvc_combo_box_set_property (GObject       *object,
+                            guint          prop_id,
+                            const GValue  *value,
+                            GParamSpec    *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                gvc_combo_box_set_switch (self, g_value_get_object (value));
+                break;
+        case PROP_LABEL:
+                gtk_label_set_text_with_mnemonic (GTK_LABEL (self->priv->label), g_value_get_string (value));
+                break;
+        case PROP_BUTTON_LABEL:
+                gtk_button_set_label (GTK_BUTTON (self->priv->button), g_value_get_string (value));
+                break;
+        case PROP_SHOW_BUTTON:
+                gtk_widget_set_visible (self->priv->button, g_value_get_boolean (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_get_property (GObject     *object,
+                            guint        prop_id,
+                            GValue      *value,
+                            GParamSpec  *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                g_value_set_object (value, self->priv->swtch);
+                break;
+        case PROP_LABEL:
+                g_value_set_string (value, gtk_label_get_text (GTK_LABEL (self->priv->label)));
+                break;
+        case PROP_BUTTON_LABEL:
+                g_value_set_string (value, gtk_button_get_label (GTK_BUTTON (self->priv->button)));
+                break;
+        case PROP_SHOW_BUTTON:
+                g_value_set_boolean (value, gtk_widget_get_visible (self->priv->button));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_class_init (GvcComboBoxClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_combo_box_dispose;
+        object_class->set_property = gvc_combo_box_set_property;
+        object_class->get_property = gvc_combo_box_get_property;
+
+        properties[PROP_SWITCH] =
+                g_param_spec_object ("switch",
+                                     "switch",
+                                     "The MateMixerSwitch",
+                                     MATE_MIXER_TYPE_SWITCH,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_LABEL] =
+                g_param_spec_string ("label",
+                                     "label",
+                                     "The combo box label",
+                                     _("_Profile:"),
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_SHOW_BUTTON] =
+                g_param_spec_boolean ("show-button",
+                                      "show-button",
+                                      "Whether to show the button",
+                                      FALSE,
+                                      G_PARAM_READWRITE |
+                                      G_PARAM_CONSTRUCT |
+                                      G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_BUTTON_LABEL] =
+                g_param_spec_string ("button-label",
+                                     "button-label",
+                                     "The button's label",
+                                     "",
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+
+        signals[CHANGING] =
+                g_signal_new ("changing",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, changing),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__OBJECT,
+                              G_TYPE_NONE,
+                              1,
+                              MATE_MIXER_TYPE_SWITCH_OPTION);
+
+        signals[BUTTON_CLICKED] =
+                g_signal_new ("button-clicked",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, button_clicked),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
+}
+
+static void
+on_combo_box_changed (GtkComboBox *widget, GvcComboBox *combobox)
+{
+        GtkTreeIter            iter;
+        gchar                 *name;
+        MateMixerSwitchOption *option;
+
+        if (G_UNLIKELY (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter) == FALSE))
+                return;
+
+        gtk_tree_model_get (combobox->priv->model, &iter,
+                            COL_NAME, &name,
+                            -1);
+
+        option = mate_mixer_switch_get_option (combobox->priv->swtch, name);
+        if (G_UNLIKELY (option == NULL)) {
+                g_warn_if_reached ();
+                g_free (name);
+                return;
+        }
+
+        /* Inform that we are about to change the active option of the switch */
+        g_signal_emit (combobox, signals[CHANGING], 0, option);
+
+        mate_mixer_switch_set_active_option (combobox->priv->swtch, option);
+        g_free (name);
+}
+
+static void
+on_combo_box_button_clicked (GtkButton *button, GvcComboBox *combobox)
+{
+        /* The meaning of the button is defined by the owner, so only notify
+         * when it is clicked on */
+        g_signal_emit (combobox, signals[BUTTON_CLICKED], 0);
+}
+
+static void
+gvc_combo_box_init (GvcComboBox *combobox)
+{
+        GtkWidget       *frame;
+        GtkCellRenderer *renderer;
+
+        frame = gtk_frame_new (NULL);
+        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
+
+        combobox->priv = gvc_combo_box_get_instance_private (combobox);
+
+        combobox->priv->model = GTK_TREE_MODEL (gtk_list_store_new (NUM_COLS,
+                                                                    G_TYPE_STRING,
+                                                                    G_TYPE_STRING));
+
+        combobox->priv->combobox = gtk_combo_box_new_with_model (combobox->priv->model);
+
+        combobox->priv->label = gtk_label_new (NULL);
+
+        gtk_label_set_xalign (GTK_LABEL (combobox->priv->label), 0.0);
+        gtk_label_set_yalign (GTK_LABEL (combobox->priv->label), 0.5);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (combobox->priv->label),
+                                       combobox->priv->combobox);
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                    renderer,
+                                    FALSE);
+        gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                       renderer,
+                                       "text",
+                                       COL_HUMAN_NAME);
+
+        combobox->priv->drop_box  = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->start_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->end_box   = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+        /* Make sure the combo box does not get too long on long profile names */
+        g_object_set (G_OBJECT (renderer),
+                      "ellipsize",
+                      PANGO_ELLIPSIZE_END,
+                      NULL);
+
+        gtk_combo_box_set_popup_fixed_width (GTK_COMBO_BOX (combobox->priv->combobox), FALSE);
+
+        gtk_box_pack_start (GTK_BOX (combobox),
+                            frame,
+                            TRUE, TRUE, 0);
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->start_box,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->start_box),
+                            combobox->priv->label,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->combobox,
+                            TRUE, TRUE, 0);
+
+        combobox->priv->button = gtk_button_new_with_label ("");
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->button,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->end_box,
+                            FALSE, FALSE, 0);
+
+        gtk_container_add (GTK_CONTAINER (frame), combobox->priv->drop_box);
+
+        g_signal_connect (G_OBJECT (combobox->priv->combobox),
+                          "changed",
+                          G_CALLBACK (on_combo_box_changed),
+                          combobox);
+        g_signal_connect (G_OBJECT (combobox->priv->button),
+                          "clicked",
+                          G_CALLBACK (on_combo_box_button_clicked),
+                          combobox);
+
+        gtk_widget_set_no_show_all (combobox->priv->button, TRUE);
+        gtk_widget_show_all (frame);
+}
+
+static void
+gvc_combo_box_dispose (GObject *object)
+{
+        GvcComboBox *combobox;
+
+        combobox = GVC_COMBO_BOX (object);
+
+        if (G_LIKELY (combobox->priv->swtch != NULL)) {
+                g_signal_handlers_disconnect_by_func (G_OBJECT (combobox->priv->swtch),
+                                                      G_CALLBACK (on_switch_active_option_notify),
+                                                      combobox);
+                g_clear_object (&combobox->priv->swtch);
+        }
+
+        g_clear_object (&combobox->priv->model);
+
+        G_OBJECT_CLASS (gvc_combo_box_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_combo_box_new (MateMixerSwitch *swtch, const gchar *label)
+{
+        return g_object_new (GVC_TYPE_COMBO_BOX,
+                             "switch", swtch,
+                             "label", label,
+                             "orientation", GTK_ORIENTATION_HORIZONTAL,
+                             NULL);
+}
+
+
+
+
+ + + diff --git a/2020-08-18-170145-8061-cppcheck@c82f5feb6c8f_master/1.html b/2020-08-18-170145-8061-cppcheck@c82f5feb6c8f_master/1.html new file mode 100644 index 0000000..9fd449d --- /dev/null +++ b/2020-08-18-170145-8061-cppcheck@c82f5feb6c8f_master/1.html @@ -0,0 +1,2384 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + +
+ +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
+ * Copyright (C) 2008 William Jon McCann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <utime.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+#include <canberra-gtk.h>
+#include <libxml/tree.h>
+
+#include "gvc-sound-theme-chooser.h"
+#include "sound-theme-file-utils.h"
+
+struct GvcSoundThemeChooserPrivate
+{
+        GtkWidget *combo_box;
+        GtkWidget *treeview;
+        GtkWidget *theme_box;
+        GtkWidget *selection_box;
+        GtkWidget *click_feedback_button;
+        GSettings *sound_settings;
+};
+
+static void     gvc_sound_theme_chooser_dispose   (GObject            *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSoundThemeChooser, gvc_sound_theme_chooser, GTK_TYPE_BOX)
+
+#define KEY_SOUNDS_SCHEMA          "org.mate.sound"
+#define EVENT_SOUNDS_KEY           "event-sounds"
+#define INPUT_SOUNDS_KEY           "input-feedback-sounds"
+#define SOUND_THEME_KEY            "theme-name"
+
+#define DEFAULT_ALERT_ID        "__default"
+#define CUSTOM_THEME_NAME       "__custom"
+#define NO_SOUNDS_THEME_NAME    "__no_sounds"
+
+enum {
+        THEME_DISPLAY_COL,
+        THEME_IDENTIFIER_COL,
+        THEME_PARENT_ID_COL,
+        THEME_NUM_COLS
+};
+
+enum {
+        ALERT_DISPLAY_COL,
+        ALERT_IDENTIFIER_COL,
+        ALERT_SOUND_TYPE_COL,
+        ALERT_ACTIVE_COL,
+        ALERT_NUM_COLS
+};
+
+enum {
+        SOUND_TYPE_UNSET,
+        SOUND_TYPE_OFF,
+        SOUND_TYPE_DEFAULT_FROM_THEME,
+        SOUND_TYPE_BUILTIN,
+        SOUND_TYPE_CUSTOM
+};
+
+static void
+on_combobox_changed (GtkComboBox          *widget,
+                     GvcSoundThemeChooser *chooser)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        char         *theme_name;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &theme_name, -1);
+
+        g_assert (theme_name != NULL);
+
+        /* It is necessary to update the theme name before any other setting as
+         * the "changed" notification will reload the contents of the widget */
+        g_settings_set_string (chooser->priv->sound_settings, SOUND_THEME_KEY, theme_name);
+
+        /* special case for no sounds */
+        if (strcmp (theme_name, NO_SOUNDS_THEME_NAME) == 0) {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, FALSE);
+                return;
+        } else {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, TRUE);
+        }
+
+        g_free (theme_name);
+
+        /* FIXME: reset alert model */
+}
+
+static char *
+load_index_theme_name (const char *index,
+                       char      **parent)
+{
+        GKeyFile *file;
+        char *indexname = NULL;
+        gboolean hidden;
+
+        file = g_key_file_new ();
+        if (g_key_file_load_from_file (file, index, G_KEY_FILE_KEEP_TRANSLATIONS, NULL) == FALSE) {
+                g_key_file_free (file);
+                return NULL;
+        }
+        /* Don't add hidden themes to the list */
+        hidden = g_key_file_get_boolean (file, "Sound Theme", "Hidden", NULL);
+        if (!hidden) {
+                indexname = g_key_file_get_locale_string (file,
+                                                          "Sound Theme",
+                                                          "Name",
+                                                          NULL,
+                                                          NULL);
+
+                /* Save the parent theme, if there's one */
+                if (parent != NULL) {
+                        *parent = g_key_file_get_string (file,
+                                                         "Sound Theme",
+                                                         "Inherits",
+                                                         NULL);
+                }
+        }
+
+        g_key_file_free (file);
+        return indexname;
+}
+
+static void
+sound_theme_in_dir (GHashTable *hash,
+                    const char *dir)
+{
+        GDir *d;
+        const char *name;
+
+        d = g_dir_open (dir, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *dirname, *index, *indexname;
+
+                /* Look for directories */
+                dirname = g_build_filename (dir, name, NULL);
+                if (g_file_test (dirname, G_FILE_TEST_IS_DIR) == FALSE) {
+                        g_free (dirname);
+                        continue;
+                }
+
+                /* Look for index files */
+                index = g_build_filename (dirname, "index.theme", NULL);
+                g_free (dirname);
+
+                /* Check the name of the theme in the index.theme file */
+                indexname = load_index_theme_name (index, NULL);
+                g_free (index);
+                if (indexname == NULL) {
+                        continue;
+                }
+
+                g_hash_table_insert (hash, g_strdup (name), indexname);
+        }
+
+        g_dir_close (d);
+}
+
+static void
+add_theme_to_store (const char   *key,
+                    const char   *value,
+                    GtkListStore *store)
+{
+        char *parent;
+
+        parent = NULL;
+
+        /* Get the parent, if we're checking the custom theme */
+        if (strcmp (key, CUSTOM_THEME_NAME) == 0) {
+                char *name, *path;
+
+                path = custom_theme_dir_path ("index.theme");
+                name = load_index_theme_name (path, &parent);
+                g_free (name);
+                g_free (path);
+        }
+        gtk_list_store_insert_with_values (store, NULL, G_MAXINT,
+                                           THEME_DISPLAY_COL, value,
+                                           THEME_IDENTIFIER_COL, key,
+                                           THEME_PARENT_ID_COL, parent,
+                                           -1);
+        g_free (parent);
+}
+
+static void
+set_combox_for_theme_name (GvcSoundThemeChooser *chooser,
+                           const char           *name)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        gboolean      found;
+
+        /* If the name is empty, use "freedesktop" */
+        if (name == NULL || *name == '\0') {
+                name = "freedesktop";
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+        if (gtk_tree_model_get_iter_first (model, &iter) == FALSE) {
+                return;
+        }
+
+        do {
+                char *value;
+
+                gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &value, -1);
+                found = (value != NULL && strcmp (value, name) == 0);
+                g_free (value);
+
+        } while (!found && gtk_tree_model_iter_next (model, &iter));
+
+        /* When we can't find the theme we need to set, try to set the default
+         * one "freedesktop" */
+        if (found) {
+                gtk_combo_box_set_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter);
+        } else if (strcmp (name, "freedesktop") != 0) {
+                g_debug ("not found, falling back to fdo");
+                set_combox_for_theme_name (chooser, "freedesktop");
+        }
+}
+
+static void
+set_input_feedback_enabled (GvcSoundThemeChooser *chooser,
+                            gboolean              enabled)
+{
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      enabled);
+}
+
+static void
+setup_theme_selector (GvcSoundThemeChooser *chooser)
+{
+        GHashTable           *hash;
+        GtkListStore         *store;
+        GtkCellRenderer      *renderer;
+        const char * const   *data_dirs;
+        const char           *data_dir;
+        char                 *dir;
+        guint                 i;
+
+        /* Add the theme names and their display name to a hash table,
+         * makes it easy to avoid duplicate themes */
+        hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+        data_dirs = g_get_system_data_dirs ();
+        for (i = 0; data_dirs[i] != NULL; i++) {
+                dir = g_build_filename (data_dirs[i], "sounds", NULL);
+                sound_theme_in_dir (hash, dir);
+                g_free (dir);
+        }
+
+        data_dir = g_get_user_data_dir ();
+        dir = g_build_filename (data_dir, "sounds", NULL);
+        sound_theme_in_dir (hash, dir);
+        g_free (dir);
+
+        /* If there isn't at least one theme, make everything
+         * insensitive, LAME! */
+        if (g_hash_table_size (hash) == 0) {
+                gtk_widget_set_sensitive (GTK_WIDGET (chooser), FALSE);
+                g_warning ("Bad setup, install the freedesktop sound theme");
+                g_hash_table_destroy (hash);
+                return;
+        }
+
+        /* Setup the tree model, 3 columns:
+         * - internal theme name/directory
+         * - display theme name
+         * - the internal id for the parent theme, used for the custom theme */
+        store = gtk_list_store_new (THEME_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING);
+
+        /* Add the themes to a combobox */
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           THEME_DISPLAY_COL, _("No sounds"),
+                                           THEME_IDENTIFIER_COL, "__no_sounds",
+                                           THEME_PARENT_ID_COL, NULL,
+                                           -1);
+        g_hash_table_foreach (hash, (GHFunc) add_theme_to_store, store);
+        g_hash_table_destroy (hash);
+
+        /* Set the display */
+        gtk_combo_box_set_model (GTK_COMBO_BOX (chooser->priv->combo_box),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                    renderer,
+                                    TRUE);
+        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                        renderer,
+                                        "text", THEME_DISPLAY_COL,
+                                        NULL);
+
+        g_signal_connect (G_OBJECT (chooser->priv->combo_box),
+                          "changed",
+                          G_CALLBACK (on_combobox_changed),
+                          chooser);
+}
+
+#define GVC_SOUND_SOUND    (xmlChar *) "sound"
+#define GVC_SOUND_NAME     (xmlChar *) "name"
+#define GVC_SOUND_FILENAME (xmlChar *) "filename"
+
+/* Adapted from yelp-toc-pager.c */
+static xmlChar *
+xml_get_and_trim_names (xmlNodePtr node)
+{
+        xmlNodePtr cur;
+        xmlChar *keep_lang = NULL;
+        xmlChar *value;
+        int j, keep_pri = INT_MAX;
+
+        const gchar * const * langs = g_get_language_names ();
+
+        value = NULL;
+
+        for (cur = node->children; cur; cur = cur->next) {
+                if (! xmlStrcmp (cur->name, GVC_SOUND_NAME)) {
+                        xmlChar *cur_lang = NULL;
+                        int cur_pri = INT_MAX;
+
+                        cur_lang = xmlNodeGetLang (cur);
+
+                        if (cur_lang) {
+                                for (j = 0; langs[j]; j++) {
+                                        if (g_str_equal (cur_lang, langs[j])) {
+                                                cur_pri = j;
+                                                break;
+                                        }
+                                }
+                        } else {
+                                cur_pri = INT_MAX - 1;
+                        }
+
+                        if (cur_pri <= keep_pri) {
+                                if (keep_lang)
+                                        xmlFree (keep_lang);
+                                if (value)
+                                        xmlFree (value);
+
+                                value = xmlNodeGetContent (cur);
+
+                                keep_lang = cur_lang;
+                                keep_pri = cur_pri;
+                        } else {
+                                if (cur_lang)
+                                        xmlFree (cur_lang);
+                        }
+                }
+        }
+
+        /* Delete all GVC_SOUND_NAME nodes */
+        cur = node->children;
+        while (cur) {
+                xmlNodePtr this = cur;
+                cur = cur->next;
+                if (! xmlStrcmp (this->name, GVC_SOUND_NAME)) {
+                        xmlUnlinkNode (this);
+                        xmlFreeNode (this);
+                }
+        }
+
+        return value;
+}
+
+static void
+populate_model_from_node (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          xmlNodePtr            node)
+{
+        xmlNodePtr child;
+        xmlChar   *filename;
+        xmlChar   *name;
+
+        filename = NULL;
+        name = xml_get_and_trim_names (node);
+        for (child = node->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+
+                if (xmlStrcmp (child->name, GVC_SOUND_FILENAME) == 0) {
+                        filename = xmlNodeGetContent (child);
+                } else if (xmlStrcmp (child->name, GVC_SOUND_NAME) == 0) {
+                        /* EH? should have been trimmed */
+                }
+        }
+
+        if (filename != NULL && name != NULL) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   ALERT_IDENTIFIER_COL, filename,
+                                                   ALERT_DISPLAY_COL, name,
+                                                   ALERT_SOUND_TYPE_COL, _("Built-in"),
+                                                   ALERT_ACTIVE_COL, FALSE,
+                                                   -1);
+        }
+
+        xmlFree (filename);
+        xmlFree (name);
+}
+
+static void
+populate_model_from_file (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          const char           *filename)
+{
+        xmlDocPtr  doc;
+        xmlNodePtr root;
+        xmlNodePtr child;
+        gboolean   exists;
+
+        exists = g_file_test (filename, G_FILE_TEST_EXISTS);
+        if (! exists) {
+                return;
+        }
+
+        doc = xmlParseFile (filename);
+        if (doc == NULL) {
+                return;
+        }
+
+        root = xmlDocGetRootElement (doc);
+
+        for (child = root->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+                if (xmlStrcmp (child->name, GVC_SOUND_SOUND) != 0) {
+                        continue;
+                }
+
+                populate_model_from_node (chooser, model, child);
+        }
+
+        xmlFreeDoc (doc);
+}
+
+static void
+populate_model_from_dir (GvcSoundThemeChooser *chooser,
+                         GtkTreeModel         *model,
+                         const char           *dirname)
+{
+        GDir       *d;
+        const char *name;
+
+        d = g_dir_open (dirname, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *path;
+
+                if (! g_str_has_suffix (name, ".xml")) {
+                        continue;
+                }
+
+                path = g_build_filename (dirname, name, NULL);
+                populate_model_from_file (chooser, model, path);
+                g_free (path);
+        }
+
+        g_dir_close (d);
+}
+
+static gboolean
+save_alert_sounds (GvcSoundThemeChooser  *chooser,
+                   const char            *id)
+{
+        const char *sounds[3] = { "bell-terminal", "bell-window-system", NULL };
+        char *path;
+
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+        } else {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+                add_custom_file (sounds, id);
+        }
+
+        /* And poke the directory so the theme gets updated */
+        path = custom_theme_dir_path (NULL);
+        if (utime (path, NULL) != 0) {
+                g_warning ("Failed to update mtime for directory '%s': %s",
+                           path, g_strerror (errno));
+        }
+        g_free (path);
+
+        return FALSE;
+}
+
+
+static void
+update_alert_model (GvcSoundThemeChooser  *chooser,
+                    const char            *id)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        gtk_tree_model_get_iter_first (model, &iter);
+        do {
+                gboolean toggled;
+                char    *this_id;
+
+                gtk_tree_model_get (model, &iter,
+                                    ALERT_IDENTIFIER_COL, &this_id,
+                                    -1);
+
+                if (strcmp (this_id, id) == 0) {
+                        toggled = TRUE;
+                } else {
+                        toggled = FALSE;
+                }
+                g_free (this_id);
+
+                gtk_list_store_set (GTK_LIST_STORE (model),
+                                    &iter,
+                                    ALERT_ACTIVE_COL, toggled,
+                                    -1);
+        } while (gtk_tree_model_iter_next (model, &iter));
+}
+
+static void
+update_alert (GvcSoundThemeChooser *chooser,
+              const char           *alert_id)
+{
+        GtkTreeModel *theme_model;
+        GtkTreeIter   iter;
+        char         *theme;
+        char         *parent;
+        gboolean      is_custom;
+        gboolean      is_default;
+        gboolean      add_custom;
+        gboolean      remove_custom;
+
+        theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        /* Get the current theme's name, and set the parent */
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        gtk_tree_model_get (theme_model, &iter,
+                            THEME_IDENTIFIER_COL, &theme,
+                            THEME_IDENTIFIER_COL, &parent,
+                            -1);
+        is_custom = strcmp (theme, CUSTOM_THEME_NAME) == 0;
+        is_default = strcmp (alert_id, DEFAULT_ALERT_ID) == 0;
+
+        /* So a few possibilities:
+         * 1. Named theme, default alert selected: noop
+         * 2. Named theme, alternate alert selected: create new custom with sound
+         * 3. Custom theme, default alert selected: remove sound and possibly custom
+         * 4. Custom theme, alternate alert selected: update custom sound
+         */
+        add_custom = FALSE;
+        remove_custom = FALSE;
+        if (! is_custom && is_default) {
+                /* remove custom just in case */
+                remove_custom = TRUE;
+        } else if (! is_custom && ! is_default) {
+                create_custom_theme (parent);
+                save_alert_sounds (chooser, alert_id);
+                add_custom = TRUE;
+        } else if (is_custom && is_default) {
+                save_alert_sounds (chooser, alert_id);
+                /* after removing files check if it is empty */
+                if (custom_theme_dir_is_empty ()) {
+                        remove_custom = TRUE;
+                }
+        } else if (is_custom && ! is_default) {
+                save_alert_sounds (chooser, alert_id);
+        }
+
+        if (add_custom) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (theme_model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   THEME_DISPLAY_COL, _("Custom"),
+                                                   THEME_IDENTIFIER_COL, CUSTOM_THEME_NAME,
+                                                   THEME_PARENT_ID_COL, theme,
+                                                   -1);
+                set_combox_for_theme_name (chooser, CUSTOM_THEME_NAME);
+        } else if (remove_custom) {
+                gtk_tree_model_get_iter_first (theme_model, &iter);
+                do {
+                        char *this_parent;
+
+                        gtk_tree_model_get (theme_model, &iter,
+                                            THEME_PARENT_ID_COL, &this_parent,
+                                            -1);
+                        if (this_parent != NULL && strcmp (this_parent, CUSTOM_THEME_NAME) != 0) {
+                                g_free (this_parent);
+                                gtk_list_store_remove (GTK_LIST_STORE (theme_model), &iter);
+                                break;
+                        }
+                        g_free (this_parent);
+                } while (gtk_tree_model_iter_next (theme_model, &iter));
+
+                delete_custom_theme_dir ();
+
+                set_combox_for_theme_name (chooser, parent);
+        }
+
+        update_alert_model (chooser, alert_id);
+
+        g_free (theme);
+        g_free (parent);
+}
+
+static void
+on_alert_toggled (GtkCellRendererToggle *renderer,
+                  char                  *path_str,
+                  GvcSoundThemeChooser  *chooser)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreePath  *path;
+        gboolean      toggled;
+        char         *id;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        path = gtk_tree_path_new_from_string (path_str);
+        gtk_tree_model_get_iter (model, &iter, path);
+        gtk_tree_path_free (path);
+
+        id = NULL;
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            ALERT_ACTIVE_COL, &toggled,
+                            -1);
+
+        toggled ^= 1;
+        if (toggled) {
+                update_alert (chooser, id);
+        }
+
+        g_free (id);
+}
+
+static void
+play_preview_for_path (GvcSoundThemeChooser *chooser, GtkTreePath *path)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreeIter   theme_iter;
+        gchar        *id = NULL;
+        gchar        *parent_theme = NULL;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        if (gtk_tree_model_get_iter (model, &iter, path) == FALSE)
+                return;
+
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            -1);
+        if (id == NULL)
+                return;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &theme_iter)) {
+                GtkTreeModel *theme_model;
+                gchar        *theme_id = NULL;
+                gchar        *parent_id = NULL;
+
+                theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+                gtk_tree_model_get (theme_model, &theme_iter,
+                                    THEME_IDENTIFIER_COL, &theme_id,
+                                    THEME_PARENT_ID_COL, &parent_id, -1);
+                if (theme_id && strcmp (theme_id, CUSTOM_THEME_NAME) == 0)
+                        parent_theme = g_strdup (parent_id);
+
+                g_free (theme_id);
+                g_free (parent_id);
+        }
+
+        /* special case: for the default item on custom themes
+         * play the alert for the parent theme */
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                if (parent_theme != NULL) {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_CANBERRA_XDG_THEME_NAME, parent_theme,
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                } else {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                }
+        } else {
+                ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                        CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                        CA_PROP_MEDIA_FILENAME, id,
+                                        CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                        CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                        CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                        CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                        NULL);
+
+        }
+        g_free (parent_theme);
+        g_free (id);
+}
+
+static void
+on_treeview_row_activated (GtkTreeView          *treeview,
+                           GtkTreePath          *path,
+                           GtkTreeViewColumn    *column,
+                           GvcSoundThemeChooser *chooser)
+{
+        play_preview_for_path (chooser, path);
+}
+
+static void
+on_treeview_selection_changed (GtkTreeSelection     *selection,
+                               GvcSoundThemeChooser *chooser)
+{
+        GList        *paths;
+        GtkTreeModel *model;
+        GtkTreePath  *path;
+
+        if (chooser->priv->treeview == NULL)
+                return;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        paths = gtk_tree_selection_get_selected_rows (selection, &model);
+        if (paths == NULL)
+                return;
+
+        path = paths->data;
+        play_preview_for_path (chooser, path);
+
+        g_list_foreach (paths, (GFunc)gtk_tree_path_free, NULL);
+        g_list_free (paths);
+}
+
+static GtkWidget *
+create_alert_treeview (GvcSoundThemeChooser *chooser)
+{
+        GtkListStore         *store;
+        GtkWidget            *treeview;
+        GtkCellRenderer      *renderer;
+        GtkTreeViewColumn    *column;
+        GtkTreeSelection     *selection;
+
+        treeview = gtk_tree_view_new ();
+
+        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
+        g_signal_connect (G_OBJECT (treeview),
+                          "row-activated",
+                          G_CALLBACK (on_treeview_row_activated),
+                          chooser);
+
+        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+        gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+        g_signal_connect (G_OBJECT (selection),
+                          "changed",
+                          G_CALLBACK (on_treeview_selection_changed),
+                          chooser);
+
+        /* Setup the tree model, 3 columns:
+         * - display name
+         * - sound id
+         * - sound type
+         */
+        store = gtk_list_store_new (ALERT_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_BOOLEAN);
+
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           ALERT_IDENTIFIER_COL, DEFAULT_ALERT_ID,
+                                           ALERT_DISPLAY_COL, _("Default"),
+                                           ALERT_SOUND_TYPE_COL, _("From theme"),
+                                           ALERT_ACTIVE_COL, TRUE,
+                                           -1);
+
+        populate_model_from_dir (chooser, GTK_TREE_MODEL (store), SOUND_SET_DIR);
+
+        gtk_tree_view_set_model (GTK_TREE_VIEW (treeview),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_toggle_new ();
+        gtk_cell_renderer_toggle_set_radio (GTK_CELL_RENDERER_TOGGLE (renderer), TRUE);
+
+        column = gtk_tree_view_column_new_with_attributes (NULL,
+                                                           renderer,
+                                                           "active", ALERT_ACTIVE_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+        g_signal_connect (renderer,
+                          "toggled",
+                          G_CALLBACK (on_alert_toggled),
+                          chooser);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Name"),
+                                                           renderer,
+                                                           "text", ALERT_DISPLAY_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Type"),
+                                                           renderer,
+                                                           "text", ALERT_SOUND_TYPE_COL,
+                                                           NULL);
+
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        return treeview;
+}
+
+static int
+get_file_type (const char *sound_name,
+               char      **linked_name)
+{
+        char *name, *filename;
+
+        *linked_name = NULL;
+
+        name = g_strdup_printf ("%s.disabled", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_REGULAR) != FALSE) {
+                g_free (filename);
+                return SOUND_TYPE_OFF;
+        }
+        g_free (filename);
+
+        /* We only check for .ogg files because those are the
+         * only ones we create */
+        name = g_strdup_printf ("%s.ogg", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_SYMLINK) != FALSE) {
+                *linked_name = g_file_read_link (filename, NULL);
+                g_free (filename);
+                return SOUND_TYPE_CUSTOM;
+        }
+        g_free (filename);
+
+        return SOUND_TYPE_BUILTIN;
+}
+
+static void
+update_alerts_from_theme_name (GvcSoundThemeChooser *chooser,
+                               const gchar          *name)
+{
+        if (strcmp (name, CUSTOM_THEME_NAME) != 0) {
+                /* reset alert to default */
+                update_alert (chooser, DEFAULT_ALERT_ID);
+        } else {
+                int   sound_type;
+                char *linkname;
+
+                linkname = NULL;
+                sound_type = get_file_type ("bell-terminal", &linkname);
+                g_debug ("Found link: %s", linkname);
+                if (sound_type == SOUND_TYPE_CUSTOM) {
+                        update_alert (chooser, linkname);
+                }
+        }
+}
+
+static void
+update_theme (GvcSoundThemeChooser *chooser)
+{
+        char        *theme_name;
+        gboolean     events_enabled;
+        gboolean     feedback_enabled;
+
+        feedback_enabled = g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY);
+        set_input_feedback_enabled (chooser, feedback_enabled);
+
+        events_enabled = g_settings_get_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY);
+        if (events_enabled) {
+                theme_name = g_settings_get_string (chooser->priv->sound_settings, SOUND_THEME_KEY);
+        } else {
+                theme_name = g_strdup (NO_SOUNDS_THEME_NAME);
+        }
+
+        gtk_widget_set_sensitive (chooser->priv->selection_box, events_enabled);
+        gtk_widget_set_sensitive (chooser->priv->click_feedback_button, events_enabled);
+
+        set_combox_for_theme_name (chooser, theme_name);
+
+        update_alerts_from_theme_name (chooser, theme_name);
+
+        g_free (theme_name);
+}
+
+static void
+gvc_sound_theme_chooser_class_init (GvcSoundThemeChooserClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_sound_theme_chooser_dispose;
+}
+
+static void
+on_click_feedback_toggled (GtkToggleButton      *button,
+                           GvcSoundThemeChooser *chooser)
+{
+        gboolean enabled;
+
+        enabled = gtk_toggle_button_get_active (button);
+
+        g_settings_set_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY, enabled);
+}
+
+static void
+on_key_changed (GSettings            *settings,
+                gchar                *key,
+                GvcSoundThemeChooser *chooser)
+{
+        if (!strcmp (key, EVENT_SOUNDS_KEY) ||
+            !strcmp (key, SOUND_THEME_KEY) ||
+            !strcmp (key, INPUT_SOUNDS_KEY))
+                update_theme (chooser);
+}
+
+static void
+setup_list_size_constraint (GtkWidget *widget,
+                            GtkWidget *to_size)
+{
+        GtkRequisition req;
+        gint           sc_height;
+        int            max_height;
+
+        /* Constrain height to be the tree height up to a max */
+        gdk_window_get_geometry (gdk_screen_get_root_window (gtk_widget_get_screen (widget)),
+                                 NULL, NULL, NULL, &sc_height);
+
+        max_height = sc_height / 4;
+
+        // XXX this doesn't work
+        gtk_widget_get_preferred_size (to_size, NULL, &req);
+
+        gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (widget),
+                                                    MIN (req.height, max_height));
+}
+
+static void
+gvc_sound_theme_chooser_init (GvcSoundThemeChooser *chooser)
+{
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *scrolled_window;
+        gchar       *str;
+
+        chooser->priv = gvc_sound_theme_chooser_get_instance_private (chooser);
+
+        chooser->priv->theme_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->theme_box, FALSE, FALSE, 0);
+
+        label = gtk_label_new_with_mnemonic (_("Sound _theme:"));
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), label, FALSE, FALSE, 0);
+        chooser->priv->combo_box = gtk_combo_box_new ();
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), chooser->priv->combo_box, FALSE, FALSE, 6);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->combo_box);
+
+        chooser->priv->sound_settings = g_settings_new (KEY_SOUNDS_SCHEMA);
+
+        g_signal_connect (G_OBJECT (chooser->priv->sound_settings),
+                          "changed",
+                          G_CALLBACK (on_key_changed),
+                          chooser);
+
+        str = g_strdup_printf ("<b>%s</b>", _("C_hoose an alert sound:"));
+        chooser->priv->selection_box = box = gtk_frame_new (str);
+        g_free (str);
+
+        label = gtk_frame_get_label_widget (GTK_FRAME (box));
+        gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
+        gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+        gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
+
+        gtk_box_pack_start (GTK_BOX (chooser), box, TRUE, TRUE, 6);
+
+        chooser->priv->treeview = create_alert_treeview (chooser);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->treeview);
+
+        scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+        gtk_widget_set_hexpand (scrolled_window, TRUE);
+        gtk_widget_set_vexpand (scrolled_window, TRUE);
+        gtk_widget_set_margin_top (scrolled_window, 6);
+
+        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+                                        GTK_POLICY_NEVER,
+                                        GTK_POLICY_AUTOMATIC);
+        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
+                                             GTK_SHADOW_IN);
+
+        gtk_container_add (GTK_CONTAINER (scrolled_window), chooser->priv->treeview);
+        gtk_container_add (GTK_CONTAINER (box), scrolled_window);
+
+        chooser->priv->click_feedback_button = gtk_check_button_new_with_mnemonic (_("Enable _window and button sounds"));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY));
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->click_feedback_button,
+                            FALSE, FALSE, 0);
+
+        g_signal_connect (G_OBJECT (chooser->priv->click_feedback_button),
+                          "toggled",
+                          G_CALLBACK (on_click_feedback_toggled),
+                          chooser);
+
+        setup_theme_selector (chooser);
+        update_theme (chooser);
+
+        setup_list_size_constraint (scrolled_window, chooser->priv->treeview);
+}
+
+static void
+gvc_sound_theme_chooser_dispose (GObject *object)
+{
+        GvcSoundThemeChooser *chooser;
+
+        chooser = GVC_SOUND_THEME_CHOOSER (object);
+
+        g_clear_object (&chooser->priv->sound_settings);
+
+        G_OBJECT_CLASS (gvc_sound_theme_chooser_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_sound_theme_chooser_new (void)
+{
+        return g_object_new (GVC_TYPE_SOUND_THEME_CHOOSER,
+                                "spacing", 6,
+                                "orientation", GTK_ORIENTATION_VERTICAL,
+                                NULL);
+}
+
+
+
+
+ + + diff --git a/2020-08-18-170145-8061-cppcheck@c82f5feb6c8f_master/2.html b/2020-08-18-170145-8061-cppcheck@c82f5feb6c8f_master/2.html new file mode 100644 index 0000000..64940b3 --- /dev/null +++ b/2020-08-18-170145-8061-cppcheck@c82f5feb6c8f_master/2.html @@ -0,0 +1,1126 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + +
+ +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <canberra.h>
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-speaker-test.h"
+#include "gvc-utils.h"
+
+struct _GvcSpeakerTestPrivate
+{
+        GArray           *controls;
+        ca_context       *canberra;
+        MateMixerStream  *stream;
+};
+
+enum {
+        PROP_0,
+        PROP_STREAM,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_speaker_test_dispose    (GObject             *object);
+static void gvc_speaker_test_finalize   (GObject             *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSpeakerTest, gvc_speaker_test, GTK_TYPE_GRID)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+typedef struct {
+        MateMixerChannelPosition position;
+        guint left;
+        guint top;
+} TablePosition;
+
+static const TablePosition positions[] = {
+        /* Position, X, Y */
+        { MATE_MIXER_CHANNEL_FRONT_LEFT, 0, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_LEFT_CENTER, 1, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_CENTER, 2, 0, },
+        { MATE_MIXER_CHANNEL_MONO, 2, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT_CENTER, 3, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT, 4, 0, },
+        { MATE_MIXER_CHANNEL_SIDE_LEFT, 0, 1, },
+        { MATE_MIXER_CHANNEL_SIDE_RIGHT, 4, 1, },
+        { MATE_MIXER_CHANNEL_BACK_LEFT, 0, 2, },
+        { MATE_MIXER_CHANNEL_BACK_CENTER, 2, 2, },
+        { MATE_MIXER_CHANNEL_BACK_RIGHT, 4, 2, },
+        { MATE_MIXER_CHANNEL_LFE, 3, 2 }
+};
+
+MateMixerStream *
+gvc_speaker_test_get_stream (GvcSpeakerTest *test)
+{
+        g_return_val_if_fail (GVC_IS_SPEAKER_TEST (test), NULL);
+
+        return test->priv->stream;
+}
+
+static void
+gvc_speaker_test_set_stream (GvcSpeakerTest *test, MateMixerStream *stream)
+{
+        MateMixerStreamControl *control;
+        const gchar            *name;
+        guint                   i;
+
+        name = mate_mixer_stream_get_name (stream);
+        control = mate_mixer_stream_get_default_control (stream);
+
+        ca_context_change_device (test->priv->canberra, name);
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                gboolean has_position =
+                        mate_mixer_stream_control_has_channel_position (control, positions[i].position);
+
+                gtk_widget_set_visible (g_array_index (test->priv->controls, GtkWidget *, i),
+                                        has_position);
+        }
+
+        test->priv->stream = g_object_ref (stream);
+}
+
+static void
+gvc_speaker_test_set_property (GObject       *object,
+                               guint          prop_id,
+                               const GValue  *value,
+                               GParamSpec    *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                gvc_speaker_test_set_stream (self, g_value_get_object (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_get_property (GObject     *object,
+                               guint        prop_id,
+                               GValue      *value,
+                               GParamSpec  *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                g_value_set_object (value, self->priv->stream);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_class_init (GvcSpeakerTestClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose  = gvc_speaker_test_dispose;
+        object_class->finalize = gvc_speaker_test_finalize;
+        object_class->set_property = gvc_speaker_test_set_property;
+        object_class->get_property = gvc_speaker_test_get_property;
+
+        properties[PROP_STREAM] =
+                g_param_spec_object ("stream",
+                                     "Stream",
+                                     "MateMixer stream",
+                                     MATE_MIXER_TYPE_STREAM,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+}
+
+static const gchar *
+sound_name (MateMixerChannelPosition position)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return "audio-channel-front-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return "audio-channel-front-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return "audio-channel-front-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return "audio-channel-rear-left";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return "audio-channel-rear-right";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return "audio-channel-rear-center";
+        case MATE_MIXER_CHANNEL_LFE:
+                return "audio-channel-lfe";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return "audio-channel-side-left";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return "audio-channel-side-right";
+        default:
+                return NULL;
+        }
+}
+
+static const gchar *
+icon_name (MateMixerChannelPosition position, gboolean playing)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return playing
+                        ? "audio-speaker-left-testing"
+                        : "audio-speaker-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return playing
+                        ? "audio-speaker-right-testing"
+                        : "audio-speaker-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return playing
+                        ? "audio-speaker-center-testing"
+                        : "audio-speaker-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return playing
+                        ? "audio-speaker-left-back-testing"
+                        : "audio-speaker-left-back";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return playing
+                        ? "audio-speaker-right-back-testing"
+                        : "audio-speaker-right-back";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return playing
+                        ? "audio-speaker-center-back-testing"
+                        : "audio-speaker-center-back";
+        case MATE_MIXER_CHANNEL_LFE:
+                return playing
+                        ? "audio-subwoofer-testing"
+                        : "audio-subwoofer";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return playing
+                        ? "audio-speaker-left-side-testing"
+                        : "audio-speaker-left-side";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return playing
+                        ? "audio-speaker-right-side-testing"
+                        : "audio-speaker-right-side";
+        default:
+                return NULL;
+        }
+}
+
+static void
+update_button (GtkWidget *control)
+{
+        GtkWidget *button;
+        GtkWidget *image;
+        gboolean   playing;
+        MateMixerChannelPosition position;
+
+        button = g_object_get_data (G_OBJECT (control), "button");
+        image  = g_object_get_data (G_OBJECT (control), "image");
+
+        position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+        playing  = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        gtk_button_set_label (GTK_BUTTON (button), playing ? _("Stop") : _("Test"));
+
+        gtk_image_set_from_icon_name (GTK_IMAGE (image),
+                                      icon_name (position, playing),
+                                      GTK_ICON_SIZE_DIALOG);
+}
+
+static gboolean
+idle_cb (GtkWidget *control)
+{
+        if (control != NULL) {
+                /* This is called in the background thread, hence forward to main thread
+                 * via idle callback */
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+
+                update_button (control);
+        }
+        return FALSE;
+}
+
+static void
+finish_cb (ca_context *c, uint32_t id, int error_code, void *userdata)
+{
+        GtkWidget *control = (GtkWidget *) userdata;
+
+        if (error_code == CA_ERROR_DESTROYED || control == NULL)
+                return;
+
+        g_idle_add ((GSourceFunc) idle_cb, control);
+}
+
+static void
+on_test_button_clicked (GtkButton *button, GtkWidget *control)
+{
+        gboolean    playing;
+        ca_context *canberra;
+
+        canberra = g_object_get_data (G_OBJECT (control), "canberra");
+
+        ca_context_cancel (canberra, 1);
+
+        playing = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        if (playing) {
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        } else {
+                MateMixerChannelPosition position;
+                const gchar *name;
+                ca_proplist *proplist;
+
+                position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+
+                ca_proplist_create (&proplist);
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_ROLE, "test");
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_NAME,
+                                  gvc_channel_position_to_pretty_string (position));
+                ca_proplist_sets (proplist,
+                                  CA_PROP_CANBERRA_FORCE_CHANNEL,
+                                  gvc_channel_position_to_pulse_string (position));
+
+                ca_proplist_sets (proplist, CA_PROP_CANBERRA_ENABLE, "1");
+
+                name = sound_name (position);
+                if (name != NULL) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, name);
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, "audio-test-signal");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets(proplist, CA_PROP_EVENT_ID, "bell-window-system");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (playing));
+        }
+
+        update_button (control);
+}
+
+static GtkWidget *
+create_control (ca_context *canberra, MateMixerChannelPosition position)
+{
+        GtkWidget   *control;
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *image;
+        GtkWidget   *test_button;
+        const gchar *name;
+
+        control = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+        box     = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        g_object_set_data (G_OBJECT (control), "position", GINT_TO_POINTER (position));
+        g_object_set_data (G_OBJECT (control), "canberra", canberra);
+
+        name = icon_name (position, FALSE);
+        if (name == NULL)
+                name = "audio-volume-medium";
+
+        image = gtk_image_new_from_icon_name (name, GTK_ICON_SIZE_DIALOG);
+        g_object_set_data (G_OBJECT (control), "image", image);
+        gtk_box_pack_start (GTK_BOX (control), image, FALSE, FALSE, 0);
+
+        label = gtk_label_new (gvc_channel_position_to_pretty_string (position));
+        gtk_box_pack_start (GTK_BOX (control), label, FALSE, FALSE, 0);
+
+        test_button = gtk_button_new_with_label (_("Test"));
+        g_signal_connect (G_OBJECT (test_button),
+                          "clicked",
+                          G_CALLBACK (on_test_button_clicked),
+                          control);
+
+        g_object_set_data (G_OBJECT (control), "button", test_button);
+
+        gtk_box_pack_start (GTK_BOX (box), test_button, TRUE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (control), box, FALSE, FALSE, 0);
+
+        gtk_widget_show_all (control);
+
+        return control;
+}
+
+static void
+create_controls (GvcSpeakerTest *test)
+{
+        guint i;
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                GtkWidget *control = create_control (test->priv->canberra, positions[i].position);
+
+                gtk_grid_attach (GTK_GRID (test),
+                                 control,
+                                 positions[i].left,
+                                 positions[i].top,
+                                 1, 1);
+                g_array_insert_val (test->priv->controls, i, control);
+        }
+}
+
+static void
+gvc_speaker_test_init (GvcSpeakerTest *test)
+{
+        GtkWidget *face;
+
+        test->priv = gvc_speaker_test_get_instance_private (test);
+
+        gtk_container_set_border_width (GTK_CONTAINER (test), 12);
+
+        face = gtk_image_new_from_icon_name ("face-smile", GTK_ICON_SIZE_DIALOG);
+
+        gtk_grid_attach (GTK_GRID (test),
+                         face,
+                         1, 1,
+                         3, 1);
+
+
+        gtk_grid_set_baseline_row (GTK_GRID (test), 1);
+        gtk_widget_show (face);
+
+        ca_context_create (&test->priv->canberra);
+
+        /* The test sounds are played for a single channel, set up using the
+         * FORCE_CHANNEL property of libcanberra; this property is only supported
+         * in the PulseAudio backend, so avoid other backends completely */
+        ca_context_set_driver (test->priv->canberra, "pulse");
+
+        ca_context_change_props (test->priv->canberra,
+                                 CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+                                 CA_PROP_APPLICATION_NAME, _("Volume Control"),
+                                 CA_PROP_APPLICATION_VERSION, VERSION,
+                                 CA_PROP_APPLICATION_ICON_NAME, "multimedia-volume-control",
+                                 NULL);
+
+        test->priv->controls = g_array_new (FALSE, FALSE, sizeof (GtkWidget *));
+
+        create_controls (test);
+}
+
+static void
+gvc_speaker_test_dispose (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        g_clear_object (&test->priv->stream);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->dispose (object);
+}
+
+static void
+gvc_speaker_test_finalize (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        ca_context_destroy (test->priv->canberra);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->finalize (object);
+}
+
+GtkWidget *
+gvc_speaker_test_new (MateMixerStream *stream)
+{
+        GObject *test;
+
+        g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL);
+
+        test = g_object_new (GVC_TYPE_SPEAKER_TEST,
+                             "row-spacing", 6,
+                             "column-spacing", 6,
+                             "row-homogeneous", TRUE,
+                             "column-homogeneous", TRUE,
+                             "stream", stream,
+                             NULL);
+
+        return GTK_WIDGET (test);
+}
+
+
+
+
+ + + diff --git a/2020-08-18-170145-8061-cppcheck@c82f5feb6c8f_master/index.html b/2020-08-18-170145-8061-cppcheck@c82f5feb6c8f_master/index.html new file mode 100644 index 0000000..235f646 --- /dev/null +++ b/2020-08-18-170145-8061-cppcheck@c82f5feb6c8f_master/index.html @@ -0,0 +1,124 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + +
+ +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
mate-volume-control/gvc-combo-box.c
70unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
mate-volume-control/gvc-sound-theme-chooser.c
735ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
746ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
758ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
mate-volume-control/gvc-speaker-test.c
53unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+
+ + + diff --git a/2020-08-18-170145-8061-cppcheck@c82f5feb6c8f_master/stats.html b/2020-08-18-170145-8061-cppcheck@c82f5feb6c8f_master/stats.html new file mode 100644 index 0000000..6eb8706 --- /dev/null +++ b/2020-08-18-170145-8061-cppcheck@c82f5feb6c8f_master/stats.html @@ -0,0 +1,109 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + +
+ +
+

Top 10 files for error severity, total findings: 2
+   1  mate-volume-control/gvc-speaker-test.c
+   1  mate-volume-control/gvc-combo-box.c
+

+

Top 10 files for information severity, total findings: 3
+   3  mate-volume-control/gvc-sound-theme-chooser.c
+

+ +
+
+ + + diff --git a/2020-08-18-170145-8061-cppcheck@c82f5feb6c8f_master/style.css b/2020-08-18-170145-8061-cppcheck@c82f5feb6c8f_master/style.css new file mode 100644 index 0000000..07125f4 --- /dev/null +++ b/2020-08-18-170145-8061-cppcheck@c82f5feb6c8f_master/style.css @@ -0,0 +1,137 @@ + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; + font-size: 13px; + line-height: 1.5; + margin: 0; + width: auto; +} + +h1 { + margin: 10px; +} + +.header { + border-bottom: thin solid #aaa; +} + +.footer { + border-top: thin solid #aaa; + font-size: 90%; + margin-top: 5px; +} + +.footer ul { + list-style-type: none; + padding-left: 0; +} + +.footer > p { + margin: 4px; +} + +.wrapper { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; +} + +#menu, +#menu_index { + text-align: left; + width: 350px; + height: 90vh; + min-height: 200px; + overflow: auto; + position: -webkit-sticky; + position: sticky; + top: 0; + padding: 0 15px 15px 15px; +} + +#menu > a { + display: block; + margin-left: 10px; + font-size: 12px; + z-index: 1; +} + +#content, +#content_index { + background-color: #fff; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + padding: 0 15px 15px 15px; + width: calc(100% - 350px); + height: 100%; + overflow-x: auto; +} + +#filename { + margin-left: 10px; + font-size: 12px; + z-index: 1; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #b6b6b4; +} + +.inconclusive2 { + background-color: #b6b6b4; + display: inline-block; + margin-left: 4px; +} + +.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +.verbose .content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid #000; + background-color: #ffffcc; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +.highlighttable { + background-color: #fff; + z-index: 10; + position: relative; + margin: -10px; +} + +.linenos { + border-right: thin solid #aaa; + color: #d3d3d3; + padding-right: 6px; +} + +.d-none { + display: none; +} diff --git a/2020-08-18-170623-4816-cppcheck@c82f5feb6c8f_v1.25.0/0.html b/2020-08-18-170623-4816-cppcheck@c82f5feb6c8f_v1.25.0/0.html new file mode 100644 index 0000000..5bf183e --- /dev/null +++ b/2020-08-18-170623-4816-cppcheck@c82f5feb6c8f_v1.25.0/0.html @@ -0,0 +1,1054 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + +
+ +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-combo-box.h"
+
+struct _GvcComboBoxPrivate
+{
+        GtkWidget       *drop_box;
+        GtkWidget       *start_box;
+        GtkWidget       *end_box;
+        GtkWidget       *label;
+        GtkWidget       *button;
+        GtkTreeModel    *model;
+        GtkWidget       *combobox;
+        MateMixerSwitch *swtch;
+};
+
+enum {
+        COL_NAME,
+        COL_HUMAN_NAME,
+        NUM_COLS
+};
+
+enum {
+        CHANGING,
+        BUTTON_CLICKED,
+        LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+enum {
+        PROP_0,
+        PROP_SWITCH,
+        PROP_LABEL,
+        PROP_SHOW_BUTTON,
+        PROP_BUTTON_LABEL,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_combo_box_dispose    (GObject          *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcComboBox, gvc_combo_box, GTK_TYPE_BOX)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+MateMixerSwitch *
+gvc_combo_box_get_switch (GvcComboBox *combobox)
+{
+        g_return_val_if_fail (GVC_IS_COMBO_BOX (combobox), NULL);
+
+        return combobox->priv->swtch;
+}
+
+void
+gvc_combo_box_set_size_group (GvcComboBox  *combobox,
+                              GtkSizeGroup *group,
+                              gboolean      symmetric)
+{
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (GTK_IS_SIZE_GROUP (group));
+
+        if (group != NULL) {
+                gtk_size_group_add_widget (group, combobox->priv->start_box);
+                if (symmetric == TRUE)
+                        gtk_size_group_add_widget (group, combobox->priv->end_box);
+        }
+        gtk_widget_queue_draw (GTK_WIDGET (combobox));
+}
+
+static void
+on_switch_active_option_notify (MateMixerSwitch *swtch,
+                                GParamSpec      *pspec,
+                                GvcComboBox     *combobox)
+{
+        GtkTreeIter            iter;
+        MateMixerSwitchOption *active;
+        gboolean               cont;
+        const gchar           *name;
+
+        active = mate_mixer_switch_get_active_option (swtch);
+        if (G_UNLIKELY (active == NULL)) {
+                g_warn_if_reached ();
+                return;
+        }
+
+        /* Select the newly activated switch option in the combo box */
+        name = mate_mixer_switch_option_get_name (active);
+        cont = gtk_tree_model_get_iter_first (combobox->priv->model, &iter);
+        while (cont == TRUE) {
+                gchar *current;
+
+                gtk_tree_model_get (combobox->priv->model, &iter,
+                                    COL_NAME, &current,
+                                    -1);
+                if (g_strcmp0 (name, current) == 0) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox), &iter);
+                        g_free (current);
+                        return;
+                }
+                g_free (current);
+
+                cont = gtk_tree_model_iter_next (combobox->priv->model, &iter);
+        }
+        g_warning ("Could not find switch option '%s' in combo box", name);
+}
+
+static void
+gvc_combo_box_set_switch (GvcComboBox *combobox, MateMixerSwitch *swtch)
+{
+        MateMixerSwitchOption *active;
+        const GList           *options;
+
+        g_return_if_fail (GVC_IS_COMBO_BOX (combobox));
+        g_return_if_fail (MATE_MIXER_IS_SWITCH (swtch));
+
+        combobox->priv->swtch = g_object_ref (swtch);
+
+        active  = mate_mixer_switch_get_active_option (swtch);
+        options = mate_mixer_switch_list_options (swtch);
+        while (options != NULL) {
+                GtkTreeIter            iter;
+                MateMixerSwitchOption *option = MATE_MIXER_SWITCH_OPTION (options->data);
+
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (combobox->priv->model),
+                                                   &iter,
+                                                   G_MAXINT,
+                                                   COL_NAME,
+                                                   mate_mixer_switch_option_get_name (option),
+                                                   COL_HUMAN_NAME,
+                                                   mate_mixer_switch_option_get_label (option),
+                                                   -1);
+
+                /* Select the currently active option of the switch */
+                if (option == active) {
+                        gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combobox->priv->combobox),
+                                                       &iter);
+                }
+                options = options->next;
+        }
+
+        g_signal_connect (G_OBJECT (swtch),
+                          "notify::active-option",
+                          G_CALLBACK (on_switch_active_option_notify),
+                          combobox);
+}
+
+static void
+gvc_combo_box_set_property (GObject       *object,
+                            guint          prop_id,
+                            const GValue  *value,
+                            GParamSpec    *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                gvc_combo_box_set_switch (self, g_value_get_object (value));
+                break;
+        case PROP_LABEL:
+                gtk_label_set_text_with_mnemonic (GTK_LABEL (self->priv->label), g_value_get_string (value));
+                break;
+        case PROP_BUTTON_LABEL:
+                gtk_button_set_label (GTK_BUTTON (self->priv->button), g_value_get_string (value));
+                break;
+        case PROP_SHOW_BUTTON:
+                gtk_widget_set_visible (self->priv->button, g_value_get_boolean (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_get_property (GObject     *object,
+                            guint        prop_id,
+                            GValue      *value,
+                            GParamSpec  *pspec)
+{
+        GvcComboBox *self = GVC_COMBO_BOX (object);
+
+        switch (prop_id) {
+        case PROP_SWITCH:
+                g_value_set_object (value, self->priv->swtch);
+                break;
+        case PROP_LABEL:
+                g_value_set_string (value, gtk_label_get_text (GTK_LABEL (self->priv->label)));
+                break;
+        case PROP_BUTTON_LABEL:
+                g_value_set_string (value, gtk_button_get_label (GTK_BUTTON (self->priv->button)));
+                break;
+        case PROP_SHOW_BUTTON:
+                g_value_set_boolean (value, gtk_widget_get_visible (self->priv->button));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_combo_box_class_init (GvcComboBoxClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_combo_box_dispose;
+        object_class->set_property = gvc_combo_box_set_property;
+        object_class->get_property = gvc_combo_box_get_property;
+
+        properties[PROP_SWITCH] =
+                g_param_spec_object ("switch",
+                                     "switch",
+                                     "The MateMixerSwitch",
+                                     MATE_MIXER_TYPE_SWITCH,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_LABEL] =
+                g_param_spec_string ("label",
+                                     "label",
+                                     "The combo box label",
+                                     _("_Profile:"),
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_SHOW_BUTTON] =
+                g_param_spec_boolean ("show-button",
+                                      "show-button",
+                                      "Whether to show the button",
+                                      FALSE,
+                                      G_PARAM_READWRITE |
+                                      G_PARAM_CONSTRUCT |
+                                      G_PARAM_STATIC_STRINGS);
+
+        properties[PROP_BUTTON_LABEL] =
+                g_param_spec_string ("button-label",
+                                     "button-label",
+                                     "The button's label",
+                                     "",
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+
+        signals[CHANGING] =
+                g_signal_new ("changing",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, changing),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__OBJECT,
+                              G_TYPE_NONE,
+                              1,
+                              MATE_MIXER_TYPE_SWITCH_OPTION);
+
+        signals[BUTTON_CLICKED] =
+                g_signal_new ("button-clicked",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GvcComboBoxClass, button_clicked),
+                              NULL, NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
+}
+
+static void
+on_combo_box_changed (GtkComboBox *widget, GvcComboBox *combobox)
+{
+        GtkTreeIter            iter;
+        gchar                 *name;
+        MateMixerSwitchOption *option;
+
+        if (G_UNLIKELY (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter) == FALSE))
+                return;
+
+        gtk_tree_model_get (combobox->priv->model, &iter,
+                            COL_NAME, &name,
+                            -1);
+
+        option = mate_mixer_switch_get_option (combobox->priv->swtch, name);
+        if (G_UNLIKELY (option == NULL)) {
+                g_warn_if_reached ();
+                g_free (name);
+                return;
+        }
+
+        /* Inform that we are about to change the active option of the switch */
+        g_signal_emit (combobox, signals[CHANGING], 0, option);
+
+        mate_mixer_switch_set_active_option (combobox->priv->swtch, option);
+        g_free (name);
+}
+
+static void
+on_combo_box_button_clicked (GtkButton *button, GvcComboBox *combobox)
+{
+        /* The meaning of the button is defined by the owner, so only notify
+         * when it is clicked on */
+        g_signal_emit (combobox, signals[BUTTON_CLICKED], 0);
+}
+
+static void
+gvc_combo_box_init (GvcComboBox *combobox)
+{
+        GtkWidget       *frame;
+        GtkCellRenderer *renderer;
+
+        frame = gtk_frame_new (NULL);
+        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
+
+        combobox->priv = gvc_combo_box_get_instance_private (combobox);
+
+        combobox->priv->model = GTK_TREE_MODEL (gtk_list_store_new (NUM_COLS,
+                                                                    G_TYPE_STRING,
+                                                                    G_TYPE_STRING));
+
+        combobox->priv->combobox = gtk_combo_box_new_with_model (combobox->priv->model);
+
+        combobox->priv->label = gtk_label_new (NULL);
+
+        gtk_label_set_xalign (GTK_LABEL (combobox->priv->label), 0.0);
+        gtk_label_set_yalign (GTK_LABEL (combobox->priv->label), 0.5);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (combobox->priv->label),
+                                       combobox->priv->combobox);
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                    renderer,
+                                    FALSE);
+        gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combobox->priv->combobox),
+                                       renderer,
+                                       "text",
+                                       COL_HUMAN_NAME);
+
+        combobox->priv->drop_box  = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->start_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+        combobox->priv->end_box   = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+        /* Make sure the combo box does not get too long on long profile names */
+        g_object_set (G_OBJECT (renderer),
+                      "ellipsize",
+                      PANGO_ELLIPSIZE_END,
+                      NULL);
+
+        gtk_combo_box_set_popup_fixed_width (GTK_COMBO_BOX (combobox->priv->combobox), FALSE);
+
+        gtk_box_pack_start (GTK_BOX (combobox),
+                            frame,
+                            TRUE, TRUE, 0);
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->start_box,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->start_box),
+                            combobox->priv->label,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->combobox,
+                            TRUE, TRUE, 0);
+
+        combobox->priv->button = gtk_button_new_with_label ("");
+
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->button,
+                            FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (combobox->priv->drop_box),
+                            combobox->priv->end_box,
+                            FALSE, FALSE, 0);
+
+        gtk_container_add (GTK_CONTAINER (frame), combobox->priv->drop_box);
+
+        g_signal_connect (G_OBJECT (combobox->priv->combobox),
+                          "changed",
+                          G_CALLBACK (on_combo_box_changed),
+                          combobox);
+        g_signal_connect (G_OBJECT (combobox->priv->button),
+                          "clicked",
+                          G_CALLBACK (on_combo_box_button_clicked),
+                          combobox);
+
+        gtk_widget_set_no_show_all (combobox->priv->button, TRUE);
+        gtk_widget_show_all (frame);
+}
+
+static void
+gvc_combo_box_dispose (GObject *object)
+{
+        GvcComboBox *combobox;
+
+        combobox = GVC_COMBO_BOX (object);
+
+        if (G_LIKELY (combobox->priv->swtch != NULL)) {
+                g_signal_handlers_disconnect_by_func (G_OBJECT (combobox->priv->swtch),
+                                                      G_CALLBACK (on_switch_active_option_notify),
+                                                      combobox);
+                g_clear_object (&combobox->priv->swtch);
+        }
+
+        g_clear_object (&combobox->priv->model);
+
+        G_OBJECT_CLASS (gvc_combo_box_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_combo_box_new (MateMixerSwitch *swtch, const gchar *label)
+{
+        return g_object_new (GVC_TYPE_COMBO_BOX,
+                             "switch", swtch,
+                             "label", label,
+                             "orientation", GTK_ORIENTATION_HORIZONTAL,
+                             NULL);
+}
+
+
+
+
+ + + diff --git a/2020-08-18-170623-4816-cppcheck@c82f5feb6c8f_v1.25.0/1.html b/2020-08-18-170623-4816-cppcheck@c82f5feb6c8f_v1.25.0/1.html new file mode 100644 index 0000000..9fd449d --- /dev/null +++ b/2020-08-18-170623-4816-cppcheck@c82f5feb6c8f_v1.25.0/1.html @@ -0,0 +1,2384 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + +
+ +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
+ * Copyright (C) 2008 William Jon McCann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <utime.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+#include <canberra-gtk.h>
+#include <libxml/tree.h>
+
+#include "gvc-sound-theme-chooser.h"
+#include "sound-theme-file-utils.h"
+
+struct GvcSoundThemeChooserPrivate
+{
+        GtkWidget *combo_box;
+        GtkWidget *treeview;
+        GtkWidget *theme_box;
+        GtkWidget *selection_box;
+        GtkWidget *click_feedback_button;
+        GSettings *sound_settings;
+};
+
+static void     gvc_sound_theme_chooser_dispose   (GObject            *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSoundThemeChooser, gvc_sound_theme_chooser, GTK_TYPE_BOX)
+
+#define KEY_SOUNDS_SCHEMA          "org.mate.sound"
+#define EVENT_SOUNDS_KEY           "event-sounds"
+#define INPUT_SOUNDS_KEY           "input-feedback-sounds"
+#define SOUND_THEME_KEY            "theme-name"
+
+#define DEFAULT_ALERT_ID        "__default"
+#define CUSTOM_THEME_NAME       "__custom"
+#define NO_SOUNDS_THEME_NAME    "__no_sounds"
+
+enum {
+        THEME_DISPLAY_COL,
+        THEME_IDENTIFIER_COL,
+        THEME_PARENT_ID_COL,
+        THEME_NUM_COLS
+};
+
+enum {
+        ALERT_DISPLAY_COL,
+        ALERT_IDENTIFIER_COL,
+        ALERT_SOUND_TYPE_COL,
+        ALERT_ACTIVE_COL,
+        ALERT_NUM_COLS
+};
+
+enum {
+        SOUND_TYPE_UNSET,
+        SOUND_TYPE_OFF,
+        SOUND_TYPE_DEFAULT_FROM_THEME,
+        SOUND_TYPE_BUILTIN,
+        SOUND_TYPE_CUSTOM
+};
+
+static void
+on_combobox_changed (GtkComboBox          *widget,
+                     GvcSoundThemeChooser *chooser)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        char         *theme_name;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &theme_name, -1);
+
+        g_assert (theme_name != NULL);
+
+        /* It is necessary to update the theme name before any other setting as
+         * the "changed" notification will reload the contents of the widget */
+        g_settings_set_string (chooser->priv->sound_settings, SOUND_THEME_KEY, theme_name);
+
+        /* special case for no sounds */
+        if (strcmp (theme_name, NO_SOUNDS_THEME_NAME) == 0) {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, FALSE);
+                return;
+        } else {
+                g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, TRUE);
+        }
+
+        g_free (theme_name);
+
+        /* FIXME: reset alert model */
+}
+
+static char *
+load_index_theme_name (const char *index,
+                       char      **parent)
+{
+        GKeyFile *file;
+        char *indexname = NULL;
+        gboolean hidden;
+
+        file = g_key_file_new ();
+        if (g_key_file_load_from_file (file, index, G_KEY_FILE_KEEP_TRANSLATIONS, NULL) == FALSE) {
+                g_key_file_free (file);
+                return NULL;
+        }
+        /* Don't add hidden themes to the list */
+        hidden = g_key_file_get_boolean (file, "Sound Theme", "Hidden", NULL);
+        if (!hidden) {
+                indexname = g_key_file_get_locale_string (file,
+                                                          "Sound Theme",
+                                                          "Name",
+                                                          NULL,
+                                                          NULL);
+
+                /* Save the parent theme, if there's one */
+                if (parent != NULL) {
+                        *parent = g_key_file_get_string (file,
+                                                         "Sound Theme",
+                                                         "Inherits",
+                                                         NULL);
+                }
+        }
+
+        g_key_file_free (file);
+        return indexname;
+}
+
+static void
+sound_theme_in_dir (GHashTable *hash,
+                    const char *dir)
+{
+        GDir *d;
+        const char *name;
+
+        d = g_dir_open (dir, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *dirname, *index, *indexname;
+
+                /* Look for directories */
+                dirname = g_build_filename (dir, name, NULL);
+                if (g_file_test (dirname, G_FILE_TEST_IS_DIR) == FALSE) {
+                        g_free (dirname);
+                        continue;
+                }
+
+                /* Look for index files */
+                index = g_build_filename (dirname, "index.theme", NULL);
+                g_free (dirname);
+
+                /* Check the name of the theme in the index.theme file */
+                indexname = load_index_theme_name (index, NULL);
+                g_free (index);
+                if (indexname == NULL) {
+                        continue;
+                }
+
+                g_hash_table_insert (hash, g_strdup (name), indexname);
+        }
+
+        g_dir_close (d);
+}
+
+static void
+add_theme_to_store (const char   *key,
+                    const char   *value,
+                    GtkListStore *store)
+{
+        char *parent;
+
+        parent = NULL;
+
+        /* Get the parent, if we're checking the custom theme */
+        if (strcmp (key, CUSTOM_THEME_NAME) == 0) {
+                char *name, *path;
+
+                path = custom_theme_dir_path ("index.theme");
+                name = load_index_theme_name (path, &parent);
+                g_free (name);
+                g_free (path);
+        }
+        gtk_list_store_insert_with_values (store, NULL, G_MAXINT,
+                                           THEME_DISPLAY_COL, value,
+                                           THEME_IDENTIFIER_COL, key,
+                                           THEME_PARENT_ID_COL, parent,
+                                           -1);
+        g_free (parent);
+}
+
+static void
+set_combox_for_theme_name (GvcSoundThemeChooser *chooser,
+                           const char           *name)
+{
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        gboolean      found;
+
+        /* If the name is empty, use "freedesktop" */
+        if (name == NULL || *name == '\0') {
+                name = "freedesktop";
+        }
+
+        model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+        if (gtk_tree_model_get_iter_first (model, &iter) == FALSE) {
+                return;
+        }
+
+        do {
+                char *value;
+
+                gtk_tree_model_get (model, &iter, THEME_IDENTIFIER_COL, &value, -1);
+                found = (value != NULL && strcmp (value, name) == 0);
+                g_free (value);
+
+        } while (!found && gtk_tree_model_iter_next (model, &iter));
+
+        /* When we can't find the theme we need to set, try to set the default
+         * one "freedesktop" */
+        if (found) {
+                gtk_combo_box_set_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter);
+        } else if (strcmp (name, "freedesktop") != 0) {
+                g_debug ("not found, falling back to fdo");
+                set_combox_for_theme_name (chooser, "freedesktop");
+        }
+}
+
+static void
+set_input_feedback_enabled (GvcSoundThemeChooser *chooser,
+                            gboolean              enabled)
+{
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      enabled);
+}
+
+static void
+setup_theme_selector (GvcSoundThemeChooser *chooser)
+{
+        GHashTable           *hash;
+        GtkListStore         *store;
+        GtkCellRenderer      *renderer;
+        const char * const   *data_dirs;
+        const char           *data_dir;
+        char                 *dir;
+        guint                 i;
+
+        /* Add the theme names and their display name to a hash table,
+         * makes it easy to avoid duplicate themes */
+        hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+        data_dirs = g_get_system_data_dirs ();
+        for (i = 0; data_dirs[i] != NULL; i++) {
+                dir = g_build_filename (data_dirs[i], "sounds", NULL);
+                sound_theme_in_dir (hash, dir);
+                g_free (dir);
+        }
+
+        data_dir = g_get_user_data_dir ();
+        dir = g_build_filename (data_dir, "sounds", NULL);
+        sound_theme_in_dir (hash, dir);
+        g_free (dir);
+
+        /* If there isn't at least one theme, make everything
+         * insensitive, LAME! */
+        if (g_hash_table_size (hash) == 0) {
+                gtk_widget_set_sensitive (GTK_WIDGET (chooser), FALSE);
+                g_warning ("Bad setup, install the freedesktop sound theme");
+                g_hash_table_destroy (hash);
+                return;
+        }
+
+        /* Setup the tree model, 3 columns:
+         * - internal theme name/directory
+         * - display theme name
+         * - the internal id for the parent theme, used for the custom theme */
+        store = gtk_list_store_new (THEME_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING);
+
+        /* Add the themes to a combobox */
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           THEME_DISPLAY_COL, _("No sounds"),
+                                           THEME_IDENTIFIER_COL, "__no_sounds",
+                                           THEME_PARENT_ID_COL, NULL,
+                                           -1);
+        g_hash_table_foreach (hash, (GHFunc) add_theme_to_store, store);
+        g_hash_table_destroy (hash);
+
+        /* Set the display */
+        gtk_combo_box_set_model (GTK_COMBO_BOX (chooser->priv->combo_box),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                    renderer,
+                                    TRUE);
+        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (chooser->priv->combo_box),
+                                        renderer,
+                                        "text", THEME_DISPLAY_COL,
+                                        NULL);
+
+        g_signal_connect (G_OBJECT (chooser->priv->combo_box),
+                          "changed",
+                          G_CALLBACK (on_combobox_changed),
+                          chooser);
+}
+
+#define GVC_SOUND_SOUND    (xmlChar *) "sound"
+#define GVC_SOUND_NAME     (xmlChar *) "name"
+#define GVC_SOUND_FILENAME (xmlChar *) "filename"
+
+/* Adapted from yelp-toc-pager.c */
+static xmlChar *
+xml_get_and_trim_names (xmlNodePtr node)
+{
+        xmlNodePtr cur;
+        xmlChar *keep_lang = NULL;
+        xmlChar *value;
+        int j, keep_pri = INT_MAX;
+
+        const gchar * const * langs = g_get_language_names ();
+
+        value = NULL;
+
+        for (cur = node->children; cur; cur = cur->next) {
+                if (! xmlStrcmp (cur->name, GVC_SOUND_NAME)) {
+                        xmlChar *cur_lang = NULL;
+                        int cur_pri = INT_MAX;
+
+                        cur_lang = xmlNodeGetLang (cur);
+
+                        if (cur_lang) {
+                                for (j = 0; langs[j]; j++) {
+                                        if (g_str_equal (cur_lang, langs[j])) {
+                                                cur_pri = j;
+                                                break;
+                                        }
+                                }
+                        } else {
+                                cur_pri = INT_MAX - 1;
+                        }
+
+                        if (cur_pri <= keep_pri) {
+                                if (keep_lang)
+                                        xmlFree (keep_lang);
+                                if (value)
+                                        xmlFree (value);
+
+                                value = xmlNodeGetContent (cur);
+
+                                keep_lang = cur_lang;
+                                keep_pri = cur_pri;
+                        } else {
+                                if (cur_lang)
+                                        xmlFree (cur_lang);
+                        }
+                }
+        }
+
+        /* Delete all GVC_SOUND_NAME nodes */
+        cur = node->children;
+        while (cur) {
+                xmlNodePtr this = cur;
+                cur = cur->next;
+                if (! xmlStrcmp (this->name, GVC_SOUND_NAME)) {
+                        xmlUnlinkNode (this);
+                        xmlFreeNode (this);
+                }
+        }
+
+        return value;
+}
+
+static void
+populate_model_from_node (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          xmlNodePtr            node)
+{
+        xmlNodePtr child;
+        xmlChar   *filename;
+        xmlChar   *name;
+
+        filename = NULL;
+        name = xml_get_and_trim_names (node);
+        for (child = node->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+
+                if (xmlStrcmp (child->name, GVC_SOUND_FILENAME) == 0) {
+                        filename = xmlNodeGetContent (child);
+                } else if (xmlStrcmp (child->name, GVC_SOUND_NAME) == 0) {
+                        /* EH? should have been trimmed */
+                }
+        }
+
+        if (filename != NULL && name != NULL) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   ALERT_IDENTIFIER_COL, filename,
+                                                   ALERT_DISPLAY_COL, name,
+                                                   ALERT_SOUND_TYPE_COL, _("Built-in"),
+                                                   ALERT_ACTIVE_COL, FALSE,
+                                                   -1);
+        }
+
+        xmlFree (filename);
+        xmlFree (name);
+}
+
+static void
+populate_model_from_file (GvcSoundThemeChooser *chooser,
+                          GtkTreeModel         *model,
+                          const char           *filename)
+{
+        xmlDocPtr  doc;
+        xmlNodePtr root;
+        xmlNodePtr child;
+        gboolean   exists;
+
+        exists = g_file_test (filename, G_FILE_TEST_EXISTS);
+        if (! exists) {
+                return;
+        }
+
+        doc = xmlParseFile (filename);
+        if (doc == NULL) {
+                return;
+        }
+
+        root = xmlDocGetRootElement (doc);
+
+        for (child = root->children; child; child = child->next) {
+                if (xmlNodeIsText (child)) {
+                        continue;
+                }
+                if (xmlStrcmp (child->name, GVC_SOUND_SOUND) != 0) {
+                        continue;
+                }
+
+                populate_model_from_node (chooser, model, child);
+        }
+
+        xmlFreeDoc (doc);
+}
+
+static void
+populate_model_from_dir (GvcSoundThemeChooser *chooser,
+                         GtkTreeModel         *model,
+                         const char           *dirname)
+{
+        GDir       *d;
+        const char *name;
+
+        d = g_dir_open (dirname, 0, NULL);
+        if (d == NULL) {
+                return;
+        }
+
+        while ((name = g_dir_read_name (d)) != NULL) {
+                char *path;
+
+                if (! g_str_has_suffix (name, ".xml")) {
+                        continue;
+                }
+
+                path = g_build_filename (dirname, name, NULL);
+                populate_model_from_file (chooser, model, path);
+                g_free (path);
+        }
+
+        g_dir_close (d);
+}
+
+static gboolean
+save_alert_sounds (GvcSoundThemeChooser  *chooser,
+                   const char            *id)
+{
+        const char *sounds[3] = { "bell-terminal", "bell-window-system", NULL };
+        char *path;
+
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+        } else {
+                delete_old_files (sounds);
+                delete_disabled_files (sounds);
+                add_custom_file (sounds, id);
+        }
+
+        /* And poke the directory so the theme gets updated */
+        path = custom_theme_dir_path (NULL);
+        if (utime (path, NULL) != 0) {
+                g_warning ("Failed to update mtime for directory '%s': %s",
+                           path, g_strerror (errno));
+        }
+        g_free (path);
+
+        return FALSE;
+}
+
+
+static void
+update_alert_model (GvcSoundThemeChooser  *chooser,
+                    const char            *id)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        gtk_tree_model_get_iter_first (model, &iter);
+        do {
+                gboolean toggled;
+                char    *this_id;
+
+                gtk_tree_model_get (model, &iter,
+                                    ALERT_IDENTIFIER_COL, &this_id,
+                                    -1);
+
+                if (strcmp (this_id, id) == 0) {
+                        toggled = TRUE;
+                } else {
+                        toggled = FALSE;
+                }
+                g_free (this_id);
+
+                gtk_list_store_set (GTK_LIST_STORE (model),
+                                    &iter,
+                                    ALERT_ACTIVE_COL, toggled,
+                                    -1);
+        } while (gtk_tree_model_iter_next (model, &iter));
+}
+
+static void
+update_alert (GvcSoundThemeChooser *chooser,
+              const char           *alert_id)
+{
+        GtkTreeModel *theme_model;
+        GtkTreeIter   iter;
+        char         *theme;
+        char         *parent;
+        gboolean      is_custom;
+        gboolean      is_default;
+        gboolean      add_custom;
+        gboolean      remove_custom;
+
+        theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+        /* Get the current theme's name, and set the parent */
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &iter) == FALSE) {
+                return;
+        }
+
+        gtk_tree_model_get (theme_model, &iter,
+                            THEME_IDENTIFIER_COL, &theme,
+                            THEME_IDENTIFIER_COL, &parent,
+                            -1);
+        is_custom = strcmp (theme, CUSTOM_THEME_NAME) == 0;
+        is_default = strcmp (alert_id, DEFAULT_ALERT_ID) == 0;
+
+        /* So a few possibilities:
+         * 1. Named theme, default alert selected: noop
+         * 2. Named theme, alternate alert selected: create new custom with sound
+         * 3. Custom theme, default alert selected: remove sound and possibly custom
+         * 4. Custom theme, alternate alert selected: update custom sound
+         */
+        add_custom = FALSE;
+        remove_custom = FALSE;
+        if (! is_custom && is_default) {
+                /* remove custom just in case */
+                remove_custom = TRUE;
+        } else if (! is_custom && ! is_default) {
+                create_custom_theme (parent);
+                save_alert_sounds (chooser, alert_id);
+                add_custom = TRUE;
+        } else if (is_custom && is_default) {
+                save_alert_sounds (chooser, alert_id);
+                /* after removing files check if it is empty */
+                if (custom_theme_dir_is_empty ()) {
+                        remove_custom = TRUE;
+                }
+        } else if (is_custom && ! is_default) {
+                save_alert_sounds (chooser, alert_id);
+        }
+
+        if (add_custom) {
+                gtk_list_store_insert_with_values (GTK_LIST_STORE (theme_model),
+                                                   NULL,
+                                                   G_MAXINT,
+                                                   THEME_DISPLAY_COL, _("Custom"),
+                                                   THEME_IDENTIFIER_COL, CUSTOM_THEME_NAME,
+                                                   THEME_PARENT_ID_COL, theme,
+                                                   -1);
+                set_combox_for_theme_name (chooser, CUSTOM_THEME_NAME);
+        } else if (remove_custom) {
+                gtk_tree_model_get_iter_first (theme_model, &iter);
+                do {
+                        char *this_parent;
+
+                        gtk_tree_model_get (theme_model, &iter,
+                                            THEME_PARENT_ID_COL, &this_parent,
+                                            -1);
+                        if (this_parent != NULL && strcmp (this_parent, CUSTOM_THEME_NAME) != 0) {
+                                g_free (this_parent);
+                                gtk_list_store_remove (GTK_LIST_STORE (theme_model), &iter);
+                                break;
+                        }
+                        g_free (this_parent);
+                } while (gtk_tree_model_iter_next (theme_model, &iter));
+
+                delete_custom_theme_dir ();
+
+                set_combox_for_theme_name (chooser, parent);
+        }
+
+        update_alert_model (chooser, alert_id);
+
+        g_free (theme);
+        g_free (parent);
+}
+
+static void
+on_alert_toggled (GtkCellRendererToggle *renderer,
+                  char                  *path_str,
+                  GvcSoundThemeChooser  *chooser)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreePath  *path;
+        gboolean      toggled;
+        char         *id;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        path = gtk_tree_path_new_from_string (path_str);
+        gtk_tree_model_get_iter (model, &iter, path);
+        gtk_tree_path_free (path);
+
+        id = NULL;
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            ALERT_ACTIVE_COL, &toggled,
+                            -1);
+
+        toggled ^= 1;
+        if (toggled) {
+                update_alert (chooser, id);
+        }
+
+        g_free (id);
+}
+
+static void
+play_preview_for_path (GvcSoundThemeChooser *chooser, GtkTreePath *path)
+{
+        GtkTreeModel *model;
+        GtkTreeIter   iter;
+        GtkTreeIter   theme_iter;
+        gchar        *id = NULL;
+        gchar        *parent_theme = NULL;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+        if (gtk_tree_model_get_iter (model, &iter, path) == FALSE)
+                return;
+
+        gtk_tree_model_get (model, &iter,
+                            ALERT_IDENTIFIER_COL, &id,
+                            -1);
+        if (id == NULL)
+                return;
+
+        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (chooser->priv->combo_box), &theme_iter)) {
+                GtkTreeModel *theme_model;
+                gchar        *theme_id = NULL;
+                gchar        *parent_id = NULL;
+
+                theme_model = gtk_combo_box_get_model (GTK_COMBO_BOX (chooser->priv->combo_box));
+
+                gtk_tree_model_get (theme_model, &theme_iter,
+                                    THEME_IDENTIFIER_COL, &theme_id,
+                                    THEME_PARENT_ID_COL, &parent_id, -1);
+                if (theme_id && strcmp (theme_id, CUSTOM_THEME_NAME) == 0)
+                        parent_theme = g_strdup (parent_id);
+
+                g_free (theme_id);
+                g_free (parent_id);
+        }
+
+        /* special case: for the default item on custom themes
+         * play the alert for the parent theme */
+        if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
+                if (parent_theme != NULL) {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_CANBERRA_XDG_THEME_NAME, parent_theme,
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                } else {
+                        ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                                CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                                CA_PROP_EVENT_ID, "bell-window-system",
+                                                CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                                CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                                CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                                CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                                NULL);
+                }
+        } else {
+                ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
+                                        CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
+                                        CA_PROP_MEDIA_FILENAME, id,
+                                        CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
+                                        CA_PROP_CANBERRA_CACHE_CONTROL, "never",
+                                        CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+#ifdef CA_PROP_CANBERRA_ENABLE
+                                        CA_PROP_CANBERRA_ENABLE, "1",<--- Skipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
+#endif
+                                        NULL);
+
+        }
+        g_free (parent_theme);
+        g_free (id);
+}
+
+static void
+on_treeview_row_activated (GtkTreeView          *treeview,
+                           GtkTreePath          *path,
+                           GtkTreeViewColumn    *column,
+                           GvcSoundThemeChooser *chooser)
+{
+        play_preview_for_path (chooser, path);
+}
+
+static void
+on_treeview_selection_changed (GtkTreeSelection     *selection,
+                               GvcSoundThemeChooser *chooser)
+{
+        GList        *paths;
+        GtkTreeModel *model;
+        GtkTreePath  *path;
+
+        if (chooser->priv->treeview == NULL)
+                return;
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
+
+        paths = gtk_tree_selection_get_selected_rows (selection, &model);
+        if (paths == NULL)
+                return;
+
+        path = paths->data;
+        play_preview_for_path (chooser, path);
+
+        g_list_foreach (paths, (GFunc)gtk_tree_path_free, NULL);
+        g_list_free (paths);
+}
+
+static GtkWidget *
+create_alert_treeview (GvcSoundThemeChooser *chooser)
+{
+        GtkListStore         *store;
+        GtkWidget            *treeview;
+        GtkCellRenderer      *renderer;
+        GtkTreeViewColumn    *column;
+        GtkTreeSelection     *selection;
+
+        treeview = gtk_tree_view_new ();
+
+        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
+        g_signal_connect (G_OBJECT (treeview),
+                          "row-activated",
+                          G_CALLBACK (on_treeview_row_activated),
+                          chooser);
+
+        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+        gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+        g_signal_connect (G_OBJECT (selection),
+                          "changed",
+                          G_CALLBACK (on_treeview_selection_changed),
+                          chooser);
+
+        /* Setup the tree model, 3 columns:
+         * - display name
+         * - sound id
+         * - sound type
+         */
+        store = gtk_list_store_new (ALERT_NUM_COLS,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_STRING,
+                                    G_TYPE_BOOLEAN);
+
+        gtk_list_store_insert_with_values (store,
+                                           NULL,
+                                           G_MAXINT,
+                                           ALERT_IDENTIFIER_COL, DEFAULT_ALERT_ID,
+                                           ALERT_DISPLAY_COL, _("Default"),
+                                           ALERT_SOUND_TYPE_COL, _("From theme"),
+                                           ALERT_ACTIVE_COL, TRUE,
+                                           -1);
+
+        populate_model_from_dir (chooser, GTK_TREE_MODEL (store), SOUND_SET_DIR);
+
+        gtk_tree_view_set_model (GTK_TREE_VIEW (treeview),
+                                 GTK_TREE_MODEL (store));
+
+        renderer = gtk_cell_renderer_toggle_new ();
+        gtk_cell_renderer_toggle_set_radio (GTK_CELL_RENDERER_TOGGLE (renderer), TRUE);
+
+        column = gtk_tree_view_column_new_with_attributes (NULL,
+                                                           renderer,
+                                                           "active", ALERT_ACTIVE_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+        g_signal_connect (renderer,
+                          "toggled",
+                          G_CALLBACK (on_alert_toggled),
+                          chooser);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Name"),
+                                                           renderer,
+                                                           "text", ALERT_DISPLAY_COL,
+                                                           NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes (_("Type"),
+                                                           renderer,
+                                                           "text", ALERT_SOUND_TYPE_COL,
+                                                           NULL);
+
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        return treeview;
+}
+
+static int
+get_file_type (const char *sound_name,
+               char      **linked_name)
+{
+        char *name, *filename;
+
+        *linked_name = NULL;
+
+        name = g_strdup_printf ("%s.disabled", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_REGULAR) != FALSE) {
+                g_free (filename);
+                return SOUND_TYPE_OFF;
+        }
+        g_free (filename);
+
+        /* We only check for .ogg files because those are the
+         * only ones we create */
+        name = g_strdup_printf ("%s.ogg", sound_name);
+        filename = custom_theme_dir_path (name);
+        g_free (name);
+
+        if (g_file_test (filename, G_FILE_TEST_IS_SYMLINK) != FALSE) {
+                *linked_name = g_file_read_link (filename, NULL);
+                g_free (filename);
+                return SOUND_TYPE_CUSTOM;
+        }
+        g_free (filename);
+
+        return SOUND_TYPE_BUILTIN;
+}
+
+static void
+update_alerts_from_theme_name (GvcSoundThemeChooser *chooser,
+                               const gchar          *name)
+{
+        if (strcmp (name, CUSTOM_THEME_NAME) != 0) {
+                /* reset alert to default */
+                update_alert (chooser, DEFAULT_ALERT_ID);
+        } else {
+                int   sound_type;
+                char *linkname;
+
+                linkname = NULL;
+                sound_type = get_file_type ("bell-terminal", &linkname);
+                g_debug ("Found link: %s", linkname);
+                if (sound_type == SOUND_TYPE_CUSTOM) {
+                        update_alert (chooser, linkname);
+                }
+        }
+}
+
+static void
+update_theme (GvcSoundThemeChooser *chooser)
+{
+        char        *theme_name;
+        gboolean     events_enabled;
+        gboolean     feedback_enabled;
+
+        feedback_enabled = g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY);
+        set_input_feedback_enabled (chooser, feedback_enabled);
+
+        events_enabled = g_settings_get_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY);
+        if (events_enabled) {
+                theme_name = g_settings_get_string (chooser->priv->sound_settings, SOUND_THEME_KEY);
+        } else {
+                theme_name = g_strdup (NO_SOUNDS_THEME_NAME);
+        }
+
+        gtk_widget_set_sensitive (chooser->priv->selection_box, events_enabled);
+        gtk_widget_set_sensitive (chooser->priv->click_feedback_button, events_enabled);
+
+        set_combox_for_theme_name (chooser, theme_name);
+
+        update_alerts_from_theme_name (chooser, theme_name);
+
+        g_free (theme_name);
+}
+
+static void
+gvc_sound_theme_chooser_class_init (GvcSoundThemeChooserClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose = gvc_sound_theme_chooser_dispose;
+}
+
+static void
+on_click_feedback_toggled (GtkToggleButton      *button,
+                           GvcSoundThemeChooser *chooser)
+{
+        gboolean enabled;
+
+        enabled = gtk_toggle_button_get_active (button);
+
+        g_settings_set_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY, enabled);
+}
+
+static void
+on_key_changed (GSettings            *settings,
+                gchar                *key,
+                GvcSoundThemeChooser *chooser)
+{
+        if (!strcmp (key, EVENT_SOUNDS_KEY) ||
+            !strcmp (key, SOUND_THEME_KEY) ||
+            !strcmp (key, INPUT_SOUNDS_KEY))
+                update_theme (chooser);
+}
+
+static void
+setup_list_size_constraint (GtkWidget *widget,
+                            GtkWidget *to_size)
+{
+        GtkRequisition req;
+        gint           sc_height;
+        int            max_height;
+
+        /* Constrain height to be the tree height up to a max */
+        gdk_window_get_geometry (gdk_screen_get_root_window (gtk_widget_get_screen (widget)),
+                                 NULL, NULL, NULL, &sc_height);
+
+        max_height = sc_height / 4;
+
+        // XXX this doesn't work
+        gtk_widget_get_preferred_size (to_size, NULL, &req);
+
+        gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (widget),
+                                                    MIN (req.height, max_height));
+}
+
+static void
+gvc_sound_theme_chooser_init (GvcSoundThemeChooser *chooser)
+{
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *scrolled_window;
+        gchar       *str;
+
+        chooser->priv = gvc_sound_theme_chooser_get_instance_private (chooser);
+
+        chooser->priv->theme_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->theme_box, FALSE, FALSE, 0);
+
+        label = gtk_label_new_with_mnemonic (_("Sound _theme:"));
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), label, FALSE, FALSE, 0);
+        chooser->priv->combo_box = gtk_combo_box_new ();
+        gtk_box_pack_start (GTK_BOX (chooser->priv->theme_box), chooser->priv->combo_box, FALSE, FALSE, 6);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->combo_box);
+
+        chooser->priv->sound_settings = g_settings_new (KEY_SOUNDS_SCHEMA);
+
+        g_signal_connect (G_OBJECT (chooser->priv->sound_settings),
+                          "changed",
+                          G_CALLBACK (on_key_changed),
+                          chooser);
+
+        str = g_strdup_printf ("<b>%s</b>", _("C_hoose an alert sound:"));
+        chooser->priv->selection_box = box = gtk_frame_new (str);
+        g_free (str);
+
+        label = gtk_frame_get_label_widget (GTK_FRAME (box));
+        gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
+        gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+        gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
+
+        gtk_box_pack_start (GTK_BOX (chooser), box, TRUE, TRUE, 6);
+
+        chooser->priv->treeview = create_alert_treeview (chooser);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->treeview);
+
+        scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+        gtk_widget_set_hexpand (scrolled_window, TRUE);
+        gtk_widget_set_vexpand (scrolled_window, TRUE);
+        gtk_widget_set_margin_top (scrolled_window, 6);
+
+        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+                                        GTK_POLICY_NEVER,
+                                        GTK_POLICY_AUTOMATIC);
+        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
+                                             GTK_SHADOW_IN);
+
+        gtk_container_add (GTK_CONTAINER (scrolled_window), chooser->priv->treeview);
+        gtk_container_add (GTK_CONTAINER (box), scrolled_window);
+
+        chooser->priv->click_feedback_button = gtk_check_button_new_with_mnemonic (_("Enable _window and button sounds"));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->priv->click_feedback_button),
+                                      g_settings_get_boolean (chooser->priv->sound_settings, INPUT_SOUNDS_KEY));
+
+        gtk_box_pack_start (GTK_BOX (chooser),
+                            chooser->priv->click_feedback_button,
+                            FALSE, FALSE, 0);
+
+        g_signal_connect (G_OBJECT (chooser->priv->click_feedback_button),
+                          "toggled",
+                          G_CALLBACK (on_click_feedback_toggled),
+                          chooser);
+
+        setup_theme_selector (chooser);
+        update_theme (chooser);
+
+        setup_list_size_constraint (scrolled_window, chooser->priv->treeview);
+}
+
+static void
+gvc_sound_theme_chooser_dispose (GObject *object)
+{
+        GvcSoundThemeChooser *chooser;
+
+        chooser = GVC_SOUND_THEME_CHOOSER (object);
+
+        g_clear_object (&chooser->priv->sound_settings);
+
+        G_OBJECT_CLASS (gvc_sound_theme_chooser_parent_class)->dispose (object);
+}
+
+GtkWidget *
+gvc_sound_theme_chooser_new (void)
+{
+        return g_object_new (GVC_TYPE_SOUND_THEME_CHOOSER,
+                                "spacing", 6,
+                                "orientation", GTK_ORIENTATION_VERTICAL,
+                                NULL);
+}
+
+
+
+
+ + + diff --git a/2020-08-18-170623-4816-cppcheck@c82f5feb6c8f_v1.25.0/2.html b/2020-08-18-170623-4816-cppcheck@c82f5feb6c8f_v1.25.0/2.html new file mode 100644 index 0000000..64940b3 --- /dev/null +++ b/2020-08-18-170623-4816-cppcheck@c82f5feb6c8f_v1.25.0/2.html @@ -0,0 +1,1126 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + +
+ +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Bastien Nocera
+ * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <canberra.h>
+#include <libmatemixer/matemixer.h>
+
+#include "gvc-speaker-test.h"
+#include "gvc-utils.h"
+
+struct _GvcSpeakerTestPrivate
+{
+        GArray           *controls;
+        ca_context       *canberra;
+        MateMixerStream  *stream;
+};
+
+enum {
+        PROP_0,
+        PROP_STREAM,
+        N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gvc_speaker_test_dispose    (GObject             *object);
+static void gvc_speaker_test_finalize   (GObject             *object);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GvcSpeakerTest, gvc_speaker_test, GTK_TYPE_GRID)<--- There is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+typedef struct {
+        MateMixerChannelPosition position;
+        guint left;
+        guint top;
+} TablePosition;
+
+static const TablePosition positions[] = {
+        /* Position, X, Y */
+        { MATE_MIXER_CHANNEL_FRONT_LEFT, 0, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_LEFT_CENTER, 1, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_CENTER, 2, 0, },
+        { MATE_MIXER_CHANNEL_MONO, 2, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT_CENTER, 3, 0, },
+        { MATE_MIXER_CHANNEL_FRONT_RIGHT, 4, 0, },
+        { MATE_MIXER_CHANNEL_SIDE_LEFT, 0, 1, },
+        { MATE_MIXER_CHANNEL_SIDE_RIGHT, 4, 1, },
+        { MATE_MIXER_CHANNEL_BACK_LEFT, 0, 2, },
+        { MATE_MIXER_CHANNEL_BACK_CENTER, 2, 2, },
+        { MATE_MIXER_CHANNEL_BACK_RIGHT, 4, 2, },
+        { MATE_MIXER_CHANNEL_LFE, 3, 2 }
+};
+
+MateMixerStream *
+gvc_speaker_test_get_stream (GvcSpeakerTest *test)
+{
+        g_return_val_if_fail (GVC_IS_SPEAKER_TEST (test), NULL);
+
+        return test->priv->stream;
+}
+
+static void
+gvc_speaker_test_set_stream (GvcSpeakerTest *test, MateMixerStream *stream)
+{
+        MateMixerStreamControl *control;
+        const gchar            *name;
+        guint                   i;
+
+        name = mate_mixer_stream_get_name (stream);
+        control = mate_mixer_stream_get_default_control (stream);
+
+        ca_context_change_device (test->priv->canberra, name);
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                gboolean has_position =
+                        mate_mixer_stream_control_has_channel_position (control, positions[i].position);
+
+                gtk_widget_set_visible (g_array_index (test->priv->controls, GtkWidget *, i),
+                                        has_position);
+        }
+
+        test->priv->stream = g_object_ref (stream);
+}
+
+static void
+gvc_speaker_test_set_property (GObject       *object,
+                               guint          prop_id,
+                               const GValue  *value,
+                               GParamSpec    *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                gvc_speaker_test_set_stream (self, g_value_get_object (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_get_property (GObject     *object,
+                               guint        prop_id,
+                               GValue      *value,
+                               GParamSpec  *pspec)
+{
+        GvcSpeakerTest *self = GVC_SPEAKER_TEST (object);
+
+        switch (prop_id) {
+        case PROP_STREAM:
+                g_value_set_object (value, self->priv->stream);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gvc_speaker_test_class_init (GvcSpeakerTestClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->dispose  = gvc_speaker_test_dispose;
+        object_class->finalize = gvc_speaker_test_finalize;
+        object_class->set_property = gvc_speaker_test_set_property;
+        object_class->get_property = gvc_speaker_test_get_property;
+
+        properties[PROP_STREAM] =
+                g_param_spec_object ("stream",
+                                     "Stream",
+                                     "MateMixer stream",
+                                     MATE_MIXER_TYPE_STREAM,
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_CONSTRUCT_ONLY |
+                                     G_PARAM_STATIC_STRINGS);
+
+        g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+}
+
+static const gchar *
+sound_name (MateMixerChannelPosition position)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return "audio-channel-front-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return "audio-channel-front-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return "audio-channel-front-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return "audio-channel-rear-left";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return "audio-channel-rear-right";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return "audio-channel-rear-center";
+        case MATE_MIXER_CHANNEL_LFE:
+                return "audio-channel-lfe";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return "audio-channel-side-left";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return "audio-channel-side-right";
+        default:
+                return NULL;
+        }
+}
+
+static const gchar *
+icon_name (MateMixerChannelPosition position, gboolean playing)
+{
+        switch (position) {
+        case MATE_MIXER_CHANNEL_FRONT_LEFT:
+                return playing
+                        ? "audio-speaker-left-testing"
+                        : "audio-speaker-left";
+        case MATE_MIXER_CHANNEL_FRONT_RIGHT:
+                return playing
+                        ? "audio-speaker-right-testing"
+                        : "audio-speaker-right";
+        case MATE_MIXER_CHANNEL_FRONT_CENTER:
+                return playing
+                        ? "audio-speaker-center-testing"
+                        : "audio-speaker-center";
+        case MATE_MIXER_CHANNEL_BACK_LEFT:
+                return playing
+                        ? "audio-speaker-left-back-testing"
+                        : "audio-speaker-left-back";
+        case MATE_MIXER_CHANNEL_BACK_RIGHT:
+                return playing
+                        ? "audio-speaker-right-back-testing"
+                        : "audio-speaker-right-back";
+        case MATE_MIXER_CHANNEL_BACK_CENTER:
+                return playing
+                        ? "audio-speaker-center-back-testing"
+                        : "audio-speaker-center-back";
+        case MATE_MIXER_CHANNEL_LFE:
+                return playing
+                        ? "audio-subwoofer-testing"
+                        : "audio-subwoofer";
+        case MATE_MIXER_CHANNEL_SIDE_LEFT:
+                return playing
+                        ? "audio-speaker-left-side-testing"
+                        : "audio-speaker-left-side";
+        case MATE_MIXER_CHANNEL_SIDE_RIGHT:
+                return playing
+                        ? "audio-speaker-right-side-testing"
+                        : "audio-speaker-right-side";
+        default:
+                return NULL;
+        }
+}
+
+static void
+update_button (GtkWidget *control)
+{
+        GtkWidget *button;
+        GtkWidget *image;
+        gboolean   playing;
+        MateMixerChannelPosition position;
+
+        button = g_object_get_data (G_OBJECT (control), "button");
+        image  = g_object_get_data (G_OBJECT (control), "image");
+
+        position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+        playing  = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        gtk_button_set_label (GTK_BUTTON (button), playing ? _("Stop") : _("Test"));
+
+        gtk_image_set_from_icon_name (GTK_IMAGE (image),
+                                      icon_name (position, playing),
+                                      GTK_ICON_SIZE_DIALOG);
+}
+
+static gboolean
+idle_cb (GtkWidget *control)
+{
+        if (control != NULL) {
+                /* This is called in the background thread, hence forward to main thread
+                 * via idle callback */
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+
+                update_button (control);
+        }
+        return FALSE;
+}
+
+static void
+finish_cb (ca_context *c, uint32_t id, int error_code, void *userdata)
+{
+        GtkWidget *control = (GtkWidget *) userdata;
+
+        if (error_code == CA_ERROR_DESTROYED || control == NULL)
+                return;
+
+        g_idle_add ((GSourceFunc) idle_cb, control);
+}
+
+static void
+on_test_button_clicked (GtkButton *button, GtkWidget *control)
+{
+        gboolean    playing;
+        ca_context *canberra;
+
+        canberra = g_object_get_data (G_OBJECT (control), "canberra");
+
+        ca_context_cancel (canberra, 1);
+
+        playing = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "playing"));
+
+        if (playing) {
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        } else {
+                MateMixerChannelPosition position;
+                const gchar *name;
+                ca_proplist *proplist;
+
+                position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (control), "position"));
+
+                ca_proplist_create (&proplist);
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_ROLE, "test");
+                ca_proplist_sets (proplist,
+                                  CA_PROP_MEDIA_NAME,
+                                  gvc_channel_position_to_pretty_string (position));
+                ca_proplist_sets (proplist,
+                                  CA_PROP_CANBERRA_FORCE_CHANNEL,
+                                  gvc_channel_position_to_pulse_string (position));
+
+                ca_proplist_sets (proplist, CA_PROP_CANBERRA_ENABLE, "1");
+
+                name = sound_name (position);
+                if (name != NULL) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, name);
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets (proplist, CA_PROP_EVENT_ID, "audio-test-signal");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                if (!playing) {
+                        ca_proplist_sets(proplist, CA_PROP_EVENT_ID, "bell-window-system");
+                        playing = ca_context_play_full (canberra, 1, proplist, finish_cb, control) >= 0;
+                }
+
+                g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (playing));
+        }
+
+        update_button (control);
+}
+
+static GtkWidget *
+create_control (ca_context *canberra, MateMixerChannelPosition position)
+{
+        GtkWidget   *control;
+        GtkWidget   *box;
+        GtkWidget   *label;
+        GtkWidget   *image;
+        GtkWidget   *test_button;
+        const gchar *name;
+
+        control = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+        box     = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+        g_object_set_data (G_OBJECT (control), "playing", GINT_TO_POINTER (FALSE));
+        g_object_set_data (G_OBJECT (control), "position", GINT_TO_POINTER (position));
+        g_object_set_data (G_OBJECT (control), "canberra", canberra);
+
+        name = icon_name (position, FALSE);
+        if (name == NULL)
+                name = "audio-volume-medium";
+
+        image = gtk_image_new_from_icon_name (name, GTK_ICON_SIZE_DIALOG);
+        g_object_set_data (G_OBJECT (control), "image", image);
+        gtk_box_pack_start (GTK_BOX (control), image, FALSE, FALSE, 0);
+
+        label = gtk_label_new (gvc_channel_position_to_pretty_string (position));
+        gtk_box_pack_start (GTK_BOX (control), label, FALSE, FALSE, 0);
+
+        test_button = gtk_button_new_with_label (_("Test"));
+        g_signal_connect (G_OBJECT (test_button),
+                          "clicked",
+                          G_CALLBACK (on_test_button_clicked),
+                          control);
+
+        g_object_set_data (G_OBJECT (control), "button", test_button);
+
+        gtk_box_pack_start (GTK_BOX (box), test_button, TRUE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (control), box, FALSE, FALSE, 0);
+
+        gtk_widget_show_all (control);
+
+        return control;
+}
+
+static void
+create_controls (GvcSpeakerTest *test)
+{
+        guint i;
+
+        for (i = 0; i < G_N_ELEMENTS (positions); i++) {
+                GtkWidget *control = create_control (test->priv->canberra, positions[i].position);
+
+                gtk_grid_attach (GTK_GRID (test),
+                                 control,
+                                 positions[i].left,
+                                 positions[i].top,
+                                 1, 1);
+                g_array_insert_val (test->priv->controls, i, control);
+        }
+}
+
+static void
+gvc_speaker_test_init (GvcSpeakerTest *test)
+{
+        GtkWidget *face;
+
+        test->priv = gvc_speaker_test_get_instance_private (test);
+
+        gtk_container_set_border_width (GTK_CONTAINER (test), 12);
+
+        face = gtk_image_new_from_icon_name ("face-smile", GTK_ICON_SIZE_DIALOG);
+
+        gtk_grid_attach (GTK_GRID (test),
+                         face,
+                         1, 1,
+                         3, 1);
+
+
+        gtk_grid_set_baseline_row (GTK_GRID (test), 1);
+        gtk_widget_show (face);
+
+        ca_context_create (&test->priv->canberra);
+
+        /* The test sounds are played for a single channel, set up using the
+         * FORCE_CHANNEL property of libcanberra; this property is only supported
+         * in the PulseAudio backend, so avoid other backends completely */
+        ca_context_set_driver (test->priv->canberra, "pulse");
+
+        ca_context_change_props (test->priv->canberra,
+                                 CA_PROP_APPLICATION_ID, "org.mate.VolumeControl",
+                                 CA_PROP_APPLICATION_NAME, _("Volume Control"),
+                                 CA_PROP_APPLICATION_VERSION, VERSION,
+                                 CA_PROP_APPLICATION_ICON_NAME, "multimedia-volume-control",
+                                 NULL);
+
+        test->priv->controls = g_array_new (FALSE, FALSE, sizeof (GtkWidget *));
+
+        create_controls (test);
+}
+
+static void
+gvc_speaker_test_dispose (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        g_clear_object (&test->priv->stream);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->dispose (object);
+}
+
+static void
+gvc_speaker_test_finalize (GObject *object)
+{
+        GvcSpeakerTest *test;
+
+        test = GVC_SPEAKER_TEST (object);
+
+        ca_context_destroy (test->priv->canberra);
+
+        G_OBJECT_CLASS (gvc_speaker_test_parent_class)->finalize (object);
+}
+
+GtkWidget *
+gvc_speaker_test_new (MateMixerStream *stream)
+{
+        GObject *test;
+
+        g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL);
+
+        test = g_object_new (GVC_TYPE_SPEAKER_TEST,
+                             "row-spacing", 6,
+                             "column-spacing", 6,
+                             "row-homogeneous", TRUE,
+                             "column-homogeneous", TRUE,
+                             "stream", stream,
+                             NULL);
+
+        return GTK_WIDGET (test);
+}
+
+
+
+
+ + + diff --git a/2020-08-18-170623-4816-cppcheck@c82f5feb6c8f_v1.25.0/index.html b/2020-08-18-170623-4816-cppcheck@c82f5feb6c8f_v1.25.0/index.html new file mode 100644 index 0000000..235f646 --- /dev/null +++ b/2020-08-18-170623-4816-cppcheck@c82f5feb6c8f_v1.25.0/index.html @@ -0,0 +1,124 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + +
+ +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
mate-volume-control/gvc-combo-box.c
70unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
mate-volume-control/gvc-sound-theme-chooser.c
735ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
746ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
758ConfigurationNotCheckedinformationSkipping configuration 'CA_PROP_CANBERRA_ENABLE' since the value of 'CA_PROP_CANBERRA_ENABLE' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.
mate-volume-control/gvc-speaker-test.c
53unknownMacroerrorThere is an unknown macro here somewhere. Configuration is required. If G_DEFINE_TYPE_WITH_PRIVATE is a macro then please configure it.
+
+
+ + + diff --git a/2020-08-18-170623-4816-cppcheck@c82f5feb6c8f_v1.25.0/stats.html b/2020-08-18-170623-4816-cppcheck@c82f5feb6c8f_v1.25.0/stats.html new file mode 100644 index 0000000..6eb8706 --- /dev/null +++ b/2020-08-18-170623-4816-cppcheck@c82f5feb6c8f_v1.25.0/stats.html @@ -0,0 +1,109 @@ + + + + + + Cppcheck - HTML report - mate-media + + + + + + +
+ +
+

Top 10 files for error severity, total findings: 2
+   1  mate-volume-control/gvc-speaker-test.c
+   1  mate-volume-control/gvc-combo-box.c
+

+

Top 10 files for information severity, total findings: 3
+   3  mate-volume-control/gvc-sound-theme-chooser.c
+

+ +
+
+ + + diff --git a/2020-08-18-170623-4816-cppcheck@c82f5feb6c8f_v1.25.0/style.css b/2020-08-18-170623-4816-cppcheck@c82f5feb6c8f_v1.25.0/style.css new file mode 100644 index 0000000..07125f4 --- /dev/null +++ b/2020-08-18-170623-4816-cppcheck@c82f5feb6c8f_v1.25.0/style.css @@ -0,0 +1,137 @@ + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; + font-size: 13px; + line-height: 1.5; + margin: 0; + width: auto; +} + +h1 { + margin: 10px; +} + +.header { + border-bottom: thin solid #aaa; +} + +.footer { + border-top: thin solid #aaa; + font-size: 90%; + margin-top: 5px; +} + +.footer ul { + list-style-type: none; + padding-left: 0; +} + +.footer > p { + margin: 4px; +} + +.wrapper { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; +} + +#menu, +#menu_index { + text-align: left; + width: 350px; + height: 90vh; + min-height: 200px; + overflow: auto; + position: -webkit-sticky; + position: sticky; + top: 0; + padding: 0 15px 15px 15px; +} + +#menu > a { + display: block; + margin-left: 10px; + font-size: 12px; + z-index: 1; +} + +#content, +#content_index { + background-color: #fff; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + padding: 0 15px 15px 15px; + width: calc(100% - 350px); + height: 100%; + overflow-x: auto; +} + +#filename { + margin-left: 10px; + font-size: 12px; + z-index: 1; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #b6b6b4; +} + +.inconclusive2 { + background-color: #b6b6b4; + display: inline-block; + margin-left: 4px; +} + +.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +.verbose .content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid #000; + background-color: #ffffcc; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +.highlighttable { + background-color: #fff; + z-index: 10; + position: relative; + margin: -10px; +} + +.linenos { + border-right: thin solid #aaa; + color: #d3d3d3; + padding-right: 6px; +} + +.d-none { + display: none; +} diff --git a/CNAME b/CNAME new file mode 100644 index 0000000..60c3d54 --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +mate-media.mate-desktop.dev diff --git a/index.html b/index.html new file mode 100644 index 0000000..fd9232c --- /dev/null +++ b/index.html @@ -0,0 +1,47 @@ + + + + + + mate-media Code Analyzer results + + +

+ mate-desktop/mate-media Static analyzer results +

+ GitHub + Build Status +
+Commit: c82f5feb6c8f0fa43e135eb66dd31de81ef02155
+Compare:
+Branch: v1.25.0
+Time: 2020-08-18 17:06:23+00:00
+Messages:
+
+release 1.25.0
+
+
+ + + -- cgit v1.2.1