SndFile.c revision e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037
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
17b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten/* libsndfile integration */
18b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten
19b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten#include "sles_allinclusive.h"
20b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten
21b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten#ifdef USE_SNDFILE
22b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten
236a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kastenvoid SndFile_Callback(SLBufferQueueItf caller, void *pContext)
24b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten{
25276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten    CAudioPlayer *thisAP = (CAudioPlayer *) pContext;
26e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    object_lock_peek(&thisAP->mObject);
27e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    SLuint32 state = thisAP->mPlay.mState;
28e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    object_unlock_peek(&thisAP->mObject);
29e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    if (SL_PLAYSTATE_PLAYING != state)
30276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten        return;
31276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten    struct SndFile *this = &thisAP->mSndFile;
32b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    SLresult result;
33b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    if (NULL != this->mRetryBuffer && 0 < this->mRetrySize) {
3427f8dfaea17ab7831a1bd34a02f85d55bacf67b7Glenn Kasten        result = (*caller)->Enqueue(caller, this->mRetryBuffer, this->mRetrySize);
35b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        if (SL_RESULT_BUFFER_INSUFFICIENT == result)
36b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten            return;     // what, again?
37b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        assert(SL_RESULT_SUCCESS == result);
38b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        this->mRetryBuffer = NULL;
39b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        this->mRetrySize = 0;
40b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        return;
41b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    }
42e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    pthread_mutex_lock(&this->mMutex);
43e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    if (this->mEOF) {
44e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        pthread_mutex_unlock(&this->mMutex);
45e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        return;
46e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    }
476a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten    short *pBuffer = &this->mBuffer[this->mWhich * SndFile_BUFSIZE];
486a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten    if (++this->mWhich >= SndFile_NUMBUFS)
496a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten        this->mWhich = 0;
50b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    sf_count_t count;
516a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten    count = sf_read_short(this->mSNDFILE, pBuffer, (sf_count_t) SndFile_BUFSIZE);
52e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    if (0 >= count)
53e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        this->mEOF = SL_BOOLEAN_TRUE;
54e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    pthread_mutex_unlock(&this->mMutex);
55b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    if (0 < count) {
567324a5ab12cc734e2feb4cef8baeda26566d3c92Glenn Kasten        SLuint32 size = (SLuint32) (count * sizeof(short));
57b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        result = (*caller)->Enqueue(caller, pBuffer, size);
58b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        if (SL_RESULT_BUFFER_INSUFFICIENT == result) {
59b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten            this->mRetryBuffer = pBuffer;
60b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten            this->mRetrySize = size;
61b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten            return;
62b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        }
63b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        assert(SL_RESULT_SUCCESS == result);
64276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten    } else {
65e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        object_lock_exclusive(&thisAP->mObject);
66e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        // FIXME Uh not yet - we just ran out of new data to enqueue,
67e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        // but there may still be (partially) full buffers in the queue.
68276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten        thisAP->mPlay.mState = SL_PLAYSTATE_PAUSED;
69e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        thisAP->mPlay.mPosition = thisAP->mPlay.mDuration;
70e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        object_unlock_exclusive_attributes(&thisAP->mObject, ATTR_TRANSPORT);
71b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    }
72b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten}
73b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten
74b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn KastenSLboolean SndFile_IsSupported(const SF_INFO *sfinfo)
75b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten{
76b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    switch (sfinfo->format & SF_FORMAT_TYPEMASK) {
77b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    case SF_FORMAT_WAV:
78b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        break;
79b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    default:
80b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        return SL_BOOLEAN_FALSE;
81b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    }
82b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    switch (sfinfo->format & SF_FORMAT_SUBMASK) {
83276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten    case SF_FORMAT_PCM_U8:
84b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    case SF_FORMAT_PCM_16:
85b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        break;
86b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    default:
87b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        return SL_BOOLEAN_FALSE;
88b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    }
89b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    switch (sfinfo->samplerate) {
90276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten    case 11025:
91276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten    case 22050:
92b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    case 44100:
93b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        break;
94b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    default:
95b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        return SL_BOOLEAN_FALSE;
96b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    }
97b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    switch (sfinfo->channels) {
98276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten    case 1:
99b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    case 2:
100b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        break;
101b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    default:
102b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        return SL_BOOLEAN_FALSE;
103b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    }
104b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    return SL_BOOLEAN_TRUE;
105b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten}
106b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten
107acd88797a1d3b8225bab888d29036e245f275be5Glenn KastenSLresult SndFile_checkAudioPlayerSourceSink(CAudioPlayer *this)
108daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten{
109acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten    const SLDataSource *pAudioSrc = &this->mDataSource.u.mSource;
110daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    SLuint32 locatorType = *(SLuint32 *)pAudioSrc->pLocator;
111daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    SLuint32 formatType = *(SLuint32 *)pAudioSrc->pFormat;
112daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    switch (locatorType) {
113daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    case SL_DATALOCATOR_BUFFERQUEUE:
114acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten        this->mBufferQueue.mNumBuffers =
115acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten            ((SLDataLocator_BufferQueue *) pAudioSrc->pLocator)->numBuffers;
116daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
117daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    case SL_DATALOCATOR_URI:
118daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        {
119daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        SLDataLocator_URI *dl_uri = (SLDataLocator_URI *) pAudioSrc->pLocator;
120daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        SLchar *uri = dl_uri->URI;
121daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        if (NULL == uri)
122daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
12327f8dfaea17ab7831a1bd34a02f85d55bacf67b7Glenn Kasten        if (!strncmp((const char *) uri, "file:///", 8))
12427f8dfaea17ab7831a1bd34a02f85d55bacf67b7Glenn Kasten            uri += 8;
125daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        switch (formatType) {
126daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case SL_DATAFORMAT_MIME:
127daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            break;
128daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        default:
129daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_CONTENT_UNSUPPORTED;
130daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        }
13127f8dfaea17ab7831a1bd34a02f85d55bacf67b7Glenn Kasten        this->mSndFile.mPathname = uri;
13240d1c40832a448e23d0bb37512aee53222575c2eGlenn Kasten        this->mBufferQueue.mNumBuffers = SndFile_NUMBUFS;
133daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        }
134daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
135daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    default:
136daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        return SL_RESULT_CONTENT_UNSUPPORTED;
137daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    }
1386a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten    this->mSndFile.mWhich = 0;
139acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten    this->mSndFile.mSNDFILE = NULL;
140e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    // this->mSndFile.mMutex is initialized only when there is a valid mSNDFILE
141e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    this->mSndFile.mEOF = SL_BOOLEAN_FALSE;
142acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten    this->mSndFile.mRetryBuffer = NULL;
143acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten    this->mSndFile.mRetrySize = 0;
144daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    return SL_RESULT_SUCCESS;
145daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten}
146daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten
147e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kastenvoid audioPlayerTransportUpdate(CAudioPlayer *audioPlayer)
148e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten{
149e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    // marker and position updates here???
150e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    SLmillisecond pos;
151e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten
152e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    pos = audioPlayer->mSeek.mPos;
153e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    audioPlayer->mSeek.mPos = SL_TIME_UNKNOWN;
154e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten
155e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    if ((SL_TIME_UNKNOWN != pos) && (NULL != audioPlayer->mSndFile.mSNDFILE)) {
156e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        pthread_mutex_lock(&audioPlayer->mSndFile.mMutex);
157e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        // FIXME use pos not 0
158e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        (void) sf_seek(audioPlayer->mSndFile.mSNDFILE, (sf_count_t) 0, SEEK_SET);
159e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        audioPlayer->mSndFile.mEOF = SL_BOOLEAN_FALSE;
160e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten        pthread_mutex_unlock(&audioPlayer->mSndFile.mMutex);
161e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    }
162e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten
163e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten}
164e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten
165b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten#endif // USE_SNDFILE
166