2 * This file is part of DisOrder.
3 * Portions copyright (C) 2004, 2005 Richard Kettlewell (see also below)
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, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU 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
26 #include <sys/types.h>
33 #include <vorbis/vorbisfile.h>
41 static void *mmap_file(const char *path
, size_t *lengthp
) {
46 if((fd
= open(path
, O_RDONLY
)) < 0) {
47 disorder_error(errno
, "error opening %s", path
);
50 if(fstat(fd
, &sb
) < 0) {
51 disorder_error(errno
, "error calling stat on %s", path
);
54 if(sb
.st_size
== 0) /* can't map 0-length files */
56 if((base
= mmap(0, sb
.st_size
, PROT_READ
,
57 MAP_SHARED
, fd
, 0)) == (void *)-1) {
58 disorder_error(errno
, "error calling mmap on %s", path
);
61 *lengthp
= sb
.st_size
;
69 static long tl_mp3(const char *path
) {
74 if(!(base
= mmap_file(path
, &length
))) return -1;
75 b
.duration
= mad_timer_zero
;
76 scan_mp3(base
, length
, &b
);
78 return b
.duration
.seconds
+ !!b
.duration
.fraction
;
81 static long tl_ogg(const char *path
) {
87 if(!(fp
= fopen(path
, "rb"))) goto error
;
88 if(ov_open(fp
, &vf
, 0, 0)) goto error
;
90 length
= ov_time_total(&vf
, -1);
98 static long tl_wav(const char *path
) {
100 int err
, sample_frame_size
;
103 if((err
= wav_init(f
, path
))) {
104 disorder_error(err
, "error opening %s", path
);
107 sample_frame_size
= (f
->bits
+ 7) / 8 * f
->channels
;
108 if(sample_frame_size
) {
109 const long long n_samples
= f
->datasize
/ sample_frame_size
;
110 duration
= (n_samples
+ f
->rate
- 1) / f
->rate
;
117 static const struct {
119 long (*fn
)(const char *path
);
128 #define N_FILE_FORMATS (int)(sizeof file_formats / sizeof *file_formats)
130 long disorder_tracklength(const char attribute((unused
)) *track
,
132 const char *ext
= strrchr(path
, '.');
133 int l
, r
, m
= 0, c
= 0; /* quieten compiler */
137 r
= N_FILE_FORMATS
- 1;
138 while(l
<= r
&& (c
= strcmp(ext
, file_formats
[m
= (l
+ r
) / 2].ext
)))
144 return file_formats
[m
].fn(path
);