00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00031 #include "stdinc.h"
00032
00033 #include "audio_file.h"
00034 #include "audio_format.h"
00035 #include "scrobbler.h"
00036 #include "vfs.h"
00037
00042 struct audio_format {
00046 int (*open)(struct audio_file *fd, const char *ext);
00050 void (*close)(struct audio_file *fd);
00054 size_t (*read)(struct audio_file *fd, int16_t *buf, size_t len);
00058 void (*seek)(struct audio_file *fd, int len, int rel);
00059 };
00060
00061
00062
00063
00064
00065
00069 static struct audio_format formats[] = {
00070 #ifdef BUILD_VORBIS
00071 { vorbis_open, vorbis_close, vorbis_read, vorbis_seek },
00072 #endif
00073 #ifdef BUILD_MP3
00074 { mp3_open, mp3_close, mp3_read, mp3_seek },
00075 #endif
00076 #ifdef BUILD_MODPLUG
00077 { modplug_open, modplug_close, modplug_read, modplug_seek },
00078 #endif
00079 #ifdef BUILD_SNDFILE
00080
00081
00082
00083
00084 { sndfile_open, sndfile_close, sndfile_read, sndfile_seek },
00085 #endif
00086 };
00090 #define NUM_FORMATS (sizeof formats / sizeof(struct audio_format))
00091
00092 struct audio_file *
00093 audio_file_open(const struct vfsref *vr)
00094 {
00095 const char *ext;
00096 struct audio_file *out = NULL;
00097 unsigned int i;
00098
00099 out = g_slice_new0(struct audio_file);
00100
00101 out->fp = vfs_open(vr);
00102 if (out->fp == NULL)
00103 goto bad;
00104
00105
00106 if ((ext = strrchr(vfs_filename(vr), '.')) != NULL)
00107 ext++;
00108
00109 for (i = 0; i < NUM_FORMATS; i++) {
00110 if (fseek(out->fp, 0, SEEK_SET) != 0)
00111 out->stream = 1;
00112
00113 if (formats[i].open(out, ext) == 0) {
00114
00115 out->drv = &formats[i];
00116 break;
00117 }
00118 }
00119
00120 if (out->drv == NULL) {
00121
00122 fclose(out->fp);
00123 goto bad;
00124 }
00125
00126
00127 if (out->title == NULL)
00128 out->title = g_strdup(vfs_name(vr));
00129
00130 return (out);
00131
00132 bad:
00133 g_slice_free(struct audio_file, out);
00134 return (NULL);
00135 }
00136
00137 void
00138 audio_file_close(struct audio_file *fd)
00139 {
00140 fd->drv->close(fd);
00141 if (fd->fp != NULL)
00142 fclose(fd->fp);
00143
00144 g_free(fd->artist);
00145 g_free(fd->title);
00146 #ifdef BUILD_SCROBBLER
00147 g_free(fd->album);
00148 #endif
00149 g_slice_free(struct audio_file, fd);
00150 }
00151
00152 size_t
00153 audio_file_read(struct audio_file *fd, int16_t *buf, size_t len)
00154 {
00155 size_t ret;
00156
00157 ret = fd->drv->read(fd, buf, len);
00158 #ifdef BUILD_SCROBBLER
00159 scrobbler_notify_read(fd, (ret == 0));
00160 #endif
00161
00162 return (ret);
00163 }
00164
00165 void
00166 audio_file_seek(struct audio_file *fd, int len, int rel)
00167 {
00168 g_assert(len != 0 || rel == 0);
00169
00170 if (!fd->stream) {
00171 fd->drv->seek(fd, len, rel);
00172 #ifdef BUILD_SCROBBLER
00173 scrobbler_notify_seek(fd);
00174 #endif
00175 }
00176 }