blob: 03a808208c9b9e49da247de5771b2afad24070e8 [file] [log] [blame]
Glenn Kasten0a058cc2010-10-18 10:56:43 -07001/*
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
Glenn Kastenc6853892011-07-19 11:16:07 -070019#include <SLES/OpenSLES.h>
Glenn Kasten0a058cc2010-10-18 10:56:43 -070020#include <assert.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <unistd.h>
25
26typedef 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
40typedef struct {
41 SLObjectItf mObject;
42 SLPlayItf mPlay;
43 SLSeekItf mSeek;
44} Player_t, *Player_pt;
45
46typedef State_t (*Action_pt)(Player_pt player);
47
48SLObjectItf engineObject;
49SLEngineItf engineEngine;
50SLObjectItf outputMixObject;
51int countTransitions = 0;
52int maxTransitions = 10;
53
54State_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
62State_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
70State_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
78State_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
86State_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
96State_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
126State_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
Glenn Kasten086a6f52015-01-02 17:36:58 -0800140State_t actionSleep(Player_pt p __unused)
Glenn Kasten0a058cc2010-10-18 10:56:43 -0700141{
142 unsigned us = 1000 + (rand() & 0xFFFFF);
143 usleep(us);
144 return STATE_UNCHANGED;
145}
146
147#if 0
148State_t actionSleep3(Player_pt p)
149{
150 sleep(3);
151 return STATE_IDLE;
152}
153#endif
154
155State_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
Glenn Kasten086a6f52015-01-02 17:36:58 -0800171State_t actionInitialize(Player_pt p __unused)
Glenn Kasten0a058cc2010-10-18 10:56:43 -0700172{
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
190typedef struct {
191 State_t mEntryState;
192 Action_pt mAction;
193 unsigned mProbability;
194 const char *mActionName;
195 unsigned mCount;
196} Transition_t;
197
198Transition_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
234int 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);
292found:
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}