1b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten/*
2b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten * Copyright (C) 2010 The Android Open Source Project
3b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten *
4b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten * Licensed under the Apache License, Version 2.0 (the "License");
5b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten * you may not use this file except in compliance with the License.
6b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten * You may obtain a copy of the License at
7b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten *
8b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten *      http://www.apache.org/licenses/LICENSE-2.0
9b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten *
10b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten * Unless required by applicable law or agreed to in writing, software
11b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten * distributed under the License is distributed on an "AS IS" BASIS,
12b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten * See the License for the specific language governing permissions and
14b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten * limitations under the License.
15b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten */
16b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten
17095ce2204cc75a50d9f1df60d1c8f357209a7c3dGlenn Kasten// This test program tortures the seek APIs by positioning "randomly" in a file.
18095ce2204cc75a50d9f1df60d1c8f357209a7c3dGlenn Kasten// It needs as input a permuted .wav and .map produced by the permute tool.
19b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten
20c6853892c94800e72c0bd676d5d2136d48cea76eGlenn Kasten#include <SLES/OpenSLES.h>
21b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten#include <assert.h>
22b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten#include <stdio.h>
23b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten#include <stdlib.h>
24b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten#include <unistd.h>
25b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten
26b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten#define ASSERT_EQ(x, y) assert((x) == (y))
27b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten
28b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kastenint main(int argc, char **argv)
29b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten{
30b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    if (argc != 3) {
31b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten        fprintf(stderr, "usage: %s file.wav file.map\n", argv[0]);
32095ce2204cc75a50d9f1df60d1c8f357209a7c3dGlenn Kasten        fprintf(stderr, "  where file.wav and file.map are created by the permute tool\n");
33b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten        return EXIT_FAILURE;
34b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    }
35b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten
36b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    SLresult result;
37b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten
38b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    // create engine
39b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    SLObjectItf engineObject;
40b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
41b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    ASSERT_EQ(SL_RESULT_SUCCESS, result);
42b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
43b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    ASSERT_EQ(SL_RESULT_SUCCESS, result);
44b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    SLEngineItf engineEngine;
45b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
46b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    ASSERT_EQ(SL_RESULT_SUCCESS, result);
47b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten
48b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    // create output mix
49b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    SLObjectItf outputmixObject;
50b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    result = (*engineEngine)->CreateOutputMix(engineEngine, &outputmixObject, 0, NULL, NULL);
51b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    ASSERT_EQ(SL_RESULT_SUCCESS, result);
52b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    result = (*outputmixObject)->Realize(outputmixObject, SL_BOOLEAN_FALSE);
53b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    ASSERT_EQ(SL_RESULT_SUCCESS, result);
54b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten
55b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    // create an audio player with URI source and output mix sink
56b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    SLDataSource audiosrc;
57b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    SLDataSink audiosnk;
58b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    SLDataLocator_OutputMix locator_outputmix;
59b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    SLDataLocator_URI locator_uri;
60c0b196d740ef7a60728a014be0eaadb0dbc1d7aeGlenn Kasten    SLDataFormat_MIME mime;
61b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    locator_uri.locatorType = SL_DATALOCATOR_URI;
62e629abc58c2acadc7487ea71c1e063f8f8989199Glenn Kasten    locator_uri.URI = (SLchar *) argv[1];
63b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
64b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    locator_outputmix.outputMix = outputmixObject;
65c0b196d740ef7a60728a014be0eaadb0dbc1d7aeGlenn Kasten    mime.formatType = SL_DATAFORMAT_MIME;
66c0b196d740ef7a60728a014be0eaadb0dbc1d7aeGlenn Kasten    mime.mimeType = (SLchar *) NULL;
67c0b196d740ef7a60728a014be0eaadb0dbc1d7aeGlenn Kasten    mime.containerType = SL_CONTAINERTYPE_UNSPECIFIED;
68b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    audiosrc.pLocator = &locator_uri;
69c0b196d740ef7a60728a014be0eaadb0dbc1d7aeGlenn Kasten    audiosrc.pFormat = &mime;
70b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    audiosnk.pLocator = &locator_outputmix;
71b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    audiosnk.pFormat = NULL;
72b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    SLObjectItf playerObject;
73b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    SLInterfaceID ids[1] = {SL_IID_SEEK};
74b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    SLboolean flags[1] = {SL_BOOLEAN_TRUE};
75a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi    result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, &audiosrc, &audiosnk,
76a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi            1, ids, flags);
77b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    ASSERT_EQ(SL_RESULT_SUCCESS, result);
78b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    result = (*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE);
79b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    ASSERT_EQ(SL_RESULT_SUCCESS, result);
80b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    SLPlayItf playerPlay;
81b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playerPlay);
82b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    ASSERT_EQ(SL_RESULT_SUCCESS, result);
83b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    SLSeekItf playerSeek;
84b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    result = (*playerObject)->GetInterface(playerObject, SL_IID_SEEK, &playerSeek);
85b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    ASSERT_EQ(SL_RESULT_SUCCESS, result);
86b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    SLmillisecond duration;
87b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    result = (*playerPlay)->GetDuration(playerPlay, &duration);
88b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    ASSERT_EQ(SL_RESULT_SUCCESS, result);
89b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PAUSED);
90b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    ASSERT_EQ(SL_RESULT_SUCCESS, result);
91b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    result = (*playerPlay)->GetDuration(playerPlay, &duration);
92b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    ASSERT_EQ(SL_RESULT_SUCCESS, result);
93b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING);
94b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    ASSERT_EQ(SL_RESULT_SUCCESS, result);
95b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten
96b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten#if 1
97b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    // play back a file in permuted order using the seek map
98b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    FILE *fp_map = fopen(argv[2], "r");
99b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    if (fp_map != NULL) {
100b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten        unsigned position, duration;
101b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten        while (fscanf(fp_map, "%u %u", &position, &duration) == 2) {
102b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten            printf("%u %u\n", position, duration);
103a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi            result = (*playerSeek)->SetPosition(playerSeek, (SLmillisecond) position,
104a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi                    SL_SEEKMODE_ACCURATE);
105b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten            ASSERT_EQ(SL_RESULT_SUCCESS, result);
106b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten            if (duration > 0)
107b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten                usleep(duration * 1000);
108b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten        }
109b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    }
110b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten#else
111b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    set_conio_terminal_mode();
112b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten
113b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    // loop repeatedly, inflicting seek pain each cycle
114b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    for (;;) {
115b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten        if (kbhit()) {
116b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten            switch (getch()) {
117b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten            case 'q':
118b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten                goto out;
119b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten            }
120b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten        }
121b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten        SLmillisecond delay = 100 + (rand() & 8191);
122b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten        printf("sleep %u\n", (unsigned) delay);
123b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten        usleep(delay * 1000);
124b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten        SLmillisecond newPos = duration * ((rand() & 65535) / 65536.0);
125b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten        printf("seek %u\n", (unsigned) newPos);
126b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten        result = (*playerSeek)->SetPosition(playerSeek, newPos, SL_SEEKMODE_ACCURATE);
127b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten        ASSERT_EQ(SL_RESULT_SUCCESS, result);
128b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten        SLmillisecond nowPos;
129b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten        result = (*playerPlay)->GetPosition(playerPlay, &nowPos);
130b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten        ASSERT_EQ(SL_RESULT_SUCCESS, result);
131b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten        printf("now %u\n", (unsigned) newPos);
132b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    }
133b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kastenout:
134b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten#endif
135b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten
136b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten    return EXIT_SUCCESS;
137b9fa556e62aa6e0c8a59f224136e509df813cfc7Glenn Kasten}
138