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 #include <stdlib.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <unistd.h>
21 #include <sys/time.h>
22 
23 #include <SLES/OpenSLES.h>
24 
25 
26 #define MAX_NUMBER_INTERFACES 2
27 
28 #define TEST_MUTE 0
29 #define TEST_SOLO 1
30 
31 //-----------------------------------------------------------------
32 /* Exits the application if an error is encountered */
33 #define ExitOnError(x) ExitOnErrorFunc(x,__LINE__)
34 
ExitOnErrorFunc(SLresult result,int line)35 void ExitOnErrorFunc( SLresult result , int line)
36 {
37     if (SL_RESULT_SUCCESS != result) {
38         fprintf(stdout, "%u error code encountered at line %d, exiting\n", result, line);
39         exit(EXIT_FAILURE);
40     }
41 }
42 
43 
44 //-----------------------------------------------------------------
45 
46 /* Play an audio URIs, play, pause, stop  */
TestPlayUri(SLObjectItf sl,const char * path)47 void TestPlayUri( SLObjectItf sl, const char* path)
48 {
49     SLresult  result;
50     SLEngineItf EngineItf;
51 
52     /* Objects this application uses: one player and an ouput mix */
53     SLObjectItf  player, outputMix;
54 
55     /* Source of audio data to play */
56     SLDataSource      audioSource;
57     SLDataLocator_URI uri;
58     SLDataFormat_MIME mime;
59 
60     /* Data sinks for the audio player */
61     SLDataSink               audioSink;
62     SLDataLocator_OutputMix  locator_outputmix;
63 
64     /* Play, Volume and PrefetchStatus interfaces for the audio player */
65     SLPlayItf           playItf;
66     SLMuteSoloItf       muteSoloItf;
67     SLPrefetchStatusItf prefetchItf;
68 
69     SLboolean required[MAX_NUMBER_INTERFACES];
70     SLInterfaceID iidArray[MAX_NUMBER_INTERFACES];
71 
72     /* Get the SL Engine Interface which is implicit */
73     result = (*sl)->GetInterface(sl, SL_IID_ENGINE, (void*)&EngineItf);
74     ExitOnError(result);
75 
76     /* Initialize arrays required[] and iidArray[] */
77     for (int i=0 ; i < MAX_NUMBER_INTERFACES ; i++) {
78         required[i] = SL_BOOLEAN_FALSE;
79         iidArray[i] = SL_IID_NULL;
80     }
81 
82     /* ------------------------------------------------------ */
83     /* Configuration of the output mix  */
84 
85     /* Create Output Mix object to be used by the player */
86      result = (*EngineItf)->CreateOutputMix(EngineItf, &outputMix, 0, iidArray, required);
87      ExitOnError(result);
88 
89     /* Realize the Output Mix object in synchronous mode */
90     result = (*outputMix)->Realize(outputMix, SL_BOOLEAN_FALSE);
91     ExitOnError(result);
92 
93     /* Setup the data sink structure */
94     locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
95     locator_outputmix.outputMix   = outputMix;
96     audioSink.pLocator            = (void*)&locator_outputmix;
97     audioSink.pFormat             = NULL;
98 
99     /* ------------------------------------------------------ */
100     /* Configuration of the player  */
101 
102     /* Set arrays required[] and iidArray[] for SLMuteSoloItf and SLPrefetchStatusItf interfaces */
103     /*  (SLPlayItf is implicit) */
104     required[0] = SL_BOOLEAN_TRUE;
105     iidArray[0] = SL_IID_MUTESOLO;
106     required[1] = SL_BOOLEAN_TRUE;
107     iidArray[1] = SL_IID_PREFETCHSTATUS;
108 
109     /* Setup the data source structure for the URI */
110     uri.locatorType = SL_DATALOCATOR_URI;
111     uri.URI         =  (SLchar*) path;
112     mime.formatType = SL_DATAFORMAT_MIME;
113     /*     this is how ignored mime information is specified, according to OpenSL ES spec
114      *     in 9.1.6 SLDataFormat_MIME and 8.23 SLMetadataTraversalItf GetChildInfo */
115     mime.mimeType      = (SLchar*)NULL;
116     mime.containerType = SL_CONTAINERTYPE_UNSPECIFIED;
117 
118     audioSource.pFormat  = (void*)&mime;
119     audioSource.pLocator = (void*)&uri;
120 
121     /* Create the audio player */
122     result = (*EngineItf)->CreateAudioPlayer(EngineItf, &player, &audioSource, &audioSink,
123             MAX_NUMBER_INTERFACES, iidArray, required);
124     ExitOnError(result);
125 
126     /* Realize the player in synchronous mode. */
127     result = (*player)->Realize(player, SL_BOOLEAN_FALSE); ExitOnError(result);
128     fprintf(stdout, "URI example: after Realize\n");
129 
130     /* Get the SLPlayItf, SLPrefetchStatusItf and SLMuteSoloItf interfaces for the player */
131     result = (*player)->GetInterface(player, SL_IID_PLAY, (void*)&playItf);
132     ExitOnError(result);
133 
134     result = (*player)->GetInterface(player, SL_IID_PREFETCHSTATUS, (void*)&prefetchItf);
135     ExitOnError(result);
136 
137     result = (*player)->GetInterface(player, SL_IID_MUTESOLO, (void*)&muteSoloItf);
138     ExitOnError(result);
139 
140 
141     fprintf(stdout, "Player configured\n");
142 
143     /* ------------------------------------------------------ */
144     /* Playback and test */
145 
146     /* Start the data prefetching by setting the player to the paused state */
147     result = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PAUSED );
148     ExitOnError(result);
149 
150     /* Wait until there's data to play */
151     SLuint32 prefetchStatus = SL_PREFETCHSTATUS_UNDERFLOW;
152     while (prefetchStatus != SL_PREFETCHSTATUS_SUFFICIENTDATA) {
153         usleep(100 * 1000);
154         (*prefetchItf)->GetPrefetchStatus(prefetchItf, &prefetchStatus);
155     }
156 
157 
158     /* Testing play states */
159     /* let it play for 2s */
160     fprintf(stdout, "----- Playing\n");
161     result = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PLAYING );
162     ExitOnError(result);
163     usleep(2 * 1000 * 1000);
164 
165     /* pause for 1s*/
166     fprintf(stdout, "----- Pausing (1s)\n");
167     result = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PAUSED );
168     ExitOnError(result);
169     usleep(2 * 1000 * 1000);
170 
171     /* resume */
172     fprintf(stdout, "----- Playing (2s, should have resumed where it paused)\n");
173     result = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PLAYING );
174     ExitOnError(result);
175     usleep(2 * 1000 * 1000);
176 
177     /* stop */
178     fprintf(stdout, "----- Stopping\n");
179     result = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED);
180     ExitOnError(result);
181 
182     /* play for 2s */
183     fprintf(stdout, "----- Playing (2s, should have started from the beginning\n");
184     result = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PLAYING );
185     ExitOnError(result);
186     usleep(2 * 1000 * 1000);
187 
188     /* stop */
189     fprintf(stdout, "----- Stopping\n");
190     result = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED);
191     ExitOnError(result);
192 
193     /* Destroy the players */
194     (*player)->Destroy(player);
195 
196     /* Destroy Output Mix object */
197     (*outputMix)->Destroy(outputMix);
198 }
199 
200 //-----------------------------------------------------------------
main(int argc,char * const argv[])201 int main(int argc, char* const argv[])
202 {
203     SLresult    result;
204     SLObjectItf sl;
205 
206     fprintf(stdout, "OpenSL ES test %s: exercises SLPlayItf, SLVolumeItf, SLMuteSoloItf\n",
207             argv[0]);
208     fprintf(stdout, "and AudioPlayer with SLDataLocator_URI source / OutputMix sink\n");
209     fprintf(stdout, "Plays a sound and alternates the muting of the channels (for 5s).\n");
210     fprintf(stdout, " and then alternates the solo\'ing of the channels (for 5s).\n");
211     fprintf(stdout, "Stops after 10s\n");
212 
213     if (argc == 1) {
214         fprintf(stdout, "Usage: \t%s url\n", argv[0]);
215         fprintf(stdout, "Example: \"%s /sdcard/my.mp3\"\n", argv[0]);
216         exit(EXIT_FAILURE);
217     }
218 
219     SLEngineOption EngineOption[] = {
220             {(SLuint32) SL_ENGINEOPTION_THREADSAFE, (SLuint32) SL_BOOLEAN_TRUE}
221     };
222 
223     result = slCreateEngine( &sl, 1, EngineOption, 0, NULL, NULL);
224     ExitOnError(result);
225 
226     /* Realizing the SL Engine in synchronous mode. */
227     result = (*sl)->Realize(sl, SL_BOOLEAN_FALSE);
228     ExitOnError(result);
229 
230     if (argc > 1) {
231         TestPlayUri(sl, argv[1]);
232     }
233 
234     /* Shutdown OpenSL ES */
235     (*sl)->Destroy(sl);
236 
237     return EXIT_SUCCESS;
238 }
239