aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/edje/src/lib/edje_multisense.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/edje/src/lib/edje_multisense.c')
-rw-r--r--libraries/edje/src/lib/edje_multisense.c408
1 files changed, 408 insertions, 0 deletions
diff --git a/libraries/edje/src/lib/edje_multisense.c b/libraries/edje/src/lib/edje_multisense.c
new file mode 100644
index 0000000..f9c7f91
--- /dev/null
+++ b/libraries/edje/src/lib/edje_multisense.c
@@ -0,0 +1,408 @@
1#include "config.h"
2#include <string.h>
3#include <fcntl.h>
4#include <Eina.h>
5#include <Edje.h>
6#include "edje_private.h"
7
8typedef struct _Multisense_Data
9{
10 Edje_Multisense_Env *msenv;
11#ifdef HAVE_LIBREMIX
12 RemixDeck *deck;
13 RemixTrack *track;
14 RemixLayer *snd_layer, *player_layer;
15 RemixBase *player;
16 RemixBase *player_snd;
17 int remaining;
18 int offset;
19 Eina_List *snd_src_list;
20
21 MULTISENSE_SOUND_PLAYER_GET_FUNC multisense_sound_player_get;
22#endif
23}Multisense_Data;
24
25#define BUF_LEN 64
26#define SND_PROCESS_LENGTH 2048
27
28#ifdef HAVE_LIBREMIX
29static Ecore_Thread *player_thread = NULL;
30static int command_pipe[2];
31static Eina_Bool pipe_initialized = EINA_FALSE;
32#endif
33
34typedef enum _Edje_Sound_Action_Type
35{
36 EDJE_PLAY_SAMPLE = 0,
37 EDJE_PLAY_TONE,
38 /*
39 EDJE_PLAY_PATTERN,
40 EDJE_PLAY_INSTRUMENT,
41 EDJE_PLAY_SONG,
42 */
43 EDJE_SOUND_LAST
44} Edje_Sound_Action_Type;
45
46typedef struct _Edje_Sample_Action Edje_Sample_Action;
47typedef struct _Edje_Tone_Action Edje_Tone_Action;
48typedef struct _Edje_Multisense_Sound_Action Edje_Multisense_Sound_Action;
49
50struct _Edje_Sample_Action
51{
52 char sample_name[BUF_LEN];
53 double speed;
54};
55
56struct _Edje_Tone_Action
57{
58 char tone_name[BUF_LEN];
59 double duration;
60};
61
62struct _Edje_Multisense_Sound_Action
63{
64 Edje *ed;
65 Edje_Sound_Action_Type action;
66 union {
67 Edje_Sample_Action sample;
68 Edje_Tone_Action tone;
69 } type;
70};
71
72#ifdef HAVE_LIBREMIX
73static Multisense_Data *
74init_multisense_environment(void)
75{
76 Multisense_Data *msdata;
77 char ms_factory[BUF_LEN];
78 char *ms_factory_env;
79 Eina_Module *m = NULL;
80 MULTISENSE_FACTORY_INIT_FUNC multisense_factory_init;
81
82 msdata = calloc(1, sizeof(Multisense_Data));
83 if (!msdata) goto err;
84
85 msdata->msenv = calloc(1, sizeof(Edje_Multisense_Env));
86 if (!msdata->msenv) goto err;
87
88 ms_factory_env = getenv("MULTISENSE_FACTORY");
89 if (ms_factory_env)
90 strncpy(ms_factory, ms_factory_env, BUF_LEN);
91 else
92 strcpy(ms_factory, "multisense_factory");
93
94 m = _edje_module_handle_load(ms_factory);
95 if (!m) goto err;
96
97 msdata->msenv->remixenv = remix_init();
98
99 multisense_factory_init =
100 eina_module_symbol_get(m, "multisense_factory_init");
101 if (multisense_factory_init) multisense_factory_init(msdata->msenv);
102
103 msdata->multisense_sound_player_get =
104 eina_module_symbol_get(m, "multisense_sound_player_get");
105 if (!msdata->multisense_sound_player_get) goto err;
106
107 msdata->deck = remix_deck_new(msdata->msenv->remixenv);
108 msdata->track = remix_track_new(msdata->msenv->remixenv, msdata->deck);
109 msdata->snd_layer = remix_layer_new_ontop(msdata->msenv->remixenv,
110 msdata->track,
111 REMIX_TIME_SAMPLES);
112 msdata->player_layer = remix_layer_new_ontop(msdata->msenv->remixenv,
113 msdata->track,
114 REMIX_TIME_SAMPLES);
115 msdata->player = msdata->multisense_sound_player_get(msdata->msenv);
116 if (!msdata->player) goto err;
117 msdata->player_snd = remix_sound_new(msdata->msenv->remixenv,
118 msdata->player, msdata->player_layer,
119 REMIX_SAMPLES(0),
120 REMIX_SAMPLES(REMIX_COUNT_INFINITE));
121 return msdata;
122
123err:
124 if (msdata)
125 {
126 if (msdata->deck) remix_destroy(msdata->msenv->remixenv, msdata->deck);
127 if (msdata->msenv->remixenv) remix_purge(msdata->msenv->remixenv);
128 if (msdata->msenv) free(msdata->msenv);
129 free(msdata);
130 }
131 return NULL;
132}
133#endif
134
135#ifdef HAVE_LIBREMIX
136static RemixBase *
137eet_sound_reader_get(Edje_Multisense_Env *msenv, const char *path, const char *sound_id, const double speed)
138{
139 RemixPlugin *sf_plugin = NULL;
140 RemixBase * eet_snd_reader = NULL;
141 int sf_path_key = 0;
142 int sf_sound_id_key = 0;
143 int sf_speed_key = 0;
144 CDSet *sf_parms = NULL;
145 RemixEnv *env = msenv->remixenv;
146
147 if (sf_plugin == NULL)
148 {
149 sf_plugin = remix_find_plugin(env, "eet_sndfile_reader");
150 if (sf_plugin == NULL)
151 {
152 ERR ("Multisense EET Sound reader plugin NULL\n");
153 return NULL;
154 }
155
156 sf_path_key = remix_get_init_parameter_key(env, sf_plugin, "path");
157 sf_sound_id_key = remix_get_init_parameter_key(env, sf_plugin, "sound_id");
158 sf_speed_key = remix_get_init_parameter_key(env, sf_plugin, "speed");
159 }
160 sf_parms = cd_set_replace(env, sf_parms, sf_path_key, CD_STRING(path));
161 sf_parms = cd_set_replace(env, sf_parms, sf_sound_id_key, CD_STRING(sound_id));
162 sf_parms = cd_set_replace(env, sf_parms, sf_speed_key, CD_DOUBLE(speed));
163 eet_snd_reader = remix_new(env, sf_plugin, sf_parms);
164
165 return eet_snd_reader;
166}
167
168
169static RemixBase *
170edje_remix_sample_create(Multisense_Data *msdata, Edje*ed, Edje_Sample_Action *action)
171{
172 RemixBase *remix_snd = NULL;
173 Edje_Sound_Sample *sample;
174 int i;
175 char snd_id_str[16];
176
177 if ((!ed) || (!ed->file) || (!ed->file->sound_dir))
178 return NULL;
179
180 for (i = 0; i < (int)ed->file->sound_dir->samples_count; i++)
181 {
182 sample = &ed->file->sound_dir->samples[i];
183 if (!strcmp(sample->name, action->sample_name))
184 {
185 snprintf(snd_id_str, sizeof(snd_id_str), "edje/sounds/%i", sample->id);
186 remix_snd = eet_sound_reader_get(msdata->msenv, ed->file->path,
187 snd_id_str, action->speed);
188 break;
189 }
190 }
191 return remix_snd;
192}
193
194static RemixBase *
195edje_remix_tone_create(Multisense_Data *msdata, Edje*ed, Edje_Tone_Action *action)
196{
197 Edje_Sound_Tone *tone;
198 RemixSquareTone *square = NULL;
199 unsigned int i;
200
201 if ((!ed) || (!ed->file) || (!ed->file->sound_dir))
202 return NULL;
203
204 for (i = 0; i < ed->file->sound_dir->tones_count; i++)
205 {
206 tone = &ed->file->sound_dir->tones[i];
207 if (!strcmp(tone->name, action->tone_name))
208 {
209 square = remix_squaretone_new (msdata->msenv->remixenv, tone->value);
210 break;
211 }
212 }
213 return square;
214}
215
216static void
217sound_command_handler(Multisense_Data *msdata)
218{
219 RemixCount length;
220 Edje_Multisense_Sound_Action command;
221 RemixBase *base = NULL;
222 RemixBase *sound;
223
224 if (read(command_pipe[0], &command, sizeof(command)) <= 0) return;
225 switch (command.action)
226 {
227 case EDJE_PLAY_SAMPLE:
228 base = edje_remix_sample_create(msdata, command.ed,
229 &command.type.sample);
230 length = remix_length(msdata->msenv->remixenv, base);
231 break;
232 case EDJE_PLAY_TONE:
233 base = edje_remix_tone_create(msdata, command.ed, &command.type.tone);
234 length = (command.type.tone.duration *
235 remix_get_samplerate(msdata->msenv->remixenv));
236 break;
237 default:
238 ERR("Invalid Sound Play Command\n");
239 break;
240 }
241 if (base)
242 {
243 sound = remix_sound_new(msdata->msenv->remixenv, base, msdata->snd_layer,
244 REMIX_SAMPLES(msdata->offset),
245 REMIX_SAMPLES(length));
246 if (msdata->remaining < length) msdata->remaining = length;
247 msdata->snd_src_list = eina_list_append(msdata->snd_src_list, sound);
248 msdata->snd_src_list = eina_list_append(msdata->snd_src_list, base);
249 }
250}
251#endif
252
253#ifdef HAVE_LIBREMIX
254// msdata outside of thread due to thread issues in dlsym etc.
255static Multisense_Data *msdata = NULL;
256
257static void
258_msdata_free(void)
259{
260 // cleanup msdata outside of thread due to thread issues in dlsym etc.
261 if (!msdata) return;
262 //cleanup Remix stuffs
263 remix_destroy(msdata->msenv->remixenv, msdata->player);
264 remix_destroy(msdata->msenv->remixenv, msdata->deck);
265 remix_purge(msdata->msenv->remixenv);
266
267 free(msdata->msenv);
268 free(msdata);
269 msdata = NULL;
270}
271
272static void
273_player_job(void *data __UNUSED__, Ecore_Thread *th)
274{
275 fd_set wait_fds;
276 RemixBase *sound;
277 RemixCount process_len;
278// disable and move outside of thread due to dlsym etc. thread issues
279// Multisense_Data * msdata = init_multisense_environment();
280
281 if (!msdata) return;
282
283 fcntl(command_pipe[0], F_SETFL, O_NONBLOCK);
284 FD_ZERO(&wait_fds);
285 FD_SET(command_pipe[0], &wait_fds);
286
287 while (!ecore_thread_check(th))
288 {
289 if (!msdata->remaining)
290 {
291 //Cleanup already played sound sources
292 EINA_LIST_FREE(msdata->snd_src_list, sound)
293 {
294 remix_destroy(msdata->msenv->remixenv, sound);
295 }
296 //wait for new sound
297 select(command_pipe[0] + 1, &wait_fds, NULL, NULL, 0);
298 }
299 //read sound command , if any
300 sound_command_handler(msdata);
301 process_len = MIN(msdata->remaining, SND_PROCESS_LENGTH);
302 remix_process(msdata->msenv->remixenv, msdata->deck, process_len,
303 RemixNone, RemixNone);
304 msdata->offset += process_len;
305 msdata->remaining -= process_len;
306 }
307
308 //Cleanup last played sound sources
309 EINA_LIST_FREE(msdata->snd_src_list, sound)
310 {
311 remix_destroy(msdata->msenv->remixenv, sound);
312 }
313
314 close(command_pipe[0]);
315 close(command_pipe[1]);
316}
317#endif
318
319#ifdef HAVE_LIBREMIX
320static void
321_player_cancel(void *data __UNUSED__, Ecore_Thread *th __UNUSED__)
322{
323 // cleanup msdata outside of thread due to thread issues in dlsym etc.
324 _msdata_free();
325 player_thread = NULL;
326}
327#endif
328
329#ifdef HAVE_LIBREMIX
330static void
331_player_end(void *data __UNUSED__, Ecore_Thread *th __UNUSED__)
332{
333 // cleanup msdata outside of thread due to thread issues in dlsym etc.
334 _msdata_free();
335 player_thread = NULL;
336}
337#endif
338
339Eina_Bool
340_edje_multisense_internal_sound_sample_play(Edje *ed, const char *sample_name, const double speed)
341{
342 ssize_t size = 0;
343#ifdef ENABLE_MULTISENSE
344 Edje_Multisense_Sound_Action command;
345
346 if ((!pipe_initialized) && (!player_thread)) return EINA_FALSE;
347
348 command.action = EDJE_PLAY_SAMPLE;
349 command.ed = ed;
350 strncpy(command.type.sample.sample_name, sample_name, BUF_LEN);
351 command.type.sample.speed = speed;
352 size = write(command_pipe[1], &command, sizeof(command));
353#else
354 ed = NULL; // warning shh
355 if (speed > 0) sample_name = NULL; // warning shh
356#endif
357 return (size == sizeof(Edje_Multisense_Sound_Action));
358}
359
360Eina_Bool
361_edje_multisense_internal_sound_tone_play(Edje *ed, const char *tone_name, const double duration)
362{
363 ssize_t size = 0;
364#ifdef ENABLE_MULTISENSE
365 Edje_Multisense_Sound_Action command;
366
367 if ((!pipe_initialized) && (!player_thread)) return EINA_FALSE;
368 command.action = EDJE_PLAY_TONE;
369 command.ed = ed;
370 strncpy(command.type.tone.tone_name, tone_name, BUF_LEN);
371 command.type.tone.duration = duration;
372 size = write(command_pipe[1], &command, sizeof(command));
373#else
374 ed = NULL; // warning shh
375 if (duration > 0) tone_name = NULL; // warning shh
376#endif
377 return (size == sizeof(Edje_Multisense_Sound_Action));
378
379}
380
381/* Initialize the modules in main thread. to avoid dlopen issue in the Threads */
382void
383_edje_multisense_init(void)
384{
385#ifdef ENABLE_MULTISENSE
386 if (!pipe_initialized && (pipe(command_pipe) != -1))
387 pipe_initialized = EINA_TRUE;
388
389 // init msdata outside of thread due to thread issues in dlsym etc.
390 if (!msdata) msdata = init_multisense_environment();
391
392 if (!player_thread)
393 player_thread = ecore_thread_run(_player_job, _player_end, _player_cancel, NULL);
394#endif
395}
396
397void
398_edje_multisense_shutdown(void)
399{
400#ifdef ENABLE_MULTISENSE
401 if (pipe_initialized)
402 {
403 close(command_pipe[1]);
404 close(command_pipe[0]);
405 }
406 if (player_thread) ecore_thread_cancel(player_thread);
407#endif
408}