10a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten/*
20a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten * Copyright (C) 2010 The Android Open Source Project
30a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten *
40a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten * Licensed under the Apache License, Version 2.0 (the "License");
50a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten * you may not use this file except in compliance with the License.
60a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten * You may obtain a copy of the License at
70a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten *
80a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten *      http://www.apache.org/licenses/LICENSE-2.0
90a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten *
100a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten * Unless required by applicable law or agreed to in writing, software
110a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten * distributed under the License is distributed on an "AS IS" BASIS,
120a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten * See the License for the specific language governing permissions and
140a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten * limitations under the License.
150a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten */
160a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
170a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten// single-threaded, single-player monkey test
180a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
19c6853892c94800e72c0bd676d5d2136d48cea76eGlenn Kasten#include <SLES/OpenSLES.h>
200a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten#include <assert.h>
210a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten#include <stdio.h>
220a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten#include <stdlib.h>
230a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten#include <string.h>
240a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten#include <unistd.h>
250a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
260a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kastentypedef enum {
270a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    STATE_UNCHANGED,
280a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    STATE_INITIAL,
290a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    STATE_NONEXISTENT,
300a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    STATE_CREATED,
310a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    STATE_REALIZED,
320a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    STATE_PAUSED,
330a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    STATE_PLAYING,
340a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    STATE_STOPPED,
350a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    STATE_ERROR,
360a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten//    STATE_IDLE,         // after Stop, then sleep for 3 seconds
370a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    STATE_TERMINAL
380a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten} State_t;
390a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
400a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kastentypedef struct {
410a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLObjectItf mObject;
420a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLPlayItf mPlay;
430a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLSeekItf mSeek;
440a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten} Player_t, *Player_pt;
450a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
460a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kastentypedef State_t (*Action_pt)(Player_pt player);
470a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
480a058cc3d720cdf3f0f8222472a862258482f34fGlenn KastenSLObjectItf engineObject;
490a058cc3d720cdf3f0f8222472a862258482f34fGlenn KastenSLEngineItf engineEngine;
500a058cc3d720cdf3f0f8222472a862258482f34fGlenn KastenSLObjectItf outputMixObject;
510a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kastenint countTransitions = 0;
520a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kastenint maxTransitions = 10;
530a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
540a058cc3d720cdf3f0f8222472a862258482f34fGlenn KastenState_t actionPause(Player_pt p)
550a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten{
560a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    assert(NULL != p->mPlay);
570a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLresult result = (*p->mPlay)->SetPlayState(p->mPlay, SL_PLAYSTATE_PAUSED);
580a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
590a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    return STATE_PAUSED;
600a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten}
610a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
620a058cc3d720cdf3f0f8222472a862258482f34fGlenn KastenState_t actionPlay(Player_pt p)
630a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten{
640a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    assert(NULL != p->mPlay);
650a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLresult result = (*p->mPlay)->SetPlayState(p->mPlay, SL_PLAYSTATE_PLAYING);
660a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
670a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    return STATE_PLAYING;
680a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten}
690a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
700a058cc3d720cdf3f0f8222472a862258482f34fGlenn KastenState_t actionStop(Player_pt p)
710a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten{
720a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    assert(NULL != p->mPlay);
730a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLresult result = (*p->mPlay)->SetPlayState(p->mPlay, SL_PLAYSTATE_STOPPED);
740a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
750a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    return STATE_STOPPED;
760a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten}
770a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
780a058cc3d720cdf3f0f8222472a862258482f34fGlenn KastenState_t actionRewind(Player_pt p)
790a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten{
800a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    assert(NULL != p->mSeek);
810a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLresult result = (*p->mSeek)->SetPosition(p->mSeek, (SLmillisecond) 0, SL_SEEKMODE_FAST);
820a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
830a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    return STATE_UNCHANGED;
840a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten}
850a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
860a058cc3d720cdf3f0f8222472a862258482f34fGlenn KastenState_t actionDestroy(Player_pt p)
870a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten{
880a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    assert(NULL != p->mObject);
890a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    (*p->mObject)->Destroy(p->mObject);
900a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    p->mObject = NULL;
910a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    p->mPlay = NULL;
920a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    p->mSeek = NULL;
930a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    return STATE_NONEXISTENT;
940a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten}
950a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
960a058cc3d720cdf3f0f8222472a862258482f34fGlenn KastenState_t actionCreate(Player_pt p)
970a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten{
980a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    // configure audio source
990a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLDataLocator_URI loc_uri;
1000a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    loc_uri.locatorType = SL_DATALOCATOR_URI;
1010a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    loc_uri.URI = (SLchar *) "wav/frog.wav";
1020a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLDataFormat_MIME format_mime;
1030a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    format_mime.formatType = SL_DATAFORMAT_MIME;
1040a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    format_mime.mimeType = NULL;
1050a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    format_mime.containerType = SL_CONTAINERTYPE_UNSPECIFIED;
1060a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLDataSource audioSrc;
1070a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    audioSrc.pLocator = &loc_uri;
1080a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    audioSrc.pFormat = &format_mime;
1090a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    // configure audio sink
1100a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLDataLocator_OutputMix loc_outmix;
1110a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
1120a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    loc_outmix.outputMix = outputMixObject;
1130a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLDataSink audioSnk;
1140a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    audioSnk.pLocator = &loc_outmix;
1150a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    audioSnk.pFormat = NULL;
1160a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    // create audio player
1170a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLInterfaceID ids[1] = {SL_IID_SEEK};
1180a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLboolean req[1] = {SL_BOOLEAN_TRUE};
1190a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLresult result = (*engineEngine)->CreateAudioPlayer(engineEngine, &p->mObject, &audioSrc,
1200a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            &audioSnk, 1, ids, req);
1210a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    if (SL_RESULT_SUCCESS != result)
1220a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        return STATE_ERROR;
1230a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    return STATE_CREATED;
1240a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten}
1250a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
1260a058cc3d720cdf3f0f8222472a862258482f34fGlenn KastenState_t actionRealize(Player_pt p)
1270a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten{
1280a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    assert(NULL != p->mObject);
1290a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    // realize the player
1300a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLresult result = (*p->mObject)->Realize(p->mObject, SL_BOOLEAN_FALSE);
1310a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
1320a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    // get interfaces
1330a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    result = (*p->mObject)->GetInterface(p->mObject, SL_IID_PLAY, &p->mPlay);
1340a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
1350a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    result = (*p->mObject)->GetInterface(p->mObject, SL_IID_SEEK, &p->mSeek);
1360a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
1370a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    return STATE_REALIZED;
1380a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten}
1390a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
1400a058cc3d720cdf3f0f8222472a862258482f34fGlenn KastenState_t actionSleep(Player_pt p)
1410a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten{
1420a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    unsigned us = 1000 + (rand() & 0xFFFFF);
1430a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    usleep(us);
1440a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    return STATE_UNCHANGED;
1450a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten}
1460a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
1470a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten#if 0
1480a058cc3d720cdf3f0f8222472a862258482f34fGlenn KastenState_t actionSleep3(Player_pt p)
1490a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten{
1500a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    sleep(3);
1510a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    return STATE_IDLE;
1520a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten}
1530a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten#endif
1540a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
1550a058cc3d720cdf3f0f8222472a862258482f34fGlenn KastenState_t actionTerminateIfDone(Player_pt p)
1560a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten{
1570a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    if (countTransitions >= maxTransitions) {
1580a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        assert(NULL == p->mObject);
1590a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        // clean up output mix and engine
1600a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        assert(NULL != outputMixObject);
1610a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        (*outputMixObject)->Destroy(outputMixObject);
1620a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        outputMixObject = NULL;
1630a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        assert(NULL != engineObject);
1640a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        (*engineObject)->Destroy(engineObject);
1650a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        engineObject = NULL;
1660a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        return STATE_TERMINAL;
1670a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    } else
1680a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        return STATE_UNCHANGED;
1690a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten}
1700a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
1710a058cc3d720cdf3f0f8222472a862258482f34fGlenn KastenState_t actionInitialize(Player_pt p)
1720a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten{
1730a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    // create engine
1740a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLresult result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
1750a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
1760a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
1770a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
1780a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
1790a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
1800a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
1810a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    // create output mix
1820a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, NULL, NULL);
1830a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
1840a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
1850a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
1860a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
1870a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    return STATE_NONEXISTENT;
1880a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten}
1890a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
1900a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kastentypedef struct {
1910a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    State_t mEntryState;
1920a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    Action_pt mAction;
1930a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    unsigned mProbability;
1940a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    const char *mActionName;
1950a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    unsigned mCount;
1960a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten} Transition_t;
1970a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
1980a058cc3d720cdf3f0f8222472a862258482f34fGlenn KastenTransition_t transitionTable[] = {
1990a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten#define _(entryState, action, probability) {entryState, action, probability, #action, 0},
2000a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    _(STATE_INITIAL, actionInitialize, 1)
2010a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    _(STATE_CREATED, actionDestroy, 1)
2020a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    _(STATE_CREATED, actionRealize, 1)
2030a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    _(STATE_CREATED, actionSleep, 1)
2040a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    _(STATE_NONEXISTENT, actionCreate, 1)
2050a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    _(STATE_NONEXISTENT, actionSleep, 1)
2060a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    _(STATE_PAUSED, actionDestroy, 1)
2070a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    _(STATE_PAUSED, actionPause, 1)
2080a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    _(STATE_PAUSED, actionPlay, 1)
2090a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    _(STATE_PAUSED, actionRewind, 1)
2100a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    _(STATE_PAUSED, actionSleep, 1)
2110a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    _(STATE_PAUSED, actionStop, 1)
2120a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    _(STATE_PLAYING, actionDestroy, 1)
2130a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    _(STATE_PLAYING, actionPause, 1)
2140a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    _(STATE_PLAYING, actionPlay, 1)
2150a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    _(STATE_PLAYING, actionRewind, 1)
2160a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    _(STATE_PLAYING, actionSleep, 1)
2170a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    _(STATE_PLAYING, actionStop, 1)
2180a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    _(STATE_REALIZED, actionDestroy, 1)
2190a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    _(STATE_REALIZED, actionPause, 1)
2200a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    _(STATE_REALIZED, actionPlay, 1)
2210a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    _(STATE_REALIZED, actionSleep, 1)
2220a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    _(STATE_REALIZED, actionStop, 1)
2230a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    _(STATE_STOPPED, actionDestroy, 1)
2240a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    _(STATE_STOPPED, actionPause, 1)
2250a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    _(STATE_STOPPED, actionPlay, 1)
2260a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    _(STATE_STOPPED, actionRewind, 1)
2270a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    _(STATE_STOPPED, actionSleep, 1)
2280a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    _(STATE_STOPPED, actionStop, 1)
2290a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten//    _(STATE_STOPPED, actionSleep3, 1)
2300a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten//    _(STATE_IDLE, actionDestroy, 1)
2310a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    _(STATE_NONEXISTENT, actionTerminateIfDone, 1)
2320a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten};
2330a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
2340a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kastenint main(int argc, char **argv)
2350a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten{
2360a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    int i;
2370a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    for (i = 1; i < argc; ++i) {
2380a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        char *arg = argv[i];
2390a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        if (arg[0] != '-')
2400a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            break;
2410a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        if (!strncmp(arg, "-m", 2)) {
2420a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            maxTransitions = atoi(&arg[2]);
2430a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        } else {
2440a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            fprintf(stderr, "Unknown option %s\n", arg);
2450a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        }
2460a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    }
2470a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    unsigned possibleTransitions = sizeof(transitionTable) / sizeof(transitionTable[0]);
2480a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    Player_t player;
2490a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    player.mObject = NULL;
2500a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    player.mPlay = NULL;
2510a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    player.mSeek = NULL;
2520a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    State_t currentState = STATE_INITIAL;
2530a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    while (STATE_TERMINAL != currentState) {
2540a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        unsigned matchingTransitions = 0;
2550a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        unsigned totalProbability = 0;
2560a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        for (i = 0; i < (int) possibleTransitions; ++i) {
2570a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            if (currentState != transitionTable[i].mEntryState)
2580a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten                continue;
2590a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            ++matchingTransitions;
2600a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            totalProbability += transitionTable[i].mProbability;
2610a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        }
2620a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        if (matchingTransitions == 0) {
2630a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            fprintf(stderr, "No matching transitions in state %d\n", currentState);
2640a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            assert(SL_BOOLEAN_FALSE);
2650a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            break;
2660a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        }
2670a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        if (totalProbability == 0) {
2680a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            fprintf(stderr, "Found at least one matching transition in state %d, "
2690a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten                    "but with probability 0\n", currentState);
2700a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            assert(SL_BOOLEAN_FALSE);
2710a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            break;
2720a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        }
2730a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        unsigned choice = (rand() & 0x7FFFFFFF) % totalProbability;
2740a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        totalProbability = 0;
2750a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        for (i = 0; i < (int) possibleTransitions; ++i) {
2760a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            if (currentState != transitionTable[i].mEntryState)
2770a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten                continue;
2780a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            totalProbability += transitionTable[i].mProbability;
2790a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            if (totalProbability <= choice)
2800a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten                continue;
2810a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            ++transitionTable[i].mCount;
2820a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            ++countTransitions;
2830a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            printf("[%d] Selecting transition %s in state %d for the %u time\n", countTransitions,
2840a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten                    transitionTable[i].mActionName, currentState, transitionTable[i].mCount);
2850a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            State_t nextState = (*transitionTable[i].mAction)(&player);
2860a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            if (STATE_UNCHANGED != nextState)
2870a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten                currentState = nextState;
2880a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            goto found;
2890a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        }
2900a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        fprintf(stderr, "This shouldn't happen\n");
2910a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        assert(SL_BOOLEAN_FALSE);
2920a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kastenfound:
2930a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        ;
2940a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    }
2950a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    for (i = 0; i < (int) possibleTransitions; ++i) {
2960a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        printf("state %d action %s count %u\n",
2970a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            transitionTable[i].mEntryState,
2980a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            transitionTable[i].mActionName,
2990a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            transitionTable[i].mCount);
3000a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    }
3010a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    return EXIT_SUCCESS;
3020a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten}
303