File: | sound-theme-spec.c |
Warning: | line 595, column 26 Out of bound memory access (access exceeds upper limit of memory block) |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /*-*- Mode: C; c-basic-offset: 8 -*-*/ | |||
2 | ||||
3 | /*** | |||
4 | This file is part of libkanberra. | |||
5 | ||||
6 | Copyright 2008 Lennart Poettering | |||
7 | ||||
8 | libkanberra is free software; you can redistribute it and/or modify | |||
9 | it under the terms of the GNU Lesser General Public License as | |||
10 | published by the Free Software Foundation, either version 2.1 of the | |||
11 | License, or (at your option) any later version. | |||
12 | ||||
13 | libkanberra is distributed in the hope that it will be useful, but | |||
14 | WITHOUT ANY WARRANTY; without even the implied warranty of | |||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
16 | Lesser General Public License for more details. | |||
17 | ||||
18 | You should have received a copy of the GNU Lesser General Public | |||
19 | License along with libkanberra. If not, see | |||
20 | <http://www.gnu.org/licenses/>. | |||
21 | ***/ | |||
22 | ||||
23 | #ifdef HAVE_CONFIG_H1 | |||
24 | #include <config.h> | |||
25 | #endif | |||
26 | ||||
27 | #include <errno(*__errno_location ()).h> | |||
28 | #include <unistd.h> | |||
29 | ||||
30 | #include <locale.h> | |||
31 | ||||
32 | #include "sound-theme-spec.h" | |||
33 | #include "malloc.h" | |||
34 | #include "llist.h" | |||
35 | #include "cache.h" | |||
36 | ||||
37 | #define DEFAULT_THEME"freedesktop" "freedesktop" | |||
38 | #define FALLBACK_THEME"freedesktop" "freedesktop" | |||
39 | #define DEFAULT_OUTPUT_PROFILE"stereo" "stereo" | |||
40 | #define N_THEME_DIR_MAX8 8 | |||
41 | ||||
42 | typedef struct ka_data_dir ka_data_dir; | |||
43 | ||||
44 | struct ka_data_dir { | |||
45 | KA_LLIST_FIELDS(ka_data_dir)ka_data_dir *next, *prev; | |||
46 | ||||
47 | char *theme_name; | |||
48 | char *dir_name; | |||
49 | char *output_profile; | |||
50 | }; | |||
51 | ||||
52 | struct ka_theme_data { | |||
53 | char *name; | |||
54 | ||||
55 | KA_LLIST_HEAD(ka_data_dir, data_dirs)ka_data_dir *data_dirs; | |||
56 | ka_data_dir *last_dir; | |||
57 | ||||
58 | unsigned n_theme_dir; | |||
59 | ka_bool_t loaded_fallback_theme; | |||
60 | }; | |||
61 | ||||
62 | int ka_get_data_home(char **e) { | |||
63 | const char *env, *subdir; | |||
64 | char *r; | |||
65 | ka_return_val_if_fail(e, KA_ERROR_INVALID)do { if ((__builtin_expect((!(e)),0))) { if (ka_debug()) fprintf (stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "e" , "sound-theme-spec.c", 65, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID ); } } while((0)); | |||
66 | ||||
67 | if ((env = getenv("XDG_DATA_HOME")) && *env == '/') | |||
68 | subdir = ""; | |||
69 | else if ((env = getenv("HOME")) && *env == '/') | |||
70 | subdir = "/.local/share"; | |||
71 | else { | |||
72 | *e = NULL((void*)0); | |||
73 | return KA_SUCCESS; | |||
74 | } | |||
75 | ||||
76 | if (!(r = ka_new(char, strlen(env) + strlen(subdir) + 1)((char*) malloc(sizeof(char)*(strlen(env) + strlen(subdir) + 1 ))))) | |||
77 | return KA_ERROR_OOM; | |||
78 | ||||
79 | sprintf(r, "%s%s", env, subdir); | |||
80 | *e = r; | |||
81 | ||||
82 | return KA_SUCCESS; | |||
83 | } | |||
84 | ||||
85 | static ka_bool_t data_dir_matches(ka_data_dir *d, const char*output_profile) { | |||
86 | ka_assert(d)do { if ((__builtin_expect((!(d)),0))) { fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s(). Aborting.\n" , "d" , "sound-theme-spec.c", 86, __PRETTY_FUNCTION__); abort (); } } while ((0)); | |||
87 | ka_assert(output_profile)do { if ((__builtin_expect((!(output_profile)),0))) { fprintf (stderr, "Assertion '%s' failed at %s:%u, function %s(). Aborting.\n" , "output_profile" , "sound-theme-spec.c", 87, __PRETTY_FUNCTION__ ); abort(); } } while ((0)); | |||
88 | ||||
89 | /* We might want to add more elaborate matching here eventually */ | |||
90 | ||||
91 | if (!d->output_profile) | |||
92 | return TRUE(!(0)); | |||
93 | ||||
94 | return ka_streq(d->output_profile, output_profile)(strcmp((d->output_profile),(output_profile)) == 0); | |||
95 | } | |||
96 | ||||
97 | static ka_data_dir* find_data_dir(ka_theme_data *t, const char *theme_name, const char *dir_name) { | |||
98 | ka_data_dir *d; | |||
99 | ||||
100 | ka_assert(t)do { if ((__builtin_expect((!(t)),0))) { fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s(). Aborting.\n" , "t" , "sound-theme-spec.c", 100, __PRETTY_FUNCTION__); abort (); } } while ((0)); | |||
101 | ka_assert(theme_name)do { if ((__builtin_expect((!(theme_name)),0))) { fprintf(stderr , "Assertion '%s' failed at %s:%u, function %s(). Aborting.\n" , "theme_name" , "sound-theme-spec.c", 101, __PRETTY_FUNCTION__ ); abort(); } } while ((0)); | |||
102 | ka_assert(dir_name)do { if ((__builtin_expect((!(dir_name)),0))) { fprintf(stderr , "Assertion '%s' failed at %s:%u, function %s(). Aborting.\n" , "dir_name" , "sound-theme-spec.c", 102, __PRETTY_FUNCTION__ ); abort(); } } while ((0)); | |||
103 | ||||
104 | for (d = t->data_dirs; d; d = d->next) | |||
105 | if (ka_streq(d->theme_name, theme_name)(strcmp((d->theme_name),(theme_name)) == 0) && | |||
106 | ka_streq(d->dir_name, dir_name)(strcmp((d->dir_name),(dir_name)) == 0)) | |||
107 | return d; | |||
108 | ||||
109 | return NULL((void*)0); | |||
110 | } | |||
111 | ||||
112 | static int add_data_dir(ka_theme_data *t, const char *theme_name, const char *dir_name) { | |||
113 | ka_data_dir *d; | |||
114 | ||||
115 | ka_return_val_if_fail(t, KA_ERROR_INVALID)do { if ((__builtin_expect((!(t)),0))) { if (ka_debug()) fprintf (stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "t" , "sound-theme-spec.c", 115, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID ); } } while((0)); | |||
116 | ka_return_val_if_fail(theme_name, KA_ERROR_INVALID)do { if ((__builtin_expect((!(theme_name)),0))) { if (ka_debug ()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n" , "theme_name" , "sound-theme-spec.c", 116, __PRETTY_FUNCTION__ ); return (KA_ERROR_INVALID); } } while((0)); | |||
117 | ka_return_val_if_fail(dir_name, KA_ERROR_INVALID)do { if ((__builtin_expect((!(dir_name)),0))) { if (ka_debug( )) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n" , "dir_name" , "sound-theme-spec.c", 117, __PRETTY_FUNCTION__ ); return (KA_ERROR_INVALID); } } while((0)); | |||
118 | ||||
119 | if (find_data_dir(t, theme_name, dir_name)) | |||
120 | return KA_SUCCESS; | |||
121 | ||||
122 | if (!(d = ka_new0(ka_data_dir, 1)((ka_data_dir*) calloc(1, (sizeof(ka_data_dir)*(1)))))) | |||
123 | return KA_ERROR_OOM; | |||
124 | ||||
125 | if (!(d->theme_name = ka_strdupstrdup(theme_name))) { | |||
126 | ka_freefree(d); | |||
127 | return KA_ERROR_OOM; | |||
128 | } | |||
129 | ||||
130 | if (!(d->dir_name = ka_strdupstrdup(dir_name))) { | |||
131 | ka_freefree(d->theme_name); | |||
132 | ka_freefree(d); | |||
133 | return KA_ERROR_OOM; | |||
134 | } | |||
135 | ||||
136 | KA_LLIST_INSERT_AFTER(ka_data_dir, t->data_dirs, t->last_dir, d)do { ka_data_dir **_head = &(t->data_dirs), *_a = (t-> last_dir), *_b = (d); do { if ((__builtin_expect((!(_b)),0))) { fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s(). Aborting.\n" , "_b" , "sound-theme-spec.c", 136, __PRETTY_FUNCTION__); abort (); } } while ((0)); if (!_a) { if ((_b->next = *_head)) _b ->next->prev = _b; _b->prev = ((void*)0); *_head = _b ; } else { if ((_b->next = _a->next)) _b->next->prev = _b; _b->prev = _a; _a->next = _b; } } while (0); | |||
137 | t->last_dir = d; | |||
138 | ||||
139 | return KA_SUCCESS; | |||
140 | } | |||
141 | ||||
142 | static int load_theme_dir(ka_theme_data *t, const char *name); | |||
143 | ||||
144 | static int load_theme_path(ka_theme_data *t, const char *prefix, const char *name) { | |||
145 | char *fn, *inherits = NULL((void*)0); | |||
146 | FILE *f; | |||
147 | ka_bool_t in_sound_theme_section = FALSE(0); | |||
148 | ka_data_dir *current_data_dir = NULL((void*)0); | |||
149 | int ret; | |||
150 | ||||
151 | ka_return_val_if_fail(t, KA_ERROR_INVALID)do { if ((__builtin_expect((!(t)),0))) { if (ka_debug()) fprintf (stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "t" , "sound-theme-spec.c", 151, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID ); } } while((0)); | |||
152 | ka_return_val_if_fail(prefix, KA_ERROR_INVALID)do { if ((__builtin_expect((!(prefix)),0))) { if (ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n" , "prefix" , "sound-theme-spec.c", 152, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID); } } while((0)); | |||
153 | ka_return_val_if_fail(name, KA_ERROR_INVALID)do { if ((__builtin_expect((!(name)),0))) { if (ka_debug()) fprintf (stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "name" , "sound-theme-spec.c", 153, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID ); } } while((0)); | |||
154 | ||||
155 | if (!(fn = ka_new(char, strlen(prefix) + sizeof("/sounds/")-1 + strlen(name) + sizeof("/index.theme"))((char*) malloc(sizeof(char)*(strlen(prefix) + sizeof("/sounds/" )-1 + strlen(name) + sizeof("/index.theme")))))) | |||
156 | return KA_ERROR_OOM; | |||
157 | ||||
158 | sprintf(fn, "%s/sounds/%s/index.theme", prefix, name); | |||
159 | f = fopen(fn, "r"); | |||
160 | ka_freefree(fn); | |||
161 | ||||
162 | if (!f) { | |||
163 | if (errno(*__errno_location ()) == ENOENT2) | |||
164 | return KA_ERROR_NOTFOUND; | |||
165 | ||||
166 | return KA_ERROR_SYSTEM; | |||
167 | } | |||
168 | ||||
169 | for (;;) { | |||
170 | char ln[1024]; | |||
171 | ||||
172 | if (!(fgets(ln, sizeof(ln), f))) { | |||
173 | ||||
174 | if (feof(f)) | |||
175 | break; | |||
176 | ||||
177 | ka_assert(ferror(f))do { if ((__builtin_expect((!(ferror(f))),0))) { fprintf(stderr , "Assertion '%s' failed at %s:%u, function %s(). Aborting.\n" , "ferror(f)" , "sound-theme-spec.c", 177, __PRETTY_FUNCTION__ ); abort(); } } while ((0)); | |||
178 | ret = KA_ERROR_SYSTEM; | |||
179 | goto fail; | |||
180 | } | |||
181 | ||||
182 | ln[strcspn(ln, "\n\r#")] = 0; | |||
183 | ||||
184 | if (!ln[0]) | |||
185 | continue; | |||
186 | ||||
187 | if (ka_streq(ln, "[Sound Theme]")(strcmp((ln),("[Sound Theme]")) == 0)) { | |||
188 | in_sound_theme_section = TRUE(!(0)); | |||
189 | current_data_dir = NULL((void*)0); | |||
190 | continue; | |||
191 | } | |||
192 | ||||
193 | if (ln[0] == '[' && ln[strlen(ln)-1] == ']') { | |||
194 | char *d; | |||
195 | ||||
196 | if (!(d = ka_strndupstrndup(ln+1, strlen(ln)-2))) { | |||
197 | ret = KA_ERROR_OOM; | |||
198 | goto fail; | |||
199 | } | |||
200 | ||||
201 | current_data_dir = find_data_dir(t, name, d); | |||
202 | ka_freefree(d); | |||
203 | ||||
204 | in_sound_theme_section = FALSE(0); | |||
205 | continue; | |||
206 | } | |||
207 | ||||
208 | ka_assert(!in_sound_theme_section || !current_data_dir)do { if ((__builtin_expect((!(!in_sound_theme_section || !current_data_dir )),0))) { fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s(). Aborting.\n" , "!in_sound_theme_section || !current_data_dir" , "sound-theme-spec.c" , 208, __PRETTY_FUNCTION__); abort(); } } while ((0)); | |||
209 | ka_assert(!current_data_dir || !in_sound_theme_section)do { if ((__builtin_expect((!(!current_data_dir || !in_sound_theme_section )),0))) { fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s(). Aborting.\n" , "!current_data_dir || !in_sound_theme_section" , "sound-theme-spec.c" , 209, __PRETTY_FUNCTION__); abort(); } } while ((0)); | |||
210 | ||||
211 | if (in_sound_theme_section) { | |||
212 | ||||
213 | if (!strncmp(ln, "Inherits=", 9)) { | |||
214 | ||||
215 | if (inherits) { | |||
216 | ret = KA_ERROR_CORRUPT; | |||
217 | goto fail; | |||
218 | } | |||
219 | ||||
220 | if (!(inherits = ka_strdupstrdup(ln + 9))) { | |||
221 | ret = KA_ERROR_OOM; | |||
222 | goto fail; | |||
223 | } | |||
224 | ||||
225 | continue; | |||
226 | } | |||
227 | ||||
228 | if (!strncmp(ln, "Directories=", 12)) { | |||
229 | char *d; | |||
230 | ||||
231 | d = ln+12; | |||
232 | for (;;) { | |||
233 | size_t k = strcspn(d, ", "); | |||
234 | ||||
235 | if (k > 0) { | |||
236 | char *p; | |||
237 | ||||
238 | if (!(p = ka_strndupstrndup(d, k))) { | |||
239 | ret = KA_ERROR_OOM; | |||
240 | goto fail; | |||
241 | } | |||
242 | ||||
243 | ret = add_data_dir(t, name, p); | |||
244 | ka_freefree(p); | |||
245 | ||||
246 | if (ret != KA_SUCCESS) | |||
247 | goto fail; | |||
248 | } | |||
249 | ||||
250 | if (d[k] == 0) | |||
251 | break; | |||
252 | ||||
253 | d += k+1; | |||
254 | } | |||
255 | ||||
256 | continue; | |||
257 | } | |||
258 | } | |||
259 | ||||
260 | if (current_data_dir) { | |||
261 | ||||
262 | if (!strncmp(ln, "OutputProfile=", 14)) { | |||
263 | ||||
264 | if (!current_data_dir->output_profile) { | |||
265 | ||||
266 | if (!(current_data_dir->output_profile = ka_strdupstrdup(ln+14))) { | |||
267 | ret = KA_ERROR_OOM; | |||
268 | goto fail; | |||
269 | } | |||
270 | ||||
271 | } else if (!ka_streq(current_data_dir->output_profile, ln+14)(strcmp((current_data_dir->output_profile),(ln+14)) == 0)) { | |||
272 | ret = KA_ERROR_CORRUPT; | |||
273 | goto fail; | |||
274 | } | |||
275 | ||||
276 | continue; | |||
277 | } | |||
278 | } | |||
279 | } | |||
280 | ||||
281 | t->n_theme_dir ++; | |||
282 | ||||
283 | if (inherits) { | |||
284 | char *i = inherits; | |||
285 | for (;;) { | |||
286 | size_t k = strcspn(i, ", "); | |||
287 | ||||
288 | if (k > 0) { | |||
289 | char *p; | |||
290 | ||||
291 | if (!(p = ka_strndupstrndup(i, k))) { | |||
292 | ret = KA_ERROR_OOM; | |||
293 | goto fail; | |||
294 | } | |||
295 | ||||
296 | ret = load_theme_dir(t, p); | |||
297 | ka_freefree(p); | |||
298 | ||||
299 | if (ret != KA_SUCCESS) | |||
300 | goto fail; | |||
301 | } | |||
302 | ||||
303 | if (i[k] == 0) | |||
304 | break; | |||
305 | ||||
306 | i += k+1; | |||
307 | } | |||
308 | } | |||
309 | ||||
310 | ret = KA_SUCCESS; | |||
311 | ||||
312 | fail: | |||
313 | ||||
314 | ka_freefree(inherits); | |||
315 | fclose(f); | |||
316 | ||||
317 | return ret; | |||
318 | } | |||
319 | ||||
320 | const char *ka_get_data_dirs(void) { | |||
321 | const char *g; | |||
322 | ||||
323 | if (!(g = getenv("XDG_DATA_DIRS")) || *g == 0) | |||
324 | return "/usr/local/share:/usr/share"; | |||
325 | ||||
326 | return g; | |||
327 | } | |||
328 | ||||
329 | static int load_theme_dir(ka_theme_data *t, const char *name) { | |||
330 | int ret; | |||
331 | char *e; | |||
332 | const char *g; | |||
333 | ||||
334 | ka_return_val_if_fail(t, KA_ERROR_INVALID)do { if ((__builtin_expect((!(t)),0))) { if (ka_debug()) fprintf (stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "t" , "sound-theme-spec.c", 334, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID ); } } while((0)); | |||
335 | ka_return_val_if_fail(name, KA_ERROR_INVALID)do { if ((__builtin_expect((!(name)),0))) { if (ka_debug()) fprintf (stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "name" , "sound-theme-spec.c", 335, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID ); } } while((0)); | |||
336 | ka_return_val_if_fail(t->n_theme_dir < N_THEME_DIR_MAX, KA_ERROR_CORRUPT)do { if ((__builtin_expect((!(t->n_theme_dir < 8)),0))) { if (ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n" , "t->n_theme_dir < N_THEME_DIR_MAX" , "sound-theme-spec.c" , 336, __PRETTY_FUNCTION__); return (KA_ERROR_CORRUPT); } } while ((0)); | |||
337 | ||||
338 | if (ka_streq(name, FALLBACK_THEME)(strcmp((name),("freedesktop")) == 0)) | |||
339 | t->loaded_fallback_theme = TRUE(!(0)); | |||
340 | ||||
341 | if ((ret = ka_get_data_home(&e)) < 0) | |||
342 | return ret; | |||
343 | ||||
344 | if (e) { | |||
345 | ret = load_theme_path(t, e, name); | |||
346 | ka_freefree(e); | |||
347 | ||||
348 | if (ret != KA_ERROR_NOTFOUND) | |||
349 | return ret; | |||
350 | } | |||
351 | ||||
352 | g = ka_get_data_dirs(); | |||
353 | ||||
354 | for (;;) { | |||
355 | size_t k; | |||
356 | ||||
357 | k = strcspn(g, ":"); | |||
358 | ||||
359 | if (g[0] == '/' && k > 0) { | |||
360 | char *p; | |||
361 | ||||
362 | if (!(p = ka_strndupstrndup(g, k))) | |||
363 | return KA_ERROR_OOM; | |||
364 | ||||
365 | ret = load_theme_path(t, p, name); | |||
366 | ka_freefree(p); | |||
367 | ||||
368 | if (ret != KA_ERROR_NOTFOUND) | |||
369 | return ret; | |||
370 | } | |||
371 | ||||
372 | if (g[k] == 0) | |||
373 | break; | |||
374 | ||||
375 | g += k+1; | |||
376 | } | |||
377 | ||||
378 | return KA_ERROR_NOTFOUND; | |||
379 | } | |||
380 | ||||
381 | static int load_theme_data(ka_theme_data **_t, const char *name) { | |||
382 | ka_theme_data *t; | |||
383 | int ret; | |||
384 | ||||
385 | ka_return_val_if_fail(_t, KA_ERROR_INVALID)do { if ((__builtin_expect((!(_t)),0))) { if (ka_debug()) fprintf (stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "_t" , "sound-theme-spec.c", 385, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID ); } } while((0)); | |||
386 | ka_return_val_if_fail(name, KA_ERROR_INVALID)do { if ((__builtin_expect((!(name)),0))) { if (ka_debug()) fprintf (stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "name" , "sound-theme-spec.c", 386, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID ); } } while((0)); | |||
387 | ||||
388 | if (*_t) | |||
389 | if (ka_streq((*_t)->name, name)(strcmp(((*_t)->name),(name)) == 0)) | |||
390 | return KA_SUCCESS; | |||
391 | ||||
392 | if (!(t = ka_new0(ka_theme_data, 1)((ka_theme_data*) calloc(1, (sizeof(ka_theme_data)*(1)))))) | |||
393 | return KA_ERROR_OOM; | |||
394 | ||||
395 | if (!(t->name = ka_strdupstrdup(name))) { | |||
396 | ret = KA_ERROR_OOM; | |||
397 | goto fail; | |||
398 | } | |||
399 | ||||
400 | if ((ret = load_theme_dir(t, name)) < 0) | |||
401 | goto fail; | |||
402 | ||||
403 | /* The fallback theme may intentionally not exist so ignore failure */ | |||
404 | if (!t->loaded_fallback_theme) | |||
405 | load_theme_dir(t, FALLBACK_THEME"freedesktop"); | |||
406 | ||||
407 | if (*_t) | |||
408 | ka_theme_data_free(*_t); | |||
409 | ||||
410 | *_t = t; | |||
411 | ||||
412 | return KA_SUCCESS; | |||
413 | ||||
414 | fail: | |||
415 | ||||
416 | if (t) | |||
417 | ka_theme_data_free(t); | |||
418 | ||||
419 | return ret; | |||
420 | } | |||
421 | ||||
422 | static int find_sound_for_suffix( | |||
423 | ka_sound_file **f, | |||
424 | ka_sound_file_open_callback_t sfopen, | |||
425 | char **sound_path, | |||
426 | const char *theme_name, | |||
427 | const char *name, | |||
428 | const char *path, | |||
429 | const char *suffix, | |||
430 | const char *locale, | |||
431 | const char *subdir) { | |||
432 | ||||
433 | char *fn; | |||
434 | int ret; | |||
435 | ||||
436 | ka_return_val_if_fail(f, KA_ERROR_INVALID)do { if ((__builtin_expect((!(f)),0))) { if (ka_debug()) fprintf (stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "f" , "sound-theme-spec.c", 436, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID ); } } while((0)); | |||
437 | ka_return_val_if_fail(sfopen, KA_ERROR_INVALID)do { if ((__builtin_expect((!(sfopen)),0))) { if (ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n" , "sfopen" , "sound-theme-spec.c", 437, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID); } } while((0)); | |||
438 | ka_return_val_if_fail(name, KA_ERROR_INVALID)do { if ((__builtin_expect((!(name)),0))) { if (ka_debug()) fprintf (stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "name" , "sound-theme-spec.c", 438, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID ); } } while((0)); | |||
439 | ka_return_val_if_fail(path, KA_ERROR_INVALID)do { if ((__builtin_expect((!(path)),0))) { if (ka_debug()) fprintf (stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "path" , "sound-theme-spec.c", 439, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID ); } } while((0)); | |||
440 | ka_return_val_if_fail(path[0] == '/', KA_ERROR_INVALID)do { if ((__builtin_expect((!(path[0] == '/')),0))) { if (ka_debug ()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n" , "path[0] == '/'" , "sound-theme-spec.c", 440, __PRETTY_FUNCTION__ ); return (KA_ERROR_INVALID); } } while((0)); | |||
441 | ||||
442 | if (!(fn = ka_sprintf_malloc("%s%s%s%s%s%s%s/%s%s", | |||
443 | path, | |||
444 | theme_name ? "/" : "", | |||
445 | theme_name ? theme_name : "", | |||
446 | subdir ? "/" : "", | |||
447 | subdir ? subdir : "", | |||
448 | locale ? "/" : "", | |||
449 | locale ? locale : "", | |||
450 | name, suffix))) | |||
451 | return KA_ERROR_OOM; | |||
452 | ||||
453 | if (ka_streq(suffix, ".disabled")(strcmp((suffix),(".disabled")) == 0)) { | |||
454 | ||||
455 | if (access(fn, F_OK0) == 0) | |||
456 | ret = KA_ERROR_DISABLED; | |||
457 | else | |||
458 | ret = errno(*__errno_location ()) == ENOENT2 ? KA_ERROR_NOTFOUND : KA_ERROR_SYSTEM; | |||
459 | ||||
460 | } else | |||
461 | ret = sfopen(f, fn); | |||
462 | ||||
463 | if (ret == KA_SUCCESS && sound_path) | |||
464 | *sound_path = fn; | |||
465 | else | |||
466 | ka_freefree(fn); | |||
467 | ||||
468 | return ret; | |||
469 | } | |||
470 | ||||
471 | static int find_sound_in_locale( | |||
472 | ka_sound_file **f, | |||
473 | ka_sound_file_open_callback_t sfopen, | |||
474 | char **sound_path, | |||
475 | const char *theme_name, | |||
476 | const char *name, | |||
477 | const char *path, | |||
478 | const char *locale, | |||
479 | const char *subdir) { | |||
480 | ||||
481 | int ret; | |||
482 | char *p; | |||
483 | ||||
484 | ka_return_val_if_fail(f, KA_ERROR_INVALID)do { if ((__builtin_expect((!(f)),0))) { if (ka_debug()) fprintf (stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "f" , "sound-theme-spec.c", 484, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID ); } } while((0)); | |||
485 | ka_return_val_if_fail(sfopen, KA_ERROR_INVALID)do { if ((__builtin_expect((!(sfopen)),0))) { if (ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n" , "sfopen" , "sound-theme-spec.c", 485, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID); } } while((0)); | |||
486 | ka_return_val_if_fail(name && *name, KA_ERROR_INVALID)do { if ((__builtin_expect((!(name && *name)),0))) { if (ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n" , "name && *name" , "sound-theme-spec.c", 486, __PRETTY_FUNCTION__ ); return (KA_ERROR_INVALID); } } while((0)); | |||
487 | ka_return_val_if_fail(path, KA_ERROR_INVALID)do { if ((__builtin_expect((!(path)),0))) { if (ka_debug()) fprintf (stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "path" , "sound-theme-spec.c", 487, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID ); } } while((0)); | |||
488 | ka_return_val_if_fail(path[0] == '/', KA_ERROR_INVALID)do { if ((__builtin_expect((!(path[0] == '/')),0))) { if (ka_debug ()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n" , "path[0] == '/'" , "sound-theme-spec.c", 488, __PRETTY_FUNCTION__ ); return (KA_ERROR_INVALID); } } while((0)); | |||
489 | ||||
490 | if (!(p = ka_new(char, strlen(path) + sizeof("/sounds"))((char*) malloc(sizeof(char)*(strlen(path) + sizeof("/sounds" )))))) | |||
491 | return KA_ERROR_OOM; | |||
492 | ||||
493 | sprintf(p, "%s/sounds", path); | |||
494 | ||||
495 | if ((ret = find_sound_for_suffix(f, sfopen, sound_path, theme_name, name, p, ".disabled", locale, subdir)) == KA_ERROR_NOTFOUND) | |||
496 | if ((ret = find_sound_for_suffix(f, sfopen, sound_path,theme_name, name, p, ".oga", locale, subdir)) == KA_ERROR_NOTFOUND) | |||
497 | if ((ret = find_sound_for_suffix(f, sfopen, sound_path,theme_name, name, p, ".ogg", locale, subdir)) == KA_ERROR_NOTFOUND) | |||
498 | ret = find_sound_for_suffix(f, sfopen, sound_path,theme_name, name, p, ".wav", locale, subdir); | |||
499 | ||||
500 | ka_freefree(p); | |||
501 | ||||
502 | return ret; | |||
503 | } | |||
504 | ||||
505 | static int find_sound_for_locale( | |||
506 | ka_sound_file **f, | |||
507 | ka_sound_file_open_callback_t sfopen, | |||
508 | char **sound_path, | |||
509 | const char *theme_name, | |||
510 | const char *name, | |||
511 | const char *path, | |||
512 | const char *locale, | |||
513 | const char *subdir) { | |||
514 | ||||
515 | const char *e; | |||
516 | int ret; | |||
517 | ||||
518 | ka_return_val_if_fail(f, KA_ERROR_INVALID)do { if ((__builtin_expect((!(f)),0))) { if (ka_debug()) fprintf (stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "f" , "sound-theme-spec.c", 518, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID ); } } while((0)); | |||
519 | ka_return_val_if_fail(sfopen, KA_ERROR_INVALID)do { if ((__builtin_expect((!(sfopen)),0))) { if (ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n" , "sfopen" , "sound-theme-spec.c", 519, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID); } } while((0)); | |||
520 | ka_return_val_if_fail(name && *name, KA_ERROR_INVALID)do { if ((__builtin_expect((!(name && *name)),0))) { if (ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n" , "name && *name" , "sound-theme-spec.c", 520, __PRETTY_FUNCTION__ ); return (KA_ERROR_INVALID); } } while((0)); | |||
521 | ka_return_val_if_fail(path, KA_ERROR_INVALID)do { if ((__builtin_expect((!(path)),0))) { if (ka_debug()) fprintf (stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "path" , "sound-theme-spec.c", 521, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID ); } } while((0)); | |||
522 | ka_return_val_if_fail(locale, KA_ERROR_INVALID)do { if ((__builtin_expect((!(locale)),0))) { if (ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n" , "locale" , "sound-theme-spec.c", 522, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID); } } while((0)); | |||
523 | ||||
524 | /* First, try the locale def itself */ | |||
525 | if ((ret = find_sound_in_locale(f, sfopen, sound_path, theme_name, name, path, locale, subdir)) != KA_ERROR_NOTFOUND) | |||
526 | return ret; | |||
527 | ||||
528 | /* Then, try to truncate at the @ */ | |||
529 | if ((e = strchr(locale, '@'))) { | |||
530 | char *t; | |||
531 | ||||
532 | if (!(t = ka_strndupstrndup(locale, (size_t) (e - locale)))) | |||
533 | return KA_ERROR_OOM; | |||
534 | ||||
535 | ret = find_sound_in_locale(f, sfopen, sound_path, theme_name, name, path, t, subdir); | |||
536 | ka_freefree(t); | |||
537 | ||||
538 | if (ret != KA_ERROR_NOTFOUND) | |||
539 | return ret; | |||
540 | } | |||
541 | ||||
542 | /* Followed by truncating at the _ */ | |||
543 | if ((e = strchr(locale, '_'))) { | |||
544 | char *t; | |||
545 | ||||
546 | if (!(t = ka_strndupstrndup(locale, (size_t) (e - locale)))) | |||
547 | return KA_ERROR_OOM; | |||
548 | ||||
549 | ret = find_sound_in_locale(f, sfopen, sound_path, theme_name, name, path, t, subdir); | |||
550 | ka_freefree(t); | |||
551 | ||||
552 | if (ret != KA_ERROR_NOTFOUND) | |||
553 | return ret; | |||
554 | } | |||
555 | ||||
556 | /* Then, try "C" as fallback locale */ | |||
557 | if (strcmp(locale, "C")) | |||
558 | if ((ret = find_sound_in_locale(f, sfopen, sound_path, theme_name, name, path, "C", subdir)) != KA_ERROR_NOTFOUND) | |||
559 | return ret; | |||
560 | ||||
561 | /* Try without locale */ | |||
562 | return find_sound_in_locale(f, sfopen, sound_path, theme_name, name, path, NULL((void*)0), subdir); | |||
563 | } | |||
564 | ||||
565 | static int find_sound_for_name( | |||
566 | ka_sound_file **f, | |||
567 | ka_sound_file_open_callback_t sfopen, | |||
568 | char **sound_path, | |||
569 | const char *theme_name, | |||
570 | const char *name, | |||
571 | const char *path, | |||
572 | const char *locale, | |||
573 | const char *subdir) { | |||
574 | ||||
575 | int ret; | |||
576 | const char *k; | |||
577 | ||||
578 | ka_return_val_if_fail(f, KA_ERROR_INVALID)do { if ((__builtin_expect((!(f)),0))) { if (ka_debug()) fprintf (stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "f" , "sound-theme-spec.c", 578, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID ); } } while((0)); | |||
579 | ka_return_val_if_fail(sfopen, KA_ERROR_INVALID)do { if ((__builtin_expect((!(sfopen)),0))) { if (ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n" , "sfopen" , "sound-theme-spec.c", 579, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID); } } while((0)); | |||
580 | ka_return_val_if_fail(name && *name, KA_ERROR_INVALID)do { if ((__builtin_expect((!(name && *name)),0))) { if (ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n" , "name && *name" , "sound-theme-spec.c", 580, __PRETTY_FUNCTION__ ); return (KA_ERROR_INVALID); } } while((0)); | |||
581 | ||||
582 | if ((ret = find_sound_for_locale(f, sfopen, sound_path, theme_name, name, path, locale, subdir)) != KA_ERROR_NOTFOUND) | |||
583 | return ret; | |||
584 | ||||
585 | k = strchr(name, 0); | |||
586 | for (;;) { | |||
587 | char *n; | |||
588 | ||||
589 | do { | |||
590 | k--; | |||
591 | ||||
592 | if (k <= name) | |||
593 | return KA_ERROR_NOTFOUND; | |||
594 | ||||
595 | } while (*k != '-'); | |||
| ||||
596 | ||||
597 | if (!(n = ka_strndupstrndup(name, (size_t) (k-name)))) | |||
598 | return KA_ERROR_OOM; | |||
599 | ||||
600 | if ((ret = find_sound_for_locale(f, sfopen, sound_path, theme_name, n, path, locale, subdir)) != KA_ERROR_NOTFOUND) { | |||
601 | ka_freefree(n); | |||
602 | return ret; | |||
603 | } | |||
604 | ||||
605 | ka_freefree(n); | |||
606 | } | |||
607 | } | |||
608 | ||||
609 | static int find_sound_in_subdir( | |||
610 | ka_sound_file **f, | |||
611 | ka_sound_file_open_callback_t sfopen, | |||
612 | char **sound_path, | |||
613 | const char *theme_name, | |||
614 | const char *name, | |||
615 | const char *locale, | |||
616 | const char *subdir) { | |||
617 | ||||
618 | int ret; | |||
619 | char *e = NULL((void*)0); | |||
620 | const char *g; | |||
621 | ||||
622 | ka_return_val_if_fail(f, KA_ERROR_INVALID)do { if ((__builtin_expect((!(f)),0))) { if (ka_debug()) fprintf (stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "f" , "sound-theme-spec.c", 622, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID ); } } while((0)); | |||
623 | ka_return_val_if_fail(sfopen, KA_ERROR_INVALID)do { if ((__builtin_expect((!(sfopen)),0))) { if (ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n" , "sfopen" , "sound-theme-spec.c", 623, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID); } } while((0)); | |||
624 | ka_return_val_if_fail(name, KA_ERROR_INVALID)do { if ((__builtin_expect((!(name)),0))) { if (ka_debug()) fprintf (stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "name" , "sound-theme-spec.c", 624, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID ); } } while((0)); | |||
625 | ||||
626 | if ((ret = ka_get_data_home(&e)) < 0) | |||
627 | return ret; | |||
628 | ||||
629 | if (e
| |||
630 | ret = find_sound_for_name(f, sfopen, sound_path, theme_name, name, e, locale, subdir); | |||
631 | ka_freefree(e); | |||
632 | ||||
633 | if (ret != KA_ERROR_NOTFOUND) | |||
634 | return ret; | |||
635 | } | |||
636 | ||||
637 | g = ka_get_data_dirs(); | |||
638 | ||||
639 | for (;;) { | |||
640 | size_t k; | |||
641 | ||||
642 | k = strcspn(g, ":"); | |||
643 | ||||
644 | if (g[0] == '/' && k > 0) { | |||
645 | char *p; | |||
646 | ||||
647 | if (!(p = ka_strndupstrndup(g, k))) | |||
648 | return KA_ERROR_OOM; | |||
649 | ||||
650 | ret = find_sound_for_name(f, sfopen, sound_path, theme_name, name, p, locale, subdir); | |||
651 | ka_freefree(p); | |||
652 | ||||
653 | if (ret != KA_ERROR_NOTFOUND) | |||
654 | return ret; | |||
655 | } | |||
656 | ||||
657 | if (g[k] == 0) | |||
658 | break; | |||
659 | ||||
660 | g += k+1; | |||
661 | } | |||
662 | ||||
663 | return KA_ERROR_NOTFOUND; | |||
664 | } | |||
665 | ||||
666 | static int find_sound_in_profile( | |||
667 | ka_sound_file **f, | |||
668 | ka_sound_file_open_callback_t sfopen, | |||
669 | char **sound_path, | |||
670 | ka_theme_data *t, | |||
671 | const char *name, | |||
672 | const char *locale, | |||
673 | const char *profile) { | |||
674 | ||||
675 | ka_data_dir *d; | |||
676 | ||||
677 | ka_return_val_if_fail(f, KA_ERROR_INVALID)do { if ((__builtin_expect((!(f)),0))) { if (ka_debug()) fprintf (stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "f" , "sound-theme-spec.c", 677, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID ); } } while((0)); | |||
678 | ka_return_val_if_fail(t, KA_ERROR_INVALID)do { if ((__builtin_expect((!(t)),0))) { if (ka_debug()) fprintf (stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "t" , "sound-theme-spec.c", 678, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID ); } } while((0)); | |||
679 | ka_return_val_if_fail(sfopen, KA_ERROR_INVALID)do { if ((__builtin_expect((!(sfopen)),0))) { if (ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n" , "sfopen" , "sound-theme-spec.c", 679, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID); } } while((0)); | |||
680 | ka_return_val_if_fail(name, KA_ERROR_INVALID)do { if ((__builtin_expect((!(name)),0))) { if (ka_debug()) fprintf (stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "name" , "sound-theme-spec.c", 680, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID ); } } while((0)); | |||
681 | ||||
682 | for (d = t->data_dirs; d; d = d->next) | |||
683 | if (data_dir_matches(d, profile)) { | |||
684 | int ret; | |||
685 | ||||
686 | if ((ret = find_sound_in_subdir(f, sfopen, sound_path, d->theme_name, name, locale, d->dir_name)) != KA_ERROR_NOTFOUND) | |||
687 | return ret; | |||
688 | } | |||
689 | ||||
690 | return KA_ERROR_NOTFOUND; | |||
691 | } | |||
692 | ||||
693 | static int find_sound_in_theme( | |||
694 | ka_sound_file **f, | |||
695 | ka_sound_file_open_callback_t sfopen, | |||
696 | char **sound_path, | |||
697 | ka_theme_data *t, | |||
698 | const char *name, | |||
699 | const char *locale, | |||
700 | const char *profile) { | |||
701 | ||||
702 | int ret; | |||
703 | ||||
704 | ka_return_val_if_fail(f, KA_ERROR_INVALID)do { if ((__builtin_expect((!(f)),0))) { if (ka_debug()) fprintf (stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "f" , "sound-theme-spec.c", 704, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID ); } } while((0)); | |||
705 | ka_return_val_if_fail(name, KA_ERROR_INVALID)do { if ((__builtin_expect((!(name)),0))) { if (ka_debug()) fprintf (stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "name" , "sound-theme-spec.c", 705, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID ); } } while((0)); | |||
706 | ka_return_val_if_fail(sfopen, KA_ERROR_INVALID)do { if ((__builtin_expect((!(sfopen)),0))) { if (ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n" , "sfopen" , "sound-theme-spec.c", 706, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID); } } while((0)); | |||
707 | ka_return_val_if_fail(profile, KA_ERROR_INVALID)do { if ((__builtin_expect((!(profile)),0))) { if (ka_debug() ) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n" , "profile" , "sound-theme-spec.c", 707, __PRETTY_FUNCTION__) ; return (KA_ERROR_INVALID); } } while((0)); | |||
708 | ||||
709 | if (t
| |||
710 | /* First, try the profile def itself */ | |||
711 | if ((ret = find_sound_in_profile(f, sfopen, sound_path, t, name, locale, profile)) != KA_ERROR_NOTFOUND) | |||
712 | return ret; | |||
713 | ||||
714 | /* Then, fall back to stereo */ | |||
715 | if (!ka_streq(profile, DEFAULT_OUTPUT_PROFILE)(strcmp((profile),("stereo")) == 0)) | |||
716 | if ((ret = find_sound_in_profile(f, sfopen, sound_path, t, name, locale, DEFAULT_OUTPUT_PROFILE"stereo")) != KA_ERROR_NOTFOUND) | |||
717 | return ret; | |||
718 | } | |||
719 | ||||
720 | /* And fall back to no profile */ | |||
721 | return find_sound_in_subdir(f, sfopen, sound_path, t
| |||
722 | } | |||
723 | ||||
724 | static int find_sound_for_theme( | |||
725 | ka_sound_file **f, | |||
726 | ka_sound_file_open_callback_t sfopen, | |||
727 | char **sound_path, | |||
728 | ka_theme_data **t, | |||
729 | const char *theme, | |||
730 | const char *name, | |||
731 | const char *locale, | |||
732 | const char *profile) { | |||
733 | ||||
734 | int ret; | |||
735 | ||||
736 | ka_return_val_if_fail(f, KA_ERROR_INVALID)do { if ((__builtin_expect((!(f)),0))) { if (ka_debug()) fprintf (stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "f" , "sound-theme-spec.c", 736, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID ); } } while((0)); | |||
737 | ka_return_val_if_fail(t, KA_ERROR_INVALID)do { if ((__builtin_expect((!(t)),0))) { if (ka_debug()) fprintf (stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "t" , "sound-theme-spec.c", 737, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID ); } } while((0)); | |||
738 | ka_return_val_if_fail(sfopen, KA_ERROR_INVALID)do { if ((__builtin_expect((!(sfopen)),0))) { if (ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n" , "sfopen" , "sound-theme-spec.c", 738, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID); } } while((0)); | |||
739 | ka_return_val_if_fail(theme, KA_ERROR_INVALID)do { if ((__builtin_expect((!(theme)),0))) { if (ka_debug()) fprintf (stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "theme" , "sound-theme-spec.c", 739, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID ); } } while((0)); | |||
740 | ka_return_val_if_fail(name && *name, KA_ERROR_INVALID)do { if ((__builtin_expect((!(name && *name)),0))) { if (ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n" , "name && *name" , "sound-theme-spec.c", 740, __PRETTY_FUNCTION__ ); return (KA_ERROR_INVALID); } } while((0)); | |||
741 | ka_return_val_if_fail(locale, KA_ERROR_INVALID)do { if ((__builtin_expect((!(locale)),0))) { if (ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n" , "locale" , "sound-theme-spec.c", 741, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID); } } while((0)); | |||
742 | ka_return_val_if_fail(profile, KA_ERROR_INVALID)do { if ((__builtin_expect((!(profile)),0))) { if (ka_debug() ) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n" , "profile" , "sound-theme-spec.c", 742, __PRETTY_FUNCTION__) ; return (KA_ERROR_INVALID); } } while((0)); | |||
743 | ||||
744 | /* First, try in the theme itself, and if that fails the fallback theme */ | |||
745 | if ((ret = load_theme_data(t, theme)) == KA_ERROR_NOTFOUND) | |||
746 | if (!ka_streq(theme, FALLBACK_THEME)(strcmp((theme),("freedesktop")) == 0)) | |||
747 | ret = load_theme_data(t, FALLBACK_THEME"freedesktop"); | |||
748 | ||||
749 | if (ret
| |||
750 | if ((ret = find_sound_in_theme(f, sfopen, sound_path, *t, name, locale, profile)) != KA_ERROR_NOTFOUND) | |||
751 | return ret; | |||
752 | ||||
753 | /* Then, fall back to "unthemed" files */ | |||
754 | return find_sound_in_theme(f, sfopen, sound_path, NULL((void*)0), name, locale, profile); | |||
755 | } | |||
756 | ||||
757 | int ka_lookup_sound_with_callback( | |||
758 | ka_sound_file **f, | |||
759 | ka_sound_file_open_callback_t sfopen, | |||
760 | char **sound_path, | |||
761 | ka_theme_data **t, | |||
762 | ka_proplist *cp, | |||
763 | ka_proplist *sp) { | |||
764 | int ret = KA_ERROR_INVALID; | |||
765 | const char *name, *fname; | |||
766 | ||||
767 | ka_return_val_if_fail(f, KA_ERROR_INVALID)do { if ((__builtin_expect((!(f)),0))) { if (ka_debug()) fprintf (stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "f" , "sound-theme-spec.c", 767, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID ); } } while((0)); | |||
768 | ka_return_val_if_fail(t, KA_ERROR_INVALID)do { if ((__builtin_expect((!(t)),0))) { if (ka_debug()) fprintf (stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "t" , "sound-theme-spec.c", 768, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID ); } } while((0)); | |||
769 | ka_return_val_if_fail(cp, KA_ERROR_INVALID)do { if ((__builtin_expect((!(cp)),0))) { if (ka_debug()) fprintf (stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "cp" , "sound-theme-spec.c", 769, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID ); } } while((0)); | |||
770 | ka_return_val_if_fail(sp, KA_ERROR_INVALID)do { if ((__builtin_expect((!(sp)),0))) { if (ka_debug()) fprintf (stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "sp" , "sound-theme-spec.c", 770, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID ); } } while((0)); | |||
771 | ka_return_val_if_fail(sfopen, KA_ERROR_INVALID)do { if ((__builtin_expect((!(sfopen)),0))) { if (ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n" , "sfopen" , "sound-theme-spec.c", 771, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID); } } while((0)); | |||
772 | ||||
773 | *f = NULL((void*)0); | |||
774 | ||||
775 | if (sound_path) | |||
776 | *sound_path = NULL((void*)0); | |||
777 | ||||
778 | ka_mutex_lock(cp->mutex); | |||
779 | ka_mutex_lock(sp->mutex); | |||
780 | ||||
781 | if ((name = ka_proplist_gets_unlocked(sp, KA_PROP_EVENT_ID"event.id"))) { | |||
782 | const char *theme, *locale, *profile; | |||
783 | ||||
784 | if (!(theme = ka_proplist_gets_unlocked(sp, KA_PROP_KANBERRA_XDG_THEME_NAME"kanberra.xdg-theme.name"))) | |||
785 | if (!(theme = ka_proplist_gets_unlocked(cp, KA_PROP_KANBERRA_XDG_THEME_NAME"kanberra.xdg-theme.name"))) | |||
786 | theme = DEFAULT_THEME"freedesktop"; | |||
787 | ||||
788 | if (!(locale = ka_proplist_gets_unlocked(sp, KA_PROP_MEDIA_LANGUAGE"media.language"))) | |||
789 | if (!(locale = ka_proplist_gets_unlocked(sp, KA_PROP_APPLICATION_LANGUAGE"application.language"))) | |||
790 | if (!(locale = ka_proplist_gets_unlocked(cp, KA_PROP_MEDIA_LANGUAGE"media.language"))) | |||
791 | if (!(locale = ka_proplist_gets_unlocked(cp, KA_PROP_APPLICATION_LANGUAGE"application.language"))) | |||
792 | if (!(locale = setlocale(LC_MESSAGES5, NULL((void*)0)))) | |||
793 | locale = "C"; | |||
794 | ||||
795 | if (!(profile = ka_proplist_gets_unlocked(sp, KA_PROP_KANBERRA_XDG_THEME_OUTPUT_PROFILE"kanberra.xdg-theme.output-profile"))) | |||
796 | if (!(profile = ka_proplist_gets_unlocked(cp, KA_PROP_KANBERRA_XDG_THEME_OUTPUT_PROFILE"kanberra.xdg-theme.output-profile"))) | |||
797 | profile = DEFAULT_OUTPUT_PROFILE"stereo"; | |||
798 | ||||
799 | #ifdef HAVE_CACHE1 | |||
800 | if ((ret = ka_cache_lookup_sound(f, sfopen, sound_path, theme, name, locale, profile)) >= 0) { | |||
801 | ||||
802 | /* This entry is available in the cache, let's transform | |||
803 | * negative cache entries to KA_ERROR_NOTFOUND */ | |||
804 | ||||
805 | if (!*f) | |||
806 | ret = KA_ERROR_NOTFOUND; | |||
807 | ||||
808 | } else { | |||
809 | char *spath = NULL((void*)0); | |||
810 | ||||
811 | /* Either this entry was not available in the database, | |||
812 | * neither positive nor negative, or the database was | |||
813 | * corrupt, or it was out-of-date. In all cases try to | |||
814 | * find the entry manually. */ | |||
815 | ||||
816 | if ((ret = find_sound_for_theme(f, sfopen, sound_path
| |||
817 | /* Ok, we found it. Let's update the cache */ | |||
818 | ka_cache_store_sound(theme, name, locale, profile, sound_path ? *sound_path : spath); | |||
819 | else if (ret == KA_ERROR_NOTFOUND) | |||
820 | /* Doesn't seem to be around, let's create a negative cache entry */ | |||
821 | ka_cache_store_sound(theme, name, locale, profile, NULL((void*)0)); | |||
822 | ||||
823 | ka_freefree(spath); | |||
824 | } | |||
825 | ||||
826 | #else | |||
827 | ret = find_sound_for_theme(f, sfopen, sound_path, t, theme, name, locale, profile); | |||
828 | #endif | |||
829 | } | |||
830 | ||||
831 | if (ret == KA_ERROR_NOTFOUND || !name) { | |||
832 | if ((fname = ka_proplist_gets_unlocked(sp, KA_PROP_MEDIA_FILENAME"media.filename"))) | |||
833 | ret = sfopen(f, fname); | |||
834 | } | |||
835 | ||||
836 | ka_mutex_unlock(cp->mutex); | |||
837 | ka_mutex_unlock(sp->mutex); | |||
838 | ||||
839 | return ret; | |||
840 | } | |||
841 | ||||
842 | int ka_lookup_sound( | |||
843 | ka_sound_file **f, | |||
844 | char **sound_path, | |||
845 | ka_theme_data **t, | |||
846 | ka_proplist *cp, | |||
847 | ka_proplist *sp) { | |||
848 | ||||
849 | return ka_lookup_sound_with_callback(f, ka_sound_file_open, sound_path, t, cp, sp); | |||
| ||||
850 | } | |||
851 | ||||
852 | void ka_theme_data_free(ka_theme_data *t) { | |||
853 | ka_assert(t)do { if ((__builtin_expect((!(t)),0))) { fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s(). Aborting.\n" , "t" , "sound-theme-spec.c", 853, __PRETTY_FUNCTION__); abort (); } } while ((0)); | |||
854 | ||||
855 | while (t->data_dirs) { | |||
856 | ka_data_dir *d = t->data_dirs; | |||
857 | ||||
858 | KA_LLIST_REMOVE(ka_data_dir, t->data_dirs, d)do { ka_data_dir **_head = &(t->data_dirs), *_item = ( d); do { if ((__builtin_expect((!(_item)),0))) { fprintf(stderr , "Assertion '%s' failed at %s:%u, function %s(). Aborting.\n" , "_item" , "sound-theme-spec.c", 858, __PRETTY_FUNCTION__); abort (); } } while ((0)); if (_item->next) _item->next->prev = _item->prev; if (_item->prev) _item->prev->next = _item->next; else { do { if ((__builtin_expect((!(*_head == _item)),0))) { fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s(). Aborting.\n" , "*_head == _item" , "sound-theme-spec.c", 858, __PRETTY_FUNCTION__ ); abort(); } } while ((0)); *_head = _item->next; } _item ->next = _item->prev = ((void*)0); } while(0); | |||
859 | ||||
860 | ka_freefree(d->theme_name); | |||
861 | ka_freefree(d->dir_name); | |||
862 | ka_freefree(d->output_profile); | |||
863 | ka_freefree(d); | |||
864 | } | |||
865 | ||||
866 | ka_freefree(t->name); | |||
867 | ka_freefree(t); | |||
868 | } |