1f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi/*
2f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi * Copyright (C) 2010 The Android Open Source Project
3f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi *
4f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License");
5f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi * you may not use this file except in compliance with the License.
6f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi * You may obtain a copy of the License at
7f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi *
8f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi *      http://www.apache.org/licenses/LICENSE-2.0
9f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi *
10f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi * Unless required by applicable law or agreed to in writing, software
11f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS,
12f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi * See the License for the specific language governing permissions and
14f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi * limitations under the License.
15f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi */
16f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
17342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten#include <assert.h>
18342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten#include <pthread.h>
19f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi#include <stdlib.h>
20f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi#include <stdio.h>
21f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi#include <string.h>
22f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi#include <unistd.h>
23f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi#include <sys/time.h>
24f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
25a6c5e52ded343b557152156c33d33a10d29bf6f1Glenn Kasten#include <SLES/OpenSLES.h>
26f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
27f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
28f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi#define MAX_NUMBER_INTERFACES 3
29f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
30f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi#define TEST_MUTE 0
31f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi#define TEST_SOLO 1
32f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
3366f75c45c9aea410b1f913d76995661e72571b67Glenn Kastentypedef struct {
3466f75c45c9aea410b1f913d76995661e72571b67Glenn Kasten    int testMode;
3566f75c45c9aea410b1f913d76995661e72571b67Glenn Kasten    SLPlayItf playItf;
3666f75c45c9aea410b1f913d76995661e72571b67Glenn Kasten    SLMuteSoloItf muteSoloItf;
3766f75c45c9aea410b1f913d76995661e72571b67Glenn Kasten} Context;
3866f75c45c9aea410b1f913d76995661e72571b67Glenn Kasten
39f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi//-----------------------------------------------------------------
40f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi/* Exits the application if an error is encountered */
41f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi#define ExitOnError(x) ExitOnErrorFunc(x,__LINE__)
42f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
43f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivivoid ExitOnErrorFunc( SLresult result , int line)
44f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi{
45f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    if (SL_RESULT_SUCCESS != result) {
46d968dacf7a35d52b6907283f3d95295a238340ccGlenn Kasten        fprintf(stdout, "%u error code encountered at line %d, exiting\n", result, line);
474d7c8c742d5b09895e7ce3d07d314b6ada56123dGlenn Kasten        exit(EXIT_FAILURE);
48f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    }
49f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi}
50f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
51342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten// These are extensions to OpenSL ES 1.0.1 values
52342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten
53342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten#define SL_PREFETCHSTATUS_UNKNOWN 0
54342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten#define SL_PREFETCHSTATUS_ERROR   (-1)
55342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten
56342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten// Mutex and condition shared with main program to protect prefetch_status
57342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten
58342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kastenstatic pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
59342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kastenstatic pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
60342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn KastenSLuint32 prefetch_status = SL_PREFETCHSTATUS_UNKNOWN;
61342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten
62342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten/* used to detect errors likely to have occured when the OpenSL ES framework fails to open
63342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten * a resource, for instance because a file URI is invalid, or an HTTP server doesn't respond.
64342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten */
65342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten#define PREFETCHEVENT_ERROR_CANDIDATE \
66342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten        (SL_PREFETCHEVENT_STATUSCHANGE | SL_PREFETCHEVENT_FILLLEVELCHANGE)
67342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten
68342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten// Prefetch status callback
69342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten
70342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kastenvoid prefetch_callback(SLPrefetchStatusItf caller, void *context, SLuint32 event)
71342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten{
72342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    SLresult result;
73342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    assert(context == NULL);
74342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    SLpermille level;
75342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    result = (*caller)->GetFillLevel(caller, &level);
76342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    assert(SL_RESULT_SUCCESS == result);
77342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    SLuint32 status;
78342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    result = (*caller)->GetPrefetchStatus(caller, &status);
79342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    assert(SL_RESULT_SUCCESS == result);
80342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    SLuint32 new_prefetch_status;
81342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    if ((event & PREFETCHEVENT_ERROR_CANDIDATE) == PREFETCHEVENT_ERROR_CANDIDATE
82342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten            && level == 0 && status == SL_PREFETCHSTATUS_UNDERFLOW) {
83342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten        new_prefetch_status = SL_PREFETCHSTATUS_ERROR;
84342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    } else if (event == SL_PREFETCHEVENT_STATUSCHANGE &&
85342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten            status == SL_PREFETCHSTATUS_SUFFICIENTDATA) {
86342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten        new_prefetch_status = status;
87342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    } else {
88342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten        return;
89342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    }
90342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    int ok;
91342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    ok = pthread_mutex_lock(&mutex);
92342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    assert(ok == 0);
93342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    prefetch_status = new_prefetch_status;
94342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    ok = pthread_cond_signal(&cond);
95342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    assert(ok == 0);
96342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    ok = pthread_mutex_unlock(&mutex);
97342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    assert(ok == 0);
98342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten}
99342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten
100f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi//-----------------------------------------------------------------
101f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi/* PlayItf callback for an audio player, will be called for every SL_PLAYEVENT_HEADATNEWPOS event */
102f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivivoid PlayEventCallback( SLPlayItf caller,  void *pContext, SLuint32 event)
103f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi{
10466f75c45c9aea410b1f913d76995661e72571b67Glenn Kasten    Context *context = (Context *) pContext;
10566f75c45c9aea410b1f913d76995661e72571b67Glenn Kasten    SLPlayItf playItf = context->playItf;
10666f75c45c9aea410b1f913d76995661e72571b67Glenn Kasten    SLMuteSoloItf muteSolo = context->muteSoloItf;
107f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    SLuint8 numChannels = 0;
108f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    SLresult res = (*muteSolo)->GetNumChannels(muteSolo, &numChannels); ExitOnError(res);
109f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    //fprintf(stdout, "Content has %d channel(s)\n", numChannels);
11066f75c45c9aea410b1f913d76995661e72571b67Glenn Kasten    SLmillisecond position;
11166f75c45c9aea410b1f913d76995661e72571b67Glenn Kasten    res = (*playItf)->GetPosition(playItf, &position); ExitOnError(res);
11266f75c45c9aea410b1f913d76995661e72571b67Glenn Kasten    printf("position=%u\n", (unsigned) position);
113f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
11466f75c45c9aea410b1f913d76995661e72571b67Glenn Kasten    switch (context->testMode) {
115f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi        case TEST_MUTE: {
116f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi            //---------------------------------------------------
117f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi            if (numChannels > 1) { // SLMuteSoloItf only works if more than one channel
118f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi                SLboolean leftMuted = SL_BOOLEAN_TRUE;
119f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi                res = (*muteSolo)->GetChannelMute(muteSolo, 0, &leftMuted); ExitOnError(res);
120f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi                // swap channel mute
121f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi                res = (*muteSolo)->SetChannelMute(muteSolo, 0,
122f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi                       leftMuted == SL_BOOLEAN_TRUE ? SL_BOOLEAN_FALSE : SL_BOOLEAN_TRUE);
123f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi                ExitOnError(res);
124f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi                res = (*muteSolo)->SetChannelMute(muteSolo, 1,
125f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi                       leftMuted == SL_BOOLEAN_TRUE ? SL_BOOLEAN_TRUE : SL_BOOLEAN_FALSE);
126f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi                ExitOnError(res);
127f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi                if (leftMuted == SL_BOOLEAN_TRUE) { // we've swapped the channel mute above
128f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi                    fprintf(stdout, "channel 0: playing, channel 1: muted\n");
129f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi                } else {
130f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi                    fprintf(stdout, "channel 0: muted, channel 1: playing\n");
131f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi                }
132f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi            }
133f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi            } break;
134f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
135f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi        case TEST_SOLO: {
136f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi            //---------------------------------------------------
137f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi            if (numChannels > 1) { // SLMuteSoloItf only works if more than one channel
138f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi                SLboolean leftSoloed = SL_BOOLEAN_TRUE;
139f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi                res = (*muteSolo)->GetChannelSolo(muteSolo, 0, &leftSoloed); ExitOnError(res);
140f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi                // swap channel solo
141f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi                res = (*muteSolo)->SetChannelSolo(muteSolo, 0,
142f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi                        leftSoloed == SL_BOOLEAN_TRUE ? SL_BOOLEAN_FALSE : SL_BOOLEAN_TRUE);
143f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi                ExitOnError(res);
144f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi                res = (*muteSolo)->SetChannelSolo(muteSolo, 1,
145f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi                        leftSoloed == SL_BOOLEAN_TRUE ? SL_BOOLEAN_TRUE : SL_BOOLEAN_FALSE);
146f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi                ExitOnError(res);
147f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi                if (leftSoloed == SL_BOOLEAN_TRUE) { // we've swapped the channel solo above
148f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi                    fprintf(stdout, "channel 0: normal, channel 1: soloed\n");
149f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi                } else {
150f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi                    fprintf(stdout, "channel 0: soloed, channel 1: normal\n");
151f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi                }
152f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi            }
153f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi            } break;
154f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
155f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi        default:
156f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi            break;
157f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    }
158f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi}
159f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
160f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi//-----------------------------------------------------------------
161f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
162f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi/* Play an audio URIs, mute and solo channels  */
163f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivivoid TestPlayUri( SLObjectItf sl, const char* path)
164f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi{
165f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    SLresult  result;
166f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    SLEngineItf EngineItf;
167f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
168342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    /* Objects this application uses: one player and an output mix */
169f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    SLObjectItf  player, outputMix;
170f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
171f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    /* Source of audio data to play */
172f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    SLDataSource      audioSource;
173f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    SLDataLocator_URI uri;
174f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    SLDataFormat_MIME mime;
175f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
176f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    /* Data sinks for the audio player */
177f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    SLDataSink               audioSink;
178f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    SLDataLocator_OutputMix  locator_outputmix;
179f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
180f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    /* Play, Volume and PrefetchStatus interfaces for the audio player */
181f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    SLPlayItf           playItf;
182f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    SLMuteSoloItf       muteSoloItf;
183f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    SLPrefetchStatusItf prefetchItf;
184f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
185f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    SLboolean required[MAX_NUMBER_INTERFACES];
186f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    SLInterfaceID iidArray[MAX_NUMBER_INTERFACES];
187f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
188f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    /* Get the SL Engine Interface which is implicit */
189f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    result = (*sl)->GetInterface(sl, SL_IID_ENGINE, (void*)&EngineItf);
190f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    ExitOnError(result);
191f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
192f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    /* Initialize arrays required[] and iidArray[] */
193f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    for (int i=0 ; i < MAX_NUMBER_INTERFACES ; i++) {
194f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi        required[i] = SL_BOOLEAN_FALSE;
195f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi        iidArray[i] = SL_IID_NULL;
196f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    }
197f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
198f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    /* ------------------------------------------------------ */
199f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    /* Configuration of the output mix  */
200f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
201f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    /* Create Output Mix object to be used by the player */
2024d7c8c742d5b09895e7ce3d07d314b6ada56123dGlenn Kasten     result = (*EngineItf)->CreateOutputMix(EngineItf, &outputMix, 0, iidArray, required);
203f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi     ExitOnError(result);
204f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
205f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    /* Realize the Output Mix object in synchronous mode */
206f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    result = (*outputMix)->Realize(outputMix, SL_BOOLEAN_FALSE);
207f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    ExitOnError(result);
208f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
209f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    /* Setup the data sink structure */
210f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
211f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    locator_outputmix.outputMix   = outputMix;
212f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    audioSink.pLocator            = (void*)&locator_outputmix;
213f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    audioSink.pFormat             = NULL;
214f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
215f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    /* ------------------------------------------------------ */
216f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    /* Configuration of the player  */
217f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
218f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    /* Set arrays required[] and iidArray[] for SLMuteSoloItf and SLPrefetchStatusItf interfaces */
219f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    /*  (SLPlayItf is implicit) */
220f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    required[0] = SL_BOOLEAN_TRUE;
221f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    iidArray[0] = SL_IID_MUTESOLO;
222f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    required[1] = SL_BOOLEAN_TRUE;
223f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    iidArray[1] = SL_IID_PREFETCHSTATUS;
224f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
225f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    /* Setup the data source structure for the URI */
226f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    uri.locatorType = SL_DATALOCATOR_URI;
227f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    uri.URI         =  (SLchar*) path;
228f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    mime.formatType = SL_DATAFORMAT_MIME;
229f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    /*     this is how ignored mime information is specified, according to OpenSL ES spec
230f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi     *     in 9.1.6 SLDataFormat_MIME and 8.23 SLMetadataTraversalItf GetChildInfo */
231f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    mime.mimeType      = (SLchar*)NULL;
232f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    mime.containerType = SL_CONTAINERTYPE_UNSPECIFIED;
233f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
234f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    audioSource.pFormat  = (void*)&mime;
235f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    audioSource.pLocator = (void*)&uri;
236f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
237f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    /* Create the audio player */
23823c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    result = (*EngineItf)->CreateAudioPlayer(EngineItf, &player, &audioSource, &audioSink, 2,
239f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi            iidArray, required);
240f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    ExitOnError(result);
241f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
242f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    /* Realize the player in synchronous mode. */
243f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    result = (*player)->Realize(player, SL_BOOLEAN_FALSE); ExitOnError(result);
244f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    fprintf(stdout, "URI example: after Realize\n");
245f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
246f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    /* Get the SLPlayItf, SLPrefetchStatusItf and SLMuteSoloItf interfaces for the player */
247f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    result = (*player)->GetInterface(player, SL_IID_PLAY, (void*)&playItf);
248f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    ExitOnError(result);
249f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
250342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    // get the prefetch status interface
251f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    result = (*player)->GetInterface(player, SL_IID_PREFETCHSTATUS, (void*)&prefetchItf);
252f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    ExitOnError(result);
253f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
254342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    // enable prefetch status callbacks
255342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    result = (*prefetchItf)->RegisterCallback(prefetchItf, prefetch_callback, NULL);
256342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    assert(SL_RESULT_SUCCESS == result);
257342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    result = (*prefetchItf)->SetCallbackEventsMask(prefetchItf,
258342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten            SL_PREFETCHEVENT_STATUSCHANGE | SL_PREFETCHEVENT_FILLLEVELCHANGE);
259342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    assert(SL_RESULT_SUCCESS == result);
260342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten
261342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    // get the mute solo interface
262f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    result = (*player)->GetInterface(player, SL_IID_MUTESOLO, (void*)&muteSoloItf);
263f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    ExitOnError(result);
264f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
265342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    // Attempt to get the duration before it is necessarily known.
266342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    // This should always return successfully.
267342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    // The reported duration may be either
268342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    // a particular duration or SL_TIME_UNKNOWN, depending on the platform.
269342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    SLmillisecond duration;
270342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    result = (*playItf)->GetDuration(playItf, &duration);
271342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    ExitOnError(result);
272342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    printf("GetDuration after Realize but before pre-fetch: result=%u, duration=%u\n",
273342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten        result, duration);
274342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten
275ec3a5a5555af3ed612b70dc54ef96998a9256b9aGlenn Kasten    // Attempt to get the channel count before it is necessarily known.
276342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    // This should either return successfully with a specific value (e.g. 1 or 2),
277342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    // or fail with SL_RESULT_PRECONDITIONS_VIOLATED, depending on the platform.
278ec3a5a5555af3ed612b70dc54ef96998a9256b9aGlenn Kasten    SLuint8 numChannels = 123;
279ec3a5a5555af3ed612b70dc54ef96998a9256b9aGlenn Kasten    result = (*muteSoloItf)->GetNumChannels(muteSoloItf, &numChannels);
280d968dacf7a35d52b6907283f3d95295a238340ccGlenn Kasten    printf("GetNumChannels after Realize but before pre-fetch: result=%u, numChannels=%u\n",
281ec3a5a5555af3ed612b70dc54ef96998a9256b9aGlenn Kasten        result, numChannels);
282342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    if (result != SL_RESULT_PRECONDITIONS_VIOLATED) {
283342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten        ExitOnError(result);
284342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    }
285ec3a5a5555af3ed612b70dc54ef96998a9256b9aGlenn Kasten
286342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    /* Initialize a context for use by the play event callback */
28766f75c45c9aea410b1f913d76995661e72571b67Glenn Kasten    Context             context;
28866f75c45c9aea410b1f913d76995661e72571b67Glenn Kasten    context.playItf = playItf;
28966f75c45c9aea410b1f913d76995661e72571b67Glenn Kasten    context.muteSoloItf = muteSoloItf;
29066f75c45c9aea410b1f913d76995661e72571b67Glenn Kasten    context.testMode = TEST_MUTE;
29166f75c45c9aea410b1f913d76995661e72571b67Glenn Kasten
292f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    /*  Setup to receive playback events on position updates */
29366f75c45c9aea410b1f913d76995661e72571b67Glenn Kasten    result = (*playItf)->RegisterCallback(playItf, PlayEventCallback, (void *) &context);
294f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    ExitOnError(result);
295f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    result = (*playItf)->SetCallbackEventsMask(playItf, SL_PLAYEVENT_HEADATNEWPOS);
296f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    ExitOnError(result);
297f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    result = (*playItf)->SetPositionUpdatePeriod(playItf, 1000);
298f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    ExitOnError(result);
299f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
300f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    fprintf(stdout, "Player configured\n");
301f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
302f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    /* ------------------------------------------------------ */
303f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    /* Playback and test */
304f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
305f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    /* Start the data prefetching by setting the player to the paused state */
306f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    result = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PAUSED );
307f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    ExitOnError(result);
308f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
309342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    // wait for prefetch status callback to indicate either sufficient data or error
310342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    pthread_mutex_lock(&mutex);
311342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    while (prefetch_status == SL_PREFETCHSTATUS_UNKNOWN) {
312342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten        pthread_cond_wait(&cond, &mutex);
313342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    }
314342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    pthread_mutex_unlock(&mutex);
315342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    if (prefetch_status == SL_PREFETCHSTATUS_ERROR) {
316342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten        fprintf(stderr, "Error during prefetch, exiting\n");
317342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten        goto destroyKillKill;
318f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    }
319f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
320342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    /* Query the duration */
321342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    result = (*playItf)->GetDuration(playItf, &duration);
322342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    printf("GetDuration after Realize and after pre-fetch: result=%u, duration=%u\n",
323342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten        result, duration);
324342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    ExitOnError(result);
325342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten
326f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    /* Query the number of channels */
327ec3a5a5555af3ed612b70dc54ef96998a9256b9aGlenn Kasten    numChannels = 123;
328f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    result = (*muteSoloItf)->GetNumChannels(muteSoloItf, &numChannels);
329342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten    printf("GetNumChannels after Realize and after pre-fetch: result=%u, numChannels=%u\n",
330342a97ea313edccccda34dc5e5ec0aacfbc1ff62Glenn Kasten        result, numChannels);
331f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    ExitOnError(result);
332f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    fprintf(stdout, "Content has %d channel(s)\n", numChannels);
333f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
334f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    if (numChannels == 1) {
335f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi        fprintf(stdout, "SLMuteSolotItf only works one content with more than one channel. Bye\n");
336f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi        goto destroyKillKill;
337f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    } else {
338f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi        /* Mute left channel */
3391a6bb4f8e738c9387dc9629db294ea5de618a53cGlenn Kasten        result = (*muteSoloItf)->SetChannelMute(muteSoloItf, 0, SL_BOOLEAN_TRUE);
3401a6bb4f8e738c9387dc9629db294ea5de618a53cGlenn Kasten        ExitOnError(result);
3411a6bb4f8e738c9387dc9629db294ea5de618a53cGlenn Kasten        result = (*muteSoloItf)->SetChannelMute(muteSoloItf, 1, SL_BOOLEAN_FALSE);
3421a6bb4f8e738c9387dc9629db294ea5de618a53cGlenn Kasten        ExitOnError(result);
343f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    }
344f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
345f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    /* Run the test for 10s */
346f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    /* see PlayEventCallback() for more of the test of the SLMuteSoloItf interface */
347f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    fprintf(stdout, "\nTesting mute functionality:\n");
34866f75c45c9aea410b1f913d76995661e72571b67Glenn Kasten    context.testMode = TEST_MUTE;
349f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    result = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PLAYING ); ExitOnError(result);
350f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    usleep( 5 * 1000 * 1000);
351f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    result = (*muteSoloItf)->SetChannelMute(muteSoloItf, 0, SL_BOOLEAN_FALSE); ExitOnError(result);
352f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    result = (*muteSoloItf)->SetChannelMute(muteSoloItf, 1, SL_BOOLEAN_FALSE); ExitOnError(result);
353f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    fprintf(stdout, "\nTesting solo functionality:\n");
35466f75c45c9aea410b1f913d76995661e72571b67Glenn Kasten    context.testMode = TEST_SOLO;
355f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    usleep( 5 * 1000 * 1000);
356f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
357f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    /* Make sure player is stopped */
358f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    fprintf(stdout, "Stopping playback\n");
359f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    result = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED);
360f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    ExitOnError(result);
361f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
362f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel TrividestroyKillKill:
363f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
364f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    /* Destroy the players */
365f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    (*player)->Destroy(player);
366f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
367f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    /* Destroy Output Mix object */
368f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    (*outputMix)->Destroy(outputMix);
369f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi}
370f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
371f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi//-----------------------------------------------------------------
372f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Triviint main(int argc, char* const argv[])
373f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi{
374f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    SLresult    result;
375f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    SLObjectItf sl;
376f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
377f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    fprintf(stdout, "OpenSL ES test %s: exercises SLPlayItf, SLVolumeItf, SLMuteSoloItf\n",
378f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi            argv[0]);
379f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    fprintf(stdout, "and AudioPlayer with SLDataLocator_URI source / OutputMix sink\n");
380f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    fprintf(stdout, "Plays a sound and alternates the muting of the channels (for 5s).\n");
381f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    fprintf(stdout, " and then alternates the solo\'ing of the channels (for 5s).\n");
382f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    fprintf(stdout, "Stops after 10s\n");
383f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
384f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    if (argc == 1) {
385f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi        fprintf(stdout, "Usage: \t%s url\n", argv[0]);
38615f9f5e609265dff9d6036af38bea084c42a702aGlenn Kasten        fprintf(stdout, "Example: \"%s /sdcard/my.mp3\"\n", argv[0]);
3874d7c8c742d5b09895e7ce3d07d314b6ada56123dGlenn Kasten        exit(EXIT_FAILURE);
388f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    }
389f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
390f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    SLEngineOption EngineOption[] = {
391f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi            {(SLuint32) SL_ENGINEOPTION_THREADSAFE, (SLuint32) SL_BOOLEAN_TRUE}
392f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    };
393f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
394f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    result = slCreateEngine( &sl, 1, EngineOption, 0, NULL, NULL);
395f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    ExitOnError(result);
396f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
397f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    /* Realizing the SL Engine in synchronous mode. */
398f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    result = (*sl)->Realize(sl, SL_BOOLEAN_FALSE);
399f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    ExitOnError(result);
400f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
401f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    if (argc > 1) {
402f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi        TestPlayUri(sl, argv[1]);
403f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    }
404f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
405f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    /* Shutdown OpenSL ES */
406f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi    (*sl)->Destroy(sl);
407f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi
4084d7c8c742d5b09895e7ce3d07d314b6ada56123dGlenn Kasten    return EXIT_SUCCESS;
409f5a72df81e05deb7afb56410aa4ecf370b2df141Jean-Michel Trivi}
410