chiark / gitweb /
debian/control: db4.8 is obsolete in wheezy.
[disorder] / server / decode-ogg.c
1 /*
2  * This file is part of DisOrder
3  * Copyright (C) 2007-2011 Richard Kettlewell
4  *
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 3 of the License, or
8  * (at your option) any later version.
9  *
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  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 /** @file server/decode-ogg.c
19  * @brief General-purpose decoder for use by speaker process
20  */
21 #include "decode.h"
22
23 #include <vorbis/vorbisfile.h>
24
25 static size_t ogg_read_func(void *ptr, size_t size, size_t nmemb, void *datasource) {
26   struct hreader *h = datasource;
27   
28   int n = hreader_read(h, ptr, size * nmemb);
29   if(n < 0) n = 0;
30   return n / size;
31 }
32
33 static int ogg_seek_func(void *datasource, ogg_int64_t offset, int whence) {
34   struct hreader *h = datasource;
35   
36   return hreader_seek(h, offset, whence) < 0 ? -1 : 0;
37 }
38
39 static int ogg_close_func(void attribute((unused)) *datasource) {
40   return 0;
41 }
42
43 static long ogg_tell_func(void *datasource) {
44   struct hreader *h = datasource;
45   
46   return hreader_seek(h, 0, SEEK_CUR);
47 }
48
49 static const ov_callbacks ogg_callbacks = {
50   ogg_read_func,
51   ogg_seek_func,
52   ogg_close_func,
53   ogg_tell_func,
54 };
55
56 /** @brief OGG decoder */
57 void decode_ogg(void) {
58   struct hreader ogginput[1];
59   OggVorbis_File vf[1];
60   int err;
61   long n;
62   int bitstream;
63   vorbis_info *vi;
64
65   hreader_init(path, ogginput);
66   /* There doesn't seem to be any standard function for mapping the error codes
67    * to strings l-( */
68   if((err = ov_open_callbacks(ogginput, vf, 0/*initial*/, 0/*ibytes*/,
69                               ogg_callbacks)))
70     disorder_fatal(0, "ov_open_callbacks %s: %d", path, err);
71   if(!(vi = ov_info(vf, 0/*link*/)))
72     disorder_fatal(0, "ov_info %s: failed", path);
73   while((n = ov_read(vf, input_buffer, sizeof input_buffer, 1/*bigendianp*/,
74                      2/*bytes/word*/, 1/*signed*/, &bitstream))) {
75     if(n < 0)
76       disorder_fatal(0, "ov_read %s: %ld", path, n);
77     if(bitstream > 0)
78       disorder_fatal(0, "only single-bitstream ogg files are supported");
79     output_header(vi->rate, vi->channels, 16/*bits*/, n, ENDIAN_BIG);
80     if(fwrite(input_buffer, 1, n, outputfp) < (size_t)n)
81       disorder_fatal(errno, "decoding %s: writing sample data", path);
82   }
83 }
84
85 /*
86 Local Variables:
87 c-basic-offset:2
88 comment-column:40
89 fill-column:79
90 indent-tabs-mode:nil
91 End:
92 */