16cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi/*
26cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi * Copyright (C) 2010 The Android Open Source Project
36cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi *
46cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License");
56cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi * you may not use this file except in compliance with the License.
66cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi * You may obtain a copy of the License at
76cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi *
86cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi *      http://www.apache.org/licenses/LICENSE-2.0
96cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi *
106cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi * Unless required by applicable law or agreed to in writing, software
116cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS,
126cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi * See the License for the specific language governing permissions and
146cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi * limitations under the License.
156cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi */
166cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
17dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten#include <assert.h>
18dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten#include <pthread.h>
196cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi#include <stdlib.h>
206cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi#include <stdio.h>
216cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi#include <string.h>
226cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi#include <unistd.h>
236cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi#include <sys/time.h>
246cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
25a6c5e52ded343b557152156c33d33a10d29bf6f1Glenn Kasten#include <SLES/OpenSLES.h>
266cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
276cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
286cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi#define MAX_NUMBER_INTERFACES 2
296cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
306cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi#define REPETITIONS 4
316cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
32dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten// These are extensions to OpenSL ES 1.0.1 values
33dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten
34dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten#define SL_PREFETCHSTATUS_UNKNOWN 0
35dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten#define SL_PREFETCHSTATUS_ERROR   (-1)
36dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten
37dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten// Mutex and condition shared with main program to protect prefetch_status
38dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten
39dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kastenstatic pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
40dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kastenstatic pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
41dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn KastenSLuint32 prefetch_status = SL_PREFETCHSTATUS_UNKNOWN;
42dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten
43dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten/* used to detect errors likely to have occured when the OpenSL ES framework fails to open
44dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten * a resource, for instance because a file URI is invalid, or an HTTP server doesn't respond.
45dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten */
46dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten#define PREFETCHEVENT_ERROR_CANDIDATE \
47dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten        (SL_PREFETCHEVENT_STATUSCHANGE | SL_PREFETCHEVENT_FILLLEVELCHANGE)
48dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten
496cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi//-----------------------------------------------------------------
506cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi//* Exits the application if an error is encountered */
516cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi#define CheckErr(x) ExitOnErrorFunc(x,__LINE__)
526cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
536cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivivoid ExitOnErrorFunc( SLresult result , int line)
546cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi{
556cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    if (SL_RESULT_SUCCESS != result) {
56d968dacf7a35d52b6907283f3d95295a238340ccGlenn Kasten        fprintf(stderr, "%u error code encountered at line %d, exiting\n", result, line);
574d7c8c742d5b09895e7ce3d07d314b6ada56123dGlenn Kasten        exit(EXIT_FAILURE);
586cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    }
596cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi}
606cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
616cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi//-----------------------------------------------------------------
626cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi/* PrefetchStatusItf callback for an audio player */
63dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kastenvoid PrefetchEventCallback( SLPrefetchStatusItf caller, void *pContext, SLuint32 event)
646cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi{
65dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    SLresult result;
66dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    // pContext is unused here, so we pass NULL
67dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    assert(pContext == NULL);
686cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    SLpermille level = 0;
69dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    result = (*caller)->GetFillLevel(caller, &level);
70dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    CheckErr(result);
716cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    SLuint32 status;
72dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    result = (*caller)->GetPrefetchStatus(caller, &status);
73dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    CheckErr(result);
746cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    if (event & SL_PREFETCHEVENT_FILLLEVELCHANGE) {
756cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi        fprintf(stdout, "\t\tPrefetchEventCallback: Buffer fill level is = %d\n", level);
766cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    }
776cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    if (event & SL_PREFETCHEVENT_STATUSCHANGE) {
78d968dacf7a35d52b6907283f3d95295a238340ccGlenn Kasten        fprintf(stdout, "\t\tPrefetchEventCallback: Prefetch Status is = %u\n", status);
796cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    }
80dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    SLuint32 new_prefetch_status;
81dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    if ((event & PREFETCHEVENT_ERROR_CANDIDATE) == PREFETCHEVENT_ERROR_CANDIDATE
82dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten            && (level == 0) && (status == SL_PREFETCHSTATUS_UNDERFLOW)) {
83dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten        fprintf(stdout, "\t\tPrefetchEventCallback: Error while prefetching data, exiting\n");
84dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten        new_prefetch_status = SL_PREFETCHSTATUS_ERROR;
85dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    } else if (event == SL_PREFETCHEVENT_STATUSCHANGE &&
86dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten            status == SL_PREFETCHSTATUS_SUFFICIENTDATA) {
87dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten        new_prefetch_status = status;
88dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    } else {
89dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten        return;
90dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    }
91dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    int ok;
92dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    ok = pthread_mutex_lock(&mutex);
93dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    assert(ok == 0);
94dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    prefetch_status = new_prefetch_status;
95dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    ok = pthread_cond_signal(&cond);
96dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    assert(ok == 0);
97dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    ok = pthread_mutex_unlock(&mutex);
98dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    assert(ok == 0);
99dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten}
100dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten
1016cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
102dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten//-----------------------------------------------------------------
103dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten/* PlayItf callback for playback events */
104dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kastenvoid PlayEventCallback(
105dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten        SLPlayItf caller,
106dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten        void *pContext,
107dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten        SLuint32 event)
108dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten{
109dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    // pContext is unused here, so we pass NULL
110dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    assert(NULL == pContext);
111dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    if (SL_PLAYEVENT_HEADATEND == event) {
112dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten        printf("SL_PLAYEVENT_HEADATEND reached\n");
113dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    } else {
114dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten        fprintf(stderr, "Unexpected play event 0x%x", event);
115dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    }
1166cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi}
1176cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
1186cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
1196cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi//-----------------------------------------------------------------
1206cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
1216cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi/* Play some music from a URI  */
1226cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivivoid TestLoopUri( SLObjectItf sl, const char* path)
1236cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi{
1246cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    SLEngineItf                EngineItf;
1256cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
1266cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    SLint32                    numOutputs = 0;
1276cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    SLuint32                   deviceID = 0;
1286cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
1296cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    SLresult                   res;
1306cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
1316cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    SLDataSource               audioSource;
1326cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    SLDataLocator_URI          uri;
1336cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    SLDataFormat_MIME          mime;
1346cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
1356cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    SLDataSink                 audioSink;
1366cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    SLDataLocator_OutputMix    locator_outputmix;
1376cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
1386cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    SLObjectItf                player;
1396cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    SLPlayItf                  playItf;
1406cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    SLSeekItf                  seekItf;
1416cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    SLPrefetchStatusItf        prefetchItf;
1426cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
1436cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    SLObjectItf                OutputMix;
1446cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
1456cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    SLboolean required[MAX_NUMBER_INTERFACES];
1466cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    SLInterfaceID iidArray[MAX_NUMBER_INTERFACES];
1476cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
1486cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    /* Get the SL Engine Interface which is implicit */
1496cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    res = (*sl)->GetInterface(sl, SL_IID_ENGINE, (void*)&EngineItf);
1506cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    CheckErr(res);
1516cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
1526cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    /* Initialize arrays required[] and iidArray[] */
1536cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    for (int i=0 ; i < MAX_NUMBER_INTERFACES ; i++) {
1546cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi        required[i] = SL_BOOLEAN_FALSE;
1556cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi        iidArray[i] = SL_IID_NULL;
1566cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    }
1576cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
1586cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    required[0] = SL_BOOLEAN_TRUE;
1596cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    iidArray[0] = SL_IID_VOLUME;
1606cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    // Create Output Mix object to be used by player
1614d7c8c742d5b09895e7ce3d07d314b6ada56123dGlenn Kasten    res = (*EngineItf)->CreateOutputMix(EngineItf, &OutputMix, 0,
1626cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi            iidArray, required); CheckErr(res);
1636cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
1646cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    // Realizing the Output Mix object in synchronous mode.
1656cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    res = (*OutputMix)->Realize(OutputMix, SL_BOOLEAN_FALSE);
1666cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    CheckErr(res);
1676cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
1686cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    /* Setup the data source structure for the URI */
1696cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    uri.locatorType = SL_DATALOCATOR_URI;
1706cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    uri.URI         =  (SLchar*) path;
1716cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    mime.formatType    = SL_DATAFORMAT_MIME;
1726cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    mime.mimeType      = (SLchar*)NULL;
1736cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    mime.containerType = SL_CONTAINERTYPE_UNSPECIFIED;
1746cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
1756cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    audioSource.pFormat      = (void *)&mime;
1766cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    audioSource.pLocator     = (void *)&uri;
1776cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
1786cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    /* Setup the data sink structure */
1796cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    locator_outputmix.locatorType   = SL_DATALOCATOR_OUTPUTMIX;
1806cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    locator_outputmix.outputMix    = OutputMix;
1816cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    audioSink.pLocator           = (void *)&locator_outputmix;
1826cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    audioSink.pFormat            = NULL;
1836cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
1846cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    /* Create the audio player */
1856cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    required[0] = SL_BOOLEAN_TRUE;
1866cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    iidArray[0] = SL_IID_SEEK;
1876cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    required[1] = SL_BOOLEAN_TRUE;
1886cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    iidArray[1] = SL_IID_PREFETCHSTATUS;
1896cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    res = (*EngineItf)->CreateAudioPlayer(EngineItf, &player, &audioSource, &audioSink,
1906cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi            MAX_NUMBER_INTERFACES, iidArray, required); CheckErr(res);
1916cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
1926cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    /* Realizing the player in synchronous mode. */
1936cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    res = (*player)->Realize(player, SL_BOOLEAN_FALSE); CheckErr(res);
1946cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    fprintf(stdout, "URI example: after Realize\n");
1956cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
1966cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    /* Get interfaces */
1976cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    res = (*player)->GetInterface(player, SL_IID_PLAY, (void*)&playItf);
1986cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    CheckErr(res);
1996cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
2006cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    res = (*player)->GetInterface(player, SL_IID_SEEK,  (void*)&seekItf);
2016cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    CheckErr(res);
2026cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
2036cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    res = (*player)->GetInterface(player, SL_IID_PREFETCHSTATUS, (void*)&prefetchItf);
2046cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    CheckErr(res);
205dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    res = (*prefetchItf)->RegisterCallback(prefetchItf, PrefetchEventCallback, NULL);
2066cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    CheckErr(res);
2076cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    res = (*prefetchItf)->SetCallbackEventsMask(prefetchItf,
2086cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi            SL_PREFETCHEVENT_FILLLEVELCHANGE | SL_PREFETCHEVENT_STATUSCHANGE);
2096cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    CheckErr(res);
2106cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
2116cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    /* Configure fill level updates every 5 percent */
2126cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    (*prefetchItf)->SetFillUpdatePeriod(prefetchItf, 50);
2136cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
214dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    /* Set up the player callback to get head-at-end events */
215dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    res = (*playItf)->SetCallbackEventsMask(playItf, SL_PLAYEVENT_HEADATEND);
216dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    CheckErr(res);
217dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    res = (*playItf)->RegisterCallback(playItf, PlayEventCallback, NULL);
218dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    CheckErr(res);
219dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten
2206cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    /* Display duration */
2216cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    SLmillisecond durationInMsec = SL_TIME_UNKNOWN;
2226cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    res = (*playItf)->GetDuration(playItf, &durationInMsec);
2236cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    CheckErr(res);
2246cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    if (durationInMsec == SL_TIME_UNKNOWN) {
2256cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi        fprintf(stdout, "Content duration is unknown (before starting to prefetch)\n");
2266cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    } else {
227d968dacf7a35d52b6907283f3d95295a238340ccGlenn Kasten        fprintf(stdout, "Content duration is %u ms (before starting to prefetch)\n",
2286cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi                durationInMsec);
2296cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    }
2306cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
2316cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    /* Loop on the whole of the content */
2326cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    res = (*seekItf)->SetLoop(seekItf, SL_BOOLEAN_TRUE, 0, SL_TIME_UNKNOWN);
2336cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    CheckErr(res);
2346cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
2356cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    /* Play the URI */
2366cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    /*     first cause the player to prefetch the data */
2376cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    res = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PAUSED );
2386cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    CheckErr(res);
2396cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
240dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    // wait for prefetch status callback to indicate either sufficient data or error
241dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    pthread_mutex_lock(&mutex);
242dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    while (prefetch_status == SL_PREFETCHSTATUS_UNKNOWN) {
243dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten        pthread_cond_wait(&cond, &mutex);
2446cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    }
245dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    pthread_mutex_unlock(&mutex);
246dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    if (prefetch_status == SL_PREFETCHSTATUS_ERROR) {
247dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten        fprintf(stderr, "Error during prefetch, exiting\n");
2486cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi        goto destroyRes;
2496cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    }
2506cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
2516cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    /* Display duration again, */
2526cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    res = (*playItf)->GetDuration(playItf, &durationInMsec);
2536cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    CheckErr(res);
2546cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    if (durationInMsec == SL_TIME_UNKNOWN) {
2556cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi        fprintf(stdout, "Content duration is unknown (after prefetch completed)\n");
2566cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    } else {
257d968dacf7a35d52b6907283f3d95295a238340ccGlenn Kasten        fprintf(stdout, "Content duration is %u ms (after prefetch completed)\n", durationInMsec);
2586cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    }
2596cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
260dfc3110139e5aa8205e5736c93c3d2bcc077f71bGlenn Kasten    /* Start playing */
2616cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    fprintf(stdout, "starting to play\n");
2626cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    res = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PLAYING );
2636cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    CheckErr(res);
2646cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
2656cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    /* Wait as long as the duration of the content, times the repetitions,
2666cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi     * before stopping the loop */
2676cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    usleep( (REPETITIONS-1) * durationInMsec * 1100);
2686cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    res = (*seekItf)->SetLoop(seekItf, SL_BOOLEAN_FALSE, 0, SL_TIME_UNKNOWN);
2696cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    CheckErr(res);
2706cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    fprintf(stdout, "As of now, stopped looping (sound shouldn't repeat from now on)\n");
2716cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    /* wait some more to make sure it doesn't repeat */
2726cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    usleep(durationInMsec * 1000);
2736cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
2746cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    /* Stop playback */
2756cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    fprintf(stdout, "stopping playback\n");
2766cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    res = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED);
2776cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    CheckErr(res);
2786cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
2796cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel TrividestroyRes:
2806cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
2816cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    /* Destroy the player */
2826cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    (*player)->Destroy(player);
2836cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
2846cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    /* Destroy Output Mix object */
2856cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    (*OutputMix)->Destroy(OutputMix);
2866cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi}
2876cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
2886cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi//-----------------------------------------------------------------
2896cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Triviint main(int argc, char* const argv[])
2906cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi{
2916cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    SLresult    res;
2926cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    SLObjectItf sl;
2936cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
2946cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    fprintf(stdout, "OpenSL ES test %s: exercises SLPlayItf, SLSeekItf ", argv[0]);
2956cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    fprintf(stdout, "and AudioPlayer with SLDataLocator_URI source / OutputMix sink\n");
2966cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    fprintf(stdout, "Plays a sound and loops it %d times.\n\n", REPETITIONS);
2976cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
2986cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    if (argc == 1) {
2996cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi        fprintf(stdout, "Usage: \n\t%s path \n\t%s url\n", argv[0], argv[0]);
3006cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi        fprintf(stdout, "Example: \"%s /sdcard/my.mp3\"  or \"%s file:///sdcard/my.mp3\"\n",
3016cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi                argv[0], argv[0]);
3024d7c8c742d5b09895e7ce3d07d314b6ada56123dGlenn Kasten        exit(EXIT_FAILURE);
3036cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    }
3046cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
3056cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    SLEngineOption EngineOption[] = {
3066cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi            {(SLuint32) SL_ENGINEOPTION_THREADSAFE,
3076cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi            (SLuint32) SL_BOOLEAN_TRUE}};
3086cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
3096cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    res = slCreateEngine( &sl, 1, EngineOption, 0, NULL, NULL);
3106cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    CheckErr(res);
3116cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    /* Realizing the SL Engine in synchronous mode. */
3126cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    res = (*sl)->Realize(sl, SL_BOOLEAN_FALSE);
3136cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    CheckErr(res);
3146cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
3156cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    TestLoopUri(sl, argv[1]);
3166cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
3176cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    /* Shutdown OpenSL ES */
3186cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi    (*sl)->Destroy(sl);
3196cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi
3204d7c8c742d5b09895e7ce3d07d314b6ada56123dGlenn Kasten    return EXIT_SUCCESS;
3216cb166eb8284fb9c9cf2d26daf7eb802168d710dJean-Michel Trivi}
322