2 * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
3 * Copyright (C) 2004-2009 Kim Woelders
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to
7 * deal in the Software without restriction, including without limitation the
8 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 * sell copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies of the Software, its documentation and marketing & publicity
14 * materials, and acknowledgment shall be given in the documentation, materials
15 * and software packages that this Software was used.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 #include "e16-ecore_list.h"
34 #define SOUND_SERVER_NAME "esd"
36 #define SOUND_SERVER_NAME "pulseaudio"
38 #error Invalid sound configuration
41 #define N_SOUNDS (SOUND_NOT_USED - 1)
49 #define SC_NAME(sc) ((sc) ? (sc)->name : "(none)")
54 unsigned int mask1, mask2;
62 #define SOUND_THEME_PATH ((Mode_sound.theme_path) ? Mode_sound.theme_path : Mode.theme.path)
64 static Ecore_List *sound_list = NULL;
67 static const SoundOps *ops = NULL;
70 extern const SoundOps SoundOps_esd;
71 static const SoundOps *ops = &SoundOps_esd;
73 extern const SoundOps SoundOps_pa;
74 static const SoundOps *ops = &SoundOps_pa;
78 static void _SoundConfigLoad(void);
80 static const char *const sound_names[N_SOUNDS] = {
81 "SOUND_ALERT", /* 0 0x00000001 */
85 "SOUND_DESKTOP_LOWER", /* 4 0x00000010 */
86 "SOUND_DESKTOP_RAISE",
89 "SOUND_EXIT", /* 8 0x00000100 */
93 "SOUND_LOGOUT", /* 12 0x00001000 */
96 "SOUND_MOVE_AREA_DOWN",
97 "SOUND_MOVE_AREA_LEFT", /* 16 0x00010000 */
98 "SOUND_MOVE_AREA_RIGHT",
101 "SOUND_MOVE_START", /* 20 0x00100000 */
104 "SOUND_RESIZE_START",
105 "SOUND_RESIZE_STOP", /* 24 0x01000000 */
107 "SOUND_SETTINGS_ACTIVE",
108 "SOUND_SETTINGS_ALL",
109 "SOUND_SETTINGS_AREA", /* 28 0x10000000 */
110 "SOUND_SETTINGS_AUDIO",
111 "SOUND_SETTINGS_AUTORAISE",
113 "SOUND_SETTINGS_COMPOSITE", /* 0 0x00000001 */
114 "SOUND_SETTINGS_DESKTOPS",
115 "SOUND_SETTINGS_FOCUS",
117 "SOUND_SETTINGS_GROUP", /* 4 0x00000010 */
118 "SOUND_SETTINGS_ICONBOX",
119 "SOUND_SETTINGS_MENUS",
120 "SOUND_SETTINGS_MISCELLANEOUS",
121 "SOUND_SETTINGS_MOVERESIZE", /* 8 0x00000100 */
122 "SOUND_SETTINGS_PAGER",
123 "SOUND_SETTINGS_PLACEMENT",
124 "SOUND_SETTINGS_SESSION",
125 "SOUND_SETTINGS_TOOLTIPS", /* 12 0x00001000 */
126 "SOUND_SETTINGS_TRANS",
128 "SOUND_SLIDEOUT_SHOW",
129 "SOUND_STARTUP", /* 16 0x00010000 */
132 "SOUND_WINDOW_BORDER_CHANGE",
133 "SOUND_WINDOW_CHANGE_LAYER_DOWN", /* 20 0x00100000 */
134 "SOUND_WINDOW_CHANGE_LAYER_UP",
135 "SOUND_WINDOW_CLOSE",
136 "SOUND_WINDOW_SLIDE",
137 "SOUND_WINDOW_SLIDE_END", /* 24 0x01000000 */
138 "SOUND_WINDOW_STICK",
139 "SOUND_WINDOW_UNSTICK",
143 _SclassSampleDestroy(void *data, void *user_data __UNUSED__)
145 SoundClass *sclass = (SoundClass *) data;
147 if (!sclass || !sclass->sample)
151 ops->SampleDestroy(sclass->sample);
152 sclass->sample = NULL;
156 SclassCreate(const char *name, const char *file)
160 sclass = EMALLOC(SoundClass, 1);
165 sound_list = ecore_list_new();
166 ecore_list_prepend(sound_list, sclass);
168 sclass->name = Estrdup(name);
169 sclass->file = Estrdup(file);
170 sclass->sample = NULL;
176 SclassDestroy(SoundClass * sclass)
181 ecore_list_node_remove(sound_list, sclass);
182 _SclassSampleDestroy(sclass, NULL);
190 _SclassDestroy(void *data, void *user_data __UNUSED__)
192 SclassDestroy((SoundClass *) data);
196 SclassApply(SoundClass * sclass)
198 if (!sclass || !Conf_sound.enable)
205 file = FindFile(sclass->file, SOUND_THEME_PATH);
208 sclass->sample = ops->SampleLoad(file);
213 DialogOK(_("Error finding sound file"),
214 _("Warning! Enlightenment was unable to load the\n"
215 "following sound file:\n%s\n"
216 "Enlightenment will continue to operate, but you\n"
217 "may wish to check your configuration settings.\n"),
219 SclassDestroy(sclass);
224 ops->SamplePlay(sclass->sample);
228 _SclassMatchName(const void *data, const void *match)
230 return strcmp(((const SoundClass *)data)->name, (const char *)match);
234 SclassFind(const char *name)
236 return (SoundClass *) ecore_list_find(sound_list, _SclassMatchName, name);
240 _SoundPlayByName(const char *name)
244 if (!Conf_sound.enable)
250 sclass = SclassFind(name);
252 if (EDebug(EDBUG_TYPE_SOUND))
253 Eprintf("%s: %s file=%s\n", "SclassApply", name, SC_NAME(sclass));
258 #define _SoundMasked(i) \
259 (((i) <= 32) ? Conf_sound.mask1 & (1 << ((i) - 1)) : \
260 Conf_sound.mask2 & (1 << ((i) - 1)))
264 if (!Conf_sound.enable)
267 if (sound <= 0 || sound > N_SOUNDS)
270 if (_SoundMasked(sound))
273 _SoundPlayByName(sound_names[sound - 1]);
277 SoundFree(const char *name)
281 sclass = SclassFind(name);
282 SclassDestroy(sclass);
284 return sclass != NULL;
292 if (!Conf_sound.enable)
299 ops = ModLoadSym("sound", "SoundOps", "esd");
301 ops = ModLoadSym("sound", "SoundOps", "pa");
304 if (ops && ops->Init)
309 Conf_sound.enable = 0;
310 AlertX(_("Error initialising sound"), _("OK"), NULL, NULL,
311 _("Audio was enabled for Enlightenment but there was an error\n"
312 "communicating with the audio server (%s).\n"
313 "Audio will now be disabled.\n"), SOUND_SERVER_NAME);
322 ecore_list_for_each(sound_list, _SclassSampleDestroy, NULL);
327 Conf_sound.enable = 0;
331 * Configuration load/save
335 _SoundConfigParse(FILE * fs)
339 char s[FILEPATH_LEN_MAX];
340 char s1[FILEPATH_LEN_MAX];
341 char s2[FILEPATH_LEN_MAX];
344 while (GetLine(s, sizeof(s), fs))
347 fields = sscanf(s, "%d", &i1);
348 if (fields == 1) /* Just skip the numeric config stuff */
351 s1[0] = s2[0] = '\0';
352 fields = sscanf(s, "%4000s %4000s", s1, s2);
355 Eprintf("*** Ignoring line: %s\n", s);
358 sc = SclassCreate(s1, s2);
360 #if 0 /* Errors here are just ignored */
362 ConfigAlertLoad("Sound");
369 _SoundConfigLoad(void)
371 if (Mode_sound.cfg_loaded)
373 Mode_sound.cfg_loaded = 1;
375 Efree(Mode_sound.theme_path);
376 if (Conf_sound.theme)
377 Mode_sound.theme_path = ThemeFind(Conf_sound.theme);
379 Mode_sound.theme_path = NULL;
381 ConfigFileLoad("sound.cfg", SOUND_THEME_PATH, _SoundConfigParse, 1);
385 _SoundConfigUnload(void)
387 ecore_list_for_each(sound_list, _SclassDestroy, NULL);
388 Mode_sound.cfg_loaded = 0;
392 _SoundThemeChange(void *item __UNUSED__, const char *theme)
396 _SoundConfigUnload();
397 _EFDUP(Conf_sound.theme, theme);
406 SoundSighan(int sig, void *prm __UNUSED__)
411 memset(&Mode_sound, 0, sizeof(Mode_sound));
413 case ESIGNAL_CONFIGURE:
417 if (!Conf_sound.enable)
419 SoundPlay(SOUND_STARTUP);
420 SoundFree("SOUND_STARTUP");
423 /* if (Mode.wm.master) */
431 * Configuration dialog
433 static char tmp_audio;
436 CB_ConfigureAudio(Dialog * d __UNUSED__, int val, void *data __UNUSED__)
440 Conf_sound.enable = tmp_audio;
441 if (Conf_sound.enable)
450 _DlgFillSound(Dialog * d __UNUSED__, DItem * table, void *data __UNUSED__)
454 tmp_audio = Conf_sound.enable;
456 DialogItemTableSetOptions(table, 2, 0, 0, 0);
458 di = DialogAddItem(table, DITEM_CHECKBUTTON);
459 DialogItemSetColSpan(di, 2);
460 DialogItemSetText(di, _("Enable sounds"));
461 DialogItemCheckButtonSetPtr(di, &tmp_audio);
464 const DialogDef DlgSound = {
467 N_("Audio Settings"),
468 SOUND_SETTINGS_AUDIO,
470 N_("Enlightenment Audio\n" "Settings Dialog\n"),
472 DLG_OAC, CB_ConfigureAudio,
474 #endif /* ENABLE_DIALOGS */
481 SoundIpc(const char *params)
484 char cmd[128], prm[4096];
488 cmd[0] = prm[0] = '\0';
493 sscanf(p, "%100s %4000s %n", cmd, prm, &len);
497 if (!strncmp(cmd, "del", 3))
501 else if (!strncmp(cmd, "list", 2))
503 ECORE_LIST_FOR_EACH(sound_list, sc) IpcPrintf("%s\n", sc->name);
505 else if (!strncmp(cmd, "new", 3))
507 SclassCreate(prm, p);
509 else if (!strncmp(cmd, "off", 2))
514 else if (!strncmp(cmd, "on", 2))
516 Conf_sound.enable = 1;
520 else if (!strncmp(cmd, "play", 2))
522 _SoundPlayByName(prm);
526 static const IpcItem SoundIpcArray[] = {
531 " sound add <classname> <filename> Create soundclass\n"
532 " sound del <classname> Delete soundclass\n"
533 " sound list Show all sounds\n"
534 " sound off Disable sounds\n"
535 " sound on Enable sounds\n"
536 " sound play <classname> Play sounds\n"}
538 #define N_IPC_FUNCS (sizeof(SoundIpcArray)/sizeof(IpcItem))
540 static const CfgItem SoundCfgItems[] = {
541 CFG_ITEM_BOOL(Conf_sound, enable, 0),
542 CFG_FUNC_STR(Conf_sound, theme, _SoundThemeChange),
543 CFG_ITEM_HEX(Conf_sound, mask1, 0),
544 CFG_ITEM_HEX(Conf_sound, mask2, 0),
546 #define N_CFG_ITEMS (sizeof(SoundCfgItems)/sizeof(CfgItem))
551 extern const EModule ModSound;
552 const EModule ModSound = {
555 {N_IPC_FUNCS, SoundIpcArray},
556 {N_CFG_ITEMS, SoundCfgItems}
559 #endif /* HAVE_SOUND */