cedric pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=62e29b39f4df40fd3c0a6b17f7a16f0f8fc1d0c9

commit 62e29b39f4df40fd3c0a6b17f7a16f0f8fc1d0c9
Author: Jean Guyomarc'h <jean.guyoma...@gmail.com>
Date:   Wed Apr 15 16:53:39 2015 +0200

    ecore_audio: integrate Apple's CoreAudio to play sounds on OS X.
    
    Summary:
    Ecore_Audio now supports Apple's CoreAudio to play sounds read by 
libsndfile.
    edje_multisense integrates this new feature to enable PLAY_SAMPLE on OS X.
    
    Test Plan:
    Compiles, links and installs fine on OS X.
    Run terminology and elementary_test to hear sound played on user input.
    
    Reviewers: raster, naguirre, cedric
    
    Reviewed By: cedric
    
    Subscribers: plamot, cedric
    
    Differential Revision: https://phab.enlightenment.org/D2295
    
    Signed-off-by: Cedric BAIL <ced...@osg.samsung.com>
---
 configure.ac                                       |  70 +++-
 src/Makefile_Ecore_Audio.am                        |  21 +-
 src/lib/ecore_audio/Ecore_Audio.h                  |   9 +-
 src/lib/ecore_audio/ecore_audio_core_audio.c       |  44 +++
 .../ecore_audio/ecore_audio_obj_out_core_audio.c   | 358 +++++++++++++++++++++
 .../ecore_audio/ecore_audio_obj_out_core_audio.h   |  15 +
 src/lib/ecore_audio/ecore_audio_out_core_audio.eo  |  12 +
 src/lib/ecore_audio/ecore_audio_private.h          |   6 +
 src/lib/edje/edje_multisense.c                     |  12 +
 9 files changed, 538 insertions(+), 9 deletions(-)

diff --git a/configure.ac b/configure.ac
index 45fa102..9eed98c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3208,6 +3208,54 @@ AC_ARG_ENABLE([pulseaudio],
    ],
    [want_pulseaudio="yes"])
 
+if test "x${have_darwin}" = "xyes"; then
+   want_pulseaudio="no"
+   want_alsa="no"
+   want_coreaudio="yes"
+else
+   want_coreaudio="no"
+fi
+
+
+# CoreAudio flags
+if test "x${want_coreaudio}" = "xyes"; then
+   coreaudio_ldflags=""
+   have_coreaudio="no"
+   LIBS_save="$LIBS"
+   LIBS="$LIBS -framework CoreAudio"
+   AC_LINK_IFELSE(
+      [AC_LANG_PROGRAM(
+        [[
+#include <CoreAudio/CoreAudio.h>
+        ]],
+        [[
+UInt32 size;
+AudioDeviceID dev_id;
+AudioObjectPropertyAddress prop = {
+   kAudioHardwarePropertyDefaultOutputDevice,
+   kAudioObjectPropertyScopeGlobal,
+   kAudioObjectPropertyElementMaster
+};
+size = sizeof(AudioDeviceID);
+AudioObjectGetPropertyData(kAudioObjectSystemObject, &prop, 0, NULL,
+                          &size, &dev_id);
+        ]])],
+        [
+         have_coreaudio="yes"
+         coreaudio_ldflags="-framework CoreAudio"
+        ],
+        [have_coreaudio="no"])
+      LIBS="$LIBS_save"
+      AC_MSG_CHECKING([whether Apple CoreAudio framework is supported])
+      AC_MSG_RESULT([${have_coreaudio}])
+fi
+AC_SUBST(coreaudio_ldflags)
+if test "x${have_coreaudio}" = "xyes"; then
+   AC_DEFINE([HAVE_COREAUDIO], [1], [CoreAudio support enabled])
+else
+   AC_DEFINE([HAVE_COREAUDIO], [0], [CoreAudio support disabled])
+fi
+
 
 ### Default values
 
@@ -3234,6 +3282,7 @@ EFL_EVAL_PKGS([ECORE_AUDIO])
 EFL_ADD_FEATURE([ECORE_AUDIO], [alsa])
 EFL_ADD_FEATURE([ECORE_AUDIO], [pulseaudio])
 EFL_ADD_FEATURE([ECORE_AUDIO], [sndfile])
+EFL_ADD_FEATURE([ECORE_AUDIO], [coreaudio])
 
 ### Checks for header files
 
@@ -3250,6 +3299,7 @@ EFL_ADD_FEATURE([ECORE_AUDIO], [sndfile])
 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"])
 
 #### End of Ecore_Audio
 
@@ -4117,7 +4167,7 @@ EFL_LIB_START([Edje])
 ### Additional options to configure
 
 ### Default values
-want_multisense="${want_pulseaudio}"
+
 AC_ARG_ENABLE([multisense],
    [AS_HELP_STRING([--enable-multisense],[Enable multisense support. 
@<:@default=enabled@:>@])],
    [
@@ -4128,7 +4178,13 @@ AC_ARG_ENABLE([multisense],
        CFOPT_WARNING="xyes"
     fi
    ],
-   [want_multisense="${want_pulseaudio}"])
+   [
+    if test "x${want_pulseaudio}" = "xyes" -o "x${want_coreaudio}" = "xyes"; 
then
+       want_multisense="yes"
+    else
+       want_multisense="no"
+    fi
+   ])
 
 # TODO: should we keep or remove these?
 want_edje_program_cache="no"
@@ -4960,11 +5016,12 @@ if test -n "$CFOPT_WARNING"; then
     echo "Reconsider disabling audio."
     echo 
"_____________________________________________________________________"
   fi
-  if test "x${want_pulseaudio}" = "xno"; then
+  if test "x${have_darwin}" = "xno" -a "x${want_pulseaudio}" = "xno"; then
     echo 
"_____________________________________________________________________"
-    echo "The only audio output method supported by Ecore right now is via"
-    echo "Pulseaudio. You have disabled that and likely have broken a whole"
-    echo "bunch of things in the process. Reconsider your configure options."
+    echo "The only audio output method supported by Ecore right now on your"
+    echo "system is via Pulseaudio. You have disabled that and likely have"
+    echo "broken a whole bunch of things in the process. Reconsider your"
+    echo "configure options."
     echo 
"_____________________________________________________________________"
   fi
   if test "x${want_xinput2}" = "xno"; then
@@ -5143,3 +5200,4 @@ if test "x${efl_deprecated_option}" = "xyes"; then
   echo ""
   echo "#-------------------------------------------------------------------#"
 fi
+
diff --git a/src/Makefile_Ecore_Audio.am b/src/Makefile_Ecore_Audio.am
index e87ffb4..8881f19 100644
--- a/src/Makefile_Ecore_Audio.am
+++ b/src/Makefile_Ecore_Audio.am
@@ -8,9 +8,17 @@ ecore_audio_eolian_files = \
        lib/ecore_audio/ecore_audio_out.eo \
        lib/ecore_audio/ecore_audio_in_sndfile.eo \
        lib/ecore_audio/ecore_audio_out_sndfile.eo \
-       lib/ecore_audio/ecore_audio_out_pulse.eo \
        lib/ecore_audio/ecore_audio_in_tone.eo
 
+
+if HAVE_ECORE_AUDIO_PULSE
+ecore_audio_eolian_files += lib/ecore_audio/ecore_audio_out_pulse.eo
+endif
+
+if HAVE_ECORE_AUDIO_CORE_AUDIO
+ecore_audio_eolian_files += lib/ecore_audio/ecore_audio_out_core_audio.eo
+endif
+
 ecore_audio_eolian_c = $(ecore_audio_eolian_files:%.eo=%.eo.c)
 ecore_audio_eolian_h = $(ecore_audio_eolian_files:%.eo=%.eo.h)
 
@@ -40,7 +48,7 @@ lib/ecore_audio/ecore_audio_obj_in_tone.h \
 lib/ecore_audio/ecore_audio_protected.h
 
 nodist_installed_ecoreaudiomainheaders_DATA = $(ecore_audio_eolian_h)
-                                      
+
 lib_ecore_audio_libecore_audio_la_SOURCES = \
 lib/ecore_audio/ecore_audio.c \
 lib/ecore_audio/ecore_audio_obj.c \
@@ -74,6 +82,15 @@ lib/ecore_audio/ecore_audio_obj_out_sndfile.c \
 lib/ecore_audio/ecore_audio_sndfile_vio.c
 endif
 
+if HAVE_ECORE_AUDIO_CORE_AUDIO
+dist_installed_ecoreaudiomainheaders_DATA += \
+lib/ecore_audio/ecore_audio_obj_out_core_audio.h
+lib_ecore_audio_libecore_audio_la_SOURCES += \
+lib/ecore_audio/ecore_audio_obj_out_core_audio.c
+lib_ecore_audio_libecore_audio_la_LDFLAGS += @coreaudio_ldflags@
+
+endif
+
 endif
 
 if HAVE_ELUA
diff --git a/src/lib/ecore_audio/Ecore_Audio.h 
b/src/lib/ecore_audio/Ecore_Audio.h
index 0835d6d..edb9b49 100644
--- a/src/lib/ecore_audio/Ecore_Audio.h
+++ b/src/lib/ecore_audio/Ecore_Audio.h
@@ -44,6 +44,7 @@ enum _Ecore_Audio_Type {
     ECORE_AUDIO_TYPE_ALSA,    /**< Use ALSA module*/
     ECORE_AUDIO_TYPE_SNDFILE, /**< Use libsndfile module */
     ECORE_AUDIO_TYPE_TONE,    /**< Use tone module */
+    ECORE_AUDIO_TYPE_CORE_AUDIO, /**< Use Core Audio module (Apple) */
     ECORE_AUDIO_TYPE_CUSTOM,  /**< Use custom module */
     ECORE_AUDIO_MODULE_LAST,  /**< Sentinel */
 };
@@ -211,7 +212,13 @@ EAPI int                 ecore_audio_shutdown(void);
 
 #include <ecore_audio_obj_in_tone.h>
 
