Mike Blumenkrantz <mike@zentific.com
Jaehwan Kim <jae.hwan.kim@samsung.com>
billiob (Boris Faure) <billiob@gmail.com>
+Govindaraju SM <govi.sm@samsung.com> <govism@gmail.com>
+Prince Kumar Dubey <prince.dubey@samsung.com> <prince.dubey@gmail.com>
],
[have_ecore_imf="no"])
+# Enable Multisense use
+want_multisense="no"
+AC_ARG_ENABLE([multisense],
+ [AC_HELP_STRING(
+ [--enable-multisense],
+ [multisense provides sound. tone and haptic effects support, [[default=disabled]]]
+ )],
+ [want_multisense=$enableval]
+)
+AM_CONDITIONAL([ENABLE_MULTISENSE], [test "x${want_multisense}" = "xyes"])
+
+if test "x${want_multisense}" = "xyes" ; then
+ AC_DEFINE([ENABLE_MULTISENSE], [1], [Use Multisense])
+fi
+
+##sndfile library
+have_sndfile="no"
+want_sndfile="auto"
+AC_ARG_ENABLE([sndfile],
+ [AC_HELP_STRING([--disable-sndfile], [disable sndfile support. @<:@default=detect@:>@])],
+ [want_sndfile=$enableval], [])
+
+if test "x${want_multisense}" = "xyes" -a "x$want_sndfile" != "xno"; then
+
+ PKG_CHECK_MODULES([SNDFILE],
+ [sndfile >= 1.0.22],
+ [
+ AC_DEFINE(HAVE_LIBSNDFILE, 1, [sndfile support for Edje])
+ have_sndfile="yes"
+ requirement_edje="sndfile >= 1.0.22 ${requirement_edje}"
+ ],
+ [have_sndfile="no"]
+ )
+
+ if test "x$want_sndfile" = "xyes" -a "x$have_sndfile" = "xno"; then
+ AC_MSG_ERROR([sndfile support requested, but not found by pkg-config.])
+ fi
+fi
+AM_CONDITIONAL([HAVE_LIBSNDFILE], [test "x${have_sndfile}" = "xyes"])
+
+##libremix library
+have_libremix="no"
+want_libremix="auto"
+AC_ARG_ENABLE([remix],
+ [AC_HELP_STRING([--disable-remix], [disable remix support. @<:@default=detect@:>@])],
+ [want_libremix=$enableval], [])
+
+if test "x${want_multisense}" = "xyes" -a "x$want_libremix" != "xno"; then
+ PKG_CHECK_MODULES([REMIX],
+ [remix >= 0.2.3],
+ [
+ AC_DEFINE(HAVE_LIBREMIX, 1, [remix support for Edje])
+ have_libremix="yes"
+ requirement_edje="remix >= 0.2.3 ${requirement_edje}"
+ AC_DEFINE(__REMIX_PLUGIN__, 1, "Set to REMIX Plugin type")
+ REMIX_PLUGIN_DIR="${libdir}/remix"
+ AC_SUBST(REMIX_PLUGIN_DIR)
+ if test "x${prefix}" = "xNONE"; then
+ REMIX_PLUGIN_DIR="${ac_default_prefix}/lib/remix"
+ else
+ REMIX_PLUGIN_DIR="${prefix}/lib/remix"
+ fi
+ AC_DEFINE_UNQUOTED(REMIX_PLUGIN_DIR, "$REMIX_PLUGIN_DIR", [Set the remix plugin directory])
+ ],
+ [have_libremix="no"]
+ )
+
+ if test "x$want_libremix" = "xyes" -a "x$have_libremix" = "xno"; then
+ AC_MSG_ERROR([remix support requested, but not found by pkg-config.])
+ fi
+fi
+AM_CONDITIONAL([HAVE_LIBREMIX], [test "x${have_libremix}" = "xyes"])
+
+##vorbis/ogg library
+have_vorbis="no"
+want_vorbis="auto"
+AC_ARG_ENABLE([vorbisenc],
+ [AC_HELP_STRING([--disable-vorbis], [disable ogg-vorbis support. @<:@default=detect@:>@])],
+ [want_vorbis=$enableval], [])
+
+if test "x${want_multisense}" = "xyes" -a "x$want_vorbis" != "xno"; then
+ PKG_CHECK_MODULES([VORBISENC],
+ [
+ ogg >= 1.1.4
+ vorbis >= 1.2.3
+ vorbisenc >= 1.2.3
+ ],
+ [
+ AC_DEFINE(HAVE_VORBIS, 1, [vorbis support for Edje])
+ have_vorbis="yes"
+ requirement_edje="ogg >= 1.1.4 vorbis >= 1.2.3 vorbisenc >= 1.2.3 ${requirement_edje}"
+ ],
+ [have_vorbis="no"]
+ )
+
+ if test "x$want_vorbis" = "xyes" -a "x$have_vorbis" = "xno"; then
+ AC_MSG_ERROR([vorbisenc support requested, but not found by pkg-config.])
+ fi
+fi
+
+##alsa library
+have_alsa_lib="no"
+want_alsa_lib="auto"
+AC_ARG_ENABLE([flac],
+ [AC_HELP_STRING([--disable-alsa], [disable alsa support. @<:@default=detect@:>@])],
+ [want_alsa_lib=$enableval], [])
+
+if test "x${want_multisense}" = "xyes" -a "x$want_alsa_lib" != "xno"; then
+ PKG_CHECK_MODULES([ALSA],
+ [
+ alsa >= 1.0.21a
+ ],
+ [
+ AC_DEFINE(HAVE_LIBALSA, 1, [ALSA support for Edje])
+ have_alsa_lib="yes"
+ requirement_edje="alsa >= 1.0.21a ${requirement_edje}"
+ ],
+ [have_alsa_lib="no"]
+ )
+
+ if test "x$want_alsa_lib" = "xyes" -a "x$have_alsa_lib" = "xno"; then
+ AC_MSG_ERROR([alsa support requested, but not found by pkg-config.])
+ fi
+fi
+AM_CONDITIONAL([HAVE_LIBALSA], [test "x${have_alsa_lib}" = "xyes"])
+
+
+##flac library
+have_flac_lib="no"
+want_flac_lib="auto"
+AC_ARG_ENABLE([flac],
+ [AC_HELP_STRING([--disable-flac], [disable flac support. @<:@default=detect@:>@])],
+ [want_flac_lib=$enableval], [])
+
+if test "x${want_multisense}" = "xyes" -a "x$want_flac_lib" != "xno"; then
+ PKG_CHECK_MODULES([FLAC],
+ [
+ flac >= 1.2.1
+ ],
+ [
+ AC_DEFINE(HAVE_LIBFLAC, 1, [flac support for Edje])
+ have_flac_lib="yes"
+ requirement_edje="flac >= 1.2.1 ${requirement_edje}"
+ ],
+ [have_flac_lib="no"]
+ )
+ if test "x$want_flac_lib" = "xyes" -a "x$have_flac_lib" = "xno"; then
+ AC_MSG_ERROR([flac support requested, but not found by pkg-config.])
+ fi
+fi
+
# Dependencies for the binaries
if test "x$have_edje_cc" = "xyes"; then
src/lib/Makefile
src/bin/Makefile
src/bin/epp/Makefile
+src/modules/Makefile
+src/modules/alsa_snd_player/Makefile
+src/modules/eet_snd_reader/Makefile
+src/modules/multisense_factory/Makefile
src/tests/Makefile
utils/Makefile
src/examples/Makefile
echo
echo " Amalgamation.........: ${do_amalgamation}"
echo " Ecore IMF............: $have_ecore_imf"
+echo " Multisense...........: $want_multisense"
+
+if test "x${want_multisense}" = "xyes" ; then
+echo " LibRemix.............: $have_libremix"
+echo " Libsndfile...........: $have_sndfile"
+echo " Ogg/Vorbis...........: $have_vorbis"
+echo " LibFLAC..............: $have_flac_lib"
+echo " LibALSA..............: $have_alsa_lib"
+fi
+
echo " EDJE_PROGRAM_CACHE...: $want_edje_program_cache"
echo " EDJE_CALC_CACHE......: $want_edje_calc_cache"
echo " Fixed point..........: $want_fixed_point"
native set_state_val(part_id, State_Param:p, ...);
native get_state_val(part_id, State_Param:p, ...);
+
+/* Multisense */
+native play_sample (sample_name[], Float:speed);
+native play_tone (tone_name[], Float:duration);
* @li @ref tutorial_edje_drag
* @li @ref tutorial_edje_perspective
* @li @ref tutorial_edje_animations
+ * @li @ref tutorial_edje_multisense
*/
/**
* @include edje-animations.c
* @include animations.edc
*/
+
+ /**
+ * @page tutorial_edje_multisense Multisense example
+ * @dontinclude edje-multisense.c
+ *
+ * This is a simple example in which a rect is created and sound and tone
+ * are played on mouse down event.
+ *
+ * Focusing on the creation of sample and tone. It should be noted that
+ * creation of sample sound is from any supported (sndfile lib) audio file,
+ * tone from of specific audible frequency range are controlled by the theme:
+ *
+ * The full source code follows:
+ * @include edje-multisense.c
+ * @include sound.edc
+ */
+
## Process this file with automake to produce Makefile.in
-SUBDIRS = lib bin tests examples
+SUBDIRS = lib bin modules tests examples
MAINTAINERCLEANFILES = Makefile.in
edje_cc_parse.c \
edje_cc_mem.c \
edje_cc_handlers.c \
-edje_cc_sources.c
+edje_cc_sources.c \
+edje_multisense_convert.c
edje_cc_CPPFLAGS = \
-I$(top_srcdir)/src/bin \
-DPACKAGE_LIB_DIR=\"$(libdir)\" \
-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
-DEPP_DIR=\"$(libdir)/$(PACKAGE)/utils\" \
-@EDJE_CFLAGS@ @EDJE_CC_CFLAGS@ @EVIL_CFLAGS@
-edje_cc_LDADD = $(top_builddir)/src/lib/libedje.la @EDJE_CC_LIBS@ @EVIL_LIBS@ -lm
+@EDJE_CFLAGS@ @EDJE_CC_CFLAGS@ @EVIL_CFLAGS@ @SNDFILE_CFLAGS@
+edje_cc_LDADD = $(top_builddir)/src/lib/libedje.la @EDJE_CC_LIBS@ @EVIL_LIBS@ @VORBISENC_LIBS@ @FLAC_LIBS@ @SNDFILE_LIBS@ -lm
edje_cc_LDFLAGS = @lt_enable_auto_import@
-I$(top_srcdir)/src/bin \
-I$(top_srcdir)/src/lib \
@EDJE_CFLAGS@ @EDJE_DECC_CFLAGS@ @EVIL_CFLAGS@
-edje_decc_LDADD = $(top_builddir)/src/lib/libedje.la @EDJE_DECC_LIBS@
+edje_decc_LDADD = $(top_builddir)/src/lib/libedje.la @EDJE_DECC_LIBS@ @VORBISENC_LIBS@ @FLAC_LIBS@ @SNDFILE_LIBS@
edje_decc_LDFLAGS = @lt_enable_auto_import@
edje_player_SOURCES = edje_player.c
-I$(top_srcdir)/src/bin \
-I$(top_srcdir)/src/lib \
@EDJE_PLAYER_CFLAGS@ @EVIL_CFLAGS@
-edje_player_LDADD = $(top_builddir)/src/lib/libedje.la @EDJE_PLAYER_LIBS@ @EVIL_LIBS@
+edje_player_LDADD = $(top_builddir)/src/lib/libedje.la @EDJE_PLAYER_LIBS@ @EVIL_LIBS@ @VORBISENC_LIBS@ @FLAC_LIBS@ @SNDFILE_LIBS@
edje_player_LDFLAGS = @lt_enable_auto_import@
edje_inspector_SOURCES = edje_inspector.c
-I$(top_srcdir)/src/bin \
-I$(top_srcdir)/src/lib \
@EDJE_INSPECTOR_CFLAGS@
-edje_inspector_LDADD = $(top_builddir)/src/lib/libedje.la @EDJE_INSPECTOR_LIBS@
+edje_inspector_LDADD = $(top_builddir)/src/lib/libedje.la @EDJE_INSPECTOR_LIBS@ @VORBISENC_LIBS@ @FLAC_LIBS@
edje_inspector_LDFLAGS = @lt_enable_auto_import@
edje_external_inspector_SOURCES = edje_external_inspector.c
-I$(top_srcdir)/src/bin \
-I$(top_srcdir)/src/lib \
@EDJE_EXTERNAL_INSPECTOR_CFLAGS@
-edje_external_inspector_LDADD = $(top_builddir)/src/lib/libedje.la @EDJE_EXTERNAL_INSPECTOR_LIBS@
+edje_external_inspector_LDADD = $(top_builddir)/src/lib/libedje.la @EDJE_EXTERNAL_INSPECTOR_LIBS@ @VORBISENC_LIBS@ @FLAC_LIBS@ @SNDFILE_LIBS@
edje_external_inspector_LDFLAGS = @lt_enable_auto_import@
-
-EXTRA_DIST = @EDJE_RECC_PRG@ edje_cc.h edje_convert.h edje_convert.c edje_convert_main.c edje_data_convert.c
+EXTRA_DIST = @EDJE_RECC_PRG@ edje_cc.h edje_convert.h edje_convert.c edje_multisense_convert.h edje_data_convert.c
EXTRA_SCRIPTS = edje_recc
static void main_help(void);
Eina_Prefix *pfx = NULL;
-
+Eina_List *snd_dirs = NULL;
Eina_List *img_dirs = NULL;
Eina_List *fnt_dirs = NULL;
Eina_List *defines = NULL;
"\n"
"-id image/directory Add a directory to look in for relative path images\n"
"-fd font/directory Add a directory to look in for relative path fonts\n"
+ "-sd sound/directory Add a directory to look in for relative path sounds samples\n"
"-td temp/directory Directory to store temporary files\n"
"-v Verbose output\n"
"-no-lossy Do NOT allow images to be lossy\n"
i++;
fnt_dirs = eina_list_append(fnt_dirs, argv[i]);
}
+ else if ((!strcmp(argv[i], "-sd") || !strcmp(argv[i], "--sound_dir")) && (i < (argc - 1)))
+ {
+ i++;
+ snd_dirs = eina_list_append(snd_dirs, argv[i]);
+ }
else if ((!strcmp(argv[i], "-td") || !strcmp(argv[i], "--tmp_dir")) && (i < (argc - 1)))
{
i++;
extern Eina_List *ext_dirs;
extern Eina_List *img_dirs;
extern Eina_List *fnt_dirs;
+extern Eina_List *snd_dirs;
extern char *file_in;
extern char *tmp_dir;
extern char *file_out;
static void st_collections_group_programs_program_api(void);
static void ob_collections_group_programs_program_script(void);
+static void st_collections_group_sound_sample_name(void);
+static void st_collections_group_sound_sample_source(void);
+static void st_collections_group_sound_tone(void);
/*****/
{"collections.color_classes.color_class.color", st_color_class_color}, /* dup */
{"collections.color_classes.color_class.color2", st_color_class_color2}, /* dup */
{"collections.color_classes.color_class.color3", st_color_class_color3}, /* dup */
+
+ {"collections.sounds.sample.name", st_collections_group_sound_sample_name},
+ {"collections.sounds.sample.source", st_collections_group_sound_sample_source},
+ {"collections.group.sounds.sample.name", st_collections_group_sound_sample_name}, /* dup */
+ {"collections.group.sounds.sample.source", st_collections_group_sound_sample_source}, /* dup */
+ {"collections.sounds.tone", st_collections_group_sound_tone},
+ {"collections.group.sounds.tone", st_collections_group_sound_tone}, /* dup */
{"collections.group.name", st_collections_group_name},
{"collections.group.inherit", st_collections_group_inherit},
{"collections.group.script_only", st_collections_group_script_only},
{"collections.styles.style", ob_styles_style}, /* dup */
{"collections.color_classes", NULL}, /* dup */
{"collections.color_classes.color_class", ob_color_class}, /* dup */
+ {"collections.sounds", NULL},
+ {"collections.group.sounds", NULL}, /* dup */
+ {"collections.sounds.sample", NULL},
+ {"collections.group.sounds.sample", NULL}, /* dup */
{"collections.group", ob_collections_group},
{"collections.group.data", NULL},
{"collections.group.script", ob_collections_group_script},
..
group { }
group { }
+ sounds { }
..
}
@description
The "collections" block is used to list the groups that compose the
theme. Additional "collections" blocks do not prevent overriding group
- names.
+ names. The "sounds" block comprises of all sound definitions.
@endblock
*/
static void
}
/**
+ @page edcref
+ @block
+ sounds
+ @context
+ sounds {
+ sample {
+ name: "sound_file1" COMP;
+ source: "sound_file1.wav";
+ }
+ sample {
+ name: "sound_file2" LOSSY 0.4;
+ source: "sound_file2.wav";
+ }
+ tone: "tone-1" 2300;
+ }
+
+ @description
+ The "sounds" block contains a list of one or more sound sample and tones items.
+ @endblock
+ @block
+ sample
+ @context
+ sample {
+ name: "sound_file1" RAW;
+ source: "sound_file1.wav";
+ }
+ sample {
+ name: "sound_file2" LOSSY 0.5;
+ source: "sound_file2.wav";
+ }
+ sample {
+ name: "sound_file3" COMP;
+ source: "sound_file3.wav";
+ }
+ sample {
+ name: "sound_file4" AS-IS;
+ source: "sound_file1.wav";
+ }
+ @description
+ The sample block defines the sound sample.
+ @endblock
+ @property
+ name
+ @parameters
+ [sample name] [compression type] [if lossy, then quality]
+ @effect
+ Used to include each sound file. The full path to the directory holding
+ the sounds can be defined later with edje_cc's "-sd" option.
+ @li RAW: Uncompressed.
+ @li COMP: Lossless compression.
+ @li LOSSY [-0.1 - 1.0]: Lossy comression with quality from 0 to 1.0.
+ @li AS_IS: Check for re-encoding, no compression/encoding, just write the file information as it is.
+ @endproperty
+ @since 1.1.0
+ */
+static void
+st_collections_group_sound_sample_name(void)
+{
+ Edje_Sound_Sample *sample;
+ const char *tmp;
+ unsigned int i;
+
+ if (!edje_file->sound_dir)
+ edje_file->sound_dir = mem_alloc(SZ(Edje_Sound_Directory));
+
+ tmp = parse_str(0);
+
+ for (i = 0; i < edje_file->sound_dir->samples_count; i++)
+ {
+ if (!strcmp(edje_file->sound_dir->samples[i].name, tmp))
+ {
+ free((char *)tmp);
+ return;
+ }
+ }
+
+ edje_file->sound_dir->samples_count++;
+ edje_file->sound_dir->samples =
+ realloc(edje_file->sound_dir->samples,
+ sizeof(Edje_Sound_Sample) *
+ edje_file->sound_dir->samples_count);
+
+ if (!edje_file->sound_dir->samples)
+ {
+ ERR("%s: Error. No enough memory.", progname);
+ exit(-1);
+ }
+
+ sample =
+ edje_file->sound_dir->samples +
+ edje_file->sound_dir->samples_count - 1;
+ memset(sample, 0, sizeof (Edje_Sound_Sample));
+
+ sample->name = tmp;
+ sample->id = edje_file->sound_dir->samples_count - 1;
+ sample->compression = parse_enum(1,
+ "RAW", EDJE_SOUND_SOURCE_TYPE_INLINE_RAW,
+ "COMP", EDJE_SOUND_SOURCE_TYPE_INLINE_COMP,
+ "LOSSY", EDJE_SOUND_SOURCE_TYPE_INLINE_LOSSY,
+ "AS_IS", EDJE_SOUND_SOURCE_TYPE_INLINE_AS_IS,
+ NULL);
+
+ if (sample->compression == EDJE_SOUND_SOURCE_TYPE_INLINE_LOSSY)
+ {
+ sample->quality = parse_float_range(2, 45.0, 1000.0);
+ check_arg_count(3);
+ }
+ else
+ check_arg_count(2);
+
+}
+
+/**
+ @page edcref
+ @property
+ source
+ @parameters
+ [sound file name]
+ @effect
+ The Sound source file name (Source can be mono/stereo WAV file.
+ Only files with 44.1 KHz sample rate supported now)
+ @endproperty
+ @since 1.1.0
+ */
+static void
+st_collections_group_sound_sample_source(void)
+{
+ Edje_Sound_Sample *sample;
+
+ if (!edje_file->sound_dir->samples)
+ {
+ ERR("%s: Error. Invalid sound sample source definition.", progname);
+ exit(-1);
+ }
+
+ sample =
+ edje_file->sound_dir->samples +
+ edje_file->sound_dir->samples_count - 1;
+
+ if (!sample)
+ {
+ ERR("%s: Error. Invalid sound sample source definition.", progname);
+ exit(-1);
+ }
+ sample->snd_src = parse_str(0);
+ check_arg_count(1);
+}
+
+/**
+ @page edcref
+ @property
+ tone
+ @parameters
+ [tone name] [frequency]
+ @effect
+ sound of specific frequency
+ @endproperty
+ @since 1.1.0
+ */
+static void
+st_collections_group_sound_tone(void)
+{
+ Edje_Sound_Tone *tone;
+ const char *tmp;
+ unsigned int i;
+ int value;
+
+ check_arg_count(2);
+
+ if (!edje_file->sound_dir)
+ edje_file->sound_dir = mem_alloc(SZ(Edje_Sound_Directory));
+
+ tmp = parse_str(0);
+ /* Audible range 20 to 20KHz */
+ value = parse_int_range(1, 20, 20000);
+
+ /* Check for Tone duplication */
+ for (i = 0; i < edje_file->sound_dir->tones_count; i++)
+ {
+ if (!strcmp(edje_file->sound_dir->tones[i].name, tmp))
+ {
+ ERR("%s: Error. Tone name: %s already exist.", progname, tmp);
+ free((char *)tmp);
+ exit(-1);
+ }
+ if (edje_file->sound_dir->tones[i].value == value)
+ {
+ ERR("%s: Error. Tone name %s with same frequency %d exist.",
+ progname, edje_file->sound_dir->tones[i].name, value);
+ exit(-1);
+ }
+ }
+ edje_file->sound_dir->tones_count++;
+ edje_file->sound_dir->tones =
+ realloc(edje_file->sound_dir->tones,
+ sizeof (Edje_Sound_Tone) *
+ edje_file->sound_dir->tones_count);
+
+ if (!edje_file->sound_dir->tones)
+ {
+ ERR("%s: Error. No enough memory.", progname);
+ exit(-1);
+ }
+
+ tone = edje_file->sound_dir->tones + edje_file->sound_dir->tones_count - 1;
+ memset(tone, 0, sizeof (Edje_Sound_Tone));
+
+ tone->name = tmp;
+ tone->value = value;
+ tone->id = edje_file->sound_dir->tones_count - 1;
+}
+
+/**
@edcsection{group,Group sub blocks}
*/
{
Edje_Part_Collection *pc;
Code *cd;
-
+
if (current_de && !current_de->entry)
{
ERR("%p: Error. A collection without a name was detected, that's not allowed.", progname);
@effect
Action to be performed by the program. Valid actions are: STATE_SET,
ACTION_STOP, SIGNAL_EMIT, DRAG_VAL_SET, DRAG_VAL_STEP, DRAG_VAL_PAGE,
- FOCUS_SET, PARAM_COPY, PARAM_SET
+ FOCUS_SET, PARAM_COPY, PARAM_SET, PLAY_SAMPLE, PLAY_TONE
Only one action can be specified per program. Examples:\n
action: STATE_SET "statename" 0.5;\n
action: ACTION_STOP;\n
action: FOCUS_SET;\n
action: FOCUS_OBJECT;\n
action: PARAM_COPY "src_part" "src_param" "dst_part" "dst_param";\n
- action: PARAM_SET "part" "param" "value";\n
+ action: PARAM_SET "part" "param" "value";\n
+ action: PLAY_SAMPLE "sample name";\n
+ action: PLAY_TONE "tone name" duration in seconds ( Range 0.1 to 10.0 );\n
@endproperty
*/
static void
{
Edje_Part_Collection *pc;
Edje_Program *ep;
-
+ int i;
+
pc = eina_list_data_get(eina_list_last(edje_collections));
ep = current_program;
ep->action = parse_enum(0,
- "STATE_SET", EDJE_ACTION_TYPE_STATE_SET,
- "ACTION_STOP", EDJE_ACTION_TYPE_ACTION_STOP,
- "SIGNAL_EMIT", EDJE_ACTION_TYPE_SIGNAL_EMIT,
- "DRAG_VAL_SET", EDJE_ACTION_TYPE_DRAG_VAL_SET,
- "DRAG_VAL_STEP", EDJE_ACTION_TYPE_DRAG_VAL_STEP,
- "DRAG_VAL_PAGE", EDJE_ACTION_TYPE_DRAG_VAL_PAGE,
- "SCRIPT", EDJE_ACTION_TYPE_SCRIPT,
- "FOCUS_SET", EDJE_ACTION_TYPE_FOCUS_SET,
- "FOCUS_OBJECT", EDJE_ACTION_TYPE_FOCUS_OBJECT,
- "PARAM_COPY", EDJE_ACTION_TYPE_PARAM_COPY,
- "PARAM_SET", EDJE_ACTION_TYPE_PARAM_SET,
- NULL);
+ "STATE_SET", EDJE_ACTION_TYPE_STATE_SET,
+ "ACTION_STOP", EDJE_ACTION_TYPE_ACTION_STOP,
+ "SIGNAL_EMIT", EDJE_ACTION_TYPE_SIGNAL_EMIT,
+ "DRAG_VAL_SET", EDJE_ACTION_TYPE_DRAG_VAL_SET,
+ "DRAG_VAL_STEP", EDJE_ACTION_TYPE_DRAG_VAL_STEP,
+ "DRAG_VAL_PAGE", EDJE_ACTION_TYPE_DRAG_VAL_PAGE,
+ "SCRIPT", EDJE_ACTION_TYPE_SCRIPT,
+ "FOCUS_SET", EDJE_ACTION_TYPE_FOCUS_SET,
+ "FOCUS_OBJECT", EDJE_ACTION_TYPE_FOCUS_OBJECT,
+ "PARAM_COPY", EDJE_ACTION_TYPE_PARAM_COPY,
+ "PARAM_SET", EDJE_ACTION_TYPE_PARAM_SET,
+ "PLAY_SAMPLE", EDJE_ACTION_TYPE_SOUND_SAMPLE,
+ "PLAY_TONE", EDJE_ACTION_TYPE_SOUND_TONE,
+ NULL);
if (ep->action == EDJE_ACTION_TYPE_STATE_SET)
{
ep->state = parse_str(1);
ep->state = parse_str(1);
ep->state2 = parse_str(2);
}
+ else if (ep->action == EDJE_ACTION_TYPE_SOUND_SAMPLE)
+ {
+ ep->sample_name = parse_str(1);
+ for (i = 0; i < (int)edje_file->sound_dir->samples_count; i++)
+ {
+ if (!strcmp(edje_file->sound_dir->samples[i].name, ep->sample_name))
+ break;
+ if (i == (int)(edje_file->sound_dir->samples_count - 1))
+ {
+ ERR("%s: Error. No Sample name %s exist.", progname,
+ ep->sample_name);
+ exit(-1);
+ }
+ }
+ ep->speed = parse_float_range(2, 0.0, 10.0);
+ }
+ else if (ep->action == EDJE_ACTION_TYPE_SOUND_TONE)
+ {
+ ep->tone_name = parse_str(1);
+ for (i = 0; i < (int)edje_file->sound_dir->tones_count; i++)
+ {
+ if (!strcmp(edje_file->sound_dir->tones[i].name, ep->tone_name))
+ break;
+ if (i == (int)(edje_file->sound_dir->tones_count - 1))
+ {
+ ERR("%s: Error. No Tone name %s exist.", progname,
+ ep->tone_name);
+ exit(-1);
+ }
+ }
+ ep->duration = parse_float_range(2, 0.1, 10.0);
+ }
else if (ep->action == EDJE_ACTION_TYPE_DRAG_VAL_SET)
{
ep->value = parse_float(1);
else if (ep->action == EDJE_ACTION_TYPE_PARAM_COPY)
{
char *src_part, *dst_part;
-
+
src_part = parse_str(1);
ep->state = parse_str(2);
dst_part = parse_str(3);
ep->state2 = parse_str(4);
-
+
data_queue_part_lookup(pc, src_part, &(ep->param.src));
data_queue_part_lookup(pc, dst_part, &(ep->param.dst));
-
+
free(src_part);
free(dst_part);
}
else if (ep->action == EDJE_ACTION_TYPE_PARAM_SET)
{
char *part;
-
+
part = parse_str(1);
ep->state = parse_str(2);
ep->state2 = parse_str(3);
-
+
data_queue_part_lookup(pc, part, &(ep->param.dst));
free(part);
}
-
+
switch (ep->action)
{
case EDJE_ACTION_TYPE_ACTION_STOP:
check_arg_count(1);
break;
case EDJE_ACTION_TYPE_PARAM_COPY:
- check_arg_count(5);
- break;
+ check_arg_count(5);
+ break;
case EDJE_ACTION_TYPE_PARAM_SET:
- check_arg_count(4);
- break;
+ check_arg_count(4);
+ break;
+ case EDJE_ACTION_TYPE_SOUND_SAMPLE:
+ check_arg_count(3);
+ break;
+ case EDJE_ACTION_TYPE_SOUND_TONE:
+ check_arg_count(3);
+ break;
default:
check_arg_count(3);
}
#include "edje_cc.h"
#include "edje_convert.h"
+#include "edje_multisense_convert.h"
#include <lua.h>
#include <lauxlib.h>
return total_bytes;
}
+static int
+data_write_sounds(Eet_File * ef, int *sound_num, int *input_bytes, int *input_raw_bytes)
+{
+ int bytes = 0;
+ int total_bytes = 0;
+
+ if ((edje_file) && (edje_file->sound_dir))
+ {
+ Eina_List *ll;
+ Edje_Sound_Sample *sample;
+#ifdef HAVE_LIBSNDFILE
+ Edje_Sound_Encode *enc_info;
+#endif
+ char *dir_path = NULL;
+ char snd_path[PATH_MAX];
+ char sndid_str[15];
+ void *fdata;
+ FILE *fp = NULL;
+ struct stat st;
+ int size = 0;
+ int i;
+
+ for (i = 0; i < (int)edje_file->sound_dir->samples_count; i++)
+ {
+ sample = &edje_file->sound_dir->samples[i];
+ memset(&st, 0, sizeof(struct stat));
+
+ // Search the Sound file in all the -sd ( sound directory )
+ EINA_LIST_FOREACH(snd_dirs, ll, dir_path)
+ {
+ snprintf((char *)snd_path, sizeof(snd_path), "%s/%s", dir_path,
+ sample->snd_src);
+ stat(snd_path, &st);
+ if (st.st_size) break;
+ }
+ if (!st.st_size)
+ {
+ snprintf((char *)snd_path, sizeof(snd_path), "%s",
+ sample->snd_src);
+ stat(snd_path, &st);
+ }
+ size = st.st_size;
+ if (!size)
+ {
+ ERR("%s: Error. Unable to load sound source file : %s",
+ progname, sample->snd_src);
+ exit(-1);
+ }
+#ifdef HAVE_LIBSNDFILE
+ enc_info = _edje_multisense_encode(snd_path, sample, sample->quality);
+
+ stat(enc_info->file, &st);
+ size = st.st_size;
+ fp = fopen(enc_info->file, "rb");
+#else
+ fp = fopen(snd_path, "rb");
+#endif
+ if (!fp)
+ {
+ ERR("%s: Error: Unable to load sound data of: %s",
+ progname, sample->name);
+ exit(-1);
+ }
+
+ snprintf(sndid_str, sizeof(sndid_str), "edje/sounds/%i", sample->id);
+ fdata = malloc(size);
+ if (!fdata)
+ {
+ ERR("%s: Error. %s:%i while allocating memory to load file \"%s\"",
+ progname, file_in, line, snd_path);
+ exit(-1);
+ }
+ if (fread(fdata, size, 1, fp))
+ bytes = eet_write(ef, sndid_str, fdata, size, EINA_FALSE);
+ free(fdata);
+ fclose(fp);
+
+#ifdef HAVE_LIBSNDFILE
+ //If encoded temporary file, delete it.
+ if (enc_info->encoded) unlink(enc_info->file);
+#endif
+ *sound_num += 1;
+ total_bytes += bytes;
+ *input_bytes += size;
+ *input_raw_bytes += size;
+
+ if (verbose)
+ {
+#ifdef HAVE_LIBSNDFILE
+ printf ("%s: Wrote %9i bytes (%4iKb) for \"%s\" %s sound entry"
+ "\"%s\" \n", progname, bytes, (bytes + 512) / 1024,
+ sndid_str, enc_info->comp_type, sample->name);
+#else
+ printf ("%s: Wrote %9i bytes (%4iKb) for \"%s\" %s sound entry"
+ "\"%s\" \n", progname, bytes, (bytes + 512) / 1024,
+ sndid_str, "RAW PCM", sample->name);
+#endif
+ }
+#ifdef HAVE_LIBSNDFILE
+ if ((enc_info->file) && (!enc_info->encoded)) eina_stringshare_del(enc_info->file);
+ if (enc_info) free(enc_info);
+ enc_info = NULL;
+#endif
+ }
+ }
+ return total_bytes;
+}
+
static void
check_groups(Eet_File *ef)
{
int fmap_bytes = 0;
int input_raw_bytes = 0;
int image_num = 0;
+ int sound_num = 0;
int font_num = 0;
int collection_num = 0;
&input_raw_bytes);
total_bytes += data_write_images(ef, &image_num, &input_bytes,
&input_raw_bytes);
+ total_bytes += data_write_sounds(ef, &sound_num, &input_bytes,
+ &input_raw_bytes);
total_bytes += data_write_groups(ef, &collection_num);
data_write_scripts(ef);
printf("Summary:\n"
" Wrote %i collections\n"
" Wrote %i images\n"
+ " Wrote %i sounds\n"
" Wrote %i fonts\n"
" Wrote %i bytes (%iKb) of original source data\n"
" Wrote %i bytes (%iKb) of original source font map\n"
,
collection_num,
image_num,
+ sound_num,
font_num,
src_bytes, (src_bytes + 512) / 1024,
fmap_bytes, (fmap_bytes + 512) / 1024,
chmod(out, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP);
}
+
+ if (edje_file->sound_dir)
+ {
+ Edje_Sound_Sample *sample;
+ void *sound_data;
+ char out[PATH_MAX];
+ char out1[PATH_MAX];
+ char *pp;
+ int sound_data_size;
+ FILE *f;
+ int i;
+
+ for (i = 0; i < (int)edje_file->sound_dir->samples_count; i++)
+ {
+ sample = &edje_file->sound_dir->samples[i];
+ if ((!sample) || (!sample->name)) continue;
+ snprintf(out, sizeof(out), "edje/sounds/%i", sample->id);
+ sound_data = (void *)eet_read_direct(tef, out, &sound_data_size);
+ if (sound_data)
+ {
+ snprintf(out1, sizeof(out1), "%s/%s", outdir, sample->name);
+ pp = strdup(out1);
+ p = strrchr(pp, '/');
+ *p = 0;
+ if (strstr(pp, "../"))
+ {
+ ERR("Potential security violation. attempt to write in parent dir.");
+ exit(-1);
+ }
+ ecore_file_mkpath(pp);
+ free(pp);
+ if (strstr(out, "../"))
+ {
+ ERR("Potential security violation. attempt to write in parent dir.");
+ exit(-1);
+ }
+ f = fopen(out1, "wb");
+ if (fwrite(sound_data, sound_data_size, 1, f) != 1)
+ ERR("Could not write sound: %s", strerror(errno));
+ fclose(f);
+ free(sound_data);
+ }
+ }
+
+ }
eet_close(tef);
}
--- /dev/null
+#include "edje_multisense_convert.h"
+
+#ifdef HAVE_LIBSNDFILE
+# define READBUF 1024
+# ifdef HAVE_VORBIS
+# include <vorbis/vorbisenc.h>
+# endif
+
+# ifdef HAVE_LIBFLAC
+# include <FLAC/metadata.h>
+# include <FLAC/stream_encoder.h>
+# endif
+
+Edje_Sound_Encode *
+_edje_multisense_encode(const char *filename, Edje_Sound_Sample *sample, double quality)
+{
+ SF_INFO sfinfo;
+ SNDFILE* sfile;
+ Edje_Sound_Encode *enc_info;
+
+ enc_info = calloc(1, sizeof(Edje_Sound_Encode));
+ if (!enc_info)
+ {
+ ERR("Error. while allocating memory to load file ");
+ exit(-1);
+ }
+ memset (&sfinfo, 0, sizeof (SF_INFO));
+
+ enc_info->encoded = EINA_FALSE;
+ enc_info->comp_type = "RAW PCM";
+
+ // Open wav file using sndfile
+ sfile = sf_open (filename, SFM_READ, &sfinfo);
+ if (!sfile)
+ {
+ ERR("Error. Unable to open audio file : %s", filename);
+ exit(-1);
+ }
+
+ if (!sf_format_check(&sfinfo))
+ {
+ ERR("Error. Unknown file, not a valid audio file");
+ exit(-1);
+ }
+
+ if (sample->compression == EDJE_SOUND_SOURCE_TYPE_INLINE_COMP)
+ {
+ sf_close(sfile);
+#ifdef HAVE_LIBFLAC
+ //encode provided wav file to flac
+ enc_info->file = _edje_multisense_encode_to_flac((char *)filename, sfinfo);
+ if (enc_info->file)
+ {
+ enc_info->comp_type = "FLAC";
+ enc_info->encoded = EINA_TRUE;
+ }
+#else
+ WRN("WARNING: Unable to encode sound %s to FLAC compression",
+ sample->name);
+#endif
+ }
+ else if (sample->compression == EDJE_SOUND_SOURCE_TYPE_INLINE_LOSSY)
+ {
+ sf_close(sfile);
+#ifdef HAVE_VORBIS
+ //encode provided wav file to ogg-vorbis
+ enc_info->file = _edje_multisense_encode_to_ogg_vorbis((char *)filename,
+ quality, sfinfo);
+ if (enc_info->file)
+ {
+ enc_info->comp_type = "OGG-VORBIS";
+ enc_info->encoded = EINA_TRUE;
+ }
+#else
+ WRN("WARNING: Unable to encode sound %s to Ogg-Vorbis",
+ sample->name);
+#endif
+ }
+ else
+ eina_stringshare_replace(&enc_info->file, filename);
+ return enc_info;
+}
+
+#ifdef HAVE_LIBFLAC
+const char*
+_edje_multisense_encode_to_flac(char *snd_path, SF_INFO sfinfo)
+{
+ unsigned total_samples = 0; /* can use a 32-bit number due to WAVE size limitations */
+ FLAC__bool ok = 1;
+ FLAC__StreamEncoder *encoder = 0;
+ FLAC__StreamEncoderInitStatus init_status;
+ FLAC__StreamMetadata *metadata[2];
+ FLAC__StreamMetadata_VorbisComment_Entry entry;
+ SNDFILE *sfile;
+ sf_count_t size;
+ char *tmp;
+
+ sfile = sf_open(snd_path, SFM_READ, &sfinfo);
+ if (!sfile) return NULL;
+ if (!sf_format_check(&sfinfo))
+ {
+ sf_close(sfile);
+ return NULL;
+ }
+ size = sf_seek(sfile, 0, SEEK_END);
+ sf_seek(sfile, 0, SEEK_SET);
+ tmp = malloc(strlen(snd_path) + 1 + 5);
+ if (!tmp)
+ {
+ sf_close(sfile);
+ return NULL;
+ }
+ strcpy(tmp, snd_path);
+ snd_path = tmp;
+ strcat(snd_path, ".flac");
+
+ total_samples = size;
+
+ /* allocate the encoder */
+ if ((encoder = FLAC__stream_encoder_new()) == NULL)
+ {
+ ERR("ERROR: Creating FLAC encoder\n");
+ free(snd_path);
+ sf_close(sfile);
+ return NULL;
+ }
+
+ /* Verify it's own encoded output. This will slow the encoding process. */
+ ok &= FLAC__stream_encoder_set_verify(encoder, 1);
+
+ //Levels range from 0 (fastest, least compression) to 8 (slowest, most compression).
+ //A value larger than 8 will be treated as 8.
+ //5 is used for good compression and moderate compression/decompression speed.
+ ok &= FLAC__stream_encoder_set_compression_level(encoder, 5);
+ ok &= FLAC__stream_encoder_set_channels(encoder, sfinfo.channels);
+ ok &= FLAC__stream_encoder_set_bits_per_sample(encoder, 16);
+ ok &= FLAC__stream_encoder_set_sample_rate(encoder, sfinfo.samplerate);
+ ok &= FLAC__stream_encoder_set_total_samples_estimate(encoder, total_samples);
+
+ /* now add some metadata; we'll add some tags and a padding block */
+ if (ok)
+ {
+ if ((metadata[0] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT)) == NULL
+ || (metadata[1] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)) == NULL
+ || !FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "Encoder", "flac")
+ || !FLAC__metadata_object_vorbiscomment_append_comment(metadata[0], entry, 0))
+ {
+ ERR("ERROR: out of memory error or tag error\n");
+ ok = 0;
+ }
+ metadata[1]->length = 16; /* set the padding length */
+ ok = FLAC__stream_encoder_set_metadata(encoder, metadata, 2);
+ }
+
+ /* initialize encoder */
+ if (ok)
+ {
+ init_status = FLAC__stream_encoder_init_file(encoder, snd_path, NULL,
+ (void *)(total_samples));
+ if (init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK)
+ {
+ ERR("ERROR: unable to initialize FLAC encoder: %s\n",
+ FLAC__StreamEncoderInitStatusString[init_status]);
+ ok = 0;
+ }
+ }
+
+ /* read blocks of samples from WAVE file and feed to encoder */
+ while (ok)
+ {
+ FLAC__int32 readbuffer[READBUF * 2];
+ sf_count_t count;
+ int i;
+
+ count = sf_readf_int(sfile, readbuffer, READBUF);
+ if (count <= 0) break;
+ for (i = 0; i < (count * sfinfo.channels); i++)
+ readbuffer[i] = readbuffer[i] >> 16;
+ ok = FLAC__stream_encoder_process_interleaved(encoder, readbuffer,
+ count);
+ }
+
+ FLAC__stream_encoder_finish(encoder);
+ /* now that encoding is finished, the metadata can be freed */
+ FLAC__metadata_object_delete(metadata[0]);
+ FLAC__metadata_object_delete(metadata[1]);
+
+ FLAC__stream_encoder_delete(encoder);
+ sf_close(sfile);
+ return (snd_path);
+}
+#endif
+
+#ifdef HAVE_VORBIS
+const char *
+_edje_multisense_encode_to_ogg_vorbis(char *snd_path, double quality, SF_INFO sfinfo)
+{
+ ogg_stream_state os; /* take physical pages, weld into a logical stream of packets */
+ ogg_page og; /* one Ogg bitstream page. Vorbis packets are inside */
+ ogg_packet op; /* one raw packet of data for decode */
+ vorbis_info vi; /* struct that stores all the static vorbis bitstream settings */
+ vorbis_comment vc; /* struct that stores all the user comments */
+ vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
+ vorbis_block vb; /* local working space for packet->PCM decode */
+ int eos = 0, ret;
+ char *tmp;
+ SNDFILE *sfile;
+ FILE *fout;
+
+ sfile = sf_open(snd_path, SFM_READ, &sfinfo);
+ if (!sfile) return NULL;
+ if (!sf_format_check(&sfinfo))
+ {
+ sf_close(sfile);
+ return NULL;
+ }
+ tmp = malloc(strlen(snd_path) + 1 + 4);
+ if (!tmp)
+ {
+ sf_close(sfile);
+ return NULL;
+ }
+ strcpy(tmp, snd_path);
+ snd_path = tmp;
+ strcat(snd_path, ".ogg");
+ fout = fopen(snd_path, "wb");
+ if (!fout)
+ {
+ free(snd_path);
+ sf_close(sfile);
+ return NULL;
+ }
+
+ /********** Encode setup ************/
+ vorbis_info_init(&vi);
+ ret = vorbis_encode_init(&vi, sfinfo.channels, sfinfo.samplerate,
+ -1, (long)(quality * 1000), -1);
+ if (ret == OV_EFAULT) printf("OV_EFAULT\n");
+ if (ret == OV_EINVAL) printf("OV_EINVAL\n");
+ if (ret == OV_EIMPL) printf("OV_EIMPL\n");
+
+ if (ret)
+ {
+ fclose(fout);
+ free(snd_path);
+ sf_close(sfile);
+ return NULL;
+ }
+
+ /* add a comment */
+ vorbis_comment_init(&vc);
+ vorbis_comment_add_tag(&vc, "", "");
+
+ /* set up the analysis state and auxiliary encoding storage */
+ vorbis_analysis_init(&vd, &vi);
+ vorbis_block_init(&vd, &vb);
+
+ srand(time(NULL));
+ ogg_stream_init(&os, rand());
+
+ ogg_packet header;
+ ogg_packet header_comm;
+ ogg_packet header_code;
+
+ vorbis_analysis_headerout(&vd, &vc, &header, &header_comm, &header_code);
+ ogg_stream_packetin(&os, &header); /* automatically placed in its own page */
+ ogg_stream_packetin(&os, &header_comm);
+ ogg_stream_packetin(&os, &header_code);
+
+ while (!eos)
+ {
+ int result = ogg_stream_flush(&os, &og);
+ if (!result) break;
+ fwrite(og.header, 1, og.header_len, fout);
+ fwrite(og.body, 1, og.body_len, fout);
+ }
+
+ while (!eos)
+ {
+ int i, ch;
+ float readbuffer[READBUF * 2];
+ sf_count_t count;
+
+ count = sf_readf_float(sfile, readbuffer, READBUF);
+
+ if (!count)
+ vorbis_analysis_wrote(&vd, 0);
+ else
+ {
+ float **buffer = vorbis_analysis_buffer(&vd, count);
+
+ /* uninterleave samples */
+ for (i = 0; i < count; i++)
+ {
+ for (ch = 0; ch < sfinfo.channels; ch++)
+ buffer[ch][i]= readbuffer[(i * sfinfo.channels) + ch];
+ }
+ vorbis_analysis_wrote(&vd, i);
+ }
+ while (vorbis_analysis_blockout(&vd, &vb) == 1)
+ {
+ vorbis_analysis(&vb, NULL);
+ vorbis_bitrate_addblock(&vb);
+
+ while (vorbis_bitrate_flushpacket(&vd, &op))
+ {
+ ogg_stream_packetin(&os, &op);
+ while (!eos)
+ {
+ int result = ogg_stream_pageout(&os, &og);
+ if (!result) break;
+ fwrite(og.header, 1, og.header_len, fout);
+ fwrite(og.body, 1, og.body_len, fout);
+ if (ogg_page_eos(&og)) eos = 1;
+ }
+ }
+ }
+ }
+ ogg_stream_clear(&os);
+ vorbis_block_clear(&vb);
+ vorbis_dsp_clear(&vd);
+ vorbis_comment_clear(&vc);
+ vorbis_info_clear(&vi);
+ sf_close(sfile);
+ fclose (fout);
+ return snd_path;
+}
+#endif
+#endif
--- /dev/null
+#ifndef EDJE_SND_CONVERT_H__
+# define EDJE_SND_CONVERT_H__
+#include "edje_private.h"
+
+#ifdef HAVE_LIBSNDFILE
+#include <sndfile.h>
+
+#define SF_CONTAINER(x) ((x) & SF_FORMAT_TYPEMASK)
+#define SF_CODEC(x) ((x) & SF_FORMAT_SUBMASK)
+
+typedef struct _Edje_Sound_Encode Edje_Sound_Encode;
+
+struct _Edje_Sound_Encode /*Encoding information*/
+{
+ const char *file; /* the encode sound file path */
+ Eina_Bool encoded; /* True if encoding is successful else False */
+ char *comp_type; /* either LOSSLESS (FLAC) or LOSSY (Ogg/Vorbis) Compression */
+};
+
+Edje_Sound_Encode *_edje_multisense_encode(const char* filename, Edje_Sound_Sample *sample, double quality);
+const char *_edje_multisense_encode_to_flac(char *snd_path, SF_INFO sfinfo);
+const char *_edje_multisense_encode_to_ogg_vorbis(char *snd_path, double quality, SF_INFO sfinfo);
+
+#endif
+#endif
MAINTAINERCLEANFILES = Makefile.in
pkglibdir = $(datadir)/$(PACKAGE)/examples
-
+if ENABLE_MULTISENSE
+MULTISENSE_EDC_FILE = multisense.edc
+SND_DIR = -sd $(srcdir)
+endif
#put here all EDCs one needs to the examples
EDCS = basic.edc \
swallow.edc \
signals-messages.edc \
color-class.edc \
perspective.edc \
- animations.edc
+ animations.edc \
+ $(MULTISENSE_EDC_FILE)
filesdir = $(datadir)/$(PACKAGE)/examples
files_DATA =
LDADD = $(top_builddir)/src/lib/libedje.la @EDJE_LIBS@
.edc.edj:
- $(edje_cc) -v -id $(srcdir) $< $(builddir)/$(@F)
+ $(edje_cc) -v -id $(srcdir) $(SND_DIR) $< $(builddir)/$(@F)
EDJS = $(EDCS:%.edc=%.edj)
--- /dev/null
+collections {
+ sounds {
+ sample {
+ name: "sound_name1" RAW;
+// source: "sample.wav";
+// source: "sample-flac10k.wav";
+ source: "sample-flac10k-mono.wav";
+ }
+ sample {
+ name: "sound_name2" COMP;
+ source: "sample.wav";
+ }
+/*
+ sample {
+ name: "sound_name3" LOSSY 0.5;
+ source: "sample.wav";
+ }
+ sample {
+ name: "sound_name4" AS_IS;
+ source: "sample.wav";
+ }
+ */
+ sample {
+// name: "sound_name5" AS_IS;
+// name: "sound_name5" COMP;
+ name: "sound_name5" RAW;
+// source: "sample-ogg.wav";
+// source: "sample-ogg10k.wav";
+ source: "sample-flac10k.wav";
+// source: "sample-flac10k-mono.wav";
+ }
+ sample {
+ name: "sound_name6" AS_IS;
+// name: "sound_name6" LOSSY 45.0;
+ source: "sample-flac44k-mono.wav";
+// source: "sample.ogg";
+ }
+ tone: "tone-name" 2600;
+ }
+ group {
+ name: "example_group";
+ parts {
+ part {
+ name: "sample_bg";
+ type: RECT;
+ mouse_events: 1;
+ description {
+ state: "default" 0.0;
+ min: 300 150;
+ max: 300 150;
+ color: 200 200 200 100;
+ align: 0.5 0.0;
+ rel1 {
+ relative: 0.0 0.0;
+ }
+ }
+ }
+ part {
+ name: "sample_text";
+ type: TEXT;
+ mouse_events: 1;
+ repeat_events: 1;
+ description {
+ state: "default" 0.0;
+ rel1.to: "sample_bg";
+ rel2.to: "sample_bg";
+ text {
+ font: "Sans";
+ size: 20;
+ text: "Play Sound Sample";
+ }
+ }
+ }
+ part {
+ name: "tone_bg";
+ type: RECT;
+ mouse_events: 1;
+ description {
+ state: "default" 0.0;
+ min: 300 150;
+ max: 300 150;
+ align: 0.5 0.0;
+ color: 180 180 180 100;
+ rel1 {
+ relative: 0.0 1.0;
+ to: "sample_bg";
+ }
+ }
+ }
+ part {
+ name: "tone_text";
+ type: TEXT;
+ mouse_events: 1;
+ repeat_events : 1;
+ description {
+ state: "default" 0.0;
+ rel1.to: "tone_bg";
+ rel2.to: "tone_bg";
+ text {
+ font: "Sans";
+ size: 20;
+ text: "Play Tone";
+ }
+ }
+ }
+ programs {
+ program {
+ name: "click_sample1";
+ signal: "mouse,down,1";
+ source: "sample_bg";
+ action: PLAY_SAMPLE "sound_name1" 1.0;
+ }
+ program {
+ name: "click_sample2";
+ signal: "mouse,down,2";
+ source: "sample_bg";
+ action: PLAY_SAMPLE "sound_name5" 1.0;
+ }
+ program {
+ name: "click_sample3";
+ signal: "mouse,down,3";
+ source: "sample_bg";
+ action: PLAY_SAMPLE "sound_name6" 1.0;
+ }
+ program {
+ name: "click_tone";
+ signal: "mouse,down,1";
+ source: "tone_bg";
+ action: PLAY_TONE "tone-name" 0.1;
+ }
+ }
+ }
+ }
+}
+
typedef enum _Edje_Action_Type
{
- EDJE_ACTION_TYPE_NONE = 0,
- EDJE_ACTION_TYPE_STATE_SET = 1,
- EDJE_ACTION_TYPE_ACTION_STOP = 2,
- EDJE_ACTION_TYPE_SIGNAL_EMIT = 3,
- EDJE_ACTION_TYPE_DRAG_VAL_SET = 4,
- EDJE_ACTION_TYPE_DRAG_VAL_STEP = 5,
- EDJE_ACTION_TYPE_DRAG_VAL_PAGE = 6,
- EDJE_ACTION_TYPE_SCRIPT = 7,
- EDJE_ACTION_TYPE_FOCUS_SET = 8,
- EDJE_ACTION_TYPE_RESERVED00 = 9,
- EDJE_ACTION_TYPE_FOCUS_OBJECT = 10,
- EDJE_ACTION_TYPE_PARAM_COPY = 11,
- EDJE_ACTION_TYPE_PARAM_SET = 12,
- EDJE_ACTION_TYPE_LAST = 13
+ EDJE_ACTION_TYPE_NONE = 0,
+ EDJE_ACTION_TYPE_STATE_SET = 1,
+ EDJE_ACTION_TYPE_ACTION_STOP = 2,
+ EDJE_ACTION_TYPE_SIGNAL_EMIT = 3,
+ EDJE_ACTION_TYPE_DRAG_VAL_SET = 4,
+ EDJE_ACTION_TYPE_DRAG_VAL_STEP = 5,
+ EDJE_ACTION_TYPE_DRAG_VAL_PAGE = 6,
+ EDJE_ACTION_TYPE_SCRIPT = 7,
+ EDJE_ACTION_TYPE_FOCUS_SET = 8,
+ EDJE_ACTION_TYPE_RESERVED00 = 9,
+ EDJE_ACTION_TYPE_FOCUS_OBJECT = 10,
+ EDJE_ACTION_TYPE_PARAM_COPY = 11,
+ EDJE_ACTION_TYPE_PARAM_SET = 12,
+ EDJE_ACTION_TYPE_SOUND_SAMPLE = 13,
+ EDJE_ACTION_TYPE_SOUND_TONE = 14,
+ EDJE_ACTION_TYPE_LAST = 15
} Edje_Action_Type;
typedef enum _Edje_Tween_Mode
*/
EAPI const Edje_External_Type *edje_external_type_get (const char *type_name);
- EAPI Eina_Bool edje_module_load (const char *module);
+ EAPI Eina_Module *edje_module_load (const char *module);
EAPI const Eina_List *edje_available_modules_get (void);
/* perspective info for maps inside edje objects */
@EVIL_CFLAGS@ \
@EDJE_CFLAGS@ \
@ECORE_IMF_CFLAGS@ \
-@EFL_EDJE_BUILD@
+@EFL_EDJE_BUILD@ \
+@REMIX_CFLAGS@ \
+@SNDFILE_CFLAGS@
lib_LTLIBRARIES = libedje.la
edje_message_queue.c \
edje_misc.c \
edje_module.c \
+edje_multisense.c \
edje_program.c \
edje_script_only.c \
edje_smart.c \
libedje_la_SOURCES = $(base_sources)
endif
-libedje_la_LIBADD = @EDJE_LIBS@ @ECORE_IMF_LIBS@ @EVIL_LIBS@ -lm
+libedje_la_LIBADD = @EDJE_LIBS@ @ECORE_IMF_LIBS@ @EVIL_LIBS@ @REMIX_LIBS@ @SNDFILE_LIBS@ -lm
libedje_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ @release_info@
EXTRA_DIST = edje_private.h edje_container.h edje_convert.h
Eet_Data_Descriptor *_edje_edd_edje_image_directory_set_entry = NULL;
Eet_Data_Descriptor *_edje_edd_edje_limit = NULL;
Eet_Data_Descriptor *_edje_edd_edje_limit_pointer = NULL;
+Eet_Data_Descriptor *_edje_edd_edje_sound_sample = NULL;
+Eet_Data_Descriptor *_edje_edd_edje_sound_tone = NULL;
+Eet_Data_Descriptor *_edje_edd_edje_sound_directory = NULL;
Eet_Data_Descriptor *_edje_edd_edje_program = NULL;
Eet_Data_Descriptor *_edje_edd_edje_program_pointer = NULL;
Eet_Data_Descriptor *_edje_edd_edje_program_target = NULL;
FREED(_edje_edd_edje_image_directory_entry);
FREED(_edje_edd_edje_limit);
FREED(_edje_edd_edje_limit_pointer);
+ FREED(_edje_edd_edje_sound_sample);
+ FREED(_edje_edd_edje_sound_tone);
+ FREED(_edje_edd_edje_sound_directory);
FREED(_edje_edd_edje_program);
FREED(_edje_edd_edje_program_pointer);
FREED(_edje_edd_edje_program_target);
EET_DATA_DESCRIPTOR_ADD_VAR_ARRAY(_edje_edd_edje_image_directory, Edje_Image_Directory, "entries", entries, _edje_edd_edje_image_directory_entry);
EET_DATA_DESCRIPTOR_ADD_VAR_ARRAY(_edje_edd_edje_image_directory, Edje_Image_Directory, "sets", sets, _edje_edd_edje_image_directory_set);
+ /* Sound */
+ EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Edje_Sound_Sample);
+ _edje_edd_edje_sound_sample =
+ eet_data_descriptor_file_new(&eddc);
+ EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_sound_sample, Edje_Sound_Sample, "name", name, EET_T_STRING);
+ EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_sound_sample, Edje_Sound_Sample, "snd_src", snd_src, EET_T_STRING);
+ EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_sound_sample, Edje_Sound_Sample, "compression", compression, EET_T_INT);
+ EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_sound_sample, Edje_Sound_Sample, "mode", mode, EET_T_INT);
+ EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_sound_sample, Edje_Sound_Sample, "quality", quality, EET_T_DOUBLE);
+ EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_sound_sample, Edje_Sound_Sample, "id", id, EET_T_INT);
+ EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Edje_Sound_Tone);
+ _edje_edd_edje_sound_tone =
+ eet_data_descriptor_file_new(&eddc);
+ EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_sound_tone, Edje_Sound_Tone, "name", name, EET_T_STRING);
+ EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_sound_tone, Edje_Sound_Tone, "value", value, EET_T_INT);
+ EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_sound_tone, Edje_Sound_Tone, "id", id, EET_T_INT);
+
+ EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Edje_Sound_Directory);
+ _edje_edd_edje_sound_directory =
+ eet_data_descriptor_file_new(&eddc);
+ EET_DATA_DESCRIPTOR_ADD_VAR_ARRAY(_edje_edd_edje_sound_directory, Edje_Sound_Directory, "samples", samples, _edje_edd_edje_sound_sample);
+ EET_DATA_DESCRIPTOR_ADD_VAR_ARRAY(_edje_edd_edje_sound_directory, Edje_Sound_Directory, "tones", tones, _edje_edd_edje_sound_tone);
+
/* collection directory */
EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Edje_Part_Collection_Directory_Entry);
_edje_edd_edje_part_collection_directory_entry =
EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_file, Edje_File, "feature_ver", feature_ver, EET_T_INT);
EET_DATA_DESCRIPTOR_ADD_SUB(_edje_edd_edje_file, Edje_File, "external_dir", external_dir, _edje_edd_edje_external_directory);
EET_DATA_DESCRIPTOR_ADD_SUB(_edje_edd_edje_file, Edje_File, "image_dir", image_dir, _edje_edd_edje_image_directory);
+ EET_DATA_DESCRIPTOR_ADD_SUB(_edje_edd_edje_file, Edje_File, "sound_dir", sound_dir, _edje_edd_edje_sound_directory);
EET_DATA_DESCRIPTOR_ADD_LIST(_edje_edd_edje_file, Edje_File, "styles", styles, _edje_edd_edje_style);
EET_DATA_DESCRIPTOR_ADD_LIST(_edje_edd_edje_file, Edje_File, "color_classes", color_classes, _edje_edd_edje_color_class);
EET_DATA_DESCRIPTOR_ADD_HASH(_edje_edd_edje_file, Edje_File, "data", data, _edje_edd_edje_string);
EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_program, Edje_Program, "in.from", in.from, EET_T_DOUBLE);
EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_program, Edje_Program, "in.range", in.range, EET_T_DOUBLE);
EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_program, Edje_Program, "action", action, EET_T_INT);
+
+ EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_program, Edje_Program, "sample_name", sample_name, EET_T_STRING);
+ EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_program, Edje_Program, "tone_name", tone_name, EET_T_STRING);
+ EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_program, Edje_Program ,"duration", duration, EET_T_DOUBLE);
+ EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_program, Edje_Program ,"speed", speed, EET_T_DOUBLE);
EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_program, Edje_Program, "state", state, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_program, Edje_Program, "state2", state2, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_program, Edje_Program, "value", value, EET_T_DOUBLE);
* set_state(part_id, state[], Float:state_val)
* get_state(part_id, dst[], maxlen, &Float:val)
* set_tween_state(part_id, Float:tween, state1[], Float:state1_val, state2[], Float:state2_val)
+ * play_sample(sample_name, speed)
+ * play_tone(tone_name, duration)
* run_program(program_id)
* Direction:get_drag_dir(part_id)
* get_drag(part_id, &Float:dx, &Float:&dy)
return -1;
}
+static Embryo_Cell
+_edje_embryo_fn_play_sample(Embryo_Program *ep, Embryo_Cell *params)
+{
+ Edje *ed;
+ char *sample_name = NULL;
+ float speed = 1.0;
+
+ CHKPARAM(1);
+ ed = embryo_program_data_get(ep);
+ GETSTR(sample_name, params[1]);
+ if ((!sample_name)) return 0;
+ speed = EMBRYO_CELL_TO_FLOAT(params[2]);
+ _edje_multisense_internal_sound_sample_play(ed, sample_name, (double)speed);
+ return 0;
+}
+
+static Embryo_Cell
+_edje_embryo_fn_play_tone(Embryo_Program *ep, Embryo_Cell *params)
+{
+ Edje *ed;
+ char *tone_name = NULL;
+ float duration = 0.1;
+
+ CHKPARAM(2);
+ ed = embryo_program_data_get(ep);
+ GETSTR(tone_name, params[1]);
+ if ((!tone_name)) return 0;
+ duration = EMBRYO_CELL_TO_FLOAT(params[2]);
+ _edje_multisense_internal_sound_tone_play(ed, tone_name, (double) duration);
+ return 0;
+}
+
/* set_state(part_id, state[], Float:state_val) */
static Embryo_Cell
_edje_embryo_fn_set_state(Embryo_Program *ep, Embryo_Cell *params)
embryo_program_native_call_add(ep, "stop_programs_on", _edje_embryo_fn_stop_programs_on);
embryo_program_native_call_add(ep, "set_min_size", _edje_embryo_fn_set_min_size);
embryo_program_native_call_add(ep, "set_max_size", _edje_embryo_fn_set_max_size);
-
+ embryo_program_native_call_add(ep, "play_sample", _edje_embryo_fn_play_sample);
+ embryo_program_native_call_add(ep, "play_tone", _edje_embryo_fn_play_tone);
embryo_program_native_call_add(ep, "send_message", _edje_embryo_fn_send_message);
embryo_program_native_call_add(ep, "get_geometry", _edje_embryo_fn_get_geometry);
embryo_program_native_call_add(ep, "custom_state", _edje_embryo_fn_custom_state);
free(edf->image_dir->sets);
free(edf->image_dir);
}
+ if (edf->sound_dir)
+ {
+ unsigned int i;
+
+ if (edf->free_strings)
+ {
+ for (i = 0; i < edf->sound_dir->samples_count; ++i)
+ {
+ eina_stringshare_del(edf->sound_dir->samples[i].name);
+ eina_stringshare_del(edf->sound_dir->samples[i].snd_src);
+ }
+
+ for (i = 0; i < edf->sound_dir->tones_count; ++i)
+ eina_stringshare_del(edf->sound_dir->tones[i].name);
+ }
+ free(edf->sound_dir->samples);
+ free(edf->sound_dir->tones);
+ free(edf->sound_dir);
+ }
if (edf->external_dir)
{
if (pr->filter.state) eina_stringshare_del(pr->filter.state);
if (pr->state) eina_stringshare_del(pr->state);
if (pr->state2) eina_stringshare_del(pr->state2);
+ if (pr->sample_name) eina_stringshare_del(pr->sample_name);
+ if (pr->tone_name) eina_stringshare_del(pr->tone_name);
}
EINA_LIST_FREE(pr->targets, prt)
free(prt);
_edje_external_init();
_edje_module_init();
_edje_message_init();
+ _edje_multisense_init();
_edje_real_part_mp = eina_mempool_add("chained_mempool",
"Edje_Real_Part", NULL,
_edje_real_part_state_mp = NULL;
_edje_real_part_mp = NULL;
+ _edje_multisense_shutdown();
_edje_message_shutdown();
_edje_module_shutdown();
_edje_external_shutdown();
# define EDJE_MODULE_NAME "module.so"
#endif
-EAPI Eina_Bool
+EAPI Eina_Module *
edje_module_load(const char *module)
{
const char *path;
Eina_List *l;
+ Eina_Module *em = NULL;
- EINA_SAFETY_ON_NULL_RETURN_VAL(module, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(module, NULL);
- if (eina_hash_find(_registered_modules, module))
- return EINA_TRUE;
+ em = (Eina_Module *)eina_hash_find(_registered_modules, module);
+ if (em) return em;
EINA_LIST_FOREACH(_modules_paths, l, path)
{
- Eina_Module *em;
- char tmp[PATH_MAX];
+ char tmp[PATH_MAX];
- snprintf(tmp, sizeof (tmp), "%s/%s/%s/" EDJE_MODULE_NAME, path, module, MODULE_ARCH
+ snprintf(tmp, sizeof (tmp), "%s/%s/%s/" EDJE_MODULE_NAME, path, module, MODULE_ARCH
#ifdef EDJE_EXTRA_MODULE_NAME
, module
#endif
);
- em = eina_module_new(tmp);
- if (!em) continue ;
-
- if (!eina_module_load(em))
- {
- eina_module_free(em);
- continue ;
- }
-
- return !!eina_hash_add(_registered_modules, module, em);
+ em = eina_module_new(tmp);
+ if (!em) continue;
+
+ if (!eina_module_load(em))
+ {
+ eina_module_free(em);
+ continue;
+ }
+ if (eina_hash_add(_registered_modules, module, em))
+ return em;
}
- ERR("Could not find the module %s", module);
- return EINA_FALSE;
+ return NULL;
}
void
--- /dev/null
+#include "config.h"
+#include <string.h>
+#include <fcntl.h>
+#include <Eina.h>
+#include <Edje.h>
+#include "edje_private.h"
+
+typedef struct _Multisense_Data
+{
+ 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;
+
+ MULTISENSE_SOUND_PLAYER_GET_FUNC multisense_sound_player_get;
+#endif
+}Multisense_Data;
+
+#define BUF_LEN 64
+#define SND_PROCESS_LENGTH 2048
+
+static Ecore_Thread *player_thread = NULL;
+static Eina_Bool pipe_initialized = EINA_FALSE;
+static int command_pipe[2];
+
+typedef enum _Edje_Sound_Action_Type
+{
+ 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;
+};
+
+struct _Edje_Tone_Action
+{
+ 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;
+};
+
+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_load(ms_factory);
+ if (!m) goto err;
+
+#ifdef HAVE_LIBREMIX
+ msdata->msenv->remixenv = remix_init();
+#endif
+
+ multisense_factory_init =
+ eina_module_symbol_get(m, "multisense_factory_init");
+ if (multisense_factory_init) multisense_factory_init(msdata->msenv);
+
+#ifdef HAVE_LIBREMIX
+ 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));
+#endif
+ return msdata;
+
+err:
+ if (msdata)
+ {
+#ifdef HAVE_LIBREMIX
+ if (msdata->deck) remix_destroy(msdata->msenv->remixenv, msdata->deck);
+ if (msdata->msenv->remixenv) remix_purge(msdata->msenv->remixenv);
+#endif
+ if (msdata->msenv) free(msdata->msenv);
+ free(msdata);
+ }
+ return NULL;
+}
+
+#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;
+}
+
+
+static RemixBase *
+edje_remix_sample_create(Multisense_Data *msdata, Edje*ed, Edje_Sample_Action *action)
+{
+ RemixBase *remix_snd = NULL;
+ Edje_Sound_Sample *sample;
+ int i;
+ char snd_id_str[16];
+
+ 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;
+ 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);
+ 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);
+ }
+}
+#endif
+
+static void
+_player_job(void *data __UNUSED__, Ecore_Thread *th)
+{
+ fd_set wait_fds;
+#ifdef HAVE_LIBREMIX
+ RemixBase *sound;
+ RemixCount process_len;
+#endif
+ Multisense_Data *msdata = init_multisense_environment();
+ if (!msdata) return;
+
+ fcntl(command_pipe[0], F_SETFL, O_NONBLOCK);
+ FD_ZERO(&wait_fds);
+ FD_SET(command_pipe[0], &wait_fds);
+
+#ifdef HAVE_LIBREMIX
+ while (!ecore_thread_check(th))
+ {
+ if (!msdata->remaining)
+ {
+ //Cleanup already played sound sources
+ EINA_LIST_FREE(msdata->snd_src_list, sound)
+ {
+ remix_destroy(msdata->msenv->remixenv, sound);
+ }
+ //wait for new sound
+ select(command_pipe[0] + 1, &wait_fds, NULL, NULL, 0);
+ }
+ //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);
+ }
+
+ //cleanup Remix stuffs
+ remix_destroy(msdata->msenv->remixenv, msdata->player);
+ remix_destroy(msdata->msenv->remixenv, msdata->deck);
+ remix_purge(msdata->msenv->remixenv);
+#endif
+
+ free(msdata->msenv);
+ free(msdata);
+ close(command_pipe[0]);
+ close(command_pipe[1]);
+}
+
+static void
+_player_cancel(void *data __UNUSED__, Ecore_Thread *th __UNUSED__)
+{
+ player_thread = NULL;
+}
+
+static void
+_player_end(void *data __UNUSED__, Ecore_Thread *th __UNUSED__)
+{
+ player_thread = NULL;
+}
+
+Eina_Bool
+_edje_multisense_internal_sound_sample_play(Edje *ed, const char *sample_name, const double speed)
+{
+ ssize_t size = 0;
+#ifdef ENABLE_MULTISENSE
+ Edje_Multisense_Sound_Action command;
+
+ if ((!pipe_initialized) && (!player_thread)) return EINA_FALSE;
+
+ 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));
+#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;
+
+ if ((!pipe_initialized) && (!player_thread)) 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));
+#endif
+ return (size == sizeof(Edje_Multisense_Sound_Action));
+
+}
+
+/* Initialize the modules in main thread. to avoid dlopen issue in the Threads */
+void
+_edje_multisense_init(void)
+{
+#ifdef ENABLE_MULTISENSE
+ if (!pipe_initialized && (pipe(command_pipe) != -1))
+ pipe_initialized = EINA_TRUE;
+
+ if (!player_thread)
+ player_thread = ecore_thread_run(_player_job, _player_end, _player_cancel, NULL);
+#endif
+}
+
+void
+_edje_multisense_shutdown(void)
+{
+#ifdef ENABLE_MULTISENSE
+ if (pipe_initialized)
+ {
+ close(command_pipe[1]);
+ close(command_pipe[0]);
+ }
+ if (player_thread) ecore_thread_cancel(player_thread);
+#endif
+}
typedef struct _Edje_Image_Directory_Set Edje_Image_Directory_Set;
typedef struct _Edje_Image_Directory_Set_Entry Edje_Image_Directory_Set_Entry;
typedef struct _Edje_Limit Edje_Limit;
+typedef struct _Edje_Sound_Sample Edje_Sound_Sample;
+typedef struct _Edje_Sound_Tone Edje_Sound_Tone;
+typedef struct _Edje_Sound_Directory Edje_Sound_Directory;
typedef struct _Edje_Program Edje_Program;
typedef struct _Edje_Program_Target Edje_Program_Target;
typedef struct _Edje_Program_After Edje_Program_After;
#define EDJE_IMAGE_SOURCE_TYPE_EXTERNAL 3
#define EDJE_IMAGE_SOURCE_TYPE_LAST 4
+#define EDJE_SOUND_SOURCE_TYPE_NONE 0
+#define EDJE_SOUND_SOURCE_TYPE_INLINE_RAW 1
+#define EDJE_SOUND_SOURCE_TYPE_INLINE_COMP 2
+#define EDJE_SOUND_SOURCE_TYPE_INLINE_LOSSY 3
+#define EDJE_SOUND_SOURCE_TYPE_INLINE_AS_IS 4
+
#define EDJE_VAR_NONE 0
#define EDJE_VAR_INT 1
#define EDJE_VAR_FLOAT 2
Edje_External_Directory *external_dir;
Edje_Image_Directory *image_dir;
+ Edje_Sound_Directory *sound_dir;
Eina_List *styles;
Eina_List *color_classes;
} size;
};
+struct _Edje_Sound_Sample /*Sound Sample*/
+{
+ const char *name; /* the nominal name of the sound */
+ const char *snd_src; /* Sound source Wav file */
+ int compression; /* Compression - RAW, LOSSLESS COMP , LOSSY ) */
+ int mode; /* alternate source mode. 0 = none */
+ double quality;
+ int id; /* the id no. of the sound */
+};
+
+struct _Edje_Sound_Tone /*Sound Sample*/
+{
+ const char *name; /* the nominal name of the sound - if any */
+ int value; /* alternate source mode. 0 = none */
+ int id; /* the id no. of the sound */
+};
+
+struct _Edje_Sound_Directory
+{
+
+ Edje_Sound_Sample *samples; /* an array of Edje_Sound_Sample entries */
+ unsigned int samples_count;
+
+ Edje_Sound_Tone *tones; /* an array of Edje_Sound_Tone entries */
+ unsigned int tones_count;
+};
+
/*----------*/
struct _Edje_Program /* a conditional program to be run */
const char *signal; /* if signal emission name matches the glob here... */
const char *source; /* if part that emitted this (name) matches this glob */
+ const char *sample_name;
+ const char *tone_name;
+ double duration;
+ double speed;
struct {
const char *part;
void _edje_lib_ref(void);
void _edje_lib_unref(void);
+void _edje_multisense_init(void);
+void _edje_multisense_shutdown(void);
+Eina_Bool _edje_multisense_internal_sound_sample_play(Edje *ed, const char *sample_name, const double speed);
+Eina_Bool _edje_multisense_internal_sound_tone_play(Edje *ed, const char *tone_name, const double duration);
+
+#ifdef HAVE_LIBREMIX
+#include <remix/remix.h>
+#endif
+#include <Eina.h>
+
+typedef struct _Edje_Multisense_Env Edje_Multisense_Env;
+
+struct _Edje_Multisense_Env
+{
+#ifdef HAVE_LIBREMIX
+ RemixEnv *remixenv;
+#endif
+};
+
+typedef Eina_Bool (*MULTISENSE_FACTORY_INIT_FUNC) (Edje_Multisense_Env *);
+#ifdef HAVE_LIBREMIX
+typedef RemixBase* (*MULTISENSE_SOUND_PLAYER_GET_FUNC) (Edje_Multisense_Env *);
+#endif
+
#endif
}
}
break;
+ case EDJE_ACTION_TYPE_SOUND_SAMPLE:
+ if (_edje_block_break(ed))
+ goto break_prog;
+ _edje_multisense_internal_sound_sample_play(ed, pr->sample_name, pr->speed);
+ break;
+ case EDJE_ACTION_TYPE_SOUND_TONE:
+ if (_edje_block_break(ed))
+ goto break_prog;
+ _edje_multisense_internal_sound_tone_play(ed, pr->tone_name, pr->duration);
+ break;
case EDJE_ACTION_TYPE_PARAM_COPY:
{
Edje_Real_Part *src_part, *dst_part;
--- /dev/null
+if ENABLE_MULTISENSE\r
+FACTORY_MODULE = multisense_factory\r
+if HAVE_LIBREMIX\r
+SND_READER_MODULE = eet_snd_reader\r
+if HAVE_LIBALSA\r
+ALSA_MODULE = alsa_snd_player\r
+endif\r
+endif\r
+endif\r
+SUBDIRS = $(FACTORY_MODULE) $(SND_READER_MODULE) $(ALSA_MODULE)\r
--- /dev/null
+## Process this file with automake to produce Makefile.in
+
+MAINTAINERCLEANFILES = Makefile.in
+
+pkglibdir = $(REMIX_PLUGIN_DIR)
+
+AM_CPPFLAGS = \
+-I. \
+-DPACKAGE_LIB_DIR=\"$(libdir)/remix\" \
+-DPACKAGE_DATA_DIR=\"$(datadir)/remix\" \
+@EDJE_CFLAGS@ \
+@REMIX_CFLAGS@ \
+@ALSA_CFLAGS@
+
+pkgdir = $(REMIX_PLUGIN_DIR)
+pkg_LTLIBRARIES = libalsa_snd_player.la
+
+libalsa_snd_player_la_SOURCES = alsa_snd_player.c
+libalsa_snd_player_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -module -avoid-version @EDJE_LIBS@ @REMIX_LIBS@ @ALSA_LIBS@
+libalsa_snd_player_la_LIBTOOLFLAGS = --tag=disable-static
--- /dev/null
+/*
+ * Remix ALSA Player: ALSA audio output
+ *
+ * Govindaraju SM <govi.sm@samsung.com>, October 2011
+ * Prince Kumar Dubey <prince.dubey@samsung.com>, October 2011
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <remix/remix.h>
+#include <alsa/asoundlib.h>
+#include <Eina.h>
+
+#define ALSA_PLAYER_BUFFERLEN 2048
+
+typedef struct _AlsaPlayerData AlsaPlayerData;
+typedef short PLAYER_PCM;
+
+struct _AlsaPlayerData
+{
+ RemixPCM databuffer[ALSA_PLAYER_BUFFERLEN];
+ snd_pcm_t *alsa_dev;
+ unsigned int stereo;
+ unsigned channels;
+ unsigned int frequency;
+};
+
+/* Optimisation dependencies: none */
+static RemixBase *alsa_player_optimise(RemixEnv *env, RemixBase *base);
+
+static snd_pcm_t *
+alsa_open(int channels, unsigned samplerate)
+{
+ const char *device = "default";
+ snd_pcm_t *alsa_dev = NULL;
+ snd_pcm_hw_params_t *hw_params;
+ snd_pcm_uframes_t alsa_buffer_frames;
+ snd_pcm_uframes_t alsa_period_size;
+ int err;
+
+ alsa_buffer_frames = ALSA_PLAYER_BUFFERLEN;
+ alsa_period_size = ALSA_PLAYER_BUFFERLEN / 4;
+
+ if ((err = snd_pcm_open (&alsa_dev, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0)
+ {
+ goto catch_error;
+ }
+
+ if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0)
+ {
+ goto catch_error;
+ }
+
+ if ((err = snd_pcm_hw_params_any(alsa_dev, hw_params)) < 0)
+ {
+ printf ("cannot initialize hardware parameter structure (%s)\n", snd_strerror (err));
+ goto catch_error;
+ }
+
+ if ((err = snd_pcm_hw_params_set_access(alsa_dev, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
+ {
+ printf ("cannot set access type (%s)\n", snd_strerror (err));
+ goto catch_error;
+ }
+
+ if ((err = snd_pcm_hw_params_set_format(alsa_dev, hw_params, SND_PCM_FORMAT_FLOAT)) < 0)
+ {
+ // FIXME: handle if float format not possible
+ printf ("cannot set sample format (%s)\n", snd_strerror (err));
+ goto catch_error;
+ }
+
+ if ((err = snd_pcm_hw_params_set_rate_near(alsa_dev, hw_params, &samplerate, 0)) < 0)
+ {
+ // FIXME: get actual sample rate and tell remix
+ printf ("cannot set sample rate (%s)\n", snd_strerror (err));
+ goto catch_error;
+ }
+
+ if ((err = snd_pcm_hw_params_set_channels(alsa_dev, hw_params, channels)) < 0)
+ {
+ printf ("cannot set channel count (%s)\n", snd_strerror (err));
+ goto catch_error;
+ }
+
+ if ((err = snd_pcm_hw_params_set_buffer_size_near(alsa_dev, hw_params, &alsa_buffer_frames)) < 0)
+ {
+ fprintf (stderr, "cannot set buffer size (%s)\n", snd_strerror (err));
+ goto catch_error;
+ }
+
+ if ((err = snd_pcm_hw_params_set_period_size_near(alsa_dev, hw_params, &alsa_period_size, 0)) < 0)
+ {
+ fprintf (stderr, "cannot set period size (%s)\n", snd_strerror (err));
+ goto catch_error;
+ }
+
+ if ((err = snd_pcm_hw_params(alsa_dev, hw_params)) < 0)
+ {
+ printf ("cannot set parameters (%s)\n", snd_strerror (err));
+ goto catch_error;
+ }
+
+ snd_pcm_hw_params_free(hw_params);
+ if ((err = snd_pcm_prepare(alsa_dev)) < 0)
+ {
+ printf ("cannot prepare audio interface for use (%s)\n", snd_strerror(err));
+ goto catch_error;
+ }
+
+ catch_error:
+ if ((err < 0) && (alsa_dev != NULL))
+ {
+ snd_pcm_close (alsa_dev);
+ return NULL;
+ }
+ return alsa_dev;
+}
+
+static RemixBase *
+alsa_player_reset_device(RemixEnv *env, RemixBase *base)
+{
+ AlsaPlayerData *player_data = remix_base_get_instance_data(env, base);
+
+ if (player_data->alsa_dev)
+ {
+ snd_pcm_drain(player_data->alsa_dev);
+ snd_pcm_close(player_data->alsa_dev);
+ }
+ player_data->alsa_dev = alsa_open(player_data->channels, player_data->frequency);
+ if (!player_data->alsa_dev)
+ {
+ remix_set_error(env, REMIX_ERROR_SYSTEM);
+ return RemixNone;
+ }
+ return base;
+}
+
+static RemixBase *
+alsa_player_init(RemixEnv *env, RemixBase *base, CDSet *parameters __UNUSED__)
+{
+ CDSet *channels;
+ AlsaPlayerData *player_data = calloc(1, sizeof(AlsaPlayerData));
+
+ if (!player_data)
+ {
+ remix_set_error(env, REMIX_ERROR_SYSTEM);
+ return RemixNone;
+ }
+
+ remix_base_set_instance_data(env, base, player_data);
+ channels = remix_get_channels(env);
+
+ player_data->channels = cd_set_size(env, channels);
+ if (player_data->channels == 1)
+ player_data->stereo = 0;
+ else if (player_data->channels == 2)
+ player_data->stereo = 1;
+
+ player_data->frequency = remix_get_samplerate(env);
+ alsa_player_reset_device(env, base);
+ base = alsa_player_optimise(env, base);
+ return base;
+}
+
+static RemixBase *
+alsa_player_clone(RemixEnv *env, RemixBase *base __UNUSED__)
+{
+ RemixBase *new_player = remix_base_new (env);
+ alsa_player_init(env, new_player, NULL);
+ return new_player;
+}
+
+static int
+alsa_player_destroy(RemixEnv *env, RemixBase *base)
+{
+ AlsaPlayerData *player_data = remix_base_get_instance_data(env, base);
+
+ if (player_data->alsa_dev)
+ {
+ snd_pcm_drain(player_data->alsa_dev);
+ snd_pcm_close(player_data->alsa_dev);
+ }
+ free(player_data);
+ return 0;
+}
+
+static int
+alsa_player_ready(RemixEnv *env, RemixBase *base)
+{
+ AlsaPlayerData *player_data = remix_base_get_instance_data(env, base);
+ RemixCount nr_channels;
+ CDSet *channels;
+ int samplerate;
+
+ channels = remix_get_channels (env);
+ samplerate = (int)remix_get_samplerate(env);
+ nr_channels = cd_set_size(env, channels);
+ return ((samplerate == (int)player_data->frequency) &&
+ (((nr_channels == 1) && (player_data->stereo == 0)) ||
+ ((nr_channels > 1) && (player_data->stereo == 1))));
+}
+
+static RemixBase *
+alsa_player_prepare(RemixEnv *env, RemixBase *base)
+{
+ alsa_player_reset_device(env, base);
+ return base;
+}
+
+static RemixCount
+alsa_player_playbuffer(RemixEnv *env __UNUSED__, AlsaPlayerData *player, RemixPCM *data, RemixCount count)
+{
+ return snd_pcm_writei(player->alsa_dev, data, count);
+}
+
+static RemixCount
+alsa_player_chunk(RemixEnv *env, RemixChunk *chunk, RemixCount offset, RemixCount count, int channelname __UNUSED__, void *data)
+{
+ AlsaPlayerData *player = data;
+ RemixCount remaining = count, written = 0, n, playcount;
+ RemixPCM *d;
+
+ while (remaining > 0)
+ {
+ playcount = MIN(remaining, ALSA_PLAYER_BUFFERLEN);
+
+ d = &chunk->data[offset];
+ n = alsa_player_playbuffer(env, player, d, playcount);
+
+ if (n == -1) return -1;
+ else n /= sizeof (PLAYER_PCM);
+
+ offset += n;
+ written += n;
+ remaining -= n;
+ }
+ return written;
+}
+
+static RemixCount
+alsa_player_process(RemixEnv *env, RemixBase *base, RemixCount count, RemixStream *input, RemixStream *output __UNUSED__)
+{
+ AlsaPlayerData *player_data = remix_base_get_instance_data(env, base);
+ RemixCount nr_channels = remix_stream_nr_channels(env, input);
+ RemixCount remaining = count, processed = 0, n, nn;
+
+ if ((nr_channels == 1) && (player_data->stereo == 0))
+ { /*MONO*/
+ return remix_stream_chunkfuncify(env, input, count,
+ alsa_player_chunk, player_data);
+ }
+ else if ((nr_channels == 2) && (player_data->stereo == 1))
+ { /*STEREO*/
+ while (processed < count)
+ {
+ n = MIN(remaining, ALSA_PLAYER_BUFFERLEN);
+ n = remix_stream_interleave_2(env, input,
+ REMIX_CHANNEL_LEFT,
+ REMIX_CHANNEL_RIGHT,
+ player_data->databuffer, n);
+ nn = alsa_player_playbuffer(env, player_data,
+ player_data->databuffer, n);
+ processed += n;
+ remaining -= n;
+ }
+ return processed;
+ }
+ printf ("[alsa_player_process] unsupported stream/output channel\n");
+ printf ("combination %ld / %d\n", nr_channels, player_data->stereo ? 2 : 1);
+ return -1;
+}
+
+static RemixCount
+alsa_player_length(RemixEnv *env __UNUSED__, RemixBase *base __UNUSED__)
+{
+ return REMIX_COUNT_INFINITE;
+}
+
+static RemixCount
+alsa_player_seek(RemixEnv *env __UNUSED__, RemixBase *base __UNUSED__, RemixCount count __UNUSED__)
+{
+ return count;
+}
+
+static int
+alsa_player_flush (RemixEnv *env, RemixBase *base)
+{
+ alsa_player_reset_device(env, base);
+ return 0;
+}
+
+static struct _RemixMethods _alsa_player_methods =
+{
+ alsa_player_clone,
+ alsa_player_destroy,
+ alsa_player_ready,
+ alsa_player_prepare,
+ alsa_player_process,
+ alsa_player_length,
+ alsa_player_seek,
+ alsa_player_flush,
+};
+
+static RemixBase *
+alsa_player_optimise(RemixEnv *env, RemixBase *base)
+{
+ remix_base_set_methods(env, base, &_alsa_player_methods);
+ return base;
+}
+
+static struct _RemixMetaText alsa_player_metatext =
+{
+ "alsa_snd_player",
+ "ALSA sound player for Remix",
+ "Output the audio stream into ALSA Driver",
+ "Copyright (C) 2011, Samsung Electronics Co., Ltd.",
+ "http://www.samsung.com",
+ REMIX_ONE_AUTHOR("Govindaraju SM", "prince.dubey@samsung.com"),
+};
+
+static struct _RemixPlugin alsa_player_plugin =
+{
+ &alsa_player_metatext,
+ REMIX_FLAGS_NONE,
+ CD_EMPTY_SET, /* init scheme */
+ alsa_player_init,
+ CD_EMPTY_SET, /* process scheme */
+ NULL, /* suggests */
+ NULL, /* plugin data */
+ NULL /* destroy */
+};
+
+EAPI CDList *
+remix_load(RemixEnv *env)
+{
+ CDList *plugins = cd_list_new(env);
+ plugins = cd_list_prepend(env, plugins, CD_POINTER(&alsa_player_plugin));
+ return plugins;
+}
--- /dev/null
+MAINTAINERCLEANFILES = Makefile.in
+
+pkglibdir = $(REMIX_PLUGIN_DIR)
+
+AM_CPPFLAGS = \
+-I. \
+-DPACKAGE_LIB_DIR=\"$(libdir)/remix\" \
+-DPACKAGE_DATA_DIR=\"$(datadir)/remix\" \
+@EDJE_CFLAGS@ \
+@REMIX_CFLAGS@
+
+pkgdir = $(REMIX_PLUGIN_DIR)
+pkg_LTLIBRARIES = libeet_sndfile_reader.la
+
+libeet_sndfile_reader_la_SOURCES = eet_snd_reader.c
+libeet_sndfile_reader_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -module -avoid-version @EDJE_LIBS@ @REMIX_LIBS@
+libeet_sndfile_reader_la_LIBTOOLFLAGS = --tag=disable-static
--- /dev/null
+/*
+ * RemixSnd_eetfile: a libsnd EET Virtual file handler
+ *
+ * Govindaraju SM <govi.sm@samsung.com>, August 2011
+ * Prince Kumar Dubey <prince.dubey@samsung.com>, August 2011
+ */
+
+#include "config.h"
+#include <math.h>
+#include <sndfile.h>
+#include <remix/remix.h>
+#include <Eet.h>
+
+#define PATH_KEY 1
+#define SOUND_ID_KEY 2
+#define SPEED_KEY 3
+#define BLOCK_FRAMES 8192
+
+static RemixBase *remix_eet_sndfile_optimise(RemixEnv *env, RemixBase *sndfile);
+
+typedef struct _VIO_DATA VIO_DATA;
+typedef struct _SndInstanceData SndInstanceData;
+
+struct _VIO_DATA
+{
+ sf_count_t offset, length;
+ const char *data;
+};
+
+struct _SndInstanceData
+{
+ /* plugin parameters */
+ char *path;
+ char *sound_id;
+ double speed;
+
+ /* Edj & Sndfile Reader */
+ Eet_File *efp;
+ SNDFILE *pcm_fp;
+ SF_INFO *snd_info;
+ VIO_DATA *vio_data;
+
+ /* PCM buffers */
+ RemixPCM *readbuf;
+ RemixPCM *inbuf;
+ RemixPCM *outbuf;
+
+ /* Resample stuffs */
+ RemixPCM prevreadbuf[2];
+ int enable_resample;
+ double rs_ratio;
+ RemixCount resample_len;
+ RemixCount in_avail;
+ RemixCount out_generated;
+ RemixCount required_resamples;
+};
+
+static sf_count_t
+eet_snd_file_get_length(void *user_data)
+{
+ VIO_DATA *vf = user_data;
+ return vf->length;
+}
+
+static sf_count_t
+eet_snd_file_seek(sf_count_t offset, int whence, void *user_data)
+{
+ VIO_DATA *vf = user_data;
+
+ switch (whence)
+ {
+ case SEEK_SET:
+ vf->offset = offset;
+ break;
+ case SEEK_CUR:
+ vf->offset += offset;
+ break;
+ case SEEK_END:
+ vf->offset = vf->length + offset;
+ break;
+ default:
+ break;
+ }
+ return vf->offset;
+}
+
+static sf_count_t
+eet_snd_file_read(void *ptr, sf_count_t count, void *user_data)
+{
+ VIO_DATA *vf = user_data;
+
+ if ((vf->offset + count) > vf->length)
+ count = vf->length - vf->offset;
+ memcpy(ptr, vf->data + vf->offset, count);
+ vf->offset += count;
+ return count;
+}
+
+static sf_count_t
+eet_snd_file_tell(void *user_data)
+{
+ VIO_DATA *vf = user_data;
+ return vf->offset;
+}
+
+static int
+remix_init_resampler_data(RemixEnv *env, RemixBase *base)
+{
+ SndInstanceData *si = remix_base_get_instance_data(env, base);
+
+ si->rs_ratio = remix_get_samplerate(env) / si->snd_info->samplerate;
+ si->rs_ratio /= si->speed;
+ si->resample_len = (si->snd_info->frames * si->rs_ratio);
+
+ si->outbuf = malloc(sizeof(RemixPCM) * BLOCK_FRAMES * 2);
+ if (!si->outbuf) return 0;
+ if ((si->rs_ratio == 1.0)/* && (si->snd_info->channels == 2)*/)
+ {
+ si->enable_resample = 0;
+ return 1;
+ }
+ else
+ si->enable_resample = 1;
+
+ si->in_avail = 0;
+ si->out_generated = 0;
+ si->inbuf = malloc(sizeof(RemixPCM) * BLOCK_FRAMES *
+ si->snd_info->channels);
+ if (!si->inbuf) return 0;
+ return 1;
+}
+
+static RemixBase *
+remix_eet_sndfile_create(RemixEnv *env, RemixBase *sndfile, const char *path, const char *sound_id, const double speed)
+{
+ SF_VIRTUAL_IO *eet_vio;
+ SndInstanceData *si;
+ const void *sound_data;
+ int sound_size;
+
+ if ((!path) || (!sound_id)) return NULL;
+
+ si = calloc(1, sizeof(SndInstanceData));
+ if (!si) goto err;
+ remix_base_set_instance_data(env, sndfile, si);
+
+ si->path = strdup(path);
+ si->sound_id = strdup(sound_id);
+ si->speed = speed;
+
+ si->efp = eet_open(path, EET_FILE_MODE_READ);
+ if (!si->efp) goto err;
+
+ // xxx: eet_read_direct does not work on Threads, using eet_read.
+ sound_data = eet_read(si->efp, sound_id, &(sound_size));
+ eet_close(si->efp);
+ si->efp = NULL;
+ if (sound_data == NULL) goto err;
+
+ eet_vio = calloc(1, sizeof(SF_VIRTUAL_IO));
+ if (!eet_vio) goto err;
+
+ /* Set up func pointers to read snd file directly from EET. */
+ eet_vio->get_filelen = eet_snd_file_get_length;
+ eet_vio->seek = eet_snd_file_seek;
+ eet_vio->read = eet_snd_file_read;
+ eet_vio->tell = eet_snd_file_tell;
+
+ si->vio_data = calloc(1, sizeof(VIO_DATA));
+ if (!si->vio_data) goto err;
+ si->vio_data->offset = 0;
+ si->vio_data->length = sound_size;
+ si->vio_data->data = sound_data;
+
+ si->snd_info = calloc(1, sizeof(SF_INFO));
+ if (!si->snd_info) goto err;
+
+ si->pcm_fp = sf_open_virtual(eet_vio, SFM_READ, si->snd_info, si->vio_data);
+ if (!si->pcm_fp) goto err;
+ free(eet_vio);
+ eet_vio = NULL;
+
+ if (!remix_init_resampler_data(env, sndfile)) goto err;
+ si->out_generated = 0;
+
+ return sndfile;
+
+err:
+ if (eet_vio) free(eet_vio);
+ remix_set_error(env, REMIX_ERROR_SYSTEM);
+ remix_destroy(env, (RemixBase *)sndfile);
+ return RemixNone;
+}
+
+static RemixBase *
+remix_eet_sndfile_reader_init(RemixEnv *env, RemixBase *base, CDSet *parameters)
+{
+ char *file_path, *sound_id;
+ double speed;
+
+ file_path = (cd_set_find(env, parameters, PATH_KEY)).s_string;
+ sound_id = (cd_set_find(env, parameters, SOUND_ID_KEY)).s_string;
+ speed = (cd_set_find(env, parameters, SPEED_KEY)).s_double;
+
+ if (!remix_eet_sndfile_create(env, base, file_path, sound_id, speed))
+ return RemixNone;
+ remix_eet_sndfile_optimise (env, base);
+ return base;
+}
+
+static RemixBase *
+remix_eet_sndfile_clone(RemixEnv *env, RemixBase *base)
+{
+ SndInstanceData *si = remix_base_get_instance_data(env, base);
+ RemixBase *new_sndfile = remix_base_new(env);
+
+ remix_eet_sndfile_create(env, new_sndfile, si->path, si->sound_id, si->speed);
+ remix_eet_sndfile_optimise(env, new_sndfile);
+ return new_sndfile;
+}
+
+static int
+remix_eet_sndfile_destroy(RemixEnv *env, RemixBase *base)
+{
+ SndInstanceData *si = remix_base_get_instance_data(env, base);
+ if (si)
+ {
+ sf_close (si->pcm_fp);
+ eet_close(si->efp);
+ if (si->path) free(si->path);
+ if (si->sound_id) free(si->sound_id);
+ if (si->snd_info) free(si->snd_info);
+ if (si->efp) eet_close(si->efp);
+ if (si->inbuf) free(si->inbuf);
+ if (si->outbuf) free(si->outbuf);
+ if (si->vio_data) free(si->vio_data);
+ free(si);
+ }
+ if (base) free (base);
+ return 0;
+}
+
+static int
+remix_pcm_resample(SndInstanceData *si)
+{
+ RemixPCM *src, *dst, *srcbase;
+ int i = 0, in_samples, pos, total, chnum, reqsamp, avail;
+ int interp = 1;
+
+ dst = si->outbuf + (si->out_generated * 2);
+ in_samples = (double)si->required_resamples / si->rs_ratio;
+ chnum = si->snd_info->channels;
+ reqsamp = si->required_resamples;
+ avail = si->in_avail;
+ srcbase = si->readbuf;
+ if ((interp) && (si->rs_ratio >= 1.0))
+ {
+ // linear interpolation of resampling for lower quality samples
+ // so they don't get high requency aliasing effects
+ for (i = 0; i < reqsamp; i++)
+ {
+ float fpos, fpos1;
+ RemixPCM psam[2];
+
+ fpos = (float)(i * in_samples) / (float)reqsamp;
+ pos = fpos;
+ if (pos >= avail) break;
+ fpos -= pos;
+ fpos1 = 1.0 - fpos;
+ src = srcbase + (pos * chnum);
+ if (chnum == 2)
+ {
+ if (i == 0)
+ {
+ psam[0] = si->prevreadbuf[0];
+ psam[1] = si->prevreadbuf[1];
+ }
+ else
+ {
+ psam[0] = src[0 - 2];
+ psam[1] = src[1 - 2];
+ }
+ *dst++ = (src[0] * fpos) + (psam[0] * fpos1);
+ *dst++ = (src[1] * fpos) + (psam[1] * fpos1);
+ }
+ else
+ {
+ if (i == 0)
+ psam[0] = si->prevreadbuf[0];
+ else
+ psam[0] = src[0 - 1];
+ *dst++ = (src[0] * fpos) + (psam[0] * fpos1);
+ }
+ }
+ }
+ else
+ {
+ // simple sample-picking/nearest. faster and simpler
+ for (i = 0; i < reqsamp; i++)
+ {
+ pos = (i * in_samples) / reqsamp;
+ if (pos >= avail) break;
+ src = srcbase + (pos * chnum);
+ if (chnum == 2)
+ {
+ *dst++ = src[0];
+ *dst++ = src[1];
+ }
+ else
+ *dst++ = src[0];
+ }
+ }
+ si->out_generated += i;
+ total = (i * in_samples) / reqsamp;
+ si->readbuf += total * chnum;
+ si->in_avail -= total;
+ return total;
+}
+
+/* An RemixChunkFunc for creating sndfile */
+static RemixCount
+remix_eet_sndfile_read_update(RemixEnv *env, RemixBase *sndfile, RemixCount count)
+{
+ SndInstanceData *si = remix_base_get_instance_data(env, sndfile);
+
+ si->out_generated = 0;
+ if (si->enable_resample)
+ {
+ RemixCount gen = 0;
+
+ while (gen < count)
+ {
+ if (si->in_avail <= 0)
+ {
+ si->in_avail = sf_readf_float(si->pcm_fp, si->inbuf, BLOCK_FRAMES);
+ si->readbuf = si->inbuf;
+ }
+ si->required_resamples = (count - gen);
+ remix_pcm_resample(si);
+ if (si->snd_info->channels == 2)
+ {
+ si->prevreadbuf[0] = si->readbuf[-2];
+ si->prevreadbuf[1] = si->readbuf[-1];
+ }
+ else
+ {
+ si->prevreadbuf[0] = si->readbuf[-1];
+ }
+ gen += si->out_generated;
+ }
+ si->out_generated = gen;
+ }
+ else
+ {
+ si->out_generated = sf_readf_float(si->pcm_fp, si->outbuf, count);
+ }
+ return si->out_generated;
+}
+
+static RemixCount
+remix_eet_sndfile_read_into_chunk(RemixEnv *env, RemixChunk *chunk, RemixCount offset, RemixCount count, int channelname, void *data)
+{
+ RemixBase *sndfile = data;
+ SndInstanceData *si = remix_base_get_instance_data(env, sndfile);
+ RemixPCM *d, *p;
+ RemixCount remaining = count, written = 0, n, i;
+
+ d = &chunk->data[offset];
+ n = MIN(remaining, BLOCK_FRAMES);
+ // Need parameter support to advance the data reading
+ if (channelname == 0)
+ remix_eet_sndfile_read_update(env, sndfile, n);
+ n = MIN(si->out_generated, remaining);
+ p = si->outbuf;
+ if (si->snd_info->channels > 1) p += channelname;
+ for (i = 0; i < n; i++)
+ {
+ *d++ = *p;
+ p += si->snd_info->channels;
+ }
+ if (n == 0) n = _remix_pcm_set(d, 0.0, remaining);
+ remaining -= n;
+ written += n;
+ return written;
+}
+
+static RemixCount
+remix_eet_sndfile_reader_process(RemixEnv *env, RemixBase *base, RemixCount count, RemixStream *input __UNUSED__, RemixStream *output)
+{
+ return remix_stream_chunkfuncify(env, output, count,
+ remix_eet_sndfile_read_into_chunk,
+ base);
+}
+
+static RemixCount
+remix_eet_sndfile_length(RemixEnv *env, RemixBase *base)
+{
+ SndInstanceData *si = remix_base_get_instance_data(env, base);
+ return si->resample_len;
+}
+
+static RemixCount
+remix_eet_sndfile_seek(RemixEnv *env, RemixBase *base, RemixCount offset)
+{
+ SndInstanceData *si = remix_base_get_instance_data(env, base);
+ return sf_seek(si->pcm_fp, offset, SEEK_SET);
+}
+
+static struct _RemixMethods _remix_eet_sndfile_reader_methods =
+{
+ remix_eet_sndfile_clone,
+ remix_eet_sndfile_destroy,
+ NULL, /* ready */
+ NULL, /* prepare */
+ remix_eet_sndfile_reader_process,
+ remix_eet_sndfile_length,
+ remix_eet_sndfile_seek,
+ NULL, /* flush */
+};
+
+static RemixBase *
+remix_eet_sndfile_optimise(RemixEnv *env, RemixBase *sndfile)
+{
+ remix_base_set_methods(env, sndfile, &_remix_eet_sndfile_reader_methods);
+ return sndfile;
+}
+
+static struct _RemixParameterScheme path_scheme =
+{
+ "path",
+ "Path to sound file",
+ REMIX_TYPE_STRING,
+ REMIX_CONSTRAINT_TYPE_NONE,
+ {NULL},
+ REMIX_HINT_FILENAME,
+};
+
+static struct _RemixParameterScheme sound_id_scheme =
+{
+ "sound_id",
+ "Sound Id (Key) inside EET",
+ REMIX_TYPE_STRING,
+ REMIX_CONSTRAINT_TYPE_NONE,
+ {NULL},
+ REMIX_HINT_DEFAULT,
+};
+
+static struct _RemixParameterScheme speed_scheme =
+{
+ "speed",
+ "Sound Play Speed",
+ REMIX_TYPE_FLOAT,
+ REMIX_CONSTRAINT_TYPE_NONE,
+ {NULL},
+ REMIX_HINT_DEFAULT,
+};
+
+static struct _RemixMetaText eet_sndfile_reader_metatext =
+{
+ "eet_sndfile_reader",
+ "File:: Sound file Reader from EET",
+ "Reads PCM audio files from EET bundle using libsndfile",
+ "Copyright (C) 2011, Samsung Electronics Co., Ltd.",
+ "http://www.samsung.com",
+ REMIX_ONE_AUTHOR ("govi.sm@samsung.com", "prince.dubey@samsung.com"),
+};
+
+static struct _RemixPlugin eet_sndfile_reader_plugin =
+{
+ &eet_sndfile_reader_metatext,
+ REMIX_FLAGS_NONE,
+ CD_EMPTY_SET, /* init scheme */
+ remix_eet_sndfile_reader_init,
+ CD_EMPTY_SET, /* process scheme */
+ NULL, /* suggests */
+ NULL, /* plugin data */
+ NULL /* destroy */
+};
+
+EAPI CDList *
+remix_load(RemixEnv *env)
+{
+ CDList *plugins = cd_list_new(env);
+
+ eet_sndfile_reader_plugin.init_scheme =
+ cd_set_insert(env, eet_sndfile_reader_plugin.init_scheme, PATH_KEY,
+ CD_POINTER(&path_scheme));
+ eet_sndfile_reader_plugin.init_scheme =
+ cd_set_insert(env, eet_sndfile_reader_plugin.init_scheme, SOUND_ID_KEY,
+ CD_POINTER(&sound_id_scheme));
+ eet_sndfile_reader_plugin.init_scheme =
+ cd_set_insert(env, eet_sndfile_reader_plugin.init_scheme, SPEED_KEY,
+ CD_POINTER(&speed_scheme));
+
+ plugins = cd_list_prepend(env, plugins,
+ CD_POINTER(&eet_sndfile_reader_plugin));
+ return plugins;
+}
--- /dev/null
+MAINTAINERCLEANFILES = Makefile.in
+
+pkglibdir = $(datadir)/$(PACKAGE)/modules/multisense_factory
+
+AM_CPPFLAGS = \
+-I. \
+-I$(top_srcdir)/src/lib \
+-I$(top_srcdir)/src/lib/include \
+-DPACKAGE_BIN_DIR=\"$(bindir)\" \
+-DPACKAGE_LIB_DIR=\"$(libdir)\" \
+-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
+-DPACKAGE_EXAMPLES_DIR=\"$(datadir)/$(PACKAGE)/multisense_factory\" \
+@EDJE_CFLAGS@ \
+@REMIX_CFLAGS@
+
+pkgdir = $(libdir)/edje/modules/multisense_factory/$(MODULE_ARCH)
+pkg_LTLIBRARIES = module.la
+
+module_la_SOURCES = multisense_factory.c
+module_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -module -avoid-version $(top_builddir)/src/lib/libedje.la @EDJE_LIBS@ @REMIX_LIBS@
+module_la_LIBTOOLFLAGS = --tag=disable-static
--- /dev/null
+#include "config.h"\r
+#include <edje_private.h>\r
+\r
+#define DEFAULT_SAMPLERATE 44100\r
+\r
+#ifdef HAVE_LIBREMIX\r
+EAPI RemixBase *\r
+multisense_sound_player_get(Edje_Multisense_Env *msenv)\r
+{\r
+ RemixEnv *env = msenv->remixenv;\r
+ RemixPlugin *player_plugin;\r
+ RemixBase *player;\r
+ \r
+ player_plugin = remix_find_plugin(env, "alsa_snd_player");\r
+ if (!player_plugin)\r
+ {\r
+ printf("ALSA player_plugin init fail\n");\r
+ return remix_monitor_new(env);\r
+ }\r
+ player = remix_new(env, player_plugin, NULL);\r
+ return player;\r
+}\r
+#endif\r
+\r
+EAPI Eina_Bool\r
+multisense_factory_init(Edje_Multisense_Env *env)\r
+{\r
+#ifdef HAVE_LIBREMIX\r
+ remix_set_samplerate(env->remixenv, DEFAULT_SAMPLERATE);\r
+ remix_set_channels(env->remixenv, REMIX_STEREO);\r
+#endif\r
+ return EINA_TRUE;\r
+}\r