1*bebae9c0SAndroid Build Coastguard Worker /*
2*bebae9c0SAndroid Build Coastguard Worker * Copyright (C) 2010 The Android Open Source Project
3*bebae9c0SAndroid Build Coastguard Worker *
4*bebae9c0SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*bebae9c0SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*bebae9c0SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*bebae9c0SAndroid Build Coastguard Worker *
8*bebae9c0SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*bebae9c0SAndroid Build Coastguard Worker *
10*bebae9c0SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*bebae9c0SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*bebae9c0SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*bebae9c0SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*bebae9c0SAndroid Build Coastguard Worker * limitations under the License.
15*bebae9c0SAndroid Build Coastguard Worker */
16*bebae9c0SAndroid Build Coastguard Worker
17*bebae9c0SAndroid Build Coastguard Worker #include <assert.h>
18*bebae9c0SAndroid Build Coastguard Worker #include <pthread.h>
19*bebae9c0SAndroid Build Coastguard Worker #include <stdlib.h>
20*bebae9c0SAndroid Build Coastguard Worker #include <stdio.h>
21*bebae9c0SAndroid Build Coastguard Worker #include <string.h>
22*bebae9c0SAndroid Build Coastguard Worker #include <unistd.h>
23*bebae9c0SAndroid Build Coastguard Worker #include <sys/time.h>
24*bebae9c0SAndroid Build Coastguard Worker
25*bebae9c0SAndroid Build Coastguard Worker #include <SLES/OpenSLES.h>
26*bebae9c0SAndroid Build Coastguard Worker
27*bebae9c0SAndroid Build Coastguard Worker
28*bebae9c0SAndroid Build Coastguard Worker #define MAX_NUMBER_INTERFACES 2
29*bebae9c0SAndroid Build Coastguard Worker
30*bebae9c0SAndroid Build Coastguard Worker #define REPETITIONS 4
31*bebae9c0SAndroid Build Coastguard Worker
32*bebae9c0SAndroid Build Coastguard Worker // These are extensions to OpenSL ES 1.0.1 values
33*bebae9c0SAndroid Build Coastguard Worker
34*bebae9c0SAndroid Build Coastguard Worker #define SL_PREFETCHSTATUS_UNKNOWN 0
35*bebae9c0SAndroid Build Coastguard Worker #define SL_PREFETCHSTATUS_ERROR ((SLuint32) -1)
36*bebae9c0SAndroid Build Coastguard Worker
37*bebae9c0SAndroid Build Coastguard Worker // Mutex and condition shared with main program to protect prefetch_status
38*bebae9c0SAndroid Build Coastguard Worker
39*bebae9c0SAndroid Build Coastguard Worker static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
40*bebae9c0SAndroid Build Coastguard Worker static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
41*bebae9c0SAndroid Build Coastguard Worker SLuint32 prefetch_status = SL_PREFETCHSTATUS_UNKNOWN;
42*bebae9c0SAndroid Build Coastguard Worker
43*bebae9c0SAndroid Build Coastguard Worker /* used to detect errors likely to have occured when the OpenSL ES framework fails to open
44*bebae9c0SAndroid Build Coastguard Worker * a resource, for instance because a file URI is invalid, or an HTTP server doesn't respond.
45*bebae9c0SAndroid Build Coastguard Worker */
46*bebae9c0SAndroid Build Coastguard Worker #define PREFETCHEVENT_ERROR_CANDIDATE \
47*bebae9c0SAndroid Build Coastguard Worker (SL_PREFETCHEVENT_STATUSCHANGE | SL_PREFETCHEVENT_FILLLEVELCHANGE)
48*bebae9c0SAndroid Build Coastguard Worker
49*bebae9c0SAndroid Build Coastguard Worker //-----------------------------------------------------------------
50*bebae9c0SAndroid Build Coastguard Worker //* Exits the application if an error is encountered */
51*bebae9c0SAndroid Build Coastguard Worker #define CheckErr(x) ExitOnErrorFunc(x,__LINE__)
52*bebae9c0SAndroid Build Coastguard Worker
ExitOnErrorFunc(SLresult result,int line)53*bebae9c0SAndroid Build Coastguard Worker void ExitOnErrorFunc( SLresult result , int line)
54*bebae9c0SAndroid Build Coastguard Worker {
55*bebae9c0SAndroid Build Coastguard Worker if (SL_RESULT_SUCCESS != result) {
56*bebae9c0SAndroid Build Coastguard Worker fprintf(stderr, "%u error code encountered at line %d, exiting\n", result, line);
57*bebae9c0SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
58*bebae9c0SAndroid Build Coastguard Worker }
59*bebae9c0SAndroid Build Coastguard Worker }
60*bebae9c0SAndroid Build Coastguard Worker
61*bebae9c0SAndroid Build Coastguard Worker //-----------------------------------------------------------------
62*bebae9c0SAndroid Build Coastguard Worker /* PrefetchStatusItf callback for an audio player */
PrefetchEventCallback(SLPrefetchStatusItf caller,void * pContext,SLuint32 event)63*bebae9c0SAndroid Build Coastguard Worker void PrefetchEventCallback( SLPrefetchStatusItf caller, void *pContext, SLuint32 event)
64*bebae9c0SAndroid Build Coastguard Worker {
65*bebae9c0SAndroid Build Coastguard Worker SLresult result;
66*bebae9c0SAndroid Build Coastguard Worker // pContext is unused here, so we pass NULL
67*bebae9c0SAndroid Build Coastguard Worker assert(pContext == NULL);
68*bebae9c0SAndroid Build Coastguard Worker SLpermille level = 0;
69*bebae9c0SAndroid Build Coastguard Worker result = (*caller)->GetFillLevel(caller, &level);
70*bebae9c0SAndroid Build Coastguard Worker CheckErr(result);
71*bebae9c0SAndroid Build Coastguard Worker SLuint32 status;
72*bebae9c0SAndroid Build Coastguard Worker result = (*caller)->GetPrefetchStatus(caller, &status);
73*bebae9c0SAndroid Build Coastguard Worker CheckErr(result);
74*bebae9c0SAndroid Build Coastguard Worker if (event & SL_PREFETCHEVENT_FILLLEVELCHANGE) {
75*bebae9c0SAndroid Build Coastguard Worker fprintf(stdout, "\t\tPrefetchEventCallback: Buffer fill level is = %d\n", level);
76*bebae9c0SAndroid Build Coastguard Worker }
77*bebae9c0SAndroid Build Coastguard Worker if (event & SL_PREFETCHEVENT_STATUSCHANGE) {
78*bebae9c0SAndroid Build Coastguard Worker fprintf(stdout, "\t\tPrefetchEventCallback: Prefetch Status is = %u\n", status);
79*bebae9c0SAndroid Build Coastguard Worker }
80*bebae9c0SAndroid Build Coastguard Worker SLuint32 new_prefetch_status;
81*bebae9c0SAndroid Build Coastguard Worker if ((event & PREFETCHEVENT_ERROR_CANDIDATE) == PREFETCHEVENT_ERROR_CANDIDATE
82*bebae9c0SAndroid Build Coastguard Worker && (level == 0) && (status == SL_PREFETCHSTATUS_UNDERFLOW)) {
83*bebae9c0SAndroid Build Coastguard Worker fprintf(stdout, "\t\tPrefetchEventCallback: Error while prefetching data, exiting\n");
84*bebae9c0SAndroid Build Coastguard Worker new_prefetch_status = SL_PREFETCHSTATUS_ERROR;
85*bebae9c0SAndroid Build Coastguard Worker } else if (event == SL_PREFETCHEVENT_STATUSCHANGE &&
86*bebae9c0SAndroid Build Coastguard Worker status == SL_PREFETCHSTATUS_SUFFICIENTDATA) {
87*bebae9c0SAndroid Build Coastguard Worker new_prefetch_status = status;
88*bebae9c0SAndroid Build Coastguard Worker } else {
89*bebae9c0SAndroid Build Coastguard Worker return;
90*bebae9c0SAndroid Build Coastguard Worker }
91*bebae9c0SAndroid Build Coastguard Worker int ok;
92*bebae9c0SAndroid Build Coastguard Worker ok = pthread_mutex_lock(&mutex);
93*bebae9c0SAndroid Build Coastguard Worker assert(ok == 0);
94*bebae9c0SAndroid Build Coastguard Worker prefetch_status = new_prefetch_status;
95*bebae9c0SAndroid Build Coastguard Worker ok = pthread_cond_signal(&cond);
96*bebae9c0SAndroid Build Coastguard Worker assert(ok == 0);
97*bebae9c0SAndroid Build Coastguard Worker ok = pthread_mutex_unlock(&mutex);
98*bebae9c0SAndroid Build Coastguard Worker assert(ok == 0);
99*bebae9c0SAndroid Build Coastguard Worker }
100*bebae9c0SAndroid Build Coastguard Worker
101*bebae9c0SAndroid Build Coastguard Worker
102*bebae9c0SAndroid Build Coastguard Worker //-----------------------------------------------------------------
103*bebae9c0SAndroid Build Coastguard Worker /* PlayItf callback for playback events */
PlayEventCallback(SLPlayItf caller __unused,void * pContext,SLuint32 event)104*bebae9c0SAndroid Build Coastguard Worker void PlayEventCallback(
105*bebae9c0SAndroid Build Coastguard Worker SLPlayItf caller __unused,
106*bebae9c0SAndroid Build Coastguard Worker void *pContext,
107*bebae9c0SAndroid Build Coastguard Worker SLuint32 event)
108*bebae9c0SAndroid Build Coastguard Worker {
109*bebae9c0SAndroid Build Coastguard Worker // pContext is unused here, so we pass NULL
110*bebae9c0SAndroid Build Coastguard Worker assert(NULL == pContext);
111*bebae9c0SAndroid Build Coastguard Worker if (SL_PLAYEVENT_HEADATEND == event) {
112*bebae9c0SAndroid Build Coastguard Worker printf("SL_PLAYEVENT_HEADATEND reached\n");
113*bebae9c0SAndroid Build Coastguard Worker } else {
114*bebae9c0SAndroid Build Coastguard Worker fprintf(stderr, "Unexpected play event 0x%x", event);
115*bebae9c0SAndroid Build Coastguard Worker }
116*bebae9c0SAndroid Build Coastguard Worker }
117*bebae9c0SAndroid Build Coastguard Worker
118*bebae9c0SAndroid Build Coastguard Worker
119*bebae9c0SAndroid Build Coastguard Worker //-----------------------------------------------------------------
120*bebae9c0SAndroid Build Coastguard Worker
121*bebae9c0SAndroid Build Coastguard Worker /* Play some music from a URI */
TestLoopUri(SLObjectItf sl,const char * path)122*bebae9c0SAndroid Build Coastguard Worker void TestLoopUri( SLObjectItf sl, const char* path)
123*bebae9c0SAndroid Build Coastguard Worker {
124*bebae9c0SAndroid Build Coastguard Worker SLEngineItf EngineItf;
125*bebae9c0SAndroid Build Coastguard Worker
126*bebae9c0SAndroid Build Coastguard Worker SLresult res;
127*bebae9c0SAndroid Build Coastguard Worker
128*bebae9c0SAndroid Build Coastguard Worker SLDataSource audioSource;
129*bebae9c0SAndroid Build Coastguard Worker SLDataLocator_URI uri;
130*bebae9c0SAndroid Build Coastguard Worker SLDataFormat_MIME mime;
131*bebae9c0SAndroid Build Coastguard Worker
132*bebae9c0SAndroid Build Coastguard Worker SLDataSink audioSink;
133*bebae9c0SAndroid Build Coastguard Worker SLDataLocator_OutputMix locator_outputmix;
134*bebae9c0SAndroid Build Coastguard Worker
135*bebae9c0SAndroid Build Coastguard Worker SLObjectItf player;
136*bebae9c0SAndroid Build Coastguard Worker SLPlayItf playItf;
137*bebae9c0SAndroid Build Coastguard Worker SLSeekItf seekItf;
138*bebae9c0SAndroid Build Coastguard Worker SLPrefetchStatusItf prefetchItf;
139*bebae9c0SAndroid Build Coastguard Worker
140*bebae9c0SAndroid Build Coastguard Worker SLObjectItf OutputMix;
141*bebae9c0SAndroid Build Coastguard Worker
142*bebae9c0SAndroid Build Coastguard Worker SLboolean required[MAX_NUMBER_INTERFACES];
143*bebae9c0SAndroid Build Coastguard Worker SLInterfaceID iidArray[MAX_NUMBER_INTERFACES];
144*bebae9c0SAndroid Build Coastguard Worker
145*bebae9c0SAndroid Build Coastguard Worker /* Get the SL Engine Interface which is implicit */
146*bebae9c0SAndroid Build Coastguard Worker res = (*sl)->GetInterface(sl, SL_IID_ENGINE, (void*)&EngineItf);
147*bebae9c0SAndroid Build Coastguard Worker CheckErr(res);
148*bebae9c0SAndroid Build Coastguard Worker
149*bebae9c0SAndroid Build Coastguard Worker /* Initialize arrays required[] and iidArray[] */
150*bebae9c0SAndroid Build Coastguard Worker for (int i=0 ; i < MAX_NUMBER_INTERFACES ; i++) {
151*bebae9c0SAndroid Build Coastguard Worker required[i] = SL_BOOLEAN_FALSE;
152*bebae9c0SAndroid Build Coastguard Worker iidArray[i] = SL_IID_NULL;
153*bebae9c0SAndroid Build Coastguard Worker }
154*bebae9c0SAndroid Build Coastguard Worker
155*bebae9c0SAndroid Build Coastguard Worker required[0] = SL_BOOLEAN_TRUE;
156*bebae9c0SAndroid Build Coastguard Worker iidArray[0] = SL_IID_VOLUME;
157*bebae9c0SAndroid Build Coastguard Worker // Create Output Mix object to be used by player
158*bebae9c0SAndroid Build Coastguard Worker res = (*EngineItf)->CreateOutputMix(EngineItf, &OutputMix, 0,
159*bebae9c0SAndroid Build Coastguard Worker iidArray, required); CheckErr(res);
160*bebae9c0SAndroid Build Coastguard Worker
161*bebae9c0SAndroid Build Coastguard Worker // Realizing the Output Mix object in synchronous mode.
162*bebae9c0SAndroid Build Coastguard Worker res = (*OutputMix)->Realize(OutputMix, SL_BOOLEAN_FALSE);
163*bebae9c0SAndroid Build Coastguard Worker CheckErr(res);
164*bebae9c0SAndroid Build Coastguard Worker
165*bebae9c0SAndroid Build Coastguard Worker /* Setup the data source structure for the URI */
166*bebae9c0SAndroid Build Coastguard Worker uri.locatorType = SL_DATALOCATOR_URI;
167*bebae9c0SAndroid Build Coastguard Worker uri.URI = (SLchar*) path;
168*bebae9c0SAndroid Build Coastguard Worker mime.formatType = SL_DATAFORMAT_MIME;
169*bebae9c0SAndroid Build Coastguard Worker mime.mimeType = (SLchar*)NULL;
170*bebae9c0SAndroid Build Coastguard Worker mime.containerType = SL_CONTAINERTYPE_UNSPECIFIED;
171*bebae9c0SAndroid Build Coastguard Worker
172*bebae9c0SAndroid Build Coastguard Worker audioSource.pFormat = (void *)&mime;
173*bebae9c0SAndroid Build Coastguard Worker audioSource.pLocator = (void *)&uri;
174*bebae9c0SAndroid Build Coastguard Worker
175*bebae9c0SAndroid Build Coastguard Worker /* Setup the data sink structure */
176*bebae9c0SAndroid Build Coastguard Worker locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
177*bebae9c0SAndroid Build Coastguard Worker locator_outputmix.outputMix = OutputMix;
178*bebae9c0SAndroid Build Coastguard Worker audioSink.pLocator = (void *)&locator_outputmix;
179*bebae9c0SAndroid Build Coastguard Worker audioSink.pFormat = NULL;
180*bebae9c0SAndroid Build Coastguard Worker
181*bebae9c0SAndroid Build Coastguard Worker /* Create the audio player */
182*bebae9c0SAndroid Build Coastguard Worker required[0] = SL_BOOLEAN_TRUE;
183*bebae9c0SAndroid Build Coastguard Worker iidArray[0] = SL_IID_SEEK;
184*bebae9c0SAndroid Build Coastguard Worker required[1] = SL_BOOLEAN_TRUE;
185*bebae9c0SAndroid Build Coastguard Worker iidArray[1] = SL_IID_PREFETCHSTATUS;
186*bebae9c0SAndroid Build Coastguard Worker res = (*EngineItf)->CreateAudioPlayer(EngineItf, &player, &audioSource, &audioSink,
187*bebae9c0SAndroid Build Coastguard Worker MAX_NUMBER_INTERFACES, iidArray, required); CheckErr(res);
188*bebae9c0SAndroid Build Coastguard Worker
189*bebae9c0SAndroid Build Coastguard Worker /* Realizing the player in synchronous mode. */
190*bebae9c0SAndroid Build Coastguard Worker res = (*player)->Realize(player, SL_BOOLEAN_FALSE); CheckErr(res);
191*bebae9c0SAndroid Build Coastguard Worker fprintf(stdout, "URI example: after Realize\n");
192*bebae9c0SAndroid Build Coastguard Worker
193*bebae9c0SAndroid Build Coastguard Worker /* Get interfaces */
194*bebae9c0SAndroid Build Coastguard Worker res = (*player)->GetInterface(player, SL_IID_PLAY, (void*)&playItf);
195*bebae9c0SAndroid Build Coastguard Worker CheckErr(res);
196*bebae9c0SAndroid Build Coastguard Worker
197*bebae9c0SAndroid Build Coastguard Worker res = (*player)->GetInterface(player, SL_IID_SEEK, (void*)&seekItf);
198*bebae9c0SAndroid Build Coastguard Worker CheckErr(res);
199*bebae9c0SAndroid Build Coastguard Worker
200*bebae9c0SAndroid Build Coastguard Worker res = (*player)->GetInterface(player, SL_IID_PREFETCHSTATUS, (void*)&prefetchItf);
201*bebae9c0SAndroid Build Coastguard Worker CheckErr(res);
202*bebae9c0SAndroid Build Coastguard Worker res = (*prefetchItf)->RegisterCallback(prefetchItf, PrefetchEventCallback, NULL);
203*bebae9c0SAndroid Build Coastguard Worker CheckErr(res);
204*bebae9c0SAndroid Build Coastguard Worker res = (*prefetchItf)->SetCallbackEventsMask(prefetchItf,
205*bebae9c0SAndroid Build Coastguard Worker SL_PREFETCHEVENT_FILLLEVELCHANGE | SL_PREFETCHEVENT_STATUSCHANGE);
206*bebae9c0SAndroid Build Coastguard Worker CheckErr(res);
207*bebae9c0SAndroid Build Coastguard Worker
208*bebae9c0SAndroid Build Coastguard Worker /* Configure fill level updates every 5 percent */
209*bebae9c0SAndroid Build Coastguard Worker (*prefetchItf)->SetFillUpdatePeriod(prefetchItf, 50);
210*bebae9c0SAndroid Build Coastguard Worker
211*bebae9c0SAndroid Build Coastguard Worker /* Set up the player callback to get head-at-end events */
212*bebae9c0SAndroid Build Coastguard Worker res = (*playItf)->SetCallbackEventsMask(playItf, SL_PLAYEVENT_HEADATEND);
213*bebae9c0SAndroid Build Coastguard Worker CheckErr(res);
214*bebae9c0SAndroid Build Coastguard Worker res = (*playItf)->RegisterCallback(playItf, PlayEventCallback, NULL);
215*bebae9c0SAndroid Build Coastguard Worker CheckErr(res);
216*bebae9c0SAndroid Build Coastguard Worker
217*bebae9c0SAndroid Build Coastguard Worker /* Display duration */
218*bebae9c0SAndroid Build Coastguard Worker SLmillisecond durationInMsec = SL_TIME_UNKNOWN;
219*bebae9c0SAndroid Build Coastguard Worker res = (*playItf)->GetDuration(playItf, &durationInMsec);
220*bebae9c0SAndroid Build Coastguard Worker CheckErr(res);
221*bebae9c0SAndroid Build Coastguard Worker if (durationInMsec == SL_TIME_UNKNOWN) {
222*bebae9c0SAndroid Build Coastguard Worker fprintf(stdout, "Content duration is unknown (before starting to prefetch)\n");
223*bebae9c0SAndroid Build Coastguard Worker } else {
224*bebae9c0SAndroid Build Coastguard Worker fprintf(stdout, "Content duration is %u ms (before starting to prefetch)\n",
225*bebae9c0SAndroid Build Coastguard Worker durationInMsec);
226*bebae9c0SAndroid Build Coastguard Worker }
227*bebae9c0SAndroid Build Coastguard Worker
228*bebae9c0SAndroid Build Coastguard Worker /* Loop on the whole of the content */
229*bebae9c0SAndroid Build Coastguard Worker res = (*seekItf)->SetLoop(seekItf, SL_BOOLEAN_TRUE, 0, SL_TIME_UNKNOWN);
230*bebae9c0SAndroid Build Coastguard Worker CheckErr(res);
231*bebae9c0SAndroid Build Coastguard Worker
232*bebae9c0SAndroid Build Coastguard Worker /* Play the URI */
233*bebae9c0SAndroid Build Coastguard Worker /* first cause the player to prefetch the data */
234*bebae9c0SAndroid Build Coastguard Worker res = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PAUSED );
235*bebae9c0SAndroid Build Coastguard Worker CheckErr(res);
236*bebae9c0SAndroid Build Coastguard Worker
237*bebae9c0SAndroid Build Coastguard Worker // wait for prefetch status callback to indicate either sufficient data or error
238*bebae9c0SAndroid Build Coastguard Worker pthread_mutex_lock(&mutex);
239*bebae9c0SAndroid Build Coastguard Worker while (prefetch_status == SL_PREFETCHSTATUS_UNKNOWN) {
240*bebae9c0SAndroid Build Coastguard Worker pthread_cond_wait(&cond, &mutex);
241*bebae9c0SAndroid Build Coastguard Worker }
242*bebae9c0SAndroid Build Coastguard Worker pthread_mutex_unlock(&mutex);
243*bebae9c0SAndroid Build Coastguard Worker if (prefetch_status == SL_PREFETCHSTATUS_ERROR) {
244*bebae9c0SAndroid Build Coastguard Worker fprintf(stderr, "Error during prefetch, exiting\n");
245*bebae9c0SAndroid Build Coastguard Worker goto destroyRes;
246*bebae9c0SAndroid Build Coastguard Worker }
247*bebae9c0SAndroid Build Coastguard Worker
248*bebae9c0SAndroid Build Coastguard Worker /* Display duration again, */
249*bebae9c0SAndroid Build Coastguard Worker res = (*playItf)->GetDuration(playItf, &durationInMsec);
250*bebae9c0SAndroid Build Coastguard Worker CheckErr(res);
251*bebae9c0SAndroid Build Coastguard Worker if (durationInMsec == SL_TIME_UNKNOWN) {
252*bebae9c0SAndroid Build Coastguard Worker fprintf(stdout, "Content duration is unknown (after prefetch completed)\n");
253*bebae9c0SAndroid Build Coastguard Worker } else {
254*bebae9c0SAndroid Build Coastguard Worker fprintf(stdout, "Content duration is %u ms (after prefetch completed)\n", durationInMsec);
255*bebae9c0SAndroid Build Coastguard Worker }
256*bebae9c0SAndroid Build Coastguard Worker
257*bebae9c0SAndroid Build Coastguard Worker /* Start playing */
258*bebae9c0SAndroid Build Coastguard Worker fprintf(stdout, "starting to play\n");
259*bebae9c0SAndroid Build Coastguard Worker res = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PLAYING );
260*bebae9c0SAndroid Build Coastguard Worker CheckErr(res);
261*bebae9c0SAndroid Build Coastguard Worker
262*bebae9c0SAndroid Build Coastguard Worker /* Wait as long as the duration of the content, times the repetitions,
263*bebae9c0SAndroid Build Coastguard Worker * before stopping the loop */
264*bebae9c0SAndroid Build Coastguard Worker usleep( (REPETITIONS-1) * durationInMsec * 1100);
265*bebae9c0SAndroid Build Coastguard Worker res = (*seekItf)->SetLoop(seekItf, SL_BOOLEAN_FALSE, 0, SL_TIME_UNKNOWN);
266*bebae9c0SAndroid Build Coastguard Worker CheckErr(res);
267*bebae9c0SAndroid Build Coastguard Worker fprintf(stdout, "As of now, stopped looping (sound shouldn't repeat from now on)\n");
268*bebae9c0SAndroid Build Coastguard Worker /* wait some more to make sure it doesn't repeat */
269*bebae9c0SAndroid Build Coastguard Worker usleep(durationInMsec * 1000);
270*bebae9c0SAndroid Build Coastguard Worker
271*bebae9c0SAndroid Build Coastguard Worker /* Stop playback */
272*bebae9c0SAndroid Build Coastguard Worker fprintf(stdout, "stopping playback\n");
273*bebae9c0SAndroid Build Coastguard Worker res = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED);
274*bebae9c0SAndroid Build Coastguard Worker CheckErr(res);
275*bebae9c0SAndroid Build Coastguard Worker
276*bebae9c0SAndroid Build Coastguard Worker destroyRes:
277*bebae9c0SAndroid Build Coastguard Worker
278*bebae9c0SAndroid Build Coastguard Worker /* Destroy the player */
279*bebae9c0SAndroid Build Coastguard Worker (*player)->Destroy(player);
280*bebae9c0SAndroid Build Coastguard Worker
281*bebae9c0SAndroid Build Coastguard Worker /* Destroy Output Mix object */
282*bebae9c0SAndroid Build Coastguard Worker (*OutputMix)->Destroy(OutputMix);
283*bebae9c0SAndroid Build Coastguard Worker }
284*bebae9c0SAndroid Build Coastguard Worker
285*bebae9c0SAndroid Build Coastguard Worker //-----------------------------------------------------------------
main(int argc,char * const argv[])286*bebae9c0SAndroid Build Coastguard Worker int main(int argc, char* const argv[])
287*bebae9c0SAndroid Build Coastguard Worker {
288*bebae9c0SAndroid Build Coastguard Worker SLresult res;
289*bebae9c0SAndroid Build Coastguard Worker SLObjectItf sl;
290*bebae9c0SAndroid Build Coastguard Worker
291*bebae9c0SAndroid Build Coastguard Worker fprintf(stdout, "OpenSL ES test %s: exercises SLPlayItf, SLSeekItf ", argv[0]);
292*bebae9c0SAndroid Build Coastguard Worker fprintf(stdout, "and AudioPlayer with SLDataLocator_URI source / OutputMix sink\n");
293*bebae9c0SAndroid Build Coastguard Worker fprintf(stdout, "Plays a sound and loops it %d times.\n\n", REPETITIONS);
294*bebae9c0SAndroid Build Coastguard Worker
295*bebae9c0SAndroid Build Coastguard Worker if (argc == 1) {
296*bebae9c0SAndroid Build Coastguard Worker fprintf(stdout, "Usage: \n\t%s path \n\t%s url\n", argv[0], argv[0]);
297*bebae9c0SAndroid Build Coastguard Worker fprintf(stdout, "Example: \"%s /sdcard/my.mp3\" or \"%s file:///sdcard/my.mp3\"\n",
298*bebae9c0SAndroid Build Coastguard Worker argv[0], argv[0]);
299*bebae9c0SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
300*bebae9c0SAndroid Build Coastguard Worker }
301*bebae9c0SAndroid Build Coastguard Worker
302*bebae9c0SAndroid Build Coastguard Worker SLEngineOption EngineOption[] = {
303*bebae9c0SAndroid Build Coastguard Worker {(SLuint32) SL_ENGINEOPTION_THREADSAFE,
304*bebae9c0SAndroid Build Coastguard Worker (SLuint32) SL_BOOLEAN_TRUE}};
305*bebae9c0SAndroid Build Coastguard Worker
306*bebae9c0SAndroid Build Coastguard Worker res = slCreateEngine( &sl, 1, EngineOption, 0, NULL, NULL);
307*bebae9c0SAndroid Build Coastguard Worker CheckErr(res);
308*bebae9c0SAndroid Build Coastguard Worker /* Realizing the SL Engine in synchronous mode. */
309*bebae9c0SAndroid Build Coastguard Worker res = (*sl)->Realize(sl, SL_BOOLEAN_FALSE);
310*bebae9c0SAndroid Build Coastguard Worker CheckErr(res);
311*bebae9c0SAndroid Build Coastguard Worker
312*bebae9c0SAndroid Build Coastguard Worker TestLoopUri(sl, argv[1]);
313*bebae9c0SAndroid Build Coastguard Worker
314*bebae9c0SAndroid Build Coastguard Worker /* Shutdown OpenSL ES */
315*bebae9c0SAndroid Build Coastguard Worker (*sl)->Destroy(sl);
316*bebae9c0SAndroid Build Coastguard Worker
317*bebae9c0SAndroid Build Coastguard Worker return EXIT_SUCCESS;
318*bebae9c0SAndroid Build Coastguard Worker }
319