1 #include "edje_private.h"
3 typedef struct _Multisense_Data
5 Edje_Multisense_Env *msenv;
9 RemixLayer *snd_layer, *player_layer;
11 RemixBase *player_snd;
14 Eina_List *snd_src_list;
16 MULTISENSE_SOUND_PLAYER_GET_FUNC multisense_sound_player_get;
21 #define SND_PROCESS_LENGTH 2048
23 #ifdef ENABLE_MULTISENSE
24 static Ecore_Thread *player_thread = NULL;
25 static int command_pipe[2];
26 static Eina_Bool pipe_initialized = EINA_FALSE;
29 typedef enum _Edje_Sound_Action_Type
39 } Edje_Sound_Action_Type;
41 typedef struct _Edje_Sample_Action Edje_Sample_Action;
42 typedef struct _Edje_Tone_Action Edje_Tone_Action;
43 typedef struct _Edje_Multisense_Sound_Action Edje_Multisense_Sound_Action;
45 struct _Edje_Sample_Action
47 char sample_name[BUF_LEN];
51 struct _Edje_Tone_Action
53 char tone_name[BUF_LEN];
57 struct _Edje_Multisense_Sound_Action
60 Edje_Sound_Action_Type action;
62 Edje_Sample_Action sample;
63 Edje_Tone_Action tone;
67 #ifdef ENABLE_MULTISENSE
68 static Eina_Module *m = NULL;
69 static Multisense_Data *
70 init_multisense_environment(void)
72 Multisense_Data *msdata;
73 char ms_factory[BUF_LEN];
75 MULTISENSE_FACTORY_INIT_FUNC multisense_factory_init;
77 msdata = calloc(1, sizeof(Multisense_Data));
78 if (!msdata) goto err;
80 msdata->msenv = calloc(1, sizeof(Edje_Multisense_Env));
81 if (!msdata->msenv) goto err;
83 ms_factory_env = getenv("MULTISENSE_FACTORY");
85 strncpy(ms_factory, ms_factory_env, BUF_LEN);
87 strcpy(ms_factory, "multisense_factory");
89 m = _edje_module_handle_load(ms_factory);
92 msdata->msenv->remixenv = remix_init();
94 multisense_factory_init =
95 eina_module_symbol_get(m, "multisense_factory_init");
96 if (multisense_factory_init) multisense_factory_init(msdata->msenv);
98 msdata->multisense_sound_player_get =
99 eina_module_symbol_get(m, "multisense_sound_player_get");
100 if (!msdata->multisense_sound_player_get) goto err;
102 msdata->deck = remix_deck_new(msdata->msenv->remixenv);
103 msdata->track = remix_track_new(msdata->msenv->remixenv, msdata->deck);
104 msdata->snd_layer = remix_layer_new_ontop(msdata->msenv->remixenv,
107 msdata->player_layer = remix_layer_new_ontop(msdata->msenv->remixenv,
110 msdata->player = msdata->multisense_sound_player_get(msdata->msenv);
111 if (!msdata->player) goto err;
112 msdata->player_snd = remix_sound_new(msdata->msenv->remixenv,
113 msdata->player, msdata->player_layer,
115 REMIX_SAMPLES(REMIX_COUNT_INFINITE));
123 if (msdata->deck) remix_destroy(msdata->msenv->remixenv, msdata->deck);
124 if (msdata->msenv->remixenv) remix_purge(msdata->msenv->remixenv);
126 if (msdata->msenv) free(msdata->msenv);
133 #if defined(ENABLE_MULTISENSE) && defined(HAVE_LIBREMIX)
135 eet_sound_reader_get(Edje_Multisense_Env *msenv, const char *path,
136 const char *sound_id, const double speed)
138 RemixPlugin *sf_plugin = NULL;
139 RemixBase * eet_snd_reader = NULL;
141 int sf_sound_id_key = 0;
142 int sf_speed_key = 0;
143 CDSet *sf_parms = NULL;
144 RemixEnv *env = msenv->remixenv;
146 if (sf_plugin == NULL)
148 sf_plugin = remix_find_plugin(env, "eet_sndfile_reader");
149 if (sf_plugin == NULL)
151 ERR ("Multisense EET Sound reader plugin NULL\n");
155 sf_path_key = remix_get_init_parameter_key(env, sf_plugin, "path");
156 sf_sound_id_key = remix_get_init_parameter_key(env, sf_plugin, "sound_id");
157 sf_speed_key = remix_get_init_parameter_key(env, sf_plugin, "speed");
159 sf_parms = cd_set_replace(env, sf_parms, sf_path_key, CD_STRING(path));
160 sf_parms = cd_set_replace(env, sf_parms, sf_sound_id_key, CD_STRING(sound_id));
161 sf_parms = cd_set_replace(env, sf_parms, sf_speed_key, CD_DOUBLE(speed));
162 eet_snd_reader = remix_new(env, sf_plugin, sf_parms);
164 return eet_snd_reader;
168 edje_remix_sample_create(Multisense_Data *msdata, Edje_File *file, Edje_Sample_Action *action)
170 RemixBase *remix_snd = NULL;
171 Edje_Sound_Sample *sample;
175 if ((!file) || (!file->sound_dir))
178 for (i = 0; i < (int)file->sound_dir->samples_count; i++)
180 sample = &file->sound_dir->samples[i];
181 if (!strcmp(sample->name, action->sample_name))
183 snprintf(snd_id_str, sizeof(snd_id_str), "edje/sounds/%i", sample->id);
184 remix_snd = eet_sound_reader_get(msdata->msenv, file->path,
185 snd_id_str, action->speed);
193 edje_remix_tone_create(Multisense_Data *msdata, Edje_File *file, Edje_Tone_Action *action)
195 Edje_Sound_Tone *tone;
196 RemixSquareTone *square = NULL;
199 if ((!file) || (!file->sound_dir))
202 for (i = 0; i < file->sound_dir->tones_count; i++)
204 tone = &file->sound_dir->tones[i];
205 if (!strcmp(tone->name, action->tone_name))
207 square = remix_squaretone_new (msdata->msenv->remixenv, tone->value);
215 sound_command_handler(Multisense_Data *msdata)
218 Edje_Multisense_Sound_Action command;
219 RemixBase *base = NULL;
222 if (read(command_pipe[0], &command, sizeof(command)) <= 0) return;
223 switch (command.action)
225 case EDJE_PLAY_SAMPLE:
226 base = edje_remix_sample_create(msdata, command.snd_file,
227 &command.type.sample);
228 length = remix_length(msdata->msenv->remixenv, base);
229 remix_flush(msdata->msenv->remixenv, msdata->player);
232 base = edje_remix_tone_create(msdata, command.snd_file, &command.type.tone);
233 length = (command.type.tone.duration *
234 remix_get_samplerate(msdata->msenv->remixenv));
236 case EDJE_SOUND_LAST:
239 ERR("Invalid Sound Play Command\n");
244 sound = remix_sound_new(msdata->msenv->remixenv, base, msdata->snd_layer,
245 REMIX_SAMPLES(msdata->offset),
246 REMIX_SAMPLES(length));
247 if (msdata->remaining < length) msdata->remaining = length;
248 msdata->snd_src_list = eina_list_append(msdata->snd_src_list, sound);
249 msdata->snd_src_list = eina_list_append(msdata->snd_src_list, base);
254 #ifdef ENABLE_MULTISENSE
255 // msdata outside of thread due to thread issues in dlsym etc.
256 static Multisense_Data *msdata = NULL;
261 // cleanup msdata outside of thread due to thread issues in dlsym etc.
264 //cleanup Remix stuffs
265 remix_destroy(msdata->msenv->remixenv, msdata->player);
266 remix_destroy(msdata->msenv->remixenv, msdata->deck);
267 remix_purge(msdata->msenv->remixenv);
275 _player_job(void *data __UNUSED__, Ecore_Thread *th)
280 RemixCount process_len;
282 // disable and move outside of thread due to dlsym etc. thread issues
283 // Multisense_Data * msdata = init_multisense_environment();
287 fcntl(command_pipe[0], F_SETFL, O_NONBLOCK);
289 FD_SET(command_pipe[0], &wait_fds);
291 while (!ecore_thread_check(th))
294 if (!msdata->remaining)
297 //Cleanup already played sound sources
298 EINA_LIST_FREE(msdata->snd_src_list, sound)
300 remix_destroy(msdata->msenv->remixenv, sound);
303 err = select(command_pipe[0] + 1, &wait_fds, NULL, NULL, 0);
305 //read sound command , if any
306 sound_command_handler(msdata);
307 process_len = MIN(msdata->remaining, SND_PROCESS_LENGTH);
308 remix_process(msdata->msenv->remixenv, msdata->deck, process_len,
309 RemixNone, RemixNone);
310 msdata->offset += process_len;
311 msdata->remaining -= process_len;
316 //Cleanup last played sound sources
317 EINA_LIST_FREE(msdata->snd_src_list, sound)
319 remix_destroy(msdata->msenv->remixenv, sound);
323 player_thread = NULL;
324 close(command_pipe[0]);
325 close(command_pipe[1]);
330 _edje_multisense_internal_sound_sample_play(Edje *ed, const char *sample_name, const double speed)
333 #if defined(ENABLE_MULTISENSE) && defined(HAVE_LIBREMIX)
334 Edje_Multisense_Sound_Action command;
336 if ((!pipe_initialized) && (!player_thread)) return EINA_FALSE;
339 ERR("Given Sample Name is NULL\n");
343 command.action = EDJE_PLAY_SAMPLE;
344 command.snd_file = ed->file;
345 strncpy(command.type.sample.sample_name, sample_name, BUF_LEN);
346 command.type.sample.speed = speed;
347 size = write(command_pipe[1], &command, sizeof(command));
354 return (size == sizeof(Edje_Multisense_Sound_Action));
358 _edje_multisense_internal_sound_tone_play(Edje *ed, const char *tone_name, const double duration)
361 #if defined(ENABLE_MULTISENSE) && defined(HAVE_LIBREMIX)
362 Edje_Multisense_Sound_Action command;
364 if ((!pipe_initialized) && (!player_thread)) return EINA_FALSE;
367 ERR("Given Tone Name is NULL\n");
371 command.action = EDJE_PLAY_TONE;
372 command.snd_file = ed->file;
373 strncpy(command.type.tone.tone_name, tone_name, BUF_LEN);
374 command.type.tone.duration = duration;
375 size = write(command_pipe[1], &command, sizeof(command));
382 return (size == sizeof(Edje_Multisense_Sound_Action));
386 /* Initialize the modules in main thread. to avoid dlopen issue in the Threads */
388 _edje_multisense_init(void)
390 #ifdef ENABLE_MULTISENSE
391 if (!pipe_initialized && (pipe(command_pipe) != -1))
392 pipe_initialized = EINA_TRUE;
393 multisense_init = EINA_TRUE;
395 // init msdata outside of thread due to thread issues in dlsym etc.
396 if (!msdata) msdata = init_multisense_environment();
399 player_thread = ecore_thread_run(_player_job, NULL, NULL, NULL);
404 _edje_multisense_shutdown(void)
406 #ifdef ENABLE_MULTISENSE
407 Edje_Multisense_Sound_Action command;
408 MULTISENSE_FACTORY_SHUTDOWN_FUNC multisense_factory_shutdown;
410 if (m) multisense_factory_shutdown
411 = eina_module_symbol_get(m,"multisense_factory_shutdown");
412 if (multisense_factory_shutdown && msdata)
413 multisense_factory_shutdown(msdata->msenv);
414 if (player_thread) ecore_thread_cancel(player_thread);
415 if (pipe_initialized)
417 //unblock the select() in player worker thread
418 command.action = EDJE_SOUND_LAST;
419 write(command_pipe[1], &command, sizeof(command));