want_multisense="yes"
AC_ARG_ENABLE([multisense],
[AC_HELP_STRING(
- [--enable-multisense],
- [multisense provides sound. tone and haptic effects support, [[default=disabled]]]
+ [--disable-multisense],
+ [multisense provides sound and tone play support, [[default=enabled]]]
)],
[want_multisense=$enableval]
)
have_vorbis="yes"
requirement_edje="ogg >= 1.1.4 vorbis >= 1.2.3 vorbisenc >= 1.2.3 ${requirement_edje}"
],
- [have_vorbis="no"; want_multisense="no"]
+ [have_vorbis="no"]
)
if test "x$want_vorbis" = "xyes" -a "x$have_vorbis" = "xno"; then
##alsa library
have_alsa_lib="no"
want_alsa_lib="auto"
-AC_ARG_ENABLE([flac],
+AC_ARG_ENABLE([alsa],
[AC_HELP_STRING([--disable-alsa], [disable alsa support. @<:@default=detect@:>@])],
[want_alsa_lib=$enableval], [])
have_alsa_lib="yes"
requirement_edje="alsa >= 1.0.21 ${requirement_edje}"
],
- [have_alsa_lib="no"; want_multisense="no"]
+ [have_alsa_lib="no"]
)
if test "x$want_alsa_lib" = "xyes" -a "x$have_alsa_lib" = "xno"; then
fi
AM_CONDITIONAL([HAVE_LIBALSA], [test "x${have_alsa_lib}" = "xyes"])
+##pulse audio library
+have_pa_lib="no"
+want_pa_lib="auto"
+AC_ARG_ENABLE([pulseaudio],
+ [AC_HELP_STRING([--disable-pa], [disable pulse audio support. @<:@default=detect@:>@])],
+ [want_pa_lib=$enableval], [])
+
+if test "x${want_multisense}" = "xyes" -a "x$want_pa_lib" != "xno"; then
+ PKG_CHECK_MODULES([PA],
+ [
+ libpulse >= 0.9.21
+ libpulse-simple >= 0.9.21
+ ],
+ [
+ AC_DEFINE(HAVE_LIBPA, 1, [Pulse Audio support for Edje])
+ have_pa_lib="yes"
+ requirement_edje="libpulse >= 0.9.21 ${requirement_edje}"
+ ],
+ [have_pa_lib="no"]
+ )
+
+ if test "x$want_pa_lib" = "xyes" -a "x$have_pa_lib" = "xno"; then
+ AC_MSG_ERROR([pulse audio support requested, but not found by pkg-config.])
+ fi
+fi
+AM_CONDITIONAL([HAVE_LIBPA], [test "x${have_pa_lib}" = "xyes"])
+
##flac library
have_flac_lib="no"
# mayhem
#requirement_edje="flac >= 1.2.1 ${requirement_edje}"
],
- [have_flac_lib="no"; want_multisense="no"]
+ [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.])
src/bin/epp/Makefile
src/modules/Makefile
src/modules/alsa_snd_player/Makefile
+src/modules/pa_snd_player/Makefile
src/modules/eet_snd_reader/Makefile
src/modules/multisense_factory/Makefile
src/tests/Makefile
echo " Ogg/Vorbis...........: $have_vorbis"
echo " LibFLAC..............: $have_flac_lib"
echo " LibALSA..............: $have_alsa_lib"
+echo " LibPA................: $have_pa_lib"
fi
echo " EDJE_PROGRAM_CACHE...: $want_edje_program_cache"
debian/tmp/usr/lib/libedje.so.*
+debian/tmp/usr/lib/edje/modules/*
CFLAGS += -fvisibility=hidden -ffast-math -fPIC
LDFLAGS += -fvisibility=hidden -Wl,--hash-style=both -Wl,--as-needed
+
+REMIX_DIR='debian/tmp/usr/lib/remix/*'
+INSTALL_FILE="$(DEB_SRCDIR)/debian/libedje.install"
+build:
+ if [ $(shell grep $(REMIX_DIR) $(INSTALL_FILE) |wc -l) = 1 ];then \
+ sed -i "/remix\/\*/d" $(INSTALL_FILE); \
+ fi
+ if [ $(shell pkg-config --modversion remix 2>/dev/null|wc -l) = 1 ];then \
+ echo $(REMIX_DIR) >> $(INSTALL_FILE); \
+ fi
+
#build/libedje-doc::
# cd $(DEB_SRCDIR)/doc && make doc
exit(-1);
}
+ _on_edjecc = EINA_TRUE;
if (!edje_init())
exit(-1);
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);
-
/*****/
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 */
if (!edje_file->collection)
edje_file->collection = eina_hash_string_small_new(NULL);
}
-
/**
@page edcref
@block
source: "sound_file1.wav";
}
sample {
- name: "sound_file2" LOSSY 0.4;
+ name: "sound_file2" LOSSY 99.0;
source: "sound_file2.wav";
}
tone: "tone-1" 2300;
source: "sound_file1.wav";
}
sample {
- name: "sound_file2" LOSSY 0.5;
+ name: "sound_file2" LOSSY 88.0;
source: "sound_file2.wav";
}
sample {
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 LOSSY [45.0 - 1000.0]: Lossy comression with quality from 45.0 to 1000.0.
@li AS_IS: Check for re-encoding, no compression/encoding, just write the file information as it is.
@endproperty
@since 1.1.0
tone->value = value;
tone->id = edje_file->sound_dir->tones_count - 1;
}
-
/**
@edcsection{group,Group sub blocks}
*/
{
Edje_Part_Collection *pc;
Edje_Program *ep;
- int i;
-
+
pc = eina_list_data_get(eina_list_last(edje_collections));
ep = current_program;
ep->action = parse_enum(0,
}
else if (ep->action == EDJE_ACTION_TYPE_SOUND_SAMPLE)
{
+ int i;
+
ep->sample_name = parse_str(1);
for (i = 0; i < (int)edje_file->sound_dir->samples_count; i++)
{
}
else if (ep->action == EDJE_ACTION_TYPE_SOUND_TONE)
{
+ int i;
+
ep->tone_name = parse_str(1);
for (i = 0; i < (int)edje_file->sound_dir->tones_count; i++)
{
# endif
Edje_Sound_Encode *
-_edje_multisense_encode(const char *filename, Edje_Sound_Sample *sample, double quality __UNUSED__)
+_edje_multisense_encode(const char *filename, Edje_Sound_Sample *sample, double quality)
{
SF_INFO sfinfo;
SNDFILE* sfile;
relative: 0.0 0.0;
}
}
+ description {
+ state: "blue" 0.0;
+ inherit: "default" 0.0;
+ color: 0 0 200 100;
+ }
}
part {
name: "sample_text";
to: "sample_bg";
}
}
+ description {
+ state: "red" 0.0;
+ inherit: "default" 0.0;
+ color: 200 0 0 100;
+ }
}
part {
name: "tone_text";
}
programs {
program {
- name: "click_sample1";
+ name: "click_sample";
signal: "mouse,down,1";
source: "sample_bg";
+ action: STATE_SET "blue" 0.0;
+ transition: SINUSOIDAL 0.4;
+ target: "sample_bg";
+ after: "change1";
+ }
+ program {
+ name: "change1";
+ action: STATE_SET "default" 0.0;
+ transition: SINUSOIDAL 0.4;
+ target: "tone_bg";
+ after: "play_sample";
+ }
+ program {
+ name: "play_sample";
action: PLAY_SAMPLE "sound_name1" 1.0;
}
program {
name: "click_tone";
signal: "mouse,down,1";
source: "tone_bg";
- action: PLAY_TONE "tone-name" 0.1;
+ action: STATE_SET "red" 0.0;
+ transition: SINUSOIDAL 0.4;
+ target: "tone_bg";
+ after: "change2";
+ }
+ program {
+ name: "change2";
+ action: STATE_SET "default" 0.0;
+ transition: SINUSOIDAL 0.4;
+ target: "sample_bg";
+ after: "play_tone";
+ }
+ program {
+ name: "play_tone";
+ action: PLAY_TONE "tone-name" 0.2;
}
}
}
int _edje_default_log_dom = -1;
Eina_Mempool *_edje_real_part_mp = NULL;
Eina_Mempool *_edje_real_part_state_mp = NULL;
+EAPI Eina_Bool _on_edjecc = EINA_FALSE;
/*============================================================================*
* API *
_edje_external_init();
_edje_module_init();
_edje_message_init();
- _edje_multisense_init();
+
+ /* Do the Multisense runtime framework initialisation, if it is not EDC compilation mode */
+ if (!_on_edjecc)
+ _edje_multisense_init();
_edje_real_part_mp = eina_mempool_add("chained_mempool",
"Edje_Real_Part", NULL,
#define BUF_LEN 64
#define SND_PROCESS_LENGTH 2048
-#ifdef HAVE_LIBREMIX
+#ifdef ENABLE_MULTISENSE
static Ecore_Thread *player_thread = NULL;
static int command_pipe[2];
static Eina_Bool pipe_initialized = EINA_FALSE;
Edje_Tone_Action tone;
} type;
};
-
-#ifdef HAVE_LIBREMIX
+#ifdef ENABLE_MULTISENSE
static Multisense_Data *
init_multisense_environment(void)
{
m = _edje_module_handle_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->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);
}
}
#endif
-#ifdef HAVE_LIBREMIX
+#if defined(ENABLE_MULTISENSE) && defined(HAVE_LIBREMIX)
static RemixBase *
-eet_sound_reader_get(Edje_Multisense_Env *msenv, const char *path, const char *sound_id, const double speed)
+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;
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_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)
+edje_remix_sample_create(Multisense_Data *msdata, Edje *ed, Edje_Sample_Action *action)
{
RemixBase *remix_snd = NULL;
Edje_Sound_Sample *sample;
}
static RemixBase *
-edje_remix_tone_create(Multisense_Data *msdata, Edje*ed, Edje_Tone_Action *action)
+edje_remix_tone_create(Multisense_Data *msdata, Edje *ed, Edje_Tone_Action *action)
{
Edje_Sound_Tone *tone;
RemixSquareTone *square = NULL;
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];
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:
}
#endif
-#ifdef HAVE_LIBREMIX
+#ifdef ENABLE_MULTISENSE
// msdata outside of thread due to thread issues in dlsym etc.
static Multisense_Data *msdata = NULL;
{
// cleanup msdata outside of thread due to thread issues in dlsym etc.
if (!msdata) return;
+#ifdef HAVE_LIBREMIX
//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);
msdata = NULL;
_player_job(void *data __UNUSED__, Ecore_Thread *th)
{
fd_set wait_fds;
+#ifdef HAVE_LIBREMIX
RemixBase *sound;
RemixCount process_len;
+#endif
// disable and move outside of thread due to dlsym etc. thread issues
// Multisense_Data * msdata = init_multisense_environment();
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)
{
remix_destroy(msdata->msenv->remixenv, sound);
}
-
+#endif
close(command_pipe[0]);
close(command_pipe[1]);
}
-#endif
-#ifdef HAVE_LIBREMIX
static void
_player_cancel(void *data __UNUSED__, Ecore_Thread *th __UNUSED__)
{
_msdata_free();
player_thread = NULL;
}
-#endif
-#ifdef HAVE_LIBREMIX
static void
_player_end(void *data __UNUSED__, Ecore_Thread *th __UNUSED__)
{
_edje_multisense_internal_sound_sample_play(Edje *ed, const char *sample_name, const double speed)
{
ssize_t size = 0;
-#ifdef ENABLE_MULTISENSE
+#if defined(ENABLE_MULTISENSE) && defined(HAVE_LIBREMIX)
Edje_Multisense_Sound_Action command;
if ((!pipe_initialized) && (!player_thread)) return EINA_FALSE;
_edje_multisense_internal_sound_tone_play(Edje *ed, const char *tone_name, const double duration)
{
ssize_t size = 0;
-#ifdef ENABLE_MULTISENSE
+#if defined(ENABLE_MULTISENSE) && defined(HAVE_LIBREMIX)
Edje_Multisense_Sound_Action command;
if ((!pipe_initialized) && (!player_thread)) return EINA_FALSE;
// init msdata outside of thread due to thread issues in dlsym etc.
if (!msdata) msdata = init_multisense_environment();
-
if (!player_thread)
player_thread = ecore_thread_run(_player_job, _player_end, _player_cancel, NULL);
#endif
EAPI extern Eet_Data_Descriptor *_edje_edd_edje_file;
EAPI extern Eet_Data_Descriptor *_edje_edd_edje_part_collection;
+EAPI extern Eina_Bool _on_edjecc;
extern int _edje_anim_count;
extern Ecore_Animator *_edje_timer;
-if ENABLE_MULTISENSE\r
FACTORY_MODULE = multisense_factory\r
+\r
if HAVE_LIBREMIX\r
-SND_READER_MODULE = eet_snd_reader\r
+SND_READER_MODULE = eet_snd_reader
if HAVE_LIBALSA\r
ALSA_MODULE = alsa_snd_player\r
+endif
+if HAVE_LIBPA\r
+PA_MODULE = pa_snd_player\r
endif\r
endif\r
-endif\r
-SUBDIRS = $(FACTORY_MODULE) $(SND_READER_MODULE) $(ALSA_MODULE)\r
+\r
+SUBDIRS = $(FACTORY_MODULE) $(SND_READER_MODULE) $(ALSA_MODULE) $(PA_MODULE)\r
AM_CPPFLAGS = \
-I. \
--DPACKAGE_LIB_DIR=\"$(libdir)/remix\" \
--DPACKAGE_DATA_DIR=\"$(datadir)/remix\" \
@EDJE_CFLAGS@ \
@REMIX_CFLAGS@ \
@ALSA_CFLAGS@
AM_CPPFLAGS = \
-I. \
--DPACKAGE_LIB_DIR=\"$(libdir)/remix\" \
--DPACKAGE_DATA_DIR=\"$(datadir)/remix\" \
@EDJE_CFLAGS@ \
@REMIX_CFLAGS@
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
{
float fpos, fpos1;
RemixPCM psam[2];
-
+
fpos = (float)(i * in_samples) / (float)reqsamp;
pos = fpos;
if (pos >= avail) break;
pkgdir = $(libdir)/edje/modules/multisense_factory/$(MODULE_ARCH)
pkg_LTLIBRARIES = module.la
+if ENABLE_MULTISENSE
module_la_SOURCES = multisense_factory.c
+else
+module_la_SOURCES =
+endif
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
multisense_sound_player_get(Edje_Multisense_Env *msenv)
{
RemixEnv *env = msenv->remixenv;
- RemixPlugin *player_plugin;
+ RemixPlugin *player_plugin = NULL;
RemixBase *player;
- player_plugin = remix_find_plugin(env, "alsa_snd_player");
+#ifdef HAVE_LIBPA
+ player_plugin = remix_find_plugin(env, "pa_snd_player");
+ INF("PA player_plugin = %p \n", player_plugin);
+#endif
+
+#ifdef HAVE_LIBALSA
if (!player_plugin)
{
- WRN("ALSA player_plugin init fail\n");
- return remix_monitor_new(env);
+ player_plugin = remix_find_plugin(env, "alsa_snd_player");
+ INF("ALSA player_plugin = %p \n", player_plugin);
}
+#endif
+ if (!player_plugin)
+ return remix_monitor_new(env);
+
player = remix_new(env, player_plugin, NULL);
return player;
}
--- /dev/null
+## Process this file with automake to produce Makefile.in
+
+MAINTAINERCLEANFILES = Makefile.in
+
+pkglibdir = $(REMIX_PLUGIN_DIR)
+
+AM_CPPFLAGS = \
+-I. \
+@EDJE_CFLAGS@ \
+@REMIX_CFLAGS@ \
+@PA_CFLAGS@
+
+pkgdir = $(REMIX_PLUGIN_DIR)
+pkg_LTLIBRARIES = libpa_snd_player.la
+
+libpa_snd_player_la_SOURCES = pa_simple_snd_player.c
+libpa_snd_player_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -module -avoid-version @EDJE_LIBS@ @REMIX_LIBS@ @PA_LIBS@
+libpa_snd_player_la_LIBTOOLFLAGS = --tag=disable-static
--- /dev/null
+/*
+ * Remix Pulse Audio Player: Pulse Audio output
+ *
+ * Prince Kumar Dubey <prince.dubey@samsung.com>, April 2012
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <remix/remix.h>
+#include <Eina.h>
+#include <pulse/simple.h>
+#include <pulse/error.h>
+#include <pulse/gccmacro.h>
+#include <pulse/proplist.h>
+
+#define PA_PLAYER_BUFFERLEN 4096
+
+typedef struct _PA_Player_Data PA_Player_Data;
+typedef short PLAYER_PCM;
+
+struct _PA_Player_Data
+{
+ RemixPCM databuffer[PA_PLAYER_BUFFERLEN];
+ PLAYER_PCM *playbuffer;
+ pa_simple *server;
+ int error;
+ unsigned int stereo;
+ unsigned channels;
+ unsigned int frequency;
+ RemixPCM max_value;
+};
+
+static int _log_dom = -1;
+static int init_count = 0;
+
+#ifdef WRN
+# undef WRN
+#endif
+#define WRN(...) EINA_LOG_DOM_WARN(_log_dom, __VA_ARGS__)
+
+/* Optimisation dependencies: none */
+static RemixBase *pa_player_optimise(RemixEnv *env, RemixBase *base);
+
+static RemixBase *
+pa_player_reset_device(RemixEnv *env, RemixBase *base)
+{
+ pa_sample_spec sample_spec;
+
+ PA_Player_Data *player_data = remix_base_get_instance_data(env, base);
+ sample_spec.rate = player_data->frequency;
+ sample_spec.channels = player_data->channels;
+ sample_spec.format = PA_SAMPLE_S16NE;
+
+ if (player_data->server)
+ {
+ /* Make sure that every single sample was played */
+ if (pa_simple_drain(player_data->server, &player_data->error) < 0)
+ {
+ WRN("pa_simple_drain() failed: (%s)", pa_strerror(player_data->error));
+ goto error;
+ }
+ /* Make sure that all data currently in buffers are thrown away. */
+ if (pa_simple_flush (player_data->server, &player_data->error) < 0)
+ {
+ WRN("pa_simple_flush() failed: (%s)", pa_strerror(player_data->error));
+ goto error;
+ }
+ }
+
+ /* Create a new playback stream */
+ if (!(player_data->server = pa_simple_new(NULL, "EFL Edje", PA_STREAM_PLAYBACK,
+ NULL, "Edje Multisense audio",
+ &sample_spec, NULL,
+ NULL, &player_data->error)))
+ {
+ WRN("pa_simple_new() failed: (%s)", pa_strerror(player_data->error));
+ goto error;
+ }
+
+ if (player_data->playbuffer) free(player_data->playbuffer);
+ player_data->playbuffer = calloc(sizeof(PLAYER_PCM), PA_PLAYER_BUFFERLEN);
+
+ if(!player_data->playbuffer) goto error;
+
+ if (sample_spec.rate != player_data->frequency)
+ {
+ player_data->frequency = sample_spec.rate;
+ remix_set_samplerate(env, player_data->frequency);
+ }
+
+ return base;
+
+error:
+ if (player_data->server)
+ pa_simple_free(player_data->server);
+ remix_set_error(env, REMIX_ERROR_SYSTEM);
+ return RemixNone;
+}
+
+static RemixBase *
+pa_player_init(RemixEnv *env, RemixBase *base, CDSet *parameters __UNUSED__)
+{
+ CDSet *channels;
+
+ PA_Player_Data *player_data = calloc(1, sizeof(PA_Player_Data));
+
+ if (!player_data)
+ {
+ remix_set_error(env, REMIX_ERROR_SYSTEM);
+ return RemixNone;
+ }
+
+ init_count++;
+ if (init_count == 1)
+ {
+ eina_init();
+ _log_dom = eina_log_domain_register("remix-pulseaudio", EINA_COLOR_CYAN);
+ }
+
+ 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);
+ player_data->max_value = (RemixPCM) SHRT_MAX / 2;
+
+ pa_player_reset_device(env, base);
+ base = pa_player_optimise(env, base);
+
+ return base;
+}
+
+static RemixBase *
+pa_player_clone(RemixEnv *env, RemixBase *base __UNUSED__)
+{
+ RemixBase *new_player = remix_base_new(env);
+ pa_player_init(env, new_player, NULL);
+ return new_player;
+}
+
+static int
+pa_player_destroy(RemixEnv *env, RemixBase *base)
+{
+ PA_Player_Data *player_data = remix_base_get_instance_data(env, base);
+
+ if (player_data->server)
+ {
+ /* Make sure that every single sample was played */
+ if (pa_simple_drain(player_data->server, &player_data->error) < 0)
+ WRN("pa_simple_drain() failed: (%s)", pa_strerror(player_data->error));
+
+ /* Make sure that all data currently in buffers are thrown away. */
+ if (pa_simple_flush (player_data->server, &player_data->error) < 0)
+ WRN("pa_simple_flush() failed: (%s)", pa_strerror(player_data->error));
+
+ pa_simple_free(player_data->server);
+ }
+ if (player_data->playbuffer) free(player_data->playbuffer);
+
+ free(player_data);
+ init_count--;
+ if (init_count == 0)
+ {
+ eina_log_domain_unregister(_log_dom);
+ _log_dom = -1;
+ eina_shutdown();
+ }
+ return 0;
+}
+
+static int
+pa_player_ready(RemixEnv *env, RemixBase *base)
+{
+ RemixCount nr_channels;
+ CDSet *channels;
+ int samplerate;
+
+ PA_Player_Data *player_data = remix_base_get_instance_data(env, base);
+
+ 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 *
+pa_player_prepare(RemixEnv *env, RemixBase *base)
+{
+ pa_player_reset_device(env, base);
+ return base;
+}
+
+static void
+pa_player_playbuffer(RemixEnv *env __UNUSED__, PA_Player_Data *player, RemixPCM *data, RemixCount count)
+{
+ int ret;
+ RemixCount i;
+ RemixPCM value;
+ size_t length;
+
+ length = count * sizeof(RemixCount);
+
+ for (i = 0; i < length; i++)
+ {
+ value = *data++ * (player->max_value);
+ *(player->playbuffer + i) = (PLAYER_PCM) value;
+ }
+
+ ret = pa_simple_write(player->server, player->playbuffer, length, &player->error);
+
+ if (ret < 0) WRN("pa_simple_write() failed: (%s)", pa_strerror(player->error));
+
+ return;
+}
+
+static RemixCount
+pa_player_chunk(RemixEnv *env, RemixChunk *chunk, RemixCount offset, RemixCount count, int channelname __UNUSED__, void *data)
+{
+ RemixCount remaining = count, written = 0, playcount;
+ RemixPCM *d;
+
+ PA_Player_Data *player = data;
+
+ while (remaining > 0)
+ {
+ playcount = MIN(remaining, PA_PLAYER_BUFFERLEN);
+
+ d = &chunk->data[offset];
+ pa_player_playbuffer(env, player, d, playcount);
+
+ offset += playcount;
+ written += playcount;
+ remaining -= playcount;
+ }
+ return written;
+}
+
+static RemixCount
+pa_player_process(RemixEnv *env, RemixBase *base, RemixCount count, RemixStream *input, RemixStream *output __UNUSED__)
+{
+ PA_Player_Data *player_data = remix_base_get_instance_data(env, base);
+ RemixCount nr_channels = remix_stream_nr_channels(env, input);
+ RemixCount remaining = count, processed = 0, n;
+
+ if ((nr_channels == 1) && (player_data->stereo == 0))
+ { /*MONO*/
+ return remix_stream_chunkfuncify(env, input, count,
+ pa_player_chunk, player_data);
+ }
+ else if ((nr_channels == 2) && (player_data->stereo == 1))
+ { /*STEREO*/
+ while (remaining > 0)
+ {
+ n = MIN(remaining, PA_PLAYER_BUFFERLEN / 2);
+ n = remix_stream_interleave_2(env, input,
+ REMIX_CHANNEL_LEFT,
+ REMIX_CHANNEL_RIGHT,
+ player_data->databuffer, n);
+ pa_player_playbuffer(env, player_data,
+ player_data->databuffer, n);
+ processed += n;
+ remaining -= n;
+ }
+ return processed;
+ }
+ WRN("[pa_player_process] unsupported stream/output channel "
+ "combination %ld / %d", nr_channels, player_data->stereo ? 2 : 1);
+ return -1;
+}
+
+static RemixCount
+pa_player_length(RemixEnv *env __UNUSED__, RemixBase *base __UNUSED__)
+{
+ return REMIX_COUNT_INFINITE;
+}
+
+static RemixCount
+pa_player_seek(RemixEnv *env __UNUSED__, RemixBase *base __UNUSED__, RemixCount count __UNUSED__)
+{
+ return count;
+}
+
+static int
+pa_player_flush(RemixEnv *env, RemixBase *base)
+{
+ pa_player_reset_device(env, base);
+ return 0;
+}
+
+static struct _RemixMethods _pa_player_methods =
+{
+ pa_player_clone,
+ pa_player_destroy,
+ pa_player_ready,
+ pa_player_prepare,
+ pa_player_process,
+ pa_player_length,
+ pa_player_seek,
+ pa_player_flush,
+};
+
+static RemixBase *
+pa_player_optimise(RemixEnv *env, RemixBase *base)
+{
+ remix_base_set_methods(env, base, &_pa_player_methods);
+ return base;
+}
+
+static struct _RemixMetaText pa_player_metatext =
+{
+ "pa_snd_player",
+ "PA sound player for Remix",
+ "Output the audio stream into Pulse Audio",
+ "Copyright (C) 2012, Samsung Electronics Co., Ltd.",
+ "http://www.samsung.com",
+ REMIX_ONE_AUTHOR("Prince Kr Dubey", "prince.dubey@samsung.com"),
+};
+
+static struct _RemixPlugin pa_player_plugin =
+{
+ &pa_player_metatext,
+ REMIX_FLAGS_NONE,
+ CD_EMPTY_SET, /* init scheme */
+ pa_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(&pa_player_plugin));
+ return plugins;
+}