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