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 <vorbis/codec.h>
00034 #include <vorbis/vorbisfile.h>
00035
00036 #include "audio_file.h"
00037 #include "audio_format.h"
00038 #include "audio_output.h"
00039
00044 static void
00045 vorbis_read_comments(struct audio_file *fd)
00046 {
00047 OggVorbis_File *vfp = fd->drv_data;
00048 struct vorbis_comment *cmt;
00049 int i;
00050 const char *tag;
00051
00052 if ((cmt = ov_comment(vfp, -1)) == NULL)
00053 return;
00054
00055 for (i = 0; i < cmt->comments; i++) {
00056 tag = cmt->user_comments[i];
00057
00058 if (g_ascii_strncasecmp(tag, "artist=", 7) == 0)
00059 fd->artist = g_strdup(tag + 7);
00060 else if (g_ascii_strncasecmp(tag, "title=", 6) == 0)
00061 fd->title = g_strdup(tag + 6);
00062 #ifdef BUILD_SCROBBLER
00063 else if (g_ascii_strncasecmp(tag, "album=", 6) == 0)
00064 fd->album = g_strdup(tag + 6);
00065 #endif
00066 }
00067 }
00068
00069 int
00070 vorbis_open(struct audio_file *fd, const char *ext)
00071 {
00072 OggVorbis_File *vfp;
00073 vorbis_info *info;
00074
00075 if (fd->stream) {
00076
00077 return (-1);
00078 }
00079
00080 vfp = g_slice_new(OggVorbis_File);
00081 if (ov_open(fd->fp, vfp, NULL, 0) != 0) {
00082 g_slice_free(OggVorbis_File, vfp);
00083 return (-1);
00084 }
00085
00086 info = ov_info(vfp, -1);
00087
00088 fd->drv_data = vfp;
00089 fd->srate = info->rate;
00090 fd->channels = 2;
00091 fd->time_len = ov_time_total(vfp, -1);
00092
00093 vorbis_read_comments(fd);
00094
00095 return (0);
00096 }
00097
00098 void
00099 vorbis_close(struct audio_file *fd)
00100 {
00101 OggVorbis_File *vfp = fd->drv_data;
00102
00103 ov_clear(vfp);
00104 g_slice_free(OggVorbis_File, vfp);
00105
00106
00107 fd->fp = NULL;
00108 }
00109
00110 size_t
00111 vorbis_read(struct audio_file *fd, int16_t *buf, size_t len)
00112 {
00113 OggVorbis_File *vfp = fd->drv_data;
00114 size_t ret = 0;
00115 long rlen;
00116 char *out = (char *)buf;
00117
00118 len *= sizeof(int16_t);
00119
00120
00121 while (ret < len) {
00122 #if G_BYTE_ORDER == G_BIG_ENDIAN
00123 rlen = ov_read(vfp, out + ret, len - ret, 1, 2, 1, NULL);
00124 #else
00125 rlen = ov_read(vfp, out + ret, len - ret, 0, 2, 1, NULL);
00126 #endif
00127 if (rlen <= 0)
00128 break;
00129 ret += rlen;
00130 }
00131 fd->time_cur = ov_time_tell(vfp);
00132
00133 return (ret / sizeof(int16_t));
00134 }
00135
00136 void
00137 vorbis_seek(struct audio_file *fd, int len, int rel)
00138 {
00139 double npos;
00140 OggVorbis_File *vfp = fd->drv_data;
00141
00142 npos = len;
00143 if (rel) {
00144
00145 npos += ov_time_tell(vfp);
00146 }
00147
00148 npos = CLAMP(npos, 0, ov_time_total(vfp, -1));
00149
00150 ov_time_seek(vfp, npos);
00151 fd->time_cur = ov_time_tell(vfp);
00152 }