Merge lp:~bbboson/ubuntu/precise/gnome-control-center/fix-for-1236612 into lp:ubuntu/precise-updates/gnome-control-center

Proposed by Madper Xie
Status: Merged
Merge reported by: Sebastien Bacher
Merged at revision: not available
Proposed branch: lp:~bbboson/ubuntu/precise/gnome-control-center/fix-for-1236612
Merge into: lp:ubuntu/precise-updates/gnome-control-center
Diff against target: 902 lines (+854/-0)
6 files modified
.pc/applied-patches (+1/-0)
.pc/sound-fix-potential-memory-corruption.patch/panels/sound/gvc-sound-theme-chooser.c (+833/-0)
debian/changelog (+6/-0)
debian/patches/series (+1/-0)
debian/patches/sound-fix-potential-memory-corruption.patch (+12/-0)
panels/sound/gvc-sound-theme-chooser.c (+1/-0)
To merge this branch: bzr merge lp:~bbboson/ubuntu/precise/gnome-control-center/fix-for-1236612
Reviewer Review Type Date Requested Status
Sebastien Bacher Approve
Review via email: mp+225776@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Sebastien Bacher (seb128) wrote :

Thanks, the vcs to use is lp:~ubuntu-desktop/gnome-control-center/precise (see debian/control), I've merged there and uploaded for you

review: Approve
Revision history for this message
Sebastien Bacher (seb128) wrote :

