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
22 #define TIMEOUT_FOR_MM_HANDLER 10
24 #ifdef ENABLE_MULTISENSE
25 static Ecore_Thread *player_thread = NULL;
26 static int command_pipe[2];
27 static Eina_Bool pipe_initialized = EINA_FALSE;
28 static Ecore_Timer *idletimer = NULL;
31 typedef enum _Edje_Sound_Action_Type
42 } Edje_Sound_Action_Type;
44 typedef struct _Edje_Sample_Action Edje_Sample_Action;
45 typedef struct _Edje_Tone_Action Edje_Tone_Action;
46 typedef struct _Edje_Multisense_Sound_Action Edje_Multisense_Sound_Action;
48 struct _Edje_Sample_Action
50 char sample_name[BUF_LEN];
54 struct _Edje_Tone_Action
56 char tone_name[BUF_LEN];
60 struct _Edje_Multisense_Sound_Action
63 Edje_Sound_Action_Type action;
65 Edje_Sample_Action sample;
66 Edje_Tone_Action tone;
70 #ifdef ENABLE_MULTISENSE
71 static Eina_Module *m = NULL;
72 static Eina_Bool _edje_multisense_Timer_Callback(void *data);
75 edje_multisense_create_timer(void)
77 ecore_thread_main_loop_begin();
78 if (idletimer) ecore_timer_del(idletimer);
79 idletimer = ecore_timer_add(TIMEOUT_FOR_MM_HANDLER,
80 _edje_multisense_Timer_Callback, NULL);
82 ecore_thread_main_loop_end();
87 edje_multisense_kill_timer(void)
89 ecore_thread_main_loop_begin();
90 if (idletimer) ecore_timer_del(idletimer);
92 ecore_thread_main_loop_end();
97 _edje_multisense_Timer_Callback(void *data)
99 #if defined(ENABLE_MULTISENSE) && defined(HAVE_LIBREMIX)
101 Edje_Multisense_Sound_Action command = {0,};
103 if ((!pipe_initialized) && (!player_thread)) return ECORE_CALLBACK_CANCEL;
105 //post a command to handle mm sound cleanup
106 command.action = EDJE_CLOSE_HANDLE;
107 size = write(command_pipe[1], &command, sizeof(command));
110 return ECORE_CALLBACK_CANCEL;
113 static Multisense_Data *
114 init_multisense_environment(void)
116 Multisense_Data *msdata;
117 char ms_factory[BUF_LEN];
118 char *ms_factory_env;
119 MULTISENSE_FACTORY_INIT_FUNC multisense_factory_init;
121 msdata = calloc(1, sizeof(Multisense_Data));
122 if (!msdata) goto err;
124 msdata->msenv = calloc(1, sizeof(Edje_Multisense_Env));
125 if (!msdata->msenv) goto err;
127 ms_factory_env = getenv("MULTISENSE_FACTORY");
129 strncpy(ms_factory, ms_factory_env, BUF_LEN);
131 strcpy(ms_factory, "multisense_factory");
133 m = _edje_module_handle_load(ms_factory);
136 msdata->msenv->remixenv = remix_init();
138 multisense_factory_init =
139 eina_module_symbol_get(m, "multisense_factory_init");
140 if (multisense_factory_init) multisense_factory_init(msdata->msenv);
142 msdata->multisense_sound_player_get =
143 eina_module_symbol_get(m, "multisense_sound_player_get");
144 if (!msdata->multisense_sound_player_get) goto err;
146 msdata->deck = remix_deck_new(msdata->msenv->remixenv);
147 msdata->track = remix_track_new(msdata->msenv->remixenv, msdata->deck);
148 msdata->snd_layer = remix_layer_new_ontop(msdata->msenv->remixenv,
151 msdata->player_layer = remix_layer_new_ontop(msdata->msenv->remixenv,
154 msdata->player = msdata->multisense_sound_player_get(msdata->msenv);
155 if (!msdata->player) goto err;
156 msdata->player_snd = remix_sound_new(msdata->msenv->remixenv,
157 msdata->player, msdata->player_layer,
159 REMIX_SAMPLES(REMIX_COUNT_INFINITE));
167 if (msdata->deck) remix_destroy(msdata->msenv->remixenv, msdata->deck);
168 if (msdata->msenv->remixenv) remix_purge(msdata->msenv->remixenv);
170 if (msdata->msenv) free(msdata->msenv);
177 #if defined(ENABLE_MULTISENSE) && defined(HAVE_LIBREMIX)
179 eet_sound_reader_get(Edje_Multisense_Env *msenv, const char *path,
180 const char *sound_id, const double speed)
182 RemixPlugin *sf_plugin = NULL;
183 RemixBase * eet_snd_reader = NULL;
185 int sf_sound_id_key = 0;
186 int sf_speed_key = 0;
187 CDSet *sf_parms = NULL;
188 RemixEnv *env = msenv->remixenv;
190 if (sf_plugin == NULL)
192 sf_plugin = remix_find_plugin(env, "eet_sndfile_reader");
193 if (sf_plugin == NULL)
195 ERR ("Multisense EET Sound reader plugin NULL\n");
199 sf_path_key = remix_get_init_parameter_key(env, sf_plugin, "path");
200 sf_sound_id_key = remix_get_init_parameter_key(env, sf_plugin, "sound_id");
201 sf_speed_key = remix_get_init_parameter_key(env, sf_plugin, "speed");
203 sf_parms = cd_set_replace(env, sf_parms, sf_path_key, CD_STRING(path));
204 sf_parms = cd_set_replace(env, sf_parms, sf_sound_id_key, CD_STRING(sound_id));
205 sf_parms = cd_set_replace(env, sf_parms, sf_speed_key, CD_DOUBLE(speed));
206 eet_snd_reader = remix_new(env, sf_plugin, sf_parms);
208 //free the sf_parms as it is no more needed.
209 cd_set_free(env, sf_parms);
211 return eet_snd_reader;
215 edje_remix_sample_create(Multisense_Data *msdata, Edje_File *file, Edje_Sample_Action *action)
217 RemixBase *remix_snd = NULL;
218 Edje_Sound_Sample *sample;
222 if ((!file) || (!file->sound_dir))
225 for (i = 0; i < (int)file->sound_dir->samples_count; i++)
227 sample = &file->sound_dir->samples[i];
228 if (sample && !strcmp(sample->name, action->sample_name))
230 snprintf(snd_id_str, sizeof(snd_id_str), "edje/sounds/%i", sample->id);
231 remix_snd = eet_sound_reader_get(msdata->msenv, file->path,
232 snd_id_str, action->speed);
240 edje_remix_tone_create(Multisense_Data *msdata, Edje_File *file, Edje_Tone_Action *action)
242 Edje_Sound_Tone *tone;
243 RemixSquareTone *square = NULL;
246 if ((!file) || (!file->sound_dir))
249 for (i = 0; i < file->sound_dir->tones_count; i++)
251 tone = &file->sound_dir->tones[i];
252 if (tone && !strcmp(tone->name, action->tone_name))
254 square = remix_squaretone_new (msdata->msenv->remixenv, tone->value);
262 sound_command_handler(Multisense_Data *msdata)
265 Edje_Multisense_Sound_Action command = {0,};
266 RemixBase *base = NULL;
268 int read_len = sizeof(command);
270 //read and handle all samples to avoid queue effect
271 while(read(command_pipe[0], &command, sizeof(command)) == read_len)
273 switch (command.action)
275 case EDJE_PLAY_SAMPLE:
276 base = edje_remix_sample_create(msdata, command.snd_file,
277 &command.type.sample);
278 length = remix_length(msdata->msenv->remixenv, base);
279 edje_multisense_create_timer();
282 base = edje_remix_tone_create(msdata, command.snd_file, &command.type.tone);
283 length = (command.type.tone.duration *
284 remix_get_samplerate(msdata->msenv->remixenv));
286 case EDJE_CLOSE_HANDLE:
287 remix_reset(msdata->msenv->remixenv, msdata->player);
290 case EDJE_SOUND_LAST:
293 ERR("Invalid Sound Play Command\n");
298 sound = remix_sound_new(msdata->msenv->remixenv, base, msdata->snd_layer,
299 REMIX_SAMPLES(msdata->offset),
300 REMIX_SAMPLES(length));
301 if (msdata->remaining < length) msdata->remaining = length;
302 msdata->snd_src_list = eina_list_append(msdata->snd_src_list, sound);
303 msdata->snd_src_list = eina_list_append(msdata->snd_src_list, base);
309 #ifdef ENABLE_MULTISENSE
310 // msdata outside of thread due to thread issues in dlsym etc.
311 static Multisense_Data *msdata = NULL;
316 // cleanup msdata outside of thread due to thread issues in dlsym etc.
318 edje_multisense_kill_timer();
320 //cleanup Remix stuffs
321 remix_destroy(msdata->msenv->remixenv, msdata->player);
322 remix_destroy(msdata->msenv->remixenv, msdata->deck);
323 remix_purge(msdata->msenv->remixenv);
331 _player_job(void *data __UNUSED__, Ecore_Thread *th)
336 RemixCount process_len;
338 // disable and move outside of thread due to dlsym etc. thread issues
339 // Multisense_Data * msdata = init_multisense_environment();
343 fcntl(command_pipe[0], F_SETFL, O_NONBLOCK);
345 FD_SET(command_pipe[0], &wait_fds);
347 while (!ecore_thread_check(th))
350 if (!msdata->remaining)
353 //Cleanup already played sound sources
354 EINA_LIST_FREE(msdata->snd_src_list, sound)
356 remix_destroy(msdata->msenv->remixenv, sound);
359 err = select(command_pipe[0] + 1, &wait_fds, NULL, NULL, 0);
361 //read sound command , if any
362 sound_command_handler(msdata);
363 process_len = MIN(msdata->remaining, SND_PROCESS_LENGTH);
364 remix_process(msdata->msenv->remixenv, msdata->deck, process_len,
365 RemixNone, RemixNone);
366 msdata->offset += process_len;
367 msdata->remaining -= process_len;
372 //Cleanup last played sound sources
373 EINA_LIST_FREE(msdata->snd_src_list, sound)
375 remix_destroy(msdata->msenv->remixenv, sound);
379 player_thread = NULL;
380 close(command_pipe[0]);
381 close(command_pipe[1]);
386 _edje_multisense_internal_sound_sample_play(Edje *ed, const char *sample_name, const double speed)
389 #if defined(ENABLE_MULTISENSE) && defined(HAVE_LIBREMIX)
390 Edje_Multisense_Sound_Action command = {0,};
392 if ((!pipe_initialized) && (!player_thread)) return EINA_FALSE;
395 ERR("Given Sample Name is NULL\n");
399 command.action = EDJE_PLAY_SAMPLE;
400 command.snd_file = ed->file;
401 strncpy(command.type.sample.sample_name, sample_name, BUF_LEN);
402 command.type.sample.speed = speed;
403 size = write(command_pipe[1], &command, sizeof(command));
410 return (size == sizeof(Edje_Multisense_Sound_Action));
414 _edje_multisense_internal_sound_tone_play(Edje *ed, const char *tone_name, const double duration)
417 #if defined(ENABLE_MULTISENSE) && defined(HAVE_LIBREMIX)
418 Edje_Multisense_Sound_Action command = {0,};
420 if ((!pipe_initialized) && (!player_thread)) return EINA_FALSE;
423 ERR("Given Tone Name is NULL\n");
427 command.action = EDJE_PLAY_TONE;
428 command.snd_file = ed->file;
429 strncpy(command.type.tone.tone_name, tone_name, BUF_LEN);
430 command.type.tone.duration = duration;
431 size = write(command_pipe[1], &command, sizeof(command));
438 return (size == sizeof(Edje_Multisense_Sound_Action));
442 /* Initialize the modules in main thread. to avoid dlopen issue in the Threads */
444 _edje_multisense_init(void)
446 #ifdef ENABLE_MULTISENSE
447 if (!pipe_initialized && (pipe(command_pipe) != -1))
448 pipe_initialized = EINA_TRUE;
449 multisense_init = EINA_TRUE;
451 // init msdata outside of thread due to thread issues in dlsym etc.
452 if (!msdata) msdata = init_multisense_environment();
455 player_thread = ecore_thread_feedback_run(_player_job, NULL, NULL, NULL,
461 _edje_multisense_shutdown(void)
463 #ifdef ENABLE_MULTISENSE
464 Edje_Multisense_Sound_Action command = {0,};
465 MULTISENSE_FACTORY_SHUTDOWN_FUNC multisense_factory_shutdown;
467 if (m) multisense_factory_shutdown
468 = eina_module_symbol_get(m,"multisense_factory_shutdown");
469 if (multisense_factory_shutdown && msdata)
470 multisense_factory_shutdown(msdata->msenv);
471 if (player_thread) ecore_thread_cancel(player_thread);
472 if (pipe_initialized)
474 //unblock the select() in player worker thread
475 command.action = EDJE_SOUND_LAST;
476 write(command_pipe[1], &command, sizeof(command));