forked from enlightenment/efl
edje-multisense: Replace sound handling with ecore_audio
The speed keyword is not yet implemented. Signed-off-by: Daniel Willmann <d.willmann@samsung.com> SVN revision: 83380
This commit is contained in:
parent
5df48569c8
commit
e069b829bf
|
@ -1,391 +1,176 @@
|
|||
#include "edje_private.h"
|
||||
#include "Ecore_Audio.h"
|
||||
#include <sndfile.h>
|
||||
|
||||
typedef struct _Multisense_Data
|
||||
static Ecore_Audio_Object *out = NULL;
|
||||
|
||||
static Eina_Bool _play_finished(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
|
||||
{
|
||||
Edje_Multisense_Env *msenv;
|
||||
#ifdef HAVE_LIBREMIX
|
||||
RemixDeck *deck;
|
||||
RemixTrack *track;
|
||||
RemixLayer *snd_layer, *player_layer;
|
||||
RemixBase *player;
|
||||
RemixBase *player_snd;
|
||||
int remaining;
|
||||
int offset;
|
||||
Eina_List *snd_src_list;
|
||||
Ecore_Audio_Object *in = (Ecore_Audio_Object *)event;
|
||||
ecore_audio_input_del(in);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
MULTISENSE_SOUND_PLAYER_GET_FUNC multisense_sound_player_get;
|
||||
#endif
|
||||
}Multisense_Data;
|
||||
|
||||
#define BUF_LEN 64
|
||||
#define SND_PROCESS_LENGTH 2048
|
||||
|
||||
#ifdef HAVE_LIBREMIX
|
||||
static Ecore_Thread *player_thread = NULL;
|
||||
static int command_pipe[2];
|
||||
static Eina_Bool pipe_initialized = EINA_FALSE;
|
||||
#endif
|
||||
|
||||
typedef enum _Edje_Sound_Action_Type
|
||||
struct _edje_multisense_eet_data
|
||||
{
|
||||
EDJE_PLAY_SAMPLE = 0,
|
||||
EDJE_PLAY_TONE,
|
||||
/*
|
||||
EDJE_PLAY_PATTERN,
|
||||
EDJE_PLAY_INSTRUMENT,
|
||||
EDJE_PLAY_SONG,
|
||||
*/
|
||||
EDJE_SOUND_LAST
|
||||
} Edje_Sound_Action_Type;
|
||||
|
||||
typedef struct _Edje_Sample_Action Edje_Sample_Action;
|
||||
typedef struct _Edje_Tone_Action Edje_Tone_Action;
|
||||
typedef struct _Edje_Multisense_Sound_Action Edje_Multisense_Sound_Action;
|
||||
|
||||
struct _Edje_Sample_Action
|
||||
{
|
||||
char sample_name[BUF_LEN];
|
||||
double speed;
|
||||
sf_count_t offset, length;
|
||||
const char *data;
|
||||
Ecore_Audio_Vio vio;
|
||||
};
|
||||
|
||||
struct _Edje_Tone_Action
|
||||
static int
|
||||
eet_snd_file_get_length(Ecore_Audio_Object *in)
|
||||
{
|
||||
char tone_name[BUF_LEN];
|
||||
double duration;
|
||||
};
|
||||
|
||||
struct _Edje_Multisense_Sound_Action
|
||||
{
|
||||
Edje *ed;
|
||||
Edje_Sound_Action_Type action;
|
||||
union {
|
||||
Edje_Sample_Action sample;
|
||||
Edje_Tone_Action tone;
|
||||
} type;
|
||||
};
|
||||
|
||||
#ifdef HAVE_LIBREMIX
|
||||
static Multisense_Data *
|
||||
init_multisense_environment(void)
|
||||
{
|
||||
Multisense_Data *msdata;
|
||||
char ms_factory[BUF_LEN];
|
||||
char *ms_factory_env;
|
||||
Eina_Module *m = NULL;
|
||||
MULTISENSE_FACTORY_INIT_FUNC multisense_factory_init;
|
||||
|
||||
msdata = calloc(1, sizeof(Multisense_Data));
|
||||
if (!msdata) goto err;
|
||||
|
||||
msdata->msenv = calloc(1, sizeof(Edje_Multisense_Env));
|
||||
if (!msdata->msenv) goto err;
|
||||
|
||||
ms_factory_env = getenv("MULTISENSE_FACTORY");
|
||||
if (ms_factory_env)
|
||||
strncpy(ms_factory, ms_factory_env, BUF_LEN);
|
||||
else
|
||||
strcpy(ms_factory, "multisense_factory");
|
||||
|
||||
m = _edje_module_handle_load(ms_factory);
|
||||
if (!m) goto err;
|
||||
|
||||
msdata->msenv->remixenv = remix_init();
|
||||
|
||||
multisense_factory_init =
|
||||
eina_module_symbol_get(m, "multisense_factory_init");
|
||||
if (multisense_factory_init) multisense_factory_init(msdata->msenv);
|
||||
|
||||
msdata->multisense_sound_player_get =
|
||||
eina_module_symbol_get(m, "multisense_sound_player_get");
|
||||
if (!msdata->multisense_sound_player_get) goto err;
|
||||
|
||||
msdata->deck = remix_deck_new(msdata->msenv->remixenv);
|
||||
msdata->track = remix_track_new(msdata->msenv->remixenv, msdata->deck);
|
||||
msdata->snd_layer = remix_layer_new_ontop(msdata->msenv->remixenv,
|
||||
msdata->track,
|
||||
REMIX_TIME_SAMPLES);
|
||||
msdata->player_layer = remix_layer_new_ontop(msdata->msenv->remixenv,
|
||||
msdata->track,
|
||||
REMIX_TIME_SAMPLES);
|
||||
msdata->player = msdata->multisense_sound_player_get(msdata->msenv);
|
||||
if (!msdata->player) goto err;
|
||||
msdata->player_snd = remix_sound_new(msdata->msenv->remixenv,
|
||||
msdata->player, msdata->player_layer,
|
||||
REMIX_SAMPLES(0),
|
||||
REMIX_SAMPLES(REMIX_COUNT_INFINITE));
|
||||
return msdata;
|
||||
|
||||
err:
|
||||
if (msdata)
|
||||
{
|
||||
if (msdata->deck) remix_destroy(msdata->msenv->remixenv, msdata->deck);
|
||||
if (msdata->msenv->remixenv) remix_purge(msdata->msenv->remixenv);
|
||||
if (msdata->msenv) free(msdata->msenv);
|
||||
free(msdata);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBREMIX
|
||||
static RemixBase *
|
||||
eet_sound_reader_get(Edje_Multisense_Env *msenv, const char *path, const char *sound_id, const double speed)
|
||||
{
|
||||
RemixPlugin *sf_plugin = NULL;
|
||||
RemixBase * eet_snd_reader = NULL;
|
||||
int sf_path_key = 0;
|
||||
int sf_sound_id_key = 0;
|
||||
int sf_speed_key = 0;
|
||||
CDSet *sf_parms = NULL;
|
||||
RemixEnv *env = msenv->remixenv;
|
||||
|
||||
if (sf_plugin == NULL)
|
||||
{
|
||||
sf_plugin = remix_find_plugin(env, "eet_sndfile_reader");
|
||||
if (sf_plugin == NULL)
|
||||
{
|
||||
ERR ("Multisense EET Sound reader plugin NULL\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sf_path_key = remix_get_init_parameter_key(env, sf_plugin, "path");
|
||||
sf_sound_id_key = remix_get_init_parameter_key(env, sf_plugin, "sound_id");
|
||||
sf_speed_key = remix_get_init_parameter_key(env, sf_plugin, "speed");
|
||||
}
|
||||
sf_parms = cd_set_replace(env, sf_parms, sf_path_key, CD_STRING(path));
|
||||
sf_parms = cd_set_replace(env, sf_parms, sf_sound_id_key, CD_STRING(sound_id));
|
||||
sf_parms = cd_set_replace(env, sf_parms, sf_speed_key, CD_DOUBLE(speed));
|
||||
eet_snd_reader = remix_new(env, sf_plugin, sf_parms);
|
||||
|
||||
return eet_snd_reader;
|
||||
struct _edje_multisense_eet_data *vf = ecore_audio_input_userdata_get(in);
|
||||
return vf->length;
|
||||
}
|
||||
|
||||
|
||||
static RemixBase *
|
||||
edje_remix_sample_create(Multisense_Data *msdata, Edje*ed, Edje_Sample_Action *action)
|
||||
static int
|
||||
eet_snd_file_seek(Ecore_Audio_Object *in, int offset, int whence)
|
||||
{
|
||||
RemixBase *remix_snd = NULL;
|
||||
Edje_Sound_Sample *sample;
|
||||
int i;
|
||||
char snd_id_str[16];
|
||||
struct _edje_multisense_eet_data *vf = ecore_audio_input_userdata_get(in);
|
||||
|
||||
if ((!ed) || (!ed->file) || (!ed->file->sound_dir))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < (int)ed->file->sound_dir->samples_count; i++)
|
||||
{
|
||||
sample = &ed->file->sound_dir->samples[i];
|
||||
if (!strcmp(sample->name, action->sample_name))
|
||||
{
|
||||
snprintf(snd_id_str, sizeof(snd_id_str), "edje/sounds/%i", sample->id);
|
||||
remix_snd = eet_sound_reader_get(msdata->msenv, ed->file->path,
|
||||
snd_id_str, action->speed);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return remix_snd;
|
||||
}
|
||||
|
||||
static RemixBase *
|
||||
edje_remix_tone_create(Multisense_Data *msdata, Edje*ed, Edje_Tone_Action *action)
|
||||
{
|
||||
Edje_Sound_Tone *tone;
|
||||
RemixSquareTone *square = NULL;
|
||||
unsigned int i;
|
||||
|
||||
if ((!ed) || (!ed->file) || (!ed->file->sound_dir))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < ed->file->sound_dir->tones_count; i++)
|
||||
{
|
||||
tone = &ed->file->sound_dir->tones[i];
|
||||
if (!strcmp(tone->name, action->tone_name))
|
||||
{
|
||||
square = remix_squaretone_new (msdata->msenv->remixenv, tone->value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return square;
|
||||
}
|
||||
|
||||
static void
|
||||
sound_command_handler(Multisense_Data *msdata)
|
||||
{
|
||||
RemixCount length;
|
||||
Edje_Multisense_Sound_Action command;
|
||||
RemixBase *base = NULL;
|
||||
RemixBase *sound;
|
||||
|
||||
if (read(command_pipe[0], &command, sizeof(command)) <= 0) return;
|
||||
switch (command.action)
|
||||
{
|
||||
case EDJE_PLAY_SAMPLE:
|
||||
base = edje_remix_sample_create(msdata, command.ed,
|
||||
&command.type.sample);
|
||||
length = remix_length(msdata->msenv->remixenv, base);
|
||||
switch (whence)
|
||||
{
|
||||
case SEEK_SET:
|
||||
vf->offset = offset;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
vf->offset += offset;
|
||||
break;
|
||||
case EDJE_PLAY_TONE:
|
||||
base = edje_remix_tone_create(msdata, command.ed, &command.type.tone);
|
||||
length = (command.type.tone.duration *
|
||||
remix_get_samplerate(msdata->msenv->remixenv));
|
||||
break;
|
||||
default:
|
||||
ERR("Invalid Sound Play Command\n");
|
||||
break;
|
||||
}
|
||||
if (base)
|
||||
{
|
||||
sound = remix_sound_new(msdata->msenv->remixenv, base, msdata->snd_layer,
|
||||
REMIX_SAMPLES(msdata->offset),
|
||||
REMIX_SAMPLES(length));
|
||||
if (msdata->remaining < length) msdata->remaining = length;
|
||||
msdata->snd_src_list = eina_list_append(msdata->snd_src_list, sound);
|
||||
msdata->snd_src_list = eina_list_append(msdata->snd_src_list, base);
|
||||
}
|
||||
case SEEK_END:
|
||||
vf->offset = vf->length + offset;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return vf->offset;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBREMIX
|
||||
// msdata outside of thread due to thread issues in dlsym etc.
|
||||
static Multisense_Data *msdata = NULL;
|
||||
|
||||
static void
|
||||
_msdata_free(void)
|
||||
static int
|
||||
eet_snd_file_read(Ecore_Audio_Object *in, void *buffer, int count)
|
||||
{
|
||||
// cleanup msdata outside of thread due to thread issues in dlsym etc.
|
||||
if (!msdata) return;
|
||||
//cleanup Remix stuffs
|
||||
remix_destroy(msdata->msenv->remixenv, msdata->player);
|
||||
remix_destroy(msdata->msenv->remixenv, msdata->deck);
|
||||
remix_purge(msdata->msenv->remixenv);
|
||||
struct _edje_multisense_eet_data *vf = ecore_audio_input_userdata_get(in);
|
||||
|
||||
free(msdata->msenv);
|
||||
free(msdata);
|
||||
msdata = NULL;
|
||||
if ((vf->offset + count) > vf->length)
|
||||
count = vf->length - vf->offset;
|
||||
memcpy(buffer, vf->data + vf->offset, count);
|
||||
vf->offset += count;
|
||||
return count;
|
||||
}
|
||||
|
||||
static void
|
||||
_player_job(void *data EINA_UNUSED, Ecore_Thread *th)
|
||||
static int
|
||||
eet_snd_file_tell(Ecore_Audio_Object *in)
|
||||
{
|
||||
fd_set wait_fds;
|
||||
RemixBase *sound;
|
||||
RemixCount process_len;
|
||||
// disable and move outside of thread due to dlsym etc. thread issues
|
||||
// Multisense_Data * msdata = init_multisense_environment();
|
||||
struct _edje_multisense_eet_data *vf = ecore_audio_input_userdata_get(in);
|
||||
|
||||
if (!msdata) return;
|
||||
|
||||
fcntl(command_pipe[0], F_SETFL, O_NONBLOCK);
|
||||
FD_ZERO(&wait_fds);
|
||||
FD_SET(command_pipe[0], &wait_fds);
|
||||
|
||||
while (!ecore_thread_check(th))
|
||||
{
|
||||
if (!msdata->remaining)
|
||||
{
|
||||
int err;
|
||||
|
||||
//Cleanup already played sound sources
|
||||
EINA_LIST_FREE(msdata->snd_src_list, sound)
|
||||
{
|
||||
remix_destroy(msdata->msenv->remixenv, sound);
|
||||
}
|
||||
//wait for new sound
|
||||
err = select(command_pipe[0] + 1, &wait_fds, NULL, NULL, 0);
|
||||
if (ecore_thread_check(th))
|
||||
break;
|
||||
}
|
||||
//read sound command , if any
|
||||
sound_command_handler(msdata);
|
||||
process_len = MIN(msdata->remaining, SND_PROCESS_LENGTH);
|
||||
remix_process(msdata->msenv->remixenv, msdata->deck, process_len,
|
||||
RemixNone, RemixNone);
|
||||
msdata->offset += process_len;
|
||||
msdata->remaining -= process_len;
|
||||
}
|
||||
|
||||
//Cleanup last played sound sources
|
||||
EINA_LIST_FREE(msdata->snd_src_list, sound)
|
||||
{
|
||||
remix_destroy(msdata->msenv->remixenv, sound);
|
||||
}
|
||||
return vf->offset;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBREMIX
|
||||
static void
|
||||
_player_cancel(void *data EINA_UNUSED, Ecore_Thread *th EINA_UNUSED)
|
||||
{
|
||||
// cleanup msdata outside of thread due to thread issues in dlsym etc.
|
||||
_msdata_free();
|
||||
player_thread = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBREMIX
|
||||
static void
|
||||
_player_end(void *data EINA_UNUSED, Ecore_Thread *th EINA_UNUSED)
|
||||
{
|
||||
// cleanup msdata outside of thread due to thread issues in dlsym etc.
|
||||
_msdata_free();
|
||||
player_thread = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
Eina_Bool
|
||||
_edje_multisense_internal_sound_sample_play(Edje *ed, const char *sample_name, const double speed)
|
||||
_edje_multisense_internal_sound_sample_play(Edje *ed, const char *sample_name, const double speed EINA_UNUSED)
|
||||
{
|
||||
ssize_t size = 0;
|
||||
#ifdef ENABLE_MULTISENSE
|
||||
Edje_Multisense_Sound_Action command;
|
||||
#ifdef ENABLE_MULTISENSE
|
||||
Ecore_Audio_Object *in;
|
||||
Edje_Sound_Sample *sample;
|
||||
char snd_id_str[255];
|
||||
int i;
|
||||
|
||||
if ((!pipe_initialized) && (!player_thread)) return EINA_FALSE;
|
||||
if (!sample_name)
|
||||
if (!sample_name)
|
||||
{
|
||||
ERR("Given Sample Name is NULL\n");
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
if ((!ed) || (!ed->file) || (!ed->file->sound_dir))
|
||||
return EINA_FALSE;
|
||||
|
||||
for(i=0; i<(int)ed->file->sound_dir->samples_count; i++)
|
||||
{
|
||||
ERR("Given Sample Name is NULL\n");
|
||||
return EINA_FALSE;
|
||||
}
|
||||
sample = &ed->file->sound_dir->samples[i];
|
||||
if (!strcmp(sample->name, sample_name))
|
||||
{
|
||||
struct _edje_multisense_eet_data *eet_data;
|
||||
Eet_File *ef;
|
||||
|
||||
command.action = EDJE_PLAY_SAMPLE;
|
||||
command.ed = ed;
|
||||
strncpy(command.type.sample.sample_name, sample_name, BUF_LEN);
|
||||
command.type.sample.speed = speed;
|
||||
size = write(command_pipe[1], &command, sizeof(command));
|
||||
snprintf(snd_id_str, sizeof(snd_id_str), "edje/sounds/%i", sample->id);
|
||||
in = ecore_audio_input_add(ECORE_AUDIO_TYPE_SNDFILE);
|
||||
ecore_audio_input_name_set(in, snd_id_str);
|
||||
|
||||
eet_data = calloc(1, sizeof(struct _edje_multisense_eet_data));
|
||||
ef = eet_open(ed->file->path, EET_FILE_MODE_READ);
|
||||
|
||||
eet_data->data = eet_read(ef, snd_id_str, (int *)&eet_data->length);
|
||||
eet_close(ef);
|
||||
|
||||
/* action->speed */
|
||||
|
||||
eet_data->vio.get_length = eet_snd_file_get_length;
|
||||
eet_data->vio.seek = eet_snd_file_seek;
|
||||
eet_data->vio.read = eet_snd_file_read;
|
||||
eet_data->vio.tell = eet_snd_file_tell;
|
||||
|
||||
eet_data->offset = 0;
|
||||
|
||||
ecore_audio_input_userdata_set(in, eet_data);
|
||||
ecore_audio_input_sndfile_vio_set(in, &eet_data->vio);
|
||||
|
||||
if (!out)
|
||||
out = ecore_audio_output_add(ECORE_AUDIO_TYPE_PULSE);
|
||||
|
||||
ecore_audio_output_input_add(out, in);
|
||||
}
|
||||
}
|
||||
return EINA_TRUE;
|
||||
#else
|
||||
// warning shh
|
||||
(void) ed;
|
||||
(void) sample_name;
|
||||
(void) speed;
|
||||
return EINA_FALSE;
|
||||
#endif
|
||||
return (size == sizeof(Edje_Multisense_Sound_Action));
|
||||
}
|
||||
|
||||
Eina_Bool
|
||||
_edje_multisense_internal_sound_tone_play(Edje *ed, const char *tone_name, const double duration)
|
||||
{
|
||||
ssize_t size = 0;
|
||||
#ifdef ENABLE_MULTISENSE
|
||||
Edje_Multisense_Sound_Action command;
|
||||
unsigned int i;
|
||||
Edje_Sound_Tone *tone;
|
||||
|
||||
if ((!pipe_initialized) && (!player_thread)) return EINA_FALSE;
|
||||
Ecore_Audio_Object *in;
|
||||
if (!tone_name)
|
||||
{
|
||||
ERR("Given Tone Name is NULL\n");
|
||||
return EINA_FALSE;
|
||||
}
|
||||
if ((!ed) || (!ed->file) || (!ed->file->sound_dir))
|
||||
return EINA_FALSE;
|
||||
|
||||
command.action = EDJE_PLAY_TONE;
|
||||
command.ed = ed;
|
||||
strncpy(command.type.tone.tone_name, tone_name, BUF_LEN);
|
||||
command.type.tone.duration = duration;
|
||||
size = write(command_pipe[1], &command, sizeof(command));
|
||||
for (i=0; i<ed->file->sound_dir->tones_count; i++)
|
||||
{
|
||||
tone = &ed->file->sound_dir->tones[i];
|
||||
if (!strcmp(tone->name, tone_name))
|
||||
{
|
||||
in = ecore_audio_input_add(ECORE_AUDIO_TYPE_TONE);
|
||||
ecore_audio_input_name_set(in, "tone");
|
||||
ecore_audio_input_tone_frequency_set(in, tone->value);
|
||||
ecore_audio_input_tone_duration_set(in, duration);
|
||||
|
||||
if (!out)
|
||||
out = ecore_audio_output_add(ECORE_AUDIO_TYPE_PULSE);
|
||||
|
||||
ecore_audio_output_input_add(out, in);
|
||||
}
|
||||
}
|
||||
return EINA_TRUE;
|
||||
#else
|
||||
// warning shh
|
||||
(void) ed;
|
||||
(void) duration;
|
||||
(void) tone_name;
|
||||
return EINA_FALSE;
|
||||
#endif
|
||||
return (size == sizeof(Edje_Multisense_Sound_Action));
|
||||
|
||||
}
|
||||
|
||||
|
@ -394,14 +179,8 @@ void
|
|||
_edje_multisense_init(void)
|
||||
{
|
||||
#ifdef ENABLE_MULTISENSE
|
||||
if (!pipe_initialized && (pipe(command_pipe) != -1))
|
||||
pipe_initialized = EINA_TRUE;
|
||||
|
||||
// init msdata outside of thread due to thread issues in dlsym etc.
|
||||
if (!msdata) msdata = init_multisense_environment();
|
||||
|
||||
if (!player_thread)
|
||||
player_thread = ecore_thread_feedback_run(_player_job, NULL, _player_end, _player_cancel, NULL, EINA_TRUE);
|
||||
ecore_audio_init();
|
||||
ecore_event_handler_add(ECORE_AUDIO_INPUT_ENDED, _play_finished, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -409,14 +188,6 @@ void
|
|||
_edje_multisense_shutdown(void)
|
||||
{
|
||||
#ifdef ENABLE_MULTISENSE
|
||||
if (player_thread) ecore_thread_cancel(player_thread);
|
||||
if (pipe_initialized)
|
||||
{
|
||||
int i = 42;
|
||||
|
||||
write(command_pipe[1], &i, sizeof (int));
|
||||
close(command_pipe[1]);
|
||||
close(command_pipe[0]);
|
||||
}
|
||||
ecore_audio_shutdown();
|
||||
#endif
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue