comparison libmpdemux/cdda.c @ 9801:2f02809d32a8

URL is cdda://tracks[:speed][/device]
author albeu
date Wed, 02 Apr 2003 19:29:26 +0000
parents ef5ae9f9c6e6
children d42177a0da2a
comparison
equal deleted inserted replaced
9800:2865ea4eca4b 9801:2f02809d32a8
1 #include "config.h" 1 #include "config.h"
2 2
3 #ifdef HAVE_CDDA 3 #ifdef HAVE_CDDA
4 4
5 #include "stream.h" 5 #include "stream.h"
6 #include "../cfgparser.h" 6 #include "../m_option.h"
7 #include "../m_struct.h"
7 8
8 #include <stdio.h> 9 #include <stdio.h>
9 #include <stdlib.h> 10 #include <stdlib.h>
11 #include "demuxer.h"
10 12
11 #include "cdd.h" 13 #include "cdd.h"
12 14
13 static int speed = -1; 15 static struct cdda_params {
14 static int paranoia_mode = 1; 16 int speed;
15 static char* generic_dev = NULL; 17 int paranoia_mode;
16 static int sector_size = 0; 18 char* generic_dev;
17 static int search_overlap = -1; 19 int sector_size;
18 static int toc_bias = 0; 20 int search_overlap;
19 static int toc_offset = 0; 21 int toc_bias;
20 static int no_skip = 0; 22 int toc_offset;
21 23 int no_skip;
22 config_t cdda_opts[] = { 24 char* device;
23 { "speed", &speed, CONF_TYPE_INT, CONF_RANGE,1,100, NULL }, 25 m_span_t span;
24 { "paranoia", &paranoia_mode, CONF_TYPE_INT,CONF_RANGE, 0, 2, NULL }, 26 } cdda_dflts = {
25 { "generic-dev", &generic_dev, CONF_TYPE_STRING, 0, 0, 0, NULL }, 27 -1,
26 { "sector-size", &sector_size, CONF_TYPE_INT, CONF_RANGE,1,100, NULL }, 28 1,
27 { "overlap", &search_overlap, CONF_TYPE_INT, CONF_RANGE,0,75, NULL }, 29 NULL,
28 { "toc-bias", &toc_bias, CONF_TYPE_INT, 0, 0, 0, NULL }, 30 0,
29 { "toc-offset", &toc_offset, CONF_TYPE_INT, 0, 0, 0, NULL }, 31 -1,
30 { "noskip", &no_skip, CONF_TYPE_FLAG, 0 , 0, 1, NULL }, 32 0,
31 { "skip", &no_skip, CONF_TYPE_FLAG, 0 , 1, 0, NULL }, 33 0,
34 0,
35 DEFAULT_CDROM_DEVICE,
36 { 0, 0 }
37 };
38
39 #define ST_OFF(f) M_ST_OFF(struct cdda_params,f)
40 m_option_t cdda_params_fields[] = {
41 { "speed", ST_OFF(speed), CONF_TYPE_INT, M_OPT_RANGE,1,100, NULL },
42 { "paranoia", ST_OFF(paranoia_mode), CONF_TYPE_INT,M_OPT_RANGE, 0, 2, NULL },
43 { "generic-dev", ST_OFF(generic_dev), CONF_TYPE_STRING, 0, 0, 0, NULL },
44 { "sector-size", ST_OFF(sector_size), CONF_TYPE_INT, M_OPT_RANGE,1,100, NULL },
45 { "overlap", ST_OFF(search_overlap), CONF_TYPE_INT, M_OPT_RANGE,0,75, NULL },
46 { "toc-bias", ST_OFF(toc_bias), CONF_TYPE_INT, 0, 0, 0, NULL },
47 { "toc-offset", ST_OFF(toc_offset), CONF_TYPE_INT, 0, 0, 0, NULL },
48 { "noskip", ST_OFF(no_skip), CONF_TYPE_FLAG, 0 , 0, 1, NULL },
49 { "skip", ST_OFF(no_skip), CONF_TYPE_FLAG, 0 , 1, 0, NULL },
50 { "device", ST_OFF(device), CONF_TYPE_STRING, 0, 0, 0, NULL },
51 { "span", ST_OFF(span), CONF_TYPE_OBJ_PARAMS, 0, 0, 0, &m_span_params_def },
52 /// For url parsing
53 { "hostname", ST_OFF(span), CONF_TYPE_OBJ_PARAMS, 0, 0, 0, &m_span_params_def },
54 { "port", ST_OFF(speed), CONF_TYPE_INT, M_OPT_RANGE,1,100, NULL },
55 { "filename", ST_OFF(device), CONF_TYPE_STRING, 0, 0, 0, NULL },
32 {NULL, NULL, 0, 0, 0, 0, NULL} 56 {NULL, NULL, 0, 0, 0, 0, NULL}
33 }; 57 };
34 58 static struct m_struct_st stream_opts = {
35 stream_t* open_cdda(char* dev,char* track) { 59 "cdda",
36 stream_t* st; 60 sizeof(struct cdda_params),
37 int start_track = 0; 61 &cdda_dflts,
38 int end_track = 0; 62 cdda_params_fields
39 int mode = paranoia_mode; 63 };
40 int offset = toc_offset; 64
65 /// We keep these options but now they set the defaults
66 m_option_t cdda_opts[] = {
67 { "speed", &cdda_dflts.speed, CONF_TYPE_INT, M_OPT_RANGE,1,100, NULL },
68 { "paranoia", &cdda_dflts.paranoia_mode, CONF_TYPE_INT,M_OPT_RANGE, 0, 2, NULL },
69 { "generic-dev", &cdda_dflts.generic_dev, CONF_TYPE_STRING, 0, 0, 0, NULL },
70 { "sector-size", &cdda_dflts.sector_size, CONF_TYPE_INT, M_OPT_RANGE,1,100, NULL },
71 { "overlap", &cdda_dflts.search_overlap, CONF_TYPE_INT, M_OPT_RANGE,0,75, NULL },
72 { "toc-bias", &cdda_dflts.toc_bias, CONF_TYPE_INT, 0, 0, 0, NULL },
73 { "toc-offset", &cdda_dflts.toc_offset, CONF_TYPE_INT, 0, 0, 0, NULL },
74 { "noskip", &cdda_dflts.no_skip, CONF_TYPE_FLAG, 0 , 0, 1, NULL },
75 { "skip", &cdda_dflts.no_skip, CONF_TYPE_FLAG, 0 , 1, 0, NULL },
76 { "device", &cdda_dflts.device, CONF_TYPE_STRING, 0, 0, 0, NULL },
77 { "span", &cdda_dflts.span, CONF_TYPE_OBJ_PARAMS, 0, 0, 0, &m_span_params_def },
78 {NULL, NULL, 0, 0, 0, 0, NULL}
79 };
80
81 extern int cddb_resolve(const char *dev, char **xmcd_file);
82 extern cd_info_t* cddb_parse_xmcd(char *xmcd_file);
83
84 static int seek(stream_t* s,off_t pos);
85 static int fill_buffer(stream_t* s, char* buffer, int max_len);
86 static void close(stream_t* s);
87
88 static int open_cdda(stream_t *st,int m, void* opts, int* file_format) {
89 struct cdda_params* p = (struct cdda_params*)opts;
90 int mode = p->paranoia_mode;
91 int offset = p->toc_offset;
41 cdrom_drive* cdd = NULL; 92 cdrom_drive* cdd = NULL;
42 cdda_priv* priv; 93 cdda_priv* priv;
43 char* end = strchr(track,'-'); 94 cd_info_t *cd_info,*cddb_info = NULL;
44 cd_info_t *cd_info;
45 unsigned int audiolen=0; 95 unsigned int audiolen=0;
46 int i; 96 int i;
47 97 char *xmcd_file = NULL;
48 if(!end) 98
49 start_track = end_track = atoi(track); 99 if(m != STREAM_READ) {
50 else { 100 m_struct_free(&stream_opts,opts);
51 int st_len = end - track; 101 return STREAM_UNSUPORTED;
52 int ed_len = strlen(track) - 1 - st_len; 102 }
53 103
54 if(st_len) { 104 #ifdef STREAMING
55 char st[st_len + 1]; 105 if(strncmp(st->url,"cddb",4) == 0) {
56 strncpy(st,track,st_len); 106 i = cddb_resolve(p->device, &xmcd_file);
57 st[st_len] = '\0'; 107 if(i == 0) {
58 start_track = atoi(st); 108 cddb_info = cddb_parse_xmcd(xmcd_file);
109 free(xmcd_file);
59 } 110 }
60 if(ed_len) { 111 }
61 char ed[ed_len + 1]; 112 #endif
62 strncpy(ed,end+1,ed_len); 113
63 ed[ed_len] = '\0'; 114 if(p->generic_dev)
64 end_track = atoi(ed); 115 cdd = cdda_identify_scsi(p->generic_dev,p->device,0,NULL);
65 }
66 }
67
68 if(generic_dev)
69 cdd = cdda_identify_scsi(generic_dev,dev,0,NULL);
70 else 116 else
71 #if defined(__NetBSD__) 117 #if defined(__NetBSD__)
72 cdd = cdda_identify_scsi(dev,dev,0,NULL); 118 cdd = cdda_identify_scsi(p->device,p->device,0,NULL);
73 #else 119 #else
74 cdd = cdda_identify(dev,0,NULL); 120 cdd = cdda_identify(p->device,0,NULL);
75 #endif 121 #endif
76 122
77 if(!cdd) { 123 if(!cdd) {
78 mp_msg(MSGT_OPEN,MSGL_ERR,"Can't open cdda device\n"); 124 mp_msg(MSGT_OPEN,MSGL_ERR,"Can't open cdda device\n");
79 return NULL; 125 m_struct_free(&stream_opts,opts);
126 return STREAM_ERROR;
80 } 127 }
81 128
82 cdda_verbose_set(cdd, CDDA_MESSAGE_FORGETIT, CDDA_MESSAGE_FORGETIT); 129 cdda_verbose_set(cdd, CDDA_MESSAGE_FORGETIT, CDDA_MESSAGE_FORGETIT);
83 130
84 if(sector_size) { 131 if(p->sector_size) {
85 cdd->nsectors = sector_size; 132 cdd->nsectors = p->sector_size;
86 cdd->bigbuff = sector_size * CD_FRAMESIZE_RAW; 133 cdd->bigbuff = p->sector_size * CD_FRAMESIZE_RAW;
87 } 134 }
88 135
89 if(cdda_open(cdd) != 0) { 136 if(cdda_open(cdd) != 0) {
90 mp_msg(MSGT_OPEN,MSGL_ERR,"Can't open disc\n"); 137 mp_msg(MSGT_OPEN,MSGL_ERR,"Can't open disc\n");
91 cdda_close(cdd); 138 cdda_close(cdd);
92 return NULL; 139 m_struct_free(&stream_opts,opts);
140 return STREAM_ERROR;
93 } 141 }
94 142
95 cd_info = cd_info_new(); 143 cd_info = cd_info_new();
96 mp_msg(MSGT_OPEN,MSGL_INFO,"Found Audio CD with %d tracks\n",cdda_tracks(cdd)); 144 mp_msg(MSGT_OPEN,MSGL_INFO,"Found Audio CD with %d tracks\n",cdda_tracks(cdd));
97 for(i=0;i<cdd->tracks;i++) { 145 for(i=0;i<cdd->tracks;i++) {
110 priv = (cdda_priv*)malloc(sizeof(cdda_priv)); 158 priv = (cdda_priv*)malloc(sizeof(cdda_priv));
111 memset(priv, 0, sizeof(cdda_priv)); 159 memset(priv, 0, sizeof(cdda_priv));
112 priv->cd = cdd; 160 priv->cd = cdd;
113 priv->cd_info = cd_info; 161 priv->cd_info = cd_info;
114 162
115 if(toc_bias) 163 if(p->toc_bias)
116 offset -= cdda_track_firstsector(cdd,1); 164 offset -= cdda_track_firstsector(cdd,1);
117 165
118 if(offset) { 166 if(offset) {
119 int i; 167 int i;
120 for(i = 0 ; i < cdd->tracks + 1 ; i++) 168 for(i = 0 ; i < cdd->tracks + 1 ; i++)
121 cdd->disc_toc[i].dwStartSector += offset; 169 cdd->disc_toc[i].dwStartSector += offset;
122 } 170 }
123 171
124 if(speed) 172 if(p->speed)
125 cdda_speed_set(cdd,speed); 173 cdda_speed_set(cdd,p->speed);
126 174
127 if(start_track) 175 if(p->span.start)
128 priv->start_sector = cdda_track_firstsector(cdd,start_track); 176 priv->start_sector = cdda_track_firstsector(cdd,p->span.start);
129 else 177 else
130 priv->start_sector = cdda_disc_firstsector(cdd); 178 priv->start_sector = cdda_disc_firstsector(cdd);
131 179
132 if(end_track) { 180 if(p->span.end) {
133 int last = cdda_tracks(cdd); 181 int last = cdda_tracks(cdd);
134 if(end_track > last) end_track = last; 182 if(p->span.end > last) p->span.end = last;
135 priv->end_sector = cdda_track_lastsector(cdd,end_track); 183 priv->end_sector = cdda_track_lastsector(cdd,p->span.end);
136 } else 184 } else
137 priv->end_sector = cdda_disc_lastsector(cdd); 185 priv->end_sector = cdda_disc_lastsector(cdd);
138 186
139 priv->cdp = paranoia_init(cdd); 187 priv->cdp = paranoia_init(cdd);
140 if(priv->cdp == NULL) { 188 if(priv->cdp == NULL) {
141 cdda_close(cdd); 189 cdda_close(cdd);
142 free(priv); 190 free(priv);
143 return NULL; 191 cd_info_free(cd_info);
192 m_struct_free(&stream_opts,opts);
193 return STREAM_ERROR;
144 } 194 }
145 195
146 if(mode == 0) 196 if(mode == 0)
147 mode = PARANOIA_MODE_DISABLE; 197 mode = PARANOIA_MODE_DISABLE;
148 else if(mode == 1) 198 else if(mode == 1)
149 mode = PARANOIA_MODE_OVERLAP; 199 mode = PARANOIA_MODE_OVERLAP;
150 else 200 else
151 mode = PARANOIA_MODE_FULL; 201 mode = PARANOIA_MODE_FULL;
152 202
153 if(no_skip) 203 if(p->no_skip)
154 mode |= PARANOIA_MODE_NEVERSKIP; 204 mode |= PARANOIA_MODE_NEVERSKIP;
155 205
156 if(search_overlap >= 0) 206 if(p->search_overlap >= 0)
157 paranoia_overlapset(cdd,search_overlap); 207 paranoia_overlapset(cdd,p->search_overlap);
158 208
159 paranoia_seek(priv->cdp,priv->start_sector,SEEK_SET); 209 paranoia_seek(priv->cdp,priv->start_sector,SEEK_SET);
160 priv->sector = priv->start_sector; 210 priv->sector = priv->start_sector;
161 211
162 st = new_stream(-1,STREAMTYPE_CDDA); 212 #ifdef STREAMING
213 if(cddb_info) {
214 cd_info_free(cd_info);
215 priv->cd_info = cddb_info;
216 cd_info_debug( cddb_info );
217 }
218 #endif
219
163 st->priv = priv; 220 st->priv = priv;
164 st->start_pos = priv->start_sector*CD_FRAMESIZE_RAW; 221 st->start_pos = priv->start_sector*CD_FRAMESIZE_RAW;
165 st->end_pos = priv->end_sector*CD_FRAMESIZE_RAW; 222 st->end_pos = priv->end_sector*CD_FRAMESIZE_RAW;
166 223 st->type = STREAMTYPE_CDDA;
167 return st; 224 st->sector_size = CD_FRAMESIZE_RAW;
225
226 st->fill_buffer = fill_buffer;
227 st->seek = seek;
228 st->close = close;
229
230 *file_format = DEMUXER_TYPE_RAWAUDIO;
231
232 m_struct_free(&stream_opts,opts);
233
234 return STREAM_OK;
168 } 235 }
169 236
170 static void cdparanoia_callback(long inpos, int function) { 237 static void cdparanoia_callback(long inpos, int function) {
171 } 238 }
172 239
173 int read_cdda(stream_t* s) { 240 static int fill_buffer(stream_t* s, char* buffer, int max_len) {
174 cdda_priv* p = (cdda_priv*)s->priv; 241 cdda_priv* p = (cdda_priv*)s->priv;
175 cd_track_t *cd_track; 242 cd_track_t *cd_track;
176 int16_t * buf; 243 int16_t * buf;
177 unsigned int i; 244 int i;
178 245
179 buf = paranoia_read(p->cdp,cdparanoia_callback); 246 buf = paranoia_read(p->cdp,cdparanoia_callback);
180 247
181 p->sector++; 248 p->sector++;
182 s->pos = p->sector*CD_FRAMESIZE_RAW; 249 s->pos = p->sector*CD_FRAMESIZE_RAW;
183 memcpy(s->buffer,buf,CD_FRAMESIZE_RAW); 250 memcpy(buffer,buf,CD_FRAMESIZE_RAW);
184 251
185 if((p->sector < p->start_sector) || (p->sector >= p->end_sector)) { 252 if((p->sector < p->start_sector) || (p->sector >= p->end_sector)) {
186 s->eof = 1; 253 s->eof = 1;
187 return 0; 254 return 0;
188 } 255 }
200 267
201 268
202 return CD_FRAMESIZE_RAW; 269 return CD_FRAMESIZE_RAW;
203 } 270 }
204 271
205 void seek_cdda(stream_t* s) { 272 static int seek(stream_t* s,off_t newpos) {
206 cdda_priv* p = (cdda_priv*)s->priv; 273 cdda_priv* p = (cdda_priv*)s->priv;
207 cd_track_t *cd_track; 274 cd_track_t *cd_track;
208 int sec; 275 int sec;
209 int current_track=0, seeked_track=0; 276 int current_track=0, seeked_track=0;
210 int i; 277 int i;
211 278
279 s->pos = newpos;
212 if(s->pos < 0) { 280 if(s->pos < 0) {
213 s->eof = 1; 281 s->eof = 1;
214 return; 282 return 0;
215 } 283 }
216 284
217 sec = s->pos/CD_FRAMESIZE_RAW; 285 sec = s->pos/CD_FRAMESIZE_RAW;
218 //printf("pos: %d, sec: %d ## %d\n", (int)s->pos, (int)sec, CD_FRAMESIZE_RAW); 286 //printf("pos: %d, sec: %d ## %d\n", (int)s->pos, (int)sec, CD_FRAMESIZE_RAW);
219 //printf("sector: %d new: %d\n", p->sector, sec ); 287 //printf("sector: %d new: %d\n", p->sector, sec );
246 p->sector = sec; 314 p->sector = sec;
247 // s->pos = sec*CD_FRAMESIZE_RAW; 315 // s->pos = sec*CD_FRAMESIZE_RAW;
248 316
249 //printf("seek: %d, sec: %d\n", (int)s->pos, sec); 317 //printf("seek: %d, sec: %d\n", (int)s->pos, sec);
250 paranoia_seek(p->cdp,sec,SEEK_SET); 318 paranoia_seek(p->cdp,sec,SEEK_SET);
251 319 return 1;
252 } 320 }
253 321
254 void close_cdda(stream_t* s) { 322 static void close(stream_t* s) {
255 cdda_priv* p = (cdda_priv*)s->priv; 323 cdda_priv* p = (cdda_priv*)s->priv;
256 paranoia_free(p->cdp); 324 paranoia_free(p->cdp);
257 cdda_close(p->cd); 325 cdda_close(p->cd);
258 } 326 cd_info_free(p->cd_info);
259 327 free(p);
260 #endif 328 }
329
330 stream_info_t stream_info_cdda = {
331 "CDDA",
332 "cdda",
333 "Albeu",
334 "",
335 open_cdda,
336 { "cdda", "cddb", NULL },
337 &stream_opts,
338 1 // Urls are an option string
339 };
340
341 #endif