/* * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors * Copyright (C) 2004-2008 Kim Woelders * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of the Software, its documentation and marketing & publicity * materials, and acknowledgment shall be given in the documentation, materials * and software packages that this Software was used. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "E.h" #if HAVE_SOUND #include "dialog.h" #include "e16-ecore_list.h" #include "emodule.h" #include "settings.h" #include "sound.h" typedef struct { char *name; char *file; Sample *sample; } SoundClass; #define SC_NAME(sc) ((sc) ? (sc)->name : "(none)") static struct { char enable; char *theme; } Conf_sound; static Ecore_List *sound_list = NULL; #if USE_MODULES static const SoundOps *ops = NULL; #else #if defined(HAVE_SOUND_ESD) extern const SoundOps SoundOps_esd; static const SoundOps *ops = &SoundOps_esd; #endif #endif static void _SclassSampleDestroy(void *data, void *user_data __UNUSED__) { SoundClass *sclass = (SoundClass *) data; if (!sclass || !sclass->sample) return; if (ops) ops->SampleDestroy(sclass->sample); sclass->sample = NULL; } static SoundClass * SclassCreate(const char *name, const char *file) { SoundClass *sclass; sclass = EMALLOC(SoundClass, 1); if (!sclass) return NULL; if (!sound_list) sound_list = ecore_list_new(); ecore_list_prepend(sound_list, sclass); sclass->name = Estrdup(name); sclass->file = Estrdup(file); sclass->sample = NULL; return sclass; } static void SclassDestroy(SoundClass * sclass) { if (!sclass) return; ecore_list_node_remove(sound_list, sclass); _SclassSampleDestroy(sclass, NULL); Efree(sclass->name); Efree(sclass->file); Efree(sclass); } static void SclassApply(SoundClass * sclass) { if (!sclass || !Conf_sound.enable) return; if (!sclass->sample) { char *file; file = FindFile(sclass->file, Mode.theme.path, 0); if (file) { sclass->sample = ops->SampleLoad(file); Efree(file); } if (!sclass->sample) { DialogOK(_("Error finding sound file"), _("Warning! Enlightenment was unable to load the\n" "following sound file:\n%s\n" "Enlightenment will continue to operate, but you\n" "may wish to check your configuration settings.\n"), sclass->file); SclassDestroy(sclass); return; } } ops->SamplePlay(sclass->sample); } static int _SclassMatchName(const void *data, const void *match) { return strcmp(((const SoundClass *)data)->name, (const char *)match); } static SoundClass * SclassFind(const char *name) { return (SoundClass *) ecore_list_find(sound_list, _SclassMatchName, name); } void SoundPlay(const char *name) { SoundClass *sclass; if (!Conf_sound.enable) return; if (!name || !*name) return; sclass = SclassFind(name); if (EDebug(EDBUG_TYPE_SOUND)) Eprintf("%s: %s file=%s\n", "SclassApply", name, SC_NAME(sclass)); SclassApply(sclass); } static int SoundFree(const char *name) { SoundClass *sclass; sclass = SclassFind(name); SclassDestroy(sclass); return sclass != NULL; } static void SoundInit(void) { int err; if (!Conf_sound.enable) return; err = -1; #if USE_MODULES if (!ops) ops = ModLoadSym("sound", "SoundOps", "esd"); #endif if (ops && ops->Init) err = ops->Init(); if (err) { AlertX(_("Error initialising sound"), _("OK"), NULL, NULL, _("Audio was enabled for Enlightenment but there was an error\n" "communicating with the audio server (Esound). Audio will\n" "now be disabled.\n")); Conf_sound.enable = 0; } } static void SoundExit(void) { ecore_list_for_each(sound_list, _SclassSampleDestroy, NULL); if (ops) ops->Exit(); Conf_sound.enable = 0; } /* * Configuration load/save */ static int SoundConfigLoad(FILE * fs) { int err = 0; SoundClass *sc; char s[FILEPATH_LEN_MAX]; char s1[FILEPATH_LEN_MAX]; char s2[FILEPATH_LEN_MAX]; int i1, fields; while (GetLine(s, sizeof(s), fs)) { i1 = -1; fields = sscanf(s, "%d", &i1); if (fields == 1) /* Just skip the numeric config stuff */ continue; s1[0] = s2[0] = '\0'; fields = sscanf(s, "%4000s %4000s", s1, s2); if (fields != 2) { Eprintf("Ignoring line: %s\n", s); continue; } sc = SclassCreate(s1, s2); } if (err) ConfigAlertLoad("Sound"); return err; } /* * Sound module */ static void SoundSighan(int sig, void *prm __UNUSED__) { switch (sig) { case ESIGNAL_INIT: SoundInit(); break; case ESIGNAL_CONFIGURE: ConfigFileLoad("sound.cfg", Mode.theme.path, SoundConfigLoad, 1); break; case ESIGNAL_START: if (!Conf_sound.enable) break; SoundPlay("SOUND_STARTUP"); SoundFree("SOUND_STARTUP"); break; case ESIGNAL_EXIT: /* if (Mode.wm.master) */ SoundExit(); break; } } /* * Configuration dialog */ static char tmp_audio; static void CB_ConfigureAudio(Dialog * d __UNUSED__, int val, void *data __UNUSED__) { if (val < 2) { Conf_sound.enable = tmp_audio; if (Conf_sound.enable) SoundInit(); else SoundExit(); } autosave(); } static void _DlgFillSound(Dialog * d __UNUSED__, DItem * table, void *data __UNUSED__) { DItem *di; tmp_audio = Conf_sound.enable; DialogItemTableSetOptions(table, 2, 0, 0, 0); di = DialogAddItem(table, DITEM_CHECKBUTTON); DialogItemSetColSpan(di, 2); DialogItemSetText(di, _("Enable sounds")); DialogItemCheckButtonSetPtr(di, &tmp_audio); } const DialogDef DlgSound = { "CONFIGURE_AUDIO", N_("Sound"), N_("Audio Settings"), "SOUND_SETTINGS_AUDIO", "pix/sound.png", N_("Enlightenment Audio\n" "Settings Dialog\n"), _DlgFillSound, DLG_OAC, CB_ConfigureAudio, }; /* * IPC functions */ static void SoundIpc(const char *params) { const char *p; char cmd[128], prm[4096]; int len; SoundClass *sc; cmd[0] = prm[0] = '\0'; p = params; if (p) { len = 0; sscanf(p, "%100s %4000s %n", cmd, prm, &len); p += len; } if (!strncmp(cmd, "cfg", 3)) { DialogShowSimple(&DlgSound, NULL); } else if (!strncmp(cmd, "del", 3)) { SoundFree(prm); } else if (!strncmp(cmd, "list", 2)) { ECORE_LIST_FOR_EACH(sound_list, sc) IpcPrintf("%s\n", sc->name); } else if (!strncmp(cmd, "new", 3)) { SclassCreate(prm, p); } else if (!strncmp(cmd, "off", 2)) { SoundExit(); } else if (!strncmp(cmd, "on", 2)) { Conf_sound.enable = 1; SoundInit(); } else if (!strncmp(cmd, "play", 2)) { SoundPlay(prm); } } static const IpcItem SoundIpcArray[] = { { SoundIpc, "sound", "snd", "Sound functions", " sound add Create soundclass\n" " sound del Delete soundclass\n" " sound list Show all sounds\n" " sound off Disable sounds\n" " sound on Enable sounds\n" " sound play Play sounds\n"} }; #define N_IPC_FUNCS (sizeof(SoundIpcArray)/sizeof(IpcItem)) static const CfgItem SoundCfgItems[] = { CFG_ITEM_BOOL(Conf_sound, enable, 0), CFG_ITEM_STR(Conf_sound, theme), }; #define N_CFG_ITEMS (sizeof(SoundCfgItems)/sizeof(CfgItem)) /* * Module descriptor */ extern const EModule ModSound; const EModule ModSound = { "sound", "audio", SoundSighan, {N_IPC_FUNCS, SoundIpcArray}, {N_CFG_ITEMS, SoundCfgItems} }; #endif /* HAVE_SOUND */