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 // multiplay is a command-line test app that plays multiple files randomly
     18 
     19 #include "SLES/OpenSLES.h"
     20 #include <assert.h>
     21 #include <string.h>
     22 #include <stdlib.h>
     23 #include <stdio.h>
     24 #include <unistd.h>
     25 
     26 // Describes the state of one player
     27 
     28 typedef struct {
     29     SLObjectItf mPlayerObject;
     30     SLPlayItf mPlayerPlay;
     31     SLSeekItf mPlayerSeek;
     32     SLVolumeItf mPlayerVolume;
     33     SLmillisecond mPlayerDuration;
     34 } Player;
     35 
     36 // Strings corresponding to result codes; FIXME should move to a common test library
     37 
     38 static const char *result_strings[] = {
     39     "SUCCESS",
     40     "PRECONDITIONS_VIOLATED",
     41     "PARAMETER_INVALID",
     42     "MEMORY_FAILURE",
     43     "RESOURCE_ERROR",
     44     "RESOURCE_LOST",
     45     "IO_ERROR",
     46     "BUFFER_INSUFFICIENT",
     47     "CONTENT_CORRUPTED",
     48     "CONTENT_UNSUPPORTED",
     49     "CONTENT_NOT_FOUND",
     50     "PERMISSION_DENIED",
     51     "FEATURE_UNSUPPORTED",
     52     "INTERNAL_ERROR",
     53     "UNKNOWN_ERROR",
     54     "OPERATION_ABORTED",
     55     "CONTROL_LOST"
     56 };
     57 
     58 // Convert result to string; FIXME should move to common test library
     59 
     60 static const char *result_to_string(SLresult result)
     61 {
     62     static char buffer[32];
     63     if ( /* result >= 0 && */ result < sizeof(result_strings) / sizeof(result_strings[0]))
     64         return result_strings[result];
     65     sprintf(buffer, "%d", (int) result);
     66     return buffer;
     67 }
     68 
     69 // Compare result against expected and exit suddenly if wrong
     70 
     71 void check2(SLresult result, int line)
     72 {
     73     if (SL_RESULT_SUCCESS != result) {
     74         fprintf(stderr, "error %s at line %d\n", result_to_string(result), line);
     75         exit(EXIT_FAILURE);
     76     }
     77 }
     78 
     79 // Same as above but automatically adds the source code line number
     80 
     81 #define check(result) check2(result, __LINE__)
     82 
     83 // Main program
     84 
     85 int main(int argc, char **argv)
     86 {
     87     int i;
     88     const char *arg;
     89     int numPlayers = 0;
     90     int playTimeInMilliseconds = 0; // default to run forever
     91     SLmillibel mixVolumeLevel = 0;
     92     for (i = 1; i < argc; ++i) {
     93         arg = argv[i];
     94         if (arg[0] != '-')
     95             break;
     96         if (!strncmp(arg, "-n", 2))
     97             numPlayers = atoi(&arg[2]);
     98         else if (!strncmp(arg, "-v", 2))
     99             mixVolumeLevel = atoi(&arg[2]);
    100         else if (!strncmp(arg, "-t", 2))
    101             playTimeInMilliseconds = atoi(&arg[2]) * 1000;
    102         else
    103             fprintf(stderr, "unknown option: %s\n", arg);
    104     }
    105     int numPathnames = argc - i;
    106     if (numPathnames <= 0) {
    107         fprintf(stderr, "usage: %s file.wav ...\n", argv[0]);
    108         return EXIT_FAILURE;
    109     }
    110     if (numPlayers <= 0)
    111         numPlayers = numPathnames;
    112     Player *players = (Player *) malloc(sizeof(Player) * numPlayers);
    113     assert(NULL != players);
    114     char **pathnames = &argv[i];
    115     SLresult result;
    116 
    117     // engine
    118     const SLInterfaceID engine_ids[] = {SL_IID_ENGINE};
    119     const SLboolean engine_req[] = {SL_BOOLEAN_TRUE};
    120     SLObjectItf engineObject;
    121     result = slCreateEngine(&engineObject, 0, NULL, 1, engine_ids, engine_req);
    122     check(result);
    123     result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
    124     check(result);
    125     SLEngineItf engineEngine;
    126     result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
    127     check(result);
    128 
    129     // mixer
    130     const SLInterfaceID mix_ids[] = {SL_IID_VOLUME};
    131     const SLboolean mix_req[] = {SL_BOOLEAN_TRUE};
    132     SLObjectItf mixObject;
    133     result = (*engineEngine)->CreateOutputMix(engineEngine, &mixObject, 0, mix_ids, mix_req);
    134     check(result);
    135     result = (*mixObject)->Realize(mixObject, SL_BOOLEAN_FALSE);
    136     check(result);
    137 #if 0
    138     SLVolumeItf mixVolume;
    139     result = (*mixObject)->GetInterface(mixObject, SL_IID_VOLUME, &mixVolume);
    140     check(result);
    141     SLmillibel mixVolumeLevelDefault;
    142     result = (*mixVolume)->GetVolumeLevel(mixVolume, &mixVolumeLevelDefault);
    143     check(result);
    144     printf("default mix volume level = %d\n", mixVolumeLevelDefault);
    145 #endif
    146 
    147     printf("numPathnames=%d\n", numPathnames);
    148     printf("numPlayers=%d\n", numPlayers);
    149     Player *p;
    150 
    151     // create all the players
    152     for (i = 0; i < numPlayers; ++i) {
    153         const SLInterfaceID player_ids[] = {SL_IID_PLAY, SL_IID_VOLUME, SL_IID_SEEK};
    154         const SLboolean player_req[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
    155         p = &players[i];
    156         SLDataLocator_URI locURI = {SL_DATALOCATOR_URI, (SLchar *) pathnames[i % numPathnames]};
    157         SLDataFormat_MIME dfMIME = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED};
    158         SLDataSource audioSrc = {&locURI, &dfMIME};
    159         SLDataLocator_OutputMix locOutputMix = {SL_DATALOCATOR_OUTPUTMIX, mixObject};
    160         SLDataSink audioSnk = {&locOutputMix, NULL};
    161         result = (*engineEngine)->CreateAudioPlayer(engineEngine, &p->mPlayerObject, &audioSrc,
    162             &audioSnk, 3, player_ids, player_req);
    163         check(result);
    164         result = (*p->mPlayerObject)->Realize(p->mPlayerObject, SL_BOOLEAN_FALSE);
    165         check(result);
    166         result = (*p->mPlayerObject)->GetInterface(p->mPlayerObject, SL_IID_PLAY, &p->mPlayerPlay);
    167         check(result);
    168         result = (*p->mPlayerObject)->GetInterface(p->mPlayerObject, SL_IID_VOLUME,
    169             &p->mPlayerVolume);
    170         check(result);
    171         result = (*p->mPlayerObject)->GetInterface(p->mPlayerObject, SL_IID_SEEK, &p->mPlayerSeek);
    172         check(result);
    173         result = (*p->mPlayerPlay)->GetDuration(p->mPlayerPlay, &p->mPlayerDuration);
    174         check(result);
    175         printf("player %d duration %d\n", (int) i, (int) p->mPlayerDuration);
    176     }
    177 
    178     // now loop randomly doing things to the players
    179     for (;;) {
    180         SLmillisecond delay = 100 + (rand() & 1023);
    181         printf("sleep %u\n", (unsigned) delay);
    182         usleep(delay * 1000);
    183         i = (rand() & 0x7FFFFFFF) % numPlayers;
    184         printf("player %d ", i);
    185         p = &players[i];
    186         SLuint32 state;
    187         result = (*p->mPlayerPlay)->GetPlayState(p->mPlayerPlay, &state);
    188         check(result);
    189         printf("state = ");
    190         switch (state) {
    191         case SL_PLAYSTATE_STOPPED:
    192             printf("STOPPED");
    193             break;
    194         case SL_PLAYSTATE_PAUSED:
    195             printf("PAUSED");
    196             break;
    197         case SL_PLAYSTATE_PLAYING:
    198             printf("PLAYING");
    199             break;
    200         default:
    201             printf("%u", (unsigned) state);
    202             break;
    203         }
    204         printf("\n");
    205         if (state == SL_PLAYSTATE_STOPPED || state == SL_PLAYSTATE_PAUSED) {
    206             SLmillibel volumeLevel = -((rand() & 0x7FFFFFFF) % ((SL_MILLIBEL_MIN + 1) / 10));
    207             printf("volume %d\n", volumeLevel);
    208             result = (*p->mPlayerVolume)->SetVolumeLevel(p->mPlayerVolume, volumeLevel);
    209             check(result);
    210             result = (*p->mPlayerVolume)->EnableStereoPosition(p->mPlayerVolume, SL_BOOLEAN_TRUE);
    211             check(result);
    212             SLpermille stereoPosition = ((rand() & 0x7FFFFFFF) % 2001) - 1000;
    213             printf("position %d\n", stereoPosition);
    214             result = (*p->mPlayerVolume)->SetStereoPosition(p->mPlayerVolume, stereoPosition);
    215             check(result);
    216             if (state != SL_PLAYSTATE_STOPPED) {
    217                 result = (*p->mPlayerSeek)->SetPosition(p->mPlayerSeek, 0, SL_SEEKMODE_FAST);
    218                 check(result);
    219             }
    220             result = (*p->mPlayerPlay)->SetPlayState(p->mPlayerPlay, SL_PLAYSTATE_PLAYING);
    221             check(result);
    222         }
    223         if ((playTimeInMilliseconds > 0) && ((playTimeInMilliseconds -= delay) < 0))
    224             break;
    225     }
    226 
    227     for (i = 0; i < numPlayers; ++i) {
    228         SLObjectItf playerObject = players[i].mPlayerObject;
    229         (*playerObject)->Destroy(playerObject);
    230     }
    231     (*mixObject)->Destroy(mixObject);
    232     (*engineObject)->Destroy(engineObject);
    233 
    234     return EXIT_SUCCESS;
    235 }
    236