ecore_audio: Add tizen ecore_audio module
authorJiwon Kim <jiwon177.kim@samsung.com>
Wed, 9 Nov 2016 14:08:05 +0000 (23:08 +0900)
committerWonki Kim <wonki_.kim@samsung.com>
Mon, 2 Jan 2017 07:23:56 +0000 (16:23 +0900)
Modulation (phase 1) is completed.
It opens %{libdir}/ecore_audio/modules/tizen/{version}/module.so ,
 and use it than libpulse.

Origin code (using libpulse) also work well.
But that's volume is handled media volume.

As using Tizen's audio module, volume control can be followed
 to platform poicy.

Change-Id: Ic8068b87a10ee8cd2e4786d4ad7d4bf529a7d881
Signed-off-by: Jiwon Kim <jiwon177.kim@samsung.com>
configure.ac
packaging/efl.spec
src/Makefile_Ecore_Audio.am
src/lib/ecore_audio/Ecore_Audio.h
src/lib/ecore_audio/ecore_audio_obj_in_sndfile.c
src/lib/ecore_audio/ecore_audio_obj_out_tizen.c [new file with mode: 0644]
src/lib/ecore_audio/ecore_audio_obj_out_tizen.h [new file with mode: 0644]
src/lib/ecore_audio/ecore_audio_out_tizen.eo [new file with mode: 0644]
src/lib/edje/edje_multisense.c

index 8aaba7b..584da9e 100755 (executable)
@@ -3311,6 +3311,22 @@ want_alsa="no"
 # TODO: and the EFL_OPTIONAL_DEPEND_PKG(), use EFL_DEPEND_PKG()
 want_sndfile="yes"
 
