185bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi/*
285bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi * Copyright (C) 2010 The Android Open Source Project
385bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi *
485bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License");
585bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi * you may not use this file except in compliance with the License.
685bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi * You may obtain a copy of the License at
785bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi *
885bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi *      http://www.apache.org/licenses/LICENSE-2.0
985bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi *
1085bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi * Unless required by applicable law or agreed to in writing, software
1185bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS,
1285bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1385bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi * See the License for the specific language governing permissions and
1485bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi * limitations under the License.
1585bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi */
1685bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
17a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten#include <assert.h>
18a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten#include <pthread.h>
1985bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi#include <stdlib.h>
2085bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi#include <stdio.h>
2185bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi#include <string.h>
2285bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi#include <unistd.h>
2385bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi#include <sys/time.h>
2485bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
25c6853892c94800e72c0bd676d5d2136d48cea76eGlenn Kasten#include <SLES/OpenSLES.h>
2685bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
2785bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
2885bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi#define MAX_NUMBER_INTERFACES 3
2985bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
3085bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi#define TEST_MUTE 0
3185bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi#define TEST_SOLO 1
3285bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
338c065779232fdd89abace68d2fc7bea786a010d7Glenn Kastentypedef struct {
348c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten    int testMode;
358c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten    SLPlayItf playItf;
368c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten    SLMuteSoloItf muteSoloItf;
378c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten} Context;
388c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten
3985bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi//-----------------------------------------------------------------
4085bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi/* Exits the application if an error is encountered */
4185bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi#define ExitOnError(x) ExitOnErrorFunc(x,__LINE__)
4285bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
4385bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivivoid ExitOnErrorFunc( SLresult result , int line)
4485bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi{
4585bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    if (SL_RESULT_SUCCESS != result) {
4658432eb9cea995c69b4f905e68b38c1b8216edebGlenn Kasten        fprintf(stdout, "%u error code encountered at line %d, exiting\n", result, line);
47c2303eb5497c488db786dcb2b8514db229452536Glenn Kasten        exit(EXIT_FAILURE);
4885bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    }
4985bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi}
5085bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
51a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten// These are extensions to OpenSL ES 1.0.1 values
52a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten
53a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten#define SL_PREFETCHSTATUS_UNKNOWN 0
54a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten#define SL_PREFETCHSTATUS_ERROR   (-1)
55a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten
56a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten// Mutex and condition shared with main program to protect prefetch_status
57a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten
58a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kastenstatic pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
59a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kastenstatic pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
60a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn KastenSLuint32 prefetch_status = SL_PREFETCHSTATUS_UNKNOWN;
61a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten
62a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten/* used to detect errors likely to have occured when the OpenSL ES framework fails to open
63a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten * a resource, for instance because a file URI is invalid, or an HTTP server doesn't respond.
64a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten */
65a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten#define PREFETCHEVENT_ERROR_CANDIDATE \
66a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten        (SL_PREFETCHEVENT_STATUSCHANGE | SL_PREFETCHEVENT_FILLLEVELCHANGE)
67a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten
68a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten// Prefetch status callback
69a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten
70a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kastenvoid prefetch_callback(SLPrefetchStatusItf caller, void *context, SLuint32 event)
71a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten{
72a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    SLresult result;
73a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    assert(context == NULL);
74a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    SLpermille level;
75a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    result = (*caller)->GetFillLevel(caller, &level);
76a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
77a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    SLuint32 status;
78a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    result = (*caller)->GetPrefetchStatus(caller, &status);
79a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
80a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    SLuint32 new_prefetch_status;
81a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    if ((event & PREFETCHEVENT_ERROR_CANDIDATE) == PREFETCHEVENT_ERROR_CANDIDATE
82a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten            && level == 0 && status == SL_PREFETCHSTATUS_UNDERFLOW) {
83a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten        new_prefetch_status = SL_PREFETCHSTATUS_ERROR;
84a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    } else if (event == SL_PREFETCHEVENT_STATUSCHANGE &&
85a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten            status == SL_PREFETCHSTATUS_SUFFICIENTDATA) {
86a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten        new_prefetch_status = status;
87a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    } else {
88a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten        return;
89a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    }
90a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    int ok;
91a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    ok = pthread_mutex_lock(&mutex);
92a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    assert(ok == 0);
93a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    prefetch_status = new_prefetch_status;
94a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    ok = pthread_cond_signal(&cond);
95a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    assert(ok == 0);
96a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    ok = pthread_mutex_unlock(&mutex);
97a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    assert(ok == 0);
98a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten}
99a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten
10085bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi//-----------------------------------------------------------------
10185bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi/* PlayItf callback for an audio player, will be called for every SL_PLAYEVENT_HEADATNEWPOS event */
10285bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivivoid PlayEventCallback( SLPlayItf caller,  void *pContext, SLuint32 event)
10385bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi{
1048c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten    Context *context = (Context *) pContext;
1058c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten    SLPlayItf playItf = context->playItf;
1068c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten    SLMuteSoloItf muteSolo = context->muteSoloItf;
10785bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    SLuint8 numChannels = 0;
10885bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    SLresult res = (*muteSolo)->GetNumChannels(muteSolo, &numChannels); ExitOnError(res);
10985bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    //fprintf(stdout, "Content has %d channel(s)\n", numChannels);
1108c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten    SLmillisecond position;
1118c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten    res = (*playItf)->GetPosition(playItf, &position); ExitOnError(res);
1128c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten    printf("position=%u\n", (unsigned) position);
11385bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
1148c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten    switch (context->testMode) {
11585bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi        case TEST_MUTE: {
11685bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi            //---------------------------------------------------
11785bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi            if (numChannels > 1) { // SLMuteSoloItf only works if more than one channel
11885bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi                SLboolean leftMuted = SL_BOOLEAN_TRUE;
11985bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi                res = (*muteSolo)->GetChannelMute(muteSolo, 0, &leftMuted); ExitOnError(res);
12085bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi                // swap channel mute
12185bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi                res = (*muteSolo)->SetChannelMute(muteSolo, 0,
12285bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi                       leftMuted == SL_BOOLEAN_TRUE ? SL_BOOLEAN_FALSE : SL_BOOLEAN_TRUE);
12385bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi                ExitOnError(res);
12485bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi                res = (*muteSolo)->SetChannelMute(muteSolo, 1,
12585bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi                       leftMuted == SL_BOOLEAN_TRUE ? SL_BOOLEAN_TRUE : SL_BOOLEAN_FALSE);
12685bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi                ExitOnError(res);
12785bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi                if (leftMuted == SL_BOOLEAN_TRUE) { // we've swapped the channel mute above
12885bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi                    fprintf(stdout, "channel 0: playing, channel 1: muted\n");
12985bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi                } else {
13085bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi                    fprintf(stdout, "channel 0: muted, channel 1: playing\n");
13185bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi                }
13285bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi            }
13385bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi            } break;
13485bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
13585bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi        case TEST_SOLO: {
13685bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi            //---------------------------------------------------
13785bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi            if (numChannels > 1) { // SLMuteSoloItf only works if more than one channel
13885bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi                SLboolean leftSoloed = SL_BOOLEAN_TRUE;
13985bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi                res = (*muteSolo)->GetChannelSolo(muteSolo, 0, &leftSoloed); ExitOnError(res);
14085bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi                // swap channel solo
14185bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi                res = (*muteSolo)->SetChannelSolo(muteSolo, 0,
14285bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi                        leftSoloed == SL_BOOLEAN_TRUE ? SL_BOOLEAN_FALSE : SL_BOOLEAN_TRUE);
14385bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi                ExitOnError(res);
14485bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi                res = (*muteSolo)->SetChannelSolo(muteSolo, 1,
14585bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi                        leftSoloed == SL_BOOLEAN_TRUE ? SL_BOOLEAN_TRUE : SL_BOOLEAN_FALSE);
14685bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi                ExitOnError(res);
14785bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi                if (leftSoloed == SL_BOOLEAN_TRUE) { // we've swapped the channel solo above
14885bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi                    fprintf(stdout, "channel 0: normal, channel 1: soloed\n");
14985bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi                } else {
15085bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi                    fprintf(stdout, "channel 0: soloed, channel 1: normal\n");
15185bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi                }
15285bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi            }
15385bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi            } break;
15485bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
15585bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi        default:
15685bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi            break;
15785bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    }
15885bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi}
15985bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
16085bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi//-----------------------------------------------------------------
16185bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
16285bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi/* Play an audio URIs, mute and solo channels  */
16385bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivivoid TestPlayUri( SLObjectItf sl, const char* path)
16485bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi{
16585bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    SLresult  result;
16685bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    SLEngineItf EngineItf;
16785bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
168a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    /* Objects this application uses: one player and an output mix */
16985bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    SLObjectItf  player, outputMix;
17085bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
17185bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    /* Source of audio data to play */
17285bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    SLDataSource      audioSource;
17385bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    SLDataLocator_URI uri;
17485bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    SLDataFormat_MIME mime;
17585bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
17685bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    /* Data sinks for the audio player */
17785bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    SLDataSink               audioSink;
17885bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    SLDataLocator_OutputMix  locator_outputmix;
17985bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
18085bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    /* Play, Volume and PrefetchStatus interfaces for the audio player */
18185bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    SLPlayItf           playItf;
18285bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    SLMuteSoloItf       muteSoloItf;
18385bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    SLPrefetchStatusItf prefetchItf;
18485bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
18585bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    SLboolean required[MAX_NUMBER_INTERFACES];
18685bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    SLInterfaceID iidArray[MAX_NUMBER_INTERFACES];
18785bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
18885bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    /* Get the SL Engine Interface which is implicit */
18985bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    result = (*sl)->GetInterface(sl, SL_IID_ENGINE, (void*)&EngineItf);
19085bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    ExitOnError(result);
19185bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
19285bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    /* Initialize arrays required[] and iidArray[] */
19385bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    for (int i=0 ; i < MAX_NUMBER_INTERFACES ; i++) {
19485bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi        required[i] = SL_BOOLEAN_FALSE;
19585bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi        iidArray[i] = SL_IID_NULL;
19685bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    }
19785bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
19885bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    /* ------------------------------------------------------ */
19985bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    /* Configuration of the output mix  */
20085bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
20185bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    /* Create Output Mix object to be used by the player */
202c2303eb5497c488db786dcb2b8514db229452536Glenn Kasten     result = (*EngineItf)->CreateOutputMix(EngineItf, &outputMix, 0, iidArray, required);
20385bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi     ExitOnError(result);
20485bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
20585bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    /* Realize the Output Mix object in synchronous mode */
20685bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    result = (*outputMix)->Realize(outputMix, SL_BOOLEAN_FALSE);
20785bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    ExitOnError(result);
20885bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
20985bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    /* Setup the data sink structure */
21085bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
21185bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    locator_outputmix.outputMix   = outputMix;
21285bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    audioSink.pLocator            = (void*)&locator_outputmix;
21385bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    audioSink.pFormat             = NULL;
21485bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
21585bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    /* ------------------------------------------------------ */
21685bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    /* Configuration of the player  */
21785bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
21885bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    /* Set arrays required[] and iidArray[] for SLMuteSoloItf and SLPrefetchStatusItf interfaces */
21985bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    /*  (SLPlayItf is implicit) */
22085bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    required[0] = SL_BOOLEAN_TRUE;
22185bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    iidArray[0] = SL_IID_MUTESOLO;
22285bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    required[1] = SL_BOOLEAN_TRUE;
22385bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    iidArray[1] = SL_IID_PREFETCHSTATUS;
22485bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
22585bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    /* Setup the data source structure for the URI */
22685bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    uri.locatorType = SL_DATALOCATOR_URI;
22785bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    uri.URI         =  (SLchar*) path;
22885bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    mime.formatType = SL_DATAFORMAT_MIME;
22985bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    /*     this is how ignored mime information is specified, according to OpenSL ES spec
23085bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi     *     in 9.1.6 SLDataFormat_MIME and 8.23 SLMetadataTraversalItf GetChildInfo */
23185bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    mime.mimeType      = (SLchar*)NULL;
23285bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    mime.containerType = SL_CONTAINERTYPE_UNSPECIFIED;
23385bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
23485bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    audioSource.pFormat  = (void*)&mime;
23585bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    audioSource.pLocator = (void*)&uri;
23685bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
23785bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    /* Create the audio player */
2384b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten    result = (*EngineItf)->CreateAudioPlayer(EngineItf, &player, &audioSource, &audioSink, 2,
23985bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi            iidArray, required);
24085bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    ExitOnError(result);
24185bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
24285bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    /* Realize the player in synchronous mode. */
24385bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    result = (*player)->Realize(player, SL_BOOLEAN_FALSE); ExitOnError(result);
24485bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    fprintf(stdout, "URI example: after Realize\n");
24585bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
24685bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    /* Get the SLPlayItf, SLPrefetchStatusItf and SLMuteSoloItf interfaces for the player */
24785bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    result = (*player)->GetInterface(player, SL_IID_PLAY, (void*)&playItf);
24885bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    ExitOnError(result);
24985bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
250a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    // get the prefetch status interface
25185bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    result = (*player)->GetInterface(player, SL_IID_PREFETCHSTATUS, (void*)&prefetchItf);
25285bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    ExitOnError(result);
25385bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
254a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    // enable prefetch status callbacks
255a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    result = (*prefetchItf)->RegisterCallback(prefetchItf, prefetch_callback, NULL);
256a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
257a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    result = (*prefetchItf)->SetCallbackEventsMask(prefetchItf,
258a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten            SL_PREFETCHEVENT_STATUSCHANGE | SL_PREFETCHEVENT_FILLLEVELCHANGE);
259a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
260a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten
261a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    // get the mute solo interface
26285bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    result = (*player)->GetInterface(player, SL_IID_MUTESOLO, (void*)&muteSoloItf);
26385bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    ExitOnError(result);
26485bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
265a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    // Attempt to get the duration before it is necessarily known.
266a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    // This should always return successfully.
267a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    // The reported duration may be either
268a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    // a particular duration or SL_TIME_UNKNOWN, depending on the platform.
269a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    SLmillisecond duration;
270a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    result = (*playItf)->GetDuration(playItf, &duration);
271a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    ExitOnError(result);
272a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    printf("GetDuration after Realize but before pre-fetch: result=%u, duration=%u\n",
273a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten        result, duration);
274a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten
275f6f5ceb363286d5ebef2c2e70c8a5aa135d5d1eeGlenn Kasten    // Attempt to get the channel count before it is necessarily known.
276a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    // This should either return successfully with a specific value (e.g. 1 or 2),
277c9a59d2a184ac461f46c3d878c6fc2574f1805f0Glenn Kasten    // or return zero, depending on whether the channel count is known yet.
278f6f5ceb363286d5ebef2c2e70c8a5aa135d5d1eeGlenn Kasten    SLuint8 numChannels = 123;
279f6f5ceb363286d5ebef2c2e70c8a5aa135d5d1eeGlenn Kasten    result = (*muteSoloItf)->GetNumChannels(muteSoloItf, &numChannels);
28058432eb9cea995c69b4f905e68b38c1b8216edebGlenn Kasten    printf("GetNumChannels after Realize but before pre-fetch: result=%u, numChannels=%u\n",
281f6f5ceb363286d5ebef2c2e70c8a5aa135d5d1eeGlenn Kasten        result, numChannels);
282a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    if (result != SL_RESULT_PRECONDITIONS_VIOLATED) {
283a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten        ExitOnError(result);
284c9a59d2a184ac461f46c3d878c6fc2574f1805f0Glenn Kasten    } else {
285c9a59d2a184ac461f46c3d878c6fc2574f1805f0Glenn Kasten        printf("Warning: returning SL_RESULT_PRECONDITIONS_VIOLATED for unknown channel count is "
286c9a59d2a184ac461f46c3d878c6fc2574f1805f0Glenn Kasten                "obsolete; now it should return SL_RESULT_SUCCESS and zero count if unknown\n");
287a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    }
288f6f5ceb363286d5ebef2c2e70c8a5aa135d5d1eeGlenn Kasten
289a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    /* Initialize a context for use by the play event callback */
2908c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten    Context             context;
2918c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten    context.playItf = playItf;
2928c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten    context.muteSoloItf = muteSoloItf;
2938c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten    context.testMode = TEST_MUTE;
2948c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten
29585bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    /*  Setup to receive playback events on position updates */
2968c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten    result = (*playItf)->RegisterCallback(playItf, PlayEventCallback, (void *) &context);
29785bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    ExitOnError(result);
29885bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    result = (*playItf)->SetCallbackEventsMask(playItf, SL_PLAYEVENT_HEADATNEWPOS);
29985bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    ExitOnError(result);
30085bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    result = (*playItf)->SetPositionUpdatePeriod(playItf, 1000);
30185bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    ExitOnError(result);
30285bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
30385bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    fprintf(stdout, "Player configured\n");
30485bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
30585bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    /* ------------------------------------------------------ */
30685bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    /* Playback and test */
30785bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
30885bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    /* Start the data prefetching by setting the player to the paused state */
30985bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    result = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PAUSED );
31085bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    ExitOnError(result);
31185bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
312a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    // wait for prefetch status callback to indicate either sufficient data or error
313a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    pthread_mutex_lock(&mutex);
314a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    while (prefetch_status == SL_PREFETCHSTATUS_UNKNOWN) {
315a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten        pthread_cond_wait(&cond, &mutex);
316a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    }
317a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    pthread_mutex_unlock(&mutex);
318a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    if (prefetch_status == SL_PREFETCHSTATUS_ERROR) {
319a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten        fprintf(stderr, "Error during prefetch, exiting\n");
320a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten        goto destroyKillKill;
32185bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    }
32285bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
323a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    /* Query the duration */
324a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    result = (*playItf)->GetDuration(playItf, &duration);
325a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    printf("GetDuration after Realize and after pre-fetch: result=%u, duration=%u\n",
326a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten        result, duration);
327a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    ExitOnError(result);
328a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten
32985bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    /* Query the number of channels */
330f6f5ceb363286d5ebef2c2e70c8a5aa135d5d1eeGlenn Kasten    numChannels = 123;
33185bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    result = (*muteSoloItf)->GetNumChannels(muteSoloItf, &numChannels);
332a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten    printf("GetNumChannels after Realize and after pre-fetch: result=%u, numChannels=%u\n",
333a2478f0cb82910d4ef1202ff0a6b1723565d009fGlenn Kasten        result, numChannels);
33485bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    ExitOnError(result);
33585bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    fprintf(stdout, "Content has %d channel(s)\n", numChannels);
33685bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
33785bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    if (numChannels == 1) {
33885bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi        fprintf(stdout, "SLMuteSolotItf only works one content with more than one channel. Bye\n");
33985bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi        goto destroyKillKill;
34085bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    } else {
34185bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi        /* Mute left channel */
34201e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten        result = (*muteSoloItf)->SetChannelMute(muteSoloItf, 0, SL_BOOLEAN_TRUE);
34301e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten        ExitOnError(result);
34401e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten        result = (*muteSoloItf)->SetChannelMute(muteSoloItf, 1, SL_BOOLEAN_FALSE);
34501e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten        ExitOnError(result);
34685bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    }
34785bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
34885bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    /* Run the test for 10s */
34985bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    /* see PlayEventCallback() for more of the test of the SLMuteSoloItf interface */
35085bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    fprintf(stdout, "\nTesting mute functionality:\n");
3518c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten    context.testMode = TEST_MUTE;
35285bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    result = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PLAYING ); ExitOnError(result);
35385bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    usleep( 5 * 1000 * 1000);
35485bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    result = (*muteSoloItf)->SetChannelMute(muteSoloItf, 0, SL_BOOLEAN_FALSE); ExitOnError(result);
35585bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    result = (*muteSoloItf)->SetChannelMute(muteSoloItf, 1, SL_BOOLEAN_FALSE); ExitOnError(result);
35685bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    fprintf(stdout, "\nTesting solo functionality:\n");
3578c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten    context.testMode = TEST_SOLO;
35885bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    usleep( 5 * 1000 * 1000);
35985bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
36085bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    /* Make sure player is stopped */
36185bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    fprintf(stdout, "Stopping playback\n");
36285bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    result = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED);
36385bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    ExitOnError(result);
36485bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
36585bae78453492b42c7095cafc404a049e52bbc22Jean-Michel TrividestroyKillKill:
36685bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
36785bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    /* Destroy the players */
36885bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    (*player)->Destroy(player);
36985bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
37085bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    /* Destroy Output Mix object */
37185bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    (*outputMix)->Destroy(outputMix);
37285bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi}
37385bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
37485bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi//-----------------------------------------------------------------
37585bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Triviint main(int argc, char* const argv[])
37685bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi{
37785bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    SLresult    result;
37885bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    SLObjectItf sl;
37985bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
38085bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    fprintf(stdout, "OpenSL ES test %s: exercises SLPlayItf, SLVolumeItf, SLMuteSoloItf\n",
38185bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi            argv[0]);
38285bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    fprintf(stdout, "and AudioPlayer with SLDataLocator_URI source / OutputMix sink\n");
38385bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    fprintf(stdout, "Plays a sound and alternates the muting of the channels (for 5s).\n");
38485bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    fprintf(stdout, " and then alternates the solo\'ing of the channels (for 5s).\n");
38585bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    fprintf(stdout, "Stops after 10s\n");
38685bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
38785bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    if (argc == 1) {
38885bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi        fprintf(stdout, "Usage: \t%s url\n", argv[0]);
389e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        fprintf(stdout, "Example: \"%s /sdcard/my.mp3\"\n", argv[0]);
390c2303eb5497c488db786dcb2b8514db229452536Glenn Kasten        exit(EXIT_FAILURE);
39185bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    }
39285bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
39385bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    SLEngineOption EngineOption[] = {
39485bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi            {(SLuint32) SL_ENGINEOPTION_THREADSAFE, (SLuint32) SL_BOOLEAN_TRUE}
39585bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    };
39685bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
39785bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    result = slCreateEngine( &sl, 1, EngineOption, 0, NULL, NULL);
39885bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    ExitOnError(result);
39985bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
40085bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    /* Realizing the SL Engine in synchronous mode. */
40185bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    result = (*sl)->Realize(sl, SL_BOOLEAN_FALSE);
40285bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    ExitOnError(result);
40385bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
40485bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    if (argc > 1) {
40585bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi        TestPlayUri(sl, argv[1]);
40685bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    }
40785bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
40885bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    /* Shutdown OpenSL ES */
40985bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi    (*sl)->Destroy(sl);
41085bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi
411c2303eb5497c488db786dcb2b8514db229452536Glenn Kasten    return EXIT_SUCCESS;
41285bae78453492b42c7095cafc404a049e52bbc22Jean-Michel Trivi}
413