xref: /aosp_15_r20/frameworks/wilhelm/tests/mimeUri/slesTestLoopUri.cpp (revision bebae9c0e76121f8312ccb50385c080b3a0b023c)
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