Mercurial > audlegacy
annotate Plugins/Input/mpg123/common.c @ 1238:dc6f7048a9fa trunk
[svn] - remove metatag entirely
author | nenolod |
---|---|
date | Wed, 14 Jun 2006 22:41:05 -0700 |
parents | e3d1c45120e1 |
children | d872c88f8c6f |
rev | line source |
---|---|
61 | 1 #include <stdlib.h> |
2 #include <string.h> | |
3 #include <ctype.h> | |
4 | |
5 #include <signal.h> | |
6 #include <sys/types.h> | |
7 #include <sys/stat.h> | |
8 #include <fcntl.h> | |
9 | |
10 #include "mpg123.h" | |
11 | |
12 const int tabsel_123[2][3][16] = { | |
13 {{0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, | |
14 448,}, | |
15 {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384,}, | |
16 {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320,}}, | |
17 {{0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256,}, | |
18 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,}, | |
19 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,}} | |
20 }; | |
21 | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
22 const int mpgdec_freqs[9] = |
61 | 23 { 44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000, 8000 }; |
24 | |
25 struct bitstream_info bsi; | |
26 | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
27 extern gint mpgdec_bitrate, mpgdec_frequency, mpgdec_length; |
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
28 extern gchar *mpgdec_title, *mpgdec_filename; |
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
29 extern gboolean mpgdec_stereo; |
61 | 30 |
31 static int fsizeold = 0, ssize; | |
32 static unsigned char bsspace[2][MAXFRAMESIZE + 512]; /* MAXFRAMESIZE */ | |
33 static unsigned char *bsbuf = bsspace[1], *bsbufold; | |
34 static int bsnum = 0; | |
35 | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
36 unsigned char *mpgdec_pcm_sample; |
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
37 int mpgdec_pcm_point = 0; |
61 | 38 |
39 static VFSFile *filept; | |
40 static int filept_opened; | |
41 | |
42 static int get_fileinfo(void); | |
43 | |
44 static int | |
45 fullread(VFSFile * fd, unsigned char *buf, int count) | |
46 { | |
47 int ret, cnt = 0; | |
48 | |
49 while (cnt < count) { | |
50 if (fd) | |
51 ret = vfs_fread(buf + cnt, 1, count - cnt, fd); | |
52 else | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
53 ret = mpgdec_http_read(buf + cnt, count - cnt); |
61 | 54 if (ret < 0) |
55 return ret; | |
56 if (ret == 0) | |
57 break; | |
58 cnt += ret; | |
59 } | |
60 return cnt; | |
61 } | |
62 | |
63 static int | |
64 stream_init(void) | |
65 { | |
66 if (get_fileinfo() < 0) | |
67 return -1; | |
68 return 0; | |
69 } | |
70 | |
71 void | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
72 mpgdec_stream_close(void) |
61 | 73 { |
74 if (filept) | |
75 vfs_fclose(filept); | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
76 else if (mpgdec_info->network_stream) |
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
77 mpgdec_http_close(); |
61 | 78 } |
79 | |
80 /**************************************** | |
81 * HACK,HACK,HACK: step back <num> frames | |
970
0f294f2b0a9b
[svn] - integer-mode decoding accuracy improvements
nenolod
parents:
957
diff
changeset
|
82 * can only work if the 'stream' isn't a mpgdec_real stream but a file |
61 | 83 static int stream_back_bytes(int bytes) |
84 { | |
85 if (vfs_fseek(filept, -bytes, SEEK_CUR) < 0) | |
86 return -1; | |
87 return 0; | |
88 } | |
89 */ | |
90 | |
91 static int | |
92 stream_head_read(unsigned long *newhead) | |
93 { | |
94 unsigned char hbuf[4]; | |
95 | |
96 if (fullread(filept, hbuf, 4) != 4) | |
97 return FALSE; | |
98 | |
99 *newhead = ((unsigned long) hbuf[0] << 24) | | |
100 ((unsigned long) hbuf[1] << 16) | | |
101 ((unsigned long) hbuf[2] << 8) | (unsigned long) hbuf[3]; | |
102 | |
103 return TRUE; | |
104 } | |
105 | |
106 static int | |
107 stream_head_shift(unsigned long *head) | |
108 { | |
109 unsigned char hbuf; | |
110 | |
111 if (fullread(filept, &hbuf, 1) != 1) | |
112 return 0; | |
113 *head <<= 8; | |
114 *head |= hbuf; | |
115 *head &= 0xffffffff; | |
116 return 1; | |
117 } | |
118 | |
119 static int | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
120 stream_mpgdec_read_frame_body(unsigned char *buf, int size) |
61 | 121 { |
122 long l; | |
123 | |
124 if ((l = fullread(filept, buf, size)) != size) { | |
125 if (l <= 0) | |
126 return 0; | |
127 memset(buf + l, 0, size - l); | |
128 } | |
129 return 1; | |
130 } | |
131 | |
132 static long | |
133 stream_tell(void) | |
134 { | |
135 return vfs_ftell(filept); | |
136 } | |
137 | |
138 /* | |
139 static void stream_rewind(void) | |
140 { | |
141 vfs_fseek(filept, 0, SEEK_SET); | |
142 } | |
143 */ | |
144 | |
145 int | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
146 mpgdec_stream_jump_to_frame(struct frame *fr, int frame) |
61 | 147 { |
148 if (!filept) | |
149 return -1; | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
150 mpgdec_read_frame_init(); |
61 | 151 vfs_fseek(filept, frame * (fr->framesize + 4), SEEK_SET); |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
152 mpgdec_read_frame(fr); |
61 | 153 return 0; |
154 } | |
155 | |
156 int | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
157 mpgdec_stream_jump_to_byte(struct frame *fr, int byte) |
61 | 158 { |
159 if (!filept) | |
160 return -1; | |
161 vfs_fseek(filept, byte, SEEK_SET); | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
162 mpgdec_read_frame(fr); |
61 | 163 return 0; |
164 } | |
165 | |
166 int | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
167 mpgdec_stream_check_for_xing_header(struct frame *fr, xing_header_t * xhead) |
61 | 168 { |
169 unsigned char *head_data; | |
170 int ret; | |
171 | |
172 vfs_fseek(filept, -(fr->framesize + 4), SEEK_CUR); | |
173 head_data = g_malloc(fr->framesize + 4); | |
174 vfs_fread(head_data, 1, fr->framesize + 4, filept); | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
175 ret = mpgdec_get_xing_header(xhead, head_data); |
61 | 176 g_free(head_data); |
177 return ret; | |
178 } | |
179 | |
180 static int | |
181 get_fileinfo(void) | |
182 { | |
183 guchar buf[3]; | |
184 | |
185 if (filept == NULL) | |
186 return -1; | |
187 if (vfs_fseek(filept, 0, SEEK_END) < 0) | |
188 return -1; | |
189 | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
190 mpgdec_info->filesize = vfs_ftell(filept); |
61 | 191 if (vfs_fseek(filept, -128, SEEK_END) < 0) |
192 return -1; | |
193 if (fullread(filept, buf, 3) != 3) | |
194 return -1; | |
195 if (!strncmp((char *) buf, "TAG", 3)) | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
196 mpgdec_info->filesize -= 128; |
61 | 197 if (vfs_fseek(filept, 0, SEEK_SET) < 0) |
198 return -1; | |
199 | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
200 if (mpgdec_info->filesize <= 0) |
61 | 201 return -1; |
202 | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
203 return mpgdec_info->filesize; |
61 | 204 } |
205 | |
206 void | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
207 mpgdec_read_frame_init(void) |
61 | 208 { |
209 memset(bsspace[0], 0, MAXFRAMESIZE + 512); | |
210 memset(bsspace[1], 0, MAXFRAMESIZE + 512); | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
211 mpgdec_info->output_audio = FALSE; |
61 | 212 } |
213 | |
214 int | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
215 mpgdec_head_check(unsigned long head) |
61 | 216 { |
217 if ((head & 0xffe00000) != 0xffe00000) | |
218 return FALSE; | |
219 if (!((head >> 17) & 3)) | |
220 return FALSE; | |
221 if (((head >> 12) & 0xf) == 0xf) | |
222 return FALSE; | |
223 if (!((head >> 12) & 0xf)) | |
224 return FALSE; | |
225 if (((head >> 10) & 0x3) == 0x3) | |
226 return FALSE; | |
227 if (((head >> 19) & 1) == 1 && | |
228 ((head >> 17) & 3) == 3 && ((head >> 16) & 1) == 1) | |
229 return FALSE; | |
230 if ((head & 0xffff0000) == 0xfffe0000) | |
231 return FALSE; | |
232 | |
233 return TRUE; | |
234 } | |
235 | |
236 /***************************************************************** | |
237 * read next frame | |
238 */ | |
239 int | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
240 mpgdec_read_frame(struct frame *fr) |
61 | 241 { |
242 unsigned long newhead; | |
243 | |
244 fsizeold = fr->framesize; /* for Layer3 */ | |
245 | |
246 if (!stream_head_read(&newhead)) | |
247 return FALSE; | |
248 | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
249 if (!mpgdec_head_check(newhead) || !mpgdec_decode_header(fr, newhead)) { |
61 | 250 int try = 0; |
251 | |
252 do { | |
253 try++; | |
254 if ((newhead & 0xffffff00) == | |
255 ('I' << 24) + ('D' << 16) + ('3' << 8)) { | |
256 if (!stream_head_read(&newhead)) | |
257 return FALSE; | |
258 } | |
259 else if (!stream_head_shift(&newhead)) | |
260 return 0; | |
261 | |
262 } | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
263 while ((!mpgdec_head_check(newhead) || |
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
264 !mpgdec_decode_header(fr, newhead)) && try < (256 * 1024)); |
61 | 265 if (try >= (256 * 1024)) |
266 return FALSE; | |
267 | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
268 mpgdec_info->filesize -= try; |
61 | 269 } |
270 /* flip/init buffer for Layer 3 */ | |
271 bsbufold = bsbuf; | |
272 bsbuf = bsspace[bsnum] + 512; | |
273 bsnum = (bsnum + 1) & 1; | |
274 | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
275 if (!stream_mpgdec_read_frame_body(bsbuf, fr->framesize)) |
61 | 276 return 0; |
277 | |
278 bsi.bitindex = 0; | |
279 bsi.wordpointer = (unsigned char *) bsbuf; | |
280 | |
281 | |
282 return 1; | |
283 | |
284 } | |
285 | |
286 /* | |
287 * the code a header and write the information | |
288 * into the frame structure | |
289 */ | |
290 int | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
291 mpgdec_decode_header(struct frame *fr, unsigned long newhead) |
61 | 292 { |
293 if (newhead & (1 << 20)) { | |
294 fr->lsf = (newhead & (1 << 19)) ? 0x0 : 0x1; | |
295 fr->mpeg25 = 0; | |
296 } | |
297 else { | |
298 fr->lsf = 1; | |
299 fr->mpeg25 = 1; | |
300 } | |
301 fr->lay = 4 - ((newhead >> 17) & 3); | |
302 if (fr->mpeg25) { | |
303 fr->sampling_frequency = 6 + ((newhead >> 10) & 0x3); | |
304 } | |
305 else | |
306 fr->sampling_frequency = ((newhead >> 10) & 0x3) + (fr->lsf * 3); | |
307 fr->error_protection = ((newhead >> 16) & 0x1) ^ 0x1; | |
308 | |
309 fr->bitrate_index = ((newhead >> 12) & 0xf); | |
310 fr->padding = ((newhead >> 9) & 0x1); | |
311 fr->extension = ((newhead >> 8) & 0x1); | |
312 fr->mode = ((newhead >> 6) & 0x3); | |
313 fr->mode_ext = ((newhead >> 4) & 0x3); | |
314 fr->copyright = ((newhead >> 3) & 0x1); | |
315 fr->original = ((newhead >> 2) & 0x1); | |
316 fr->emphasis = newhead & 0x3; | |
317 | |
318 fr->stereo = (fr->mode == MPG_MD_MONO) ? 1 : 2; | |
319 | |
320 ssize = 0; | |
321 | |
322 if (!fr->bitrate_index) | |
323 return (0); | |
324 | |
325 switch (fr->lay) { | |
326 case 1: | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
327 fr->do_layer = mpgdec_do_layer1; |
61 | 328 /* inits also shared tables with layer1 */ |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
329 mpgdec_init_layer2(fr->synth_type == SYNTH_MMX); |
61 | 330 fr->framesize = |
331 (long) tabsel_123[fr->lsf][0][fr->bitrate_index] * 12000; | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
332 fr->framesize /= mpgdec_freqs[fr->sampling_frequency]; |
61 | 333 fr->framesize = ((fr->framesize + fr->padding) << 2) - 4; |
334 break; | |
335 case 2: | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
336 fr->do_layer = mpgdec_do_layer2; |
61 | 337 /* inits also shared tables with layer1 */ |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
338 mpgdec_init_layer2(fr->synth_type == SYNTH_MMX); |
61 | 339 fr->framesize = |
340 (long) tabsel_123[fr->lsf][1][fr->bitrate_index] * 144000; | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
341 fr->framesize /= mpgdec_freqs[fr->sampling_frequency]; |
61 | 342 fr->framesize += fr->padding - 4; |
343 break; | |
344 case 3: | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
345 fr->do_layer = mpgdec_do_layer3; |
61 | 346 if (fr->lsf) |
347 ssize = (fr->stereo == 1) ? 9 : 17; | |
348 else | |
349 ssize = (fr->stereo == 1) ? 17 : 32; | |
350 if (fr->error_protection) | |
351 ssize += 2; | |
352 fr->framesize = | |
353 (long) tabsel_123[fr->lsf][2][fr->bitrate_index] * 144000; | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
354 fr->framesize /= mpgdec_freqs[fr->sampling_frequency] << (fr->lsf); |
61 | 355 fr->framesize = fr->framesize + fr->padding - 4; |
356 break; | |
357 default: | |
358 return (0); | |
359 } | |
360 if (fr->framesize > MAXFRAMESIZE) | |
361 return 0; | |
362 return 1; | |
363 } | |
364 | |
365 void | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
366 mpgdec_open_stream(char *bs_filenam, int fd) |
61 | 367 { |
368 filept_opened = 1; | |
369 if (!strncasecmp(bs_filenam, "http://", 7)) { | |
370 filept = NULL; | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
371 mpgdec_http_open(bs_filenam); |
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
372 mpgdec_info->filesize = 0; |
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
373 mpgdec_info->network_stream = TRUE; |
61 | 374 } |
375 else { | |
376 if ((filept = vfs_fopen(bs_filenam, "rb")) == NULL || | |
377 stream_init() == -1) | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
378 mpgdec_info->eof = TRUE; |
61 | 379 } |
380 | |
381 } | |
382 | |
383 void | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
384 mpgdec_set_pointer(long backstep) |
61 | 385 { |
386 bsi.wordpointer = bsbuf + ssize - backstep; | |
387 if (backstep) | |
388 memcpy(bsi.wordpointer, bsbufold + fsizeold - backstep, backstep); | |
389 bsi.bitindex = 0; | |
390 } | |
391 | |
392 double | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
393 mpgdec_compute_bpf(struct frame *fr) |
61 | 394 { |
395 double bpf; | |
396 | |
397 switch (fr->lay) { | |
398 case 1: | |
399 bpf = tabsel_123[fr->lsf][0][fr->bitrate_index]; | |
400 bpf *= 12000.0 * 4.0; | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
401 bpf /= mpgdec_freqs[fr->sampling_frequency] << (fr->lsf); |
61 | 402 break; |
403 case 2: | |
404 case 3: | |
405 bpf = tabsel_123[fr->lsf][fr->lay - 1][fr->bitrate_index]; | |
406 bpf *= 144000; | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
407 bpf /= mpgdec_freqs[fr->sampling_frequency] << (fr->lsf); |
61 | 408 break; |
409 default: | |
410 bpf = 1.0; | |
411 } | |
412 | |
413 return bpf; | |
414 } | |
415 | |
416 int | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
417 mpgdec_calc_numframes(struct frame *fr) |
61 | 418 { |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
419 return (int) (mpgdec_info->filesize / mpgdec_compute_bpf(fr)); |
61 | 420 } |
421 | |
422 double | |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
423 mpgdec_relative_pos(void) |
61 | 424 { |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
425 if (!filept || !mpgdec_info->filesize) |
61 | 426 return 0; |
1098
b5ae09a6c2f1
[svn] - prepare to split audacious code away from the actual decoder and use a highlevel API
nenolod
parents:
970
diff
changeset
|
427 return ((double) stream_tell()) / mpgdec_info->filesize; |
61 | 428 } |