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