100667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi/*
200667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi * Copyright (C) 2010 The Android Open Source Project
300667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi *
400667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License");
500667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi * you may not use this file except in compliance with the License.
600667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi * You may obtain a copy of the License at
700667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi *
800667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi *      http://www.apache.org/licenses/LICENSE-2.0
900667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi *
1000667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi * Unless required by applicable law or agreed to in writing, software
1100667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS,
1200667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1300667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi * See the License for the specific language governing permissions and
1400667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi * limitations under the License.
1500667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi */
1600667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
1747c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten#include <assert.h>
1800667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi#include <stdlib.h>
1900667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi#include <stdio.h>
2000667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi#include <string.h>
2100667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi#include <unistd.h>
2200667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi#include <sys/time.h>
2300667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi#include <fcntl.h>
2400667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
25c6853892c94800e72c0bd676d5d2136d48cea76eGlenn Kasten#include <SLES/OpenSLES.h>
2600667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi#ifdef ANDROID
27c6853892c94800e72c0bd676d5d2136d48cea76eGlenn Kasten#include <SLES/OpenSLES_Android.h>
2800667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi#endif
2900667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
3000667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
3147c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten#define MAX_NUMBER_INTERFACES 4
3200667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
3347c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten#define TIME_S_BETWEEN_SETTING_CHANGE 3
3400667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
3500667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi//-----------------------------------------------------------------
3600667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi/* Exits the application if an error is encountered */
3700667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi#define ExitOnError(x) ExitOnErrorFunc(x,__LINE__)
3800667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
3900667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivivoid ExitOnErrorFunc( SLresult result , int line)
4000667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi{
4100667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    if (SL_RESULT_SUCCESS != result) {
4258432eb9cea995c69b4f905e68b38c1b8216edebGlenn Kasten        fprintf(stderr, "%u error code encountered at line %d, exiting\n", result, line);
43c2303eb5497c488db786dcb2b8514db229452536Glenn Kasten        exit(EXIT_FAILURE);
4400667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    }
4500667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi}
4600667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
4747c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten// Prefetch status callback
4847c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten
4947c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten#define PREFETCHEVENT_ERROR_CANDIDATE \
5047c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten            (SL_PREFETCHEVENT_STATUSCHANGE | SL_PREFETCHEVENT_FILLLEVELCHANGE)
5147c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten
5247c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn KastenSLboolean errorInPrefetchCallback = SL_BOOLEAN_FALSE;
5347c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten
5447c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kastenvoid prefetch_callback(SLPrefetchStatusItf caller, void *context, SLuint32 event)
5547c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten{
5647c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    SLresult result;
5747c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    assert(context == NULL);
5847c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    SLpermille level;
5947c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    result = (*caller)->GetFillLevel(caller, &level);
6047c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    ExitOnError(result);
6147c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    SLuint32 status;
6247c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    result = (*caller)->GetPrefetchStatus(caller, &status);
6347c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    ExitOnError(result);
6447c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    if ((PREFETCHEVENT_ERROR_CANDIDATE == (event & PREFETCHEVENT_ERROR_CANDIDATE))
6547c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten            && (level == 0) && (status == SL_PREFETCHSTATUS_UNDERFLOW)) {
6647c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten        errorInPrefetchCallback = SL_BOOLEAN_TRUE;
6747c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    }
6847c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten}
6900667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
7000667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi//-----------------------------------------------------------------
7100667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
7200667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi/* Play an audio path and feed a global reverb  */
7300667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivivoid TestSendToPresetReverb( SLObjectItf sl, const char* path, int preset, SLmillibel directLevel,
7447c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten        SLmillibel sendLevel, bool alwaysOn, bool useFd, bool loop)
7500667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi{
7600667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    SLresult  result;
7700667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    SLEngineItf EngineItf;
7800667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
7900667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /* Objects this application uses: one player and an ouput mix */
8000667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    SLObjectItf  player, outputMix;
8100667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
8200667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /* Source of audio data to play */
8300667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    SLDataSource            audioSource;
8400667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi#ifdef ANDROID
8500667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    SLDataLocator_AndroidFD locatorFd;
8600667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi#endif
8747c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    SLDataLocator_URI       locatorUri;
8800667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    SLDataFormat_MIME       mime;
8900667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
9000667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /* Data sinks for the audio player */
9100667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    SLDataSink               audioSink;
9200667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    SLDataLocator_OutputMix  locator_outputmix;
9300667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
9400667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /* Interfaces for the audio player */
9500667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    SLPlayItf              playItf;
967c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten    SLPrefetchStatusItf    prefetchItf;
9700667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    SLEffectSendItf        effectSendItf;
9847c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    SLSeekItf              seekItf;
9900667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
10000667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /* Interface for the output mix */
10100667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    SLPresetReverbItf      reverbItf;
10200667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
10300667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    SLboolean required[MAX_NUMBER_INTERFACES];
10400667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    SLInterfaceID iidArray[MAX_NUMBER_INTERFACES];
10500667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
10600667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /* Get the SL Engine Interface which is implicit */
10700667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    result = (*sl)->GetInterface(sl, SL_IID_ENGINE, (void*)&EngineItf);
10800667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    ExitOnError(result);
10900667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
11000667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /* Initialize arrays required[] and iidArray[] */
11100667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    for (int i=0 ; i < MAX_NUMBER_INTERFACES ; i++) {
11200667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi        required[i] = SL_BOOLEAN_FALSE;
11300667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi        iidArray[i] = SL_IID_NULL;
11400667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    }
11500667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
11600667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /* ------------------------------------------------------ */
11700667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /* Configuration of the output mix  */
11800667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
11900667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /* Set arrays required[] and iidArray[] for required interfaces */
12000667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    required[0] = SL_BOOLEAN_TRUE;
12100667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    iidArray[0] = SL_IID_PRESETREVERB;
12200667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
12300667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /* Create Output Mix object to be used by the player */
12400667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi     result = (*EngineItf)->CreateOutputMix(EngineItf, &outputMix, 1, iidArray, required);
12500667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi     ExitOnError(result);
12600667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
12700667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /* Realize the Output Mix object in synchronous mode */
12800667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    result = (*outputMix)->Realize(outputMix, SL_BOOLEAN_FALSE);
12900667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    ExitOnError(result);
13000667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
13100667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /* Get the SLPresetReverbItf for the output mix */
13200667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    result = (*outputMix)->GetInterface(outputMix, SL_IID_PRESETREVERB, (void*)&reverbItf);
13300667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    ExitOnError(result);
13400667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
13500667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /* Setup the data sink structure */
13600667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
13700667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    locator_outputmix.outputMix   = outputMix;
13800667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    audioSink.pLocator            = (void*)&locator_outputmix;
13900667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    audioSink.pFormat             = NULL;
14000667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
14100667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /* Select the reverb preset */
14200667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    fprintf(stdout, "\nUsing preset ");
14300667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    switch(preset) {
14400667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi        case SL_REVERBPRESET_NONE:
14500667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi            fprintf(stdout, "SL_REVERBPRESET_NONE, don't expect to hear reverb\n");
14600667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi            break;
14700667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi        case SL_REVERBPRESET_SMALLROOM: fprintf(stdout, "SL_REVERBPRESET_SMALLROOM\n"); break;
14800667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi        case SL_REVERBPRESET_MEDIUMROOM: fprintf(stdout, "SL_REVERBPRESET_MEDIUMROOM\n"); break;
14900667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi        case SL_REVERBPRESET_LARGEROOM: fprintf(stdout, "SL_REVERBPRESET_LARGEROOM\n"); break;
15000667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi        case SL_REVERBPRESET_MEDIUMHALL: fprintf(stdout, "SL_REVERBPRESET_MEDIUMHALL\n"); break;
15100667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi        case SL_REVERBPRESET_LARGEHALL: fprintf(stdout, "SL_REVERBPRESET_LARGEHALL\n"); break;
15200667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi        case SL_REVERBPRESET_PLATE: fprintf(stdout, "SL_REVERBPRESET_PLATE\n"); break;
15300667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi        default:
15400667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi            fprintf(stdout, "unknown, use at your own risk\n"); break;
15500667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    }
15600667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    result = (*reverbItf)->SetPreset(reverbItf, preset);
15700667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    ExitOnError(result);
15800667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
15900667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /* ------------------------------------------------------ */
16000667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /* Configuration of the player  */
16100667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
16200667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /* Set arrays required[] and iidArray[] for required interfaces */
16300667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /*  (SLPlayItf is implicit) */
16400667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    required[0] = SL_BOOLEAN_TRUE;
16500667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    iidArray[0] = SL_IID_PREFETCHSTATUS;
16600667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    required[1] = SL_BOOLEAN_TRUE;
16700667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    iidArray[1] = SL_IID_EFFECTSEND;
16847c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    required[2] = SL_BOOLEAN_TRUE;
16947c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    iidArray[2] = SL_IID_SEEK;
17000667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
17100667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    locatorUri.locatorType = SL_DATALOCATOR_URI;
17200667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    locatorUri.URI = (SLchar *) path;
17347c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    audioSource.pLocator = (void*)&locatorUri;
17447c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    if (useFd) {
17547c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten#ifdef ANDROID
17647c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten        /* Setup the data source structure for the URI */
17747c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten        locatorFd.locatorType = SL_DATALOCATOR_ANDROIDFD;
17847c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten        int fd = open(path, O_RDONLY);
17947c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten        if (fd == -1) {
18047c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten            perror(path);
18147c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten            exit(EXIT_FAILURE);
18247c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten        }
18347c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten        locatorFd.fd = (SLint32) fd;
18447c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten        locatorFd.length = SL_DATALOCATOR_ANDROIDFD_USE_FILE_SIZE;
18547c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten        locatorFd.offset = 0;
18647c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten        audioSource.pLocator = (void*)&locatorFd;
18747c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten#else
18847c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten        fprintf(stderr, "option --fd is not supported\n");
18900667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi#endif
19047c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    }
19100667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
19200667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    mime.formatType = SL_DATAFORMAT_MIME;
19300667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /*     this is how ignored mime information is specified, according to OpenSL ES spec
19400667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi     *     in 9.1.6 SLDataFormat_MIME and 8.23 SLMetadataTraversalItf GetChildInfo */
19500667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    mime.mimeType      = (SLchar*)NULL;
19600667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    mime.containerType = SL_CONTAINERTYPE_UNSPECIFIED;
19700667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
19800667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    audioSource.pFormat  = (void*)&mime;
19900667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
20000667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /* Create the audio player */
20147c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    result = (*EngineItf)->CreateAudioPlayer(EngineItf, &player, &audioSource, &audioSink, 3,
20200667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi            iidArray, required);
20300667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    ExitOnError(result);
20400667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
20500667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /* Realize the player in synchronous mode. */
20600667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    result = (*player)->Realize(player, SL_BOOLEAN_FALSE); ExitOnError(result);
20700667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    fprintf(stdout, "URI example: after Realize\n");
20800667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
20900667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /* Get the SLPlayItf, SLPrefetchStatusItf and SLEffectSendItf interfaces for the player*/
21000667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    result = (*player)->GetInterface(player, SL_IID_PLAY, (void*)&playItf);
21100667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    ExitOnError(result);
21200667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
2137c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten    result = (*player)->GetInterface(player, SL_IID_PREFETCHSTATUS, (void*)&prefetchItf);
2147c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten    ExitOnError(result);
21547c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    result = (*prefetchItf)->RegisterCallback(prefetchItf, prefetch_callback, NULL);
21647c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    ExitOnError(result);
21747c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    result = (*prefetchItf)->SetCallbackEventsMask(prefetchItf,
21847c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten            SL_PREFETCHEVENT_STATUSCHANGE | SL_PREFETCHEVENT_FILLLEVELCHANGE);
21947c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    ExitOnError(result);
2207c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten
22100667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    result = (*player)->GetInterface(player, SL_IID_EFFECTSEND, (void*)&effectSendItf);
22200667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    ExitOnError(result);
22300667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
22447c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    result = (*player)->GetInterface(player, SL_IID_SEEK, (void*)&seekItf);
22547c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    ExitOnError(result);
22647c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten
22700667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    fprintf(stdout, "Player configured\n");
22800667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
22900667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /* ------------------------------------------------------ */
23000667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /* Playback and test */
23100667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
2327c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten    /* Start the data prefetching by setting the player to the paused state */
2337c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten    result = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PAUSED );
2347c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten    ExitOnError(result);
2357c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten
2367c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten    /* Wait until there's data to play */
2377c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten    SLuint32 prefetchStatus = SL_PREFETCHSTATUS_UNDERFLOW;
2387c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten    while (prefetchStatus != SL_PREFETCHSTATUS_SUFFICIENTDATA) {
23947c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten        if (errorInPrefetchCallback) {
24047c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten            fprintf(stderr, "Error during prefetch, exiting\n");
24147c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten            exit(EXIT_FAILURE);
24247c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten        }
2437c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten        usleep(100 * 1000);
2447c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten        (*prefetchItf)->GetPrefetchStatus(prefetchItf, &prefetchStatus);
2457c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten        ExitOnError(result);
2467c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten    }
2477c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten
24800667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /* Get duration */
24900667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    SLmillisecond durationInMsec = SL_TIME_UNKNOWN;
25000667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    result = (*playItf)->GetDuration(playItf, &durationInMsec);
25100667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    ExitOnError(result);
25200667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    if (durationInMsec == SL_TIME_UNKNOWN) {
25347c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten        printf("Duration unknown, assuming 10 seconds\n");
2542246c698482ab6860906672229f0ae6d886e6302Glenn Kasten        durationInMsec = 10000;
25547c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    } else {
25647c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten        printf("Duration is %.1f seconds\n", durationInMsec / 1000.0);
25700667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    }
25800667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
25900667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /* Feed the output mix' reverb from the audio player using the given send level */
26000667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    result = (*effectSendItf)->EnableEffectSend(effectSendItf, reverbItf, SL_BOOLEAN_TRUE,
26100667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi            sendLevel);
26200667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    ExitOnError(result);
26300667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
26400667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    result = (*effectSendItf)->SetDirectLevel(effectSendItf, directLevel);
26500667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    ExitOnError(result);
26600667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    fprintf(stdout, "Set direct level to %dmB\n", directLevel);
26700667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
26800667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    result = (*effectSendItf)->SetSendLevel(effectSendItf, reverbItf, sendLevel);
26900667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    ExitOnError(result);
27000667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    fprintf(stdout, "Set send level to %dmB\n", sendLevel);
27100667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
27247c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    /* Enable looping */
27347c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    if (loop) {
27447c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten        result = (*seekItf)->SetLoop(seekItf, SL_BOOLEAN_TRUE, (SLmillisecond) 0, SL_TIME_UNKNOWN);
27547c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten        ExitOnError(result);
27647c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    }
27747c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten
27800667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /* Start playback */
27900667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    result = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PLAYING );
28000667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    ExitOnError(result);
28100667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
2827c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten    /* Disable preset reverb every TIME_S_BETWEEN_SETTING_CHANGE seconds unless always on */
2837c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten    SLboolean previousEnabled = SL_BOOLEAN_FALSE;
28447c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    SLuint32 playState;
28547c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    for (;;) {
28647c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten        result = (*playItf)->GetPlayState(playItf, &playState);
28747c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten        ExitOnError(result);
28847c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten        if (playState != SL_PLAYSTATE_PLAYING)
28947c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten            break;
2907c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten        SLboolean enabled;
2917c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten        enabled = alwaysOn || !previousEnabled;
2927c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten        if (enabled != previousEnabled) {
2937c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten            result = (*reverbItf)->SetPreset(reverbItf, enabled ? preset : SL_REVERBPRESET_NONE);
294c2f5fd8659f405de1a4769dfb075b2b27b217bd8Glenn Kasten            fprintf(stdout, "SetPreset(%d)=%d\n", enabled ? preset : SL_REVERBPRESET_NONE, result);
29547c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten            ExitOnError(result);
2967c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten            previousEnabled = enabled;
2977c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten            if (enabled) {
2987c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten                fprintf(stdout, "Reverb on\n");
2997c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten            } else {
3007c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten                fprintf(stdout, "Reverb off\n");
3017c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten            }
30200667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi        }
30300667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi        usleep(TIME_S_BETWEEN_SETTING_CHANGE * 1000 * 1000);
30400667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    }
30500667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
30600667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /* Make sure player is stopped */
30747c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    assert(playState == SL_PLAYSTATE_STOPPED);
30847c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten#if 0
30900667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    fprintf(stdout, "Stopping playback\n");
31000667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    result = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED);
31100667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    ExitOnError(result);
31247c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten#endif
31300667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
31400667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /* Destroy the player */
31500667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    (*player)->Destroy(player);
31600667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
31700667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /* Destroy Output Mix object */
31800667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    (*outputMix)->Destroy(outputMix);
31900667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
32000667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi#ifdef ANDROID
32147c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    if (useFd)
32247c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten        close(locatorFd.fd);
32300667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi#endif
32400667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi}
32500667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
32600667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi//-----------------------------------------------------------------
32700667fcca51d62236b538e6857b7e6b923453569Jean-Michel Triviint main(int argc, char* const argv[])
32800667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi{
3297c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten    const char *programName = argv[0];
33000667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    SLresult    result;
33100667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    SLObjectItf sl;
33200667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
3337c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten    fprintf(stdout, "OpenSL ES test %s: exercises SLEffectSendItf ", programName);
33400667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    fprintf(stdout, "on AudioPlayer and SLPresetReverbItf on OutputMix.\n");
33500667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    fprintf(stdout, "Plays the sound file designated by the given path, ");
33600667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    fprintf(stdout, "and sends a specified amount of energy to a global reverb\n");
33700667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    fprintf(stdout, "(sendLevel in mB), with a given direct level (in mB).\n");
33847c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    fprintf(stdout, "Every %d seconds, the reverb is turned on and off,\n",
33900667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi            TIME_S_BETWEEN_SETTING_CHANGE);
3407c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten    fprintf(stdout, "unless the --always-on option is specified before the path.\n");
3417c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten
3427c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten    bool alwaysOn = false;
34347c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    bool useFd = false;
34447c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    bool loop = false;
34547c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    int i;
34647c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    for (i = 1; i < argc; ++i) {
34747c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten        const char *arg = argv[i];
34847c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten        if (arg[0] != '-')
34947c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten            break;
35047c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten        if (!strcmp(arg, "--always-on")) {
35147c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten            alwaysOn = true;
35247c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten        } else if (!strcmp(arg, "--fd")) {
35347c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten            useFd = true;
35447c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten        } else if (!strcmp(arg, "--loop")) {
35547c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten            loop = true;
35647c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten        } else {
35747c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten            fprintf(stderr, "unknown option %s ignored\n", arg);
35847c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten        }
3597c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten    }
36000667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
36147c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    if (argc - i != 4) {
36247c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten        fprintf(stdout, "Usage: \t%s [--always-on] [--fd] [--loop] path preset directLevel "
36347c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten                "sendLevel\n", programName);
3647c7511aa96e54d94df836357fbbf76c681f20a26Glenn Kasten        fprintf(stdout, "Example: \"%s /sdcard/my.mp3 6 -2000 0\" \n", programName);
365c2303eb5497c488db786dcb2b8514db229452536Glenn Kasten        exit(EXIT_FAILURE);
36600667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    }
36700667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
36800667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    SLEngineOption EngineOption[] = {
36900667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi            {(SLuint32) SL_ENGINEOPTION_THREADSAFE, (SLuint32) SL_BOOLEAN_TRUE}
37000667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    };
37100667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
37200667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    result = slCreateEngine( &sl, 1, EngineOption, 0, NULL, NULL);
37300667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    ExitOnError(result);
37400667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
37500667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /* Realizing the SL Engine in synchronous mode. */
37600667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    result = (*sl)->Realize(sl, SL_BOOLEAN_FALSE);
37700667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    ExitOnError(result);
37800667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
37900667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    // intentionally not checking that levels are of correct value
38047c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten    TestSendToPresetReverb(sl, argv[i], atoi(argv[i+1]), (SLmillibel)atoi(argv[i+2]),
38147c325b8fe4cd967886ee82070c1eb3d1bb0c18cGlenn Kasten            (SLmillibel)atoi(argv[i+3]), alwaysOn, useFd, loop);
38200667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
38300667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    /* Shutdown OpenSL ES */
38400667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi    (*sl)->Destroy(sl);
38500667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi
386c2303eb5497c488db786dcb2b8514db229452536Glenn Kasten    return EXIT_SUCCESS;
38700667fcca51d62236b538e6857b7e6b923453569Jean-Michel Trivi}
388