(could you make the bug SRU compliant, see https://wiki.ubuntu.com/StableReleaseUpdates)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.pc/applied-patches'
2--- .pc/applied-patches 2014-04-02 10:52:39 +0000
3+++ .pc/applied-patches 2014-07-07 05:56:11 +0000
4@@ -44,3 +44,4 @@
5 use_rfkill_airplane_mode.patch
6 more-power-suspend-options.patch
7 fix-input-device-bar-status.patch
8+sound-fix-potential-memory-corruption.patch
9
10=== added directory '.pc/sound-fix-potential-memory-corruption.patch'
11=== added file '.pc/sound-fix-potential-memory-corruption.patch/.timestamp'
12=== added directory '.pc/sound-fix-potential-memory-corruption.patch/panels'
13=== added directory '.pc/sound-fix-potential-memory-corruption.patch/panels/sound'
14=== added file '.pc/sound-fix-potential-memory-corruption.patch/panels/sound/gvc-sound-theme-chooser.c'
15--- .pc/sound-fix-potential-memory-corruption.patch/panels/sound/gvc-sound-theme-chooser.c 1970-01-01 00:00:00 +0000
16+++ .pc/sound-fix-potential-memory-corruption.patch/panels/sound/gvc-sound-theme-chooser.c 2014-07-07 05:56:11 +0000
17@@ -0,0 +1,833 @@
18+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
19+ *
20+ * Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
21+ * Copyright (C) 2008 William Jon McCann
22+ *
23+ * This program is free software; you can redistribute it and/or modify
24+ * it under the terms of the GNU General Public License as published by
25+ * the Free Software Foundation; either version 2 of the License, or
26+ * (at your option) any later version.
27+ *
28+ * This program is distributed in the hope that it will be useful,
29+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
30+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31+ * GNU General Public License for more details.
32+ *
33+ * You should have received a copy of the GNU General Public License
34+ * along with this program; if not, write to the Free Software
35+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
36+ *
37+ */
38+
39+#include "config.h"
40+
41+#include <stdlib.h>
42+#include <stdio.h>
43+#include <unistd.h>
44+#include <utime.h>
45+#include <errno.h>
46+
47+#include <glib.h>
48+#include <glib/gi18n-lib.h>
49+#include <gtk/gtk.h>
50+#include <canberra-gtk.h>
51+#include <libxml/tree.h>
52+
53+#include <gsettings-desktop-schemas/gdesktop-enums.h>
54+
55+#include "gvc-sound-theme-chooser.h"
56+#include "sound-theme-file-utils.h"
57+
58+#define GVC_SOUND_THEME_CHOOSER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_SOUND_THEME_CHOOSER, GvcSoundThemeChooserPrivate))
59+
60+struct GvcSoundThemeChooserPrivate
61+{
62+ GtkWidget *treeview;
63+ GtkWidget *selection_box;
64+ GSettings *settings;
65+ GSettings *sound_settings;
66+ char *current_theme;
67+ char *current_parent;
68+};
69+
70+static void gvc_sound_theme_chooser_class_init (GvcSoundThemeChooserClass *klass);
71+static void gvc_sound_theme_chooser_init (GvcSoundThemeChooser *sound_theme_chooser);
72+static void gvc_sound_theme_chooser_finalize (GObject *object);
73+
74+G_DEFINE_TYPE (GvcSoundThemeChooser, gvc_sound_theme_chooser, GTK_TYPE_VBOX)
75+
76+#define KEY_SOUNDS_SCHEMA "org.gnome.desktop.sound"
77+#define EVENT_SOUNDS_KEY "event-sounds"
78+#define INPUT_SOUNDS_KEY "input-feedback-sounds"
79+#define SOUND_THEME_KEY "theme-name"
80+
81+#define WM_SCHEMA "org.gnome.desktop.wm.preferences"
82+#define AUDIO_BELL_KEY "audible-bell"
83+
84+#define DEFAULT_ALERT_ID "__default"
85+#define CUSTOM_THEME_NAME "__custom"
86+#define NO_SOUNDS_THEME_NAME "__no_sounds"
87+#define DEFAULT_THEME "ubuntu"
88+
89+enum {
90+ THEME_DISPLAY_COL,
91+ THEME_IDENTIFIER_COL,
92+ THEME_PARENT_ID_COL,
93+ THEME_NUM_COLS
94+};
95+
96+enum {
97+ ALERT_DISPLAY_COL,
98+ ALERT_IDENTIFIER_COL,
99+ ALERT_SOUND_TYPE_COL,
100+ ALERT_NUM_COLS
101+};
102+
103+enum {
104+ SOUND_TYPE_UNSET,
105+ SOUND_TYPE_OFF,
106+ SOUND_TYPE_DEFAULT_FROM_THEME,
107+ SOUND_TYPE_BUILTIN,
108+ SOUND_TYPE_CUSTOM
109+};
110+
111+#define GVC_SOUND_SOUND (xmlChar *) "sound"
112+#define GVC_SOUND_NAME (xmlChar *) "name"
113+#define GVC_SOUND_FILENAME (xmlChar *) "filename"
114+
115+/* Adapted from yelp-toc-pager.c */
116+static xmlChar *
117+xml_get_and_trim_names (xmlNodePtr node)
118+{
119+ xmlNodePtr cur;
120+ xmlChar *keep_lang = NULL;
121+ xmlChar *value;
122+ int j, keep_pri = INT_MAX;
123+
124+ const gchar * const * langs = g_get_language_names ();
125+
126+ value = NULL;
127+
128+ for (cur = node->children; cur; cur = cur->next) {
129+ if (! xmlStrcmp (cur->name, GVC_SOUND_NAME)) {
130+ xmlChar *cur_lang = NULL;
131+ int cur_pri = INT_MAX;
132+
133+ cur_lang = xmlNodeGetLang (cur);
134+
135+ if (cur_lang) {
136+ for (j = 0; langs[j]; j++) {
137+ if (g_str_equal (cur_lang, langs[j])) {
138+ cur_pri = j;
139+ break;
140+ }
141+ }
142+ } else {
143+ cur_pri = INT_MAX - 1;
144+ }
145+
146+ if (cur_pri <= keep_pri) {
147+ if (keep_lang)
148+ xmlFree (keep_lang);
149+ if (value)
150+ xmlFree (value);
151+
152+ value = xmlNodeGetContent (cur);
153+
154+ keep_lang = cur_lang;
155+ keep_pri = cur_pri;
156+ } else {
157+ if (cur_lang)
158+ xmlFree (cur_lang);
159+ }
160+ }
161+ }
162+
163+ /* Delete all GVC_SOUND_NAME nodes */
164+ cur = node->children;
165+ while (cur) {
166+ xmlNodePtr this = cur;
167+ cur = cur->next;
168+ if (! xmlStrcmp (this->name, GVC_SOUND_NAME)) {
169+ xmlUnlinkNode (this);
170+ xmlFreeNode (this);
171+ }
172+ }
173+
174+ return value;
175+}
176+
177+static void
178+populate_model_from_node (GvcSoundThemeChooser *chooser,
179+ GtkTreeModel *model,
180+ xmlNodePtr node)
181+{
182+ xmlNodePtr child;
183+ xmlChar *filename;
184+ xmlChar *name;
185+
186+ filename = NULL;
187+ name = xml_get_and_trim_names (node);
188+ for (child = node->children; child; child = child->next) {
189+ if (xmlNodeIsText (child)) {
190+ continue;
191+ }
192+
193+ if (xmlStrcmp (child->name, GVC_SOUND_FILENAME) == 0) {
194+ filename = xmlNodeGetContent (child);
195+ } else if (xmlStrcmp (child->name, GVC_SOUND_NAME) == 0) {
196+ /* EH? should have been trimmed */
197+ }
198+ }
199+
200+ if (filename != NULL && name != NULL) {
201+ gtk_list_store_insert_with_values (GTK_LIST_STORE (model),
202+ NULL,
203+ G_MAXINT,
204+ ALERT_IDENTIFIER_COL, filename,
205+ ALERT_DISPLAY_COL, name,
206+ ALERT_SOUND_TYPE_COL, _("Built-in"),
207+ -1);
208+ }
209+
210+ xmlFree (filename);
211+ xmlFree (name);
212+}
213+
214+static void
215+populate_model_from_file (GvcSoundThemeChooser *chooser,
216+ GtkTreeModel *model,
217+ const char *filename)
218+{
219+ xmlDocPtr doc;
220+ xmlNodePtr root;
221+ xmlNodePtr child;
222+ gboolean exists;
223+
224+ exists = g_file_test (filename, G_FILE_TEST_EXISTS);
225+ if (! exists) {
226+ return;
227+ }
228+
229+ doc = xmlParseFile (filename);
230+ if (doc == NULL) {
231+ return;
232+ }
233+
234+ root = xmlDocGetRootElement (doc);
235+
236+ for (child = root->children; child; child = child->next) {
237+ if (xmlNodeIsText (child)) {
238+ continue;
239+ }
240+ if (xmlStrcmp (child->name, GVC_SOUND_SOUND) != 0) {
241+ continue;
242+ }
243+
244+ populate_model_from_node (chooser, model, child);
245+ }
246+
247+ xmlFreeDoc (doc);
248+}
249+
250+static void
251+populate_model_from_dir (GvcSoundThemeChooser *chooser,
252+ GtkTreeModel *model,
253+ const char *dirname)
254+{
255+ GDir *d;
256+ const char *name;
257+
258+ d = g_dir_open (dirname, 0, NULL);
259+ if (d == NULL) {
260+ return;
261+ }
262+
263+ while ((name = g_dir_read_name (d)) != NULL) {
264+ char *path;
265+
266+ if (! g_str_has_suffix (name, ".xml")) {
267+ continue;
268+ }
269+
270+ path = g_build_filename (dirname, name, NULL);
271+ populate_model_from_file (chooser, model, path);
272+ g_free (path);
273+ }
274+}
275+
276+static gboolean
277+save_alert_sounds (GvcSoundThemeChooser *chooser,
278+ const char *id)
279+{
280+ const char *sounds[3] = { "bell-terminal", "bell-window-system", NULL };
281+ char *path;
282+
283+ if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
284+ delete_old_files (sounds);
285+ delete_disabled_files (sounds);
286+ } else {
287+ delete_old_files (sounds);
288+ delete_disabled_files (sounds);
289+ add_custom_file (sounds, id);
290+ }
291+
292+ /* And poke the directory so the theme gets updated */
293+ path = custom_theme_dir_path (NULL);
294+ if (utime (path, NULL) != 0) {
295+ g_warning ("Failed to update mtime for directory '%s': %s",
296+ path, g_strerror (errno));
297+ }
298+ g_free (path);
299+
300+ return FALSE;
301+}
302+
303+
304+static void
305+update_alert_model (GvcSoundThemeChooser *chooser,
306+ const char *id)
307+{
308+ GtkTreeModel *model;
309+ GtkTreeIter iter;
310+
311+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
312+ gtk_tree_model_get_iter_first (model, &iter);
313+ do {
314+ char *this_id;
315+
316+ gtk_tree_model_get (model, &iter,
317+ ALERT_IDENTIFIER_COL, &this_id,
318+ -1);
319+
320+ if (strcmp (this_id, id) == 0) {
321+ GtkTreeSelection *selection;
322+
323+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (chooser->priv->treeview));
324+ gtk_tree_selection_select_iter (selection, &iter);
325+ }
326+
327+ g_free (this_id);
328+ } while (gtk_tree_model_iter_next (model, &iter));
329+}
330+
331+static void
332+save_theme_name (GvcSoundThemeChooser *chooser,
333+ const char *theme_name)
334+{
335+ /* If the name is empty, use "freedesktop" */
336+ if (theme_name == NULL || *theme_name == '\0') {
337+ theme_name = DEFAULT_THEME;
338+ }
339+
340+ /* special case for no sounds */
341+ if (strcmp (theme_name, NO_SOUNDS_THEME_NAME) == 0) {
342+ g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, FALSE);
343+ return;
344+ } else {
345+ g_settings_set_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY, TRUE);
346+ }
347+
348+ g_settings_set_string (chooser->priv->sound_settings, SOUND_THEME_KEY, theme_name);
349+}
350+
351+static gboolean
352+load_theme_file (const char *path,
353+ char **parent)
354+{
355+ GKeyFile *file;
356+ gboolean hidden;
357+
358+ file = g_key_file_new ();
359+ if (g_key_file_load_from_file (file, path, G_KEY_FILE_KEEP_TRANSLATIONS, NULL) == FALSE) {
360+ g_key_file_free (file);
361+ return FALSE;
362+ }
363+ /* Don't add hidden themes to the list */
364+ hidden = g_key_file_get_boolean (file, "Sound Theme", "Hidden", NULL);
365+ if (!hidden) {
366+ /* Save the parent theme, if there's one */
367+ if (parent != NULL) {
368+ *parent = g_key_file_get_string (file,
369+ "Sound Theme",
370+ "Inherits",
371+ NULL);
372+ }
373+ }
374+
375+ g_key_file_free (file);
376+
377+ return TRUE;
378+}
379+
380+static gboolean
381+load_theme_name (const char *name,
382+ char **parent)
383+{
384+ const char * const *data_dirs;
385+ const char *data_dir;
386+ char *path;
387+ guint i;
388+ gboolean res;
389+
390+ data_dir = g_get_user_data_dir ();
391+ path = g_build_filename (data_dir, "sounds", name, "index.theme", NULL);
392+ res = load_theme_file (path, parent);
393+ g_free (path);
394+ if (res)
395+ return TRUE;
396+
397+ data_dirs = g_get_system_data_dirs ();
398+ for (i = 0; data_dirs[i] != NULL; i++) {
399+ path = g_build_filename (data_dirs[i], "sounds", name, "index.theme", NULL);
400+ res = load_theme_file (path, parent);
401+ g_free (path);
402+ if (res)
403+ return TRUE;
404+ }
405+
406+ return FALSE;
407+}
408+
409+static void
410+update_alert (GvcSoundThemeChooser *chooser,
411+ const char *alert_id)
412+{
413+ gboolean is_custom;
414+ gboolean is_default;
415+ gboolean add_custom;
416+ gboolean remove_custom;
417+
418+ is_custom = strcmp (chooser->priv->current_theme, CUSTOM_THEME_NAME) == 0;
419+ is_default = strcmp (alert_id, DEFAULT_ALERT_ID) == 0;
420+
421+ /* So a few possibilities:
422+ * 1. Named theme, default alert selected: noop
423+ * 2. Named theme, alternate alert selected: create new custom with sound
424+ * 3. Custom theme, default alert selected: remove sound and possibly custom
425+ * 4. Custom theme, alternate alert selected: update custom sound
426+ */
427+ add_custom = FALSE;
428+ remove_custom = FALSE;
429+ if (! is_custom && is_default) {
430+ /* remove custom just in case */
431+ remove_custom = TRUE;
432+ } else if (! is_custom && ! is_default) {
433+ if (chooser->priv->current_parent)
434+ create_custom_theme (chooser->priv->current_parent);
435+ else
436+ create_custom_theme (DEFAULT_THEME);
437+ save_alert_sounds (chooser, alert_id);
438+ add_custom = TRUE;
439+ } else if (is_custom && is_default) {
440+ save_alert_sounds (chooser, alert_id);
441+ /* after removing files check if it is empty */
442+ if (custom_theme_dir_is_empty ()) {
443+ remove_custom = TRUE;
444+ }
445+ } else if (is_custom && ! is_default) {
446+ save_alert_sounds (chooser, alert_id);
447+ }
448+
449+ if (add_custom) {
450+ save_theme_name (chooser, CUSTOM_THEME_NAME);
451+ } else if (remove_custom) {
452+ delete_custom_theme_dir ();
453+ if (is_custom) {
454+ save_theme_name (chooser, chooser->priv->current_parent);
455+ }
456+ }
457+
458+ update_alert_model (chooser, alert_id);
459+}
460+
461+static void
462+play_preview_for_id (GvcSoundThemeChooser *chooser,
463+ const char *id)
464+{
465+ g_return_if_fail (id != NULL);
466+
467+ /* special case: for the default item on custom themes
468+ * play the alert for the parent theme */
469+ if (strcmp (id, DEFAULT_ALERT_ID) == 0) {
470+ if (chooser->priv->current_parent != NULL) {
471+ ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
472+ CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
473+ CA_PROP_EVENT_ID, "bell-window-system",
474+ CA_PROP_CANBERRA_XDG_THEME_NAME, chooser->priv->current_parent,
475+ CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
476+ CA_PROP_CANBERRA_CACHE_CONTROL, "never",
477+ CA_PROP_APPLICATION_ID, "org.gnome.VolumeControl",
478+#ifdef CA_PROP_CANBERRA_ENABLE
479+ CA_PROP_CANBERRA_ENABLE, "1",
480+#endif
481+ NULL);
482+ } else {
483+ ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
484+ CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
485+ CA_PROP_EVENT_ID, "bell-window-system",
486+ CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
487+ CA_PROP_CANBERRA_CACHE_CONTROL, "never",
488+ CA_PROP_APPLICATION_ID, "org.gnome.VolumeControl",
489+#ifdef CA_PROP_CANBERRA_ENABLE
490+ CA_PROP_CANBERRA_ENABLE, "1",
491+#endif
492+ NULL);
493+ }
494+ } else {
495+ ca_gtk_play_for_widget (GTK_WIDGET (chooser), 0,
496+ CA_PROP_APPLICATION_NAME, _("Sound Preferences"),
497+ CA_PROP_MEDIA_FILENAME, id,
498+ CA_PROP_EVENT_DESCRIPTION, _("Testing event sound"),
499+ CA_PROP_CANBERRA_CACHE_CONTROL, "never",
500+ CA_PROP_APPLICATION_ID, "org.gnome.VolumeControl",
501+#ifdef CA_PROP_CANBERRA_ENABLE
502+ CA_PROP_CANBERRA_ENABLE, "1",
503+#endif
504+ NULL);
505+
506+ }
507+}
508+
509+static void
510+on_treeview_selection_changed (GtkTreeSelection *selection,
511+ GvcSoundThemeChooser *chooser)
512+{
513+ GtkTreeModel *model;
514+ GtkTreeIter iter;
515+ char *id;
516+
517+ if (chooser->priv->treeview == NULL) {
518+ return;
519+ }
520+
521+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (chooser->priv->treeview));
522+
523+ if (gtk_tree_selection_get_selected (selection, &model, &iter) == FALSE) {
524+ return;
525+ }
526+
527+ id = NULL;
528+ gtk_tree_model_get (model, &iter,
529+ ALERT_IDENTIFIER_COL, &id,
530+ -1);
531+ if (id == NULL) {
532+ return;
533+ }
534+
535+ play_preview_for_id (chooser, id);
536+ update_alert (chooser, id);
537+ g_free (id);
538+}
539+
540+static gboolean
541+on_treeview_button_pressed (GtkTreeView *treeview,
542+ GdkEventButton *event,
543+ GvcSoundThemeChooser *chooser)
544+{
545+ GtkTreeSelection *selection;
546+ GtkTreePath *path;
547+
548+ selection = gtk_tree_view_get_selection (treeview);
549+ if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (treeview),
550+ event->x, event->y, &path, NULL, NULL, NULL) == FALSE) {
551+ return FALSE;
552+ }
553+
554+ if (gtk_tree_selection_path_is_selected (selection, path) == FALSE) {
555+ gtk_tree_path_free (path);
556+ return FALSE;
557+ }
558+ gtk_tree_path_free (path);
559+
560+ on_treeview_selection_changed (selection, chooser);
561+
562+ return FALSE;
563+}
564+
565+static GtkWidget *
566+create_alert_treeview (GvcSoundThemeChooser *chooser)
567+{
568+ GtkListStore *store;
569+ GtkWidget *treeview;
570+ GtkCellRenderer *renderer;
571+ GtkTreeViewColumn *column;
572+ GtkTreeSelection *selection;
573+
574+ treeview = gtk_tree_view_new ();
575+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
576+ g_signal_connect (treeview,
577+ "button-press-event",
578+ G_CALLBACK (on_treeview_button_pressed),
579+ chooser);
580+
581+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
582+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
583+ g_signal_connect (selection,
584+ "changed",
585+ G_CALLBACK (on_treeview_selection_changed),
586+ chooser);
587+
588+ /* Setup the tree model, 3 columns:
589+ * - display name
590+ * - sound id
591+ * - sound type
592+ */
593+ store = gtk_list_store_new (ALERT_NUM_COLS,
594+ G_TYPE_STRING,
595+ G_TYPE_STRING,
596+ G_TYPE_STRING);
597+
598+ gtk_list_store_insert_with_values (store,
599+ NULL,
600+ G_MAXINT,
601+ ALERT_IDENTIFIER_COL, DEFAULT_ALERT_ID,
602+ ALERT_DISPLAY_COL, _("Default"),
603+ ALERT_SOUND_TYPE_COL, _("From theme"),
604+ -1);
605+
606+ populate_model_from_dir (chooser, GTK_TREE_MODEL (store), SOUND_SET_DIR);
607+
608+ gtk_tree_view_set_model (GTK_TREE_VIEW (treeview),
609+ GTK_TREE_MODEL (store));
610+
611+ renderer = gtk_cell_renderer_text_new ();
612+ column = gtk_tree_view_column_new_with_attributes (_("Name"),
613+ renderer,
614+ "text", ALERT_DISPLAY_COL,
615+ NULL);
616+ gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
617+
618+ return treeview;
619+}
620+
621+static int
622+get_file_type (const char *sound_name,
623+ char **linked_name)
624+{
625+ char *name, *filename;
626+
627+ *linked_name = NULL;
628+
629+ name = g_strdup_printf ("%s.disabled", sound_name);
630+ filename = custom_theme_dir_path (name);
631+ g_free (name);
632+
633+ if (g_file_test (filename, G_FILE_TEST_IS_REGULAR) != FALSE) {
634+ g_free (filename);
635+ return SOUND_TYPE_OFF;
636+ }
637+ g_free (filename);
638+
639+ /* We only check for .ogg files because those are the
640+ * only ones we create */
641+ name = g_strdup_printf ("%s.ogg", sound_name);
642+ filename = custom_theme_dir_path (name);
643+ g_free (name);
644+
645+ if (g_file_test (filename, G_FILE_TEST_IS_SYMLINK) != FALSE) {
646+ *linked_name = g_file_read_link (filename, NULL);
647+ g_free (filename);
648+ return SOUND_TYPE_CUSTOM;
649+ }
650+ g_free (filename);
651+
652+ return SOUND_TYPE_BUILTIN;
653+}
654+
655+static void
656+update_alerts_from_theme_name (GvcSoundThemeChooser *chooser,
657+ const char *name)
658+{
659+ if (strcmp (name, CUSTOM_THEME_NAME) != 0) {
660+ /* reset alert to default */
661+ update_alert (chooser, DEFAULT_ALERT_ID);
662+ } else {
663+ int sound_type;
664+ char *linkname;
665+
666+ linkname = NULL;
667+ sound_type = get_file_type ("bell-terminal", &linkname);
668+ g_debug ("Found link: %s", linkname);
669+ if (sound_type == SOUND_TYPE_CUSTOM) {
670+ update_alert (chooser, linkname);
671+ }
672+ }
673+}
674+
675+static void
676+update_theme (GvcSoundThemeChooser *chooser)
677+{
678+ gboolean events_enabled;
679+ char *last_theme;
680+
681+ events_enabled = g_settings_get_boolean (chooser->priv->sound_settings, EVENT_SOUNDS_KEY);
682+
683+ last_theme = chooser->priv->current_theme;
684+ if (events_enabled) {
685+ chooser->priv->current_theme = g_settings_get_string (chooser->priv->sound_settings, SOUND_THEME_KEY);
686+ } else {
687+ chooser->priv->current_theme = g_strdup (NO_SOUNDS_THEME_NAME);
688+ }
689+
690+ if (g_strcmp0 (last_theme, chooser->priv->current_theme) != 0) {
691+ g_free (chooser->priv->current_parent);
692+ if (load_theme_name (chooser->priv->current_theme,
693+ &chooser->priv->current_parent) == FALSE) {
694+ g_free (chooser->priv->current_theme);
695+ chooser->priv->current_theme = g_strdup (DEFAULT_THEME);
696+ load_theme_name (DEFAULT_THEME,
697+ &chooser->priv->current_parent);
698+ }
699+ }
700+ g_free (last_theme);
701+
702+ gtk_widget_set_sensitive (chooser->priv->selection_box, events_enabled);
703+
704+ update_alerts_from_theme_name (chooser, chooser->priv->current_theme);
705+}
706+
707+static GObject *
708+gvc_sound_theme_chooser_constructor (GType type,
709+ guint n_construct_properties,
710+ GObjectConstructParam *construct_params)
711+{
712+ GObject *object;
713+ GvcSoundThemeChooser *self;
714+
715+ object = G_OBJECT_CLASS (gvc_sound_theme_chooser_parent_class)->constructor (type, n_construct_properties, construct_params);
716+
717+ self = GVC_SOUND_THEME_CHOOSER (object);
718+
719+ update_theme (self);
720+
721+ return object;
722+}
723+
724+static void
725+gvc_sound_theme_chooser_class_init (GvcSoundThemeChooserClass *klass)
726+{
727+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
728+
729+ object_class->constructor = gvc_sound_theme_chooser_constructor;
730+ object_class->finalize = gvc_sound_theme_chooser_finalize;
731+
732+ g_type_class_add_private (klass, sizeof (GvcSoundThemeChooserPrivate));
733+}
734+
735+static void
736+on_sound_settings_changed (GSettings *settings,
737+ const char *key,
738+ GvcSoundThemeChooser *chooser)
739+{
740+ if (strcmp (key, EVENT_SOUNDS_KEY) == 0) {
741+ update_theme (chooser);
742+ } else if (strcmp (key, SOUND_THEME_KEY) == 0) {
743+ update_theme (chooser);
744+ } else if (strcmp (key, INPUT_SOUNDS_KEY) == 0) {
745+ update_theme (chooser);
746+ }
747+}
748+
749+static void
750+on_audible_bell_changed (GSettings *settings,
751+ const char *key,
752+ GvcSoundThemeChooser *chooser)
753+{
754+ update_theme (chooser);
755+}
756+
757+static void
758+setup_list_size_constraint (GtkWidget *widget,
759+ GtkWidget *to_size)
760+{
761+ GtkRequisition req;
762+ int max_height;
763+
764+ /* constrain height to be the tree height up to a max */
765+ max_height = (gdk_screen_get_height (gtk_widget_get_screen (widget))) / 4;
766+
767+ gtk_widget_get_preferred_size (to_size, NULL, &req);
768+
769+ gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (widget),
770+ MIN (req.height, max_height));
771+}
772+
773+static void
774+gvc_sound_theme_chooser_init (GvcSoundThemeChooser *chooser)
775+{
776+ GtkWidget *box;
777+ GtkWidget *label;
778+ GtkWidget *scrolled_window;
779+ GtkWidget *alignment;
780+ char *str;
781+
782+ chooser->priv = GVC_SOUND_THEME_CHOOSER_GET_PRIVATE (chooser);
783+
784+ chooser->priv->settings = g_settings_new (WM_SCHEMA);
785+ chooser->priv->sound_settings = g_settings_new (KEY_SOUNDS_SCHEMA);
786+
787+ str = g_strdup_printf ("<b>%s</b>", _("C_hoose an alert sound:"));
788+ chooser->priv->selection_box = box = gtk_frame_new (str);
789+ g_free (str);
790+ label = gtk_frame_get_label_widget (GTK_FRAME (box));
791+ gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
792+ gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
793+ gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
794+
795+ alignment = gtk_alignment_new (0, 0, 1, 1);
796+ gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 6, 0, 0, 0);
797+ gtk_container_add (GTK_CONTAINER (alignment), box);
798+ gtk_box_pack_start (GTK_BOX (chooser), alignment, TRUE, TRUE, 6);
799+
800+ alignment = gtk_alignment_new (0, 0, 1, 1);
801+ gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 6, 0, 0, 0);
802+ gtk_container_add (GTK_CONTAINER (box), alignment);
803+
804+ chooser->priv->treeview = create_alert_treeview (chooser);
805+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser->priv->treeview);
806+
807+ scrolled_window = gtk_scrolled_window_new (NULL, NULL);
808+ setup_list_size_constraint (scrolled_window, chooser->priv->treeview);
809+
810+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
811+ GTK_POLICY_NEVER,
812+ GTK_POLICY_AUTOMATIC);
813+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
814+ GTK_SHADOW_IN);
815+ gtk_container_add (GTK_CONTAINER (scrolled_window), chooser->priv->treeview);
816+ gtk_container_add (GTK_CONTAINER (alignment), scrolled_window);
817+
818+ g_signal_connect (G_OBJECT (chooser->priv->sound_settings), "changed",
819+ G_CALLBACK (on_sound_settings_changed), chooser);
820+ g_signal_connect (chooser->priv->settings, "changed::" AUDIO_BELL_KEY,
821+ G_CALLBACK (on_audible_bell_changed), chooser);
822+}
823+
824+static void
825+gvc_sound_theme_chooser_finalize (GObject *object)
826+{
827+ GvcSoundThemeChooser *sound_theme_chooser;
828+
829+ g_return_if_fail (object != NULL);
830+ g_return_if_fail (GVC_IS_SOUND_THEME_CHOOSER (object));
831+
832+ sound_theme_chooser = GVC_SOUND_THEME_CHOOSER (object);
833+
834+ if (sound_theme_chooser->priv != NULL) {
835+ g_object_unref (sound_theme_chooser->priv->settings);
836+ g_object_unref (sound_theme_chooser->priv->sound_settings);
837+ }
838+
839+ G_OBJECT_CLASS (gvc_sound_theme_chooser_parent_class)->finalize (object);
840+}
841+
842+GtkWidget *
843+gvc_sound_theme_chooser_new (void)
844+{
845+ GObject *chooser;
846+ chooser = g_object_new (GVC_TYPE_SOUND_THEME_CHOOSER,
847+ "spacing", 6,
848+ NULL);
849+ return GTK_WIDGET (chooser);
850+}
851
852=== modified file 'debian/changelog'
853--- debian/changelog 2014-04-02 10:52:39 +0000
854+++ debian/changelog 2014-07-07 05:56:11 +0000
855@@ -1,3 +1,9 @@
856+gnome-control-center (1:3.4.2-0ubuntu0.13.3) precise; urgency=medium
857+
858+ * sound: fix potential memory corruption (LP: #1236612)
859+
860+ -- Madper Xie <madper.xie@canonical.com> Mon, 07 Jul 2014 13:41:57 +0800
861+
862 gnome-control-center (1:3.4.2-0ubuntu0.13.2) precise; urgency=medium
863
864 * Disable the input/output bar when no input/output devices (LP: #1291862)
865
866=== modified file 'debian/patches/series'
867--- debian/patches/series 2014-04-02 10:52:39 +0000
868+++ debian/patches/series 2014-07-07 05:56:11 +0000
869@@ -44,3 +44,4 @@
870 use_rfkill_airplane_mode.patch
871 more-power-suspend-options.patch
872 fix-input-device-bar-status.patch
873+sound-fix-potential-memory-corruption.patch
874
875=== added file 'debian/patches/sound-fix-potential-memory-corruption.patch'
876--- debian/patches/sound-fix-potential-memory-corruption.patch 1970-01-01 00:00:00 +0000
877+++ debian/patches/sound-fix-potential-memory-corruption.patch 2014-07-07 05:56:11 +0000
878@@ -0,0 +1,12 @@
879+Index: gnome-control-center/panels/sound/gvc-sound-theme-chooser.c
880+===================================================================
881+--- gnome-control-center.orig/panels/sound/gvc-sound-theme-chooser.c 2014-07-07 12:40:00.839504000 +0800
882++++ gnome-control-center/panels/sound/gvc-sound-theme-chooser.c 2014-07-07 12:48:15.822986459 +0800
883+@@ -672,6 +672,7 @@
884+
885+ if (g_strcmp0 (last_theme, chooser->priv->current_theme) != 0) {
886+ g_free (chooser->priv->current_parent);
887++ chooser->priv->current_parent = NULL;
888+ if (load_theme_name (chooser->priv->current_theme,
889+ &chooser->priv->current_parent) == FALSE) {
890+ g_free (chooser->priv->current_theme);
891
892=== modified file 'panels/sound/gvc-sound-theme-chooser.c'
893--- panels/sound/gvc-sound-theme-chooser.c 2012-02-15 23:16:31 +0000
894+++ panels/sound/gvc-sound-theme-chooser.c 2014-07-07 05:56:11 +0000
895@@ -672,6 +672,7 @@
896
897 if (g_strcmp0 (last_theme, chooser->priv->current_theme) != 0) {
898 g_free (chooser->priv->current_parent);
899+ chooser->priv->current_parent = NULL;
900 if (load_theme_name (chooser->priv->current_theme,
901 &chooser->priv->current_parent) == FALSE) {
902 g_free (chooser->priv->current_theme);

Subscribers

People subscribed via source and target branches

to all changes: