ecore_audio: Implement virtual IO for generic input
authorDaniel Willmann <d.willmann@samsung.com>
Wed, 17 Apr 2013 18:06:21 +0000 (19:06 +0100)
committerDaniel Willmann <d.willmann@samsung.com>
Thu, 18 Apr 2013 18:15:39 +0000 (19:15 +0100)
Signed-off-by: Daniel Willmann <d.willmann@samsung.com>
src/lib/ecore_audio/Ecore_Audio.h
src/lib/ecore_audio/ecore_audio_obj.c
src/lib/ecore_audio/ecore_audio_obj.h
src/lib/ecore_audio/ecore_audio_obj_in.c
src/lib/ecore_audio/ecore_audio_private.h

index b87f647..c405140 100644 (file)
@@ -76,11 +76,11 @@ typedef struct _Ecore_Audio_Object Ecore_Audio_Object;  /**< The audio object */
 typedef int (*Ecore_Audio_Read_Callback)(void *user_data, void *data, int len);
 
 struct _Ecore_Audio_Vio {
-    int (*get_length)(Ecore_Audio_Object *in);
-    int (*seek)(Ecore_Audio_Object *in, int offset, int whence);
-    int (*tell)(Ecore_Audio_Object *in);
-    int (*read)(Ecore_Audio_Object *in, void *buffer, int length);
-    int (*write)(Ecore_Audio_Object *out, const void *buffer, int length);
+    int (*get_length)(void *data, Eo *eo_obj);
+    int (*seek)(void *data, Eo *eo_obj, int offset, int whence);
+    int (*tell)(void *data, Eo *eo_obj);
+    int (*read)(void *data, Eo *eo_obj, void *buffer, int length);
+    int (*write)(void *data, Eo *eo_obj, const void *buffer, int length);
 };
 
 typedef struct _Ecore_Audio_Vio Ecore_Audio_Vio; /**< Functions to implement IO virtually */
index aa78c9c..62a784e 100644 (file)
@@ -137,6 +137,7 @@ static const Eo_Op_Description op_desc[] = {
     EO_OP_DESCRIPTION(ECORE_AUDIO_OBJ_SUB_ID_SOURCE_GET, "Gets the source of the object."),
     EO_OP_DESCRIPTION(ECORE_AUDIO_OBJ_SUB_ID_FORMAT_SET, "Sets the format of the object."),
     EO_OP_DESCRIPTION(ECORE_AUDIO_OBJ_SUB_ID_FORMAT_GET, "Gets the format of the object."),
+    EO_OP_DESCRIPTION(ECORE_AUDIO_OBJ_SUB_ID_VIO_SET, "Sets virtual IO callbacks for this object."),
     EO_OP_DESCRIPTION_SENTINEL
 };
 
index e806e8a..87c08b8 100644 (file)
@@ -51,6 +51,7 @@ enum Ecore_Audio_Obj_Sub_Ids
    ECORE_AUDIO_OBJ_SUB_ID_SOURCE_GET,
    ECORE_AUDIO_OBJ_SUB_ID_FORMAT_SET,
    ECORE_AUDIO_OBJ_SUB_ID_FORMAT_GET,
+   ECORE_AUDIO_OBJ_SUB_ID_VIO_SET,
    ECORE_AUDIO_OBJ_SUB_ID_LAST
 };
 
@@ -92,6 +93,8 @@ enum Ecore_Audio_Obj_Sub_Ids
 
 #define ecore_audio_obj_format_get(ret) ECORE_AUDIO_OBJ_ID(ECORE_AUDIO_OBJ_SUB_ID_FORMAT_GET), EO_TYPECHECK(Ecore_Audio_Format *, ret)
 
+#define ecore_audio_obj_vio_set(vio, data, free_func) ECORE_AUDIO_OBJ_ID(ECORE_AUDIO_OBJ_SUB_ID_VIO_SET), EO_TYPECHECK(Ecore_Audio_Vio *, vio), EO_TYPECHECK(void *, data), EO_TYPECHECK(eo_base_data_free_func, free_func)
+
 /**
  * @}
  */
index 983b310..1528a04 100644 (file)
@@ -132,7 +132,9 @@ static void _remaining_get(Eo *eo_obj, void *_pd, va_list *list)
 
   double *ret = va_arg(*list, double *);
 
