X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/blobdiff_plain/71b70599a2cd81c13cc4326499a5d0c45358cd7d..e2daf70b506edb51fa81a003c9794120f2769672:/server/decode.c
diff --git a/server/decode.c b/server/decode.c
index 639ad15..ef999b3 100644
--- a/server/decode.c
+++ b/server/decode.c
@@ -1,37 +1,26 @@
/*
* This file is part of DisOrder
- * Copyright (C) 2007 Richard Kettlewell
+ * Copyright (C) 2007, 2008 Richard Kettlewell
*
- * This program is free software; you can redistribute it and/or modify
+ * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
+ * along with this program. If not, see .
*/
/** @file server/decode.c
* @brief General-purpose decoder for use by speaker process
*/
-#include
-#include "types.h"
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
+#include "disorder-server.h"
+
#include
#include
@@ -44,12 +33,10 @@
#define FLAC__FileDecoderState FLAC__StreamDecoderState
#endif
-#include "log.h"
-#include "syscalls.h"
-#include "defs.h"
#include "wav.h"
#include "speaker-protocol.h"
+
/** @brief Encoding lookup table type */
struct decoder {
/** @brief Glob pattern matching file */
@@ -70,22 +57,8 @@ static const char *path;
/** @brief Input buffer */
static char input_buffer[1048576];
-/** @brief Open the input file */
-static void open_input(void) {
- if((inputfd = open(path, O_RDONLY)) < 0)
- fatal(errno, "opening %s", path);
-}
-
-/** @brief Fill the buffer
- * @return Number of bytes read
- */
-static size_t fill(void) {
- int n = read(inputfd, input_buffer, sizeof input_buffer);
-
- if(n < 0)
- fatal(errno, "reading from %s", path);
- return n;
-}
+/** @brief Number of bytes read into buffer */
+static int input_count;
/** @brief Write an 8-bit word */
static inline void output_8(int n) {
@@ -165,11 +138,11 @@ static inline unsigned long prng(unsigned long state)
/** @brief Generic linear sample quantize and dither routine
* Filched from mpg321, which credits it to Robert Leslie */
-#define bits 16
static long audio_linear_dither(mad_fixed_t sample,
struct audio_dither *dither) {
unsigned int scalebits;
mad_fixed_t output, mask, rnd;
+ const int bits = 16;
enum {
MIN = -MAD_F_ONE,
@@ -217,7 +190,6 @@ static long audio_linear_dither(mad_fixed_t sample,
/* scale */
return output >> scalebits;
}
-#undef bits
/** @brief MP3 output callback */
static enum mad_flow mp3_output(void attribute((unused)) *data,
@@ -250,15 +222,34 @@ static enum mad_flow mp3_output(void attribute((unused)) *data,
/** @brief MP3 input callback */
static enum mad_flow mp3_input(void attribute((unused)) *data,
struct mad_stream *stream) {
- const size_t n = fill();
-
- if(!n)
+ int used, remain, n;
+
+ /* libmad requires its caller to do ALL the buffering work, including coping
+ * with partial frames. Given that it appears to be completely undocumented
+ * you could perhaps be forgiven for not discovering this... */
+ if(input_count) {
+ /* Compute total number of bytes consumed */
+ used = (char *)stream->next_frame - input_buffer;
+ /* Compute number of bytes left to consume */
+ remain = input_count - used;
+ memmove(input_buffer, input_buffer + used, remain);
+ } else {
+ remain = 0;
+ }
+ /* Read new data */
+ n = read(inputfd, input_buffer + remain, (sizeof input_buffer) - remain);
+ if(n < 0)
+ fatal(errno, "reading from %s", path);
+ /* Compute total number of bytes available */
+ input_count = remain + n;
+ if(input_count)
+ mad_stream_buffer(stream, (unsigned char *)input_buffer, input_count);
+ if(n)
+ return MAD_FLOW_CONTINUE;
+ else
return MAD_FLOW_STOP;
- mad_stream_buffer(stream, (unsigned char *)input_buffer, n);
- return MAD_FLOW_CONTINUE;
}
-
/** @brief MP3 error callback */
static enum mad_flow mp3_error(void attribute((unused)) *data,
struct mad_stream *stream,
@@ -274,7 +265,8 @@ static enum mad_flow mp3_error(void attribute((unused)) *data,
static void decode_mp3(void) {
struct mad_decoder mad[1];
- open_input();
+ if((inputfd = open(path, O_RDONLY)) < 0)
+ fatal(errno, "opening %s", path);
mad_decoder_init(mad, 0/*data*/, mp3_input, 0/*header*/, 0/*filter*/,
mp3_output, mp3_error, 0/*message*/);
if(mad_decoder_run(mad, MAD_DECODER_MODE_SYNC))
@@ -438,13 +430,6 @@ static void help(void) {
exit(0);
}
-/* Display version number and terminate. */
-static void version(void) {
- xprintf("%s", disorder_version_string);
- xfclose(stdout);
- exit(0);
-}
-
int main(int argc, char **argv) {
int n;
const char *e;
@@ -454,7 +439,7 @@ int main(int argc, char **argv) {
while((n = getopt_long(argc, argv, "hV", options, 0)) >= 0) {
switch(n) {
case 'h': help();
- case 'V': version();
+ case 'V': version("disorder-decode");
default: fatal(0, "invalid option");
}
}