Get rid of code I neither know nor use anymore.
[mplayer/glamo.git] / stream / stream_cue.c
blobef2c8f71a23233066411c8d4756464002aacf9cc
1 //=================== VideoCD BinCue ==========================
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <unistd.h>
10 #include <fcntl.h>
12 #include "config.h"
13 #include "mp_msg.h"
14 #include "help_mp.h"
16 #include "stream.h"
18 #include "help_mp.h"
19 #include "m_option.h"
20 #include "m_struct.h"
22 #define byte unsigned char
23 #define SIZERAW 2352
24 #define SIZEISO_MODE1 2048
25 #define SIZEISO_MODE2_RAW 2352
26 #define SIZEISO_MODE2_FORM1 2048
27 #define SIZEISO_MODE2_FORM2 2336
28 #define AUDIO 0
29 #define MODE1 1
30 #define MODE2 2
31 #define MODE1_2352 10
32 #define MODE2_2352 20
33 #define MODE1_2048 30
34 #define MODE2_2336 40
35 #define UNKNOWN -1
37 static struct stream_priv_s {
38 char* filename;
39 } stream_priv_dflts = {
40 NULL
43 #define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f)
44 /// URL definition
45 static m_option_t stream_opts_fields[] = {
46 { "string", ST_OFF(filename), CONF_TYPE_STRING, 0, 0 ,0, NULL},
47 { NULL, NULL, 0, 0, 0, 0, NULL }
49 static struct m_struct_st stream_opts = {
50 "cue",
51 sizeof(struct stream_priv_s),
52 &stream_priv_dflts,
53 stream_opts_fields
56 static FILE* fd_cue;
57 static int fd_bin = 0;
59 static char bin_filename[256];
61 static char cue_filename[256];
62 static char bincue_path[256];
65 typedef struct track
67 unsigned short mode;
68 unsigned short minute;
69 unsigned short second;
70 unsigned short frame;
72 /* (min*60 + sec) * 75 + fps */
74 unsigned long start_sector;
76 /* = the sizes in bytes off all tracks bevor this one */
77 /* its needed if there are mode1 tracks befor the mpeg tracks */
78 unsigned long start_offset;
80 /* unsigned char num[3]; */
81 } tTrack;
83 /* max 99 tracks on a cd */
84 static tTrack tracks[100];
86 static struct cue_track_pos {
87 int track;
88 unsigned short mode;
89 unsigned short minute;
90 unsigned short second;
91 unsigned short frame;
92 } cue_current_pos;
94 /* number of tracks on the cd */
95 static int nTracks = 0;
97 /* presumes Line is preloaded with the "current" line of the file */
98 static int cue_getTrackinfo(char *Line, tTrack *track)
100 char inum[3];
101 char min;
102 char sec;
103 char fps;
104 int already_set = 0;
106 /* Get the 'mode' */
107 if (strncmp(&Line[2], "TRACK ", 6)==0)
109 /* strncpy(track->num, &Line[8], 2); track->num[2] = '\0'; */
111 track->mode = UNKNOWN;
112 if(strncmp(&Line[11], "AUDIO", 5)==0) track->mode = AUDIO;
113 if(strncmp(&Line[11], "MODE1/2352", 10)==0) track->mode = MODE1_2352;
114 if(strncmp(&Line[11], "MODE1/2048", 10)==0) track->mode = MODE1_2048;
115 if(strncmp(&Line[11], "MODE2/2352", 10)==0) track->mode = MODE2_2352;
116 if(strncmp(&Line[11], "MODE2/2336", 10)==0) track->mode = MODE2_2336;
118 else return(1);
120 /* Get the track indexes */
121 while(1) {
122 if(! fgets( Line, 256, fd_cue ) ) { break;}
124 if (strncmp(&Line[2], "TRACK ", 6)==0)
126 /* next track starting */
127 break;
130 /* Track 0 or 1, take the first an get fill the values*/
131 if (strncmp(&Line[4], "INDEX ", 6)==0)
133 /* check stuff here so if the answer is false the else stuff below won't be executed */
134 strncpy(inum, &Line[10], 2); inum[2] = '\0';
135 if ((already_set == 0) &&
136 ((strcmp(inum, "00")==0) || (strcmp(inum, "01")==0)))
138 already_set = 1;
140 min = ((Line[13]-'0')<<4) | (Line[14]-'0');
141 sec = ((Line[16]-'0')<<4) | (Line[17]-'0');
142 fps = ((Line[19]-'0')<<4) | (Line[20]-'0');
144 track->minute = (((min>>4)*10) + (min&0xf));
145 track->second = (((sec>>4)*10) + (sec&0xf));
146 track->frame = (((fps>>4)*10) + (fps&0xf));
149 else if (strncmp(&Line[4], "PREGAP ", 7)==0) { ; /* ignore */ }
150 else if (strncmp(&Line[4], "FLAGS ", 6)==0) { ; /* ignore */ }
151 else mp_msg (MSGT_OPEN,MSGL_INFO,
152 MSGTR_MPDEMUX_CUEREAD_UnexpectedCuefileLine, Line);
154 return(0);
159 /* FIXME: the string operations ( strcpy,strcat ) below depend
160 * on the arrays to have the same size, thus we need to make
161 * sure the sizes are in sync.
163 static int cue_find_bin (char *firstline) {
164 int i,j;
165 char s[256];
166 char t[256];
168 /* get the filename out of that */
169 /* 12345 6 */
170 mp_msg (MSGT_OPEN,MSGL_INFO, "[bincue] cue_find_bin(%s)\n", firstline);
171 if (strncmp(firstline, "FILE \"",6)==0)
173 i = 0;
174 j = 0;
175 while ( firstline[6 + i] != '"')
177 bin_filename[j] = firstline[6 + i];
179 /* if I found a path info, than delete all bevor it */
180 switch (bin_filename[j])
182 case '\\':
183 j = 0;
184 break;
186 case '/':
187 j = 0;
188 break;
190 default:
191 j++;
193 i++;
195 bin_filename[j+1] = '\0';
199 /* now try to open that file, without path */
200 fd_bin = open (bin_filename, O_RDONLY);
201 if (fd_bin == -1)
203 mp_msg(MSGT_OPEN,MSGL_STATUS, MSGTR_MPDEMUX_CUEREAD_BinFilenameTested,
204 bin_filename);
206 /* now try to find it with the path of the cue file */
207 snprintf(s,sizeof( s ),"%s/%s",bincue_path,bin_filename);
208 fd_bin = open (s, O_RDONLY);
209 if (fd_bin == -1)
211 mp_msg(MSGT_OPEN,MSGL_STATUS,
212 MSGTR_MPDEMUX_CUEREAD_BinFilenameTested, s);
213 /* now I would say the whole filename is shit, build our own */
214 strncpy(s, cue_filename, strlen(cue_filename) - 3 );
215 s[strlen(cue_filename) - 3] = '\0';
216 strcat(s, "bin");
217 fd_bin = open (s, O_RDONLY);
218 if (fd_bin == -1)
220 mp_msg(MSGT_OPEN,MSGL_STATUS,
221 MSGTR_MPDEMUX_CUEREAD_BinFilenameTested, s);
223 /* ok try it with path */
224 snprintf(t, sizeof( t ), "%s/%s", bincue_path, s);
225 fd_bin = open (t, O_RDONLY);
226 if (fd_bin == -1)
228 mp_msg(MSGT_OPEN,MSGL_STATUS,
229 MSGTR_MPDEMUX_CUEREAD_BinFilenameTested,t);
230 /* now I would say the whole filename is shit, build our own */
231 strncpy(s, cue_filename, strlen(cue_filename) - 3 );
232 s[strlen(cue_filename) - 3] = '\0';
233 strcat(s, "img");
234 fd_bin = open (s, O_RDONLY);
235 if (fd_bin == -1)
237 mp_msg(MSGT_OPEN,MSGL_STATUS,
238 MSGTR_MPDEMUX_CUEREAD_BinFilenameTested, s);
239 /* ok try it with path */
240 snprintf(t, sizeof( t ), "%s/%s", bincue_path, s);
241 fd_bin = open (t, O_RDONLY);
242 if (fd_bin == -1)
244 mp_msg(MSGT_OPEN,MSGL_STATUS,
245 MSGTR_MPDEMUX_CUEREAD_BinFilenameTested, s);
247 /* I'll give up */
248 mp_msg(MSGT_OPEN,MSGL_ERR,
249 MSGTR_MPDEMUX_CUEREAD_CannotFindBinFile);
250 return -1;
253 } else strcpy(bin_filename, t);
255 } else strcpy(bin_filename, s);
257 } else strcpy(bin_filename, s);
261 mp_msg(MSGT_OPEN,MSGL_INFO,
262 MSGTR_MPDEMUX_CUEREAD_UsingBinFile, bin_filename);
263 return 0;
266 static inline int cue_msf_2_sector(int minute, int second, int frame) {
267 return frame + (second + minute * 60 ) * 75;
270 static inline int cue_get_msf(void) {
271 return cue_msf_2_sector (cue_current_pos.minute,
272 cue_current_pos.second,
273 cue_current_pos.frame);
276 static inline void cue_set_msf(unsigned int sect){
277 cue_current_pos.frame=sect%75;
278 sect=sect/75;
279 cue_current_pos.second=sect%60;
280 sect=sect/60;
281 cue_current_pos.minute=sect;
284 static inline int cue_mode_2_sector_size(int mode)
286 switch (mode)
288 case AUDIO: return AUDIO;
289 case MODE1_2352: return SIZERAW;
290 case MODE1_2048: return SIZEISO_MODE1;
291 case MODE2_2352: return SIZEISO_MODE2_RAW;
292 case MODE2_2336: return SIZEISO_MODE2_FORM2;
294 default:
295 mp_msg(MSGT_OPEN,MSGL_FATAL,
296 MSGTR_MPDEMUX_CUEREAD_UnknownModeForBinfile);
297 abort();
303 static int cue_read_cue (char *in_cue_filename)
305 struct stat filestat;
306 char sLine[256];
307 unsigned int sect;
308 char *s,*t;
309 int i;
311 /* we have no tracks at the beginning */
312 nTracks = 0;
314 fd_bin = 0;
316 /* split the filename into a path and filename part */
317 s = strdup(in_cue_filename);
318 t = strrchr(s, '/');
319 if (t == (char *)NULL)
320 t = ".";
321 else {
322 *t = '\0';
323 t = s;
324 if (*t == '\0')
325 strcpy(t, "/");
328 strlcpy(bincue_path,t,sizeof( bincue_path ));
329 mp_msg(MSGT_OPEN,MSGL_V,"dirname: %s, cuepath: %s\n", t, bincue_path);
331 /* no path at all? */
332 if (strcmp(bincue_path, ".") == 0) {
333 mp_msg(MSGT_OPEN,MSGL_V,"bincue_path: %s\n", bincue_path);
334 strlcpy(cue_filename,in_cue_filename,sizeof( cue_filename ));
335 } else {
336 strlcpy(cue_filename,in_cue_filename + strlen(bincue_path) + 1,
337 sizeof( cue_filename ));
342 /* open the cue file */
343 fd_cue = fopen (in_cue_filename, "r");
344 if (fd_cue == NULL)
346 mp_msg(MSGT_OPEN,MSGL_ERR,
347 MSGTR_MPDEMUX_CUEREAD_CannotOpenCueFile, in_cue_filename);
348 return -1;
351 /* read the first line and hand it to find_bin, which will
352 test more than one possible name of the file */
354 if(! fgets( sLine, 256, fd_cue ) )
356 mp_msg(MSGT_OPEN,MSGL_ERR,
357 MSGTR_MPDEMUX_CUEREAD_ErrReadingFromCueFile, in_cue_filename);
358 fclose (fd_cue);
359 return -1;
362 if (cue_find_bin(sLine)) {
363 fclose (fd_cue);
364 return -1;
368 /* now build the track list */
369 /* red the next line and call our track finder */
370 if(! fgets( sLine, 256, fd_cue ) )
372 mp_msg(MSGT_OPEN,MSGL_ERR,
373 MSGTR_MPDEMUX_CUEREAD_ErrReadingFromCueFile, in_cue_filename);
374 fclose (fd_cue);
375 return -1;
378 while(!feof(fd_cue))
380 if (cue_getTrackinfo(sLine, &tracks[nTracks++]) != 0)
382 mp_msg(MSGT_OPEN,MSGL_ERR,
383 MSGTR_MPDEMUX_CUEREAD_ErrReadingFromCueFile, in_cue_filename);
384 fclose (fd_cue);
385 return -1;
389 /* make a fake track with stands for the Lead out */
390 if (fstat (fd_bin, &filestat) == -1) {
391 mp_msg(MSGT_OPEN,MSGL_ERR,
392 MSGTR_MPDEMUX_CUEREAD_ErrGettingBinFileSize);
393 fclose (fd_cue);
394 return -1;
397 sect = filestat.st_size / 2352;
399 tracks[nTracks].frame = sect%75;
400 sect=sect/75;
401 tracks[nTracks].second = sect%60;
402 sect=sect/60;
403 tracks[nTracks].minute = sect;
406 /* let's calculate the start sectors and offsets */
407 for(i = 0; i <= nTracks; i++)
409 tracks[i].start_sector = cue_msf_2_sector(tracks[i].minute,
410 tracks[nTracks].second,
411 tracks[nTracks].frame);
413 /* if we're the first track we don't need to offset of the one befor */
414 if (i == 0)
416 /* was always 0 on my svcds, but who knows */
417 tracks[0].start_offset = tracks[0].start_sector *
418 cue_mode_2_sector_size(tracks[0].mode);
419 } else
421 tracks[i].start_offset = tracks[i-1].start_offset +
422 (tracks[i].start_sector - tracks[i-1].start_sector) *
423 cue_mode_2_sector_size(tracks[i-1].mode);
427 fclose (fd_cue);
429 return fd_bin;
435 static int cue_read_toc_entry(void) {
437 int track = cue_current_pos.track - 1;
439 /* check if its a valid track, if not return -1 */
440 if (track >= nTracks)
441 return -1;
444 switch (tracks[track].mode)
446 case AUDIO:
447 cue_current_pos.mode = AUDIO;
448 break;
449 case MODE1_2352:
450 cue_current_pos.mode = MODE1;
451 break;
452 case MODE1_2048:
453 cue_current_pos.mode = MODE1;
454 break;
455 default: /* MODE2_2352 and MODE2_2336 */
456 cue_current_pos.mode = MODE2;
458 cue_current_pos.minute = tracks[track].minute;
459 cue_current_pos.second = tracks[track].second;
460 cue_current_pos.frame = tracks[track].frame;
462 return 0;
465 static int cue_vcd_seek_to_track (int track){
466 cue_current_pos.track = track;
468 if (cue_read_toc_entry ())
469 return -1;
471 return VCD_SECTOR_DATA * cue_get_msf();
474 static int cue_vcd_get_track_end (int track){
475 cue_current_pos.frame = tracks[track].frame;
476 cue_current_pos.second = tracks[track].second;
477 cue_current_pos.minute = tracks[track].minute;
479 return VCD_SECTOR_DATA * cue_get_msf();
482 static void cue_vcd_read_toc(void){
483 int i;
484 for (i = 0; i < nTracks; ++i) {
486 mp_msg(MSGT_OPEN,MSGL_INFO,
487 MSGTR_MPDEMUX_CUEREAD_InfoTrackFormat,
488 i+1,
489 tracks[i].mode,
490 tracks[i].minute,
491 tracks[i].second,
492 tracks[i].frame
497 static int cue_vcd_read(stream_t *stream, char *mem, int size) {
498 unsigned long position;
499 int track = cue_current_pos.track - 1;
501 position = tracks[track].start_offset +
502 (cue_msf_2_sector(cue_current_pos.minute,
503 cue_current_pos.second,
504 cue_current_pos.frame) -
505 tracks[track].start_sector)
506 * cue_mode_2_sector_size(tracks[track].mode);
509 if(position >= tracks[track+1].start_offset)
510 return 0;
512 if(lseek(fd_bin, position+VCD_SECTOR_OFFS, SEEK_SET) == -1) {
513 mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_MPDEMUX_CUEREAD_UnexpectedBinFileEOF);
514 return 0;
517 if(read(fd_bin, mem, VCD_SECTOR_DATA) != VCD_SECTOR_DATA) {
518 mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_MPDEMUX_CUEREAD_CannotReadNBytesOfPayload, VCD_SECTOR_DATA);
519 return 0;
522 cue_current_pos.frame++;
523 if (cue_current_pos.frame==75){
524 cue_current_pos.frame=0;
525 cue_current_pos.second++;
526 if (cue_current_pos.second==60){
527 cue_current_pos.second=0;
528 cue_current_pos.minute++;
532 return VCD_SECTOR_DATA;
535 static int seek(stream_t *s,off_t newpos) {
536 s->pos=newpos;
537 cue_set_msf(s->pos/VCD_SECTOR_DATA);
538 return 1;
542 static int open_s(stream_t *stream,int mode, void* opts, int* file_format) {
543 struct stream_priv_s* p = (struct stream_priv_s*)opts;
544 int ret,ret2,f,track = 0;
545 char *filename = NULL, *colon = NULL;
547 if(mode != STREAM_READ || !p->filename) {
548 m_struct_free(&stream_opts,opts);
549 return STREAM_UNSUPORTED;
551 filename = strdup(p->filename);
552 if(!filename) {
553 m_struct_free(&stream_opts,opts);
554 return STREAM_UNSUPORTED;
556 colon = strstr(filename, ":");
557 if(colon) {
558 if(strlen(colon)>1)
559 track = atoi(colon+1);
560 *colon = 0;
562 if(!track)
563 track = 1;
565 f = cue_read_cue(filename);
566 if(f < 0) {
567 m_struct_free(&stream_opts,opts);
568 return STREAM_UNSUPORTED;
570 cue_vcd_read_toc();
571 ret2=cue_vcd_get_track_end(track);
572 ret=cue_vcd_seek_to_track(track);
573 if(ret<0){
574 mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_ErrTrackSelect " (seek)\n");
575 return STREAM_UNSUPORTED;
577 mp_msg(MSGT_OPEN,MSGL_INFO,MSGTR_MPDEMUX_CUEREAD_CueStreamInfo_FilenameTrackTracksavail, filename, track, ret, ret2);
579 stream->fd = f;
580 stream->type = STREAMTYPE_VCDBINCUE;
581 stream->sector_size = VCD_SECTOR_DATA;
582 stream->flags = STREAM_READ | STREAM_SEEK_FW;
583 stream->start_pos = ret;
584 stream->end_pos = ret2;
585 stream->fill_buffer = cue_vcd_read;
586 stream->seek = seek;
588 free(filename);
589 m_struct_free(&stream_opts,opts);
590 return STREAM_OK;
593 stream_info_t stream_info_cue = {
594 "CUE track",
595 "cue",
596 "Albeu",
597 "based on the code from ???",
598 open_s,
599 { "cue", NULL },
600 &stream_opts,
601 1 // Urls are an option string