flac: Fix metadata reading
[cmus.git] / mad.c
blob650fe61754d0f46270ac1ba25ddd133fef008b89
1 /*
2 * Copyright 2004 Timo Hirvonen
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
17 * 02111-1307, USA.
20 #include "ip.h"
21 #include "nomad.h"
22 #include "id3.h"
23 #include "xmalloc.h"
24 #include "read_wrapper.h"
25 #include "debug.h"
27 #include <errno.h>
28 #include <sys/types.h>
29 #include <unistd.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
34 /* ------------------------------------------------------------------------- */
36 static ssize_t read_func(void *datasource, void *buffer, size_t count)
38 struct input_plugin_data *ip_data = datasource;
40 return read_wrapper(ip_data, buffer, count);
43 static off_t lseek_func(void *datasource, off_t offset, int whence)
45 struct input_plugin_data *ip_data = datasource;
47 return lseek(ip_data->fd, offset, whence);
50 static int close_func(void *datasource)
52 struct input_plugin_data *ip_data = datasource;
54 return close(ip_data->fd);
57 static struct nomad_callbacks callbacks = {
58 .read = read_func,
59 .lseek = lseek_func,
60 .close = close_func
63 /* ------------------------------------------------------------------------- */
65 static int mad_open(struct input_plugin_data *ip_data)
67 struct nomad *nomad;
68 struct nomad_info info;
69 int rc, fast;
71 fast = 1;
72 rc = nomad_open_callbacks(&nomad, ip_data, fast, &callbacks);
73 switch (rc) {
74 case -NOMAD_ERROR_ERRNO:
75 return -1;
76 case -NOMAD_ERROR_FILE_FORMAT:
77 return -IP_ERROR_FILE_FORMAT;
79 ip_data->private = nomad;
81 nomad_info(nomad, &info);
83 /* always 16-bit signed little-endian */
84 ip_data->sf = sf_rate(info.sample_rate) | sf_channels(info.channels) |
85 sf_bits(16) | sf_signed(1);
86 return 0;
89 static int mad_close(struct input_plugin_data *ip_data)
91 struct nomad *nomad;
93 nomad = ip_data->private;
94 nomad_close(nomad);
95 ip_data->fd = -1;
96 ip_data->private = NULL;
97 return 0;
100 static int mad_read(struct input_plugin_data *ip_data, char *buffer, int count)
102 struct nomad *nomad;
104 nomad = ip_data->private;
105 return nomad_read(nomad, buffer, count);
108 static int mad_seek(struct input_plugin_data *ip_data, double offset)
110 struct nomad *nomad;
112 nomad = ip_data->private;
113 return nomad_time_seek(nomad, offset);
116 static int mad_read_comments(struct input_plugin_data *ip_data,
117 struct keyval **comments)
119 ID3 *id3;
120 int fd, rc, save, i;
121 GROWING_KEYVALS(c);
123 fd = open(ip_data->filename, O_RDONLY);
124 if (fd == -1) {
125 return -1;
127 d_print("filename: %s\n", ip_data->filename);
129 id3 = id3_new();
130 rc = id3_read_tags(id3, fd, ID3_V1 | ID3_V2);
131 save = errno;
132 close(fd);
133 errno = save;
134 if (rc) {
135 if (rc == -1) {
136 d_print("error: %s\n", strerror(errno));
137 return -1;
139 d_print("corrupted tag?\n");
140 goto out;
143 for (i = 0; i < NUM_ID3_KEYS; i++) {
144 char *val = id3_get_comment(id3, i);
146 if (val)
147 comments_add(&c, id3_key_names[i], val);
149 out:
150 comments_terminate(&c);
151 *comments = c.comments;
152 id3_free(id3);
153 return 0;
156 static int mad_duration(struct input_plugin_data *ip_data)
158 struct nomad *nomad;
160 nomad = ip_data->private;
161 return nomad_time_total(nomad);
164 const struct input_plugin_ops ip_ops = {
165 .open = mad_open,
166 .close = mad_close,
167 .read = mad_read,
168 .seek = mad_seek,
169 .read_comments = mad_read_comments,
170 .duration = mad_duration
173 const char * const ip_extensions[] = { "mp3", "mp2", NULL };
174 const char * const ip_mime_types[] = {
175 "audio/mpeg", "audio/x-mp3", "audio/x-mpeg", "audio/x-mpegurl", NULL