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 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 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 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 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 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 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 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 140 State_t actionSleep(Player_pt p) 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 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 171 State_t actionInitialize(Player_pt p) 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 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