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
This commit is contained in:
parent
eaa1a494be
commit
3cc8139906
|
@ -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}
|
||||
*/
|
||||
|
@ -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
|
||||
|
@ -7017,6 +7245,8 @@ st_collections_group_programs_program_in(void)
|
|||
action: FOCUS_OBJECT;\n
|
||||
action: PARAM_COPY "src_part" "src_param" "dst_part" "dst_param";\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,6 +7254,7 @@ 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;
|
||||
|
@ -7039,6 +7270,8 @@ st_collections_group_programs_program_action(void)
|
|||
"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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -7111,6 +7376,12 @@ st_collections_group_programs_program_action(void)
|
|||
case EDJE_ACTION_TYPE_PARAM_SET:
|
||||
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
|
||||
#endif
|
|
@ -0,0 +1,25 @@
|
|||
#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
|
|
@ -1,7 +1,10 @@
|
|||
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 \
|
||||
|
@ -12,7 +15,8 @@ EDCS = basic.edc \
|
|||
signals-messages.edc \
|
||||
color-class.edc \
|
||||
perspective.edc \
|
||||
animations.edc
|
||||
animations.edc \
|
||||
$(MULTISENSE_EDC_FILE)
|
||||
|
||||
filesdir = $(datadir)/$(PACKAGE)/examples
|
||||
files_DATA =
|
||||
|
@ -49,7 +53,7 @@ pkglib_PROGRAMS += \
|
|||
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)
|
||||
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -615,7 +615,9 @@ typedef enum _Edje_Action_Type
|
|||
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_SOUND_SAMPLE = 13,
|
||||
EDJE_ACTION_TYPE_SOUND_TONE = 14,
|
||||
EDJE_ACTION_TYPE_LAST = 15
|
||||
} Edje_Action_Type;
|
||||
|
||||
typedef enum _Edje_Tween_Mode
|
||||
|
@ -3798,7 +3800,7 @@ EAPI const Edje_External_Param_Info *edje_external_param_info_get (const char
|
|||
*/
|
||||
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 */
|
||||
|
|
|
@ -12,7 +12,9 @@ AM_CPPFLAGS = \
|
|||
@EVIL_CFLAGS@ \
|
||||
@EDJE_CFLAGS@ \
|
||||
@ECORE_IMF_CFLAGS@ \
|
||||
@EFL_EDJE_BUILD@
|
||||
@EFL_EDJE_BUILD@ \
|
||||
@REMIX_CFLAGS@ \
|
||||
@SNDFILE_CFLAGS@
|
||||
|
||||
lib_LTLIBRARIES = libedje.la
|
||||
|
||||
|
@ -39,6 +41,7 @@ edje_match.c \
|
|||
edje_message_queue.c \
|
||||
edje_misc.c \
|
||||
edje_module.c \
|
||||
edje_multisense.c \
|
||||
edje_program.c \
|
||||
edje_script_only.c \
|
||||
edje_smart.c \
|
||||
|
@ -127,7 +130,7 @@ else
|
|||
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
|
||||
|
|
|
@ -16,6 +16,9 @@ Eet_Data_Descriptor *_edje_edd_edje_image_directory_set = NULL;
|
|||
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;
|
||||
|
@ -169,6 +172,9 @@ _edje_edd_shutdown(void)
|
|||
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);
|
||||
|
@ -284,6 +290,29 @@ _edje_edd_init(void)
|
|||
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 =
|
||||
|
@ -341,6 +370,7 @@ _edje_edd_init(void)
|
|||
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);
|
||||
|
@ -376,6 +406,11 @@ _edje_edd_init(void)
|
|||
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);
|
||||
|
|
|
@ -72,6 +72,8 @@
|
|||
* 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)
|
||||
|
@ -824,6 +826,38 @@ _edje_embryo_fn_get_part_id(Embryo_Program *ep, Embryo_Cell *params)
|
|||
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)
|
||||
|
@ -3006,7 +3040,8 @@ _edje_embryo_script_init(Edje_Part_Collection *edc)
|
|||
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);
|
||||
|
|
|
@ -1094,6 +1094,25 @@ _edje_file_free(Edje_File *edf)
|
|||
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)
|
||||
{
|
||||
|
@ -1130,6 +1149,8 @@ _edje_program_free(Edje_Program *pr, Eina_Bool free_strings)
|
|||
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);
|
||||
|
|
|
@ -61,6 +61,7 @@ edje_init(void)
|
|||
_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,
|
||||
|
@ -123,6 +124,7 @@ _edje_shutdown_core(void)
|
|||
_edje_real_part_state_mp = NULL;
|
||||
_edje_real_part_mp = NULL;
|
||||
|
||||
_edje_multisense_shutdown();
|
||||
_edje_message_shutdown();
|
||||
_edje_module_shutdown();
|
||||
_edje_external_shutdown();
|
||||
|
|
|
@ -14,20 +14,20 @@ Eina_List *_modules_found = NULL;
|
|||
# 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];
|
||||
|
||||
snprintf(tmp, sizeof (tmp), "%s/%s/%s/" EDJE_MODULE_NAME, path, module, MODULE_ARCH
|
||||
|
@ -43,12 +43,11 @@ edje_module_load(const char *module)
|
|||
eina_module_free(em);
|
||||
continue;
|
||||
}
|
||||
|
||||
return !!eina_hash_add(_registered_modules, module, em);
|
||||
if (eina_hash_add(_registered_modules, module, em))
|
||||
return em;
|
||||
}
|
||||
|
||||
ERR("Could not find the module %s", module);
|
||||
return EINA_FALSE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -0,0 +1,382 @@
|
|||
#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
|
||||
}
|
|
@ -268,6 +268,9 @@ typedef struct _Edje_Image_Directory_Entry Edje_Image_Directory_Entry;
|
|||
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;
|
||||
|
@ -328,6 +331,12 @@ typedef struct _Edje_Text_Insert_Filter_Callback Edje_Text_Insert_Filter_Callbac
|
|||
#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
|
||||
|
@ -410,6 +419,7 @@ struct _Edje_File
|
|||
|
||||
Edje_External_Directory *external_dir;
|
||||
Edje_Image_Directory *image_dir;
|
||||
Edje_Sound_Directory *sound_dir;
|
||||
Eina_List *styles;
|
||||
Eina_List *color_classes;
|
||||
|
||||
|
@ -517,6 +527,33 @@ struct _Edje_Image_Directory_Set_Entry
|
|||
} 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 */
|
||||
|
@ -526,6 +563,10 @@ 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;
|
||||
|
@ -1921,4 +1962,28 @@ void _edje_object_orientation_inform(Evas_Object *obj);
|
|||
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
|
||||
|
|
|
@ -769,6 +769,16 @@ _edje_program_run(Edje *ed, Edje_Program *pr, Eina_Bool force, const char *ssig,
|
|||
}
|
||||
}
|
||||
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;
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
if ENABLE_MULTISENSE
|
||||
FACTORY_MODULE = multisense_factory
|
||||
if HAVE_LIBREMIX
|
||||
SND_READER_MODULE = eet_snd_reader
|
||||
if HAVE_LIBALSA
|
||||
ALSA_MODULE = alsa_snd_player
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
SUBDIRS = $(FACTORY_MODULE) $(SND_READER_MODULE) $(ALSA_MODULE)
|
|
@ -0,0 +1,20 @@
|
|||
## 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
|
|
@ -0,0 +1,340 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
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
|
|
@ -0,0 +1,498 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
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
|
|
@ -0,0 +1,33 @@
|
|||
#include "config.h"
|
||||
#include <edje_private.h>
|
||||
|
||||
#define DEFAULT_SAMPLERATE 44100
|
||||
|
||||
#ifdef HAVE_LIBREMIX
|
||||
EAPI RemixBase *
|
||||
multisense_sound_player_get(Edje_Multisense_Env *msenv)
|
||||
{
|
||||
RemixEnv *env = msenv->remixenv;
|
||||
RemixPlugin *player_plugin;
|
||||
RemixBase *player;
|
||||
|
||||
player_plugin = remix_find_plugin(env, "alsa_snd_player");
|
||||
if (!player_plugin)
|
||||
{
|
||||
printf("ALSA player_plugin init fail\n");
|
||||
return remix_monitor_new(env);
|
||||
}
|
||||
player = remix_new(env, player_plugin, NULL);
|
||||
return player;
|
||||
}
|
||||
#endif
|
||||
|
||||
EAPI Eina_Bool
|
||||
multisense_factory_init(Edje_Multisense_Env *env)
|
||||
{
|
||||
#ifdef HAVE_LIBREMIX
|
||||
remix_set_samplerate(env->remixenv, DEFAULT_SAMPLERATE);
|
||||
remix_set_channels(env->remixenv, REMIX_STEREO);
|
||||
#endif
|
||||
return EINA_TRUE;
|
||||
}
|
Loading…
Reference in New Issue