1 /* the Music Player Daemon (MPD)
2 * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
3 * This project's homepage is: http://www.musicpd.org
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "outputBuffer.h"
21 #include "pcm_utils.h"
22 #include "playerData.h"
25 #include "normalize.h"
30 static mpd_sint16 currentChunk = -1;
32 static mpd_sint8 currentMetaChunk = -1;
33 static mpd_sint8 sendMetaChunk;
35 void clearAllMetaChunkSets(OutputBuffer * cb)
37 memset(cb->metaChunkSet, 0, BUFFERED_METACHUNKS);
40 void clearOutputBuffer(OutputBuffer * cb)
46 /* be sure to reset metaChunkSets cause we are skipping over audio
47 * audio chunks, and thus skipping over metadata */
48 if (currentChunk >= 0 && sendMetaChunk == 0 && currentMetaChunk >= 0) {
49 currentSet = cb->metaChunkSet[currentChunk];
51 clearAllMetaChunkSets(cb);
52 if (currentChunk >= 0 && sendMetaChunk == 0 && currentMetaChunk >= 0) {
53 cb->metaChunkSet[currentChunk] = currentSet;
58 void flushOutputBuffer(OutputBuffer * cb)
60 if (currentChunk == cb->end) {
61 if ((cb->end + 1) >= buffered_chunks) {
69 int sendDataToOutputBuffer(OutputBuffer * cb, InputStream * inStream,
70 DecoderControl * dc, int seekable, void *dataIn,
71 long dataInLen, float time, mpd_uint16 bitRate,
72 ReplayGainInfo * replayGainInfo)
74 mpd_uint16 dataToSend;
78 static char *convBuffer;
79 static long convBufferLen;
81 if (cmpAudioFormat(&(cb->audioFormat), &(dc->audioFormat)) == 0) {
85 datalen = pcm_sizeOfConvBuffer(&(dc->audioFormat), dataInLen,
87 if (datalen > convBufferLen) {
88 convBuffer = xrealloc(convBuffer, datalen);
89 convBufferLen = datalen;
92 datalen = pcm_convertAudioFormat(&(dc->audioFormat), dataIn,
93 dataInLen, &(cb->audioFormat),
94 data, &(cb->convState));
97 if (replayGainInfo && (replayGainState != REPLAYGAIN_OFF))
98 doReplayGain(replayGainInfo, data, datalen, &cb->audioFormat);
99 else if (normalizationEnabled)
100 normalizeData(data, datalen, &cb->audioFormat);
103 if (currentChunk != cb->end) {
104 int next = cb->end + 1;
105 if (next >= buffered_chunks) {
108 while (cb->begin == next && !dc->stop) {
111 return OUTPUT_BUFFER_DC_SEEK;
118 bufferInputStream(inStream) <= 0) {
123 return OUTPUT_BUFFER_DC_STOP;
125 currentChunk = cb->end;
126 cb->chunkSize[currentChunk] = 0;
129 cb->metaChunk[currentChunk] = currentMetaChunk;
131 cb->metaChunk[currentChunk] = -1;
132 cb->bitRate[currentChunk] = bitRate;
133 cb->times[currentChunk] = time;
136 chunkLeft = CHUNK_SIZE - cb->chunkSize[currentChunk];
137 dataToSend = datalen > chunkLeft ? chunkLeft : datalen;
139 memcpy(cb->chunks + currentChunk * CHUNK_SIZE +
140 cb->chunkSize[currentChunk], data, dataToSend);
141 cb->chunkSize[currentChunk] += dataToSend;
142 datalen -= dataToSend;
145 if (cb->chunkSize[currentChunk] == CHUNK_SIZE) {
146 flushOutputBuffer(cb);
153 int copyMpdTagToOutputBuffer(OutputBuffer * cb, MpdTag * tag)
158 if (!cb->acceptMetadata || !tag) {
163 DEBUG("copyMpdTagToOB: !acceptMetadata || !tag\n");
167 if (last && mpdTagsAreEqual(last, tag)) {
168 DEBUG("copyMpdTagToOB: same as last\n");
176 nextChunk = currentMetaChunk + 1;
177 if (nextChunk >= BUFFERED_METACHUNKS)
180 if (cb->metaChunkSet[nextChunk]) {
182 DEBUG("copyMpdTagToOB: metachunk in use!\n");
187 currentMetaChunk = nextChunk;
189 last = mpdTagDup(tag);
191 copyMpdTagToMetadataChunk(tag, &(cb->metadataChunks[currentMetaChunk]));
193 cb->metaChunkSet[nextChunk] = 1;
195 DEBUG("copyMpdTagToOB: copiedTag\n");