From: Prince Kumar Dubey <prince.dubey@samsung.com>

From: Govindaraju S M <govi.sm@samsung.com>
Subject: edje multisense patch for sound sample, tone and haptic play

... This is the beginning of sound (and haptic) support in Edje - it
works, but only at certain basic sample playback levels. more will come.



SVN revision: 64731
devs/devilhorns/wayland_egl
Prince Kumar Dubey 11 years ago committed by Carsten Haitzler
parent eaa1a494be
commit 3cc8139906
  1. 2
      legacy/edje/AUTHORS
  2. 165
      legacy/edje/configure.ac
  3. 4
      legacy/edje/data/include/edje.inc
  4. 18
      legacy/edje/doc/examples.dox
  5. 2
      legacy/edje/src/Makefile.am
  6. 18
      legacy/edje/src/bin/Makefile.am
  7. 8
      legacy/edje/src/bin/edje_cc.c
  8. 1
      legacy/edje/src/bin/edje_cc.h
  9. 325
      legacy/edje/src/bin/edje_cc_handlers.c
  10. 114
      legacy/edje/src/bin/edje_cc_out.c
  11. 45
      legacy/edje/src/bin/edje_decc.c
  12. 329
      legacy/edje/src/bin/edje_multisense_convert.c
  13. 25
      legacy/edje/src/bin/edje_multisense_convert.h
  14. 10
      legacy/edje/src/examples/Makefile.am
  15. 135
      legacy/edje/src/examples/multisense.edc
  16. 32
      legacy/edje/src/lib/Edje.h
  17. 7
      legacy/edje/src/lib/Makefile.am
  18. 35
      legacy/edje/src/lib/edje_data.c
  19. 37
      legacy/edje/src/lib/edje_embryo.c
  20. 21
      legacy/edje/src/lib/edje_load.c
  21. 2
      legacy/edje/src/lib/edje_main.c
  22. 37
      legacy/edje/src/lib/edje_module.c
  23. 382
      legacy/edje/src/lib/edje_multisense.c
  24. 65
      legacy/edje/src/lib/edje_private.h
  25. 10
      legacy/edje/src/lib/edje_program.c
  26. 10
      legacy/edje/src/modules/Makefile.am
  27. 20
      legacy/edje/src/modules/alsa_snd_player/Makefile.am
  28. 340
      legacy/edje/src/modules/alsa_snd_player/alsa_snd_player.c
  29. 17
      legacy/edje/src/modules/eet_snd_reader/Makefile.am
  30. 498
      legacy/edje/src/modules/eet_snd_reader/eet_snd_reader.c
  31. 21
      legacy/edje/src/modules/multisense_factory/Makefile.am
  32. 33
      legacy/edje/src/modules/multisense_factory/multisense_factory.c

@ -18,3 +18,5 @@ Shilpa Singh <shilpa.singh@samsung.com> <shilpasingh.o@gmail.com>
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>

@ -290,6 +290,157 @@ PKG_CHECK_MODULES([ECORE_IMF],
],
[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
@ -432,6 +583,10 @@ src/Makefile
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
@ -452,6 +607,16 @@ echo "Configuration Options Summary:"
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"

@ -213,3 +213,7 @@ enum State_Param
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);

@ -14,6 +14,7 @@
* @li @ref tutorial_edje_drag
* @li @ref tutorial_edje_perspective
* @li @ref tutorial_edje_animations
* @li @ref tutorial_edje_multisense
*/
/**
@ -826,3 +827,20 @@
* @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
*/

@ -1,4 +1,4 @@
## Process this file with automake to produce Makefile.in
SUBDIRS = lib bin tests examples
SUBDIRS = lib bin modules tests examples
MAINTAINERCLEANFILES = Makefile.in

@ -16,7 +16,8 @@ edje_cc_out.c \
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 \
@ -25,8 +26,8 @@ edje_cc_CPPFLAGS = \
-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@
@ -40,7 +41,7 @@ edje_decc_CPPFLAGS = \
-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
@ -48,7 +49,7 @@ edje_player_CPPFLAGS = \
-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
@ -56,7 +57,7 @@ edje_inspector_CPPFLAGS = \
-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
@ -64,9 +65,8 @@ edje_external_inspector_CPPFLAGS = \
-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

@ -12,7 +12,7 @@ int _edje_cc_log_dom = -1;
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;
@ -40,6 +40,7 @@ main_help(void)
"\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"
@ -113,6 +114,11 @@ main(int argc, char **argv)
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++;

@ -197,6 +197,7 @@ void error_and_abort(Eet_File *ef, const char *fmt, ...);
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;

@ -261,6 +261,9 @@ static void st_collections_group_programs_program_after(void);
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);
/*****/
@ -299,6 +302,13 @@ New_Statement_Handler statement_handlers[] =
{"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},
@ -663,6 +673,10 @@ New_Object_Handler object_handlers[] =
{"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},
@ -1825,12 +1839,13 @@ st_styles_style_tag(void)
..
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
@ -1840,6 +1855,219 @@ ob_collections(void)
edje_file->collection = eina_hash_string_small_new(NULL);
}
/**
@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}
*/
@ -1874,7 +2102,7 @@ ob_collections_group(void)
{
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);
@ -7005,7 +7233,7 @@ st_collections_group_programs_program_in(void)
@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
@ -7016,7 +7244,9 @@ st_collections_group_programs_program_in(void)
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
@ -7024,22 +7254,25 @@ st_collections_group_programs_program_action(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);
@ -7050,6 +7283,38 @@ st_collections_group_programs_program_action(void)
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);
@ -7068,30 +7333,30 @@ st_collections_group_programs_program_action(void)
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:
@ -7106,11 +7371,17 @@ st_collections_group_programs_program_action(void)
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);
}

@ -28,6 +28,7 @@ void *alloca (size_t);
#include "edje_cc.h"
#include "edje_convert.h"
#include "edje_multisense_convert.h"
#include <lua.h>
#include <lauxlib.h>
@ -650,6 +651,114 @@ data_write_images(Eet_File *ef, int *image_num, int *input_bytes, int *input_raw
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)
{
@ -1058,6 +1167,7 @@ data_write(void)
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;
@ -1083,6 +1193,8 @@ data_write(void)
&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);
@ -1106,6 +1218,7 @@ data_write(void)
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"
@ -1120,6 +1233,7 @@ data_write(void)
,
collection_num,
image_num,
sound_num,
font_num,
src_bytes, (src_bytes + 512) / 1024,
fmap_bytes, (fmap_bytes + 512) / 1024,

@ -370,6 +370,51 @@ output(void)
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);
}

@ -0,0 +1,329 @@
#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