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