• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /* Engine implementation */
18 
19 #include "sles_allinclusive.h"
20 
21 
22 /* Utility functions */
23 
initializeBufferQueueMembers(CAudioPlayer * ap)24 static SLresult initializeBufferQueueMembers(CAudioPlayer *ap) {
25     // inline allocation of circular mArray, up to a typical max
26     if (BUFFER_HEADER_TYPICAL >= ap->mBufferQueue.mNumBuffers) {
27         ap->mBufferQueue.mArray = ap->mBufferQueue.mTypical;
28     } else {
29         // Avoid possible integer overflow during multiplication; this arbitrary
30         // maximum is big enough to not interfere with real applications, but
31         // small enough to not overflow.
32         if (ap->mBufferQueue.mNumBuffers >= 256) {
33             return SL_RESULT_MEMORY_FAILURE;
34         }
35         ap->mBufferQueue.mArray = (BufferHeader *)
36                 malloc((ap->mBufferQueue.mNumBuffers + 1) * sizeof(BufferHeader));
37         if (NULL == ap->mBufferQueue.mArray) {
38             return SL_RESULT_MEMORY_FAILURE;
39         }
40     }
41     ap->mBufferQueue.mFront = ap->mBufferQueue.mArray;
42     ap->mBufferQueue.mRear = ap->mBufferQueue.mArray;
43     return SL_RESULT_SUCCESS;
44 }
45 
46 #ifdef ANDROID
initializeAndroidBufferQueueMembers(CAudioPlayer * ap)47 static SLresult initializeAndroidBufferQueueMembers(CAudioPlayer *ap) {
48     // Avoid possible integer overflow during multiplication; this arbitrary
49     // maximum is big enough to not interfere with real applications, but
50     // small enough to not overflow.
51     if (ap->mAndroidBufferQueue.mNumBuffers >= 256) {
52         return SL_RESULT_MEMORY_FAILURE;
53     }
54     ap->mAndroidBufferQueue.mBufferArray = (AdvancedBufferHeader *)
55             malloc( (ap->mAndroidBufferQueue.mNumBuffers + 1) * sizeof(AdvancedBufferHeader));
56     if (NULL == ap->mAndroidBufferQueue.mBufferArray) {
57         return SL_RESULT_MEMORY_FAILURE;
58     } else {
59 
60         // initialize ABQ buffer type
61         // assert below has been checked in android_audioPlayer_checkSourceSink
62         assert(SL_DATAFORMAT_MIME == ap->mDataSource.mFormat.mFormatType);
63         switch(ap->mDataSource.mFormat.mMIME.containerType) {
64           case SL_CONTAINERTYPE_MPEG_TS:
65             ap->mAndroidBufferQueue.mBufferType = kAndroidBufferTypeMpeg2Ts;
66             break;
67           case SL_CONTAINERTYPE_AAC:
68           case SL_CONTAINERTYPE_RAW: {
69             const char* mime = (char*)ap->mDataSource.mFormat.mMIME.mimeType;
70             if ((mime != NULL) && !(strcasecmp(mime, ANDROID_MIME_AACADTS) &&
71                     strcasecmp(mime, ANDROID_MIME_AACADTS_ANDROID_FRAMEWORK))) {
72                 ap->mAndroidBufferQueue.mBufferType = kAndroidBufferTypeAacadts;
73             } else {
74                 ap->mAndroidBufferQueue.mBufferType = kAndroidBufferTypeInvalid;
75                 SL_LOGE("CreateAudioPlayer: Invalid buffer type in Android Buffer Queue");
76                 return SL_RESULT_CONTENT_UNSUPPORTED;
77             }
78           } break;
79           default:
80             ap->mAndroidBufferQueue.mBufferType = kAndroidBufferTypeInvalid;
81             SL_LOGE("CreateAudioPlayer: Invalid buffer type in Android Buffer Queue");
82             return SL_RESULT_CONTENT_UNSUPPORTED;
83         }
84 
85         // initialize ABQ memory
86         for (SLuint16 i=0 ; i<(ap->mAndroidBufferQueue.mNumBuffers + 1) ; i++) {
87             AdvancedBufferHeader *pBuf = &ap->mAndroidBufferQueue.mBufferArray[i];
88             pBuf->mDataBuffer = NULL;
89             pBuf->mDataSize = 0;
90             pBuf->mDataSizeConsumed = 0;
91             pBuf->mBufferContext = NULL;
92             pBuf->mBufferState = SL_ANDROIDBUFFERQUEUEEVENT_NONE;
93             switch (ap->mAndroidBufferQueue.mBufferType) {
94               case kAndroidBufferTypeMpeg2Ts:
95                 pBuf->mItems.mTsCmdData.mTsCmdCode = ANDROID_MP2TSEVENT_NONE;
96                 pBuf->mItems.mTsCmdData.mPts = 0;
97                 break;
98               case kAndroidBufferTypeAacadts:
99                 pBuf->mItems.mAdtsCmdData.mAdtsCmdCode = ANDROID_ADTSEVENT_NONE;
100                 break;
101               default:
102                 return SL_RESULT_CONTENT_UNSUPPORTED;
103             }
104         }
105         ap->mAndroidBufferQueue.mFront = ap->mAndroidBufferQueue.mBufferArray;
106         ap->mAndroidBufferQueue.mRear  = ap->mAndroidBufferQueue.mBufferArray;
107     }
108 
109     return SL_RESULT_SUCCESS;
110 }
111 #endif
112 
113 
IEngine_CreateLEDDevice(SLEngineItf self,SLObjectItf * pDevice,SLuint32 deviceID,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired)114 static SLresult IEngine_CreateLEDDevice(SLEngineItf self, SLObjectItf *pDevice, SLuint32 deviceID,
115     SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
116 {
117     SL_ENTER_INTERFACE
118 
119 #if USE_PROFILES & USE_PROFILES_OPTIONAL
120     if ((NULL == pDevice) || (SL_DEFAULTDEVICEID_LED != deviceID)) {
121         result = SL_RESULT_PARAMETER_INVALID;
122     } else {
123         *pDevice = NULL;
124         unsigned exposedMask;
125         const ClassTable *pCLEDDevice_class = objectIDtoClass(SL_OBJECTID_LEDDEVICE);
126         if (NULL == pCLEDDevice_class) {
127             result = SL_RESULT_FEATURE_UNSUPPORTED;
128         } else {
129             result = checkInterfaces(pCLEDDevice_class, numInterfaces, pInterfaceIds,
130                 pInterfaceRequired, &exposedMask, NULL);
131         }
132         if (SL_RESULT_SUCCESS == result) {
133             CLEDDevice *thiz = (CLEDDevice *) construct(pCLEDDevice_class, exposedMask, self);
134             if (NULL == thiz) {
135                 result = SL_RESULT_MEMORY_FAILURE;
136             } else {
137                 thiz->mDeviceID = deviceID;
138                 IObject_Publish(&thiz->mObject);
139                 // return the new LED object
140                 *pDevice = &thiz->mObject.mItf;
141             }
142         }
143     }
144 #else
145     result = SL_RESULT_FEATURE_UNSUPPORTED;
146 #endif
147 
148     SL_LEAVE_INTERFACE
149 }
150 
151 
IEngine_CreateVibraDevice(SLEngineItf self,SLObjectItf * pDevice,SLuint32 deviceID,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired)152 static SLresult IEngine_CreateVibraDevice(SLEngineItf self, SLObjectItf *pDevice, SLuint32 deviceID,
153     SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
154 {
155     SL_ENTER_INTERFACE
156 
157 #if USE_PROFILES & USE_PROFILES_OPTIONAL
158     if ((NULL == pDevice) || (SL_DEFAULTDEVICEID_VIBRA != deviceID)) {
159         result = SL_RESULT_PARAMETER_INVALID;
160     } else {
161         *pDevice = NULL;
162         unsigned exposedMask;
163         const ClassTable *pCVibraDevice_class = objectIDtoClass(SL_OBJECTID_VIBRADEVICE);
164         if (NULL == pCVibraDevice_class) {
165             result = SL_RESULT_FEATURE_UNSUPPORTED;
166         } else {
167             result = checkInterfaces(pCVibraDevice_class, numInterfaces,
168                 pInterfaceIds, pInterfaceRequired, &exposedMask, NULL);
169         }
170         if (SL_RESULT_SUCCESS == result) {
171             CVibraDevice *thiz = (CVibraDevice *) construct(pCVibraDevice_class, exposedMask, self);
172             if (NULL == thiz) {
173                 result = SL_RESULT_MEMORY_FAILURE;
174             } else {
175                 thiz->mDeviceID = deviceID;
176                 IObject_Publish(&thiz->mObject);
177                 // return the new vibra object
178                 *pDevice = &thiz->mObject.mItf;
179             }
180         }
181     }
182 #else
183     result = SL_RESULT_FEATURE_UNSUPPORTED;
184 #endif
185 
186     SL_LEAVE_INTERFACE
187 }
188 
189 
IEngine_CreateAudioPlayer(SLEngineItf self,SLObjectItf * pPlayer,SLDataSource * pAudioSrc,SLDataSink * pAudioSnk,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired)190 static SLresult IEngine_CreateAudioPlayer(SLEngineItf self, SLObjectItf *pPlayer,
191     SLDataSource *pAudioSrc, SLDataSink *pAudioSnk, SLuint32 numInterfaces,
192     const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
193 {
194     SL_ENTER_INTERFACE
195 
196     if (NULL == pPlayer) {
197        result = SL_RESULT_PARAMETER_INVALID;
198     } else {
199         *pPlayer = NULL;
200         unsigned exposedMask, requiredMask;
201         const ClassTable *pCAudioPlayer_class = objectIDtoClass(SL_OBJECTID_AUDIOPLAYER);
202         assert(NULL != pCAudioPlayer_class);
203         result = checkInterfaces(pCAudioPlayer_class, numInterfaces,
204             pInterfaceIds, pInterfaceRequired, &exposedMask, &requiredMask);
205         if (SL_RESULT_SUCCESS == result) {
206 
207             // Construct our new AudioPlayer instance
208             CAudioPlayer *thiz = (CAudioPlayer *) construct(pCAudioPlayer_class, exposedMask, self);
209             if (NULL == thiz) {
210                 result = SL_RESULT_MEMORY_FAILURE;
211             } else {
212 
213                 do {
214 
215                     // Initialize private fields not associated with an interface
216 
217                     // Default data source in case of failure in checkDataSource
218                     thiz->mDataSource.mLocator.mLocatorType = SL_DATALOCATOR_NULL;
219                     thiz->mDataSource.mFormat.mFormatType = SL_DATAFORMAT_NULL;
220 
221                     // Default data sink in case of failure in checkDataSink
222                     thiz->mDataSink.mLocator.mLocatorType = SL_DATALOCATOR_NULL;
223                     thiz->mDataSink.mFormat.mFormatType = SL_DATAFORMAT_NULL;
224 
225                     // Default is no per-channel mute or solo
226                     thiz->mMuteMask = 0;
227                     thiz->mSoloMask = 0;
228 
229                     // Will be set soon for PCM buffer queues, or later by platform-specific code
230                     // during Realize or Prefetch
231                     thiz->mNumChannels = UNKNOWN_NUMCHANNELS;
232                     thiz->mSampleRateMilliHz = UNKNOWN_SAMPLERATE;
233 
234                     // More default values, in case destructor needs to be called early
235                     thiz->mDirectLevel = 0;
236 #ifdef USE_OUTPUTMIXEXT
237                     thiz->mTrack = NULL;
238                     thiz->mGains[0] = 1.0f;
239                     thiz->mGains[1] = 1.0f;
240                     thiz->mDestroyRequested = SL_BOOLEAN_FALSE;
241 #endif
242 #ifdef USE_SNDFILE
243                     thiz->mSndFile.mPathname = NULL;
244                     thiz->mSndFile.mSNDFILE = NULL;
245                     memset(&thiz->mSndFile.mSfInfo, 0, sizeof(SF_INFO));
246                     memset(&thiz->mSndFile.mMutex, 0, sizeof(pthread_mutex_t));
247                     thiz->mSndFile.mEOF = SL_BOOLEAN_FALSE;
248                     thiz->mSndFile.mWhich = 0;
249                     memset(thiz->mSndFile.mBuffer, 0, sizeof(thiz->mSndFile.mBuffer));
250 #endif
251 #ifdef ANDROID
252                     // placement new (explicit constructor)
253                     // FIXME unnecessary once those fields are encapsulated in one class, rather
254                     //   than a structure
255                     (void) new (&thiz->mAudioTrack) android::sp<android::AudioTrackProxy>();
256                     (void) new (&thiz->mCallbackProtector)
257                             android::sp<android::CallbackProtector>();
258                     (void) new (&thiz->mAuxEffect) android::sp<android::AudioEffect>();
259                     (void) new (&thiz->mAPlayer) android::sp<android::GenericPlayer>();
260 #endif
261 
262                     // Check the source and sink parameters against generic constraints,
263                     // and make a local copy of all parameters in case other application threads
264                     // change memory concurrently.
265 
266                     result = checkDataSource("pAudioSrc", pAudioSrc, &thiz->mDataSource,
267                             DATALOCATOR_MASK_URI | DATALOCATOR_MASK_ADDRESS |
268                             DATALOCATOR_MASK_BUFFERQUEUE
269 #ifdef ANDROID
270                             | DATALOCATOR_MASK_ANDROIDFD | DATALOCATOR_MASK_ANDROIDSIMPLEBUFFERQUEUE
271                             | DATALOCATOR_MASK_ANDROIDBUFFERQUEUE
272 #endif
273                             , DATAFORMAT_MASK_MIME | DATAFORMAT_MASK_PCM);
274 
275                     if (SL_RESULT_SUCCESS != result) {
276                         break;
277                     }
278 
279                     result = checkDataSink("pAudioSnk", pAudioSnk, &thiz->mDataSink,
280                             DATALOCATOR_MASK_OUTPUTMIX                  // for playback
281 #ifdef ANDROID
282                             | DATALOCATOR_MASK_ANDROIDSIMPLEBUFFERQUEUE // for decode to a BQ
283                             | DATALOCATOR_MASK_BUFFERQUEUE              // for decode to a BQ
284 #endif
285                             , DATAFORMAT_MASK_NULL
286 #ifdef ANDROID
287                             | DATAFORMAT_MASK_PCM                       // for decode to PCM
288 #endif
289                             );
290                     if (SL_RESULT_SUCCESS != result) {
291                         break;
292                     }
293 
294                     // It would be unsafe to ever refer to the application pointers again
295                     pAudioSrc = NULL;
296                     pAudioSnk = NULL;
297 
298                     // Check that the requested interfaces are compatible with data source and sink
299                     result = checkSourceSinkVsInterfacesCompatibility(&thiz->mDataSource,
300                             &thiz->mDataSink, pCAudioPlayer_class, requiredMask);
301                     if (SL_RESULT_SUCCESS != result) {
302                         break;
303                     }
304 
305                     // copy the buffer queue count from source locator (for playback) / from the
306                     // sink locator (for decode on ANDROID build) to the buffer queue interface
307                     // we have already range-checked the value down to a smaller width
308                     SLuint16 nbBuffers = 0;
309                     bool usesAdvancedBufferHeaders = false;
310                     bool usesSimpleBufferQueue = false;
311                     // creating an AudioPlayer which decodes AAC ADTS buffers to a PCM buffer queue
312                     //  will cause usesAdvancedBufferHeaders and usesSimpleBufferQueue to be true
313                     switch (thiz->mDataSource.mLocator.mLocatorType) {
314                     case SL_DATALOCATOR_BUFFERQUEUE:
315 #ifdef ANDROID
316                     case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE:
317 #endif
318                         usesSimpleBufferQueue = true;
319                         nbBuffers = (SLuint16) thiz->mDataSource.mLocator.mBufferQueue.numBuffers;
320                         assert(SL_DATAFORMAT_PCM == thiz->mDataSource.mFormat.mFormatType);
321                         thiz->mNumChannels = thiz->mDataSource.mFormat.mPCM.numChannels;
322                         thiz->mSampleRateMilliHz = thiz->mDataSource.mFormat.mPCM.samplesPerSec;
323                         break;
324 #ifdef ANDROID
325                     case SL_DATALOCATOR_ANDROIDBUFFERQUEUE:
326                         usesAdvancedBufferHeaders = true;
327                         nbBuffers = (SLuint16) thiz->mDataSource.mLocator.mABQ.numBuffers;
328                         thiz->mAndroidBufferQueue.mNumBuffers = nbBuffers;
329                         break;
330 #endif
331                     default:
332                         nbBuffers = 0;
333                         break;
334                     }
335 #ifdef ANDROID
336                     switch(thiz->mDataSink.mLocator.mLocatorType) {
337                     case SL_DATALOCATOR_BUFFERQUEUE:
338                     case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE:
339                         usesSimpleBufferQueue = true;
340                         nbBuffers = thiz->mDataSink.mLocator.mBufferQueue.numBuffers;
341                         assert(SL_DATAFORMAT_PCM == thiz->mDataSink.mFormat.mFormatType);
342                         // FIXME The values specified by the app are meaningless. We get the
343                         // real values from the decoder.  But the data sink checks currently require
344                         // that the app specify these useless values.  Needs doc/fix.
345                         // Instead use the "unknown" values, as needed by prepare completion.
346                         // thiz->mNumChannels = thiz->mDataSink.mFormat.mPCM.numChannels;
347                         // thiz->mSampleRateMilliHz = thiz->mDataSink.mFormat.mPCM.samplesPerSec;
348                         thiz->mNumChannels = UNKNOWN_NUMCHANNELS;
349                         thiz->mSampleRateMilliHz = UNKNOWN_SAMPLERATE;
350                         break;
351                     default:
352                         // leave nbBuffers unchanged
353                         break;
354                     }
355 #endif
356                     thiz->mBufferQueue.mNumBuffers = nbBuffers;
357 
358                     // check the audio source and sink parameters against platform support
359 #ifdef ANDROID
360                     result = android_audioPlayer_checkSourceSink(thiz);
361                     if (SL_RESULT_SUCCESS != result) {
362                         break;
363                     }
364 #endif
365 
366 #ifdef USE_SNDFILE
367                     result = SndFile_checkAudioPlayerSourceSink(thiz);
368                     if (SL_RESULT_SUCCESS != result) {
369                         break;
370                     }
371 #endif
372 
373 #ifdef USE_OUTPUTMIXEXT
374                     result = IOutputMixExt_checkAudioPlayerSourceSink(thiz);
375                     if (SL_RESULT_SUCCESS != result) {
376                         break;
377                     }
378 #endif
379 
380                     // Allocate memory for buffer queue
381                     if (usesAdvancedBufferHeaders) {
382 #ifdef ANDROID
383                         // locator is SL_DATALOCATOR_ANDROIDBUFFERQUEUE
384                         result = initializeAndroidBufferQueueMembers(thiz);
385 #else
386                         assert(false);
387 #endif
388                     }
389 
390                     if (usesSimpleBufferQueue) {
391                         // locator is SL_DATALOCATOR_BUFFERQUEUE
392                         //         or SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE
393                         result = initializeBufferQueueMembers(thiz);
394                     }
395 
396                     // used to store the data source of our audio player
397                     thiz->mDynamicSource.mDataSource = &thiz->mDataSource.u.mSource;
398 
399                     // platform-specific initialization
400 #ifdef ANDROID
401                     android_audioPlayer_create(thiz);
402 #endif
403 
404                 } while (0);
405 
406                 if (SL_RESULT_SUCCESS != result) {
407                     IObject_Destroy(&thiz->mObject.mItf);
408                 } else {
409                     IObject_Publish(&thiz->mObject);
410                     // return the new audio player object
411                     *pPlayer = &thiz->mObject.mItf;
412                 }
413 
414             }
415         }
416 
417     }
418 
419     SL_LEAVE_INTERFACE
420 }
421 
422 
IEngine_CreateAudioRecorder(SLEngineItf self,SLObjectItf * pRecorder,SLDataSource * pAudioSrc,SLDataSink * pAudioSnk,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired)423 static SLresult IEngine_CreateAudioRecorder(SLEngineItf self, SLObjectItf *pRecorder,
424     SLDataSource *pAudioSrc, SLDataSink *pAudioSnk, SLuint32 numInterfaces,
425     const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
426 {
427     SL_ENTER_INTERFACE
428 
429 #if (USE_PROFILES & USE_PROFILES_OPTIONAL) || defined(ANDROID)
430     if (NULL == pRecorder) {
431         result = SL_RESULT_PARAMETER_INVALID;
432     } else {
433         *pRecorder = NULL;
434         unsigned exposedMask;
435         const ClassTable *pCAudioRecorder_class = objectIDtoClass(SL_OBJECTID_AUDIORECORDER);
436         if (NULL == pCAudioRecorder_class) {
437             result = SL_RESULT_FEATURE_UNSUPPORTED;
438         } else {
439             result = checkInterfaces(pCAudioRecorder_class, numInterfaces,
440                     pInterfaceIds, pInterfaceRequired, &exposedMask, NULL);
441         }
442 
443         if (SL_RESULT_SUCCESS == result) {
444 
445             // Construct our new AudioRecorder instance
446             CAudioRecorder *thiz = (CAudioRecorder *) construct(pCAudioRecorder_class, exposedMask,
447                     self);
448             if (NULL == thiz) {
449                 result = SL_RESULT_MEMORY_FAILURE;
450             } else {
451 
452                 do {
453 
454                     // Initialize fields not associated with any interface
455 
456                     // Default data source in case of failure in checkDataSource
457                     thiz->mDataSource.mLocator.mLocatorType = SL_DATALOCATOR_NULL;
458                     thiz->mDataSource.mFormat.mFormatType = SL_DATAFORMAT_NULL;
459 
460                     // Default data sink in case of failure in checkDataSink
461                     thiz->mDataSink.mLocator.mLocatorType = SL_DATALOCATOR_NULL;
462                     thiz->mDataSink.mFormat.mFormatType = SL_DATAFORMAT_NULL;
463 
464                     // These fields are set to real values by
465                     // android_audioRecorder_checkSourceSinkSupport.  Note that the data sink is
466                     // always PCM buffer queue, so we know the channel count and sample rate early.
467                     thiz->mNumChannels = UNKNOWN_NUMCHANNELS;
468                     thiz->mSampleRateMilliHz = UNKNOWN_SAMPLERATE;
469 #ifdef ANDROID
470                     thiz->mAudioRecord = NULL;
471                     thiz->mRecordSource = AUDIO_SOURCE_DEFAULT;
472 #endif
473 
474                     // Check the source and sink parameters, and make a local copy of all parameters
475                     result = checkDataSource("pAudioSrc", pAudioSrc, &thiz->mDataSource,
476                             DATALOCATOR_MASK_IODEVICE, DATAFORMAT_MASK_NULL);
477                     if (SL_RESULT_SUCCESS != result) {
478                         break;
479                     }
480                     result = checkDataSink("pAudioSnk", pAudioSnk, &thiz->mDataSink,
481                             DATALOCATOR_MASK_URI
482 #ifdef ANDROID
483                             | DATALOCATOR_MASK_ANDROIDSIMPLEBUFFERQUEUE
484 #endif
485                             , DATAFORMAT_MASK_MIME | DATAFORMAT_MASK_PCM
486                     );
487                     if (SL_RESULT_SUCCESS != result) {
488                         break;
489                     }
490 
491                     // It would be unsafe to ever refer to the application pointers again
492                     pAudioSrc = NULL;
493                     pAudioSnk = NULL;
494 
495                     // check the audio source and sink parameters against platform support
496 #ifdef ANDROID
497                     result = android_audioRecorder_checkSourceSinkSupport(thiz);
498                     if (SL_RESULT_SUCCESS != result) {
499                         SL_LOGE("Cannot create AudioRecorder: invalid source or sink");
500                         break;
501                     }
502 #endif
503 
504 #ifdef ANDROID
505                     // Allocate memory for buffer queue
506                     SLuint32 locatorType = thiz->mDataSink.mLocator.mLocatorType;
507                     if (locatorType == SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE) {
508                         thiz->mBufferQueue.mNumBuffers =
509                             thiz->mDataSink.mLocator.mBufferQueue.numBuffers;
510                         // inline allocation of circular Buffer Queue mArray, up to a typical max
511                         if (BUFFER_HEADER_TYPICAL >= thiz->mBufferQueue.mNumBuffers) {
512                             thiz->mBufferQueue.mArray = thiz->mBufferQueue.mTypical;
513                         } else {
514                             // Avoid possible integer overflow during multiplication; this arbitrary
515                             // maximum is big enough to not interfere with real applications, but
516                             // small enough to not overflow.
517                             if (thiz->mBufferQueue.mNumBuffers >= 256) {
518                                 result = SL_RESULT_MEMORY_FAILURE;
519                                 break;
520                             }
521                             thiz->mBufferQueue.mArray = (BufferHeader *) malloc((thiz->mBufferQueue.
522                                     mNumBuffers + 1) * sizeof(BufferHeader));
523                             if (NULL == thiz->mBufferQueue.mArray) {
524                                 result = SL_RESULT_MEMORY_FAILURE;
525                                 break;
526                             }
527                         }
528                         thiz->mBufferQueue.mFront = thiz->mBufferQueue.mArray;
529                         thiz->mBufferQueue.mRear = thiz->mBufferQueue.mArray;
530                     }
531 #endif
532 
533                     // platform-specific initialization
534 #ifdef ANDROID
535                     android_audioRecorder_create(thiz);
536 #endif
537 
538                 } while (0);
539 
540                 if (SL_RESULT_SUCCESS != result) {
541                     IObject_Destroy(&thiz->mObject.mItf);
542                 } else {
543                     IObject_Publish(&thiz->mObject);
544                     // return the new audio recorder object
545                     *pRecorder = &thiz->mObject.mItf;
546                 }
547             }
548 
549         }
550 
551     }
552 #else
553     result = SL_RESULT_FEATURE_UNSUPPORTED;
554 #endif
555 
556     SL_LEAVE_INTERFACE
557 }
558 
559 
IEngine_CreateMidiPlayer(SLEngineItf self,SLObjectItf * pPlayer,SLDataSource * pMIDISrc,SLDataSource * pBankSrc,SLDataSink * pAudioOutput,SLDataSink * pVibra,SLDataSink * pLEDArray,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired)560 static SLresult IEngine_CreateMidiPlayer(SLEngineItf self, SLObjectItf *pPlayer,
561     SLDataSource *pMIDISrc, SLDataSource *pBankSrc, SLDataSink *pAudioOutput,
562     SLDataSink *pVibra, SLDataSink *pLEDArray, SLuint32 numInterfaces,
563     const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
564 {
565     SL_ENTER_INTERFACE
566 
567 #if USE_PROFILES & (USE_PROFILES_GAME | USE_PROFILES_PHONE)
568     if ((NULL == pPlayer) || (NULL == pMIDISrc) || (NULL == pAudioOutput)) {
569         result = SL_RESULT_PARAMETER_INVALID;
570     } else {
571         *pPlayer = NULL;
572         unsigned exposedMask;
573         const ClassTable *pCMidiPlayer_class = objectIDtoClass(SL_OBJECTID_MIDIPLAYER);
574         if (NULL == pCMidiPlayer_class) {
575             result = SL_RESULT_FEATURE_UNSUPPORTED;
576         } else {
577             result = checkInterfaces(pCMidiPlayer_class, numInterfaces,
578                 pInterfaceIds, pInterfaceRequired, &exposedMask, NULL);
579         }
580         if (SL_RESULT_SUCCESS == result) {
581             CMidiPlayer *thiz = (CMidiPlayer *) construct(pCMidiPlayer_class, exposedMask, self);
582             if (NULL == thiz) {
583                 result = SL_RESULT_MEMORY_FAILURE;
584             } else {
585 #if 0
586                 "pMIDISrc", pMIDISrc, URI | MIDIBUFFERQUEUE, NONE
587                 "pBankSrc", pBanksrc, NULL | URI | ADDRESS, NULL
588                 "pAudioOutput", pAudioOutput, OUTPUTMIX, NULL
589                 "pVibra", pVibra, NULL | IODEVICE, NULL
590                 "pLEDArray", pLEDArray, NULL | IODEVICE, NULL
591 #endif
592                 // a fake value - why not use value from IPlay_init? what does CT check for?
593                 thiz->mPlay.mDuration = 0;
594                 IObject_Publish(&thiz->mObject);
595                 // return the new MIDI player object
596                 *pPlayer = &thiz->mObject.mItf;
597             }
598         }
599     }
600 #else
601     result = SL_RESULT_FEATURE_UNSUPPORTED;
602 #endif
603 
604     SL_LEAVE_INTERFACE
605 }
606 
607 
IEngine_CreateListener(SLEngineItf self,SLObjectItf * pListener,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired)608 static SLresult IEngine_CreateListener(SLEngineItf self, SLObjectItf *pListener,
609     SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
610 {
611     SL_ENTER_INTERFACE
612 
613 #if USE_PROFILES & USE_PROFILES_GAME
614     if (NULL == pListener) {
615         result = SL_RESULT_PARAMETER_INVALID;
616     } else {
617         *pListener = NULL;
618         unsigned exposedMask;
619         const ClassTable *pCListener_class = objectIDtoClass(SL_OBJECTID_LISTENER);
620         if (NULL == pCListener_class) {
621             result = SL_RESULT_FEATURE_UNSUPPORTED;
622         } else {
623             result = checkInterfaces(pCListener_class, numInterfaces,
624                 pInterfaceIds, pInterfaceRequired, &exposedMask, NULL);
625         }
626         if (SL_RESULT_SUCCESS == result) {
627             CListener *thiz = (CListener *) construct(pCListener_class, exposedMask, self);
628             if (NULL == thiz) {
629                 result = SL_RESULT_MEMORY_FAILURE;
630             } else {
631                 IObject_Publish(&thiz->mObject);
632                 // return the new 3D listener object
633                 *pListener = &thiz->mObject.mItf;
634             }
635         }
636     }
637 #else
638     result = SL_RESULT_FEATURE_UNSUPPORTED;
639 #endif
640 
641     SL_LEAVE_INTERFACE
642 }
643 
644 
IEngine_Create3DGroup(SLEngineItf self,SLObjectItf * pGroup,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired)645 static SLresult IEngine_Create3DGroup(SLEngineItf self, SLObjectItf *pGroup, SLuint32 numInterfaces,
646     const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
647 {
648     SL_ENTER_INTERFACE
649 
650 #if USE_PROFILES & USE_PROFILES_GAME
651     if (NULL == pGroup) {
652         result = SL_RESULT_PARAMETER_INVALID;
653     } else {
654         *pGroup = NULL;
655         unsigned exposedMask;
656         const ClassTable *pC3DGroup_class = objectIDtoClass(SL_OBJECTID_3DGROUP);
657         if (NULL == pC3DGroup_class) {
658             result = SL_RESULT_FEATURE_UNSUPPORTED;
659         } else {
660             result = checkInterfaces(pC3DGroup_class, numInterfaces,
661                 pInterfaceIds, pInterfaceRequired, &exposedMask, NULL);
662         }
663         if (SL_RESULT_SUCCESS == result) {
664             C3DGroup *thiz = (C3DGroup *) construct(pC3DGroup_class, exposedMask, self);
665             if (NULL == thiz) {
666                 result = SL_RESULT_MEMORY_FAILURE;
667             } else {
668                 thiz->mMemberMask = 0;
669                 IObject_Publish(&thiz->mObject);
670                 // return the new 3D group object
671                 *pGroup = &thiz->mObject.mItf;
672             }
673         }
674     }
675 #else
676     result = SL_RESULT_FEATURE_UNSUPPORTED;
677 #endif
678 
679     SL_LEAVE_INTERFACE
680 }
681 
682 
IEngine_CreateOutputMix(SLEngineItf self,SLObjectItf * pMix,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired)683 static SLresult IEngine_CreateOutputMix(SLEngineItf self, SLObjectItf *pMix, SLuint32 numInterfaces,
684     const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
685 {
686     SL_ENTER_INTERFACE
687 
688     if (NULL == pMix) {
689         result = SL_RESULT_PARAMETER_INVALID;
690     } else {
691         *pMix = NULL;
692         unsigned exposedMask;
693         const ClassTable *pCOutputMix_class = objectIDtoClass(SL_OBJECTID_OUTPUTMIX);
694         assert(NULL != pCOutputMix_class);
695         result = checkInterfaces(pCOutputMix_class, numInterfaces,
696             pInterfaceIds, pInterfaceRequired, &exposedMask, NULL);
697         if (SL_RESULT_SUCCESS == result) {
698             COutputMix *thiz = (COutputMix *) construct(pCOutputMix_class, exposedMask, self);
699             if (NULL == thiz) {
700                 result = SL_RESULT_MEMORY_FAILURE;
701             } else {
702 #ifdef ANDROID
703                 android_outputMix_create(thiz);
704 #endif
705 #ifdef USE_SDL
706                 IEngine *thisEngine = &thiz->mObject.mEngine->mEngine;
707                 interface_lock_exclusive(thisEngine);
708                 bool unpause = false;
709                 if (NULL == thisEngine->mOutputMix) {
710                     thisEngine->mOutputMix = thiz;
711                     unpause = true;
712                 }
713                 interface_unlock_exclusive(thisEngine);
714 #endif
715                 IObject_Publish(&thiz->mObject);
716 #ifdef USE_SDL
717                 if (unpause) {
718                     // Enable SDL_callback to be called periodically by SDL's internal thread
719                     SDL_PauseAudio(0);
720                 }
721 #endif
722                 // return the new output mix object
723                 *pMix = &thiz->mObject.mItf;
724             }
725         }
726     }
727 
728     SL_LEAVE_INTERFACE
729 }
730 
731 
IEngine_CreateMetadataExtractor(SLEngineItf self,SLObjectItf * pMetadataExtractor,SLDataSource * pDataSource,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired)732 static SLresult IEngine_CreateMetadataExtractor(SLEngineItf self, SLObjectItf *pMetadataExtractor,
733     SLDataSource *pDataSource, SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds,
734     const SLboolean *pInterfaceRequired)
735 {
736     SL_ENTER_INTERFACE
737 
738 #if USE_PROFILES & (USE_PROFILES_GAME | USE_PROFILES_MUSIC)
739     if (NULL == pMetadataExtractor) {
740         result = SL_RESULT_PARAMETER_INVALID;
741     } else {
742         *pMetadataExtractor = NULL;
743         unsigned exposedMask;
744         const ClassTable *pCMetadataExtractor_class =
745             objectIDtoClass(SL_OBJECTID_METADATAEXTRACTOR);
746         if (NULL == pCMetadataExtractor_class) {
747             result = SL_RESULT_FEATURE_UNSUPPORTED;
748         } else {
749             result = checkInterfaces(pCMetadataExtractor_class, numInterfaces,
750                 pInterfaceIds, pInterfaceRequired, &exposedMask, NULL);
751         }
752         if (SL_RESULT_SUCCESS == result) {
753             CMetadataExtractor *thiz = (CMetadataExtractor *)
754                 construct(pCMetadataExtractor_class, exposedMask, self);
755             if (NULL == thiz) {
756                 result = SL_RESULT_MEMORY_FAILURE;
757             } else {
758 #if 0
759                 "pDataSource", pDataSource, NONE, NONE
760 #endif
761                 IObject_Publish(&thiz->mObject);
762                 // return the new metadata extractor object
763                 *pMetadataExtractor = &thiz->mObject.mItf;
764                 result = SL_RESULT_SUCCESS;
765             }
766         }
767     }
768 #else
769     result = SL_RESULT_FEATURE_UNSUPPORTED;
770 #endif
771 
772     SL_LEAVE_INTERFACE
773 }
774 
775 
IEngine_CreateExtensionObject(SLEngineItf self,SLObjectItf * pObject,void * pParameters,SLuint32 objectID,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired)776 static SLresult IEngine_CreateExtensionObject(SLEngineItf self, SLObjectItf *pObject,
777     void *pParameters, SLuint32 objectID, SLuint32 numInterfaces,
778     const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
779 {
780     SL_ENTER_INTERFACE
781 
782     if (NULL == pObject) {
783         result = SL_RESULT_PARAMETER_INVALID;
784     } else {
785         *pObject = NULL;
786         result = SL_RESULT_FEATURE_UNSUPPORTED;
787     }
788 
789     SL_LEAVE_INTERFACE
790 }
791 
792 
IEngine_QueryNumSupportedInterfaces(SLEngineItf self,SLuint32 objectID,SLuint32 * pNumSupportedInterfaces)793 static SLresult IEngine_QueryNumSupportedInterfaces(SLEngineItf self,
794     SLuint32 objectID, SLuint32 *pNumSupportedInterfaces)
795 {
796     SL_ENTER_INTERFACE
797 
798     if (NULL == pNumSupportedInterfaces) {
799         result = SL_RESULT_PARAMETER_INVALID;
800     } else {
801         const ClassTable *clazz = objectIDtoClass(objectID);
802         if (NULL == clazz) {
803             result = SL_RESULT_FEATURE_UNSUPPORTED;
804         } else {
805             SLuint32 count = 0;
806             SLuint32 i;
807             for (i = 0; i < clazz->mInterfaceCount; ++i) {
808                 switch (clazz->mInterfaces[i].mInterface) {
809                 case INTERFACE_IMPLICIT:
810                 case INTERFACE_IMPLICIT_PREREALIZE:
811                 case INTERFACE_EXPLICIT:
812                 case INTERFACE_EXPLICIT_PREREALIZE:
813                 case INTERFACE_DYNAMIC:
814                     ++count;
815                     break;
816                 case INTERFACE_UNAVAILABLE:
817                     break;
818                 default:
819                     assert(false);
820                     break;
821                 }
822             }
823             *pNumSupportedInterfaces = count;
824             result = SL_RESULT_SUCCESS;
825         }
826     }
827 
828     SL_LEAVE_INTERFACE;
829 }
830 
831 
IEngine_QuerySupportedInterfaces(SLEngineItf self,SLuint32 objectID,SLuint32 index,SLInterfaceID * pInterfaceId)832 static SLresult IEngine_QuerySupportedInterfaces(SLEngineItf self,
833     SLuint32 objectID, SLuint32 index, SLInterfaceID *pInterfaceId)
834 {
835     SL_ENTER_INTERFACE
836 
837     if (NULL == pInterfaceId) {
838         result = SL_RESULT_PARAMETER_INVALID;
839     } else {
840         *pInterfaceId = NULL;
841         const ClassTable *clazz = objectIDtoClass(objectID);
842         if (NULL == clazz) {
843             result = SL_RESULT_FEATURE_UNSUPPORTED;
844         } else {
845             result = SL_RESULT_PARAMETER_INVALID; // will be reset later
846             SLuint32 i;
847             for (i = 0; i < clazz->mInterfaceCount; ++i) {
848                 switch (clazz->mInterfaces[i].mInterface) {
849                 case INTERFACE_IMPLICIT:
850                 case INTERFACE_IMPLICIT_PREREALIZE:
851                 case INTERFACE_EXPLICIT:
852                 case INTERFACE_EXPLICIT_PREREALIZE:
853                 case INTERFACE_DYNAMIC:
854                     break;
855                 case INTERFACE_UNAVAILABLE:
856                     continue;
857                 default:
858                     assert(false);
859                     break;
860                 }
861                 if (index == 0) {
862                     *pInterfaceId = &SL_IID_array[clazz->mInterfaces[i].mMPH];
863                     result = SL_RESULT_SUCCESS;
864                     break;
865                 }
866                 --index;
867             }
868         }
869     }
870 
871     SL_LEAVE_INTERFACE
872 };
873 
874 
875 static const char * const extensionNames[] = {
876 #ifdef ANDROID
877 #define _(n) #n
878 #define __(n) _(n)
879     "ANDROID_SDK_LEVEL_" __(PLATFORM_SDK_VERSION),
880 #undef _
881 #undef __
882 #else
883     "WILHELM_DESKTOP",
884 #endif
885 };
886 
887 
IEngine_QueryNumSupportedExtensions(SLEngineItf self,SLuint32 * pNumExtensions)888 static SLresult IEngine_QueryNumSupportedExtensions(SLEngineItf self, SLuint32 *pNumExtensions)
889 {
890     SL_ENTER_INTERFACE
891 
892     if (NULL == pNumExtensions) {
893         result = SL_RESULT_PARAMETER_INVALID;
894     } else {
895         *pNumExtensions = sizeof(extensionNames) / sizeof(extensionNames[0]);
896         result = SL_RESULT_SUCCESS;
897     }
898 
899     SL_LEAVE_INTERFACE
900 }
901 
902 
IEngine_QuerySupportedExtension(SLEngineItf self,SLuint32 index,SLchar * pExtensionName,SLint16 * pNameLength)903 static SLresult IEngine_QuerySupportedExtension(SLEngineItf self,
904     SLuint32 index, SLchar *pExtensionName, SLint16 *pNameLength)
905 {
906     SL_ENTER_INTERFACE
907 
908     if (NULL == pNameLength) {
909         result = SL_RESULT_PARAMETER_INVALID;
910     } else {
911         size_t actualNameLength;
912         unsigned numExtensions = sizeof(extensionNames) / sizeof(extensionNames[0]);
913         if (index >= numExtensions) {
914             actualNameLength = 0;
915             result = SL_RESULT_PARAMETER_INVALID;
916         } else {
917             const char *extensionName = extensionNames[index];
918             actualNameLength = strlen(extensionName) + 1;
919             if (NULL == pExtensionName) {
920                 // application is querying the name length in order to allocate a buffer
921                 result = SL_RESULT_SUCCESS;
922             } else {
923                 SLint16 availableNameLength = *pNameLength;
924                 if (0 >= availableNameLength) {
925                     // there is not even room for the terminating NUL
926                     result = SL_RESULT_BUFFER_INSUFFICIENT;
927                 } else if (actualNameLength > (size_t) availableNameLength) {
928                     // "no invalid strings are written. That is, the null-terminator always exists"
929                     memcpy(pExtensionName, extensionName, (size_t) availableNameLength - 1);
930                     pExtensionName[(size_t) availableNameLength - 1] = '\0';
931                     result = SL_RESULT_BUFFER_INSUFFICIENT;
932                 } else {
933                     memcpy(pExtensionName, extensionName, actualNameLength);
934                     result = SL_RESULT_SUCCESS;
935                 }
936             }
937         }
938         *pNameLength = actualNameLength;
939     }
940 
941     SL_LEAVE_INTERFACE
942 }
943 
944 
IEngine_IsExtensionSupported(SLEngineItf self,const SLchar * pExtensionName,SLboolean * pSupported)945 static SLresult IEngine_IsExtensionSupported(SLEngineItf self,
946     const SLchar *pExtensionName, SLboolean *pSupported)
947 {
948     SL_ENTER_INTERFACE
949 
950     if (NULL == pSupported) {
951         result = SL_RESULT_PARAMETER_INVALID;
952     } else {
953         SLboolean isSupported = SL_BOOLEAN_FALSE;
954         if (NULL == pExtensionName) {
955             result = SL_RESULT_PARAMETER_INVALID;
956         } else {
957             unsigned numExtensions = sizeof(extensionNames) / sizeof(extensionNames[0]);
958             unsigned i;
959             for (i = 0; i < numExtensions; ++i) {
960                 if (!strcmp((const char *) pExtensionName, extensionNames[i])) {
961                     isSupported = SL_BOOLEAN_TRUE;
962                     break;
963                 }
964             }
965             result = SL_RESULT_SUCCESS;
966         }
967         *pSupported = isSupported;
968     }
969 
970     SL_LEAVE_INTERFACE
971 }
972 
973 
974 static const struct SLEngineItf_ IEngine_Itf = {
975     IEngine_CreateLEDDevice,
976     IEngine_CreateVibraDevice,
977     IEngine_CreateAudioPlayer,
978     IEngine_CreateAudioRecorder,
979     IEngine_CreateMidiPlayer,
980     IEngine_CreateListener,
981     IEngine_Create3DGroup,
982     IEngine_CreateOutputMix,
983     IEngine_CreateMetadataExtractor,
984     IEngine_CreateExtensionObject,
985     IEngine_QueryNumSupportedInterfaces,
986     IEngine_QuerySupportedInterfaces,
987     IEngine_QueryNumSupportedExtensions,
988     IEngine_QuerySupportedExtension,
989     IEngine_IsExtensionSupported
990 };
991 
IEngine_init(void * self)992 void IEngine_init(void *self)
993 {
994     IEngine *thiz = (IEngine *) self;
995     thiz->mItf = &IEngine_Itf;
996     // mLossOfControlGlobal is initialized in slCreateEngine
997 #ifdef USE_SDL
998     thiz->mOutputMix = NULL;
999 #endif
1000     thiz->mInstanceCount = 1; // ourself
1001     thiz->mInstanceMask = 0;
1002     thiz->mChangedMask = 0;
1003     unsigned i;
1004     for (i = 0; i < MAX_INSTANCE; ++i) {
1005         thiz->mInstances[i] = NULL;
1006     }
1007     thiz->mShutdown = SL_BOOLEAN_FALSE;
1008     thiz->mShutdownAck = SL_BOOLEAN_FALSE;
1009 }
1010 
IEngine_deinit(void * self)1011 void IEngine_deinit(void *self)
1012 {
1013 }
1014 
1015 
1016 // OpenMAX AL Engine
1017 
1018 
IEngine_CreateCameraDevice(XAEngineItf self,XAObjectItf * pDevice,XAuint32 deviceID,XAuint32 numInterfaces,const XAInterfaceID * pInterfaceIds,const XAboolean * pInterfaceRequired)1019 static XAresult IEngine_CreateCameraDevice(XAEngineItf self, XAObjectItf *pDevice,
1020         XAuint32 deviceID, XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds,
1021         const XAboolean *pInterfaceRequired)
1022 {
1023     XA_ENTER_INTERFACE
1024 
1025     //IXAEngine *thiz = (IXAEngine *) self;
1026     result = SL_RESULT_FEATURE_UNSUPPORTED;
1027 
1028     XA_LEAVE_INTERFACE
1029 }
1030 
1031 
IEngine_CreateRadioDevice(XAEngineItf self,XAObjectItf * pDevice,XAuint32 numInterfaces,const XAInterfaceID * pInterfaceIds,const XAboolean * pInterfaceRequired)1032 static XAresult IEngine_CreateRadioDevice(XAEngineItf self, XAObjectItf *pDevice,
1033         XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds,
1034         const XAboolean *pInterfaceRequired)
1035 {
1036     XA_ENTER_INTERFACE
1037 
1038     //IXAEngine *thiz = (IXAEngine *) self;
1039     result = SL_RESULT_FEATURE_UNSUPPORTED;
1040 
1041     XA_LEAVE_INTERFACE
1042 }
1043 
1044 
IXAEngine_CreateLEDDevice(XAEngineItf self,XAObjectItf * pDevice,XAuint32 deviceID,XAuint32 numInterfaces,const XAInterfaceID * pInterfaceIds,const XAboolean * pInterfaceRequired)1045 static XAresult IXAEngine_CreateLEDDevice(XAEngineItf self, XAObjectItf *pDevice, XAuint32 deviceID,
1046         XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds,
1047         const XAboolean *pInterfaceRequired)
1048 {
1049     // forward to OpenSL ES
1050     return IEngine_CreateLEDDevice(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf,
1051             (SLObjectItf *) pDevice, deviceID, numInterfaces, (const SLInterfaceID *) pInterfaceIds,
1052             (const SLboolean *) pInterfaceRequired);
1053 }
1054 
1055 
IXAEngine_CreateVibraDevice(XAEngineItf self,XAObjectItf * pDevice,XAuint32 deviceID,XAuint32 numInterfaces,const XAInterfaceID * pInterfaceIds,const XAboolean * pInterfaceRequired)1056 static XAresult IXAEngine_CreateVibraDevice(XAEngineItf self, XAObjectItf *pDevice,
1057         XAuint32 deviceID, XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds,
1058         const XAboolean *pInterfaceRequired)
1059 {
1060     // forward to OpenSL ES
1061     return IEngine_CreateVibraDevice(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf,
1062             (SLObjectItf *) pDevice, deviceID, numInterfaces, (const SLInterfaceID *) pInterfaceIds,
1063             (const SLboolean *) pInterfaceRequired);
1064 }
1065 
1066 
IEngine_CreateMediaPlayer(XAEngineItf self,XAObjectItf * pPlayer,XADataSource * pDataSrc,XADataSource * pBankSrc,XADataSink * pAudioSnk,XADataSink * pImageVideoSnk,XADataSink * pVibra,XADataSink * pLEDArray,XAuint32 numInterfaces,const XAInterfaceID * pInterfaceIds,const XAboolean * pInterfaceRequired)1067 static XAresult IEngine_CreateMediaPlayer(XAEngineItf self, XAObjectItf *pPlayer,
1068         XADataSource *pDataSrc, XADataSource *pBankSrc, XADataSink *pAudioSnk,
1069         XADataSink *pImageVideoSnk, XADataSink *pVibra, XADataSink *pLEDArray,
1070         XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds,
1071         const XAboolean *pInterfaceRequired)
1072 {
1073     XA_ENTER_INTERFACE
1074 
1075     if (NULL == pPlayer) {
1076         result = XA_RESULT_PARAMETER_INVALID;
1077     } else {
1078         *pPlayer = NULL;
1079         unsigned exposedMask;
1080         const ClassTable *pCMediaPlayer_class = objectIDtoClass(XA_OBJECTID_MEDIAPLAYER);
1081         assert(NULL != pCMediaPlayer_class);
1082         result = checkInterfaces(pCMediaPlayer_class, numInterfaces,
1083                 (const SLInterfaceID *) pInterfaceIds, pInterfaceRequired, &exposedMask, NULL);
1084         if (XA_RESULT_SUCCESS == result) {
1085 
1086             // Construct our new MediaPlayer instance
1087             CMediaPlayer *thiz = (CMediaPlayer *) construct(pCMediaPlayer_class, exposedMask,
1088                     &((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf);
1089             if (NULL == thiz) {
1090                 result = XA_RESULT_MEMORY_FAILURE;
1091             } else {
1092 
1093                 do {
1094 
1095                     // Initialize private fields not associated with an interface
1096 
1097                     // Default data source in case of failure in checkDataSource
1098                     thiz->mDataSource.mLocator.mLocatorType = SL_DATALOCATOR_NULL;
1099                     thiz->mDataSource.mFormat.mFormatType = XA_DATAFORMAT_NULL;
1100 
1101                     // Default andio and image sink in case of failure in checkDataSink
1102                     thiz->mAudioSink.mLocator.mLocatorType = XA_DATALOCATOR_NULL;
1103                     thiz->mAudioSink.mFormat.mFormatType = XA_DATAFORMAT_NULL;
1104                     thiz->mImageVideoSink.mLocator.mLocatorType = XA_DATALOCATOR_NULL;
1105                     thiz->mImageVideoSink.mFormat.mFormatType = XA_DATAFORMAT_NULL;
1106 
1107                     // More default values, in case destructor needs to be called early
1108                     thiz->mNumChannels = UNKNOWN_NUMCHANNELS;
1109 
1110                     // (assume calloc or memset 0 during allocation)
1111                     // placement new
1112 #ifdef ANDROID
1113                     // placement new (explicit constructor)
1114                     // FIXME unnecessary once those fields are encapsulated in one class, rather
1115                     //   than a structure
1116                     (void) new (&thiz->mAVPlayer) android::sp<android::GenericPlayer>();
1117                     (void) new (&thiz->mCallbackProtector)
1118                             android::sp<android::CallbackProtector>();
1119 #endif
1120 
1121                     // Check the source and sink parameters against generic constraints
1122 
1123                     result = checkDataSource("pDataSrc", (const SLDataSource *) pDataSrc,
1124                             &thiz->mDataSource, DATALOCATOR_MASK_URI
1125 #ifdef ANDROID
1126                             | DATALOCATOR_MASK_ANDROIDFD
1127                             | DATALOCATOR_MASK_ANDROIDBUFFERQUEUE
1128 #endif
1129                             , DATAFORMAT_MASK_MIME);
1130                     if (XA_RESULT_SUCCESS != result) {
1131                         break;
1132                     }
1133 
1134                     result = checkDataSource("pBankSrc", (const SLDataSource *) pBankSrc,
1135                             &thiz->mBankSource, DATALOCATOR_MASK_NULL | DATALOCATOR_MASK_URI |
1136                             DATALOCATOR_MASK_ADDRESS, DATAFORMAT_MASK_NULL);
1137                     if (XA_RESULT_SUCCESS != result) {
1138                         break;
1139                     }
1140 
1141                     result = checkDataSink("pAudioSnk", (const SLDataSink *) pAudioSnk,
1142                             &thiz->mAudioSink, DATALOCATOR_MASK_OUTPUTMIX, DATAFORMAT_MASK_NULL);
1143                     if (XA_RESULT_SUCCESS != result) {
1144                         break;
1145                     }
1146 
1147                     result = checkDataSink("pImageVideoSnk", (const SLDataSink *) pImageVideoSnk,
1148                             &thiz->mImageVideoSink,
1149                             DATALOCATOR_MASK_NULL | DATALOCATOR_MASK_NATIVEDISPLAY,
1150                             DATAFORMAT_MASK_NULL);
1151                     if (XA_RESULT_SUCCESS != result) {
1152                         break;
1153                     }
1154 
1155                     result = checkDataSink("pVibra", (const SLDataSink *) pVibra, &thiz->mVibraSink,
1156                             DATALOCATOR_MASK_NULL | DATALOCATOR_MASK_IODEVICE,
1157                             DATAFORMAT_MASK_NULL);
1158                     if (XA_RESULT_SUCCESS != result) {
1159                         break;
1160                     }
1161 
1162                     result = checkDataSink("pLEDArray", (const SLDataSink *) pLEDArray,
1163                             &thiz->mLEDArraySink, DATALOCATOR_MASK_NULL | DATALOCATOR_MASK_IODEVICE,
1164                             DATAFORMAT_MASK_NULL);
1165                     if (XA_RESULT_SUCCESS != result) {
1166                         break;
1167                     }
1168 
1169                     // Unsafe to ever refer to application pointers again
1170                     pDataSrc = NULL;
1171                     pBankSrc = NULL;
1172                     pAudioSnk = NULL;
1173                     pImageVideoSnk = NULL;
1174                     pVibra = NULL;
1175                     pLEDArray = NULL;
1176 
1177                     // Check that the requested interfaces are compatible with the data source
1178                     // FIXME implement
1179 
1180                     // check the source and sink parameters against platform support
1181 #ifdef ANDROID
1182                     result = android_Player_checkSourceSink(thiz);
1183                     if (XA_RESULT_SUCCESS != result) {
1184                         break;
1185                     }
1186 #endif
1187 
1188 #ifdef ANDROID
1189                     // AndroidBufferQueue-specific initialization
1190                     if (XA_DATALOCATOR_ANDROIDBUFFERQUEUE ==
1191                             thiz->mDataSource.mLocator.mLocatorType) {
1192                         XAuint16 nbBuffers = (XAuint16) thiz->mDataSource.mLocator.mABQ.numBuffers;
1193 
1194                         // Avoid possible integer overflow during multiplication; this arbitrary
1195                         // maximum is big enough to not interfere with real applications, but
1196                         // small enough to not overflow.
1197                         if (nbBuffers >= 256) {
1198                             result = SL_RESULT_MEMORY_FAILURE;
1199                             break;
1200                         }
1201 
1202                         // initialize ABQ buffer type
1203                         // assert below has been checked in android_audioPlayer_checkSourceSink
1204                         assert(XA_DATAFORMAT_MIME == thiz->mDataSource.mFormat.mFormatType);
1205                         if (XA_CONTAINERTYPE_MPEG_TS ==
1206                                 thiz->mDataSource.mFormat.mMIME.containerType) {
1207                             thiz->mAndroidBufferQueue.mBufferType = kAndroidBufferTypeMpeg2Ts;
1208 
1209                             // Set the container type for the StreamInformation interface
1210                             XAMediaContainerInformation *containerInfo =
1211                                     (XAMediaContainerInformation*)
1212                                         // always storing container info at index 0, as per spec
1213                                         &(thiz->mStreamInfo.mStreamInfoTable.itemAt(0).
1214                                                 containerInfo);
1215                             containerInfo->containerType = XA_CONTAINERTYPE_MPEG_TS;
1216                             // there are no streams at this stage
1217                             containerInfo->numStreams = 0;
1218 
1219                         } else {
1220                             thiz->mAndroidBufferQueue.mBufferType = kAndroidBufferTypeInvalid;
1221                             SL_LOGE("Invalid buffer type in Android Buffer Queue");
1222                             result = SL_RESULT_CONTENT_UNSUPPORTED;
1223                         }
1224 
1225                         // initialize ABQ memory
1226                         thiz->mAndroidBufferQueue.mBufferArray = (AdvancedBufferHeader *)
1227                                     malloc( (nbBuffers + 1) * sizeof(AdvancedBufferHeader));
1228                         if (NULL == thiz->mAndroidBufferQueue.mBufferArray) {
1229                             result = SL_RESULT_MEMORY_FAILURE;
1230                             break;
1231                         } else {
1232                             for (XAuint16 i=0 ; i<(nbBuffers + 1) ; i++) {
1233                                 thiz->mAndroidBufferQueue.mBufferArray[i].mDataBuffer = NULL;
1234                                 thiz->mAndroidBufferQueue.mBufferArray[i].mDataSize = 0;
1235                                 thiz->mAndroidBufferQueue.mBufferArray[i].mDataSizeConsumed = 0;
1236                                 thiz->mAndroidBufferQueue.mBufferArray[i].mBufferContext = NULL;
1237                                 thiz->mAndroidBufferQueue.mBufferArray[i].mBufferState =
1238                                         XA_ANDROIDBUFFERQUEUEEVENT_NONE;
1239                                 switch (thiz->mAndroidBufferQueue.mBufferType) {
1240                                   case kAndroidBufferTypeMpeg2Ts:
1241                                     thiz->mAndroidBufferQueue.mBufferArray[i].mItems.mTsCmdData.
1242                                             mTsCmdCode = ANDROID_MP2TSEVENT_NONE;
1243                                     thiz->mAndroidBufferQueue.mBufferArray[i].mItems.mTsCmdData.
1244                                             mPts = 0;
1245                                     break;
1246                                   default:
1247                                     result = SL_RESULT_CONTENT_UNSUPPORTED;
1248                                     break;
1249                                 }
1250                             }
1251                             thiz->mAndroidBufferQueue.mFront =
1252                                     thiz->mAndroidBufferQueue.mBufferArray;
1253                             thiz->mAndroidBufferQueue.mRear =
1254                                     thiz->mAndroidBufferQueue.mBufferArray;
1255                         }
1256 
1257                         thiz->mAndroidBufferQueue.mNumBuffers = nbBuffers;
1258 
1259                     }
1260 #endif
1261 
1262                     // used to store the data source of our audio player
1263                     thiz->mDynamicSource.mDataSource = &thiz->mDataSource.u.mSource;
1264 
1265                     // platform-specific initialization
1266 #ifdef ANDROID
1267                     android_Player_create(thiz);
1268 #endif
1269 
1270                 } while (0);
1271 
1272                 if (XA_RESULT_SUCCESS != result) {
1273                     IObject_Destroy(&thiz->mObject.mItf);
1274                 } else {
1275                     IObject_Publish(&thiz->mObject);
1276                     // return the new media player object
1277                     *pPlayer = (XAObjectItf) &thiz->mObject.mItf;
1278                 }
1279 
1280             }
1281         }
1282 
1283     }
1284 
1285     XA_LEAVE_INTERFACE
1286 }
1287 
1288 
IEngine_CreateMediaRecorder(XAEngineItf self,XAObjectItf * pRecorder,XADataSource * pAudioSrc,XADataSource * pImageVideoSrc,XADataSink * pDataSnk,XAuint32 numInterfaces,const XAInterfaceID * pInterfaceIds,const XAboolean * pInterfaceRequired)1289 static XAresult IEngine_CreateMediaRecorder(XAEngineItf self, XAObjectItf *pRecorder,
1290         XADataSource *pAudioSrc, XADataSource *pImageVideoSrc,
1291         XADataSink *pDataSnk, XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds,
1292         const XAboolean *pInterfaceRequired)
1293 {
1294     XA_ENTER_INTERFACE
1295 
1296     //IXAEngine *thiz = (IXAEngine *) self;
1297     result = SL_RESULT_FEATURE_UNSUPPORTED;
1298 
1299 #if 0
1300     "pAudioSrc", pAudioSrc,
1301     "pImageVideoSrc", pImageVideoSrc,
1302     "pDataSink", pDataSnk,
1303 #endif
1304 
1305     XA_LEAVE_INTERFACE
1306 }
1307 
1308 
IXAEngine_CreateOutputMix(XAEngineItf self,XAObjectItf * pMix,XAuint32 numInterfaces,const XAInterfaceID * pInterfaceIds,const XAboolean * pInterfaceRequired)1309 static XAresult IXAEngine_CreateOutputMix(XAEngineItf self, XAObjectItf *pMix,
1310         XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds,
1311         const XAboolean *pInterfaceRequired)
1312 {
1313     // forward to OpenSL ES
1314     return IEngine_CreateOutputMix(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf,
1315             (SLObjectItf *) pMix, numInterfaces, (const SLInterfaceID *) pInterfaceIds,
1316             (const SLboolean *) pInterfaceRequired);
1317 }
1318 
1319 
IXAEngine_CreateMetadataExtractor(XAEngineItf self,XAObjectItf * pMetadataExtractor,XADataSource * pDataSource,XAuint32 numInterfaces,const XAInterfaceID * pInterfaceIds,const XAboolean * pInterfaceRequired)1320 static XAresult IXAEngine_CreateMetadataExtractor(XAEngineItf self, XAObjectItf *pMetadataExtractor,
1321             XADataSource *pDataSource, XAuint32 numInterfaces,
1322             const XAInterfaceID *pInterfaceIds, const XAboolean *pInterfaceRequired)
1323 {
1324     // forward to OpenSL ES
1325     return IEngine_CreateMetadataExtractor(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf,
1326             (SLObjectItf *) pMetadataExtractor, (SLDataSource *) pDataSource, numInterfaces,
1327             (const SLInterfaceID *) pInterfaceIds, (const SLboolean *) pInterfaceRequired);
1328 }
1329 
1330 
IXAEngine_CreateExtensionObject(XAEngineItf self,XAObjectItf * pObject,void * pParameters,XAuint32 objectID,XAuint32 numInterfaces,const XAInterfaceID * pInterfaceIds,const XAboolean * pInterfaceRequired)1331 static XAresult IXAEngine_CreateExtensionObject(XAEngineItf self, XAObjectItf *pObject,
1332             void *pParameters, XAuint32 objectID, XAuint32 numInterfaces,
1333             const XAInterfaceID *pInterfaceIds, const XAboolean *pInterfaceRequired)
1334 {
1335     // forward to OpenSL ES
1336     return IEngine_CreateExtensionObject(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf,
1337             (SLObjectItf *) pObject, pParameters, objectID, numInterfaces,
1338             (const SLInterfaceID *) pInterfaceIds, (const SLboolean *) pInterfaceRequired);
1339 }
1340 
1341 
IEngine_GetImplementationInfo(XAEngineItf self,XAuint32 * pMajor,XAuint32 * pMinor,XAuint32 * pStep,const XAchar * pImplementationText)1342 static XAresult IEngine_GetImplementationInfo(XAEngineItf self, XAuint32 *pMajor, XAuint32 *pMinor,
1343         XAuint32 *pStep, /* XAuint32 nImplementationTextSize, */ const XAchar *pImplementationText)
1344 {
1345     XA_ENTER_INTERFACE
1346 
1347     //IXAEngine *thiz = (IXAEngine *) self;
1348     result = SL_RESULT_FEATURE_UNSUPPORTED;
1349 
1350     XA_LEAVE_INTERFACE
1351 }
1352 
1353 
IXAEngine_QuerySupportedProfiles(XAEngineItf self,XAint16 * pProfilesSupported)1354 static XAresult IXAEngine_QuerySupportedProfiles(XAEngineItf self, XAint16 *pProfilesSupported)
1355 {
1356     XA_ENTER_INTERFACE
1357 
1358     if (NULL == pProfilesSupported) {
1359         result = XA_RESULT_PARAMETER_INVALID;
1360     } else {
1361 #if 1
1362         *pProfilesSupported = 0;
1363         // the code below was copied from OpenSL ES and needs to be adapted for OpenMAX AL.
1364 #else
1365         // The generic implementation doesn't implement any of the profiles, they shouldn't be
1366         // declared as supported. Also exclude the fake profiles BASE and OPTIONAL.
1367         *pProfilesSupported = USE_PROFILES &
1368                 (USE_PROFILES_GAME | USE_PROFILES_MUSIC | USE_PROFILES_PHONE);
1369 #endif
1370         result = XA_RESULT_SUCCESS;
1371     }
1372 
1373     XA_LEAVE_INTERFACE
1374 }
1375 
1376 
IXAEngine_QueryNumSupportedInterfaces(XAEngineItf self,XAuint32 objectID,XAuint32 * pNumSupportedInterfaces)1377 static XAresult IXAEngine_QueryNumSupportedInterfaces(XAEngineItf self, XAuint32 objectID,
1378         XAuint32 *pNumSupportedInterfaces)
1379 {
1380     // forward to OpenSL ES
1381     return IEngine_QueryNumSupportedInterfaces(
1382             &((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf, objectID,
1383             pNumSupportedInterfaces);
1384 }
1385 
1386 
IXAEngine_QuerySupportedInterfaces(XAEngineItf self,XAuint32 objectID,XAuint32 index,XAInterfaceID * pInterfaceId)1387 static XAresult IXAEngine_QuerySupportedInterfaces(XAEngineItf self, XAuint32 objectID,
1388         XAuint32 index, XAInterfaceID *pInterfaceId)
1389 {
1390     // forward to OpenSL ES
1391     return IEngine_QuerySupportedInterfaces(
1392             &((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf, objectID, index,
1393             (SLInterfaceID *) pInterfaceId);
1394 }
1395 
1396 
IXAEngine_QueryNumSupportedExtensions(XAEngineItf self,XAuint32 * pNumExtensions)1397 static XAresult IXAEngine_QueryNumSupportedExtensions(XAEngineItf self, XAuint32 *pNumExtensions)
1398 {
1399     // forward to OpenSL ES
1400     return IEngine_QueryNumSupportedExtensions(
1401             &((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf, pNumExtensions);
1402 }
1403 
1404 
IXAEngine_QuerySupportedExtension(XAEngineItf self,XAuint32 index,XAchar * pExtensionName,XAint16 * pNameLength)1405 static XAresult IXAEngine_QuerySupportedExtension(XAEngineItf self, XAuint32 index,
1406         XAchar *pExtensionName, XAint16 *pNameLength)
1407 {
1408     // forward to OpenSL ES
1409     return IEngine_QuerySupportedExtension(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf,
1410             index, pExtensionName, (SLint16 *) pNameLength);
1411 }
1412 
1413 
IXAEngine_IsExtensionSupported(XAEngineItf self,const XAchar * pExtensionName,XAboolean * pSupported)1414 static XAresult IXAEngine_IsExtensionSupported(XAEngineItf self, const XAchar *pExtensionName,
1415         XAboolean *pSupported)
1416 {
1417     // forward to OpenSL ES
1418     return IEngine_IsExtensionSupported(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf,
1419             pExtensionName, pSupported);
1420 }
1421 
1422 
IXAEngine_QueryLEDCapabilities(XAEngineItf self,XAuint32 * pIndex,XAuint32 * pLEDDeviceID,XALEDDescriptor * pDescriptor)1423 static XAresult IXAEngine_QueryLEDCapabilities(XAEngineItf self, XAuint32 *pIndex,
1424         XAuint32 *pLEDDeviceID, XALEDDescriptor *pDescriptor)
1425 {
1426     // forward to OpenSL ES EngineCapabilities
1427     return (XAresult) IEngineCapabilities_QueryLEDCapabilities(
1428             &((CEngine *) ((IXAEngine *) self)->mThis)->mEngineCapabilities.mItf, pIndex,
1429             pLEDDeviceID, (SLLEDDescriptor *) pDescriptor);
1430 }
1431 
1432 
IXAEngine_QueryVibraCapabilities(XAEngineItf self,XAuint32 * pIndex,XAuint32 * pVibraDeviceID,XAVibraDescriptor * pDescriptor)1433 static XAresult IXAEngine_QueryVibraCapabilities(XAEngineItf self, XAuint32 *pIndex,
1434         XAuint32 *pVibraDeviceID, XAVibraDescriptor *pDescriptor)
1435 {
1436     // forward to OpenSL ES EngineCapabilities
1437     return (XAresult) IEngineCapabilities_QueryVibraCapabilities(
1438             &((CEngine *) ((IXAEngine *) self)->mThis)->mEngineCapabilities.mItf, pIndex,
1439             pVibraDeviceID, (SLVibraDescriptor *) pDescriptor);
1440 }
1441 
1442 
1443 // OpenMAX AL engine v-table
1444 
1445 static const struct XAEngineItf_ IXAEngine_Itf = {
1446     IEngine_CreateCameraDevice,
1447     IEngine_CreateRadioDevice,
1448     IXAEngine_CreateLEDDevice,
1449     IXAEngine_CreateVibraDevice,
1450     IEngine_CreateMediaPlayer,
1451     IEngine_CreateMediaRecorder,
1452     IXAEngine_CreateOutputMix,
1453     IXAEngine_CreateMetadataExtractor,
1454     IXAEngine_CreateExtensionObject,
1455     IEngine_GetImplementationInfo,
1456     IXAEngine_QuerySupportedProfiles,
1457     IXAEngine_QueryNumSupportedInterfaces,
1458     IXAEngine_QuerySupportedInterfaces,
1459     IXAEngine_QueryNumSupportedExtensions,
1460     IXAEngine_QuerySupportedExtension,
1461     IXAEngine_IsExtensionSupported,
1462     IXAEngine_QueryLEDCapabilities,
1463     IXAEngine_QueryVibraCapabilities
1464 };
1465 
1466 
IXAEngine_init(void * self)1467 void IXAEngine_init(void *self)
1468 {
1469     IXAEngine *thiz = (IXAEngine *) self;
1470     thiz->mItf = &IXAEngine_Itf;
1471 }
1472 
1473 
IXAEngine_deinit(void * self)1474 void IXAEngine_deinit(void *self)
1475 {
1476 }
1477