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