xref: /aosp_15_r20/frameworks/wilhelm/tests/sandbox/multiplay.c (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 // multiplay is a command-line test app that plays multiple files randomly
18*bebae9c0SAndroid Build Coastguard Worker 
19*bebae9c0SAndroid Build Coastguard Worker #include <SLES/OpenSLES.h>
20*bebae9c0SAndroid Build Coastguard Worker #include <assert.h>
21*bebae9c0SAndroid Build Coastguard Worker #include <string.h>
22*bebae9c0SAndroid Build Coastguard Worker #include <stdlib.h>
23*bebae9c0SAndroid Build Coastguard Worker #include <stdio.h>
24*bebae9c0SAndroid Build Coastguard Worker #include <unistd.h>
25*bebae9c0SAndroid Build Coastguard Worker 
26*bebae9c0SAndroid Build Coastguard Worker // Describes the state of one player
27*bebae9c0SAndroid Build Coastguard Worker 
28*bebae9c0SAndroid Build Coastguard Worker typedef struct {
29*bebae9c0SAndroid Build Coastguard Worker     SLObjectItf mPlayerObject;
30*bebae9c0SAndroid Build Coastguard Worker     SLPlayItf mPlayerPlay;
31*bebae9c0SAndroid Build Coastguard Worker     SLSeekItf mPlayerSeek;
32*bebae9c0SAndroid Build Coastguard Worker     SLPrefetchStatusItf mPlayerPrefetchStatus;
33*bebae9c0SAndroid Build Coastguard Worker     SLVolumeItf mPlayerVolume;
34*bebae9c0SAndroid Build Coastguard Worker     SLmillisecond mPlayerDuration;
35*bebae9c0SAndroid Build Coastguard Worker     SLboolean mPlayerErrorInCallback;
36*bebae9c0SAndroid Build Coastguard Worker     SLboolean mPlayerErrorReported;
37*bebae9c0SAndroid Build Coastguard Worker } Player;
38*bebae9c0SAndroid Build Coastguard Worker 
39*bebae9c0SAndroid Build Coastguard Worker // Strings corresponding to result codes; FIXME should move to a common test library
40*bebae9c0SAndroid Build Coastguard Worker 
41*bebae9c0SAndroid Build Coastguard Worker static const char *result_strings[] = {
42*bebae9c0SAndroid Build Coastguard Worker     "SUCCESS",
43*bebae9c0SAndroid Build Coastguard Worker     "PRECONDITIONS_VIOLATED",
44*bebae9c0SAndroid Build Coastguard Worker     "PARAMETER_INVALID",
45*bebae9c0SAndroid Build Coastguard Worker     "MEMORY_FAILURE",
46*bebae9c0SAndroid Build Coastguard Worker     "RESOURCE_ERROR",
47*bebae9c0SAndroid Build Coastguard Worker     "RESOURCE_LOST",
48*bebae9c0SAndroid Build Coastguard Worker     "IO_ERROR",
49*bebae9c0SAndroid Build Coastguard Worker     "BUFFER_INSUFFICIENT",
50*bebae9c0SAndroid Build Coastguard Worker     "CONTENT_CORRUPTED",
51*bebae9c0SAndroid Build Coastguard Worker     "CONTENT_UNSUPPORTED",
52*bebae9c0SAndroid Build Coastguard Worker     "CONTENT_NOT_FOUND",
53*bebae9c0SAndroid Build Coastguard Worker     "PERMISSION_DENIED",
54*bebae9c0SAndroid Build Coastguard Worker     "FEATURE_UNSUPPORTED",
55*bebae9c0SAndroid Build Coastguard Worker     "INTERNAL_ERROR",
56*bebae9c0SAndroid Build Coastguard Worker     "UNKNOWN_ERROR",
57*bebae9c0SAndroid Build Coastguard Worker     "OPERATION_ABORTED",
58*bebae9c0SAndroid Build Coastguard Worker     "CONTROL_LOST"
59*bebae9c0SAndroid Build Coastguard Worker };
60*bebae9c0SAndroid Build Coastguard Worker 
61*bebae9c0SAndroid Build Coastguard Worker // Convert result to string; FIXME should move to common test library
62*bebae9c0SAndroid Build Coastguard Worker 
result_to_string(SLresult result)63*bebae9c0SAndroid Build Coastguard Worker static const char *result_to_string(SLresult result)
64*bebae9c0SAndroid Build Coastguard Worker {
65*bebae9c0SAndroid Build Coastguard Worker     static char buffer[32];
66*bebae9c0SAndroid Build Coastguard Worker     if ( /* result >= 0 && */ result < sizeof(result_strings) / sizeof(result_strings[0]))
67*bebae9c0SAndroid Build Coastguard Worker         return result_strings[result];
68*bebae9c0SAndroid Build Coastguard Worker     sprintf(buffer, "%d", (int) result);
69*bebae9c0SAndroid Build Coastguard Worker     return buffer;
70*bebae9c0SAndroid Build Coastguard Worker }
71*bebae9c0SAndroid Build Coastguard Worker 
72*bebae9c0SAndroid Build Coastguard Worker // Compare result against expected and exit suddenly if wrong
73*bebae9c0SAndroid Build Coastguard Worker 
check2(SLresult result,int line)74*bebae9c0SAndroid Build Coastguard Worker void check2(SLresult result, int line)
75*bebae9c0SAndroid Build Coastguard Worker {
76*bebae9c0SAndroid Build Coastguard Worker     if (SL_RESULT_SUCCESS != result) {
77*bebae9c0SAndroid Build Coastguard Worker         fprintf(stderr, "error %s at line %d\n", result_to_string(result), line);
78*bebae9c0SAndroid Build Coastguard Worker         exit(EXIT_FAILURE);
79*bebae9c0SAndroid Build Coastguard Worker     }
80*bebae9c0SAndroid Build Coastguard Worker }
81*bebae9c0SAndroid Build Coastguard Worker 
82*bebae9c0SAndroid Build Coastguard Worker // Same as above but automatically adds the source code line number
83*bebae9c0SAndroid Build Coastguard Worker 
84*bebae9c0SAndroid Build Coastguard Worker #define check(result) check2(result, __LINE__)
85*bebae9c0SAndroid Build Coastguard Worker 
86*bebae9c0SAndroid Build Coastguard Worker // Prefetch status callback
87*bebae9c0SAndroid Build Coastguard Worker 
88*bebae9c0SAndroid Build Coastguard Worker #define PREFETCHEVENT_ERROR_CANDIDATE \
89*bebae9c0SAndroid Build Coastguard Worker             (SL_PREFETCHEVENT_STATUSCHANGE | SL_PREFETCHEVENT_FILLLEVELCHANGE)
90*bebae9c0SAndroid Build Coastguard Worker 
prefetch_callback(SLPrefetchStatusItf caller,void * context,SLuint32 event)91*bebae9c0SAndroid Build Coastguard Worker void prefetch_callback(SLPrefetchStatusItf caller, void *context, SLuint32 event)
92*bebae9c0SAndroid Build Coastguard Worker {
93*bebae9c0SAndroid Build Coastguard Worker     SLresult result;
94*bebae9c0SAndroid Build Coastguard Worker     assert(context != NULL);
95*bebae9c0SAndroid Build Coastguard Worker     Player *p = (Player *) context;
96*bebae9c0SAndroid Build Coastguard Worker     assert(p->mPlayerPrefetchStatus == caller);
97*bebae9c0SAndroid Build Coastguard Worker     SLpermille level;
98*bebae9c0SAndroid Build Coastguard Worker     result = (*caller)->GetFillLevel(caller, &level);
99*bebae9c0SAndroid Build Coastguard Worker     check(result);
100*bebae9c0SAndroid Build Coastguard Worker     SLuint32 status;
101*bebae9c0SAndroid Build Coastguard Worker     result = (*caller)->GetPrefetchStatus(caller, &status);
102*bebae9c0SAndroid Build Coastguard Worker     check(result);
103*bebae9c0SAndroid Build Coastguard Worker     //fprintf(stderr, "PrefetchEventCallback: received event %u, level %u, status %u\n",
104*bebae9c0SAndroid Build Coastguard Worker     //      event, level, status);
105*bebae9c0SAndroid Build Coastguard Worker     if ((PREFETCHEVENT_ERROR_CANDIDATE == (event & PREFETCHEVENT_ERROR_CANDIDATE))
106*bebae9c0SAndroid Build Coastguard Worker             && (level == 0) && (status == SL_PREFETCHSTATUS_UNDERFLOW)) {
107*bebae9c0SAndroid Build Coastguard Worker         p->mPlayerErrorInCallback = SL_BOOLEAN_TRUE;
108*bebae9c0SAndroid Build Coastguard Worker     }
109*bebae9c0SAndroid Build Coastguard Worker }
110*bebae9c0SAndroid Build Coastguard Worker 
111*bebae9c0SAndroid Build Coastguard Worker // Main program
112*bebae9c0SAndroid Build Coastguard Worker 
main(int argc,char ** argv)113*bebae9c0SAndroid Build Coastguard Worker int main(int argc, char **argv)
114*bebae9c0SAndroid Build Coastguard Worker {
115*bebae9c0SAndroid Build Coastguard Worker     int i;
116*bebae9c0SAndroid Build Coastguard Worker     const char *arg;
117*bebae9c0SAndroid Build Coastguard Worker     int numPlayers = 0;
118*bebae9c0SAndroid Build Coastguard Worker     int playTimeInMilliseconds = 0; // default to run forever
119*bebae9c0SAndroid Build Coastguard Worker     SLmillibel mixVolumeLevel = 0;
120*bebae9c0SAndroid Build Coastguard Worker     for (i = 1; i < argc; ++i) {
121*bebae9c0SAndroid Build Coastguard Worker         arg = argv[i];
122*bebae9c0SAndroid Build Coastguard Worker         if (arg[0] != '-')
123*bebae9c0SAndroid Build Coastguard Worker             break;
124*bebae9c0SAndroid Build Coastguard Worker         if (!strncmp(arg, "-n", 2))
125*bebae9c0SAndroid Build Coastguard Worker             numPlayers = atoi(&arg[2]);
126*bebae9c0SAndroid Build Coastguard Worker         else if (!strncmp(arg, "-v", 2))
127*bebae9c0SAndroid Build Coastguard Worker             mixVolumeLevel = atoi(&arg[2]);
128*bebae9c0SAndroid Build Coastguard Worker         else if (!strncmp(arg, "-t", 2))
129*bebae9c0SAndroid Build Coastguard Worker             playTimeInMilliseconds = atoi(&arg[2]) * 1000;
130*bebae9c0SAndroid Build Coastguard Worker         else
131*bebae9c0SAndroid Build Coastguard Worker             fprintf(stderr, "unknown option: %s\n", arg);
132*bebae9c0SAndroid Build Coastguard Worker     }
133*bebae9c0SAndroid Build Coastguard Worker     int numPathnames = argc - i;
134*bebae9c0SAndroid Build Coastguard Worker     if (numPathnames <= 0) {
135*bebae9c0SAndroid Build Coastguard Worker         fprintf(stderr, "usage: %s file.wav ...\n", argv[0]);
136*bebae9c0SAndroid Build Coastguard Worker         return EXIT_FAILURE;
137*bebae9c0SAndroid Build Coastguard Worker     }
138*bebae9c0SAndroid Build Coastguard Worker     if (numPlayers <= 0) {
139*bebae9c0SAndroid Build Coastguard Worker         numPlayers = numPathnames;
140*bebae9c0SAndroid Build Coastguard Worker     }
141*bebae9c0SAndroid Build Coastguard Worker     Player *players = (Player *) calloc(numPlayers, sizeof(Player));
142*bebae9c0SAndroid Build Coastguard Worker     assert(NULL != players);
143*bebae9c0SAndroid Build Coastguard Worker     char **pathnames = &argv[i];
144*bebae9c0SAndroid Build Coastguard Worker     SLresult result;
145*bebae9c0SAndroid Build Coastguard Worker 
146*bebae9c0SAndroid Build Coastguard Worker     // engine
147*bebae9c0SAndroid Build Coastguard Worker     const SLInterfaceID engine_ids[] = {SL_IID_ENGINE};
148*bebae9c0SAndroid Build Coastguard Worker     const SLboolean engine_req[] = {SL_BOOLEAN_TRUE};
149*bebae9c0SAndroid Build Coastguard Worker     SLObjectItf engineObject;
150*bebae9c0SAndroid Build Coastguard Worker     result = slCreateEngine(&engineObject, 0, NULL, 1, engine_ids, engine_req);
151*bebae9c0SAndroid Build Coastguard Worker     check(result);
152*bebae9c0SAndroid Build Coastguard Worker     result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
153*bebae9c0SAndroid Build Coastguard Worker     check(result);
154*bebae9c0SAndroid Build Coastguard Worker     SLEngineItf engineEngine;
155*bebae9c0SAndroid Build Coastguard Worker     result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
156*bebae9c0SAndroid Build Coastguard Worker     check(result);
157*bebae9c0SAndroid Build Coastguard Worker 
158*bebae9c0SAndroid Build Coastguard Worker     // mixer
159*bebae9c0SAndroid Build Coastguard Worker     const SLInterfaceID mix_ids[] = {SL_IID_VOLUME};
160*bebae9c0SAndroid Build Coastguard Worker     const SLboolean mix_req[] = {SL_BOOLEAN_TRUE};
161*bebae9c0SAndroid Build Coastguard Worker     SLObjectItf mixObject;
162*bebae9c0SAndroid Build Coastguard Worker     result = (*engineEngine)->CreateOutputMix(engineEngine, &mixObject, 0, mix_ids, mix_req);
163*bebae9c0SAndroid Build Coastguard Worker     check(result);
164*bebae9c0SAndroid Build Coastguard Worker     result = (*mixObject)->Realize(mixObject, SL_BOOLEAN_FALSE);
165*bebae9c0SAndroid Build Coastguard Worker     check(result);
166*bebae9c0SAndroid Build Coastguard Worker #if 0
167*bebae9c0SAndroid Build Coastguard Worker     SLVolumeItf mixVolume;
168*bebae9c0SAndroid Build Coastguard Worker     result = (*mixObject)->GetInterface(mixObject, SL_IID_VOLUME, &mixVolume);
169*bebae9c0SAndroid Build Coastguard Worker     check(result);
170*bebae9c0SAndroid Build Coastguard Worker     SLmillibel mixVolumeLevelDefault;
171*bebae9c0SAndroid Build Coastguard Worker     result = (*mixVolume)->GetVolumeLevel(mixVolume, &mixVolumeLevelDefault);
172*bebae9c0SAndroid Build Coastguard Worker     check(result);
173*bebae9c0SAndroid Build Coastguard Worker     printf("default mix volume level = %d\n", mixVolumeLevelDefault);
174*bebae9c0SAndroid Build Coastguard Worker #endif
175*bebae9c0SAndroid Build Coastguard Worker 
176*bebae9c0SAndroid Build Coastguard Worker     printf("numPathnames=%d\n", numPathnames);
177*bebae9c0SAndroid Build Coastguard Worker     printf("numPlayers=%d\n", numPlayers);
178*bebae9c0SAndroid Build Coastguard Worker     Player *p;
179*bebae9c0SAndroid Build Coastguard Worker 
180*bebae9c0SAndroid Build Coastguard Worker     // create all the players
181*bebae9c0SAndroid Build Coastguard Worker     for (i = 0; i < numPlayers; ++i) {
182*bebae9c0SAndroid Build Coastguard Worker         const SLInterfaceID player_ids[] =
183*bebae9c0SAndroid Build Coastguard Worker                 {SL_IID_PLAY, SL_IID_VOLUME, SL_IID_SEEK, SL_IID_PREFETCHSTATUS};
184*bebae9c0SAndroid Build Coastguard Worker         const SLboolean player_req[] =
185*bebae9c0SAndroid Build Coastguard Worker                 {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
186*bebae9c0SAndroid Build Coastguard Worker         p = &players[i];
187*bebae9c0SAndroid Build Coastguard Worker         SLDataLocator_URI locURI = {SL_DATALOCATOR_URI, (SLchar *) pathnames[i % numPathnames]};
188*bebae9c0SAndroid Build Coastguard Worker         SLDataFormat_MIME dfMIME = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED};
189*bebae9c0SAndroid Build Coastguard Worker         SLDataSource audioSrc = {&locURI, &dfMIME};
190*bebae9c0SAndroid Build Coastguard Worker         SLDataLocator_OutputMix locOutputMix = {SL_DATALOCATOR_OUTPUTMIX, mixObject};
191*bebae9c0SAndroid Build Coastguard Worker         SLDataSink audioSnk = {&locOutputMix, NULL};
192*bebae9c0SAndroid Build Coastguard Worker         result = (*engineEngine)->CreateAudioPlayer(engineEngine, &p->mPlayerObject, &audioSrc,
193*bebae9c0SAndroid Build Coastguard Worker             &audioSnk, sizeof(player_ids)/sizeof(player_ids[0]), player_ids, player_req);
194*bebae9c0SAndroid Build Coastguard Worker         check(result);
195*bebae9c0SAndroid Build Coastguard Worker         result = (*p->mPlayerObject)->Realize(p->mPlayerObject, SL_BOOLEAN_FALSE);
196*bebae9c0SAndroid Build Coastguard Worker         check(result);
197*bebae9c0SAndroid Build Coastguard Worker         result = (*p->mPlayerObject)->GetInterface(p->mPlayerObject, SL_IID_PLAY, &p->mPlayerPlay);
198*bebae9c0SAndroid Build Coastguard Worker         check(result);
199*bebae9c0SAndroid Build Coastguard Worker         result = (*p->mPlayerObject)->GetInterface(p->mPlayerObject, SL_IID_VOLUME,
200*bebae9c0SAndroid Build Coastguard Worker             &p->mPlayerVolume);
201*bebae9c0SAndroid Build Coastguard Worker         check(result);
202*bebae9c0SAndroid Build Coastguard Worker         result = (*p->mPlayerObject)->GetInterface(p->mPlayerObject, SL_IID_SEEK, &p->mPlayerSeek);
203*bebae9c0SAndroid Build Coastguard Worker         check(result);
204*bebae9c0SAndroid Build Coastguard Worker         result = (*p->mPlayerObject)->GetInterface(p->mPlayerObject, SL_IID_PREFETCHSTATUS,
205*bebae9c0SAndroid Build Coastguard Worker                 &p->mPlayerPrefetchStatus);
206*bebae9c0SAndroid Build Coastguard Worker         check(result);
207*bebae9c0SAndroid Build Coastguard Worker         result = (*p->mPlayerPrefetchStatus)->RegisterCallback(p->mPlayerPrefetchStatus,
208*bebae9c0SAndroid Build Coastguard Worker                 prefetch_callback, p);
209*bebae9c0SAndroid Build Coastguard Worker         check(result);
210*bebae9c0SAndroid Build Coastguard Worker         result = (*p->mPlayerPrefetchStatus)->SetCallbackEventsMask(p->mPlayerPrefetchStatus,
211*bebae9c0SAndroid Build Coastguard Worker                 SL_PREFETCHEVENT_STATUSCHANGE | SL_PREFETCHEVENT_FILLLEVELCHANGE);
212*bebae9c0SAndroid Build Coastguard Worker         check(result);
213*bebae9c0SAndroid Build Coastguard Worker     }
214*bebae9c0SAndroid Build Coastguard Worker 
215*bebae9c0SAndroid Build Coastguard Worker     // now loop randomly doing things to the players
216*bebae9c0SAndroid Build Coastguard Worker     for (;;) {
217*bebae9c0SAndroid Build Coastguard Worker         SLmillisecond delay = 100 + (rand() & 1023);
218*bebae9c0SAndroid Build Coastguard Worker         printf("sleep %u\n", (unsigned) delay);
219*bebae9c0SAndroid Build Coastguard Worker         usleep(delay * 1000);
220*bebae9c0SAndroid Build Coastguard Worker         i = (rand() & 0x7FFFFFFF) % numPlayers;
221*bebae9c0SAndroid Build Coastguard Worker         p = &players[i];
222*bebae9c0SAndroid Build Coastguard Worker         if (p->mPlayerErrorReported)
223*bebae9c0SAndroid Build Coastguard Worker             continue;
224*bebae9c0SAndroid Build Coastguard Worker         printf("player %d (%s): ", i, pathnames[i]);
225*bebae9c0SAndroid Build Coastguard Worker         if (p->mPlayerErrorInCallback && !p->mPlayerErrorReported) {
226*bebae9c0SAndroid Build Coastguard Worker             printf("error, ");
227*bebae9c0SAndroid Build Coastguard Worker             p->mPlayerErrorReported = SL_BOOLEAN_TRUE;
228*bebae9c0SAndroid Build Coastguard Worker         }
229*bebae9c0SAndroid Build Coastguard Worker         result = (*p->mPlayerPlay)->GetDuration(p->mPlayerPlay, &p->mPlayerDuration);
230*bebae9c0SAndroid Build Coastguard Worker         check(result);
231*bebae9c0SAndroid Build Coastguard Worker         if (p->mPlayerDuration == SL_TIME_UNKNOWN) {
232*bebae9c0SAndroid Build Coastguard Worker             printf("duration unknown, ");
233*bebae9c0SAndroid Build Coastguard Worker         } else {
234*bebae9c0SAndroid Build Coastguard Worker             printf("duration %d ms, ", (int) p->mPlayerDuration);
235*bebae9c0SAndroid Build Coastguard Worker         }
236*bebae9c0SAndroid Build Coastguard Worker         SLuint32 state;
237*bebae9c0SAndroid Build Coastguard Worker         result = (*p->mPlayerPlay)->GetPlayState(p->mPlayerPlay, &state);
238*bebae9c0SAndroid Build Coastguard Worker         check(result);
239*bebae9c0SAndroid Build Coastguard Worker         printf("state = ");
240*bebae9c0SAndroid Build Coastguard Worker         switch (state) {
241*bebae9c0SAndroid Build Coastguard Worker         case SL_PLAYSTATE_STOPPED:
242*bebae9c0SAndroid Build Coastguard Worker             printf("STOPPED");
243*bebae9c0SAndroid Build Coastguard Worker             break;
244*bebae9c0SAndroid Build Coastguard Worker         case SL_PLAYSTATE_PAUSED:
245*bebae9c0SAndroid Build Coastguard Worker             printf("PAUSED");
246*bebae9c0SAndroid Build Coastguard Worker             break;
247*bebae9c0SAndroid Build Coastguard Worker         case SL_PLAYSTATE_PLAYING:
248*bebae9c0SAndroid Build Coastguard Worker             printf("PLAYING");
249*bebae9c0SAndroid Build Coastguard Worker             break;
250*bebae9c0SAndroid Build Coastguard Worker         default:
251*bebae9c0SAndroid Build Coastguard Worker             printf("%u", (unsigned) state);
252*bebae9c0SAndroid Build Coastguard Worker             break;
253*bebae9c0SAndroid Build Coastguard Worker         }
254*bebae9c0SAndroid Build Coastguard Worker         printf("\n");
255*bebae9c0SAndroid Build Coastguard Worker         if (state == SL_PLAYSTATE_STOPPED || state == SL_PLAYSTATE_PAUSED) {
256*bebae9c0SAndroid Build Coastguard Worker             SLmillibel volumeLevel = -((rand() & 0x7FFFFFFF) % ((SL_MILLIBEL_MIN + 1) / 10));
257*bebae9c0SAndroid Build Coastguard Worker             printf("volume %d\n", volumeLevel);
258*bebae9c0SAndroid Build Coastguard Worker             result = (*p->mPlayerVolume)->SetVolumeLevel(p->mPlayerVolume, volumeLevel);
259*bebae9c0SAndroid Build Coastguard Worker             check(result);
260*bebae9c0SAndroid Build Coastguard Worker             result = (*p->mPlayerVolume)->EnableStereoPosition(p->mPlayerVolume, SL_BOOLEAN_TRUE);
261*bebae9c0SAndroid Build Coastguard Worker             check(result);
262*bebae9c0SAndroid Build Coastguard Worker             SLpermille stereoPosition = ((rand() & 0x7FFFFFFF) % 2001) - 1000;
263*bebae9c0SAndroid Build Coastguard Worker             printf("position %d\n", stereoPosition);
264*bebae9c0SAndroid Build Coastguard Worker             result = (*p->mPlayerVolume)->SetStereoPosition(p->mPlayerVolume, stereoPosition);
265*bebae9c0SAndroid Build Coastguard Worker             check(result);
266*bebae9c0SAndroid Build Coastguard Worker             if (state != SL_PLAYSTATE_STOPPED) {
267*bebae9c0SAndroid Build Coastguard Worker                 result = (*p->mPlayerSeek)->SetPosition(p->mPlayerSeek, 0, SL_SEEKMODE_FAST);
268*bebae9c0SAndroid Build Coastguard Worker                 check(result);
269*bebae9c0SAndroid Build Coastguard Worker             }
270*bebae9c0SAndroid Build Coastguard Worker             result = (*p->mPlayerPlay)->SetPlayState(p->mPlayerPlay, SL_PLAYSTATE_PLAYING);
271*bebae9c0SAndroid Build Coastguard Worker             check(result);
272*bebae9c0SAndroid Build Coastguard Worker         }
273*bebae9c0SAndroid Build Coastguard Worker         if ((playTimeInMilliseconds > 0) && ((playTimeInMilliseconds -= delay) < 0))
274*bebae9c0SAndroid Build Coastguard Worker             break;
275*bebae9c0SAndroid Build Coastguard Worker     }
276*bebae9c0SAndroid Build Coastguard Worker 
277*bebae9c0SAndroid Build Coastguard Worker     for (i = 0; i < numPlayers; ++i) {
278*bebae9c0SAndroid Build Coastguard Worker         SLObjectItf playerObject = players[i].mPlayerObject;
279*bebae9c0SAndroid Build Coastguard Worker         (*playerObject)->Destroy(playerObject);
280*bebae9c0SAndroid Build Coastguard Worker     }
281*bebae9c0SAndroid Build Coastguard Worker     (*mixObject)->Destroy(mixObject);
282*bebae9c0SAndroid Build Coastguard Worker     (*engineObject)->Destroy(engineObject);
283*bebae9c0SAndroid Build Coastguard Worker 
284*bebae9c0SAndroid Build Coastguard Worker     return EXIT_SUCCESS;
285*bebae9c0SAndroid Build Coastguard Worker }
286