diff options
author | Lennart Poettering <lennart@poettering.net> | 2008-05-24 20:54:21 +0000 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2008-05-24 20:54:21 +0000 |
commit | 9010c443230c167398e22ffa3fa7643dfc252f00 (patch) | |
tree | b62679d0558f1078dedf8e034ef88609876acb7c | |
parent | 9b324b65f4aae8f7e4b182df59da625aa751e800 (diff) |
finish sound theme spec implementation
git-svn-id: file:///home/lennart/svn/public/libcanberra/trunk@8 01b60673-d06a-42c0-afdd-89cb8e0f78ac
-rw-r--r-- | canberra.h | 54 | ||||
-rw-r--r-- | sound-theme-spec.c | 636 | ||||
-rw-r--r-- | sound-theme-spec.h | 34 |
3 files changed, 556 insertions, 168 deletions
@@ -80,32 +80,34 @@ #endif /** Context, event, and playback properties */ -#define CA_PROP_MEDIA_NAME "media.name" -#define CA_PROP_MEDIA_TITLE "media.title" -#define CA_PROP_MEDIA_ARTIST "media.artist" -#define CA_PROP_MEDIA_LANGUAGE "media.language" -#define CA_PROP_MEDIA_FILENAME "media.filename" -#define CA_PROP_MEDIA_ICON "media.icon" -#define CA_PROP_MEDIA_ICON_NAME "media.icon_name" -#define CA_PROP_MEDIA_ROLE "media.role" -#define CA_PROP_EVENT_ID "event.id" -#define CA_PROP_EVENT_MOUSE_X "event.mouse.x" -#define CA_PROP_EVENT_MOUSE_Y "event.mouse.y" -#define CA_PROP_EVENT_MOUSE_BUTTON "event.mouse.button" -#define CA_PROP_WINDOW_X11_DISPLAY "window.x11.display" -#define CA_PROP_WINDOW_X11_XID "window.x11.xid" -#define CA_PROP_APPLICATION_NAME "application.name" -#define CA_PROP_APPLICATION_ID "application.id" -#define CA_PROP_APPLICATION_VERSION "application.version" -#define CA_PROP_APPLICATION_ICON "application.icon" -#define CA_PROP_APPLICATION_ICON_NAME "application.icon_name" -#define CA_PROP_APPLICATION_LANGUAGE "application.language" -#define CA_PROP_APPLICATION_PROCESS_ID "application.process.id" -#define CA_PROP_APPLICATION_PROCESS_BINARY "application.process.binary" -#define CA_PROP_APPLICATION_PROCESS_USER "application.process.user" -#define CA_PROP_APPLICATION_PROCESS_HOST "application.process.host" -#define CA_PROP_CANBERRA_CONTROL_CACHE "canberra.control.cache" /* permanent, volatile, never */ -#define CA_PROP_CANBERRA_CONTROL_VOLUME "canberra.control.volume" /* decibel */ +#define CA_PROP_MEDIA_NAME "media.name" +#define CA_PROP_MEDIA_TITLE "media.title" +#define CA_PROP_MEDIA_ARTIST "media.artist" +#define CA_PROP_MEDIA_LANGUAGE "media.language" +#define CA_PROP_MEDIA_FILENAME "media.filename" +#define CA_PROP_MEDIA_ICON "media.icon" +#define CA_PROP_MEDIA_ICON_NAME "media.icon_name" +#define CA_PROP_MEDIA_ROLE "media.role" +#define CA_PROP_EVENT_ID "event.id" +#define CA_PROP_EVENT_MOUSE_X "event.mouse.x" +#define CA_PROP_EVENT_MOUSE_Y "event.mouse.y" +#define CA_PROP_EVENT_MOUSE_BUTTON "event.mouse.button" +#define CA_PROP_WINDOW_X11_DISPLAY "window.x11.display" +#define CA_PROP_WINDOW_X11_XID "window.x11.xid" +#define CA_PROP_APPLICATION_NAME "application.name" +#define CA_PROP_APPLICATION_ID "application.id" +#define CA_PROP_APPLICATION_VERSION "application.version" +#define CA_PROP_APPLICATION_ICON "application.icon" +#define CA_PROP_APPLICATION_ICON_NAME "application.icon_name" +#define CA_PROP_APPLICATION_LANGUAGE "application.language" +#define CA_PROP_APPLICATION_PROCESS_ID "application.process.id" +#define CA_PROP_APPLICATION_PROCESS_BINARY "application.process.binary" +#define CA_PROP_APPLICATION_PROCESS_USER "application.process.user" +#define CA_PROP_APPLICATION_PROCESS_HOST "application.process.host" +#define CA_PROP_CANBERRA_CACHE_CONTROL "canberra.cache-control" /* permanent, volatile, never */ +#define CA_PROP_CANBERRA_VOLUME "canberra.volume" /* decibel */ +#define CA_PROP_CANBERRA_XDG_THEME_NAME "canberra.xdg-theme.name" /* XDG theme name */ +#define CA_PROP_CANBERRA_XDG_THEME_OUTPUT_PROFILE "canberra.xdg-theme.output-profile" /* XDG theme profile */ /* Context object */ typedef struct ca_context ca_context; diff --git a/sound-theme-spec.c b/sound-theme-spec.c index 0a82ef2..fd0f95b 100644 --- a/sound-theme-spec.c +++ b/sound-theme-spec.c @@ -1,20 +1,397 @@ +/* $Id$ */ -#define DEFAULT_THEME "dudeldidei" -#define DEFAULT_PROFILE "stereo" +/*** + This file is part of libcanberra. -static int find_sound_for_suffix(ca_sound_file **f, const char *path, const char *name, const char *suffix, const char *theme, const char *locale, const char *subdir) { + Copyright 2008 Lennart Poettering + + libcanberra is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 2.1 of the + License, or (at your option) any later version. + + libcanberra is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with libcanberra. If not, If not, see + <http://www.gnu.org/licenses/>. +***/ + +#include "sound-theme-spec.h" +#include "llist.h" + +#define DEFAULT_THEME "freedesktop" +#define FALLBACK_THEME "freedesktop" +#define DEFAULT_OUTPUT_PROFILE "stereo" +#define N_THEME_DIR_MAX 8 + +typedef struct ca_data_dir ca_data_dir; + +struct ca_data_dir { + CA_LLIST_FIELDS(ca_data_dir); + + char *name; + char *output_profile; +}; + +struct ca_theme_data { + char *name; + + CA_LLIST_HEAD(ca_data_dir, data_dirs); + ca_theme_dir *last_dir; + + unsigned n_theme_dir; + ca_bool_t loaded_fallback_theme; +}; + +static int get_data_home(char **e) { + const char *env, *subdir; + char *r; + ca_return_val_if_fail(e, CA_ERROR_INVALID); + + if ((env = getenv("XDG_DATA_HOME")) && *env == '/') + subdir = ""; + else if ((env = getenv("HOME")) && *env == '/') + subdir = "/.local/share"; + else { + *e = NULL; + return CA_SUCCESS; + } + + if (!(r = ca_new(char, strlen(env) + strlen(subdir) + 1))) + return CA_ERROR_OOM; + + sprintf(r, "%s%s", env, subdir); + *e = r; + + return CA_SUCCESS; +} + +static ca_bool_t data_dir_matches(ca_data_dir *d, const char*output_profile) { + ca_assert(d); + ca_assert(profile); + + /* We might want to add more elaborate matching here eventually */ + + return streq(d->profile, output_profile); +} + +static ca_data_dir* find_data_dir(ca_theme_data *t, const char *name) { + ca_data_dir *d; + + ca_assert(t); + ca_assert(name); + + for (d = t->data_dirs; d; d = d->next) + if (streq(d->name, name)) + return d; + + return NULL; +} + +static int add_data_dir(ca_theme_data *t, const char *name) { + ca_data_dir *d; + + ca_return_val_if_fail(t, CA_ERROR_INVALID); + ca_return_val_if_fail(name, CA_ERROR_INVALID); + + if (find_data_dir(t, name)) + return; + + if (!(d = ca_new0(ca_data_dir, 1))) + return CA_ERROR_OOM; + + if (!(d->name = ca_strdup(name))) { + ca_free(d); + return CA_ERROR_OOM; + } + + CA_LLIST_INSERT_AFTER(ca_data_dir, t->data_dirs, t->last_dir, d); + t->last_dir = d; + + return CA_SUCCESS; +} + +static int load_theme_path(ca_theme_data *t, const char *prefix, const char *name) { + char *fn, *inherits = NULL; + FILE *f; + ca_bool_t in_sound_theme_section = FALSE; + ca_data_dir *current_data_dir = NULL; + + ca_return_val_if_fail(t, CA_ERROR_INVALID); + ca_return_val_if_fail(prefix, CA_ERROR_INVALID); + ca_return_val_if_fail(name, CA_ERROR_INVALID); + + if (!(fn = ca_new(char, strlen(prefix) + sizeof("/sounds/")-1 + strlen(name) + sizeof("index.theme")))) + return CA_ERROR_OOM; + + sprintf(fn, "%s/sounds/%s/index.theme", prefix, name); + f = fopen(fn, "r"); + ca_free(fn); + + if (!f) { + if (errno == ENOENT) + return CA_ERROR_NOTFOUND; + + return CA_ERROR_SYSTEM; + } + + for (;;) { + char ln[1024]; + + if (!(fgets(ln, f))) { + + if (feof(f)) + break; + + ca_assert(ferror(f)); + ret = CA_ERROR_SYSTEM; + goto fail; + } + + ln[strcspn(ln, "\n\r#")] = 0; + + if (!ln[0]) + continue; + + if (streq(ln, "[Sound Theme]")) { + in_sound_theme_section = TRUE; + current_data_dir = NULL; + continue; + } + + if (ln[0] == '[' && ln[strlen(ln-1)] == ']') { + char *d; + + if (!(d = ca_strndup(ln+1, strlen(ln)-2))) { + ret = CA_ERROR_OOM; + goto fail; + } + + current_data_dir = find_data_dir(e, d); + ca_free(d); + + in_sound_theme_section = FALSE; + continue; + } + + ca_assert(!in_sound_theme_section || !current_data_dir); + ca_assert(!current_data_dir || !in_sound_theme_section); + + if (in_sound_theme_section) { + + if (!strncmp(ln, "Inherits", 8)) { + + if (inherits) { + ret = CA_ERROR_CORRUPT; + goto fail; + } + + if (!(inherits = ca_strdup(ln + 8))) { + ret = CA_ERROR_OOM; + goto fail; + } + + continue; + } + + if (!strncmp(ln, "Directories", 11)) { + char *d; + + d = ln+11; + for (;;) { + size_t k = strcspn(d, ", "); + + if (k > 0) { + char *p; + + if (!(p = ca_strndup(d, k))) { + ret = CA_ERROR_OOM; + goto fail; + } + + ret = add_data_dir(t, p); + ca_free(p); + + if (ret != CA_SUCCESS) + goto fail; + } + + if (d[k] == 0) + break; + + = k+1; + } + + continue; + } + } + + if (current_data_dir) { + + if (!strncmp(ln, "OutputProfile", 13)) { + + if (current_data_dir->output_profile && !streq(current_data_dir->output_profile, ln+13)) { + ret = CA_ERROR_CORRUPT; + goto fail; + } + + if (!(current_data_dir->output_profile = ca_strdup(ln+13))) { + ret = CA_ERROR_OOM; + goto fail; + } + + continue; + } + } + } + + t->n_theme_dir ++; + + if (inherits) { + i = inherits; + for (;;) { + size_t k = strcspn(i, ", "); + + if (k > 0) { + char *p; + + if (!(p = ca_strndup(i, k))) { + ret = CA_ERROR_OOM; + goto fail; + } + + ret = load_theme_dir(t, p); + ca_free(p); + + if (ret != CA_SUCCESS) + goto fail; + } + + if (i[k] == 0) + break; + + i = k+1; + } + } + + ret = CA_SUCCESS; + +fail: + + ca_free(inherits); + ca_free(directories); + fclose(f); + + return ret; +} + +static int load_theme_dir(ca_theme_data *t, const char *name) { + ca_return_val_if_fail(t, CA_ERROR_INVALID); + ca_return_val_if_fail(name, CA_ERROR_INVALID); + ca_return_val_if_fail(t->n_theme_dir < N_THEME_DIR_MAX, CA_ERROR_CORRUPT); + + if ((ret = get_data_home(&e)) < 0) + return ret; + + if (streq(name, FALLBACK_THEME)) + t->loaded_fallback_theme = TRUE; + + if (e) { + ret = load_theme_path(t, e, name); + ca_free(e); + + if (ret != CA_ERROR_NOTFOUND) + return ret; + } + + if (!(e = getenv("XDG_DATA_DIRS")) || *e = 0) + e = "/usr/local/share:/usr/share"; + + for (;;) { + size_t k; + + k = strcspn(e, ":"); + + if (e[0] == '/' && k > 0) { + char *p; + + if (!(p = ca_strndup(e, k))) + return CA_ERROR_OOM; + + ret = load_theme_path(t, p, name); + ca_free(p); + + if (ret != CA_ERROR_NOTFOUND) + return ret; + } + + if (e[k] == 0) + break; + + e += k+1; + } + + return CA_ERROR_NOTFOUND; +} + +static int load_theme_data(ca_theme_data **_t, const char *name) { + ca_theme_data *t; + int ret; + + ca_return_val_if_fail(_t, CA_ERROR_INVALID); + ca_return_val_if_fail(name, CA_ERROR_INVALID); + + if (*_t) + if (streq((*_t)->name, name)) + return CA_SUCCESS; + + if (!(t = pa_xnew0(ca_theme_data, 1))) + return CA_ERROR_OOM; + + if (!(t->name = ca_strdup(name))) { + ret = CA_ERROR_OOM; + goto fail; + } + + if ((ret = load_theme_dir(t, name)) < 0) + goto fail; + + if (!t->loaded_fallback_theme) + if ((ret = load_theme_dir(t, FALLBACK_THEME)) < 0) + goto fail; + + if (*_t) + ca_theme_data_free(*_t); + + *_t = t; + + return CA_SUCCESS; + +fail: + + if (t) + ca_theme_data_free(t); + + return ret; +} + +static int find_sound_for_suffix(ca_sound_file **f, ca_theme_data *t, const char *name, const char *path, const char *suffix, const char *locale, const char *subdir) { const char *fn; ca_return_val_if_fail(f, CA_ERROR_INVALID); + ca_return_val_if_fail(name, CA_ERROR_INVALID); ca_return_val_if_fail(path, CA_ERROR_INVALID); ca_return_val_if_fail(path[0] == '/', CA_ERROR_INVALID); - ca_return_val_if_fail(name, CA_ERROR_INVALID); ca_return_val_if_fail(suffix, CA_ERROR_INVALID); if (!(fn = ca_sprintf_malloc("%s/%s%s%s%s%s%s", path, - theme ? "/" : "", - theme ? theme : "", + t ? "/" : "", + t ? t->name : "", subdir ? "/" : "" subdir ? subdir : "", locale ? "/" : "", @@ -28,85 +405,113 @@ static int find_sound_for_suffix(ca_sound_file **f, const char *path, const char return ret; } -static int find_sound_in_path(ca_sound_file **f, const char *path, const char *name, const char *theme, const char *locale, const char *subdir) { +static int find_sound_in_path(ca_sound_file **f, ca_theme_data *t, const char *name, const char *path, const char *locale, const char *subdir) { int ret; ca_return_val_if_fail(f, CA_ERROR_INVALID); + ca_return_val_if_fail(name, CA_ERROR_INVALID); ca_return_val_if_fail(path, CA_ERROR_INVALID); ca_return_val_if_fail(path[0] == '/', CA_ERROR_INVALID); - ca_return_val_if_fail(name, CA_ERROR_INVALID); - if ((ret = find_sound_for_suffix(f, path, name, ".ogg", theme, locale, subdir)) != CA_ERROR_NOTFOUND) - return ret; + if (!(p = ca_new(char, strlen(path) + sizeof("/sounds")))) + return CA_ERROR_OOM; + + sprintf(p, "%s/sounds", path); + + if ((ret = find_sound_for_suffix(f, t, name, p, ".ogg", locale, subdir)) == CA_ERROR_NOTFOUND) + ret = find_sound_for_suffix(f, t, name, p, ".wav", locale, subdir); + + ca_free(p); - return find_sound_for_suffix(f, path, name, ".wav", theme, locale, subdir); + return ret; } -static int find_sound_in_theme(ca_sound_file **f, const char *name, const char *theme, const char *locale, const char *subdir) { +static int find_sound_in_subdir(ca_sound_file **f, ca_theme_data *t, const char *name, const char *locale, const char *subdir) { int ret; - const char *e; + char *e = NULL; ca_return_val_if_fail(f, CA_ERROR_INVALID); ca_return_val_if_fail(name, CA_ERROR_INVALID); - if ((e = getenv("XDG_DATA_DIRS"))) { - for (;;) { - const char *r; - char *p; + if ((ret = get_data_home(&e)) < 0) + return ret; - if (!(r = strchr(e, ':'))) - break; + if (e) { + ret = find_sound_in_path(f, t, name, e, locale, subdir); + ca_free(e); + + if (ret != CA_ERROR_NOTFOUND) + return ret; + } - if (!(p = ca_strndup(e, r-e))) + if (!(e = getenv("XDG_DATA_DIRS")) || *e = 0) + e = "/usr/local/share:/usr/share"; + + for (;;) { + size_t k; + + k = strcspn(e, ":"); + + if (e[0] == '/' && k > 0) { + char *p; + + if (!(p = ca_strndup(e, k))) return CA_ERROR_OOM; - ret = find_sound_in_path(f, p, name, theme, locale, subdir); + ret = find_sound_in_path(f, t, name, p, locale, subdir); ca_free(p); if (ret != CA_ERROR_NOTFOUND) return ret; - - e = r+1; } + + if (e[k] == 0) + break; + + e += k+1; } - if ((e = getenv("HOME"))) { - char *p; - #define SUBDIR "/.share/sounds" + return CA_ERROR_NOTFOUND; +} - if (!(p = ca_new(char, strlen(e) + sizeof(SUBDIR)))) - return CA_ERROR_OOM; +static int find_sound_for_profile(ca_sound_file **f, ca_theme_data *t, const char *name, const char *locale, const char *profile) { + ca_data_dir *d; - sprintf(p, "%s" SUBDIR, e); + ca_return_val_if_fail(f, CA_ERROR_INVALID); + ca_return_val_if_fail(name, CA_ERROR_INVALID); - ret = find_sound_in_path(f, p, name, theme, locale, subdir); - ca_free(p); + if (!t) + return find_sound_in_subdir(f, NULL, name, locale, NULL); - if (ret != CA_ERROR_NOTFOUND) - return ret; - } + for (d = t->data_dirs; d; d = d->next) + if (data_dir_matches(d, profile)) { + int ret; + + if ((ret = find_sound_in_subdir(f, t, name, locale, d->name)) != CA_ERROR_NOTFOUND) + return ret; + } return CA_ERROR_NOTFOUND; } -static int find_sound_in_locale(ca_sound_file **f, const char *name, const char *theme, const char *locale, const char *profile) { +static int find_sound_in_locale(ca_sound_file **f, ca_theme_data *t, const char *name, const char *locale, const char *profile) { ca_return_val_if_fail(f, CA_ERROR_INVALID); ca_return_val_if_fail(name, CA_ERROR_INVALID); ca_return_val_if_fail(profile, CA_ERROR_INVALID); /* First, try the profile def itself */ - if ((ret = find_sound_in_profile(f, name, theme, locale, profile)) != CA_ERROR_NOTFOUND) + if ((ret = find_sound_for_profile(f, t, name, locale, profile)) != CA_ERROR_NOTFOUND) return ret; /* Then, fall back to stereo */ - if (strcmp(profile, "stereo")) - if ((ret = find_sound_in_profile(f, name, theme, locale, "stereo")) != CA_ERROR_NOTFOUND) + if (!streq(profile, DEFAULT_OUTPUT_PROFILE)) + if ((ret = find_sound_for_profile(f, t, name, locale, DEFAULT_PROFILE)) != CA_ERROR_NOTFOUND) return ret; /* And fall back to no profile */ - return find_sound_in_profile(f, name, theme, locale, NULL); + return find_sound_for_profile(f, t, name, locale, NULL); } -static int find_sound_in_theme(ca_sound_file **f, const char *name, const char *theme, const char *locale, const char *profile) { +static int find_sound_for_locale(ca_sound_file **f, ca_theme_data *theme, const char *name, const char *locale, const char *profile) { const char *e; ca_return_val_if_fail(f, CA_ERROR_INVALID); @@ -115,7 +520,7 @@ static int find_sound_in_theme(ca_sound_file **f, const char *name, const char * ca_return_val_if_fail(profile, CA_ERROR_INVALID); /* First, try the locale def itself */ - if ((ret = find_sound_in_locale(f, name, theme, locale, profile)) != CA_ERROR_NOTFOUND) + if ((ret = find_sound_in_locale(f, theme, name, locale, profile)) != CA_ERROR_NOTFOUND) return ret; /* Then, try to truncate at the @ */ @@ -125,7 +530,7 @@ static int find_sound_in_theme(ca_sound_file **f, const char *name, const char * if (!(t = ca_strndup(t, e - locale))) return CA_ERROR_OOM; - ret = find_sound_in_locale(f, name, theme, t, profile); + ret = find_sound_in_locale(f, theme, name, t, profile); ca_free(t); if (ret != CA_ERROR_NOTFOUND) @@ -139,7 +544,7 @@ static int find_sound_in_theme(ca_sound_file **f, const char *name, const char * if (!(t = ca_strndup(t, e - locale))) return CA_ERROR_OOM; - ret = find_sound_in_locale(f, name, theme, t, profile); + ret = find_sound_in_locale(f, theme, name, t, profile); ca_free(t); if (ret != CA_ERROR_NOTFOUND) @@ -148,133 +553,80 @@ static int find_sound_in_theme(ca_sound_file **f, const char *name, const char * /* Then, try "C" as fallback locale */ if (strcmp(locale, "C")) - if ((ret = find_sound_in_locale(f, name, theme, "C", profile)) != CA_ERROR_NOTFOUND) + if ((ret = find_sound_in_locale(f, theme, name, "C", profile)) != CA_ERROR_NOTFOUND) return ret; /* Try without locale */ - if ((ret = find_sound_in_locale(f, name, theme, NULL, profile))) - return ret; - - /* Try to find an inherited theme */ - + return find_sound_in_locale(f, theme, name, NULL, profile); } -int find_sound(ca_sound_file **f, const char *name, const char *theme, const char *locale, const char *profile) { +static int find_sound_for_theme(ca_sound_file **f, ca_theme_data **t, const char *theme, const char *name, const char *locale, const char *profile) { int ret; ca_return_val_if_fail(f, CA_ERROR_INVALID); + ca_return_val_if_fail(t, CA_ERROR_INVALID); + ca_return_val_if_fail(theme, CA_ERROR_INVALID); ca_return_val_if_fail(name, CA_ERROR_INVALID); - - if (!theme) - theme = DEFAULT_THEME; - - if (!locale) - locale = setlocale(LC_MESSAGES, NULL); - - if (!locale) - locale = "C"; - - if (!profile) - profile = DEFAULT_PROFILE; + ca_return_val_if_fail(locale, CA_ERROR_INVALID); + ca_return_val_if_fail(profile, CA_ERROR_INVALID); /* First, try in the theme itself */ - if ((ret = find_sound_in_theme(f, name, theme, locale, profile)) != CA_ERROR_NOTFOUND) - return ret; - - /* Then, fall back to the magic freedesktop theme */ - if (strcmp(theme, "freedesktop")) - if ((ret = find_sound_in_theme(f, name, "freedesktop", locale, profile)) != CA_ERROR_NOTFOUND) + if ((ret = load_theme_data(t, theme)) == CA_SUCCESS) + if ((ret = find_sound_in_theme(f, t, name, locale, profile)) != CA_ERROR_NOTFOUND) return ret; - /* Finally, fall back to "unthemed" files */ - return find_sound_in_theme(f, name, NULL, locale, profile); + /* Then, fall back to "unthemed" files */ + return find_sound_in_theme(f, NULL, name, locale, profile); } -FindSound(sound, locale) { - filename = FindSoundHelper(sound, locale, soundsystem, user selected theme); - if filename != none - return filename +int ca_lookup_sound(ca_sound_file **f, ca_theme_data **t, ca_proplist *p) { + int ret; + const char *name, *fname; - filename = FindSoundHelper(sound, locale, soundsystem, "freedesktop"); - if filename != none - return filename + ca_return_val_if_fail(f, CA_ERROR_INVALID); + ca_return_val_if_fail(t, CA_ERROR_INVALID); + ca_return_val_if_fail(p, CA_ERROR_INVALID); - return LookupFallbackSound (sound) -} + ca_mutex_lock(p->mutex); -FindSoundHelper(sound, locale, soundsystem, theme) { - filename = LookupSound (sound, locale, soundsystem, theme) - if filename != none - return filename + if ((name = ca_proplist_gets(p, CA_PROP_EVENT_ID))) { + const char *theme, *locale, *profile; - if theme has parents - parents = theme.parents + if (!(theme = ca_proplist_gets(p, CA_PROP_CANBERRA_XDG_THEME_NAME))) + theme = DEFAULT_THEME; - for parent in parents { - filename = FindSoundHelper (sound, locale, soundsystem, parent) - if filename != none - return filename - } - return none -} + if (!(locale = ca_proplist_gets(p, CA_PROP_APPLICATION_LANGUAGE))) + if (!(locale = setlocale(LC_MESSAGES, NULL))) + locale = "C"; -LookupSound (sound, locale, soundsystem, theme) { - // lookup localized version - for each subdir in $(theme subdir list) { - for each directory in $(basename list) { - for system in (soundsystem, "stereo") { - if DirectoryMatchesSoundSystem(subdir, system) { - for extension in ("wav", "ogg") { - filename = directory/$(themename)/subdir/$locale/sound.extension - if exist filename - return filename - } - } - } - } - } - - // lookup unlocalized version - for each subdir in $(theme subdir list) { - for each directory in $(basename list) { - for system in (soundsystem, "stereo") { - if DirectoryMatchesSoundSystem(subdir, system) { - for extension in ("wav", "ogg") { - filename = directory/$(themename)/subdir/sound.extension - if exist filename - return filename - } - } - } - } - } + if (!(profile = ca_proplist_gets(p, CA_PROP_CANBERRA_XDG_THEME_OUTPUT_PROFILE))) + profile = DEFAULT_OUTPUT_PROFILE; - return none -} + ret = find_sound_for_theme(f, t, theme, name, locale, profile); -LookupFallbackSound (sound) { - for each directory in $(basename list) { - for extension in ("wav", "ogg") { - if exists directory/sound.extension - return directory/sound.extension - } - } - return none -} + } else if ((fname = ca_proplist_gets(p, CA_PROP_MEDIA_FILENAME))) + ret = ca_sound_file_open(f, fname); + else + ret = CA_ERROR_INVALID; -DirectoryMatchesSoundSystem(subdir, system) { - read SoundSystem from subdir - if SoundSystem == system - return true - return false -} + ca_mutex_unlock(p->mutex); + return ret; +} -int ca_resolve_file(ca_sound_file *f, ca_proplist *p) { - ca_return_val_if_fail(f, CA_ERROR_INVALID); - ca_return_val_if_fail(p, CA_ERROR_INVALID); +void ca_theme_data_free(ca_theme_data *t) { + ca_assert(t); + while (t->data_dirs) { + ca_data_dir *d = t->data_dirs; + CA_LLIST_REMOVE(ca_data_dir, t->data_dirs, d); + ca_free(d->name); + ca_free(d->output_profile); + ca_free(d); + } + ca_free(t->name); + ca_free(t); } diff --git a/sound-theme-spec.h b/sound-theme-spec.h new file mode 100644 index 0000000..527ad11 --- /dev/null +++ b/sound-theme-spec.h @@ -0,0 +1,34 @@ +#ifndef foocasoundthemespechfoo +#define foocasoundthemespechfoo + +/* $Id$ */ + +/*** + This file is part of libcanberra. + + Copyright 2008 Lennart Poettering + + libcanberra is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 2.1 of the + License, or (at your option) any later version. + + libcanberra is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with libcanberra. If not, If not, see + <http://www.gnu.org/licenses/>. +***/ + +#include "read-sound-file.h" +#include "proplist.h" + +typedef struct ca_theme_data ca_theme_data; + +int ca_lookup_sound(ca_sound_file **f, ca_theme_data **t, ca_proplist *p); +void ca_theme_data_free(ca_theme_data *t); + +#endif |