1 #ifdef HAVE_CONFIG_H
2 #include <config.h>
3 #endif
4 
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <string.h>
8 
9 #ifdef HAVE_FEATURES_H
10 #include <features.h>
11 #endif
12 
13 #include <Eo.h>
14 #include "ecore_audio_private.h"
15 #include <sndfile.h>
16 
17 #define MY_CLASS ECORE_AUDIO_IN_SNDFILE_CLASS
18 #define MY_CLASS_NAME "Ecore_Audio_In_Sndfile"
19 
20 extern SF_VIRTUAL_IO vio_wrapper;
21 
22 struct _Ecore_Audio_In_Sndfile_Data
23 {
24   SNDFILE *handle;
25   SF_INFO sfinfo;
26 };
27 
28 typedef struct _Ecore_Audio_In_Sndfile_Data Ecore_Audio_In_Sndfile_Data;
29 
30 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)31 _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)
32 {
33   if (!ESF_LOAD()) return 0;
34   return ESF_CALL(sf_read_float)(obj->handle, data, len/4)*4;
35 }
36 
37 EOLIAN static double
_ecore_audio_in_sndfile_ecore_audio_in_seek(Eo * eo_obj EINA_UNUSED,Ecore_Audio_In_Sndfile_Data * obj,double offs,int mode)38 _ecore_audio_in_sndfile_ecore_audio_in_seek(Eo *eo_obj EINA_UNUSED, Ecore_Audio_In_Sndfile_Data *obj, double offs, int mode)
39 {
40   sf_count_t count, pos;
41 
42   if (!ESF_LOAD()) return 0.0;
43   count = offs * obj->sfinfo.samplerate;
44   pos = ESF_CALL(sf_seek)(obj->handle, count, mode);
45 
46   return (double)pos / obj->sfinfo.samplerate;
47 }
48 
49 EOLIAN static Eina_Bool
_ecore_audio_in_sndfile_ecore_audio_source_set(Eo * eo_obj,Ecore_Audio_In_Sndfile_Data * obj,const char * source)50 _ecore_audio_in_sndfile_ecore_audio_source_set(Eo *eo_obj, Ecore_Audio_In_Sndfile_Data *obj, const char *source)
51 {
52   Ecore_Audio_Object *ea_obj = efl_data_scope_get(eo_obj, ECORE_AUDIO_CLASS);
53   Ecore_Audio_Input *in_obj = efl_data_scope_get(eo_obj, ECORE_AUDIO_IN_CLASS);
54 
55   if (!ESF_LOAD()) return EINA_FALSE;
56   if (obj->handle) {
57     ESF_CALL(sf_close)(obj->handle);
58     obj->handle = NULL;
59   }
60 
61   eina_stringshare_replace(&ea_obj->source, source);
62 
63   if (!ea_obj->source)
64     return EINA_FALSE;
65 
66   obj->handle = ESF_CALL(sf_open)(ea_obj->source, SFM_READ, &obj->sfinfo);
67 
68   if (!obj->handle) {
69     eina_stringshare_del(ea_obj->source);
70     ea_obj->source = NULL;
71     return EINA_FALSE;
72   }
73 
74   in_obj->seekable = EINA_TRUE;
75   in_obj->length = (double)obj->sfinfo.frames / obj->sfinfo.samplerate;
76 
77   in_obj->samplerate =  obj->sfinfo.samplerate;
78   in_obj->channels =  obj->sfinfo.channels;
79 
80   if (obj->sfinfo.format& SF_FORMAT_WAV)
81     ea_obj->format = ECORE_AUDIO_FORMAT_WAV;
82   else if (obj->sfinfo.format& SF_FORMAT_OGG)
83     ea_obj->format = ECORE_AUDIO_FORMAT_OGG;
84   else if (obj->sfinfo.format& SF_FORMAT_FLAC)
85     ea_obj->format = ECORE_AUDIO_FORMAT_FLAC;
86   else
87     ea_obj->format = ECORE_AUDIO_FORMAT_AUTO;
88 
89    return EINA_TRUE;
90 }
91 
92 EOLIAN static const char*
_ecore_audio_in_sndfile_ecore_audio_source_get(const Eo * eo_obj,Ecore_Audio_In_Sndfile_Data * _pd EINA_UNUSED)93 _ecore_audio_in_sndfile_ecore_audio_source_get(const Eo *eo_obj, Ecore_Audio_In_Sndfile_Data *_pd EINA_UNUSED)
94 {
95   Ecore_Audio_Object *obj = efl_data_scope_get(eo_obj, ECORE_AUDIO_CLASS);
96   return obj->source;
97 }
98 
99 EOLIAN static Eina_Bool
_ecore_audio_in_sndfile_ecore_audio_format_set(Eo * eo_obj,Ecore_Audio_In_Sndfile_Data * obj,Ecore_Audio_Format format)100 _ecore_audio_in_sndfile_ecore_audio_format_set(Eo *eo_obj, Ecore_Audio_In_Sndfile_Data *obj, Ecore_Audio_Format format)
101 {
102   Ecore_Audio_Object *ea_obj = efl_data_scope_get(eo_obj, ECORE_AUDIO_CLASS);
103 
104   if (ea_obj->source) {
105       ERR("Input is already open - cannot change format");
106       return EINA_FALSE;
107   }
108 
109   switch (format) {
110     case ECORE_AUDIO_FORMAT_AUTO:
111       obj->sfinfo.format = 0;
112       break;
113     case ECORE_AUDIO_FORMAT_WAV:
114       obj->sfinfo.format = SF_FORMAT_WAV|SF_FORMAT_PCM_16;
115       break;
116     case ECORE_AUDIO_FORMAT_OGG:
117       obj->sfinfo.format = SF_FORMAT_OGG|SF_FORMAT_VORBIS;
118       break;
119     case ECORE_AUDIO_FORMAT_FLAC:
120       obj->sfinfo.format = SF_FORMAT_FLAC;
121       break;
122     default:
123       ERR("Format not supported!");
124       return EINA_FALSE;
125   }
126   ea_obj->format = format;
127 
128   return EINA_TRUE;
129 }
130 
131 EOLIAN static Ecore_Audio_Format
_ecore_audio_in_sndfile_ecore_audio_format_get(const Eo * eo_obj,Ecore_Audio_In_Sndfile_Data * _pd EINA_UNUSED)132 _ecore_audio_in_sndfile_ecore_audio_format_get(const Eo *eo_obj, Ecore_Audio_In_Sndfile_Data *_pd EINA_UNUSED)
133 {
134   Ecore_Audio_Object *obj = efl_data_scope_get(eo_obj, ECORE_AUDIO_CLASS);
135   return obj->format;;
136 }
137 
138 EOLIAN static void
_ecore_audio_in_sndfile_ecore_audio_vio_set(Eo * eo_obj,Ecore_Audio_In_Sndfile_Data * obj,Ecore_Audio_Vio * vio,void * data,efl_key_data_free_func free_func)139 _ecore_audio_in_sndfile_ecore_audio_vio_set(Eo *eo_obj, Ecore_Audio_In_Sndfile_Data *obj, Ecore_Audio_Vio *vio, void *data, efl_key_data_free_func free_func)
140 {
141   Ecore_Audio_Object *ea_obj = efl_data_scope_get(eo_obj, ECORE_AUDIO_CLASS);
142   Ecore_Audio_Input *in_obj = efl_data_scope_get(eo_obj, ECORE_AUDIO_IN_CLASS);
143 
144   if (!ESF_LOAD()) return;
145   if (obj->handle) {
146     ESF_CALL(sf_close)(obj->handle);
147     obj->handle = NULL;
148   }
149 
150   if (vio)
151     eina_stringshare_replace(&ea_obj->source, "VIO");
152   else
153     eina_stringshare_replace(&ea_obj->source, NULL);
154 
155   in_obj->seekable = EINA_FALSE;
156   ecore_audio_obj_vio_set(efl_super(eo_obj, MY_CLASS), vio, data, free_func);
157 
158   if (!vio)
159     return;
160   in_obj->seekable = (vio->seek != NULL);
161 
162   obj->handle = ESF_CALL(sf_open_virtual)(&vio_wrapper, SFM_READ, &obj->sfinfo, eo_obj);
163 
164   if (!obj->handle) {
165     if (ea_obj->vio->free_func)
166       ea_obj->vio->free_func(ea_obj->vio->data);
167     free(ea_obj->vio);
168     ea_obj->vio = NULL;
169     eina_stringshare_del(ea_obj->source);
170     ea_obj->source = NULL;
171     return;
172   }
173 
174   in_obj->seekable = EINA_TRUE;
175   in_obj->length = (double)obj->sfinfo.frames / obj->sfinfo.samplerate;
176 
177   in_obj->samplerate =  obj->sfinfo.samplerate;
178   in_obj->channels =  obj->sfinfo.channels;
179 
180   if (obj->sfinfo.format& SF_FORMAT_WAV)
181     ea_obj->format = ECORE_AUDIO_FORMAT_WAV;
182   else if (obj->sfinfo.format& SF_FORMAT_OGG)
183     ea_obj->format = ECORE_AUDIO_FORMAT_OGG;
184   else if (obj->sfinfo.format& SF_FORMAT_FLAC)
185     ea_obj->format = ECORE_AUDIO_FORMAT_FLAC;
186   else
187     ea_obj->format = ECORE_AUDIO_FORMAT_AUTO;
188 }
189 
190 EOLIAN static void
_ecore_audio_in_sndfile_efl_object_destructor(Eo * eo_obj,Ecore_Audio_In_Sndfile_Data * obj)191 _ecore_audio_in_sndfile_efl_object_destructor(Eo *eo_obj, Ecore_Audio_In_Sndfile_Data *obj)
192 {
193   if (obj->handle)
194     ESF_CALL(sf_close)(obj->handle);
195 
196   efl_destructor(efl_super(eo_obj, MY_CLASS));
197 }
198 
199 #include "ecore_audio_in_sndfile.eo.c"
200