12b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi/*
22b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi * Copyright (C) 2011 The Android Open Source Project
32b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi *
42b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License");
52b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi * you may not use this file except in compliance with the License.
62b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi * You may obtain a copy of the License at
72b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi *
82b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi *      http://www.apache.org/licenses/LICENSE-2.0
92b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi *
102b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi * Unless required by applicable law or agreed to in writing, software
112b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS,
122b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi * See the License for the specific language governing permissions and
142b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi * limitations under the License.
152b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi */
162b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
172b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi#include <stdlib.h>
182b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi#include <stdio.h>
192b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi#include <unistd.h>
202b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi//#include <sys/time.h>
212b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
22c6853892c94800e72c0bd676d5d2136d48cea76eGlenn Kasten#include <SLES/OpenSLES.h>
232b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
242b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
252b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi#define MAX_NUMBER_INTERFACES 2
262b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi#define MAX_NUMBER_PLAYERS 40
272b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
282b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi#define PREFETCHEVENT_ERROR_CANDIDATE \
292b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        (SL_PREFETCHEVENT_STATUSCHANGE | SL_PREFETCHEVENT_FILLLEVELCHANGE)
302b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
312b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi/* the OpenSL ES engine from which we create all other resources */
322b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel TriviSLObjectItf  slEngine;
332b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel TriviSLEngineItf  engineItf;
342b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel TriviSLObjectItf  outputMix;
352b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
362b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel TriviSLboolean     required[MAX_NUMBER_INTERFACES];
372b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel TriviSLInterfaceID iidArray[MAX_NUMBER_INTERFACES];
382b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
392b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel TriviSLObjectItf  audioPlayer[MAX_NUMBER_PLAYERS];
402b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivibool         validplayer[MAX_NUMBER_PLAYERS];
412b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Triviint          playerNum[MAX_NUMBER_PLAYERS];
422b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel TriviSLPlayItf    playItfs[MAX_NUMBER_PLAYERS];
432b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel TriviSLVolumeItf  volItfs[MAX_NUMBER_PLAYERS];
442b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel TriviSLPrefetchStatusItf prefetchItfs[MAX_NUMBER_PLAYERS];
452b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
462b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel TriviSLDataSource      audioSource;
472b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel TriviSLDataLocator_URI uri;
482b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel TriviSLDataFormat_MIME mime;
492b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
502b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel TriviSLDataSink              audioSink;
512b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel TriviSLDataLocator_OutputMix locator_outputmix;
522b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
532b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
542b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi//-----------------------------------------------------------------
552b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi//* Exits the application if an error is encountered */
562b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi#define CheckErr(x) ExitOnErrorFunc(x, -1, __LINE__)
572b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi#define CheckErrPlyr(x, id) ExitOnErrorFunc(x, id, __LINE__)
582b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
592b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivivoid ExitOnErrorFunc( SLresult result, int playerId, int line)
602b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi{
612b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    if (SL_RESULT_SUCCESS != result) {
622b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        if (playerId == -1) {
632b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi            fprintf(stderr, "Error %u code encountered at line %d, exiting\n", result, line);
642b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        } else {
652b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi            fprintf(stderr, "Error %u code encountered at line %d for player %d, exiting\n",
662b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi                    result, line, playerId);
672b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        }
682b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        exit(EXIT_FAILURE);
692b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    }
702b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi}
712b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
722b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi//-----------------------------------------------------------------
732b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi/* PrefetchStatusItf callback for an audio player */
742b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivivoid PrefetchEventCallback( SLPrefetchStatusItf caller,  void *pContext, SLuint32 event)
752b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi{
762b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    SLresult res;
772b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    SLpermille level = 0;
782b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    int* pPlayerId = (int*)pContext;
792b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    res = (*caller)->GetFillLevel(caller, &level); CheckErrPlyr(res, *pPlayerId);
802b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    SLuint32 status;
812b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    //fprintf(stdout, "PrefetchEventCallback: received event %u\n", event);
822b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    res = (*caller)->GetPrefetchStatus(caller, &status); CheckErrPlyr(res, *pPlayerId);
832b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    if ((PREFETCHEVENT_ERROR_CANDIDATE == (event & PREFETCHEVENT_ERROR_CANDIDATE))
842b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi            && (level == 0) && (status == SL_PREFETCHSTATUS_UNDERFLOW)) {
852b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        fprintf(stdout, "PrefetchEventCallback: Error while prefetching data for player %d, "
862b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi                "exiting\n", *pPlayerId);
872b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        exit(EXIT_FAILURE);
882b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    }
892b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    if (event & SL_PREFETCHEVENT_FILLLEVELCHANGE) {
902b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        fprintf(stdout, "PrefetchEventCallback: Buffer fill level is = %d for player %d\n",
912b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi                level, *pPlayerId);
922b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    }
932b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    if (event & SL_PREFETCHEVENT_STATUSCHANGE) {
942b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        fprintf(stdout, "PrefetchEventCallback: Prefetch Status is = %u for player %d\n",
952b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi                status, *pPlayerId);
962b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    }
972b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi}
982b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
992b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
1002b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi//-----------------------------------------------------------------
1012b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi/* PlayItf callback for playback events */
1022b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivivoid PlayEventCallback(
1032b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        SLPlayItf caller,
1042b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        void *pContext,
1052b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        SLuint32 event)
1062b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi{
1072b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    SLresult res;
1082b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    int* pPlayerId = (int*)pContext;
1092b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    if (SL_PLAYEVENT_HEADATEND & event) {
1102b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        fprintf(stdout, "SL_PLAYEVENT_HEADATEND reached for player %d\n", *pPlayerId);
1112b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        //SignalEos();
1122b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    }
1132b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
1142b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    if (SL_PLAYEVENT_HEADATNEWPOS & event) {
1152b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        SLmillisecond pMsec = 0;
1162b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        res = (*caller)->GetPosition(caller, &pMsec); CheckErrPlyr(res, *pPlayerId);
1172b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        fprintf(stdout, "SL_PLAYEVENT_HEADATNEWPOS current position=%ums for player %d\n",
1182b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi                pMsec, *pPlayerId);
1192b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    }
1202b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
1212b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    if (SL_PLAYEVENT_HEADATMARKER & event) {
1222b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        SLmillisecond pMsec = 0;
1232b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        res = (*caller)->GetPosition(caller, &pMsec); CheckErrPlyr(res, *pPlayerId);
1242b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        fprintf(stdout, "SL_PLAYEVENT_HEADATMARKER current position=%ums for player %d\n",
1252b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi                pMsec, *pPlayerId);
1262b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    }
1272b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi}
1282b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
1292b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
1302b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi//-----------------------------------------------------------------
1312b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivivoid TestSetup(const char* path) {
1322b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    SLint32                 numOutputs = 0;
1332b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    SLuint32                deviceID = 0;
1342b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    SLresult                res;
1352b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
1362b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    /* Create the engine */
1372b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    SLEngineOption EngineOption[] = {
1382b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi            {(SLuint32) SL_ENGINEOPTION_THREADSAFE,
1392b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi                    (SLuint32) SL_BOOLEAN_TRUE}};
1402b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
1412b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    res = slCreateEngine( &slEngine, 1, EngineOption, 0, NULL, NULL);
1422b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    CheckErr(res);
1432b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    /* Realizing the SL Engine in synchronous mode. */
1442b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    res = (*slEngine)->Realize(slEngine, SL_BOOLEAN_FALSE);
1452b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    CheckErr(res);
1462b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    /* Get the SL Engine Interface which is implicit */
1472b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    res = (*slEngine)->GetInterface(slEngine, SL_IID_ENGINE, (void*)&engineItf);
1482b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    CheckErr(res);
1492b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
1502b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    /* Create Output Mix object to be used by player */
1512b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    res = (*engineItf)->CreateOutputMix(engineItf, &outputMix, 0,
1522b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi            iidArray, required); CheckErr(res);
1532b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    /* Realizing the Output Mix object in synchronous mode. */
1542b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    res = (*outputMix)->Realize(outputMix, SL_BOOLEAN_FALSE);
1552b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    CheckErr(res);
1562b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
1572b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    /* Setup the data source structure for the URI */
1582b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    // the syntax below is more future-proof than the individual field initialization
1592b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    //  with regards to OpenSL ES 1.1 but adds scary compilation warnings
1602b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    //uri = { SL_DATALOCATOR_URI /*locatorType*/, (SLchar*) path /*URI*/ };
1612b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    //mime = { /*formatType*/ SL_DATAFORMAT_MIME, /*mimeType*/ (SLchar*)NULL,
1622b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    //         /*containerType*/ SL_CONTAINERTYPE_UNSPECIFIED };
1632b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    uri.locatorType = SL_DATALOCATOR_URI;
1642b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    uri.URI         =  (SLchar*) path;
1652b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    mime.formatType    = SL_DATAFORMAT_MIME;
1662b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    mime.mimeType      = (SLchar*)NULL;
1672b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    mime.containerType = SL_CONTAINERTYPE_UNSPECIFIED;
1682b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
1692b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    audioSource.pFormat      = (void *)&mime;
1702b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    audioSource.pLocator     = (void *)&uri;
1712b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
1722b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    /* Setup the data sink structure */
1732b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    locator_outputmix.locatorType   = SL_DATALOCATOR_OUTPUTMIX;
1742b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    locator_outputmix.outputMix    = outputMix;
1752b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    audioSink.pLocator           = (void *)&locator_outputmix;
1762b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    audioSink.pFormat            = NULL;
1772b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
1782b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    /* Initialize arrays required[] and iidArray[] */
1792b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    for (int i=0 ; i < MAX_NUMBER_INTERFACES ; i++) {
1802b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        required[i] = SL_BOOLEAN_FALSE;
1812b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        iidArray[i] = SL_IID_NULL;
1822b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    }
1832b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    /* Set arrays required[] and iidArray[] for VOLUME and PREFETCHSTATUS interface */
1842b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    required[0] = SL_BOOLEAN_TRUE;
1852b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    iidArray[0] = SL_IID_VOLUME;
1862b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    required[1] = SL_BOOLEAN_TRUE;
1872b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    iidArray[1] = SL_IID_PREFETCHSTATUS;
1882b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
1892b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    fprintf(stdout, "TestSetup(%s) completed\n", path);
1902b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi}
1912b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
1922b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
1932b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi//-----------------------------------------------------------------
1942b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivivoid TestTeardown() {
1952b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    /* Destroy Output Mix object */
1962b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    (*outputMix)->Destroy(outputMix);
1972b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
1982b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    /* Shutdown OpenSL ES */
1992b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    (*slEngine)->Destroy(slEngine);
2002b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi}
2012b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
2022b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
2032b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi//-----------------------------------------------------------------
2042b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi/**
2052b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi * Create a player and, if the creation is successful,
2062b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi * configure it, and start playing.
2072b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi */
2082b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivivoid CreatePlayer(int playerId) {
2092b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    SLresult res;
2102b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    playerNum[playerId] = playerId;
2112b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
2122b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    /* Create the audio player */
2132b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    res = (*engineItf)->CreateAudioPlayer(engineItf, &audioPlayer[playerId],
2142b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi            &audioSource, &audioSink, MAX_NUMBER_INTERFACES, iidArray, required);
2152b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    if (SL_RESULT_SUCCESS != res) {
2162b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi            // do not abort the test, just flag the player as not a candidate for destruction
2172b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi            fprintf(stdout, "CreateAudioPlayer for player %d failed\n", playerId);
2182b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi            validplayer[playerId] = false;
2192b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi            return;
2202b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        }
2212b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    validplayer[playerId] = true;
2222b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
2232b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    /* Realizing the player in synchronous mode. */
2242b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    res = (*audioPlayer[playerId])->Realize(audioPlayer[playerId], SL_BOOLEAN_FALSE);
2252b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    if (SL_RESULT_SUCCESS != res) {
2262b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        // do not abort the test, just stop the player initialization here
2272b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        fprintf(stdout, "Realize for player %d failed\n", playerId);
2282b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        // this player is still a candidate for destruction
2292b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        return;
2302b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    }
2312b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    // after this point, any failure is a test failure
2322b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
2332b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    /* Get interfaces */
2342b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    res = (*audioPlayer[playerId])->GetInterface(audioPlayer[playerId], SL_IID_PLAY,
2352b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi            (void*)&playItfs[playerId]);
2362b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    CheckErrPlyr(res, playerId);
2372b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
2382b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    res = (*audioPlayer[playerId])->GetInterface(audioPlayer[playerId], SL_IID_VOLUME,
2392b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi            (void*)&volItfs[playerId]);
2402b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    CheckErrPlyr(res, playerId);
2412b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
2422b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    res = (*audioPlayer[playerId])->GetInterface(audioPlayer[playerId], SL_IID_PREFETCHSTATUS,
2432b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi            (void*)&prefetchItfs[playerId]);
2442b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    CheckErrPlyr(res, playerId);
2452b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    res = (*prefetchItfs[playerId])->RegisterCallback(prefetchItfs[playerId], PrefetchEventCallback,
2462b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi            &playerNum[playerId]);
2472b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    CheckErrPlyr(res, playerId);
2482b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    res = (*prefetchItfs[playerId])->SetCallbackEventsMask(prefetchItfs[playerId],
2492b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi            SL_PREFETCHEVENT_FILLLEVELCHANGE | SL_PREFETCHEVENT_STATUSCHANGE);
2502b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    CheckErrPlyr(res, playerId);
2512b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
2522b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    /* Set the player volume */
2532b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    res = (*volItfs[playerId])->SetVolumeLevel( volItfs[playerId], -300);
2542b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    CheckErrPlyr(res, playerId);
2552b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
2562b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    /* Set up the player callback to get events during the decoding */
2572b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    res = (*playItfs[playerId])->SetMarkerPosition(playItfs[playerId], 2000);
2582b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    CheckErrPlyr(res, playerId);
2592b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    res = (*playItfs[playerId])->SetPositionUpdatePeriod(playItfs[playerId], 500);
2602b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    CheckErrPlyr(res, playerId);
2612b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    res = (*playItfs[playerId])->SetCallbackEventsMask(playItfs[playerId],
2622b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi            SL_PLAYEVENT_HEADATMARKER | SL_PLAYEVENT_HEADATNEWPOS | SL_PLAYEVENT_HEADATEND);
2632b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    CheckErrPlyr(res, playerId);
2642b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    res = (*playItfs[playerId])->RegisterCallback(playItfs[playerId], PlayEventCallback,
2652b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi            &playerNum[playerId]);
2662b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    CheckErrPlyr(res, playerId);
2672b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
2682b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    /* Configure fill level updates every 5 percent */
2692b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    (*prefetchItfs[playerId])->SetFillUpdatePeriod(prefetchItfs[playerId], 50);
2702b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
2712b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    /* Play the URI */
2722b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    /*     first cause the player to prefetch the data */
2732b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    fprintf(stdout, "Setting player %d  to PAUSED\n", playerId);
2742b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    res = (*playItfs[playerId])->SetPlayState( playItfs[playerId], SL_PLAYSTATE_PAUSED );
2752b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    CheckErrPlyr(res, playerId);
2762b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    /*     wait until there's data to play */
2772b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    SLuint32 prefetchStatus = SL_PREFETCHSTATUS_UNDERFLOW;
2782b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    SLuint32 timeOutIndex = 10; // 1s, should be enough for a local file
2792b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    while ((prefetchStatus != SL_PREFETCHSTATUS_SUFFICIENTDATA) && (timeOutIndex > 0)) {
2802b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        usleep(100 * 1000);
2812b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        res = (*prefetchItfs[playerId])->GetPrefetchStatus(prefetchItfs[playerId], &prefetchStatus);
2822b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        CheckErrPlyr(res, playerId);
2832b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        timeOutIndex--;
2842b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    }
2852b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
2862b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    if (timeOutIndex == 0) {
2872b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        fprintf(stderr, "Prefetch timed out for player %d\n", playerId);
2882b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        return;
2892b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    }
2902b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    res = (*playItfs[playerId])->SetPlayState( playItfs[playerId], SL_PLAYSTATE_PLAYING );
2912b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    CheckErrPlyr(res, playerId);
2922b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
2932b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    /* Display duration */
2942b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    SLmillisecond durationInMsec = SL_TIME_UNKNOWN;
2952b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    res = (*playItfs[playerId])->GetDuration(playItfs[playerId], &durationInMsec);
2962b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    CheckErrPlyr(res, playerId);
2972b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    if (durationInMsec == SL_TIME_UNKNOWN) {
2982b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        fprintf(stdout, "Content duration is unknown for player %d\n", playerId);
2992b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    } else {
3002b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        fprintf(stdout, "Content duration is %u ms for player %d\n", durationInMsec, playerId);
3012b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    }
3022b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi}
3032b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
3042b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi//-----------------------------------------------------------------
3052b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivivoid DestroyPlayer(int playerId) {
3062b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    fprintf(stdout, "About to destroy player %d\n", playerId);
3072b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    /* Destroy the player */
3082b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    (*audioPlayer[playerId])->Destroy(audioPlayer[playerId]);
3092b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi}
3102b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
3112b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
3122b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi//-----------------------------------------------------------------
3132b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Triviint main(int argc, char* const argv[])
3142b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi{
3152b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    fprintf(stdout, "OpenSL ES test %s: creates and destroys as many ", argv[0]);
3162b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    fprintf(stdout, "AudioPlayer objects as possible (max=%d)\n\n", MAX_NUMBER_PLAYERS);
3172b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
3182b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    if (argc == 1) {
3192b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        fprintf(stdout, "Usage: %s path \n\t%s url\n", argv[0], argv[0]);
3202b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        fprintf(stdout, "Example: \"%s /sdcard/my.mp3\"  or \"%s file:///sdcard/my.mp3\"\n",
3212b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi                argv[0], argv[0]);
3222b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        exit(EXIT_FAILURE);
3232b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    }
3242b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
3252b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    TestSetup(argv[1]);
3262b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
3272b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    for (int i=0 ; i<MAX_NUMBER_PLAYERS ; i++) {
3282b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        CreatePlayer(i);
3292b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    }
3302b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    fprintf(stdout, "After creating %d AudioPlayers\n", MAX_NUMBER_PLAYERS);
3312b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
3322b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    /* Wait for an arbitrary amount of time. if playing a long file, the players will still
3332b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi       be playing while the destructions start. */
3342b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    usleep(10*1000*1000); // 10s
3352b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
3362b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    for (int i=0 ; i<MAX_NUMBER_PLAYERS ; i++) {
3372b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        if (validplayer[i]) {
3382b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi            DestroyPlayer(i);
3392b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi        }
3402b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    }
3412b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    fprintf(stdout, "After destroying valid players among %d AudioPlayers\n", MAX_NUMBER_PLAYERS);
3422b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
3432b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    TestTeardown();
3442b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi
3452b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi    return EXIT_SUCCESS;
3462b750ac8e486b75a0f5755d4b595077ec525235eJean-Michel Trivi}
347