diff options
Diffstat (limited to 'sound-theme-spec.c')
| -rw-r--r-- | sound-theme-spec.c | 280 | 
1 files changed, 280 insertions, 0 deletions
| 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); + + + + +} | 
