| File: | sound-theme-spec.c |
| Warning: | line 858, column 17 Use of memory after it is freed |
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 ? t->name : NULL((void*)0), name, locale, NULL((void*)0)); | |||
| 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 == KA_SUCCESS) | |||
| 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 | } |