Home | History | Annotate | Download | only in sandbox
      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