1711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten/*
2711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten * Copyright (C) 2010 The Android Open Source Project
3711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten *
4711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten * Licensed under the Apache License, Version 2.0 (the "License");
5711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten * you may not use this file except in compliance with the License.
6711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten * You may obtain a copy of the License at
7711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten *
8711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten *      http://www.apache.org/licenses/LICENSE-2.0
9711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten *
10711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten * Unless required by applicable law or agreed to in writing, software
11711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten * distributed under the License is distributed on an "AS IS" BASIS,
12711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten * See the License for the specific language governing permissions and
14711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten * limitations under the License.
15711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten */
16711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
17711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten// Test audio player configurations with URI data source and MIME data format
18711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
19711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten#include <assert.h>
20711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten#include <math.h>
21711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten#include <stdio.h>
22711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten#include <stdlib.h>
23c2303eb5497c488db786dcb2b8514db229452536Glenn Kasten#include <unistd.h>
24711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
25c6853892c94800e72c0bd676d5d2136d48cea76eGlenn Kasten#include <SLES/OpenSLES.h>
26711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten#ifdef ANDROID
27c6853892c94800e72c0bd676d5d2136d48cea76eGlenn Kasten#include <SLES/OpenSLES_Android.h>
28711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten#endif
29711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
30711332800108ad6e0e594796e5f8db0da3eff402Glenn Kastenint main(int argc, char **argv)
31711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten{
32711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    if (argc != 2) {
33711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        fprintf(stderr, "usage: %s URI\n", argv[0]);
34711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        return EXIT_FAILURE;
35711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    }
36711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
37711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    SLresult result;
38711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    SLObjectItf engineObject;
39711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
40711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    // create engine
41711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
42711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    assert(SL_RESULT_SUCCESS == result);
43711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    SLEngineItf engineEngine;
44711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
45711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    assert(SL_RESULT_SUCCESS == result);
46711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
47711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    assert(SL_RESULT_SUCCESS == result);
48711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
49711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    // create output mix
50711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    SLObjectItf outputMixObject;
51711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, NULL, NULL);
52711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    assert(SL_RESULT_SUCCESS == result);
53711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
54711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    assert(SL_RESULT_SUCCESS == result);
55711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
56711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    // configure audio source
57711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    SLDataLocator_URI loc_uri;
58711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    loc_uri.locatorType = SL_DATALOCATOR_URI;
59e629abc58c2acadc7487ea71c1e063f8f8989199Glenn Kasten    loc_uri.URI = (SLchar *) argv[1];
60711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    SLDataFormat_MIME format_mime;
61711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    format_mime.formatType = SL_DATAFORMAT_MIME;
62711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    format_mime.mimeType = NULL;
63711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    format_mime.containerType = SL_CONTAINERTYPE_UNSPECIFIED;
64711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    SLDataSource audioSrc;
65711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    audioSrc.pLocator = &loc_uri;
66711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    audioSrc.pFormat = &format_mime;
67711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
68711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    // configure audio sink
69711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    SLDataLocator_OutputMix loc_outmix;
70711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
71711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    loc_outmix.outputMix = outputMixObject;
72711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    SLDataSink audioSnk;
73711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    audioSnk.pLocator = &loc_outmix;
74711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    audioSnk.pFormat = NULL;
75711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
76711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    // create audio player, requesting a buffer queue interface
77711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    SLuint32 numInterfaces = 1;
78711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    SLInterfaceID ids[1];
79711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    SLboolean req[1];
80711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    ids[0] = SL_IID_BUFFERQUEUE;
81711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    req[0] = SL_BOOLEAN_TRUE;
82711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    SLObjectItf playerObject;
83711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, &audioSrc,
84711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten            &audioSnk, numInterfaces, ids, req);
85711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    assert(SL_RESULT_FEATURE_UNSUPPORTED == result);
86711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    assert(NULL == playerObject);
87711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten#ifdef ANDROID
88711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    ids[0] = SL_IID_ANDROIDSIMPLEBUFFERQUEUE;
89711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, &audioSrc,
90711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten            &audioSnk, numInterfaces, ids, req);
91711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    assert(SL_RESULT_FEATURE_UNSUPPORTED == result);
92711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    assert(NULL == playerObject);
93711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten#endif
94711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
95711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    // create audio player, without requesting a buffer queue interface
96711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, &audioSrc,
97711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten            &audioSnk, 0, NULL, NULL);
98711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    assert(SL_RESULT_SUCCESS == result);
99711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
100711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    // realize the player
101711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    result = (*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE);
102711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    assert(SL_RESULT_SUCCESS == result);
103711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
104711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    // get the play interface
105711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    SLPlayItf playerPlay;
106711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playerPlay);
107711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    assert(SL_RESULT_SUCCESS == result);
108711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
109711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    // get the buffer queue interface
110711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    SLBufferQueueItf playerBufferQueue;
111711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    result = (*playerObject)->GetInterface(playerObject, SL_IID_BUFFERQUEUE, &playerBufferQueue);
112711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    assert(SL_RESULT_FEATURE_UNSUPPORTED == result);
113711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    assert(NULL == playerBufferQueue);
114711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten#ifdef ANDROID
115711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    SLAndroidSimpleBufferQueueItf playerAndroidSimpleBufferQueue;
116711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    result = (*playerObject)->GetInterface(playerObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
117711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten            &playerAndroidSimpleBufferQueue);
118711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    assert(SL_RESULT_FEATURE_UNSUPPORTED == result);
119711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    assert(NULL == playerAndroidSimpleBufferQueue);
120711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten#endif
121711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
122711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    // get the player duration
123711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    SLmillisecond duration;
124711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    result = (*playerPlay)->GetDuration(playerPlay, &duration);
125711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    assert(SL_RESULT_SUCCESS == result);
126711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    if (SL_TIME_UNKNOWN == duration)
127711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        printf("Duration: unknown\n");
128711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    else
129711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        printf("Duration: %.1f\n", duration / 1000.0f);
130711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
131711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    // set the player's state to playing
132711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING);
133711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    assert(SL_RESULT_SUCCESS == result);
134711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
135711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    // wait for the playback to finish
136711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    for (;;) {
137711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        SLuint32 playState;
138711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        result = (*playerPlay)->GetPlayState(playerPlay, &playState);
139711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        assert(SL_RESULT_SUCCESS == result);
140711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        if (SL_PLAYSTATE_PLAYING != playState) {
141711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten            break;
142711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        }
143711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        usleep(10000);
144711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    }
145711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
146711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    // get the player duration
147711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    result = (*playerPlay)->GetDuration(playerPlay, &duration);
148711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    assert(SL_RESULT_SUCCESS == result);
149711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    if (SL_TIME_UNKNOWN == duration)
150711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        printf("Duration: unknown\n");
151711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    else
152711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten        printf("Duration: %.1f\n", duration / 1000.0f);
153711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
154711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    // destroy audio player
155711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    (*playerObject)->Destroy(playerObject);
156711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
157711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    // destroy output mix
158711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    (*outputMixObject)->Destroy(outputMixObject);
159711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
160711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    // destroy engine
161711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    (*engineObject)->Destroy(engineObject);
162711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten
163711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten    return EXIT_SUCCESS;
164711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten}
165