SndFile.c revision 369f3138f19f7102bf0f98b890ab84c8df633a93
1b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten/*
2b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten * Copyright (C) 2010 The Android Open Source Project
3b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten *
4b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten * Licensed under the Apache License, Version 2.0 (the "License");
5b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten * you may not use this file except in compliance with the License.
6b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten * You may obtain a copy of the License at
7b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten *
8b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten *      http://www.apache.org/licenses/LICENSE-2.0
9b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten *
10b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten * Unless required by applicable law or agreed to in writing, software
11b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten * distributed under the License is distributed on an "AS IS" BASIS,
12b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten * See the License for the specific language governing permissions and
14b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten * limitations under the License.
15b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten */
16b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten
17369f3138f19f7102bf0f98b890ab84c8df633a93Glenn Kasten/** \brief libsndfile integration */
18b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten
19b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten#include "sles_allinclusive.h"
20b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten
21b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten#ifdef USE_SNDFILE
22b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten
23369f3138f19f7102bf0f98b890ab84c8df633a93Glenn Kasten/** \brief Called by BufferQueue after each buffer is consumed */
24369f3138f19f7102bf0f98b890ab84c8df633a93Glenn Kasten
256a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kastenvoid SndFile_Callback(SLBufferQueueItf caller, void *pContext)
26b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten{
27276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten    CAudioPlayer *thisAP = (CAudioPlayer *) pContext;
28e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    object_lock_peek(&thisAP->mObject);
29e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    SLuint32 state = thisAP->mPlay.mState;
30e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    object_unlock_peek(&thisAP->mObject);
314b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten    // FIXME should not muck around directly at this low level
32e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    if (SL_PLAYSTATE_PLAYING != state)
33276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten        return;
34276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten    struct SndFile *this = &thisAP->mSndFile;
35b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    SLresult result;
364b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten    pthread_mutex_lock(&this->mMutex);
374b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten    if ((NULL != this->mRetryBuffer) && (0 < this->mRetrySize)) {
3827f8dfaea17ab7831a1bd34a02f85d55bacf67b7Glenn Kasten        result = (*caller)->Enqueue(caller, this->mRetryBuffer, this->mRetrySize);
394b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        if (SL_RESULT_BUFFER_INSUFFICIENT == result) {
404b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            pthread_mutex_unlock(&this->mMutex);
41b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten            return;     // what, again?
424b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        }
43b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        assert(SL_RESULT_SUCCESS == result);
44b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        this->mRetryBuffer = NULL;
45b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        this->mRetrySize = 0;
464b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        pthread_mutex_unlock(&this->mMutex);
47b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        return;
48b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    }
49e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    if (this->mEOF) {
50e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        pthread_mutex_unlock(&this->mMutex);
51e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        return;
52e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    }
536a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten    short *pBuffer = &this->mBuffer[this->mWhich * SndFile_BUFSIZE];
546a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten    if (++this->mWhich >= SndFile_NUMBUFS)
556a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten        this->mWhich = 0;
56b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    sf_count_t count;
576a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten    count = sf_read_short(this->mSNDFILE, pBuffer, (sf_count_t) SndFile_BUFSIZE);
58e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    if (0 >= count)
59e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        this->mEOF = SL_BOOLEAN_TRUE;
60e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    pthread_mutex_unlock(&this->mMutex);
61b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    if (0 < count) {
627324a5ab12cc734e2feb4cef8baeda26566d3c92Glenn Kasten        SLuint32 size = (SLuint32) (count * sizeof(short));
63b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        result = (*caller)->Enqueue(caller, pBuffer, size);
644b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        // this should not happen, but if it does, who will call us to kick off again?
65b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        if (SL_RESULT_BUFFER_INSUFFICIENT == result) {
66b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten            this->mRetryBuffer = pBuffer;
67b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten            this->mRetrySize = size;
68b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten            return;
69b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        }
70b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        assert(SL_RESULT_SUCCESS == result);
71276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten    } else {
72e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        object_lock_exclusive(&thisAP->mObject);
734b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        // FIXME This is really hosed, you can't do this anymore!
744b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        // FIXME Need a state PAUSE_WHEN_EMPTY
757a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten        // Should not pause yet - we just ran out of new data to enqueue,
76e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        // but there may still be (partially) full buffers in the queue.
77276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten        thisAP->mPlay.mState = SL_PLAYSTATE_PAUSED;
78e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        thisAP->mPlay.mPosition = thisAP->mPlay.mDuration;
79e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        object_unlock_exclusive_attributes(&thisAP->mObject, ATTR_TRANSPORT);
80b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    }
81b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten}
82b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten
83369f3138f19f7102bf0f98b890ab84c8df633a93Glenn Kasten
84369f3138f19f7102bf0f98b890ab84c8df633a93Glenn Kasten/** \brief Check whether the supplied libsndfile format is supported by us */
85369f3138f19f7102bf0f98b890ab84c8df633a93Glenn Kasten
86b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn KastenSLboolean SndFile_IsSupported(const SF_INFO *sfinfo)
87b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten{
88b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    switch (sfinfo->format & SF_FORMAT_TYPEMASK) {
89b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    case SF_FORMAT_WAV:
90b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        break;
91b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    default:
92b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        return SL_BOOLEAN_FALSE;
93b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    }
94b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    switch (sfinfo->format & SF_FORMAT_SUBMASK) {
95276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten    case SF_FORMAT_PCM_U8:
96b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    case SF_FORMAT_PCM_16:
97b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        break;
98b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    default:
99b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        return SL_BOOLEAN_FALSE;
100b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    }
101b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    switch (sfinfo->samplerate) {
102276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten    case 11025:
103276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten    case 22050:
104b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    case 44100:
105b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        break;
106b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    default:
107b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        return SL_BOOLEAN_FALSE;
108b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    }
109b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    switch (sfinfo->channels) {
110276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten    case 1:
111b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    case 2:
112b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        break;
113b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    default:
114b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        return SL_BOOLEAN_FALSE;
115b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    }
116b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    return SL_BOOLEAN_TRUE;
117b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten}
118b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten
119369f3138f19f7102bf0f98b890ab84c8df633a93Glenn Kasten
120369f3138f19f7102bf0f98b890ab84c8df633a93Glenn Kasten/** \brief Check whether the partially-constructed AudioPlayer is compatible with libsndfile */
121369f3138f19f7102bf0f98b890ab84c8df633a93Glenn Kasten
122acd88797a1d3b8225bab888d29036e245f275be5Glenn KastenSLresult SndFile_checkAudioPlayerSourceSink(CAudioPlayer *this)
123daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten{
124acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten    const SLDataSource *pAudioSrc = &this->mDataSource.u.mSource;
125daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    SLuint32 locatorType = *(SLuint32 *)pAudioSrc->pLocator;
126daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    SLuint32 formatType = *(SLuint32 *)pAudioSrc->pFormat;
127daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    switch (locatorType) {
128daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    case SL_DATALOCATOR_BUFFERQUEUE:
129daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
130daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    case SL_DATALOCATOR_URI:
131daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        {
132daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        SLDataLocator_URI *dl_uri = (SLDataLocator_URI *) pAudioSrc->pLocator;
133daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        SLchar *uri = dl_uri->URI;
134daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        if (NULL == uri)
135daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
13627f8dfaea17ab7831a1bd34a02f85d55bacf67b7Glenn Kasten        if (!strncmp((const char *) uri, "file:///", 8))
13727f8dfaea17ab7831a1bd34a02f85d55bacf67b7Glenn Kasten            uri += 8;
138daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        switch (formatType) {
139a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        case SL_DATAFORMAT_NULL:    // OK to omit the data format
140a438eb1cf1ae602afab00336528dd230bd929206Glenn Kasten        case SL_DATAFORMAT_MIME:    // we ignore a MIME type if specified
141daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            break;
142daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        default:
143daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_CONTENT_UNSUPPORTED;
144daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        }
14527f8dfaea17ab7831a1bd34a02f85d55bacf67b7Glenn Kasten        this->mSndFile.mPathname = uri;
14640d1c40832a448e23d0bb37512aee53222575c2eGlenn Kasten        this->mBufferQueue.mNumBuffers = SndFile_NUMBUFS;
147daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        }
148daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
149daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    default:
150daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        return SL_RESULT_CONTENT_UNSUPPORTED;
151daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    }
1523d81b8ca5d3cee893672beb76e00849d4f3fa8b8Glenn Kasten    const SLDataSink *pAudioSnk = &this->mDataSink.u.mSink;
1536a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten    this->mSndFile.mWhich = 0;
154acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten    this->mSndFile.mSNDFILE = NULL;
155e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    // this->mSndFile.mMutex is initialized only when there is a valid mSNDFILE
156e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    this->mSndFile.mEOF = SL_BOOLEAN_FALSE;
157acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten    this->mSndFile.mRetryBuffer = NULL;
158acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten    this->mSndFile.mRetrySize = 0;
1593d81b8ca5d3cee893672beb76e00849d4f3fa8b8Glenn Kasten    if (SL_DATALOCATOR_OUTPUTMIX == ((SLDataLocator_OutputMix *)pAudioSnk->pLocator)->locatorType) {
1603d81b8ca5d3cee893672beb76e00849d4f3fa8b8Glenn Kasten         // FIXME possible race between the earlier check and here - should atomically link these
161369f3138f19f7102bf0f98b890ab84c8df633a93Glenn Kasten        this->mEffectSend.mOutputMix = (COutputMix*) ((SLDataLocator_OutputMix *)pAudioSnk->pLocator)->outputMix;
1623d81b8ca5d3cee893672beb76e00849d4f3fa8b8Glenn Kasten    }
1633d81b8ca5d3cee893672beb76e00849d4f3fa8b8Glenn Kasten
164daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    return SL_RESULT_SUCCESS;
165daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten}
166daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten
167369f3138f19f7102bf0f98b890ab84c8df633a93Glenn Kasten/** \brief Called with mutex unlocked for marker and position updates, and play state change */
1684b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten
169e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kastenvoid audioPlayerTransportUpdate(CAudioPlayer *audioPlayer)
170e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten{
171369f3138f19f7102bf0f98b890ab84c8df633a93Glenn Kasten    // FIXME should use two separate hooks since we have separate attributes TRANSPORT and POSITION
1724b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten
1734b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten    if (NULL != audioPlayer->mSndFile.mSNDFILE) {
1744b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten
1754b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        object_lock_exclusive(&audioPlayer->mObject);
1764b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        SLmillisecond pos = audioPlayer->mSeek.mPos;
1774b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        audioPlayer->mSeek.mPos = SL_TIME_UNKNOWN;
1784b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        SLboolean empty = 0 == audioPlayer->mBufferQueue.mState.count;
1793d81b8ca5d3cee893672beb76e00849d4f3fa8b8Glenn Kasten        // FIXME a made-up number that should depend on player state and prefetch status
1803d81b8ca5d3cee893672beb76e00849d4f3fa8b8Glenn Kasten        audioPlayer->mPrefetchStatus.mLevel = 1000;
1814b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        object_unlock_exclusive(&audioPlayer->mObject);
1824b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten
1834b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        if (SL_TIME_UNKNOWN != pos) {
1844b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten
1854b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            // discard any enqueued buffers for the old position
1864b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            (*&audioPlayer->mBufferQueue.mItf)->Clear(&audioPlayer->mBufferQueue.mItf);
1874b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            empty = SL_BOOLEAN_TRUE;
1884b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten
1894b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            pthread_mutex_lock(&audioPlayer->mSndFile.mMutex);
1904b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            (void) sf_seek(audioPlayer->mSndFile.mSNDFILE, (sf_count_t) (((long long) pos *
1914b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten                audioPlayer->mSndFile.mSfInfo.samplerate) / 1000LL), SEEK_SET);
1924b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            audioPlayer->mSndFile.mEOF = SL_BOOLEAN_FALSE;
1934b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            audioPlayer->mSndFile.mRetryBuffer = NULL;
1944b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            audioPlayer->mSndFile.mRetrySize = 0;
1954b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            audioPlayer->mSndFile.mWhich = 0;
1964b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            pthread_mutex_unlock(&audioPlayer->mSndFile.mMutex);
1974b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten
1984b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        }
1994b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten
2004b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        // FIXME only on seek or play state change (STOPPED, PAUSED) -> PLAYING
2014b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        if (empty) {
2024b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            SndFile_Callback(&audioPlayer->mBufferQueue.mItf, audioPlayer);
2034b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        }
2044b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten
205e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    }
206e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten
207e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten}
208e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten
209b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten#endif // USE_SNDFILE
210