summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2008-05-24 00:10:07 +0000
committerLennart Poettering <lennart@poettering.net>2008-05-24 00:10:07 +0000
commit9b324b65f4aae8f7e4b182df59da625aa751e800 (patch)
tree1cb08f8e7a26a85a2886d395c47952891c9752dc
parent3f00b1697f7304bb565232f5378ec38a23e12649 (diff)
commit half-baked sound theme spec implementaiton
git-svn-id: file:///home/lennart/svn/public/libcanberra/trunk@7 01b60673-d06a-42c0-afdd-89cb8e0f78ac
-rw-r--r--canberra.h3
-rw-r--r--read-sound-file.c10
-rw-r--r--sound-theme-spec.c280
3 files changed, 291 insertions, 2 deletions
diff --git a/canberra.h b/canberra.h
index abcfd05..b4783a9 100644
--- a/canberra.h
+++ b/canberra.h
@@ -124,7 +124,8 @@ enum {
CA_ERROR_SYSTEM = -6,
CA_ERROR_CORRUPT = -7,
CA_ERROR_TOOBIG = -8,
- _CA_ERROR_MAX = -9
+ CA_ERROR_NOT_FOUND = -9,
+ _CA_ERROR_MAX = -10
};
typedef struct ca_proplist ca_proplist;
diff --git a/read-sound-file.c b/read-sound-file.c
index 37d0dd1..13066b1 100644
--- a/read-sound-file.c
+++ b/read-sound-file.c
@@ -25,6 +25,7 @@
struct ca_sound_file {
ca_wav *wav;
ca_vorbis *vorbis;
+ char *filename;
unsigned nchannels;
unsigned rate;
@@ -42,8 +43,13 @@ int ca_sound_file_open(ca_sound_file *_f, const char *fn) {
if (!(f = ca_new0(ca_sound_file, 1)))
return CA_ERROR_OOM;
+ if (!(f->filename = ca_strdup(fn))) {
+ ret = CA_ERROR_OOM;
+ goto fail;
+ }
+
if (!(file = fopen(fn, "r"))) {
- ret = CA_ERROR_SYSTEM;
+ ret = errno == ENOENT ? CA_ERROR_NOTFOUND : CA_ERROR_SYSTEM;
goto fail;
}
@@ -72,6 +78,8 @@ int ca_sound_file_open(ca_sound_file *_f, const char *fn) {
}
fail:
+
+ ca_free(f->filename);
ca_free(f);
return ret;
diff --git a/sound-theme-spec.c b/sound-theme-spec.c
new file mode 100644
index 0000000..0a82ef2
--- /dev/null
+++ b/sound-theme-spec.c
@@ -0,0 +1,280 @@
+
+#define DEFAULT_THEME "dudeldidei"
+#define DEFAULT_PROFILE "stereo"
+
+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) {
+ const char *fn;
+
+ ca_return_val_if_fail(f, 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 : "",
+ subdir ? "/" : ""
+ subdir ? subdir : "",
+ locale ? "/" : "",
+ locale ? locale : "",
+ name, suffix)))
+ return CA_ERROR_OOM;
+
+ ret = ca_sound_file_open(f, fn);
+ ca_free(fn);
+
+ 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) {
+ int ret;
+
+ ca_return_val_if_fail(f, 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;
+
+ return find_sound_for_suffix(f, path, name, ".wav", theme, locale, subdir);
+}
+
+static int find_sound_in_theme(ca_sound_file **f, const char *name, const char *theme, const char *locale, const char *subdir) {
+ int ret;
+ const char *e;
+ 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 (!(r = strchr(e, ':')))
+ break;
+
+ if (!(p = ca_strndup(e, r-e)))
+ return CA_ERROR_OOM;
+
+ ret = find_sound_in_path(f, p, name, theme, locale, subdir);
+ ca_free(p);
+
+ if (ret != CA_ERROR_NOTFOUND)
+ return ret;
+
+ e = r+1;
+ }
+ }
+
+ if ((e = getenv("HOME"))) {
+ char *p;
+ #define SUBDIR "/.share/sounds"
+
+ if (!(p = ca_new(char, strlen(e) + sizeof(SUBDIR))))
+ return CA_ERROR_OOM;
+
+ sprintf(p, "%s" SUBDIR, e);
+
+ ret = find_sound_in_path(f, p, name, theme, locale, subdir);
+ ca_free(p);
+
+ if (ret != 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) {
+ 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)
+ 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)
+ return ret;
+
+ /* And fall back to no profile */
+ return find_sound_in_profile(f, name, theme, locale, NULL);
+}
+
+static int find_sound_in_theme(ca_sound_file **f, const char *name, const char *theme, const char *locale, const char *profile) {
+ const char *e;
+
+ ca_return_val_if_fail(f, CA_ERROR_INVALID);
+ ca_return_val_if_fail(name, CA_ERROR_INVALID);
+ ca_return_val_if_fail(locale, CA_ERROR_INVALID);
+ 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)
+ return ret;
+
+ /* Then, try to truncate at the @ */
+ if ((e = strchr(locale, '@'))) {
+ char *t;
+
+ if (!(t = ca_strndup(t, e - locale)))
+ return CA_ERROR_OOM;
+
+ ret = find_sound_in_locale(f, name, theme, t, profile);
+ ca_free(t);
+
+ if (ret != CA_ERROR_NOTFOUND)
+ return ret;
+ }
+
+ /* Followed by truncating at the _ */
+ if ((e = strchr(locale, '_'))) {
+ char *t;
+
+ if (!(t = ca_strndup(t, e - locale)))
+ return CA_ERROR_OOM;
+
+ ret = find_sound_in_locale(f, name, theme, t, profile);
+ ca_free(t);
+
+ if (ret != CA_ERROR_NOTFOUND)
+ return ret;
+ }
+
+ /* Then, try "C" as fallback locale */
+ if (strcmp(locale, "C"))
+ if ((ret = find_sound_in_locale(f, name, theme, "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 */
+
+}
+
+int find_sound(ca_sound_file **f, const char *name, const char *theme, const char *locale, const char *profile) {
+ int ret;
+
+ ca_return_val_if_fail(f, 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;
+
+ /* 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)
+ return ret;
+
+ /* Finally, fall back to "unthemed" files */
+ return find_sound_in_theme(f, name, NULL, locale, profile);
+}
+
+FindSound(sound, locale) {
+ filename = FindSoundHelper(sound, locale, soundsystem, user selected theme);
+ if filename != none
+ return filename
+
+ filename = FindSoundHelper(sound, locale, soundsystem, "freedesktop");
+ if filename != none
+ return filename
+
+ return LookupFallbackSound (sound)
+}
+
+FindSoundHelper(sound, locale, soundsystem, theme) {
+ filename = LookupSound (sound, locale, soundsystem, theme)
+ if filename != none
+ return filename
+
+ if theme has parents
+ parents = theme.parents
+
+ for parent in parents {
+ filename = FindSoundHelper (sound, locale, soundsystem, parent)
+ if filename != none
+ return filename
+ }
+ return none
+}
+
+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
+ }
+ }
+ }
+ }
+ }
+
+ return none
+}
+
+LookupFallbackSound (sound) {
+ for each directory in $(basename list) {
+ for extension in ("wav", "ogg") {
+ if exists directory/sound.extension
+ return directory/sound.extension
+ }
+ }
+ return none
+}
+
+DirectoryMatchesSoundSystem(subdir, system) {
+ read SoundSystem from subdir
+ if SoundSystem == system
+ return true
+ return false
+}
+
+
+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);
+
+
+
+
+}