Bug fixed for unix error "readlink /proc/self/fd/0" on MacOS.
[Faustine.git] / interpreter / lib / src / libsndfile-1.0.25 / src / ogg.c
1 /*
2 ** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
3 ** Copyright (C) 2007 John ffitch
4 **
5 ** This program is free software ; you can redistribute it and/or modify
6 ** it under the terms of the GNU Lesser General Public License as published by
7 ** the Free Software Foundation ; either version 2.1 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 Lesser General Public License for more details.
14 **
15 ** You should have received a copy of the GNU Lesser General Public License
16 ** along with this program ; if not, write to the Free Software
17 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20 #include "sfconfig.h"
21
22 #include <stdio.h>
23 #include <fcntl.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <time.h>
27 #include <math.h>
28
29 #if HAVE_UNISTD_H
30 #include <unistd.h>
31 #endif
32
33 #include "sndfile.h"
34 #include "sfendian.h"
35 #include "common.h"
36
37 #if HAVE_EXTERNAL_LIBS
38
39 #include <ogg/ogg.h>
40
41 #include "ogg.h"
42
43 static int ogg_close (SF_PRIVATE *psf) ;
44 static int ogg_stream_classify (SF_PRIVATE *psf, OGG_PRIVATE * odata) ;
45 static int ogg_page_classify (SF_PRIVATE * psf, const ogg_page * og) ;
46
47 int
48 ogg_open (SF_PRIVATE *psf)
49 { OGG_PRIVATE* odata = calloc (1, sizeof (OGG_PRIVATE)) ;
50 sf_count_t pos = psf_ftell (psf) ;
51 int error = 0 ;
52
53 psf->container_data = odata ;
54 psf->container_close = ogg_close ;
55
56 if (psf->file.mode == SFM_RDWR)
57 return SFE_BAD_MODE_RW ;
58
59 if (psf->file.mode == SFM_READ)
60 if ((error = ogg_stream_classify (psf, odata)) != 0)
61 return error ;
62
63 /* Reset everything to an initial state. */
64 ogg_sync_clear (&odata->osync) ;
65 ogg_stream_clear (&odata->ostream) ;
66 psf_fseek (psf, pos, SEEK_SET) ;
67
68 switch (psf->sf.format)
69 { case SF_FORMAT_OGG | SF_FORMAT_VORBIS :
70 return ogg_vorbis_open (psf) ;
71
72 case SF_FORMAT_OGGFLAC :
73 free (psf->container_data) ;
74 psf->container_data = NULL ;
75 psf->container_close = NULL ;
76 return flac_open (psf) ;
77
78 #if ENABLE_EXPERIMENTAL_CODE
79 case SF_FORMAT_OGG | SF_FORMAT_SPEEX :
80 return ogg_speex_open (psf) ;
81
82 case SF_FORMAT_OGG | SF_FORMAT_PCM_16 :
83 case SF_FORMAT_OGG | SF_FORMAT_PCM_24 :
84 return ogg_pcm_open (psf) ;
85 #endif
86
87 default :
88 break ;
89 } ;
90
91 psf_log_printf (psf, "%s : mode should be SFM_READ or SFM_WRITE.\n", __func__) ;
92 return SFE_INTERNAL ;
93 } /* ogg_open */
94
95
96 static int
97 ogg_close (SF_PRIVATE *psf)
98 { OGG_PRIVATE* odata = psf->container_data ;
99
100 ogg_sync_clear (&odata->osync) ;
101 ogg_stream_clear (&odata->ostream) ;
102
103 return 0 ;
104 } /* ogg_close */
105
106 static int
107 ogg_stream_classify (SF_PRIVATE *psf, OGG_PRIVATE* odata)
108 { char *buffer ;
109 int bytes, nn ;
110
111 /* Call this here so it only gets called once, so no memory is leaked. */
112 ogg_sync_init (&odata->osync) ;
113
114 odata->eos = 0 ;
115
116 /* Weird stuff happens if these aren't called. */
117 ogg_stream_reset (&odata->ostream) ;
118 ogg_sync_reset (&odata->osync) ;
119
120 /*
121 ** Grab some data at the head of the stream. We want the first page
122 ** (which is guaranteed to be small and only contain the Vorbis
123 ** stream initial header) We need the first page to get the stream
124 ** serialno.
125 */
126
127 /* Expose the buffer */
128 buffer = ogg_sync_buffer (&odata->osync, 4096L) ;
129
130 /* Grab the part of the header that has already been read. */
131 memcpy (buffer, psf->header, psf->headindex) ;
132 bytes = psf->headindex ;
133
134 /* Submit a 4k block to libvorbis' Ogg layer */
135 bytes += psf_fread (buffer + psf->headindex, 1, 4096 - psf->headindex, psf) ;
136 ogg_sync_wrote (&odata->osync, bytes) ;
137
138 /* Get the first page. */
139 if ((nn = ogg_sync_pageout (&odata->osync, &odata->opage)) != 1)
140 {
141 /* Have we simply run out of data? If so, we're done. */
142 if (bytes < 4096)
143 return 0 ;
144
145 /* Error case. Must not be Vorbis data */
146 psf_log_printf (psf, "Input does not appear to be an Ogg bitstream.\n") ;
147 return SFE_MALFORMED_FILE ;
148 } ;
149
150 /*
151 ** Get the serial number and set up the rest of decode.
152 ** Serialno first ; use it to set up a logical stream.
153 */
154 ogg_stream_clear (&odata->ostream) ;
155 ogg_stream_init (&odata->ostream, ogg_page_serialno (&odata->opage)) ;
156
157 if (ogg_stream_pagein (&odata->ostream, &odata->opage) < 0)
158 { /* Error ; stream version mismatch perhaps. */
159 psf_log_printf (psf, "Error reading first page of Ogg bitstream data\n") ;
160 return SFE_MALFORMED_FILE ;
161 } ;
162
163 if (ogg_stream_packetout (&odata->ostream, &odata->opacket) != 1)
164 { /* No page? must not be vorbis. */
165 psf_log_printf (psf, "Error reading initial header packet.\n") ;
166 return SFE_MALFORMED_FILE ;
167 } ;
168
169 odata->codec = ogg_page_classify (psf, &odata->opage) ;
170
171 switch (odata->codec)
172 { case OGG_VORBIS :
173 psf->sf.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS ;
174 return 0 ;
175
176 case OGG_FLAC :
177 case OGG_FLAC0 :
178 psf->sf.format = SF_FORMAT_OGGFLAC ;
179 return 0 ;
180
181 case OGG_SPEEX :
182 psf->sf.format = SF_FORMAT_OGG | SF_FORMAT_SPEEX ;
183 return 0 ;
184
185 case OGG_PCM :
186 psf_log_printf (psf, "Detected Ogg/PCM data. This is not supported yet.\n") ;
187 return SFE_UNIMPLEMENTED ;
188
189 default :
190 break ;
191 } ;
192
193 psf_log_printf (psf, "This Ogg bitstream contains some uknown data type.\n") ;
194 return SFE_UNIMPLEMENTED ;
195 } /* ogg_stream_classify */
196
197 /*==============================================================================
198 */
199
200 static struct
201 { const char *str, *name ;
202 int len, codec ;
203 } codec_lookup [] =
204 { { "Annodex", "Annodex", 8, OGG_ANNODEX },
205 { "AnxData", "AnxData", 7, OGG_ANXDATA },
206 { "\177FLAC", "Flac1", 5, OGG_FLAC },
207 { "fLaC", "Flac0", 4, OGG_FLAC0 },
208 { "PCM ", "PCM", 8, OGG_PCM },
209 { "Speex", "Speex", 5, OGG_SPEEX },
210 { "\001vorbis", "Vorbis", 7, OGG_VORBIS },
211 } ;
212
213 static int
214 ogg_page_classify (SF_PRIVATE * psf, const ogg_page * og)
215 { int k, len ;
216
217 for (k = 0 ; k < ARRAY_LEN (codec_lookup) ; k++)
218 { if (codec_lookup [k].len > og->body_len)
219 continue ;
220
221 if (memcmp (og->body, codec_lookup [k].str, codec_lookup [k].len) == 0)
222 { psf_log_printf (psf, "Ogg stream data : %s\n", codec_lookup [k].name) ;
223 psf_log_printf (psf, "Stream serialno : %010D\n", (int64_t) ogg_page_serialno (og)) ;
224 return codec_lookup [k].codec ;
225 } ;
226 } ;
227
228 len = og->body_len < 8 ? og->body_len : 8 ;
229
230 psf_log_printf (psf, "Ogg_stream data : '") ;
231 for (k = 0 ; k < len ; k++)
232 psf_log_printf (psf, "%c", isprint (og->body [k]) ? og->body [k] : '.') ;
233 psf_log_printf (psf, "' ") ;
234 for (k = 0 ; k < len ; k++)
235 psf_log_printf (psf, " %02x", og->body [k] & 0xff) ;
236 psf_log_printf (psf, "\n") ;
237
238 return 0 ;
239 } /* ogg_page_classify */
240
241 #else /* HAVE_EXTERNAL_LIBS */
242
243 int
244 ogg_open (SF_PRIVATE *psf)
245 {
246 psf_log_printf (psf, "This version of libsndfile was compiled without Ogg/Vorbis support.\n") ;
247 return SFE_UNIMPLEMENTED ;
248 } /* ogg_open */
249
250 #endif