-  if (ret) {
+  if (!ea_obj->seekable && ret) {
+      *ret = -1;
+  } else if (ret) {
     eo_do(eo_obj, ecore_audio_obj_in_seek(0, SEEK_CUR, ret));
     *ret = obj->length - *ret;
   }
@@ -154,7 +156,7 @@ static void _read(Eo *eo_obj, void *_pd, va_list *list)
   } else {
       eo_do(eo_obj, ecore_audio_obj_in_read_internal(buf, len, &len_read));
       if (len_read == 0) {
-          if (!obj->looped) {
+          if (!obj->looped || !ea_obj->seekable) {
               eo_do(eo_obj, eo_event_callback_call(ECORE_AUDIO_EV_IN_STOPPED, NULL, NULL));
           } else {
               eo_do(eo_obj, ecore_audio_obj_in_seek(0, SEEK_SET, NULL));
@@ -169,6 +171,24 @@ static void _read(Eo *eo_obj, void *_pd, va_list *list)
     *ret = len_read;
 }
 
+static void _read_internal(Eo *eo_obj, void *_pd, va_list *list)
+{
+  const Ecore_Audio_Input *obj = _pd;
+  ssize_t len_read = 0;
+  const Ecore_Audio_Object *ea_obj = eo_data_get(eo_obj, ECORE_AUDIO_OBJ_CLASS);
+
+  char *buf = va_arg(*list, char *);
+  size_t len = va_arg(*list, size_t);
+  ssize_t *ret = va_arg(*list, ssize_t *);
+
+  if (ea_obj->vio && ea_obj->vio->vio->read) {
+      len_read = ea_obj->vio->vio->read(ea_obj->vio->data, eo_obj, buf, len);
+  }
+
+  if (ret)
+    *ret = len_read;
+}
+
 static void _output_get(Eo *eo_obj, void *_pd, va_list *list)
 {
   const Ecore_Audio_Input *obj = _pd;
@@ -179,6 +199,37 @@ static void _output_get(Eo *eo_obj, void *_pd, va_list *list)
     *ret = obj->output;
 }
 
+static void _free_vio(Ecore_Audio_Object *ea_obj)
+{
+  if (ea_obj->vio->free_func)
+    ea_obj->vio->free_func(ea_obj->vio->data);
+
+  free(ea_obj->vio);
+  ea_obj->vio = NULL;
+}
+
+static void _vio_set(Eo *eo_obj, void *_pd EINA_UNUSED, va_list *list)
+{
+  Ecore_Audio_Object *ea_obj = eo_data_get(eo_obj, ECORE_AUDIO_OBJ_CLASS);
+
+  Ecore_Audio_Vio *vio = va_arg(*list, Ecore_Audio_Vio *);
+  void *data = va_arg(*list, Ecore_Audio_Vio *);
+  eo_base_data_free_func free_func = va_arg(*list, eo_base_data_free_func);
+
+  if (ea_obj->vio)
+    _free_vio(ea_obj);
+
+  if (!vio)
+    return;
+
+  ea_obj->vio = calloc(1, sizeof(Ecore_Audio_Vio_Internal));
+  ea_obj->vio->vio = vio;
+  ea_obj->vio->data = data;
+  ea_obj->vio->free_func = free_func;
+  //FIXME: Save previous value
+  ea_obj->seekable = (vio->seek != NULL);
+}
+
 static void _constructor(Eo *eo_obj, void *_pd, va_list *list EINA_UNUSED)
 {
   Ecore_Audio_Input *obj = _pd;
@@ -205,6 +256,8 @@ static void _class_constructor(Eo_Class *klass)
       EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_CONSTRUCTOR), _constructor),
       EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_DESTRUCTOR), _destructor),
 
+      EO_OP_FUNC(ECORE_AUDIO_OBJ_ID(ECORE_AUDIO_OBJ_SUB_ID_VIO_SET), _vio_set),
+
       /* Specific functions to this class */
       EO_OP_FUNC(ECORE_AUDIO_OBJ_IN_ID(ECORE_AUDIO_OBJ_IN_SUB_ID_SPEED_SET), _speed_set),
       EO_OP_FUNC(ECORE_AUDIO_OBJ_IN_ID(ECORE_AUDIO_OBJ_IN_SUB_ID_SPEED_GET), _speed_get),
@@ -217,6 +270,7 @@ static void _class_constructor(Eo_Class *klass)
       EO_OP_FUNC(ECORE_AUDIO_OBJ_IN_ID(ECORE_AUDIO_OBJ_IN_SUB_ID_LENGTH_GET), _length_get),
       EO_OP_FUNC(ECORE_AUDIO_OBJ_IN_ID(ECORE_AUDIO_OBJ_IN_SUB_ID_REMAINING_GET), _remaining_get),
       EO_OP_FUNC(ECORE_AUDIO_OBJ_IN_ID(ECORE_AUDIO_OBJ_IN_SUB_ID_READ), _read),
+      EO_OP_FUNC(ECORE_AUDIO_OBJ_IN_ID(ECORE_AUDIO_OBJ_IN_SUB_ID_READ_INTERNAL), _read_internal),
       EO_OP_FUNC(ECORE_AUDIO_OBJ_IN_ID(ECORE_AUDIO_OBJ_IN_SUB_ID_OUTPUT_GET), _output_get),
 
       EO_OP_FUNC_SENTINEL
index 7868b08..e899a04 100644 (file)
@@ -91,6 +91,13 @@ struct _Ecore_Audio_Module
    struct output_api *out_ops;
 };
 
+struct _Ecore_Audio_Vio_Internal {
+    Ecore_Audio_Vio *vio;
+    void *data;
+    eo_base_data_free_func free_func;
+};
+typedef struct _Ecore_Audio_Vio_Internal Ecore_Audio_Vio_Internal;
+
 /**
  * @brief A common structure, could be input or output
  */
@@ -99,10 +106,11 @@ struct _Ecore_Audio_Object
    const char         *name;
    const char         *source;
 
+   Eina_Bool           seekable;
    Eina_Bool           paused;
    double              volume;
    Ecore_Audio_Format  format;
-
+   Ecore_Audio_Vio_Internal *vio;
 };
 
 /**