+AC_ARG_ENABLE([tizenaudio],
+   [AS_HELP_STRING([--enable-tizenaudio],[enable tizen audio sound support. @<:@default=enabled@:>@])],
+   [
+    if test "x${enableval}" = "xyes" ; then
+       want_tizenaudio="yes"
+    else
+       want_tizenaudio="no"
+    fi
+   ],
+   [want_tizenaudio="no"])
+if test "x${want_tizenaudio}" = "xyes"; then
+   AC_DEFINE([HAVE_TIZENAUDIO], [1], [Tizen Audio support enabled])
+else
+   AC_DEFINE([HAVE_TIZENAUDIO], [0], [Tizen Audio support disabled])
+fi
+
 AC_ARG_ENABLE([pulseaudio],
    [AS_HELP_STRING([--disable-pulseaudio],[disable pulseaudio sound support. @<:@default=enabled@:>@])],
    [
@@ -3398,6 +3414,7 @@ EFL_ADD_FEATURE([ECORE_AUDIO], [alsa])
 EFL_ADD_FEATURE([ECORE_AUDIO], [pulseaudio])
 EFL_ADD_FEATURE([ECORE_AUDIO], [sndfile])
 EFL_ADD_FEATURE([ECORE_AUDIO], [coreaudio])
+EFL_ADD_FEATURE([ECORE_AUDIO], [tizenaudio])
 
 ### Checks for header files
 
@@ -3415,6 +3432,7 @@ EFL_LIB_END_OPTIONAL([Ecore_Audio])
 AM_CONDITIONAL([HAVE_ECORE_AUDIO_PULSE], [test "x${want_pulseaudio}" = "xyes"])
 AM_CONDITIONAL([HAVE_ECORE_AUDIO_SNDFILE], [test "x${want_sndfile}" = "xyes"])
 AM_CONDITIONAL([HAVE_ECORE_AUDIO_CORE_AUDIO], [test "x${want_coreaudio}" = "xyes"])
+AM_CONDITIONAL([HAVE_ECORE_AUDIO_TIZEN], [test "x${want_tizenaudio}" = "xyes"])
 
 #### End of Ecore_Audio
 
index a869eb5..5d71ca0 100755 (executable)
@@ -729,6 +729,7 @@ CFLAGS+=" -DEFL_FEATURE_EMULATOR "
     --enable-harfbuzz \
     --enable-hyphen \
     --with-dictionaries-hyphen-dir=/usr/share/hyphen/ \
+    --enable-tizenaudio \
     --enable-i-really-know-what-i-am-doing-and-that-this-will-probably-break-things-and-i-will-fix-them-myself-and-send-patches-aba
 
 
index ccce8f7..5cd5d96 100644 (file)
@@ -11,6 +11,10 @@ ecore_audio_eolian_files = \
        lib/ecore_audio/ecore_audio_in_tone.eo
 
 
+if HAVE_ECORE_AUDIO_TIZEN
+ecore_audio_eolian_files += lib/ecore_audio/ecore_audio_out_tizen.eo
+endif
+
 if HAVE_ECORE_AUDIO_PULSE
 ecore_audio_eolian_files += lib/ecore_audio/ecore_audio_out_pulse.eo
 endif
@@ -57,11 +61,20 @@ lib/ecore_audio/ecore_audio_obj_out.c \
 lib/ecore_audio/ecore_audio_obj_in_tone.c \
 lib/ecore_audio/ecore_audio_private.h
 
-lib_ecore_audio_libecore_audio_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl @ECORE_AUDIO_CFLAGS@
+lib_ecore_audio_libecore_audio_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl @ECORE_AUDIO_CFLAGS@ -DPACKAGE_LIB_DIR=\"$(libdir)\"
+
 lib_ecore_audio_libecore_audio_la_LIBADD = @ECORE_AUDIO_LIBS@
 lib_ecore_audio_libecore_audio_la_DEPENDENCIES = @ECORE_AUDIO_INTERNAL_LIBS@
 lib_ecore_audio_libecore_audio_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@
 
+if HAVE_ECORE_AUDIO_TIZEN
+dist_installed_ecoreaudiomainheaders_DATA += \
+lib/ecore_audio/ecore_audio_obj_out_tizen.h
+
+lib_ecore_audio_libecore_audio_la_SOURCES += \
+lib/ecore_audio/ecore_audio_obj_out_tizen.c
+endif
+
 if HAVE_ECORE_AUDIO_PULSE
 dist_installed_ecoreaudiomainheaders_DATA += \
 lib/ecore_audio/ecore_audio_obj_out_pulse.h
index 116ab68..56fc383 100644 (file)
@@ -226,6 +226,10 @@ EAPI int                 ecore_audio_shutdown(void);
 # include <ecore_audio_obj_out_pulse.h>
 #endif
 
+#if HAVE_TIZENAUDIO
+# include <ecore_audio_obj_out_tizen.h>
+#endif
+
 /**
  * @}
  */
index 599ae27..3237c5c 100644 (file)
@@ -30,6 +30,13 @@ typedef struct _Ecore_Audio_In_Sndfile_Data Ecore_Audio_In_Sndfile_Data;
 EOLIAN static ssize_t
 _ecore_audio_in_sndfile_ecore_audio_in_read_internal(Eo *eo_obj EINA_UNUSED, Ecore_Audio_In_Sndfile_Data *obj, void *data, size_t len)
 {
+  // TIZEN_ONLY(20161116): Add signed 16 read if write module only support S16
+  char *pcm_fmt;
+  eo_do(eo_obj, pcm_fmt = (char *)eo_key_data_get("pcm_fmt"));
+  if (pcm_fmt && !strcmp(pcm_fmt, "S16"))
+    return sf_read_short(obj->handle, data, len/2)*2;
+  //
+
   return sf_read_float(obj->handle, data, len/4)*4;
 }
 
@@ -205,6 +212,13 @@ _ecore_audio_in_sndfile_eo_base_destructor(Eo *eo_obj, Ecore_Audio_In_Sndfile_Da
   if (ea_obj->vio)
     _free_vio(ea_obj);
 
+  // TIZEN_ONLY(20161116): Add signed 16 read if write module only support S16
+  char *pcm_fmt;
+  eo_do(eo_obj, pcm_fmt = (char *)eo_key_data_get("pcm_fmt"));
+  eo_do(eo_obj, eo_key_data_set("pcm_fmt", NULL));
+  free(pcm_fmt);
+  //
+
   eo_do_super(eo_obj, MY_CLASS, eo_destructor());
 }
 
diff --git a/src/lib/ecore_audio/ecore_audio_obj_out_tizen.c b/src/lib/ecore_audio/ecore_audio_obj_out_tizen.c
new file mode 100644 (file)
index 0000000..591f9a9
--- /dev/null
@@ -0,0 +1,208 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#if defined (__MacOSX__) || (defined (__MACH__) && defined (__APPLE__)) || defined (__FreeBSD__)
+# include <libgen.h>
+#endif
+
+#ifdef HAVE_FEATURES_H
+#include <features.h>
+#endif
+
+#include <Eo.h>
+#include "ecore_audio_private.h"
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#define MY_CLASS ECORE_AUDIO_OUT_TIZEN_CLASS
+#define MY_CLASS_NAME "Ecore_Audio_Out_Tizen"
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+# define MODULE_EXT ".dll"
+#else
+# define MODULE_EXT ".so"
+#endif
+
+#define AUDIO_MODULE_NAME "module"MODULE_EXT
+#define MODULE_PATH PACKAGE_LIB_DIR"/ecore_audio/modules/tizen/"MODULE_ARCH
+
+struct _Ecore_Audio_Out_Tizen_Module_Func
+{
+   int (*init)    (int sample_rate, int channel, void **handle);
+   int (*deinit)  (void *handle);
+   int (*get_buffer_size)  (void *handle, size_t *size);
+   int (*write)   (void *handle, void *buf, unsigned int len);
+   int (*drain)   (void *handle);
+   int (*set_write_cb)  (void *handle, void (*out_cb)(void *handle, size_t nbytes, void *user_data), void *data);
+   int (*unset_write_cb)  (void *handle);
+};
+
+typedef struct _Ecore_Audio_Out_Tizen_Module_Func Ecore_Audio_Out_Tizen_Module_Func;
+
+static Ecore_Audio_Out_Tizen_Module_Func module_func = { NULL, };
+static Eina_Module *module = NULL;
+
+struct _Ecore_Audio_Out_Tizen_Data
+{
+   Ecore_Audio_Out_Tizen_Module_Func *func;
+   Eo *attached_in;
+};
+
+typedef struct _Ecore_Audio_Out_Tizen_Data Ecore_Audio_Out_Tizen_Data;
+
+static Eina_Bool _module_load(Ecore_Audio_Out_Tizen_Data *td)
+{
+   if (td->func)
+     return EINA_TRUE;
+
+   if (!module)
+     {
+        Eina_Module *em = NULL;
+        em = eina_module_new(MODULE_PATH "/" AUDIO_MODULE_NAME);
+        if (!eina_module_load(em))
+          {
+             eina_module_free(em);
+             return EINA_FALSE;
+          }
+
+        module_func.init            = eina_module_symbol_get(em, "ecore_audio_init");
+        module_func.deinit          = eina_module_symbol_get(em, "ecore_audio_deinit");
+        module_func.get_buffer_size = eina_module_symbol_get(em, "ecore_audio_get_buffer_size");
+        module_func.write           = eina_module_symbol_get(em, "ecore_audio_write");
+        module_func.drain           = eina_module_symbol_get(em, "ecore_audio_drain");
+        module_func.set_write_cb    = eina_module_symbol_get(em, "ecore_audio_set_write_cb");
+        module_func.unset_write_cb  = eina_module_symbol_get(em, "ecore_audio_unset_write_cb");
+
+        if ((!module_func.init) || (!module_func.deinit) || (!module_func.get_buffer_size)
+            || (!module_func.write) || (!module_func.drain) || (!module_func.set_write_cb))
+          {
+             module_func.init            = NULL;
+             module_func.deinit          = NULL;
+             module_func.get_buffer_size = NULL;
+             module_func.write           = NULL;
+             module_func.drain           = NULL;
+             module_func.set_write_cb    = NULL;
+             module_func.unset_write_cb  = NULL;
+
+             eina_module_free(em);
+             return EINA_FALSE;
+          }
+        module = em;
+     }
+
+   td->func = &module_func;
+
+   return EINA_TRUE;
+}
+
+static void _stream_write_cb(void *handle, size_t len EINA_UNUSED, void *data)
+{
+   Eo *in = data;
+   Ecore_Audio_Out_Tizen_Data *_td;
+   eo_do(in, _td = eo_key_data_get("mod_data"));
+
+   void *buf;
+   ssize_t bread = 0;
+   size_t wlen;
+
+   _td->func->get_buffer_size(handle, &wlen);
+   buf = malloc(wlen);
+   eo_do(in, bread = ecore_audio_obj_in_read(buf, wlen));
+
+   if (bread > 0)
+     {
+        _td->func->write(handle, buf, (unsigned int)bread);
+     }
+
+   free(buf);
+}
+
+EOLIAN static Eina_Bool
+_ecore_audio_out_tizen_ecore_audio_out_input_attach(Eo *eo_obj, Ecore_Audio_Out_Tizen_Data *_td, Eo *in)
+{
+   int ret;
+   Eina_Bool ret2;
+   void *handle;
+   int samplerate = 0;
+   int channels = 0;
+
+   eo_do_super(eo_obj, MY_CLASS, ret2 = ecore_audio_obj_out_input_attach(in));
+   if (!ret2)
+      return EINA_FALSE;
+
+   eo_do(in, channels = ecore_audio_obj_in_channels_get());
+   eo_do(in, samplerate = ecore_audio_obj_in_samplerate_get());
+
+   ret = _td->func->init(samplerate, channels, &handle);
+   if (ret)
+     {
+        eo_do_super(eo_obj, MY_CLASS, ecore_audio_obj_out_input_detach(in));
+        ERR("init error : %d", ret);
+        return EINA_FALSE;
+     }
+   eo_do(in, eo_key_data_set("mod_handle", handle));
+   eo_do(in, eo_key_data_set("mod_data", _td));
+   eo_do(in, eo_key_data_set("pcm_fmt", strdup("S16")));
+   _td->attached_in = in;
+   ret = _td->func->set_write_cb(handle, _stream_write_cb, in);
+   if (ret)
+     {
+        eo_do_super(eo_obj, MY_CLASS, ecore_audio_obj_out_input_detach(in));
+        ERR("set_write_callback error : %d", ret);
+        _td->func->deinit(handle);
+        return EINA_FALSE;
+     }
+
+   return EINA_TRUE;
+}
+
+EOLIAN static Eina_Bool
+_ecore_audio_out_tizen_ecore_audio_out_input_detach(Eo *eo_obj, Ecore_Audio_Out_Tizen_Data *_td, Eo *in)
+{
+   Eina_Bool ret2 = EINA_FALSE;
+   void *handle;
+
+   eo_do_super(eo_obj, MY_CLASS, ret2 = ecore_audio_obj_out_input_detach(in));
+   if (!ret2)
+     return EINA_FALSE;
+
+   eo_do(in, handle = eo_key_data_get("mod_handle"));
+   _td->func->unset_write_cb(handle);
+   _td->func->drain(handle);
+   _td->func->deinit(handle);
+
+   return EINA_TRUE;
+}
+
+EOLIAN static Eo *
+_ecore_audio_out_tizen_eo_base_constructor(Eo *eo_obj, Ecore_Audio_Out_Tizen_Data *_td)
+{
+
+   Ecore_Audio_Output *out_obj = eo_data_scope_get(eo_obj, ECORE_AUDIO_OUT_CLASS);
+
+   eo_obj = eo_do_super_ret(eo_obj, MY_CLASS, eo_obj, eo_constructor());
+
+   if (!_module_load(_td))
+     {
+        // Need to destructing
+        ERR("Faild to load ecore audio module");
+        return NULL;
+     }
+
+   return eo_obj;
+}
+
+EOLIAN static void
+_ecore_audio_out_tizen_eo_base_destructor(Eo *eo_obj, Ecore_Audio_Out_Tizen_Data *_td EINA_UNUSED)
+{
+   eo_do_super(eo_obj, MY_CLASS, eo_destructor());
+}
+
+#include "ecore_audio_out_tizen.eo.c"
diff --git a/src/lib/ecore_audio/ecore_audio_obj_out_tizen.h b/src/lib/ecore_audio/ecore_audio_obj_out_tizen.h
new file mode 100644 (file)
index 0000000..60d9caf
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef ECORE_AUDIO_OUT_TIZEN_H
+#define ECORE_AUDIO_OUT_TIZEN_H
+
+#include <Eina.h>
+#include <Eo.h>
+
+#ifdef EAPI
+#undef EAPI
+#endif
+
+#ifdef __GNUC__
+#if __GNUC__ >= 4
+#define EAPI __attribute__ ((visibility("default")))
+#else
+#define EAPI
+#endif
+#else
+#define EAPI
+#endif
+
+/**
+ * @file ecore_audio_obj_out_pulse.h
+ * @brief Ecore_Audio pulseaudio output
+ */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * @internal
+ * @defgroup ecore_audio_obj_out_tizen - Ecore_Audio tizen audio-io output
+ * @ingroup Ecore_Audio_Group
+ * @{
+ */
+#include "ecore_audio_out_tizen.eo.h"
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/lib/ecore_audio/ecore_audio_out_tizen.eo b/src/lib/ecore_audio/ecore_audio_out_tizen.eo
new file mode 100644 (file)
index 0000000..80b3063
--- /dev/null
@@ -0,0 +1,10 @@
+class Ecore_Audio_Out_Tizen (Ecore_Audio_Out)
+{
+   eo_prefix: ecore_audio_obj_out_tizen;
+   implements {
+      Eo.Base.constructor;
+      Eo.Base.destructor;
+      Ecore_Audio_Out.input_attach;
+      Ecore_Audio_Out.input_detach;
+   }
+}
index 92e36d5..fec67df 100644 (file)
@@ -209,12 +209,22 @@ _edje_multisense_internal_sound_sample_play(Edje *ed, const char *sample_name, c
                          eo_event_callback_add(ECORE_AUDIO_IN_EVENT_IN_STOPPED, _play_finished, NULL));
              if (!out)
                {
+#if HAVE_TIZENAUDIO
+                  if (!(out = eo_add(ECORE_AUDIO_OUT_TIZEN_CLASS, NULL)))
+                    {
+                       ERR("Could not create multisense audio out (Tizen Audio)");
+#endif
+
 #if HAVE_COREAUDIO
                   out = eo_add(ECORE_AUDIO_OUT_CORE_AUDIO_CLASS, NULL);
 #elif HAVE_PULSE
                   out = eo_add(ECORE_AUDIO_OUT_PULSE_CLASS, NULL,
                                eo_event_callback_add(ECORE_AUDIO_OUT_PULSE_EVENT_CONTEXT_FAIL, _out_fail, NULL));
 #endif
+
+#if HAVE_TIZENAUDIO
+                    }
+#endif
                   if (out) outs++;
                }
              if (!out)