-#include <ecore_audio_obj_out_pulse.h>
+#if HAVE_COREAUDIO
+# include <ecore_audio_obj_out_core_audio.h>
+#endif
+
+#if HAVE_PULSE
+# include <ecore_audio_obj_out_pulse.h>
+#endif
 
 /**
  * @}
diff --git a/src/lib/ecore_audio/ecore_audio_core_audio.c 
b/src/lib/ecore_audio/ecore_audio_core_audio.c
new file mode 100644
index 0000000..2141d9d
--- /dev/null
+++ b/src/lib/ecore_audio/ecore_audio_core_audio.c
@@ -0,0 +1,44 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_COREAUDIO
+#include "Ecore.h"
+#include "ecore_private.h"
+#include "Ecore_Audio.h"
+#include "ecore_audio_private.h"
+
+static Ecore_Audio_Module *_module = NULL;
+
+EAPI Ecore_Audio_Module *
+ecore_audio_core_audio_init(void)
+{
+   /* Don't call this twice */
+   if (_module != NULL) return _module;
+
+   _module = calloc(1, sizeof(Ecore_Audio_Module));
+   if (EINA_UNLIKELY(_module == NULL))
+     {
+        CRI("Failed to allocate Ecore_Audio_Module");
+        goto ret_null;
+     }
+
+   ECORE_MAGIC_SET(_module, ECORE_MAGIC_AUDIO_MODULE);
+   _module->type = ECORE_AUDIO_TYPE_CORE_AUDIO;
+   _module->name = "CoreAudio";
+
+   return _module;
+
+ret_null:
+   return NULL;
+}
+
+EAPI void
+ecore_audio_nssound_shutdown(void)
+{
+   free(_module);
+   _module = NULL;
+}
+
+#endif /* HAVE_COREAUDIO */
+
diff --git a/src/lib/ecore_audio/ecore_audio_obj_out_core_audio.c 
b/src/lib/ecore_audio/ecore_audio_obj_out_core_audio.c
new file mode 100644
index 0000000..d358ec0
--- /dev/null
+++ b/src/lib/ecore_audio/ecore_audio_obj_out_core_audio.c
@@ -0,0 +1,358 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Eo.h>
+#include "ecore_audio_private.h"
+
+#include <CoreAudio/CoreAudio.h>
+
+/* Notes:
+ *
+ * A lot of source code on the internet dealing with CoreAudio is deprecated.
+ * sndfile-play (bundled with libsndfile) is no exception and uses an almost
+ * 10 years old API. Nethertheless, sndfile-play has been heavily used to
+ * create the CoreAudio module.
+ *
+ * Documentation is almost non-existant, but here is the technical note from
+ * Apple explaining how CoreAudio objects should be manipulated:
+ * https://developer.apple.com/library/mac/technotes/tn2223/_index.html
+ */
+
+#include "ecore_audio_obj_out_core_audio.h"
+
+typedef struct
+{
+   Eo                                  *input;
+   Eo                                  *output;
+   AudioDeviceIOProcID                  proc_id;
+   AudioStreamBasicDescription          format;
+   AudioObjectID                        obj_id;
+   UInt32                               buf_size;
+
+   Eina_Bool                            is_playing;
+   Eina_Bool                            fake_stereo;
+} Core_Audio_Helper;
+
+
+/* Apple's error codes are tricky: they are stored as 32 bits integers.
+ * However, they are supposed to be represented as 4-bytes strings.
+ * There is no equivalent of strerror() (of what I know).
+ *
+ * Ref: http://vgable.com/blog/2008/04/23/printing-a-fourcharcode/
+ *
+ * In case of error, take a look at CoreAudio/AudioHardwareBase.h where
+ * the error codes are explained.
+ */
+#define APPLE_ERROR(err_) \
+   (char[5]){((err_) >> 24) & 0xff, ((err_) >> 16) & 0xff, ((err_) >> 8) & 
0xff, (err_) & 0xff, 0}
+
+#define MY_CLASS ECORE_AUDIO_OUT_CORE_AUDIO_CLASS
+#define MY_CLASS_NAME "Ecore_Audio_Out_Core_Audio"
+
+/*
+ * Unused structure. Only here because of Eolian.
+ * XXX Maybe it is possible to get rid of it.
+ */
+typedef struct
+{
+   void *this_data_is_here_to_silent_warnings;
+} Ecore_Audio_Out_Core_Audio_Data;
+
+
+/*============================================================================*
+ *                                 Helper API                                 *
+ 
*============================================================================*/
+
+static Core_Audio_Helper *
+_core_audio_helper_new(void)
+{
+   return calloc(1, sizeof(Core_Audio_Helper));
+}
+
+static void
+_core_audio_helper_stop(Core_Audio_Helper *helper)
+{
+   EINA_SAFETY_ON_NULL_RETURN(helper);
+
+   OSStatus err;
+
+   if (!helper->is_playing) return;
+
+   /* Stop audio device */
+   err = AudioDeviceStop(helper->obj_id, helper->proc_id);
+   if (EINA_UNLIKELY(err != noErr))
+     ERR("Failed to stop audio device %i for proc id %p: '%s'",
+         helper->obj_id, helper->proc_id, APPLE_ERROR(err));
+
+   /* Remove proc ID */
+   err = AudioDeviceDestroyIOProcID(helper->obj_id, helper->proc_id);
+   if (EINA_UNLIKELY(err != noErr))
+     ERR("Failed to stop audio device %i for proc id %p: '%s'",
+         helper->obj_id, helper->proc_id, APPLE_ERROR(err));
+
+   helper->is_playing = EINA_FALSE;
+}
+
+static void
+_core_audio_helper_free(Core_Audio_Helper *helper)
+{
+   EINA_SAFETY_ON_NULL_RETURN(helper);
+
+   if (helper->is_playing)
+     _core_audio_helper_stop(helper);
+   free(helper);
+}
+
+
+/*============================================================================*
+ *                           Audio Object Properties                          *
+ 
*============================================================================*/
+
+static OSStatus
+_audio_object_id_get(AudioObjectID *obj_id)
+{
+   OSStatus err;
+   UInt32 size;
+   AudioObjectPropertyAddress prop = {
+      kAudioHardwarePropertyDefaultOutputDevice,
+      kAudioObjectPropertyScopePlayThrough,
+      kAudioObjectPropertyElementMaster
+   };
+
+   /* Default output device */
+   size = sizeof(AudioObjectID);
+   err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &prop, 0, NULL,
+                                    &size, obj_id);
+   return err;
+}
+
+static OSStatus
+_audio_device_stream_format_get(AudioObjectID                obj_id,
+                                AudioStreamBasicDescription *format)
+{
+   OSStatus err;
+   UInt32 size;
+   AudioObjectPropertyAddress prop = {
+      kAudioDevicePropertyStreamFormat,
+      kAudioObjectPropertyScopePlayThrough,
+      kAudioObjectPropertyElementMaster /* Channel number */
+   };
+
+   size = sizeof(AudioStreamBasicDescription);
+   err = AudioObjectGetPropertyData(obj_id, &prop, 0, NULL, &size, format);
+   return err;
+}
+
+static OSStatus
+_audio_device_stream_format_set(AudioObjectID                obj_id,
+                                AudioStreamBasicDescription *format)
+{
+   OSStatus err;
+   UInt32 size;
+   AudioObjectPropertyAddress prop = {
+      kAudioDevicePropertyStreamFormat,
+      kAudioObjectPropertyScopePlayThrough,
+      kAudioObjectPropertyElementMaster /* Channel number */
+   };
+
+   size = sizeof(AudioStreamBasicDescription);
+   err = AudioObjectSetPropertyData(obj_id, &prop, 0, NULL, size, format);
+   return err;
+}
+
+
+/*============================================================================*
+ *                               Audio Callback                               *
+ 
*============================================================================*/
+
+static OSStatus
+_audio_io_proc_cb(AudioObjectID          obj_id         EINA_UNUSED,
+                  const AudioTimeStamp  *in_now         EINA_UNUSED,
+                  const AudioBufferList *input_data     EINA_UNUSED,
+                  const AudioTimeStamp  *input_time     EINA_UNUSED,
+                  AudioBufferList       *output_data,
+                  const AudioTimeStamp  *in_output_time EINA_UNUSED,
+                  void                  *data)
+{
+   Core_Audio_Helper *helper = data;
+   float *buf;
+   int size, bread, sample_count, k;
+
+   size = output_data->mBuffers[0].mDataByteSize;
+   buf = output_data->mBuffers[0].mData;
+   sample_count = size / sizeof(float);
+
+   if (helper->fake_stereo)
+     {
+        eo_do(helper->input, bread = ecore_audio_obj_in_read(buf, size * 2));
+
+        for (k = bread - 1; k >= 0; --k)
+          {
+             buf[2 * k + 0] = buf[k];
+             buf[2 * k + 1] = buf[k];
+          }
+        bread /= 2;
+     }
+   else
+     {
+        eo_do(helper->input, bread = ecore_audio_obj_in_read(buf, size * 4));
+        bread /= 4;
+     }
+
+   /* Done playing */
+   if (bread < sample_count)
+     {
+        INF("Done playing: %i < %i", bread, sample_count);
+        /* Auto-detached. Don't need to do more. */
+     }
+
+   return noErr;
+}
+
+
+/*============================================================================*
+ *                                   Eo API                                   *
+ 
*============================================================================*/
+
+EOLIAN static void
+_ecore_audio_out_core_audio_eo_base_constructor(Eo *obj, 
Ecore_Audio_Out_Core_Audio_Data *sd EINA_UNUSED)
+{
+   eo_do_super(obj, MY_CLASS, eo_constructor());
+}
+
+EOLIAN static void
+_ecore_audio_out_core_audio_eo_base_destructor(Eo *obj, 
Ecore_Audio_Out_Core_Audio_Data *sd EINA_UNUSED)
+{
+   eo_do_super(obj, MY_CLASS, eo_destructor());
+}
+
+EOLIAN static void
+_ecore_audio_out_core_audio_ecore_audio_volume_set(Eo *obj, 
Ecore_Audio_Out_Core_Audio_Data *sd EINA_UNUSED, double volume)
+{
+   // TODO Change volume of playing inputs
+   eo_do_super(obj, MY_CLASS, ecore_audio_obj_volume_set(volume));
+}
+
+EOLIAN static Eina_Bool
+_ecore_audio_out_core_audio_ecore_audio_out_input_attach(Eo *obj, 
Ecore_Audio_Out_Core_Audio_Data *sd EINA_UNUSED, Eo *input)
+{
+   Core_Audio_Helper *helper;
+   UInt32 channels;
+   OSStatus err;
+   Eina_Bool chk;
+
+   eo_do_super(obj, MY_CLASS, chk = ecore_audio_obj_out_input_attach(input));
+   if (EINA_UNLIKELY(!chk))
+     {
+        ERR("Failed to attach input (eo_do_super)");
+        goto return_failure;
+     }
+
+   helper = _core_audio_helper_new();
+   if (EINA_UNLIKELY(helper == NULL))
+     {
+        CRI("Failed to allocate memory");
+        goto detach;
+     }
+
+   /* Keep track of input source and output object */
+   helper->input = input;
+   helper->output = obj;
+
+   /* Default output device */
+   err = _audio_object_id_get(&(helper->obj_id));
+   if (EINA_UNLIKELY(err != noErr))
+     {
+        ERR("Failed to get object property: default output device: '%s'",
+            APPLE_ERROR(err));
+        goto free_helper;
+     }
+
+   /* Get data format description */
+   err = _audio_device_stream_format_get(helper->obj_id, &(helper->format));
+   if (EINA_UNLIKELY(err != noErr))
+     {
+        ERR("Failed to get property: stream format: '%s'", APPLE_ERROR(err));
+        goto free_helper;
+     }
+
+   /* Forward samplerate to CoreAudio */
+   eo_do(input, helper->format.mSampleRate = 
ecore_audio_obj_in_samplerate_get());
+
+   /* Set channels. If only 1 channel, emulate stereo */
+   eo_do(input, channels = ecore_audio_obj_in_channels_get());
+   if (channels == 1)
+     {
+        DBG("Fake stereo enabled for input %p", input);
+        helper->fake_stereo = EINA_TRUE;
+        channels = 2;
+     }
+   helper->format.mChannelsPerFrame = channels;
+
+   /* Set new format description */
+   err = _audio_device_stream_format_set(helper->obj_id, &(helper->format));
+   if (EINA_UNLIKELY(err != noErr))
+     {
+        ERR("Failed to set property: stream format: '%s'", APPLE_ERROR(err));
+        goto free_helper;
+     }
+
+   /* We want linear PCM */
+   if (helper->format.mFormatID != kAudioFormatLinearPCM)
+     {
+        ERR("Invalid format ID. Expected linear PCM: '%s'", APPLE_ERROR(err));
+        goto free_helper;
+     }
+
+   /* Create IO proc ID */
+   err = AudioDeviceCreateIOProcID(helper->obj_id, _audio_io_proc_cb,
+                                   helper, &(helper->proc_id));
+   if (err != noErr)
+     {
+        ERR("Failed to create IO proc ID. Error: '%s'", APPLE_ERROR(err));
+        goto free_helper;
+     }
+
+   /* Keep track of data for deallocation */
+   eo_do(input, eo_key_data_set("coreaudio_data", helper, NULL));
+
+   /* Start playing */
+   helper->is_playing = EINA_TRUE;
+   err = AudioDeviceStart(helper->obj_id, helper->proc_id);
+   if (err != noErr)
+     {
+        ERR("Failed to start proc ID %p for device id %i: '%s'",
+            helper->proc_id, helper->obj_id, APPLE_ERROR(err));
+        goto free_proc_id;
+     }
+
+   return EINA_TRUE;
+
+free_proc_id:
+   AudioDeviceDestroyIOProcID(helper->obj_id, helper->proc_id);
+free_helper:
+   free(helper);
+detach:
+   eo_do_super(obj, MY_CLASS, ecore_audio_obj_out_input_detach(input));
+return_failure:
+   return EINA_FALSE;
+}
+
+EOLIAN static Eina_Bool
+_ecore_audio_out_core_audio_ecore_audio_out_input_detach(Eo *obj, 
Ecore_Audio_Out_Core_Audio_Data *sd EINA_UNUSED, Eo *input)
+{
+   Core_Audio_Helper *data;
+   Eina_Bool ret;
+
+   DBG("Detach");
+   /* Free helper */
+   eo_do(input, data = eo_key_data_get("coreaudio_data"));
+   _core_audio_helper_free(data);
+
+   eo_do_super(obj, MY_CLASS, ret = ecore_audio_obj_out_input_detach(input));
+
+   return ret;
+}
+
+#include "ecore_audio_out_core_audio.eo.c"
diff --git a/src/lib/ecore_audio/ecore_audio_obj_out_core_audio.h 
b/src/lib/ecore_audio/ecore_audio_obj_out_core_audio.h
new file mode 100644
index 0000000..9b8eb7d
--- /dev/null
+++ b/src/lib/ecore_audio/ecore_audio_obj_out_core_audio.h
@@ -0,0 +1,15 @@
+#ifndef _ECORE_AUDIO_OBJ_OUT_CORE_AUDIO_H_
+#define _ECORE_AUDIO_OBJ_OUT_CORE_AUDIO_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ecore_audio_out_core_audio.eo.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ! _ECORE_AUDIO_OBJ_OUT_CORE_AUDIO_H_ */
+
diff --git a/src/lib/ecore_audio/ecore_audio_out_core_audio.eo 
b/src/lib/ecore_audio/ecore_audio_out_core_audio.eo
new file mode 100644
index 0000000..6176ce7
--- /dev/null
+++ b/src/lib/ecore_audio/ecore_audio_out_core_audio.eo
@@ -0,0 +1,12 @@
+class Ecore_Audio_Out_Core_Audio (Ecore_Audio_Out)
+{
+   eo_prefix: ecore_audio_obj_out_core_audio;
+   implements {
+      Eo.Base.constructor;
+      Eo.Base.destructor;
+      Ecore_Audio.volume.set;
+      Ecore_Audio_Out.input_attach;
+      Ecore_Audio_Out.input_detach;
+   }
+}
+
diff --git a/src/lib/ecore_audio/ecore_audio_private.h 
b/src/lib/ecore_audio/ecore_audio_private.h
index 36a06f5..13a7b6a 100644
--- a/src/lib/ecore_audio/ecore_audio_private.h
+++ b/src/lib/ecore_audio/ecore_audio_private.h
@@ -169,6 +169,12 @@ Ecore_Audio_Module *ecore_audio_sndfile_init(void);
 void                ecore_audio_sndfile_shutdown(void);
 #endif /* HAVE_SNDFILE */
 
+#ifdef HAVE_COREAUDIO
+/* ecore_audio_core_audio */
+Ecore_Audio_Module *ecore_audio_core_audio_init(void);
+void                ecore_audio_core_audio_shutdown(void);
+#endif /* HAVE_COREAUDIO */
+
 Ecore_Audio_Module *ecore_audio_tone_init(void);
 void                ecore_audio_tone_shutdown(void);
 
diff --git a/src/lib/edje/edje_multisense.c b/src/lib/edje/edje_multisense.c
index da24e0c..913c1f9 100644
--- a/src/lib/edje/edje_multisense.c
+++ b/src/lib/edje/edje_multisense.c
@@ -204,13 +204,21 @@ _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_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 (out) outs++;
               }
             if (!out)
               {
+#if HAVE_COREAUDIO
+                 ERR("Could not create multisense audio out (CoreAudio)");
+#elif HAVE_PULSE
                  ERR("Could not create multisense audio out (pulse)");
+#endif
                  eo_del(in);
                  return EINA_FALSE;
               }
@@ -269,8 +277,12 @@ _edje_multisense_internal_sound_tone_play(Edje *ed, const 
char *tone_name, const
 
              if (!out)
                {
+#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 (out) outs++;
                }
 

-- 


Reply via email to