2 * Copyright (c) 2006-2011 Ed Schouten <ed@80386.nl>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * @brief Generic access and decoding of audio file formats.
33 #include "audio_file.h"
34 #include "audio_format.h"
35 #include "scrobbler.h"
39 * @brief Audio format containg its functions to open, close, read and
44 * @brief The format's open call.
46 int (*open
)(struct audio_file
*fd
, const char *ext
);
48 * @brief The format's close call.
50 void (*close
)(struct audio_file
*fd
);
52 * @brief The format's read call.
54 size_t (*read
)(struct audio_file
*fd
, int16_t *buf
, size_t len
);
56 * @brief The format's seek call.
58 void (*seek
)(struct audio_file
*fd
, int len
, int rel
);
62 * Make sure you add the most strict matching formats at the top. Raw or
63 * headerless file formats should be listed at the bottom, as the
64 * matching code just runs through this list.
67 * @brief List of audio formats.
69 static struct audio_format formats
[] = {
71 { vorbis_open
, vorbis_close
, vorbis_read
, vorbis_seek
},
72 #endif /* !BUILD_VORBIS */
74 { mp3_open
, mp3_close
, mp3_read
, mp3_seek
},
75 #endif /* !BUILD_MP3 */
77 { modplug_open
, modplug_close
, modplug_read
, modplug_seek
},
78 #endif /* !BUILD_MODPLUG */
81 * Keep this entry at the bottom - it does evil stuff with raw
82 * file descriptors. It could also catch some raw formats.
84 { sndfile_open
, sndfile_close
, sndfile_read
, sndfile_seek
},
85 #endif /* !BUILD_SNDFILE */
88 * @brief Amount of audio formats.
90 #define NUM_FORMATS (sizeof formats / sizeof(struct audio_format))
93 audio_file_open(const struct vfsref
*vr
)
96 struct audio_file
*out
= NULL
;
99 out
= g_slice_new0(struct audio_file
);
101 out
->fp
= vfs_open(vr
);
105 /* Store file extension */
106 if ((ext
= strrchr(vfs_filename(vr
), '.')) != NULL
)
109 for (i
= 0; i
< NUM_FORMATS
; i
++) {
110 if (fseek(out
->fp
, 0, SEEK_SET
) != 0)
113 if (formats
[i
].open(out
, ext
) == 0) {
114 /* Assign the format to the file */
115 out
->drv
= &formats
[i
];
120 if (out
->drv
== NULL
) {
121 /* No matched format */
126 /* No tag - just use the display name then */
127 if (out
->title
== NULL
)
128 out
->title
= g_strdup(vfs_name(vr
));
133 g_slice_free(struct audio_file
, out
);
138 audio_file_close(struct audio_file
*fd
)
146 #ifdef BUILD_SCROBBLER
148 #endif /* BUILD_SCROBBLER */
149 g_slice_free(struct audio_file
, fd
);
153 audio_file_read(struct audio_file
*fd
, int16_t *buf
, size_t len
)
157 ret
= fd
->drv
->read(fd
, buf
, len
);
158 #ifdef BUILD_SCROBBLER
159 scrobbler_notify_read(fd
, (ret
== 0));
160 #endif /* BUILD_SCROBBLER */
166 audio_file_seek(struct audio_file
*fd
, int len
, int rel
)
168 g_assert(len
!= 0 || rel
== 0);
171 fd
->drv
->seek(fd
, len
, rel
);
172 #ifdef BUILD_SCROBBLER
173 scrobbler_notify_seek(fd
);
174 #endif /* BUILD_SCROBBLER */