1 /*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 // single-threaded, single-player monkey test
18
19 #include <SLES/OpenSLES.h>
20 #include <assert.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25
26 typedef enum {
27 STATE_UNCHANGED,
28 STATE_INITIAL,
29 STATE_NONEXISTENT,
30 STATE_CREATED,
31 STATE_REALIZED,
32 STATE_PAUSED,
33 STATE_PLAYING,
34 STATE_STOPPED,
35 STATE_ERROR,
36 // STATE_IDLE, // after Stop, then sleep for 3 seconds
37 STATE_TERMINAL
38 } State_t;
39
40 typedef struct {
41 SLObjectItf mObject;
42 SLPlayItf mPlay;
43 SLSeekItf mSeek;
44 } Player_t, *Player_pt;
45
46 typedef State_t (*Action_pt)(Player_pt player);
47
48 SLObjectItf engineObject;
49 SLEngineItf engineEngine;
50 SLObjectItf outputMixObject;
51 int countTransitions = 0;
52 int maxTransitions = 10;
53
actionPause(Player_pt p)54 State_t actionPause(Player_pt p)
55 {
56 assert(NULL != p->mPlay);
57 SLresult result = (*p->mPlay)->SetPlayState(p->mPlay, SL_PLAYSTATE_PAUSED);
58 assert(SL_RESULT_SUCCESS == result);
59 return STATE_PAUSED;
60 }
61
actionPlay(Player_pt p)62 State_t actionPlay(Player_pt p)
63 {
64 assert(NULL != p->mPlay);
65 SLresult result = (*p->mPlay)->SetPlayState(p->mPlay, SL_PLAYSTATE_PLAYING);
66 assert(SL_RESULT_SUCCESS == result);
67 return STATE_PLAYING;
68 }
69
actionStop(Player_pt p)70 State_t actionStop(Player_pt p)
71 {
72 assert(NULL != p->mPlay);
73 SLresult result = (*p->mPlay)->SetPlayState(p->mPlay, SL_PLAYSTATE_STOPPED);
74 assert(SL_RESULT_SUCCESS == result);
75 return STATE_STOPPED;
76 }
77
actionRewind(Player_pt p)78 State_t actionRewind(Player_pt p)
79 {
80 assert(NULL != p->mSeek);
81 SLresult result = (*p->mSeek)->SetPosition(p->mSeek, (SLmillisecond) 0, SL_SEEKMODE_FAST);
82 assert(SL_RESULT_SUCCESS == result);
83 return STATE_UNCHANGED;
84 }
85
actionDestroy(Player_pt p)86 State_t actionDestroy(Player_pt p)
87 {
88 assert(NULL != p->mObject);
89 (*p->mObject)->Destroy(p->mObject);
90 p->mObject = NULL;
91 p->mPlay = NULL;
92 p->mSeek = NULL;
93 return STATE_NONEXISTENT;
94 }
95
actionCreate(Player_pt p)96 State_t actionCreate(Player_pt p)
97 {
98 // configure audio source
99 SLDataLocator_URI loc_uri;
100 loc_uri.locatorType = SL_DATALOCATOR_URI;
101 loc_uri.URI = (SLchar *) "wav/frog.wav";
102 SLDataFormat_MIME format_mime;
103 format_mime.formatType = SL_DATAFORMAT_MIME;
104 format_mime.mimeType = NULL;
105 format_mime.containerType = SL_CONTAINERTYPE_UNSPECIFIED;
106 SLDataSource audioSrc;
107 audioSrc.pLocator = &loc_uri;
108 audioSrc.pFormat = &format_mime;
109 // configure audio sink
110 SLDataLocator_OutputMix loc_outmix;
111 loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
112 loc_outmix.outputMix = outputMixObject;
113 SLDataSink audioSnk;
114 audioSnk.pLocator = &loc_outmix;
115 audioSnk.pFormat = NULL;
116 // create audio player
117 SLInterfaceID ids[1] = {SL_IID_SEEK};
118 SLboolean req[1] = {SL_BOOLEAN_TRUE};
119 SLresult result = (*engineEngine)->CreateAudioPlayer(engineEngine, &p->mObject, &audioSrc,
120 &audioSnk, 1, ids, req);
121 if (SL_RESULT_SUCCESS != result)
122 return STATE_ERROR;
123 return STATE_CREATED;
124 }
125
actionRealize(Player_pt p)126 State_t actionRealize(Player_pt p)
127 {
128 assert(NULL != p->mObject);
129 // realize the player
130 SLresult result = (*p->mObject)->Realize(p->mObject, SL_BOOLEAN_FALSE);
131 assert(SL_RESULT_SUCCESS == result);
132 // get interfaces
133 result = (*p->mObject)->GetInterface(p->mObject, SL_IID_PLAY, &p->mPlay);
134 assert(SL_RESULT_SUCCESS == result);
135 result = (*p->mObject)->GetInterface(p->mObject, SL_IID_SEEK, &p->mSeek);
136 assert(SL_RESULT_SUCCESS == result);
137 return STATE_REALIZED;
138 }
139
actionSleep(Player_pt p __unused)140 State_t actionSleep(Player_pt p __unused)
141 {
142 unsigned us = 1000 + (rand() & 0xFFFFF);
143 usleep(us);
144 return STATE_UNCHANGED;
145 }
146
147 #if 0
148 State_t actionSleep3(Player_pt p)
149 {
150 sleep(3);
151 return STATE_IDLE;
152 }
153 #endif
154
actionTerminateIfDone(Player_pt p)155 State_t actionTerminateIfDone(Player_pt p)
156 {
157 if (countTransitions >= maxTransitions) {
158 assert(NULL == p->mObject);
159 // clean up output mix and engine
160 assert(NULL != outputMixObject);
161 (*outputMixObject)->Destroy(outputMixObject);
162 outputMixObject = NULL;
163 assert(NULL != engineObject);
164 (*engineObject)->Destroy(engineObject);
165 engineObject = NULL;
166 return STATE_TERMINAL;
167 } else
168 return STATE_UNCHANGED;
169 }
170
actionInitialize(Player_pt p __unused)171 State_t actionInitialize(Player_pt p __unused)
172 {
173 // create engine
174 SLresult result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
175 assert(SL_RESULT_SUCCESS == result);
176 result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
177 assert(SL_RESULT_SUCCESS == result);
178 result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
179 assert(SL_RESULT_SUCCESS == result);
180
181 // create output mix
182 result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, NULL, NULL);
183 assert(SL_RESULT_SUCCESS == result);
184 result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
185 assert(SL_RESULT_SUCCESS == result);
186
187 return STATE_NONEXISTENT;
188 }
189
190 typedef struct {
191 State_t mEntryState;
192 Action_pt mAction;
193 unsigned mProbability;
194 const char *mActionName;
195 unsigned mCount;
196 } Transition_t;
197
198 Transition_t transitionTable[] = {
199 #define _(entryState, action, probability) {entryState, action, probability, #action, 0},
200 _(STATE_INITIAL, actionInitialize, 1)
201 _(STATE_CREATED, actionDestroy, 1)
202 _(STATE_CREATED, actionRealize, 1)
203 _(STATE_CREATED, actionSleep, 1)
204 _(STATE_NONEXISTENT, actionCreate, 1)
205 _(STATE_NONEXISTENT, actionSleep, 1)
206 _(STATE_PAUSED, actionDestroy, 1)
207 _(STATE_PAUSED, actionPause, 1)
208 _(STATE_PAUSED, actionPlay, 1)
209 _(STATE_PAUSED, actionRewind, 1)
210 _(STATE_PAUSED, actionSleep, 1)
211 _(STATE_PAUSED, actionStop, 1)
212 _(STATE_PLAYING, actionDestroy, 1)
213 _(STATE_PLAYING, actionPause, 1)
214 _(STATE_PLAYING, actionPlay, 1)
215 _(STATE_PLAYING, actionRewind, 1)
216 _(STATE_PLAYING, actionSleep, 1)
217 _(STATE_PLAYING, actionStop, 1)
218 _(STATE_REALIZED, actionDestroy, 1)
219 _(STATE_REALIZED, actionPause, 1)
220 _(STATE_REALIZED, actionPlay, 1)
221 _(STATE_REALIZED, actionSleep, 1)
222 _(STATE_REALIZED, actionStop, 1)
223 _(STATE_STOPPED, actionDestroy, 1)
224 _(STATE_STOPPED, actionPause, 1)
225 _(STATE_STOPPED, actionPlay, 1)
226 _(STATE_STOPPED, actionRewind, 1)
227 _(STATE_STOPPED, actionSleep, 1)
228 _(STATE_STOPPED, actionStop, 1)
229 // _(STATE_STOPPED, actionSleep3, 1)
230 // _(STATE_IDLE, actionDestroy, 1)
231 _(STATE_NONEXISTENT, actionTerminateIfDone, 1)
232 };
233
main(int argc,char ** argv)234 int main(int argc, char **argv)
235 {
236 int i;
237 for (i = 1; i < argc; ++i) {
238 char *arg = argv[i];
239 if (arg[0] != '-')
240 break;
241 if (!strncmp(arg, "-m", 2)) {
242 maxTransitions = atoi(&arg[2]);
243 } else {
244 fprintf(stderr, "Unknown option %s\n", arg);
245 }
246 }
247 unsigned possibleTransitions = sizeof(transitionTable) / sizeof(transitionTable[0]);
248 Player_t player;
249 player.mObject = NULL;
250 player.mPlay = NULL;
251 player.mSeek = NULL;
252 State_t currentState = STATE_INITIAL;
253 while (STATE_TERMINAL != currentState) {
254 unsigned matchingTransitions = 0;
255 unsigned totalProbability = 0;
256 for (i = 0; i < (int) possibleTransitions; ++i) {
257 if (currentState != transitionTable[i].mEntryState)
258 continue;
259 ++matchingTransitions;
260 totalProbability += transitionTable[i].mProbability;
261 }
262 if (matchingTransitions == 0) {
263 fprintf(stderr, "No matching transitions in state %d\n", currentState);
264 assert(SL_BOOLEAN_FALSE);
265 break;
266 }
267 if (totalProbability == 0) {
268 fprintf(stderr, "Found at least one matching transition in state %d, "
269 "but with probability 0\n", currentState);
270 assert(SL_BOOLEAN_FALSE);
271 break;
272 }
273 unsigned choice = (rand() & 0x7FFFFFFF) % totalProbability;
274 totalProbability = 0;
275 for (i = 0; i < (int) possibleTransitions; ++i) {
276 if (currentState != transitionTable[i].mEntryState)
277 continue;
278 totalProbability += transitionTable[i].mProbability;
279 if (totalProbability <= choice)
280 continue;
281 ++transitionTable[i].mCount;
282 ++countTransitions;
283 printf("[%d] Selecting transition %s in state %d for the %u time\n", countTransitions,
284 transitionTable[i].mActionName, currentState, transitionTable[i].mCount);
285 State_t nextState = (*transitionTable[i].mAction)(&player);
286 if (STATE_UNCHANGED != nextState)
287 currentState = nextState;
288 goto found;
289 }
290 fprintf(stderr, "This shouldn't happen\n");
291 assert(SL_BOOLEAN_FALSE);
292 found:
293 ;
294 }
295 for (i = 0; i < (int) possibleTransitions; ++i) {
296 printf("state %d action %s count %u\n",
297 transitionTable[i].mEntryState,
298 transitionTable[i].mActionName,
299 transitionTable[i].mCount);
300 }
301 return EXIT_SUCCESS;
302 }
303