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