AudioPlayer_to_android.cpp revision 6fff2c605cdc46a10037e011d8fb47702ae70c37
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 18#include "sles_to_android.h" 19#include "math.h" 20 21 22//----------------------------------------------------------------------------- 23inline uint32_t sles_to_android_sampleRate(SLuint32 sampleRateMilliHertz) { 24 return (uint32_t)(sampleRateMilliHertz / 1000); 25} 26 27inline int sles_to_android_sampleFormat(SLuint32 pcmFormat) { 28 switch (pcmFormat) { 29 case SL_PCMSAMPLEFORMAT_FIXED_16: 30 return android::AudioSystem::PCM_16_BIT; 31 break; 32 case SL_PCMSAMPLEFORMAT_FIXED_8: 33 return android::AudioSystem::PCM_8_BIT; 34 break; 35 case SL_PCMSAMPLEFORMAT_FIXED_20: 36 case SL_PCMSAMPLEFORMAT_FIXED_24: 37 case SL_PCMSAMPLEFORMAT_FIXED_28: 38 case SL_PCMSAMPLEFORMAT_FIXED_32: 39 default: 40 return android::AudioSystem::INVALID_FORMAT; 41 } 42} 43 44 45inline int sles_to_android_channelMask(SLuint32 nbChannels, SLuint32 channelMask) { 46 // FIXME handle channel mask mapping between SL ES and Android 47 return (nbChannels == 1 ? 48 android::AudioSystem::CHANNEL_OUT_MONO : 49 android::AudioSystem::CHANNEL_OUT_STEREO); 50} 51 52 53int android_getMinFrameCount(uint32_t sampleRate) { 54 int afSampleRate; 55 if (android::AudioSystem::getOutputSamplingRate(&afSampleRate, 56 ANDROID_DEFAULT_OUTPUT_STREAM_TYPE) != android::NO_ERROR) { 57 return ANDROID_DEFAULT_AUDIOTRACK_BUFFER_SIZE; 58 } 59 int afFrameCount; 60 if (android::AudioSystem::getOutputFrameCount(&afFrameCount, 61 ANDROID_DEFAULT_OUTPUT_STREAM_TYPE) != android::NO_ERROR) { 62 return ANDROID_DEFAULT_AUDIOTRACK_BUFFER_SIZE; 63 } 64 uint32_t afLatency; 65 if (android::AudioSystem::getOutputLatency(&afLatency, 66 ANDROID_DEFAULT_OUTPUT_STREAM_TYPE) != android::NO_ERROR) { 67 return ANDROID_DEFAULT_AUDIOTRACK_BUFFER_SIZE; 68 } 69 // minimum nb of buffers to cover output latency, given the size of each hardware audio buffer 70 uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate); 71 if (minBufCount < 2) minBufCount = 2; 72 // minimum number of frames to cover output latency at the sample rate of the content 73 return (afFrameCount*sampleRate*minBufCount)/afSampleRate; 74} 75 76 77void android_audioPlayerUpdateStereoVolume(IVolume *pVolItf) { 78 // should not be used when muted 79 if (pVolItf->mMute) { 80 return; 81 } 82 float leftVol = 1.0f, rightVol = 1.0f; 83 84 //int muteSoloLeft, muteSoleRight; 85 CAudioPlayer *ap = (CAudioPlayer *)pVolItf->mThis; 86 //muteSoloLeft = (mChannelMutes & CHANNEL_OUT_FRONT_LEFT) >> 2; 87 //muteSoloRight = (mChannelMutes & CHANNEL_OUT_FRONT_RIGHT) >> 3; 88 89 // compute amplification as the combination of volume level and stereo position 90 91 // amplification from volume level 92 // FIXME use the FX Framework conversions 93 pVolItf->mAmplFromVolLevel = pow(10, (float)pVolItf->mLevel/2000); 94 leftVol *= pVolItf->mAmplFromVolLevel; 95 rightVol *= pVolItf->mAmplFromVolLevel; 96 97 switch(ap->mAndroidObjType) { 98 case AUDIOTRACK_PUSH: 99 case AUDIOTRACK_PULL: 100 // amplification from stereo position 101 if (pVolItf->mEnableStereoPosition) { 102 // panning law depends on number of channels of content: stereo panning vs 2ch. balance 103 if(ap->mAudioTrack->channelCount() == 1) { 104 // stereo panning 105 double theta = (1000+pVolItf->mStereoPosition)*M_PI_4/1000.0f; // 0 <= theta <= Pi/2 106 pVolItf->mAmplFromStereoPos[0] = cos(theta); 107 pVolItf->mAmplFromStereoPos[1] = sin(theta); 108 } else { 109 // stereo balance 110 if (pVolItf->mStereoPosition > 0) { 111 pVolItf->mAmplFromStereoPos[0] = (1000-pVolItf->mStereoPosition)/1000.0f; 112 pVolItf->mAmplFromStereoPos[1] = 1.0f; 113 } else { 114 pVolItf->mAmplFromStereoPos[0] = 1.0f; 115 pVolItf->mAmplFromStereoPos[1] = (1000+pVolItf->mStereoPosition)/1000.0f; 116 } 117 } 118 leftVol *= pVolItf->mAmplFromStereoPos[0]; 119 rightVol *= pVolItf->mAmplFromStereoPos[1]; 120 } 121 ap->mAudioTrack->setVolume(leftVol, rightVol); 122 break; 123 case MEDIAPLAYER: 124 ap->mMediaPlayer->setVolume(leftVol, rightVol); 125 break; 126 default: 127 break; 128 } 129} 130 131 132//----------------------------------------------------------------------------- 133SLresult sles_to_android_checkAudioPlayerSourceSink(const SLDataSource *pAudioSrc, 134 const SLDataSink *pAudioSnk) 135{ 136 //-------------------------------------- 137 // Sink check: 138 // currently only OutputMix sinks are supported, regardless of the data source 139 if (*(SLuint32 *)pAudioSnk->pLocator != SL_DATALOCATOR_OUTPUTMIX) { 140 fprintf(stderr, "Cannot create audio player: data sink is not SL_DATALOCATOR_OUTPUTMIX\n"); 141 return SL_RESULT_PARAMETER_INVALID; 142 } 143 // FIXME verify output mix is in realized state 144 fprintf(stderr, "FIXME verify OutputMix is in Realized state\n"); 145 146 //-------------------------------------- 147 // Source check: 148 SLuint32 locatorType = *(SLuint32 *)pAudioSrc->pLocator; 149 SLuint32 formatType = *(SLuint32 *)pAudioSrc->pFormat; 150 SLuint32 numBuffers = 0; 151 switch (locatorType) { 152 //------------------ 153 // Buffer Queues 154 case SL_DATALOCATOR_BUFFERQUEUE: { 155 SLDataLocator_BufferQueue *dl_bq = (SLDataLocator_BufferQueue *) pAudioSrc->pLocator; 156 numBuffers = dl_bq->numBuffers; 157 if (0 == numBuffers) { 158 fprintf(stderr, "Cannot create audio player: data source buffer queue has "); 159 fprintf(stderr, "a depth of 0"); 160 return SL_RESULT_PARAMETER_INVALID; 161 } 162 // Buffer format 163 switch (formatType) { 164 // currently only PCM buffer queues are supported, 165 case SL_DATAFORMAT_PCM: { 166 SLDataFormat_PCM *df_pcm = (SLDataFormat_PCM *) pAudioSrc->pFormat; 167 switch (df_pcm->numChannels) { 168 case 1: 169 case 2: 170 break; 171 default: 172 fprintf(stderr, "Cannot create audio player: implementation doesn't "); 173 fprintf(stderr, "support buffers with more than 2 channels"); 174 return SL_RESULT_CONTENT_UNSUPPORTED; 175 } 176 switch (df_pcm->samplesPerSec) { 177 case SL_SAMPLINGRATE_8: 178 case SL_SAMPLINGRATE_11_025: 179 case SL_SAMPLINGRATE_12: 180 case SL_SAMPLINGRATE_16: 181 case SL_SAMPLINGRATE_22_05: 182 case SL_SAMPLINGRATE_24: 183 case SL_SAMPLINGRATE_32: 184 case SL_SAMPLINGRATE_44_1: 185 break; 186 // others 187 default: 188 fprintf(stderr, "Cannot create audio player: unsupported sample rate"); 189 return SL_RESULT_CONTENT_UNSUPPORTED; 190 } 191 switch (df_pcm->bitsPerSample) { 192 case SL_PCMSAMPLEFORMAT_FIXED_8: 193 case SL_PCMSAMPLEFORMAT_FIXED_16: 194 break; 195 // others 196 default: 197 fprintf(stderr, "Cannot create audio player: unsupported sample format %lu", 198 (SLuint32)df_pcm->bitsPerSample); 199 return SL_RESULT_CONTENT_UNSUPPORTED; 200 } 201 switch (df_pcm->containerSize) { 202 case 16: 203 break; 204 // others 205 default: 206 //FIXME add error message 207 return SL_RESULT_CONTENT_UNSUPPORTED; 208 } 209 switch (df_pcm->channelMask) { 210 // FIXME needs work 211 default: 212 break; 213 } 214 switch (df_pcm->endianness) { 215 case SL_BYTEORDER_LITTLEENDIAN: 216 break; 217 // others esp. big and native (new not in spec) 218 default: 219 //FIXME add error message 220 return SL_RESULT_CONTENT_UNSUPPORTED; 221 } 222 } //case SL_DATAFORMAT_PCM 223 break; 224 case SL_DATAFORMAT_MIME: 225 case SL_DATAFORMAT_RESERVED3: 226 fprintf(stderr, "Error: cannot create Audio Player with SL_DATALOCATOR_BUFFERQUEUE data source without SL_DATAFORMAT_PCM format\n"); 227 return SL_RESULT_CONTENT_UNSUPPORTED; 228 default: 229 fprintf(stderr, "Error: cannot create Audio Player with SL_DATALOCATOR_BUFFERQUEUE data source without SL_DATAFORMAT_PCM format\n"); 230 return SL_RESULT_PARAMETER_INVALID; 231 } // switch (formatType) 232 } // case SL_DATALOCATOR_BUFFERQUEUE 233 break; 234 //------------------ 235 // URI 236 case SL_DATALOCATOR_URI: 237 { 238 SLDataLocator_URI *dl_uri = (SLDataLocator_URI *) pAudioSrc->pLocator; 239 if (NULL == dl_uri->URI) { 240 return SL_RESULT_PARAMETER_INVALID; 241 } 242 // URI format 243 switch (formatType) { 244 case SL_DATAFORMAT_MIME: 245 break; 246 case SL_DATAFORMAT_PCM: 247 case SL_DATAFORMAT_RESERVED3: 248 fprintf(stderr, "Error: cannot create Audio Player with SL_DATALOCATOR_URI data source without SL_DATAFORMAT_MIME format\n"); 249 return SL_RESULT_CONTENT_UNSUPPORTED; 250 } // switch (formatType) 251 } // case SL_DATALOCATOR_URI 252 break; 253 //------------------ 254 // Address 255 case SL_DATALOCATOR_ADDRESS: 256 case SL_DATALOCATOR_IODEVICE: 257 case SL_DATALOCATOR_OUTPUTMIX: 258 case SL_DATALOCATOR_RESERVED5: 259 case SL_DATALOCATOR_MIDIBUFFERQUEUE: 260 case SL_DATALOCATOR_RESERVED8: 261 return SL_RESULT_CONTENT_UNSUPPORTED; 262 default: 263 return SL_RESULT_PARAMETER_INVALID; 264 }// switch (locatorType) 265 266 return SL_RESULT_SUCCESS; 267} 268 269 270//----------------------------------------------------------------------------- 271// Callback associated with an AudioTrack of an SL ES AudioPlayer that gets its data 272// from a buffer queue. 273static void android_pullAudioTrackCallback(int event, void* user, void *info) { 274 CAudioPlayer *pAudioPlayer = (CAudioPlayer *)user; 275 switch(event) { 276 277 case (android::AudioTrack::EVENT_MORE_DATA) : { 278 //fprintf(stdout, "received event EVENT_MORE_DATA from AudioTrack\n"); 279 android::AudioTrack::Buffer* pBuff = (android::AudioTrack::Buffer*)info; 280 // retrieve data from the buffer queue 281 // FIXME locks: issue of callbacks calling callbacks without reentrant locks 282 //interface_lock_exclusive(&pAudioPlayer->mBufferQueue); 283 if (pAudioPlayer->mBufferQueue.mState.count != 0) { 284 //fprintf(stderr, "nbBuffers in queue = %lu\n",pAudioPlayer->mBufferQueue.mState.count); 285 assert(pAudioPlayer->mBufferQueue.mFront != pAudioPlayer->mBufferQueue.mRear); 286 287 struct BufferHeader *oldFront = pAudioPlayer->mBufferQueue.mFront; 288 struct BufferHeader *newFront = &oldFront[1]; 289 290 // FIXME handle 8bit based on buffer format 291 short *pSrc = (short*)((char *)oldFront->mBuffer 292 + pAudioPlayer->mBufferQueue.mSizeConsumed); 293 if (pAudioPlayer->mBufferQueue.mSizeConsumed + pBuff->size < oldFront->mSize) { 294 // can't consume the whole or rest of the buffer in one shot 295 pAudioPlayer->mBufferQueue.mSizeConsumed += pBuff->size; 296 // leave pBuff->size untouched 297 // consume data 298 memcpy (pBuff->i16, pSrc, pBuff->size); 299 } else { 300 // finish consuming the buffer or consume the buffer in one shot 301 pBuff->size = oldFront->mSize - pAudioPlayer->mBufferQueue.mSizeConsumed; 302 pAudioPlayer->mBufferQueue.mSizeConsumed = 0; 303 304 if (newFront == 305 &pAudioPlayer->mBufferQueue.mArray[pAudioPlayer->mBufferQueue.mNumBuffers]) 306 { 307 newFront = pAudioPlayer->mBufferQueue.mArray; 308 } 309 pAudioPlayer->mBufferQueue.mFront = newFront; 310 311 pAudioPlayer->mBufferQueue.mState.count--; 312 pAudioPlayer->mBufferQueue.mState.playIndex++; 313 314 // consume data 315 memcpy (pBuff->i16, pSrc, pBuff->size); 316 317 // data has been consumed, and the buffer queue state has been updated 318 // we can notify the client if applicable 319 slBufferQueueCallback callback = pAudioPlayer->mBufferQueue.mCallback; 320 if (NULL != callback) { 321 (*callback)(&pAudioPlayer->mBufferQueue.mItf, 322 pAudioPlayer->mBufferQueue.mContext); 323 } 324 } 325 } else { 326 // no data available 327 pBuff->size = 0; 328 } 329 // FIXME locks: issue of callbacks calling callbacks without reentrant locks 330 //interface_unlock_exclusive(&pAudioPlayer->mBufferQueue); 331 } 332 break; 333 334 case (android::AudioTrack::EVENT_MARKER) : { 335 //fprintf(stdout, "received event EVENT_MARKER from AudioTrack\n"); 336 // FIXME locks: issue of callbacks calling callbacks without reentrant locks 337 slPlayCallback callback = pAudioPlayer->mPlay.mCallback; 338 if (NULL != callback) { 339 // getting this event implies SL_PLAYEVENT_HEADATMARKER was set in the event mask 340 (*callback)(&pAudioPlayer->mPlay.mItf, pAudioPlayer->mPlay.mContext, 341 SL_PLAYEVENT_HEADATMARKER); 342 } 343 // FIXME locks: issue of callbacks calling callbacks without reentrant locks 344 } 345 break; 346 347 case (android::AudioTrack::EVENT_NEW_POS) : { 348 //fprintf(stdout, "received event EVENT_NEW_POS from AudioTrack\n"); 349 // FIXME locks: issue of callbacks calling callbacks without reentrant locks 350 slPlayCallback callback = pAudioPlayer->mPlay.mCallback; 351 if (NULL != callback) { 352 // getting this event implies SL_PLAYEVENT_HEADATNEWPOS was set in the event mask 353 (*callback)(&pAudioPlayer->mPlay.mItf, pAudioPlayer->mPlay.mContext, 354 SL_PLAYEVENT_HEADATNEWPOS); 355 } 356 // FIXME locks: issue of callbacks calling callbacks without reentrant locks 357 } 358 break; 359 360 case (android::AudioTrack::EVENT_UNDERRUN) : { 361 // FIXME locks: issue of callbacks calling callbacks without reentrant locks 362 slPlayCallback callback = pAudioPlayer->mPlay.mCallback; 363 if ((NULL != callback) && (pAudioPlayer->mPlay.mEventFlags & SL_PLAYEVENT_HEADSTALLED)) { 364 (*callback)(&pAudioPlayer->mPlay.mItf, pAudioPlayer->mPlay.mContext, 365 SL_PLAYEVENT_HEADSTALLED); 366 } 367 // FIXME locks: issue of callbacks calling callbacks without reentrant locks 368 } 369 break; 370 371 default: 372 // FIXME where does the notification of SL_PLAYEVENT_HEADATEND, SL_PLAYEVENT_HEADMOVING fit? 373 break; 374 } 375} 376 377 378//----------------------------------------------------------------------------- 379static void android_pushAudioTrackCallback(int event, void* user, void *info) { 380 if (event == android::AudioTrack::EVENT_MORE_DATA) { 381 fprintf(stderr, "received event EVENT_MORE_DATA from AudioTrack\n"); 382 // set size to 0 to signal we're not using the callback to write more data 383 android::AudioTrack::Buffer* pBuff = (android::AudioTrack::Buffer*)info; 384 pBuff->size = 0; 385 386 } else if (event == android::AudioTrack::EVENT_MARKER) { 387 fprintf(stderr, "received event EVENT_MARKER from AudioTrack\n"); 388 } else if (event == android::AudioTrack::EVENT_NEW_POS) { 389 fprintf(stderr, "received event EVENT_NEW_POS from AudioTrack\n"); 390 } 391} 392 393 394//----------------------------------------------------------------------------- 395SLresult sles_to_android_audioPlayerCreate(const SLDataSource *pAudioSrc, 396 const SLDataSink *pAudioSnk, 397 CAudioPlayer *pAudioPlayer) { 398 399 SLresult result = SL_RESULT_SUCCESS; 400 401 //-------------------------------------- 402 // Output check: 403 // currently only OutputMix sinks are supported 404 // this has been verified in sles_to_android_CheckAudioPlayerSourceSink 405 406 //-------------------------------------- 407 // Source check: 408 SLuint32 locatorType = *(SLuint32 *)pAudioSrc->pLocator; 409 switch (locatorType) { 410 // ----------------------------------- 411 // Buffer Queue to AudioTrack 412 case SL_DATALOCATOR_BUFFERQUEUE: 413 pAudioPlayer->mAndroidObjType = AUDIOTRACK_PULL; 414 break; 415 // ----------------------------------- 416 // URI to MediaPlayer 417 case SL_DATALOCATOR_URI: { 418 pAudioPlayer->mAndroidObjType = MEDIAPLAYER; 419 // save URI 420 SLDataLocator_URI *dl_uri = (SLDataLocator_URI *) pAudioSrc->pLocator; 421 pAudioPlayer->mUri = (char*) malloc(1 + sizeof(SLchar)*strlen((char*)dl_uri->URI)); 422 strcpy(pAudioPlayer->mUri, (char*)dl_uri->URI); 423 } 424 break; 425 default: 426 pAudioPlayer->mAndroidObjType = INVALID_TYPE; 427 result = SL_RESULT_PARAMETER_INVALID; 428 } 429 430 return result; 431 432} 433 434 435//----------------------------------------------------------------------------- 436SLresult sles_to_android_audioPlayerRealize(CAudioPlayer *pAudioPlayer, SLboolean async) { 437 438 SLresult result = SL_RESULT_SUCCESS; 439 //fprintf(stderr, "entering sles_to_android_audioPlayerRealize\n"); 440 switch (pAudioPlayer->mAndroidObjType) { 441 //----------------------------------- 442 // AudioTrack 443 case AUDIOTRACK_PUSH: 444 case AUDIOTRACK_PULL: 445 { 446 SLDataLocator_BufferQueue *dl_bq = (SLDataLocator_BufferQueue *) 447 pAudioPlayer->mDynamicSource.mDataSource; 448 SLDataFormat_PCM *df_pcm = (SLDataFormat_PCM *) 449 pAudioPlayer->mDynamicSource.mDataSource->pFormat; 450 451 uint32_t sampleRate = sles_to_android_sampleRate(df_pcm->samplesPerSec); 452 453 pAudioPlayer->mAudioTrack = new android::AudioTrack( 454 ANDROID_DEFAULT_OUTPUT_STREAM_TYPE, // streamType 455 sampleRate, // sampleRate 456 sles_to_android_sampleFormat(df_pcm->bitsPerSample), // format 457 sles_to_android_channelMask(df_pcm->numChannels, df_pcm->channelMask),//channel mask 458 0, // frameCount (here min) 459 0, // flags 460 android_pullAudioTrackCallback, // callback 461 (void *) pAudioPlayer, // user 462 0); // FIXME find appropriate frame count // notificationFrame 463 } 464 if (pAudioPlayer->mAudioTrack->initCheck() != android::NO_ERROR) { 465 result = SL_RESULT_CONTENT_UNSUPPORTED; 466 } 467 break; 468 //----------------------------------- 469 // MediaPlayer 470 case MEDIAPLAYER: { 471 pAudioPlayer->mMediaPlayer = new android::MediaPlayer(); 472 if (pAudioPlayer->mMediaPlayer == NULL) { 473 result = SL_RESULT_MEMORY_FAILURE; 474 break; 475 } 476 pAudioPlayer->mMediaPlayer->setAudioStreamType(ANDROID_DEFAULT_OUTPUT_STREAM_TYPE); 477 if (pAudioPlayer->mMediaPlayer->setDataSource(android::String8(pAudioPlayer->mUri), NULL) 478 != android::NO_ERROR) { 479 result = SL_RESULT_CONTENT_UNSUPPORTED; 480 break; 481 } 482 483 // FIXME move the call to MediaPlayer::prepare() to the start of the prefetching 484 // i.e. in SL ES: when setting the play state of the AudioPlayer to Paused. 485 if (async == SL_BOOLEAN_FALSE) { 486 if (pAudioPlayer->mMediaPlayer->prepare() != android::NO_ERROR) { 487 fprintf(stderr, "Failed to prepare() MediaPlayer in synchronous mode for %s\n", 488 pAudioPlayer->mUri); 489 result = SL_RESULT_CONTENT_UNSUPPORTED; 490 } 491 } else { 492 // FIXME verify whether async prepare will be handled by SL ES framework or 493 // Android-specific code (and rely on MediaPlayer::prepareAsync() ) 494 fprintf(stderr, "FIXME implement async realize for a MediaPlayer\n"); 495 } 496 } 497 break; 498 default: 499 result = SL_RESULT_CONTENT_UNSUPPORTED; 500 } 501 502 return result; 503} 504 505 506//----------------------------------------------------------------------------- 507SLresult sles_to_android_audioPlayerDestroy(CAudioPlayer *pAudioPlayer) { 508 SLresult result = SL_RESULT_SUCCESS; 509 //fprintf(stdout, "sles_to_android_audioPlayerDestroy\n"); 510 switch (pAudioPlayer->mAndroidObjType) { 511 //----------------------------------- 512 // AudioTrack 513 case AUDIOTRACK_PUSH: 514 case AUDIOTRACK_PULL: 515 pAudioPlayer->mAudioTrack->stop(); 516 delete pAudioPlayer->mAudioTrack; 517 pAudioPlayer->mAudioTrack = NULL; 518 pAudioPlayer->mAndroidObjType = INVALID_TYPE; 519 break; 520 //----------------------------------- 521 // MediaPlayer 522 case MEDIAPLAYER: 523 // FIXME destroy MediaPlayer 524 if (pAudioPlayer->mMediaPlayer != NULL) { 525 pAudioPlayer->mMediaPlayer->stop(); 526 pAudioPlayer->mMediaPlayer->setListener(0); 527 pAudioPlayer->mMediaPlayer->disconnect(); 528 fprintf(stderr, "FIXME destroy MediaPlayer\n"); 529 //delete pAudioPlayer->mMediaPlayer; 530 pAudioPlayer->mMediaPlayer = NULL; 531 free(pAudioPlayer->mUri); 532 } 533 break; 534 default: 535 result = SL_RESULT_CONTENT_UNSUPPORTED; 536 } 537 538 return result; 539} 540 541 542//----------------------------------------------------------------------------- 543SLresult sles_to_android_audioPlayerSetPlayState(IPlay *pPlayItf, SLuint32 state) { 544 CAudioPlayer *ap = (CAudioPlayer *)pPlayItf->mThis; 545 switch(ap->mAndroidObjType) { 546 case AUDIOTRACK_PUSH: 547 case AUDIOTRACK_PULL: 548 switch (state) { 549 case SL_PLAYSTATE_STOPPED: 550 fprintf(stdout, "setting AudioPlayer to SL_PLAYSTATE_STOPPED\n"); 551 ap->mAudioTrack->stop(); 552 break; 553 case SL_PLAYSTATE_PAUSED: 554 fprintf(stdout, "setting AudioPlayer to SL_PLAYSTATE_PAUSED\n"); 555 ap->mAudioTrack->pause(); 556 break; 557 case SL_PLAYSTATE_PLAYING: 558 fprintf(stdout, "setting AudioPlayer to SL_PLAYSTATE_PLAYING\n"); 559 ap->mAudioTrack->start(); 560 break; 561 default: 562 return SL_RESULT_PARAMETER_INVALID; 563 } 564 break; 565 case MEDIAPLAYER: 566 switch (state) { 567 case SL_PLAYSTATE_STOPPED: 568 fprintf(stdout, "setting AudioPlayer to SL_PLAYSTATE_STOPPED\n"); 569 ap->mMediaPlayer->stop(); 570 break; 571 case SL_PLAYSTATE_PAUSED: 572 fprintf(stdout, "setting AudioPlayer to SL_PLAYSTATE_PAUSED\n"); 573 //FIXME implement start of prefetching when transitioning from stopped to paused 574 ap->mMediaPlayer->pause(); 575 break; 576 case SL_PLAYSTATE_PLAYING: 577 fprintf(stdout, "setting AudioPlayer to SL_PLAYSTATE_PLAYING\n"); 578 ap->mMediaPlayer->start(); 579 break; 580 default: 581 return SL_RESULT_PARAMETER_INVALID; 582 } 583 break; 584 default: 585 break; 586 } 587 return SL_RESULT_SUCCESS; 588} 589 590 591//----------------------------------------------------------------------------- 592SLresult sles_to_android_audioPlayerUseEventMask(IPlay *pPlayItf, SLuint32 eventFlags) { 593 CAudioPlayer *ap = (CAudioPlayer *)pPlayItf->mThis; 594 switch(ap->mAndroidObjType) { 595 case AUDIOTRACK_PUSH: 596 case AUDIOTRACK_PULL: 597 if (eventFlags & SL_PLAYEVENT_HEADATMARKER) { 598 ap->mAudioTrack->setMarkerPosition( (uint32_t)((pPlayItf->mMarkerPosition 599 * ap->mAudioTrack->getSampleRate())/1000)); 600 } else { 601 // clear marker 602 ap->mAudioTrack->setMarkerPosition(0); 603 } 604 if (eventFlags & SL_PLAYEVENT_HEADATNEWPOS) { 605 ap->mAudioTrack->setPositionUpdatePeriod( (uint32_t)((pPlayItf->mPositionUpdatePeriod 606 * ap->mAudioTrack->getSampleRate())/1000)); 607 } else { 608 // clear periodic update 609 ap->mAudioTrack->setPositionUpdatePeriod(0); 610 } 611 if (eventFlags & SL_PLAYEVENT_HEADATEND) { 612 // FIXME support SL_PLAYEVENT_HEADATEND 613 fprintf(stderr, "FIXME: IPlay_SetCallbackEventsMask(SL_PLAYEVENT_HEADATEND) on an SL_OBJECTID_AUDIOPLAYER to be implemented\n"); 614 } 615 if (eventFlags & SL_PLAYEVENT_HEADMOVING) { 616 // FIXME support SL_PLAYEVENT_HEADMOVING 617 fprintf(stderr, "FIXME: IPlay_SetCallbackEventsMask(SL_PLAYEVENT_HEADMOVING) on an SL_OBJECTID_AUDIOPLAYER to be implemented\n"); 618 } 619 if (eventFlags & SL_PLAYEVENT_HEADSTALLED) { 620 // FIXME support SL_PLAYEVENT_HEADSTALLED 621 fprintf(stderr, "FIXME: IPlay_SetCallbackEventsMask(SL_PLAYEVENT_HEADSTALLED) on an SL_OBJECTID_AUDIOPLAYER to be implemented\n"); 622 } 623 break; 624 case MEDIAPLAYER: 625 //FIXME implement 626 fprintf(stderr, "FIXME: IPlay_SetCallbackEventsMask() mapped to a MediaPlayer to be implemented\n"); 627 break; 628 default: 629 break; 630 } 631 return SL_RESULT_SUCCESS; 632 633} 634 635 636//----------------------------------------------------------------------------- 637SLresult sles_to_android_audioPlayerGetPosition(IPlay *pPlayItf, SLmillisecond *pPosMsec) { 638 CAudioPlayer *ap = (CAudioPlayer *)pPlayItf->mThis; 639 switch(ap->mAndroidObjType) { 640 case AUDIOTRACK_PUSH: 641 case AUDIOTRACK_PULL: 642 uint32_t positionInFrames; 643 ap->mAudioTrack->getPosition(&positionInFrames); 644 *pPosMsec = positionInFrames * 1000 / ap->mAudioTrack->getSampleRate(); 645 break; 646 case MEDIAPLAYER: 647 //FIXME implement 648 fprintf(stderr, "FIXME: sles_to_android_audioPlayerGetPosition() mapped to a MediaPlayer to be implemented\n"); 649 break; 650 default: 651 break; 652 } 653 return SL_RESULT_SUCCESS; 654} 655 656//----------------------------------------------------------------------------- 657SLresult sles_to_android_audioPlayerVolumeUpdate(IVolume *pVolItf) { 658 CAudioPlayer *ap = (CAudioPlayer *)pVolItf->mThis; 659 // FIXME use the FX Framework conversions 660 android_audioPlayerUpdateStereoVolume(pVolItf); 661 return SL_RESULT_SUCCESS; 662} 663 664 665//----------------------------------------------------------------------------- 666SLresult sles_to_android_audioPlayerSetMute(IVolume *pVolItf, SLboolean mute) { 667 CAudioPlayer *ap = (CAudioPlayer *)pVolItf->mThis; 668 switch(ap->mAndroidObjType) { 669 case AUDIOTRACK_PUSH: 670 case AUDIOTRACK_PULL: 671 // when unmuting: volume levels have already been updated in IVolume_SetMute 672 ap->mAudioTrack->mute(mute == SL_BOOLEAN_TRUE); 673 break; 674 case MEDIAPLAYER: 675 if (mute == SL_BOOLEAN_TRUE) { 676 ap->mMediaPlayer->setVolume(0.0f, 0.0f); 677 } 678 // when unmuting: volume levels have already been updated in IVolume_SetMute which causes 679 // the MediaPlayer to receive non 0 amplification values 680 break; 681 default: 682 break; 683 } 684 return SL_RESULT_SUCCESS; 685} 686 687 688