You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
303 lines
9.4 KiB
303 lines
9.4 KiB
/*
|
|
* Copyright (C) 2010 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
// single-threaded, single-player monkey test
|
|
|
|
#include <SLES/OpenSLES.h>
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
typedef enum {
|
|
STATE_UNCHANGED,
|
|
STATE_INITIAL,
|
|
STATE_NONEXISTENT,
|
|
STATE_CREATED,
|
|
STATE_REALIZED,
|
|
STATE_PAUSED,
|
|
STATE_PLAYING,
|
|
STATE_STOPPED,
|
|
STATE_ERROR,
|
|
// STATE_IDLE, // after Stop, then sleep for 3 seconds
|
|
STATE_TERMINAL
|
|
} State_t;
|
|
|
|
typedef struct {
|
|
SLObjectItf mObject;
|
|
SLPlayItf mPlay;
|
|
SLSeekItf mSeek;
|
|
} Player_t, *Player_pt;
|
|
|
|
typedef State_t (*Action_pt)(Player_pt player);
|
|
|
|
SLObjectItf engineObject;
|
|
SLEngineItf engineEngine;
|
|
SLObjectItf outputMixObject;
|
|
int countTransitions = 0;
|
|
int maxTransitions = 10;
|
|
|
|
State_t actionPause(Player_pt p)
|
|
{
|
|
assert(NULL != p->mPlay);
|
|
SLresult result = (*p->mPlay)->SetPlayState(p->mPlay, SL_PLAYSTATE_PAUSED);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
return STATE_PAUSED;
|
|
}
|
|
|
|
State_t actionPlay(Player_pt p)
|
|
{
|
|
assert(NULL != p->mPlay);
|
|
SLresult result = (*p->mPlay)->SetPlayState(p->mPlay, SL_PLAYSTATE_PLAYING);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
return STATE_PLAYING;
|
|
}
|
|
|
|
State_t actionStop(Player_pt p)
|
|
{
|
|
assert(NULL != p->mPlay);
|
|
SLresult result = (*p->mPlay)->SetPlayState(p->mPlay, SL_PLAYSTATE_STOPPED);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
return STATE_STOPPED;
|
|
}
|
|
|
|
State_t actionRewind(Player_pt p)
|
|
{
|
|
assert(NULL != p->mSeek);
|
|
SLresult result = (*p->mSeek)->SetPosition(p->mSeek, (SLmillisecond) 0, SL_SEEKMODE_FAST);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
return STATE_UNCHANGED;
|
|
}
|
|
|
|
State_t actionDestroy(Player_pt p)
|
|
{
|
|
assert(NULL != p->mObject);
|
|
(*p->mObject)->Destroy(p->mObject);
|
|
p->mObject = NULL;
|
|
p->mPlay = NULL;
|
|
p->mSeek = NULL;
|
|
return STATE_NONEXISTENT;
|
|
}
|
|
|
|
State_t actionCreate(Player_pt p)
|
|
{
|
|
// configure audio source
|
|
SLDataLocator_URI loc_uri;
|
|
loc_uri.locatorType = SL_DATALOCATOR_URI;
|
|
loc_uri.URI = (SLchar *) "wav/frog.wav";
|
|
SLDataFormat_MIME format_mime;
|
|
format_mime.formatType = SL_DATAFORMAT_MIME;
|
|
format_mime.mimeType = NULL;
|
|
format_mime.containerType = SL_CONTAINERTYPE_UNSPECIFIED;
|
|
SLDataSource audioSrc;
|
|
audioSrc.pLocator = &loc_uri;
|
|
audioSrc.pFormat = &format_mime;
|
|
// configure audio sink
|
|
SLDataLocator_OutputMix loc_outmix;
|
|
loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
|
|
loc_outmix.outputMix = outputMixObject;
|
|
SLDataSink audioSnk;
|
|
audioSnk.pLocator = &loc_outmix;
|
|
audioSnk.pFormat = NULL;
|
|
// create audio player
|
|
SLInterfaceID ids[1] = {SL_IID_SEEK};
|
|
SLboolean req[1] = {SL_BOOLEAN_TRUE};
|
|
SLresult result = (*engineEngine)->CreateAudioPlayer(engineEngine, &p->mObject, &audioSrc,
|
|
&audioSnk, 1, ids, req);
|
|
if (SL_RESULT_SUCCESS != result)
|
|
return STATE_ERROR;
|
|
return STATE_CREATED;
|
|
}
|
|
|
|
State_t actionRealize(Player_pt p)
|
|
{
|
|
assert(NULL != p->mObject);
|
|
// realize the player
|
|
SLresult result = (*p->mObject)->Realize(p->mObject, SL_BOOLEAN_FALSE);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
// get interfaces
|
|
result = (*p->mObject)->GetInterface(p->mObject, SL_IID_PLAY, &p->mPlay);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
result = (*p->mObject)->GetInterface(p->mObject, SL_IID_SEEK, &p->mSeek);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
return STATE_REALIZED;
|
|
}
|
|
|
|
State_t actionSleep(Player_pt p __unused)
|
|
{
|
|
unsigned us = 1000 + (rand() & 0xFFFFF);
|
|
usleep(us);
|
|
return STATE_UNCHANGED;
|
|
}
|
|
|
|
#if 0
|
|
State_t actionSleep3(Player_pt p)
|
|
{
|
|
sleep(3);
|
|
return STATE_IDLE;
|
|
}
|
|
#endif
|
|
|
|
State_t actionTerminateIfDone(Player_pt p)
|
|
{
|
|
if (countTransitions >= maxTransitions) {
|
|
assert(NULL == p->mObject);
|
|
// clean up output mix and engine
|
|
assert(NULL != outputMixObject);
|
|
(*outputMixObject)->Destroy(outputMixObject);
|
|
outputMixObject = NULL;
|
|
assert(NULL != engineObject);
|
|
(*engineObject)->Destroy(engineObject);
|
|
engineObject = NULL;
|
|
return STATE_TERMINAL;
|
|
} else
|
|
return STATE_UNCHANGED;
|
|
}
|
|
|
|
State_t actionInitialize(Player_pt p __unused)
|
|
{
|
|
// create engine
|
|
SLresult result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
|
|
// create output mix
|
|
result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, NULL, NULL);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
|
|
assert(SL_RESULT_SUCCESS == result);
|
|
|
|
return STATE_NONEXISTENT;
|
|
}
|
|
|
|
typedef struct {
|
|
State_t mEntryState;
|
|
Action_pt mAction;
|
|
unsigned mProbability;
|
|
const char *mActionName;
|
|
unsigned mCount;
|
|
} Transition_t;
|
|
|
|
Transition_t transitionTable[] = {
|
|
#define _(entryState, action, probability) {entryState, action, probability, #action, 0},
|
|
_(STATE_INITIAL, actionInitialize, 1)
|
|
_(STATE_CREATED, actionDestroy, 1)
|
|
_(STATE_CREATED, actionRealize, 1)
|
|
_(STATE_CREATED, actionSleep, 1)
|
|
_(STATE_NONEXISTENT, actionCreate, 1)
|
|
_(STATE_NONEXISTENT, actionSleep, 1)
|
|
_(STATE_PAUSED, actionDestroy, 1)
|
|
_(STATE_PAUSED, actionPause, 1)
|
|
_(STATE_PAUSED, actionPlay, 1)
|
|
_(STATE_PAUSED, actionRewind, 1)
|
|
_(STATE_PAUSED, actionSleep, 1)
|
|
_(STATE_PAUSED, actionStop, 1)
|
|
_(STATE_PLAYING, actionDestroy, 1)
|
|
_(STATE_PLAYING, actionPause, 1)
|
|
_(STATE_PLAYING, actionPlay, 1)
|
|
_(STATE_PLAYING, actionRewind, 1)
|
|
_(STATE_PLAYING, actionSleep, 1)
|
|
_(STATE_PLAYING, actionStop, 1)
|
|
_(STATE_REALIZED, actionDestroy, 1)
|
|
_(STATE_REALIZED, actionPause, 1)
|
|
_(STATE_REALIZED, actionPlay, 1)
|
|
_(STATE_REALIZED, actionSleep, 1)
|
|
_(STATE_REALIZED, actionStop, 1)
|
|
_(STATE_STOPPED, actionDestroy, 1)
|
|
_(STATE_STOPPED, actionPause, 1)
|
|
_(STATE_STOPPED, actionPlay, 1)
|
|
_(STATE_STOPPED, actionRewind, 1)
|
|
_(STATE_STOPPED, actionSleep, 1)
|
|
_(STATE_STOPPED, actionStop, 1)
|
|
// _(STATE_STOPPED, actionSleep3, 1)
|
|
// _(STATE_IDLE, actionDestroy, 1)
|
|
_(STATE_NONEXISTENT, actionTerminateIfDone, 1)
|
|
};
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
int i;
|
|
for (i = 1; i < argc; ++i) {
|
|
char *arg = argv[i];
|
|
if (arg[0] != '-')
|
|
break;
|
|
if (!strncmp(arg, "-m", 2)) {
|
|
maxTransitions = atoi(&arg[2]);
|
|
} else {
|
|
fprintf(stderr, "Unknown option %s\n", arg);
|
|
}
|
|
}
|
|
unsigned possibleTransitions = sizeof(transitionTable) / sizeof(transitionTable[0]);
|
|
Player_t player;
|
|
player.mObject = NULL;
|
|
player.mPlay = NULL;
|
|
player.mSeek = NULL;
|
|
State_t currentState = STATE_INITIAL;
|
|
while (STATE_TERMINAL != currentState) {
|
|
unsigned matchingTransitions = 0;
|
|
unsigned totalProbability = 0;
|
|
for (i = 0; i < (int) possibleTransitions; ++i) {
|
|
if (currentState != transitionTable[i].mEntryState)
|
|
continue;
|
|
++matchingTransitions;
|
|
totalProbability += transitionTable[i].mProbability;
|
|
}
|
|
if (matchingTransitions == 0) {
|
|
fprintf(stderr, "No matching transitions in state %d\n", currentState);
|
|
assert(SL_BOOLEAN_FALSE);
|
|
break;
|
|
}
|
|
if (totalProbability == 0) {
|
|
fprintf(stderr, "Found at least one matching transition in state %d, "
|
|
"but with probability 0\n", currentState);
|
|
assert(SL_BOOLEAN_FALSE);
|
|
break;
|
|
}
|
|
unsigned choice = (rand() & 0x7FFFFFFF) % totalProbability;
|
|
totalProbability = 0;
|
|
for (i = 0; i < (int) possibleTransitions; ++i) {
|
|
if (currentState != transitionTable[i].mEntryState)
|
|
continue;
|
|
totalProbability += transitionTable[i].mProbability;
|
|
if (totalProbability <= choice)
|
|
continue;
|
|
++transitionTable[i].mCount;
|
|
++countTransitions;
|
|
printf("[%d] Selecting transition %s in state %d for the %u time\n", countTransitions,
|
|
transitionTable[i].mActionName, currentState, transitionTable[i].mCount);
|
|
State_t nextState = (*transitionTable[i].mAction)(&player);
|
|
if (STATE_UNCHANGED != nextState)
|
|
currentState = nextState;
|
|
goto found;
|
|
}
|
|
fprintf(stderr, "This shouldn't happen\n");
|
|
assert(SL_BOOLEAN_FALSE);
|
|
found:
|
|
;
|
|
}
|
|
for (i = 0; i < (int) possibleTransitions; ++i) {
|
|
printf("state %d action %s count %u\n",
|
|
transitionTable[i].mEntryState,
|
|
transitionTable[i].mActionName,
|
|
transitionTable[i].mCount);
|
|
}
|
|
return EXIT_SUCCESS;
|
|
}
|