"Fossies" - the Fresh Open Source Software Archive 
Member "xorriso-1.5.4/libburn/structure.c" (30 Jan 2021, 52955 Bytes) of package /linux/misc/xorriso-1.5.4.pl02.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "structure.c" see the
Fossies "Dox" file reference documentation.
1
2 /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
3 Copyright (c) 2006 - 2014 Thomas Schmitt <scdbackup@gmx.net>
4 Provided under GPL version 2 or later.
5 */
6
7 #ifdef HAVE_CONFIG_H
8 #include "../config.h"
9 #endif
10
11 /* ts A61008 */
12 /* #include <a ssert.h> */
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <ctype.h>
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <fcntl.h>
21 #include <unistd.h>
22 #include <errno.h>
23
24 /* ts B41126 : O_BINARY is needed for Cygwin but undefined elsewhere */
25 #ifndef O_BINARY
26 #define O_BINARY 0
27 #endif
28
29 #include "libburn.h"
30 #include "structure.h"
31 #include "write.h"
32 #include "debug.h"
33 #include "init.h"
34 #include "util.h"
35 #include "transport.h"
36 #include "mmc.h"
37
38 #include "libdax_msgs.h"
39 extern struct libdax_msgs *libdax_messenger;
40
41
42 /* ts A61008 : replaced Assert by if and return 0 */
43 /* a ssert(!(pos > BURN_POS_END)); */
44
45 #define RESIZE(TO, NEW, pos) {\
46 void *tmp;\
47 \
48 if (pos > BURN_POS_END)\
49 return 0;\
50 if (pos == BURN_POS_END)\
51 pos = TO->NEW##s;\
52 if ((int) pos > TO->NEW##s)\
53 return 0;\
54 \
55 tmp = realloc(TO->NEW, sizeof(struct NEW *) * (TO->NEW##s + 1));\
56 if (!tmp)\
57 return 0;\
58 TO->NEW = tmp;\
59 memmove(TO->NEW + pos + 1, TO->NEW + pos,\
60 sizeof(struct NEW *) * (TO->NEW##s - pos));\
61 TO->NEW##s++;\
62 }
63
64 struct burn_disc *burn_disc_create(void)
65 {
66 struct burn_disc *d;
67 d = calloc(1, sizeof(struct burn_disc));
68 if (d == NULL) /* ts A70825 */
69 return NULL;
70 d->refcnt = 1;
71 d->sessions = 0;
72 d->session = NULL;
73
74 #ifdef Libburn_disc_with_incomplete_sessioN
75 d->incomplete_sessions= 0;
76 #endif
77
78 return d;
79 }
80
81 void burn_disc_free(struct burn_disc *d)
82 {
83 d->refcnt--;
84 if (d->refcnt == 0) {
85 /* dec refs on all elements */
86 int i;
87
88 for (i = 0; i < d->sessions; i++)
89 burn_session_free(d->session[i]);
90 free(d->session);
91 free(d);
92 }
93 }
94
95 struct burn_session *burn_session_create(void)
96 {
97 struct burn_session *s;
98 int i;
99
100 s = calloc(1, sizeof(struct burn_session));
101 if (s == NULL) /* ts A70825 */
102 return NULL;
103 s->firsttrack = 1;
104 s->lasttrack = 0;
105 s->refcnt = 1;
106 s->tracks = 0;
107 s->track = NULL;
108 s->hidefirst = 0;
109 for (i = 0; i < 8; i++) {
110 s->cdtext[i] = NULL;
111 s->cdtext_language[i] = 0x00; /* Unknown */
112 s->cdtext_char_code[i] = 0x00; /* ISO-8859-1 */
113 s->cdtext_copyright[i] = 0x00;
114 }
115 s->cdtext_language[0] = 0x09; /* Single-block default is English */
116 s->mediacatalog[0] = 0;
117 return s;
118 }
119
120 void burn_session_hide_first_track(struct burn_session *s, int onoff)
121 {
122 s->hidefirst = onoff;
123 }
124
125 void burn_session_free(struct burn_session *s)
126 {
127 int i;
128
129 s->refcnt--;
130 if (s->refcnt == 0) {
131 /* dec refs on all elements */
132 for (i = 0; i < s->tracks; i++)
133 burn_track_free(s->track[i]);
134 for (i = 0; i < 8; i++)
135 burn_cdtext_free(&(s->cdtext[i]));
136 free(s->track);
137 free(s);
138 }
139
140 }
141
142 int burn_disc_add_session(struct burn_disc *d, struct burn_session *s,
143 unsigned int pos)
144 {
145 RESIZE(d, session, pos);
146 d->session[pos] = s;
147 s->refcnt++;
148 return 1;
149 }
150
151
152 /* ts A81202: this function was in the API but not implemented.
153 */
154 int burn_disc_remove_session(struct burn_disc *d, struct burn_session *s)
155 {
156 int i, skip = 0;
157
158 if (d->session == NULL)
159 return 0;
160 for (i = 0; i < d->sessions; i++) {
161 if (s == d->session[i]) {
162 skip++;
163 continue;
164 }
165 d->session[i - skip] = d->session[i];
166 }
167 if (!skip)
168 return 0;
169 burn_session_free(s);
170 d->sessions--;
171 return 1;
172 }
173
174
175 struct burn_track *burn_track_create(void)
176 {
177 struct burn_track *t;
178 int i;
179
180 t = calloc(1, sizeof(struct burn_track));
181 if (t == NULL) /* ts A70825 */
182 return NULL;
183 t->refcnt = 1;
184 t->indices = 0;
185 for (i = 0; i < 100; i++)
186 t->index[i] = 0x7fffffff;
187 t->offset = 0;
188 t->offsetcount = 0;
189 t->tail = 0;
190 t->tailcount = 0;
191 t->mode = BURN_MODE1;
192 t->isrc.has_isrc = 0;
193 t->pad = 1;
194
195 /* ts A70213 */
196 t->fill_up_media = 0;
197 /* ts A70218 */
198 t->default_size = 0;
199
200 t->entry = NULL;
201 t->source = NULL;
202 t->eos = 0;
203
204 /* ts A61101 */
205 t->sourcecount = 0;
206 t->writecount = 0;
207 t->written_sectors = 0;
208
209 /* ts A61031 */
210 t->open_ended = 0;
211 t->track_data_done = 0;
212 /* ts B10103 */
213 t->end_on_premature_eoi = 0;
214
215 t->pregap1 = 0;
216 t->pregap2 = 0;
217 t->pregap2_size = 150;
218
219 t->postgap = 0;
220 t->postgap_size = 150;
221
222 /* ts A61024 */
223 t->swap_source_bytes = 0;
224
225 /* ts B11206 */
226 for (i = 0; i < 8; i++)
227 t->cdtext[i] = NULL;
228
229 return t;
230 }
231
232 void burn_track_free(struct burn_track *t)
233 {
234 int i;
235
236 t->refcnt--;
237 if (t->refcnt == 0) {
238 /* dec refs on all elements */
239 if (t->source)
240 burn_source_free(t->source);
241 for (i = 0; i < 8; i++)
242 burn_cdtext_free(&(t->cdtext[i]));
243 free(t);
244 }
245 }
246
247 int burn_session_add_track(struct burn_session *s, struct burn_track *t,
248 unsigned int pos)
249 {
250 RESIZE(s, track, pos);
251 s->track[pos] = t;
252 t->refcnt++;
253 return 1;
254 }
255
256 int burn_session_remove_track(struct burn_session *s, struct burn_track *t)
257 {
258 struct burn_track **tmp;
259 int i, pos = -1;
260
261 /* ts A61008 */
262 /* a ssert(s->track != NULL); */
263 if (s->track == NULL)
264 return 0;
265
266 burn_track_free(t);
267
268 /* Find the position */
269 for (i = 0; i < s->tracks; i++) {
270 if (t == s->track[i]) {
271 pos = i;
272 break;
273 }
274 }
275
276 if (pos == -1)
277 return 0;
278
279 /* Is it the last track? */
280 if (pos != s->tracks - 1) {
281 memmove(&s->track[pos], &s->track[pos + 1],
282 sizeof(struct burn_track *) * (s->tracks - (pos + 1)));
283 }
284
285 s->tracks--;
286 tmp = realloc(s->track, sizeof(struct burn_track *) * s->tracks);
287 if (tmp)
288 s->track = tmp;
289 return 1;
290 }
291
292 void burn_structure_print_disc(struct burn_disc *d)
293 {
294 int i;
295 char msg[40];
296
297 sprintf(msg, "This disc has %d sessions", d->sessions);
298 libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
299 LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
300 msg, 0, 0);
301 for (i = 0; i < d->sessions; i++) {
302 burn_structure_print_session(d->session[i]);
303 }
304 }
305 void burn_structure_print_session(struct burn_session *s)
306 {
307 int i;
308 char msg[40];
309
310 sprintf(msg, " Session has %d tracks", s->tracks);
311 libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
312 LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
313 msg, 0, 0);
314 for (i = 0; i < s->tracks; i++) {
315 burn_structure_print_track(s->track[i]);
316 }
317 }
318 void burn_structure_print_track(struct burn_track *t)
319 {
320 char msg[80];
321
322 sprintf(msg, " track size %d sectors",
323 burn_track_get_sectors(t));
324 libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
325 LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
326 msg, 0, 0);
327 }
328
329 void burn_track_define_data(struct burn_track *t, int offset, int tail,
330 int pad, int mode)
331 {
332 int type_to_form(int mode, unsigned char *ctladr, int *form);
333 int burn_sector_length(int tracktype);
334 unsigned char ctladr;
335 int form = -1; /* unchanged form will be considered an error too */
336 char msg[80];
337
338 type_to_form(mode, &ctladr, &form);
339 if (form == -1 || burn_sector_length(mode) <= 0) {
340
341 sprintf(msg,
342 "Attempt to set track mode to unusable value 0x%X",
343 (unsigned int) mode);
344 libdax_msgs_submit(libdax_messenger, -1, 0x00020115,
345 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
346 msg, 0, 0);
347 return;
348 }
349
350 t->offset = offset;
351 t->pad = pad;
352 t->mode = mode;
353 t->tail = tail;
354 }
355
356
357 /* ts A61024 */
358 int burn_track_set_byte_swap(struct burn_track *t, int swap_source_bytes)
359 {
360 if (swap_source_bytes != 0 && swap_source_bytes != 1)
361 return 0;
362 t->swap_source_bytes = swap_source_bytes;
363 return 1;
364 }
365
366
367 /* ts A90911 : API */
368 int burn_track_set_cdxa_conv(struct burn_track *t, int value)
369 {
370 if (value < 0 || value > 1)
371 return 0;
372 t->cdxa_conversion = value;
373 return 1;
374 }
375
376
377 void burn_track_set_isrc(struct burn_track *t, char *country, char *owner,
378 unsigned char year, unsigned int serial)
379 {
380 int i;
381
382 /* ts B11226 */
383 t->isrc.has_isrc = 0;
384
385 for (i = 0; i < 2; ++i) {
386
387 /* ts A61008 : This is always true */
388 /* a ssert((country[i] >= '0' || country[i] < '9') &&
389 (country[i] >= 'a' || country[i] < 'z') &&
390 (country[i] >= 'A' || country[i] < 'Z')); */
391 /* ts A61008 : now coordinated with sector.c: char_to_isrc() */
392 if (! ((country[i] >= '0' && country[i] <= '9') ||
393 (country[i] >= 'a' && country[i] <= 'z') ||
394 (country[i] >= 'A' && country[i] <= 'Z') ) )
395 goto is_not_allowed;
396
397 t->isrc.country[i] = country[i];
398 }
399 for (i = 0; i < 3; ++i) {
400
401 /* ts A61008 : This is always true */
402 /* a ssert((owner[i] >= '0' || owner[i] < '9') &&
403 (owner[i] >= 'a' || owner[i] < 'z') &&
404 (owner[i] >= 'A' || owner[i] < 'Z')); */
405 /* ts A61008 : now coordinated with sector.c: char_to_isrc() */
406 if (! ((owner[i] >= '0' && owner[i] <= '9') ||
407 (owner[i] >= 'a' && owner[i] <= 'z') ||
408 (owner[i] >= 'A' && owner[i] <= 'Z') ) )
409 goto is_not_allowed;
410
411 t->isrc.owner[i] = owner[i];
412 }
413
414 /* ts A61008 */
415 /* a ssert(year <= 99); */
416 if (year > 99)
417 goto is_not_allowed;
418
419 t->isrc.year = year;
420
421 /* ts A61008 */
422 /* a ssert(serial <= 99999); */
423 if (serial > 99999)
424 goto is_not_allowed;
425
426 t->isrc.serial = serial;
427
428 /* ts A61008 */
429 t->isrc.has_isrc = 1;
430 return;
431 is_not_allowed:;
432 libdax_msgs_submit(libdax_messenger, -1, 0x00020114,
433 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
434 "Attempt to set ISRC with bad data", 0, 0);
435 return;
436 }
437
438 /* ts B11226 API */
439 int burn_track_set_isrc_string(struct burn_track *t, char isrc[13], int flag)
440 {
441 unsigned char year;
442 unsigned int serial = 2000000000;
443
444 if (strlen(isrc) != 12 ||
445 isrc[5] < '0' || isrc[5] > '9' || isrc[6] < '0' || isrc[6] > '9') {
446 libdax_msgs_submit(libdax_messenger, -1, 0x00020114,
447 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
448 "Attempt to set ISRC with bad data", 0, 0);
449 return 0;
450 }
451 year = (isrc[5] - '0') * 10 + (isrc[6] - '0');
452 isrc[12] = 0;
453 sscanf(isrc + 7, "%u", &serial);
454 burn_track_set_isrc(t, isrc, isrc + 2, year, serial);
455 return t->isrc.has_isrc;
456 }
457
458 void burn_track_clear_isrc(struct burn_track *t)
459 {
460 t->isrc.has_isrc = 0;
461 }
462
463 /* ts B20103 API */
464 int burn_track_set_index(struct burn_track *t, int index_number,
465 unsigned int relative_lba, int flag)
466 {
467 if (index_number < 0 || index_number > 99) {
468 libdax_msgs_submit(libdax_messenger, -1, 0x0002019a,
469 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
470 "Bad track index number", 0, 0);
471 return 0;
472 }
473
474 /* >>> if track size known : check index */;
475
476 t->index[index_number] = relative_lba;
477 if (index_number >= t->indices)
478 t->indices = index_number + 1;
479 return 1;
480 }
481
482 /* ts B20103 API */
483 int burn_track_clear_indice(struct burn_track *t, int flag)
484 {
485 int i;
486
487 for (i = 0; i < 100; i++)
488 t->index[i] = 0x7fffffff;
489 t->indices = 0;
490 return 1;
491 }
492
493 /* ts B20110 API */
494 int burn_track_set_pregap_size(struct burn_track *t, int size, int flag)
495 {
496 t->pregap2 = (size >= 0);
497 t->pregap2_size = size;
498 return 1;
499 }
500
501 /* ts B20111 API */
502 int burn_track_set_postgap_size(struct burn_track *t, int size, int flag)
503 {
504 t->postgap = (size >= 0);
505 t->postgap_size = size;
506 return 1;
507 }
508
509 /* ts B20119: outsourced from burn_track_get_sectors()
510 @param flag bit0= do not add post-gap
511 */
512 int burn_track_get_sectors_2(struct burn_track *t, int flag)
513 {
514 /* ts A70125 : was int */
515 off_t size = 0;
516 int sectors, seclen;
517
518 seclen = burn_sector_length(t->mode);
519
520 if (t->cdxa_conversion == 1)
521 /* ts A90911 : will read blocks of 2056 bytes and write 2048 */
522 seclen += 8;
523
524 if (t->source != NULL) { /* ts A80808 : mending sigsegv */
525 size = t->offset + t->source->get_size(t->source) + t->tail;
526 /* ts B20119 : adding post-gap */
527 if (t->postgap && !(flag & 1))
528 size += t->postgap_size;
529 } else if(t->entry != NULL) {
530 /* ts A80808 : all burn_toc_entry of track starts should now
531 have (extensions_valid & 1), even those from CD.
532 */
533 if (t->entry->extensions_valid & 1)
534 size = ((off_t) t->entry->track_blocks) * (off_t) 2048;
535 }
536 sectors = size / seclen;
537 if (size % seclen)
538 sectors++;
539 return sectors;
540 }
541
542
543 int burn_track_get_sectors(struct burn_track *t)
544 {
545 return burn_track_get_sectors_2(t, 0);
546 }
547
548 /* ts A70125 */
549 int burn_track_set_sectors(struct burn_track *t, int sectors)
550 {
551 off_t size, seclen;
552 int ret;
553
554 seclen = burn_sector_length(t->mode);
555 size = seclen * (off_t) sectors - (off_t) t->offset - (off_t) t->tail;
556 if (size < 0)
557 return 0;
558 ret = t->source->set_size(t->source, size);
559 t->open_ended = (t->source->get_size(t->source) <= 0);
560 return ret;
561 }
562
563
564 /* ts A70218 , API since A70328 */
565 int burn_track_set_size(struct burn_track *t, off_t size)
566 {
567 if (t->source == NULL)
568 return 0;
569 if (t->source->set_size == NULL)
570 return 0;
571 t->open_ended = (size <= 0);
572 return t->source->set_size(t->source, size);
573 }
574
575
576 /* ts A70213 */
577 int burn_track_set_fillup(struct burn_track *t, int fill_up_media)
578 {
579 t->fill_up_media = fill_up_media;
580 if (fill_up_media)
581 t->open_ended = 0;
582 return 1;
583 }
584
585
586 /* ts A70213 */
587 /**
588 @param flag bit0= force new size even if existing track size is larger
589 */
590 int burn_track_apply_fillup(struct burn_track *t, off_t max_size, int flag)
591 {
592 int max_sectors, ret = 2;
593 char msg[80];
594
595 if (t->fill_up_media <= 0)
596 return 2;
597 max_sectors = max_size / 2048;
598 if (burn_track_get_sectors(t) < max_sectors || (flag & 1)) {
599 sprintf(msg, "Setting total track size to %ds (payload %ds)\n",
600 max_sectors & 0x7fffffff,
601 (int) ((t->source->get_size(t->source) / 2048)
602 & 0x7fffffff));
603 libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
604 LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
605 msg, 0, 0);
606 ret = burn_track_set_sectors(t, max_sectors);
607 t->open_ended = 0;
608 }
609 return ret;
610 }
611
612
613 /* ts A61031 */
614 int burn_track_is_open_ended(struct burn_track *t)
615 {
616 return !!t->open_ended;
617 }
618
619
620 /* ts A70218 : API */
621 int burn_track_set_default_size(struct burn_track *t, off_t size)
622 {
623 t->default_size = size;
624 return 1;
625 }
626
627
628 /* ts A70218 */
629 off_t burn_track_get_default_size(struct burn_track *t)
630 {
631 return t->default_size;
632 }
633
634
635 /* ts A61101 : API function */
636 int burn_track_get_counters(struct burn_track *t,
637 off_t *read_bytes, off_t *written_bytes)
638 {
639 /*
640 fprintf(stderr, "libburn_experimental: sizeof(off_t)=%d\n",
641 sizeof(off_t));
642 */
643 *read_bytes = t->sourcecount;
644 *written_bytes = t->writecount;
645 return 1;
646 }
647
648 /* ts A61031 */
649 int burn_track_is_data_done(struct burn_track *t)
650 {
651 return !!t->track_data_done;
652 }
653
654 int burn_track_get_shortage(struct burn_track *t)
655 {
656 int size;
657 int seclen;
658
659 seclen = burn_sector_length(t->mode);
660 size = t->offset + t->source->get_size(t->source) + t->tail;
661 if (size % seclen)
662 return seclen - size % seclen;
663 return 0;
664 }
665
666 int burn_session_get_sectors(struct burn_session *s)
667 {
668 int sectors = 0, i;
669
670 for (i = 0; i < s->tracks; i++)
671 sectors += burn_track_get_sectors(s->track[i]);
672 return sectors;
673 }
674
675
676 int burn_disc_get_sectors(struct burn_disc *d)
677 {
678 int sectors = 0, i;
679
680 for (i = 0; i < d->sessions; i++)
681 sectors += burn_session_get_sectors(d->session[i]);
682 return sectors;
683 }
684
685 void burn_track_get_entry(struct burn_track *t, struct burn_toc_entry *entry)
686 {
687 if (t->entry == NULL)
688 memset(entry, 0, sizeof(struct burn_toc_entry));
689 else
690 memcpy(entry, t->entry, sizeof(struct burn_toc_entry));
691 }
692
693 void burn_session_get_leadout_entry(struct burn_session *s,
694 struct burn_toc_entry *entry)
695 {
696 if (s->leadout_entry == NULL)
697 memset(entry, 0, sizeof(struct burn_toc_entry));
698 else
699 memcpy(entry, s->leadout_entry, sizeof(struct burn_toc_entry));
700 }
701
702 struct burn_session **burn_disc_get_sessions(struct burn_disc *d, int *num)
703 {
704
705 #ifdef Libburn_disc_with_incomplete_sessioN
706
707 *num = d->sessions - d->incomplete_sessions;
708
709 #else
710
711 *num = d->sessions;
712
713 #endif
714
715
716 return d->session;
717 }
718
719
720 /* ts B30112 : API */
721 int burn_disc_get_incomplete_sessions(struct burn_disc *d)
722 {
723 #ifdef Libburn_disc_with_incomplete_sessioN
724
725 return d->incomplete_sessions;
726
727 #else
728
729 return 0;
730
731 #endif
732 }
733
734
735 struct burn_track **burn_session_get_tracks(struct burn_session *s, int *num)
736 {
737 *num = s->tracks;
738 return s->track;
739 }
740
741 int burn_track_get_mode(struct burn_track *track)
742 {
743 return track->mode;
744 }
745
746 int burn_session_get_hidefirst(struct burn_session *session)
747 {
748 return session->hidefirst;
749 }
750
751
752 /* ts A80808 : Enhance CD toc to DVD toc */
753 int burn_disc_cd_toc_extensions(struct burn_drive *drive, int flag)
754 {
755 int sidx= 0, tidx= 0, ret, track_offset, alloc_len = 34;
756 struct burn_toc_entry *entry, *prev_entry= NULL;
757 struct burn_disc *d;
758 /* ts A81126 : ticket 146 : There was a SIGSEGV in here */
759 char *msg_data = NULL, *msg;
760 struct buffer *buf = NULL;
761
762 d = drive->disc;
763 BURN_ALLOC_MEM(msg_data, char, 321);
764 BURN_ALLOC_MEM(buf, struct buffer, 1);
765 strcpy(msg_data,
766 "Damaged CD table-of-content detected and truncated.");
767 strcat(msg_data, " In burn_disc_cd_toc_extensions: ");
768 msg = msg_data + strlen(msg_data);
769 if (d->session == NULL) {
770 strcpy(msg, "d->session == NULL");
771 goto failure;
772 }
773 if (d->sessions <= 0) {
774 ret = 1;
775 goto ex;
776 }
777
778 for (sidx = 0; sidx < d->sessions; sidx++) {
779 track_offset = burn_session_get_start_tno(d->session[sidx], 0);
780 if (track_offset <= 0)
781 track_offset = 1;
782 if (d->session[sidx] == NULL) {
783 sprintf(msg, "d->session[%d of %d] == NULL",
784 sidx, d->sessions);
785 goto failure;
786 }
787 if (d->session[sidx]->track == NULL) {
788 sprintf(msg, "d->session[%d of %d]->track == NULL",
789 sidx, d->sessions);
790 goto failure;
791 }
792 if (d->session[sidx]->leadout_entry == NULL) {
793 sprintf(msg,
794 " Session %d of %d: Leadout entry missing.",
795 sidx, d->sessions);
796 goto failure;
797 }
798 for (tidx = 0; tidx < d->session[sidx]->tracks + 1; tidx++) {
799 if (tidx < d->session[sidx]->tracks) {
800 if (d->session[sidx]->track[tidx] == NULL) {
801 sprintf(msg,
802 "d->session[%d of %d]->track[%d of %d] == NULL",
803 sidx, d->sessions, tidx, d->session[sidx]->tracks);
804 goto failure;
805 }
806 entry = d->session[sidx]->track[tidx]->entry;
807 if (entry == NULL) {
808 sprintf(msg,
809 "session %d of %d, track %d of %d, entry == NULL",
810 sidx, d->sessions, tidx,
811 d->session[sidx]->tracks);
812 goto failure;
813 }
814 } else
815 entry = d->session[sidx]->leadout_entry;
816 entry->session_msb = 0;
817 entry->point_msb = 0;
818 entry->start_lba = burn_msf_to_lba(entry->pmin,
819 entry->psec, entry->pframe);
820 if (tidx > 0) {
821 prev_entry->track_blocks =
822 entry->start_lba
823 - prev_entry->start_lba;
824
825 /* The drive might know size restrictions
826 like pre-gaps
827 */
828 ret = mmc_read_track_info(drive,
829 tidx - 1 + track_offset, buf,
830 alloc_len);
831 if (ret > 0) {
832 ret = mmc_four_char_to_int(
833 buf->data + 24);
834 if (ret < prev_entry->track_blocks &&
835 ((!drive->current_is_cd_profile) ||
836 ret < prev_entry->track_blocks - 2))
837 prev_entry->track_blocks = ret;
838 }
839 prev_entry->extensions_valid |= 1;
840 }
841 if (tidx == d->session[sidx]->tracks) {
842 entry->session_msb = 0;
843 entry->point_msb = 0;
844 entry->track_blocks = 0;
845 entry->extensions_valid |= 1;
846 }
847 prev_entry = entry;
848 }
849 }
850 {ret = 1; goto ex;}
851 failure:
852 libdax_msgs_submit(libdax_messenger, -1, 0x0002015f,
853 LIBDAX_MSGS_SEV_MISHAP, LIBDAX_MSGS_PRIO_HIGH, msg_data, 0, 0);
854 d->sessions= sidx;
855 ret = 0;
856 ex:;
857 BURN_FREE_MEM(buf);
858 BURN_FREE_MEM(msg_data);
859 return ret;
860 }
861
862
863 /* ts B20107 API */
864 int burn_session_set_start_tno(struct burn_session *session, int tno, int flag)
865 {
866 if (tno < 1 || tno > 99) {
867 libdax_msgs_submit(libdax_messenger, -1, 0x0002019b,
868 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
869 "CD start track number exceeds range of 1 to 99",
870 0, 0);
871 return 0;
872 }
873 if (tno + session->tracks - 1 > 99) {
874 libdax_msgs_submit(libdax_messenger, -1, 0x0002019b,
875 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
876 "CD track number exceeds 99", 0, 0);
877 return 0;
878 }
879 session->firsttrack = tno;
880 return 1;
881 }
882
883
884 /* ts B20108 API */
885 int burn_session_get_start_tno(struct burn_session *session, int flag)
886 {
887 return (int) session->firsttrack;
888 }
889
890
891 struct burn_cdtext *burn_cdtext_create(void)
892 {
893 struct burn_cdtext *t;
894 int i;
895
896 t = burn_alloc_mem(sizeof(struct burn_cdtext), 1, 0);
897 if (t == NULL)
898 return NULL;
899 for(i = 0; i < Libburn_pack_num_typeS; i ++) {
900 t->payload[i] = NULL;
901 t->length[i] = 0;
902 }
903 return t;
904 }
905
906
907 void burn_cdtext_free(struct burn_cdtext **cdtext)
908 {
909 struct burn_cdtext *t;
910 int i;
911
912 t = *cdtext;
913 if (t == NULL)
914 return;
915 for (i = 0; i < Libburn_pack_num_typeS; i++)
916 if (t->payload[i] != NULL)
917 free(t->payload[i]);
918 free(t);
919 }
920
921
922 static int burn_cdtext_name_to_type(char *pack_type_name)
923 {
924 int i, j;
925 static char *pack_type_names[] = {
926 Libburn_pack_type_nameS
927 };
928
929 for (i = 0; i < Libburn_pack_num_typeS; i++) {
930 if (pack_type_names[i][0] == 0)
931 continue;
932 for (j = 0; pack_type_names[i][j]; j++)
933 if (pack_type_names[i][j] != pack_type_name[j] &&
934 tolower(pack_type_names[i][j]) !=
935 pack_type_name[j])
936 break;
937 if (pack_type_names[i][j] == 0)
938 return Libburn_pack_type_basE + i;
939 }
940 return -1;
941 }
942
943
944 /* @param flag bit0= double byte characters
945 */
946 static int burn_cdtext_set(struct burn_cdtext **cdtext,
947 int pack_type, char *pack_type_name,
948 unsigned char *payload, int length, int flag)
949 {
950 int i;
951 struct burn_cdtext *t;
952
953 if (pack_type_name != NULL)
954 if (pack_type_name[0])
955 pack_type = burn_cdtext_name_to_type(pack_type_name);
956 if (pack_type < Libburn_pack_type_basE ||
957 pack_type >= Libburn_pack_type_basE + Libburn_pack_num_typeS) {
958 libdax_msgs_submit(libdax_messenger, -1, 0x0002018c,
959 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
960 "CD-TEXT pack type out of range", 0, 0);
961 return 0;
962 }
963 t = *cdtext;
964 if (t == NULL) {
965 *cdtext = t = burn_cdtext_create();
966 if (t == NULL)
967 return -1;
968 }
969 i = pack_type - Libburn_pack_type_basE;
970 if (t->payload[i] != NULL)
971 free(t->payload[i]);
972 t->payload[i] = burn_alloc_mem((size_t) length, 1, 0);
973 if (t->payload[i] == NULL)
974 return -1;
975 memcpy(t->payload[i], payload, length);
976 t->length[i] = length;
977 t->flags = (t->flags & ~(1 << i)) | (flag & (1 << i));
978 return 1;
979 }
980
981
982 /* @return 1=single byte char , 2= double byte char , <=0 error */
983 static int burn_cdtext_get(struct burn_cdtext *t, int pack_type,
984 char *pack_type_name,
985 unsigned char **payload, int *length, int flag)
986 {
987 if (pack_type_name != NULL)
988 if (pack_type_name[0])
989 pack_type = burn_cdtext_name_to_type(pack_type_name);
990 if (pack_type < Libburn_pack_type_basE ||
991 pack_type >= Libburn_pack_type_basE + Libburn_pack_num_typeS) {
992 libdax_msgs_submit(libdax_messenger, -1, 0x0002018c,
993 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
994 "CD-TEXT pack type out of range", 0, 0);
995 return 0;
996 }
997 *payload = t->payload[pack_type - Libburn_pack_type_basE];
998 *length = t->length[pack_type - Libburn_pack_type_basE];
999 return 1 + ((t->flags >> (pack_type - Libburn_pack_type_basE)) & 1);
1000 }
1001
1002
1003 static int burn_cdtext_check_blockno(int block)
1004 {
1005 if (block < 0 || block > 7) {
1006 libdax_msgs_submit(libdax_messenger, -1, 0x0002018d,
1007 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
1008 "CD-TEXT block number out of range", 0, 0);
1009 return 0;
1010 }
1011 return 1;
1012 }
1013
1014
1015 /* ts B11206 API */
1016 /* @param flag bit0= double byte characters
1017 */
1018 int burn_track_set_cdtext(struct burn_track *t, int block,
1019 int pack_type, char *pack_type_name,
1020 unsigned char *payload, int length, int flag)
1021 {
1022 int ret;
1023
1024 if (burn_cdtext_check_blockno(block) <= 0)
1025 return 0;
1026 ret = burn_cdtext_set(&(t->cdtext[block]), pack_type, pack_type_name,
1027 payload, length, flag & 1);
1028 return ret;
1029 }
1030
1031
1032 /* ts B11206 API */
1033 /* @return 1=single byte char , 2= double byte char , <=0 error */
1034 int burn_track_get_cdtext(struct burn_track *t, int block,
1035 int pack_type, char *pack_type_name,
1036 unsigned char **payload, int *length, int flag)
1037 {
1038 int ret;
1039
1040 if (burn_cdtext_check_blockno(block) <= 0)
1041 return 0;
1042 if (t->cdtext[block] == NULL) {
1043 *payload = NULL;
1044 *length = 0;
1045 return 1;
1046 }
1047 ret = burn_cdtext_get(t->cdtext[block], pack_type, pack_type_name,
1048 payload, length, 0);
1049 return ret;
1050 }
1051
1052
1053 /* ts B11206 API */
1054 int burn_track_dispose_cdtext(struct burn_track *t, int block)
1055 {
1056 int i;
1057
1058 if (block == -1) {
1059 for (i= 0; i < 8; i++)
1060 burn_cdtext_free(&(t->cdtext[i]));
1061 return 1;
1062 }
1063 if (burn_cdtext_check_blockno(block) <= 0)
1064 return 0;
1065 burn_cdtext_free(&(t->cdtext[0]));
1066 return 1;
1067 }
1068
1069
1070 /* ts B11206 API */
1071 /* @param flag bit0= double byte characters
1072 */
1073 int burn_session_set_cdtext(struct burn_session *s, int block,
1074 int pack_type, char *pack_type_name,
1075 unsigned char *payload, int length, int flag)
1076 {
1077 int ret;
1078
1079 if (burn_cdtext_check_blockno(block) <= 0)
1080 return 0;
1081 ret = burn_cdtext_set(&(s->cdtext[block]), pack_type, pack_type_name,
1082 payload, length, flag & 1);
1083 return ret;
1084 }
1085
1086
1087 /* ts B11206 API */
1088 /* @return 1=single byte char , 2= double byte char , <=0 error */
1089 int burn_session_get_cdtext(struct burn_session *s, int block,
1090 int pack_type, char *pack_type_name,
1091 unsigned char **payload, int *length, int flag)
1092 {
1093 int ret;
1094
1095 if (burn_cdtext_check_blockno(block) <= 0)
1096 return 0;
1097
1098 if (s->cdtext[block] == NULL) {
1099 *payload = NULL;
1100 *length = 0;
1101 return 1;
1102 }
1103 ret = burn_cdtext_get(s->cdtext[block], pack_type, pack_type_name,
1104 payload, length, 0);
1105 return ret;
1106 }
1107
1108
1109 /* ts B11206 API */
1110 int burn_session_set_cdtext_par(struct burn_session *s,
1111 int char_codes[8], int copyrights[8],
1112 int block_languages[8], int flag)
1113 {
1114 int i;
1115
1116 for (i = 0; i < 8; i++) {
1117 if (char_codes[i] >= 0 && char_codes[i] <= 255)
1118 s->cdtext_char_code[i] = char_codes[i];
1119 if (copyrights[i] >= 0 && copyrights[i] <= 255)
1120 s->cdtext_copyright[i] = copyrights[i];
1121 if (block_languages[i] >= 0 && block_languages[i] <= 255)
1122 s->cdtext_language[i] = block_languages[i];
1123 }
1124 return 1;
1125 }
1126
1127
1128 /* ts B11206 API */
1129 int burn_session_get_cdtext_par(struct burn_session *s,
1130 int char_codes[8], int copyrights[8],
1131 int block_languages[8], int flag)
1132 {
1133 int i;
1134
1135 for (i = 0; i < 8; i++) {
1136 char_codes[i] = s->cdtext_char_code[i];
1137 copyrights[i] = s->cdtext_copyright[i];
1138 block_languages[i]= s->cdtext_language[i];
1139 }
1140 return 1;
1141 }
1142
1143
1144 /* ts B11206 API */
1145 int burn_session_dispose_cdtext(struct burn_session *s, int block)
1146 {
1147 int i;
1148
1149 if (block == -1) {
1150 for (i= 0; i < 8; i++) {
1151 burn_session_dispose_cdtext(s, i);
1152 s->cdtext_char_code[i] = 0x01; /* 7 bit ASCII */
1153 s->cdtext_copyright[i] = 0;
1154 s->cdtext_language[i] = 0;
1155 }
1156 return 1;
1157 }
1158 if (burn_cdtext_check_blockno(block) <= 0)
1159 return 0;
1160 burn_cdtext_free(&(s->cdtext[block]));
1161 s->cdtext_language[block] = 0x09; /* english */
1162 return 1;
1163 }
1164
1165
1166 /* --------------------- Reading CDRWIN cue sheet files ----------------- */
1167
1168
1169 struct burn_cue_file_cursor {
1170 char *cdtextfile;
1171 char *source_file;
1172 off_t source_size;
1173 struct burn_source *file_source;
1174 int fifo_size;
1175 struct burn_source *fifo;
1176 int swap_audio_bytes;
1177 int no_cdtext;
1178 int no_catalog_isrc;
1179 int start_track_no;
1180 struct burn_source *offst_source;
1181 int current_file_ba;
1182 int current_index_ba;
1183 struct burn_track *prev_track;
1184 int prev_file_ba;
1185 int prev_block_size;
1186 struct burn_track *track;
1187 int track_no;
1188 int track_current_index;
1189 int track_has_source;
1190 int block_size;
1191 int block_size_locked;
1192 int track_mode;
1193 int flags;
1194 };
1195
1196
1197 static int cue_crs_new(struct burn_cue_file_cursor **reply, int flag)
1198 {
1199 int ret;
1200 struct burn_cue_file_cursor *crs;
1201
1202 BURN_ALLOC_MEM(crs, struct burn_cue_file_cursor, 1);
1203 crs->cdtextfile = NULL;
1204 crs->source_file = NULL;
1205 crs->source_size = -1;
1206 crs->file_source = NULL;
1207 crs->fifo_size = 0;
1208 crs->fifo = NULL;
1209 crs->swap_audio_bytes = 0;
1210 crs->no_cdtext = 0;
1211 crs->no_catalog_isrc = 0;
1212 crs->start_track_no = 1;
1213 crs->offst_source = NULL;
1214 crs->current_file_ba = -1000000000;
1215 crs->current_index_ba = -1000000000;
1216 crs->prev_track = NULL;
1217 crs->prev_file_ba = -1000000000;
1218 crs->prev_block_size = 0;
1219 crs->track = NULL;
1220 crs->track_no = 0;
1221 crs->track_current_index = -1;
1222 crs->track_has_source = 0;
1223 crs->block_size = 0;
1224 crs->block_size_locked = 0;
1225 crs->track_mode = 0;
1226 crs->flags = 0;
1227
1228 *reply = crs;
1229 ret = 1;
1230 ex:;
1231 return ret;
1232 }
1233
1234
1235 static int cue_crs_destroy(struct burn_cue_file_cursor **victim, int flag)
1236 {
1237 struct burn_cue_file_cursor *crs;
1238
1239 if (*victim == NULL)
1240 return 2;
1241 crs = *victim;
1242 if (crs->cdtextfile != NULL)
1243 free(crs->cdtextfile);
1244 if (crs->source_file != NULL)
1245 free(crs->source_file);
1246 if (crs->file_source != NULL)
1247 burn_source_free(crs->file_source);
1248 if (crs->fifo != NULL)
1249 burn_source_free(crs->fifo);
1250 if (crs->offst_source != NULL)
1251 burn_source_free(crs->offst_source);
1252 if (crs->prev_track != NULL)
1253 burn_track_free(crs->prev_track);
1254 if (crs->track != NULL)
1255 burn_track_free(crs->track);
1256 BURN_FREE_MEM(crs);
1257 *victim = NULL;
1258 return 1;
1259 }
1260
1261
1262 static char *cue_unquote_text(char *text, int flag)
1263 {
1264 char *ept, *spt;
1265
1266 spt = text;
1267 for (ept = text + strlen(text); ept > text; ept--)
1268 if (*(ept - 1) != 32 && *(ept - 1) != 9)
1269 break;
1270 if (text[0] == '"') {
1271 spt = text + 1;
1272 if (ept > spt)
1273 if (*(ept - 1) == '"')
1274 ept--;
1275 }
1276 *ept = 0;
1277 return spt;
1278 }
1279
1280
1281 /* @param flag bit0= insist in having a track object
1282 bit1= remove quotation marks if present
1283 */
1284 static int cue_set_cdtext(struct burn_session *session,
1285 struct burn_track *track, int pack_type, char *text,
1286 struct burn_cue_file_cursor *crs, int flag)
1287 {
1288 int ret;
1289 char *payload;
1290
1291 if (crs->no_cdtext == 1) {
1292 libdax_msgs_submit(libdax_messenger, -1, 0x00020195,
1293 LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
1294 "In cue sheet file: Being set to ignore all CD-TEXT aspects",
1295 0, 0);
1296 crs->no_cdtext = 2;
1297 }
1298 if (crs->no_cdtext)
1299 return 2;
1300 if ((flag & 1) && track == NULL) {
1301 libdax_msgs_submit(libdax_messenger, -1, 0x00020192,
1302 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
1303 "Track attribute set before first track in cue sheet file",
1304 0, 0);
1305 ret = 0; goto ex;
1306 }
1307 if (flag & 2)
1308 payload = cue_unquote_text(text, 0);
1309 else
1310 payload = text;
1311 if (track != NULL) {
1312 ret = burn_track_set_cdtext(track, 0, pack_type, "",
1313 (unsigned char *) payload,
1314 strlen(payload) + 1, 0);
1315 } else {
1316 ret = burn_session_set_cdtext(session, 0, pack_type, "",
1317 (unsigned char *) payload,
1318 strlen(payload) + 1, 0);
1319 }
1320 ex:;
1321 return ret;
1322 }
1323
1324
1325 static int cue_attach_track(struct burn_session *session,
1326 struct burn_cue_file_cursor *crs, int flag)
1327 {
1328 int ret;
1329
1330 if (crs->track == NULL)
1331 return 2;
1332
1333 if (!crs->track_has_source) {
1334 libdax_msgs_submit(libdax_messenger, -1, 0x00020194,
1335 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
1336 "In cue sheet file: TRACK without INDEX 01", 0, 0);
1337 return 0;
1338 }
1339 if (crs->track_current_index < 1) {
1340 libdax_msgs_submit(libdax_messenger, -1, 0x00020192,
1341 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
1342 "No INDEX 01 defined for last TRACK in cue sheet file",
1343 0, 0);
1344 return 0;
1345 }
1346 if (session->tracks == 0) {
1347 crs->start_track_no = crs->track_no;
1348 ret = burn_session_set_start_tno(session, crs->track_no, 0);
1349 if (ret <= 0)
1350 return ret;
1351 }
1352 if (session->tracks + crs->start_track_no - 1 > 99) {
1353 libdax_msgs_submit(libdax_messenger, -1, 0x0002019b,
1354 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
1355 "CD track number exceeds 99",
1356 0, 0);
1357 return 0;
1358 }
1359 ret = burn_session_add_track(session, crs->track, BURN_POS_END);
1360 if (ret <= 0)
1361 return ret;
1362 if (crs->prev_track != NULL)
1363 burn_track_free(crs->prev_track); /* release reference */
1364 crs->prev_track = crs->track;
1365 crs->prev_file_ba = crs->current_file_ba;
1366 crs->prev_block_size = crs->block_size;
1367 crs->track = NULL;
1368 crs->track_current_index = -1;
1369 crs->track_has_source = 0;
1370 crs->current_file_ba = -1;
1371 crs->current_index_ba = -1;
1372 if (!crs->block_size_locked)
1373 crs->block_size = 0;
1374 return 1;
1375 }
1376
1377
1378 /* @param flag bit0= do not alter the content of *payload
1379 do not change *payload
1380 */
1381 static int cue_read_number(char **payload, int *number, int flag)
1382 {
1383 int ret, at_end = 0;
1384 char *apt, *msg = NULL;
1385
1386 for(apt = *payload; *apt != 0 && *apt != 32 && *apt != 9; apt++);
1387 if (*apt == 0)
1388 at_end = 1;
1389 else if (!(flag & 1))
1390 *apt = 0;
1391 ret = sscanf(*payload, "%d", number);
1392 if (ret != 1) {
1393 BURN_ALLOC_MEM(msg, char, 4096);
1394 sprintf(msg,
1395 "Unsuitable number in cue sheet file: '%.4000s'",
1396 *payload);
1397 libdax_msgs_submit(libdax_messenger, -1, 0x00020194,
1398 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
1399 burn_printify(msg), 0, 0);
1400 ret = 0; goto ex;
1401 }
1402 /* Find start of next argument */
1403 if (!at_end)
1404 for (apt++; *apt == 32 || *apt == 9; apt++);
1405 if (!(flag & 1))
1406 *payload = apt;
1407
1408 ret = 1;
1409 ex:
1410 BURN_FREE_MEM(msg);
1411 return ret;
1412 }
1413
1414
1415 /* @param flag bit0-7: desired type : 0=any , 1=.wav
1416 */
1417 static int cue_open_audioxtr(char *path, struct burn_cue_file_cursor *crs,
1418 int *fd, int flag)
1419 {
1420 struct libdax_audioxtr *xtr= NULL;
1421 char *fmt, *fmt_info;
1422 int ret, num_channels, sample_rate, bits_per_sample, msb_first;
1423 char *msg = NULL;
1424
1425 BURN_ALLOC_MEM(msg, char, 4096);
1426
1427 ret= libdax_audioxtr_new(&xtr, path, 0);
1428 if (ret <= 0)
1429 goto ex;
1430 libdax_audioxtr_get_id(xtr, &fmt, &fmt_info, &num_channels,
1431 &sample_rate, &bits_per_sample, &msb_first, 0);
1432 if ((flag & 255) == 1) {
1433 if (strcmp(fmt, ".wav") != 0) {
1434 sprintf(msg,
1435 "In cue sheet: Not recognized as WAVE : FILE '%.4000s'",
1436 path);
1437 libdax_msgs_submit(libdax_messenger, -1, 0x00020193,
1438 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
1439 burn_printify(msg), 0, 0);
1440 ret = 0; goto ex;
1441 }
1442 }
1443 ret = libdax_audioxtr_get_size(xtr, &(crs->source_size), 0);
1444 if (ret <= 0) {
1445 sprintf(msg,
1446 "In cue sheet: Cannot get payload size of FILE '%.4000s'",
1447 path);
1448 libdax_msgs_submit(libdax_messenger, -1, 0x00020193,
1449 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
1450 burn_printify(msg), 0, 0);
1451 ret = 0; goto ex;
1452 }
1453 ret = libdax_audioxtr_detach_fd(xtr, fd, 0);
1454 if (ret <= 0) {
1455 sprintf(msg,
1456 "In cue sheet: Cannot represent payload as plain fd: FILE '%.4000s'",
1457 path);
1458 libdax_msgs_submit(libdax_messenger, -1, 0x00020193,
1459 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
1460 burn_printify(msg), 0, 0);
1461 ret = 0; goto ex;
1462 }
1463 crs->swap_audio_bytes = (msb_first == 1);
1464
1465 ret = 1;
1466 ex:
1467 if (xtr != NULL)
1468 libdax_audioxtr_destroy(&xtr, 0);
1469 BURN_FREE_MEM(msg);
1470 return ret;
1471 }
1472
1473
1474 /* @param flag bit0-7: desired type : 0=any , 1=.wav
1475 bit8= open by libdax_audioxtr functions
1476
1477 */
1478 static int cue_create_file_source(char *path, struct burn_cue_file_cursor *crs,
1479 int flag)
1480 {
1481 int fd, ret;
1482 char *msg = NULL;
1483
1484 BURN_ALLOC_MEM(msg, char, 4096);
1485
1486 if (flag & 256) {
1487 ret = cue_open_audioxtr(path, crs, &fd, flag & 255);
1488 if (ret <= 0)
1489 goto ex;
1490 } else {
1491 fd = open(path, O_RDONLY | O_BINARY);
1492 if (fd == -1) {
1493 sprintf(msg,
1494 "In cue sheet: Cannot open FILE '%.4000s'",
1495 path);
1496 libdax_msgs_submit(libdax_messenger, -1, 0x00020193,
1497 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
1498 burn_printify(msg), errno, 0);
1499 ret = 0; goto ex;
1500 }
1501 }
1502 crs->file_source = burn_fd_source_new(fd, -1, crs->source_size);
1503 if (crs->file_source == NULL) {
1504 ret = -1; goto ex;
1505 }
1506
1507 ret = 1;
1508 ex:;
1509 BURN_FREE_MEM(msg);
1510 return ret;
1511 }
1512
1513
1514 static int cue_read_timepoint_lba(char *apt, char *purpose, int *file_ba,
1515 int flag)
1516 {
1517 int ret, minute, second, frame;
1518 char *msg = NULL, msf[3], *msf_pt;
1519
1520 BURN_ALLOC_MEM(msg, char, 4096);
1521 if (strlen(apt) < 8) {
1522 no_time_point:;
1523 sprintf(msg,
1524 "Inappropriate cue sheet file %s '%.4000s'",
1525 purpose, apt);
1526 libdax_msgs_submit(libdax_messenger, -1, 0x00020194,
1527 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
1528 burn_printify(msg), 0, 0);
1529 ret = 0; goto ex;
1530 }
1531 if (apt[2] != ':' || apt[5] != ':' ||
1532 (apt[8] != 0 && apt[8] != 32 && apt[8] != 9))
1533 goto no_time_point;
1534 msf[2] = 0;
1535 msf_pt = msf;
1536 strncpy(msf, apt, 2);
1537 ret = cue_read_number(&msf_pt, &minute, 1);
1538 if (ret <= 0)
1539 goto ex;
1540 strncpy(msf, apt + 3, 2);
1541 ret = cue_read_number(&msf_pt, &second, 1);
1542 if (ret <= 0)
1543 goto ex;
1544 strncpy(msf, apt + 6, 2);
1545 ret = cue_read_number(&msf_pt, &frame, 1);
1546 if (ret <= 0)
1547 goto ex;
1548
1549 *file_ba = ((minute * 60) + second ) * 75 + frame;
1550 ret = 1;
1551 ex:;
1552 BURN_FREE_MEM(msg);
1553 return ret;
1554 }
1555
1556 static int cue_check_for_track(struct burn_cue_file_cursor *crs, char *cmd,
1557 int flag)
1558 {
1559 int ret;
1560 char *msg = NULL;
1561
1562 if (crs->track == NULL) {
1563 BURN_ALLOC_MEM(msg, char, 4096);
1564 sprintf(msg, "In cue sheet file: %s found before TRACK",
1565 cmd);
1566 libdax_msgs_submit(libdax_messenger, -1, 0x00020192,
1567 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
1568 msg, 0, 0);
1569 ret = 0; goto ex;
1570 }
1571 ret = 1;
1572 ex:;
1573 BURN_FREE_MEM(msg);
1574 return ret;
1575 }
1576
1577
1578 static int cue_interpret_line(struct burn_session *session, char *line,
1579 struct burn_cue_file_cursor *crs, int flag)
1580 {
1581 int ret, mode, index_no, file_ba, chunks;
1582 int block_size, step, audio_xtr = 0;
1583 off_t size;
1584 char *cmd, *apt, *msg = NULL, *cpt, *filetype;
1585 struct burn_source *src, *inp_src;
1586 enum burn_source_status source_status;
1587 struct stat stbuf;
1588
1589 BURN_ALLOC_MEM(msg, char, 4096);
1590
1591 if (line[0] == 0 || line[0] == '#') {
1592 ret = 1; goto ex;
1593 }
1594
1595 for (cmd = line; *cmd == 32 || *cmd == 9; cmd++);
1596 for(apt = cmd; *apt != 0 && *apt != 32 && *apt != 9; apt++);
1597 if (*apt != 0) {
1598 *apt = 0;
1599 for (apt++; *apt == 32 || *apt == 9; apt++);
1600 }
1601
1602 if (strcmp(cmd, "ARRANGER") == 0) {
1603 ret = cue_set_cdtext(session, crs->track, 0x84, apt, crs, 2);
1604 if (ret <= 0)
1605 goto ex;
1606
1607 } else if (strcmp(cmd, "CATALOG") == 0) {
1608 for (cpt = apt; (cpt - apt) < 13 && *cpt == (*cpt & 0x7f);
1609 cpt++);
1610 if ((cpt - apt) < 13) {
1611 libdax_msgs_submit(libdax_messenger, -1, 0x00020194,
1612 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
1613 "In cue sheet file: Inappropriate content of CATALOG",
1614 0, 0);
1615 ret = 0; goto ex;
1616 }
1617 ret = cue_set_cdtext(session, NULL, 0x8e, apt, crs, 0);
1618 if (ret <= 0)
1619 goto ex;
1620 if (!crs->no_catalog_isrc) {
1621 memcpy(session->mediacatalog, apt, 13);
1622 session->mediacatalog[13] = 0;
1623 }
1624
1625 } else if (strcmp(cmd, "CDTEXTFILE") == 0) {
1626 if (crs->no_cdtext) {
1627 ret = 1; goto ex;
1628 }
1629 apt = cue_unquote_text(apt, 0);
1630 if (crs->cdtextfile != NULL)
1631 free(crs->cdtextfile);
1632 crs->cdtextfile = strdup(apt);
1633 if (crs->cdtextfile == NULL) {
1634 out_of_mem:;
1635 libdax_msgs_submit(libdax_messenger, -1, 0x00000003,
1636 LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
1637 "Out of virtual memory", 0, 0);
1638 ret = -1; goto ex;
1639 }
1640
1641 } else if (strcmp(cmd, "COMPOSER") == 0) {
1642 ret = cue_set_cdtext(session, crs->track, 0x83, apt, crs, 2);
1643 if (ret <= 0)
1644 goto ex;
1645
1646 } else if (strcmp(cmd, "FILE") == 0) {
1647 if (crs->file_source != NULL) {
1648 libdax_msgs_submit(libdax_messenger, -1, 0x00020192,
1649 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
1650 "In cue sheet file: Multiple occurrences of FILE",
1651 0, 0);
1652 ret = 0; goto ex;
1653 }
1654 /* Obtain type */
1655 for (cpt = apt + (strlen(apt) - 1);
1656 cpt > apt && (*cpt == 32 || *cpt == 9); cpt--);
1657 cpt[1] = 0;
1658 for (; cpt > apt && *cpt != 32 && *cpt != 9; cpt--);
1659 if (cpt <= apt) {
1660 libdax_msgs_submit(libdax_messenger, -1, 0x00020194,
1661 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
1662 "In cue sheet file: FILE without type word",
1663 0, 0);
1664 ret = 0; goto ex;
1665 }
1666 *cpt = 0;
1667 filetype = cpt + 1;
1668 if (strcmp(filetype, "BINARY") == 0) {
1669 crs->swap_audio_bytes = 0;
1670 } else if (strcmp(filetype, "MOTOROLA") == 0) {
1671 crs->swap_audio_bytes = 1;
1672 } else if (strcmp(filetype, "WAVE") == 0) {
1673 audio_xtr = 0x101;
1674 } else {
1675 sprintf(msg,
1676 "In cue sheet file: Unsupported FILE type '%.4000s'",
1677 filetype);
1678 libdax_msgs_submit(libdax_messenger, -1, 0x00020197,
1679 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
1680 burn_printify(msg), 0, 0);
1681 ret = 0; goto ex;
1682 }
1683
1684 apt = cue_unquote_text(apt, 0);
1685 if (*apt == 0)
1686 ret = -1;
1687 else
1688 ret = stat(apt, &stbuf);
1689 if (ret == -1) {
1690 not_usable_file:;
1691 sprintf(msg,
1692 "In cue sheet file: Unusable FILE '%.4000s'",
1693 apt);
1694 libdax_msgs_submit(libdax_messenger, -1, 0x00020194,
1695 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
1696 burn_printify(msg), 0, 0);
1697 ret = 0; goto ex;
1698 }
1699 if (!S_ISREG(stbuf.st_mode))
1700 goto not_usable_file;
1701 crs->source_size = stbuf.st_size;
1702 if (crs->source_file != NULL)
1703 free(crs->source_file);
1704 crs->source_file = strdup(apt);
1705 if (crs->source_file == NULL)
1706 goto out_of_mem;
1707 ret = cue_create_file_source(apt, crs, audio_xtr);
1708 if (ret <= 0)
1709 goto ex;
1710
1711 } else if (strcmp(cmd, "FLAGS") == 0) {
1712 ret = cue_check_for_track(crs, cmd, 0);
1713 if (ret <= 0)
1714 goto ex;
1715 while (*apt) {
1716 if (strncmp(apt, "DCP", 3) == 0) {
1717 crs->track_mode |= BURN_COPY;
1718 step = 3;
1719 } else if (strncmp(apt, "4CH", 3) == 0) {
1720 crs->track_mode |= BURN_4CH;
1721 step = 3;
1722 } else if (strncmp(apt, "PRE", 3) == 0) {
1723 crs->track_mode |= BURN_PREEMPHASIS;
1724 step = 3;
1725 } else if (strncmp(apt, "SCMS", 4) == 0) {
1726 crs->track_mode |= BURN_SCMS;
1727 step = 4;
1728 } else {
1729 bad_flags:;
1730 for (cpt = apt;
1731 *cpt != 32 && *cpt != 9 && *cpt != 0; cpt++);
1732 *cpt = 0;
1733 sprintf(msg,
1734 "In cue sheet file: Unknown FLAGS option '%.4000s'",
1735 apt);
1736 libdax_msgs_submit(libdax_messenger, -1,
1737 0x00020194,
1738 LIBDAX_MSGS_SEV_FAILURE,
1739 LIBDAX_MSGS_PRIO_HIGH,
1740 burn_printify(msg), 0, 0);
1741 ret = 0; goto ex;
1742 }
1743
1744 /* Look for start of next word */
1745 if (apt[step] != 0 && apt[step] != 32 &&
1746 apt[step] != 9)
1747 goto bad_flags;
1748 for (apt += step; *apt == 32 || *apt == 9; apt++);
1749 }
1750 burn_track_define_data(crs->track, 0, 0, 1, crs->track_mode);
1751
1752 } else if (strcmp(cmd, "INDEX") == 0) {
1753 ret = cue_check_for_track(crs, cmd, 0);
1754 if (ret <= 0)
1755 goto ex;
1756 ret = cue_read_number(&apt, &index_no, 0);
1757 if (ret <= 0)
1758 goto ex;
1759 ret = cue_read_timepoint_lba(apt, "index time point",
1760 &file_ba, 0);
1761 if (ret <= 0)
1762 goto ex;
1763 if (file_ba < crs->prev_file_ba) {
1764 overlapping_ba:;
1765 libdax_msgs_submit(libdax_messenger, -1, 0x00020192,
1766 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
1767 "Backward INDEX address in cue sheet file",
1768 0, 0);
1769 ret = 0; goto ex;
1770 }
1771 if (file_ba < crs->current_index_ba)
1772 goto overlapping_ba;
1773 if (crs->prev_track != NULL && crs->track_current_index < 0) {
1774 size = (file_ba - crs->prev_file_ba) *
1775 crs->prev_block_size;
1776 if (size <= 0)
1777 goto overlapping_ba;
1778 burn_track_set_size(crs->prev_track, size);
1779 }
1780 if (crs->track_current_index + 1 != index_no &&
1781 !(crs->track_current_index < 0 && index_no <= 1)) {
1782 libdax_msgs_submit(libdax_messenger, -1, 0x00020192,
1783 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
1784 "Unacceptable INDEX number in cue sheet file",
1785 0, 0);
1786 ret = 0; goto ex;
1787 }
1788 crs->track_current_index = index_no;
1789
1790 if (crs->current_file_ba < 0)
1791 crs->current_file_ba = file_ba;
1792 crs->current_index_ba = file_ba;
1793
1794 /* Set index address relative to track source start */
1795 ret = burn_track_set_index(crs->track, index_no,
1796 file_ba - crs->current_file_ba, 0);
1797 if (ret <= 0)
1798 goto ex;
1799
1800 if (crs->track_has_source) {
1801 ret = 1; goto ex;
1802 }
1803
1804 if (crs->block_size_locked && crs->fifo == NULL &&
1805 crs->fifo_size > 0) {
1806 /* Now that the block size is known from TRACK:
1807 Create fifo and use it for creating the offset
1808 sources. This will fixate the block size to one
1809 common value.
1810 */
1811 chunks = crs->fifo_size / crs->block_size +
1812 !!(crs->fifo_size % crs->block_size);
1813 if (chunks < 4)
1814 chunks = 4;
1815 crs->fifo = burn_fifo_source_new(crs->file_source,
1816 crs->block_size, chunks, 0);
1817 if (crs->fifo == NULL) {
1818 ret = -1; goto ex;
1819 }
1820 }
1821 if (crs->fifo != NULL)
1822 inp_src = crs->fifo;
1823 else
1824 inp_src = crs->file_source;
1825 src = burn_offst_source_new(inp_src, crs->offst_source,
1826 (off_t) (file_ba * crs->block_size), (off_t) 0, 1);
1827 if (src == NULL)
1828 goto out_of_mem;
1829
1830 /* >>> Alternative to above fifo creation:
1831 Create a fifo for each track track.
1832 This will be necessary if mixed-mode sessions get supporded.
1833 */;
1834
1835 source_status = burn_track_set_source(crs->track, src);
1836 if (source_status != BURN_SOURCE_OK) {
1837 ret = -1; goto ex;
1838 }
1839
1840 /* Switch current source in crs */
1841 if (crs->offst_source != NULL)
1842 burn_source_free(crs->offst_source);
1843 crs->offst_source = src;
1844 crs->track_has_source = 1;
1845
1846 } else if (strcmp(cmd, "ISRC") == 0) {
1847 ret = cue_check_for_track(crs, cmd, 0);
1848 if (ret <= 0)
1849 goto ex;
1850 ret = cue_set_cdtext(session, crs->track, 0x8e, apt, crs,
1851 1 | 2);
1852 if (ret <= 0)
1853 goto ex;
1854 if (!crs->no_catalog_isrc) {
1855 ret = burn_track_set_isrc_string(crs->track, apt, 0);
1856 if (ret <= 0)
1857 goto ex;
1858 }
1859
1860 } else if (strcmp(cmd, "MESSAGE") == 0) {
1861 ret = cue_set_cdtext(session, crs->track, 0x85, apt, crs, 2);
1862 if (ret <= 0)
1863 goto ex;
1864
1865 } else if (strcmp(cmd, "PERFORMER") == 0) {
1866 ret = cue_set_cdtext(session, crs->track, 0x81, apt, crs, 2);
1867 if (ret <= 0)
1868 goto ex;
1869
1870 } else if (strcmp(cmd, "POSTGAP") == 0) {
1871 ret = cue_check_for_track(crs, cmd, 0);
1872 if (ret <= 0)
1873 goto ex;
1874 ret = cue_read_timepoint_lba(apt, "post-gap duration",
1875 &file_ba, 0);
1876 if (ret <= 0)
1877 goto ex;
1878 ret = burn_track_set_postgap_size(crs->track, file_ba, 0);
1879 if (ret <= 0)
1880 goto ex;
1881
1882 } else if (strcmp(cmd, "PREGAP") == 0) {
1883 ret = cue_check_for_track(crs, cmd, 0);
1884 if (ret <= 0)
1885 goto ex;
1886 ret = cue_read_timepoint_lba(apt, "pre-gap duration",
1887 &file_ba, 0);
1888 if (ret <= 0)
1889 goto ex;
1890 ret = burn_track_set_pregap_size(crs->track, file_ba, 0);
1891 if (ret <= 0)
1892 goto ex;
1893
1894 } else if (strcmp(cmd, "REM") == 0) {
1895 ;
1896
1897 } else if (strcmp(cmd, "SONGWRITER") == 0) {
1898 ret = cue_set_cdtext(session, crs->track, 0x82, apt, crs, 2);
1899 if (ret <= 0)
1900 goto ex;
1901
1902 } else if (strcmp(cmd, "TITLE") == 0) {
1903 ret = cue_set_cdtext(session, crs->track, 0x80, apt, crs, 2);
1904 if (ret <= 0)
1905 goto ex;
1906
1907 } else if (strcmp(cmd, "TRACK") == 0) {
1908 if (crs->file_source == NULL) {
1909 libdax_msgs_submit(libdax_messenger, -1, 0x00020192,
1910 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
1911 "No FILE defined before TRACK in cue sheet file",
1912 0, 0);
1913 ret = 0; goto ex;
1914 }
1915 /* Attach previous track to session */
1916 ret = cue_attach_track(session, crs, 0);
1917 if (ret <= 0)
1918 goto ex;
1919 /* Create new track */;
1920 ret = cue_read_number(&apt, &(crs->track_no), 0);
1921 if (ret <= 0)
1922 goto ex;
1923 if (crs->track_no < 1 || crs->track_no > 99) {
1924 sprintf(msg,
1925 "Inappropriate cue sheet file track number %d",
1926 crs->track_no);
1927 libdax_msgs_submit(libdax_messenger, -1, 0x00020194,
1928 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
1929 burn_printify(msg), 0, 0);
1930 ret = 0; goto ex;
1931 }
1932 if (strcmp(apt, "AUDIO") == 0) {
1933 mode = BURN_AUDIO;
1934 block_size = 2352;
1935 } else if (strcmp(apt, "MODE1/2048") == 0) {
1936 mode = BURN_MODE1;
1937 block_size = 2048;
1938 } else {
1939 sprintf(msg,
1940 "Unsupported cue sheet file track datatype '%.4000s'",
1941 apt);
1942 libdax_msgs_submit(libdax_messenger, -1, 0x00020197,
1943 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
1944 burn_printify(msg), 0, 0);
1945 ret = 0; goto ex;
1946 }
1947 if (block_size != crs->block_size && crs->block_size > 0 &&
1948 crs->block_size_locked) {
1949 libdax_msgs_submit(libdax_messenger, -1, 0x00020197,
1950 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
1951 "In cue sheet file: Unsupported mix track block sizes",
1952 0, 0);
1953 ret = 0; goto ex;
1954 }
1955 crs->block_size = block_size;
1956
1957 crs->track = burn_track_create();
1958 if (crs->track == NULL)
1959 goto out_of_mem;
1960 crs->track_has_source = 0;
1961 crs->track_mode = mode;
1962 burn_track_define_data(crs->track, 0, 0, 1, mode);
1963 if (mode & BURN_AUDIO)
1964 burn_track_set_byte_swap(crs->track,
1965 !!crs->swap_audio_bytes);
1966
1967 } else {
1968 sprintf(msg, "Unknown cue sheet file command '%.4000s'", line);
1969 libdax_msgs_submit(libdax_messenger, -1, 0x00020191,
1970 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
1971 burn_printify(msg), 0, 0);
1972 ret = 0; goto ex;
1973 }
1974
1975 ret = 1;
1976 ex:;
1977 BURN_FREE_MEM(msg);
1978 return ret;
1979 }
1980
1981
1982 /* ts B11216 API */
1983 /* @param flag bit0= do not attach CD-TEXT information to session and tracks
1984 bit1= do not attach CATALOG to session or ISRC to track for
1985 writing to Q sub-channel
1986 */
1987 int burn_session_by_cue_file(struct burn_session *session, char *path,
1988 int fifo_size, struct burn_source **fifo,
1989 unsigned char **text_packs, int *num_packs, int flag)
1990 {
1991 int ret, num_tracks, i, pack_type, length, double_byte = 0;
1992 int line_counter = 0;
1993 struct burn_track **tracks;
1994 char *msg = NULL, *line = NULL;
1995 unsigned char *payload;
1996 struct stat stbuf;
1997 FILE *fp = NULL;
1998 struct burn_cue_file_cursor *crs = NULL;
1999
2000 static unsigned char dummy_cdtext[2] = {0, 0};
2001
2002 if (fifo != NULL)
2003 *fifo = NULL;
2004 if (text_packs != NULL)
2005 *text_packs = NULL;
2006 *num_packs = 0;
2007
2008 BURN_ALLOC_MEM(msg, char, 4096);
2009 BURN_ALLOC_MEM(line, char, 4096);
2010 ret = cue_crs_new(&crs, 0);
2011 if (ret <= 0)
2012 goto ex;
2013 crs->no_cdtext = (flag & 1);
2014 crs->no_catalog_isrc = !!(flag & 2);
2015 crs->fifo_size = fifo_size;
2016 crs->block_size_locked = 1; /* No mixed sessions for now */
2017
2018 tracks = burn_session_get_tracks(session, &num_tracks);
2019 if (num_tracks > 0) {
2020 sprintf(msg,
2021 "Cue sheet file reader called while session has already defined tracks");
2022 libdax_msgs_submit(libdax_messenger, -1, 0x00020196,
2023 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
2024 burn_printify(msg), 0, 0);
2025 ret = 0; goto ex;
2026 }
2027 if (stat(path, &stbuf) == -1) {
2028 cannot_open:;
2029 sprintf(msg, "Cannot open cue sheet file '%.4000s'",
2030 path);
2031 libdax_msgs_submit(libdax_messenger, -1, 0x00020193,
2032 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
2033 burn_printify(msg), errno, 0);
2034 ret = 0; goto ex;
2035 }
2036 if (!S_ISREG(stbuf.st_mode)) {
2037 sprintf(msg,
2038 "File is not of usable type: Cue sheet file '%.4000s'",
2039 path);
2040 libdax_msgs_submit(libdax_messenger, -1, 0x00020193,
2041 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
2042 burn_printify(msg), 0, 0);
2043 ret = 0; goto ex;
2044 }
2045
2046 fp = fopen(path, "rb");
2047 if (fp == NULL)
2048 goto cannot_open;
2049
2050 while (1) {
2051 if (burn_sfile_fgets(line, 4095, fp) == NULL) {
2052 if (!ferror(fp))
2053 break;
2054 sprintf(msg,
2055 "Cannot read all bytes from cue sheet file '%.4000s'",
2056 path);
2057 libdax_msgs_submit(libdax_messenger, -1, 0x00020193,
2058 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
2059 burn_printify(msg), 0, 0);
2060 ret = 0; goto ex;
2061 }
2062 line_counter++;
2063 ret = cue_interpret_line(session, line, crs, 0);
2064 if (ret <= 0) {
2065 sprintf(msg,
2066 "Cue sheet file '%.4000s': Reading aborted after line %d",
2067 path, line_counter);
2068 libdax_msgs_submit(libdax_messenger, -1, 0x00020199,
2069 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
2070 burn_printify(msg), 0, 0);
2071 goto ex;
2072 }
2073 }
2074
2075 /* Attach last track to session */
2076 if (crs->track != NULL) {
2077 /* Set track size up to end of file */
2078 if (crs->current_file_ba < 0 || crs->track_current_index < 1) {
2079 libdax_msgs_submit(libdax_messenger, -1, 0x00020192,
2080 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
2081 "No INDEX 01 defined for last TRACK in cue sheet file",
2082 0, 0);
2083 ret = 0; goto ex;
2084 }
2085 if (crs->current_file_ba * crs->block_size >=
2086 crs->source_size) {
2087 libdax_msgs_submit(libdax_messenger, -1, 0x00020194,
2088 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
2089 "TRACK start time point exceeds size of FILE from cue sheet file",
2090 0, 0);
2091 ret = 0; goto ex;
2092 }
2093 ret = burn_track_set_size(crs->track, crs->source_size -
2094 (off_t) (crs->current_file_ba * crs->block_size));
2095 if (ret <= 0)
2096 goto ex;
2097
2098 ret = cue_attach_track(session, crs, 0);
2099 if (ret <= 0)
2100 goto ex;
2101 }
2102 if (crs->cdtextfile != NULL) {
2103 if (text_packs == NULL) {
2104
2105 /* >>> Warn of ignored text packs */;
2106
2107 } else {
2108 ret = burn_cdtext_from_packfile(crs->cdtextfile,
2109 text_packs, num_packs, 0);
2110 if (ret <= 0)
2111 goto ex;
2112 }
2113 }
2114
2115 /* Check which tracks have data of pack types where session has not */
2116 tracks = burn_session_get_tracks(session, &num_tracks);
2117 for (pack_type = 0x80; pack_type < 0x8f; pack_type++) {
2118 if (pack_type > 0x86 && pack_type != 0x8e)
2119 continue;
2120 ret = burn_session_get_cdtext(session, 0, pack_type, "",
2121 &payload, &length, 0);
2122 if (ret <= 0)
2123 goto ex;
2124 if (payload != NULL)
2125 continue;
2126 for (i = 0; i < num_tracks; i++) {
2127 ret = burn_track_get_cdtext(tracks[i], 0, pack_type,
2128 "", &payload, &length, 0);
2129 if (ret <= 0)
2130 goto ex;
2131 double_byte = (ret > 1);
2132 if (payload != NULL)
2133 break;
2134 }
2135 if (i < num_tracks) {
2136 ret = burn_session_set_cdtext(session, 0, pack_type,
2137 "", dummy_cdtext, 1 + double_byte,
2138 double_byte);
2139 if (ret <= 0)
2140 goto ex;
2141 }
2142 }
2143 ret = 1;
2144 ex:
2145 if (ret <= 0) {
2146 tracks = burn_session_get_tracks(session, &num_tracks);
2147 for (i = 0; i < num_tracks; i++)
2148 burn_track_free(tracks[i]);
2149 if(text_packs != NULL) {
2150 if(*text_packs != NULL)
2151 free(*text_packs);
2152 *text_packs = NULL;
2153 *num_packs = 0;
2154 }
2155 } else {
2156 if (fifo != NULL) {
2157 *fifo = crs->fifo;
2158 crs->fifo = NULL;
2159 }
2160 }
2161 cue_crs_destroy(&crs, 0);
2162 BURN_FREE_MEM(line);
2163 BURN_FREE_MEM(msg);
2164 if (fp != NULL)
2165 fclose(fp);
2166 return ret;
2167 }
2168