1 /*
2 io.c
3 All the functions that interact with hardware and subprocesses
4 and file IO.
5 28.3.99 tn
6 */
7
8 #ifdef HAVE_CONFIG_H
9 # include <config.h>
10 #endif
11
12 #include "largefile.h"
13 #include "gettext.h"
14
15 #include <stdio.h>
16 #include <string.h>
17 #include <strings.h>
18 #include <stdlib.h>
19 #include <sys/stat.h>
20 #include <fcntl.h>
21 #include <unistd.h>
22 #include <sys/socket.h>
23 #include <sys/types.h>
24 #include <sys/wait.h>
25 #include <signal.h>
26 #include <time.h>
27 #if defined(linux) || defined(__FreeBSD__)
28 # include <sys/soundcard.h>
29 # include <sys/ioctl.h>
30 #endif
31 #if defined(sun) || defined(__OpenBSD__)
32 # include <sys/ioctl.h>
33 # include <sys/audioio.h>
34 #endif
35 #ifdef aix
36 #include <sys/audio.h>
37 #endif
38 #ifdef hpux
39 # ifndef hpux_alib
40 # include <sys/audio.h>
41 # endif
42 #endif
43 #if defined(__sgi)
44 #include <dmedia/audio.h>
45 #endif
46
47 #if ENABLE_NLS
48 # define _(String) gettext (String)
49 # define N_(String) gettext_noop (String)
50 #else
51 # define _(String) (String)
52 # define N_(String) (String)
53 #endif
54 #define GTK_ENABLE_BROKEN
55
56 #include <gtk/gtk.h>
57 #include <gdk/gdk.h>
58 #include <glib.h>
59 #include "xcdrdata.h"
60 #include "xcdroast.h"
61 #include "main.h"
62
63 writerreader_devices_t **writerreaderdevs;
64 gchar **alt_scsidevices;
65 cd_info_t cdinfo;
66 track_info_t **trackinfo;
67 writer_driver_t **drivers;
68 writer_driver_t **blankmodes;
69 write_track_param_t writeparams;
70 gchar xcdroast_version_loaded[MAXLINE];
71 gint read_done;
72 gint read_abort_mark;
73
74 static gint scsicount;
75 static gint busnr;
76 static gint tocstate;
77 static gint tocnr;
78 static gint drvcount;
79 static gint dfrun;
80 static gint readcdda_callback;
81 static gint readcdda_callback2;
82 static gint readcdda_callback3;
83 static gint read_output_ctrl;
84 static gint read_tracknr;
85 static gchar readtrack_info_string[1024];
86 static gfloat pct_so_far, pct_this_track;
87 static pid_t mkisofs_pid;
88 static pid_t readcdda_pid, readcdda_pid2;
89 static gint readcd_startsector, readcd_endsector;
90 static gint readerr_count;
91 static gint matchnr;
92 static gint cddb_in;
93 static gchar cdinfo_cddb_title_bak[MAXLINE];
94 static gint cd_is_still_the_same;
95 static gint cdrecord_stdin, cdrecord_reload;
96 static gint delete_count, delete_start, delete_all;
97 static gint msinfo_nr1, msinfo_nr2;
98 static gint cdrtimer, count_mmaperror, checkmedium_found;
99 static time_t cdrcmdtimer;
100 static GtkWidget *getcdtoc_atapi_timeout_dialog;
101
102 extern gint debug;
103 extern gint dialog_done2, dialog_done, dialog_done3;
104 extern setup_data_t setupdata;
105 extern track_read_set_t trackreadset;
106 extern current_set_t curset;
107 extern gchar *system_platform;
108 extern GtkWidget *toplevel;
109 extern GtkWidget *viewmode_dialog;
110 extern GtkWidget *readtrack_info_label, *readtrack_textview;
111 extern GtkWidget *readtrack_pbar1, *readtrack_pbar2, *readtrack_pbar3;
112 extern GtkWidget *readtrack_pbar4, *readtrack_spd;
113 extern GtkWidget *readtrack_small_info, *readtrack_small_info2;
114 extern gchar hostname[MAXLINE];
115 extern gchar username[MAXLINE];
116 extern gchar sharedir[MAXLINE];
117 extern gchar configdir[MAXLINE];
118 extern gchar prefixdir[MAXLINE];
119 extern GtkWidget *cddb_info_label;
120 extern GtkCList *cddb_clist;
121 extern master_param_t masterparam;
122 extern gchar **charset_types;
123 extern gchar *master_fname1;
124 extern gchar *master_fname2;
125 extern GdkFont *fixedfont;
126 extern gint support_ontheflyaudio;
127
128 static void verify_readcd_err(gpointer pid, gint source, GdkInputCondition cond);
129 static void read_write_out(gpointer data, gint source, GdkInputCondition cond);
130 static gint getdevicecap(gchar *dev, gint *readmax, gint *cdrmax, gint *dvdmax, gint *iscdr, gint *isdvdrom, gint *isdvdr);
131 static gint check_medium_loaded(gint devnr);
132 static gint get_cdrecord_toc(gint devnr);
133 static void remove_tmp_writetracks_tocfile(gchar *tocfile);
134 static void edit_xinf_for_cd_text2(gchar *infname, gchar *title, gchar *artist, gchar *cdtitle, gchar *cdartist);
135 static pid_t full_dpl_pipe3(gint *out, gint *in, gint *err, gchar *cmd,
136 gint use_socketpair);
137
138
139 /* convert device-type-names back to numeric */
140 /* -1 means unknown */
141
get_scsi_type(gchar * type)142 static gint get_scsi_type(gchar *type) {
143
144 if (strcmp(type,"Disk") == 0) {
145 return 0;
146 }
147 if (strcmp(type,"Tape") == 0) {
148 return 1;
149 }
150 if (strcmp(type,"Printer") == 0) {
151 return 2;
152 }
153 if (strcmp(type,"Processor") == 0) {
154 return 3;
155 }
156 if (strcmp(type,"WORM") == 0) {
157 return 4;
158 }
159 if (strcmp(type,"CD-ROM") == 0) {
160 return 5;
161 }
162 if (strcmp(type,"Scanner") == 0) {
163 return 6;
164 }
165 if (strcmp(type,"Optical Storage") == 0) {
166 return 7;
167 }
168 if (strcmp(type,"Juke Box") == 0) {
169 return 8;
170 }
171 if (strcmp(type,"Communication") == 0) {
172 return 9;
173 }
174
175 return -1;
176 }
177
178
179 /* convert the scsi-type-number back to string */
180
181 #if 0
182 static void get_scsi_type_string(gchar *str, gint type, gint removeable) {
183
184 switch(type) {
185 case 0:
186 if (removeable == 0) {
187 strcpy(str,_("Disk"));
188 } else {
189 strcpy(str,_("Removable Disk"));
190 }
191 break;
192 case 1:
193 strcpy(str,_("Tape"));
194 break;
195 case 2:
196 strcpy(str,_("Printer"));
197 break;
198 case 3:
199 strcpy(str,_("Processor/Scanner"));
200 break;
201 case 4:
202 strcpy(str,_("WORM"));
203 break;
204 case 5:
205 strcpy(str,_("CD-ROM"));
206 break;
207 case 6:
208 strcpy(str,_("Scanner"));
209 break;
210 case 7:
211 strcpy(str,_("Optical Storage"));
212 break;
213 case 8:
214 strcpy(str,_("Juke Box"));
215 break;
216 case 9:
217 strcpy(str,_("Communication"));
218 break;
219 default:
220 strcpy(str,"");
221 break;
222 }
223 }
224 #endif
225
226
get_cur_audioread_speed()227 static gint get_cur_audioread_speed() {
228 gint i;
229 i = get_writerreaderdevs_index(curset.reader_devnr);
230 return (writerreaderdevs[i]->audioread_speed);
231 }
232
get_cur_audioread_overlap()233 static gint get_cur_audioread_overlap() {
234 gint i;
235 i = get_writerreaderdevs_index(curset.reader_devnr);
236 return (writerreaderdevs[i]->audioread_overlap);
237 }
238
get_cur_audioread_sectorburst()239 static gint get_cur_audioread_sectorburst() {
240 gint i;
241 i = get_writerreaderdevs_index(curset.reader_devnr);
242 return (writerreaderdevs[i]->audioread_sectorburst);
243 }
244
get_cur_audioread_useparanoia()245 static gint get_cur_audioread_useparanoia() {
246 gint i;
247 i = get_writerreaderdevs_index(curset.reader_devnr);
248 return (writerreaderdevs[i]->audioread_useparanoia);
249 }
250
get_cur_audioread_paranoiaretries()251 static gint get_cur_audioread_paranoiaretries() {
252 gint i;
253 i = get_writerreaderdevs_index(curset.reader_devnr);
254 return (writerreaderdevs[i]->audioread_paranoiaretries);
255 }
256
get_cur_writer_speed()257 static gint get_cur_writer_speed() {
258 gint i;
259 i = get_writerreaderdevs_index(curset.writer_devnr);
260 return (writerreaderdevs[i]->writer_speed);
261 }
262
get_cur_writer_fifo()263 static gint get_cur_writer_fifo() {
264 gint i;
265 i = get_writerreaderdevs_index(curset.writer_devnr);
266 return (writerreaderdevs[i]->writer_fifo);
267 }
268
get_cur_writemode()269 static gint get_cur_writemode() {
270 gint i;
271 i = get_writerreaderdevs_index(curset.writer_devnr);
272 return (writerreaderdevs[i]->writer_mode);
273 }
274
get_cur_writer_drvmode()275 static gint get_cur_writer_drvmode() {
276 gint i;
277 i = get_writerreaderdevs_index(curset.writer_devnr);
278 return (writerreaderdevs[i]->writer_drvmode);
279 }
280
281
282 /* look in given string for "' '" and return index to it */
283 /* return -1 if not found */
284
look_for_scan_delimitor(gchar * str)285 static gint look_for_scan_delimitor(gchar *str) {
286 gint i;
287
288 for(i = 0; i < strlen(str)-2; i++) {
289
290 if (str[i] == '\'' && str[i+1] == ' ' && str[i+2] == '\'') {
291 return i;
292 }
293 }
294 return -1;
295 }
296
297
298 /* look in given string for "' " and return index to it */
299 /* return -1 if not found */
300
look_for_scan_delimitor2(gchar * str)301 static gint look_for_scan_delimitor2(gchar *str) {
302 gint i;
303
304 for(i = 0; i < strlen(str)-1; i++) {
305
306 if (str[i] == '\'' && str[i+1] == ' ') {
307 return i;
308 }
309 }
310 return -1;
311 }
312
313
314 /* interpret output of -scanbus and sort into memory structure */
315 /* if idx != -1 then we run in manual-device-mode */
316
parse_scan(gchar * line,gint idx,gint transport,scsi_devices_t ** scsidevices)317 static void parse_scan(gchar *line, gint idx, gint transport, scsi_devices_t **scsidevices) {
318 gchar tmp[MAXLINE];
319 gchar tmp2[MAXLINE];
320 gchar *p1, *p2;
321 gint s_id;
322 gchar s_vendor[9];
323 gchar s_model[17];
324 gchar s_rev[5];
325 gint s_removable;
326 gint s_type;
327 gint next;
328
329 /* skip header */
330 if (strncmp(line,"Cdrecord",8) == 0) {
331 return;
332 }
333 #if 0
334 if (strncmp(line,"devname",7) == 0 ) {
335 /* set current scsibus nr */
336 strcpy(tmp,line+7);
337 p1=strtok(tmp,":");
338 /* now tmp2 contains the current busnr as string */
339 devname = strdup(p1);
340 return;
341 }
342 #endif
343 if (strncmp(line,"scsibus",7) == 0 ) {
344 /* set current scsibus nr */
345 strcpy(tmp,line+7);
346 p1=strtok(tmp,":");
347 strcpy(tmp2,p1);
348 /* now tmp2 contains the current busnr as string */
349 busnr = atoi(tmp2);
350 return;
351 }
352
353
354 /* a line with an error message? */
355 /* get_spawn_path(CDRECORD,tmp); */
356 strcpy(tmp,"cdrecord: ");
357 if (strncmp(line, tmp, strlen(tmp)) == 0) {
358 return;
359 }
360
361 /* a line with device-info found (by checking for ")")*/
362 p1 = index(line,')');
363 if (p1 != NULL && !strstr(line,")\"") &&
364 (strstr(line,"\t") || line[0] == ' ')) {
365 strip_string(line);
366
367 /* get scsi-id */
368 p1=strtok(line,")");
369 if (!p1) return;
370
371 strcpy(tmp,p1);
372 strcpy(tmp2,p1);
373 /* look for last tab or last space in tmp and remove
374 everything before */
375 p1=rindex(tmp2,'\t');
376 p2=rindex(tmp2,' ');
377 if (p1 > p2) {
378 /* last interesting char was a tab - cut here */
379 if (p1 != NULL) {
380 strcpy(tmp,p1+1);
381 }
382 } else {
383 /* last interesting char was a space - cut here */
384 if (p2 != NULL) {
385 strcpy(tmp,p2+1);
386 }
387 }
388 s_id = atoi(tmp);
389
390 /* strip host-id from scsi-id-number */
391 s_id = s_id % 100;
392
393 p1=strtok(NULL,"'");
394 if (p1 == NULL) {
395 g_warning("cdrecord scanbus error: Try to remove all media from your CD-ROM drives before starting X-CD-Roast.\n");
396 return;
397 }
398
399 strcpy(tmp,p1);
400 strip_string(tmp);
401
402 if (*tmp == '*') {
403 /* no device found */
404 return;
405 }
406
407 if (*tmp == 'H') {
408 /* HOST ADAPTER found */
409 /* treat as no device for now */
410 return;
411 }
412
413 /* get full rest of line */
414 p1=strtok(NULL,"");
415 if (!p1) return;
416 strcpy(tmp,p1);
417
418 if (*tmp == '\'') {
419 /* empty device found? ignore */
420 return;
421 }
422
423 /* e.g. tmp=YAMAHA ' 'CRW8424S ' '1.0j' */
424 /* get vendor */
425 next = look_for_scan_delimitor(tmp);
426 if (next < 0) {
427 g_error("cdrecord -scanbus output syntax error\n");
428 }
429
430 strcpy(s_vendor," ");
431 if (next <= 8) {
432 strncpy(s_vendor,tmp,next);
433 } else {
434 /* strip if to long */
435 strncpy(s_vendor,tmp,8);
436 }
437 s_vendor[8] = '\0';
438
439 /* get model */
440 strcpy(tmp2,tmp+next+3);
441 strcpy(tmp,tmp2);
442 next = look_for_scan_delimitor(tmp);
443 if (next < 0) {
444 g_error("cdrecord -scanbus output syntax error\n");
445 }
446 strcpy(s_model," ");
447 if (next <= 16) {
448 strncpy(s_model,tmp,next);
449 } else {
450 strncpy(s_model,tmp,16);
451 }
452 s_model[16] = '\0';
453
454 /* get revision */
455 strcpy(tmp2,tmp+next+3);
456 strcpy(tmp,tmp2);
457 next = look_for_scan_delimitor2(tmp);
458 if (next < 0) {
459 g_error("cdrecord -scanbus output syntax error\n");
460 }
461 strcpy(s_rev," ");
462 if (next <= 4) {
463 strncpy(s_rev,tmp,next);
464 } else {
465 strncpy(s_rev,tmp,4);
466 }
467 s_rev[4] = '\0';
468
469 /* get type */
470 strcpy(tmp2,tmp+next+2);
471 strcpy(tmp,tmp2);
472 strip_string(tmp);
473
474 if (strncmp(tmp,"Removable",9) == 0) {
475 s_removable = 1;
476 strcpy(tmp2,tmp+10);
477 strcpy(tmp,tmp2);
478 } else {
479 s_removable = 0;
480 }
481
482 s_type = get_scsi_type(tmp);
483
484 /* allocate and fill structure */
485 scsidevices[scsicount]=g_new(scsi_devices_t,1);
486 if (idx == -1) {
487 /* autoscan mode */
488 scsidevices[scsicount]->devnr =
489 transport*1024+busnr*32+s_id;
490 scsidevices[scsicount]->alt_dev = -1;
491 } else {
492 /* manual mode */
493 scsidevices[scsicount]->devnr = idx;
494 scsidevices[scsicount]->alt_dev = idx;
495 }
496
497 scsidevices[scsicount]->sector_size = DATASECTORSIZE;
498 scsidevices[scsicount]->transport = transport;
499 scsidevices[scsicount]->bus = busnr;
500 scsidevices[scsicount]->id = s_id;
501 strcpy(scsidevices[scsicount]->vendor,s_vendor);
502 strcpy(scsidevices[scsicount]->model,s_model);
503 strcpy(scsidevices[scsicount]->rev,s_rev);
504 scsidevices[scsicount]->removable = s_removable;
505 scsidevices[scsicount]->type = s_type;
506
507 scsicount++;
508 if (scsicount >= MAXDEVICES) {
509 g_error("Error: More than %d devices scanned\n",MAXDEVICES);
510 }
511 }
512 }
513
514
515 /* print memory-structure with scsidevices (debug purposes) */
516 #if 0
517 static void print_scsidevices(scsi_devices_t **scsidevices) {
518 gint count;
519
520 dodebug(2,"------ cdrecord scsidevices-structure -----\n");
521 count = 0;
522 while(scsidevices[count] != NULL) {
523 dodebug(2,"devnr=%d %d:%d %s %s %s %d,%d (alt: %d) (ssize: %d)\n",
524 scsidevices[count]->devnr,
525 scsidevices[count]->bus,
526 scsidevices[count]->id,
527 scsidevices[count]->vendor,
528 scsidevices[count]->model,
529 scsidevices[count]->rev,
530 scsidevices[count]->removable,
531 scsidevices[count]->type,
532 scsidevices[count]->alt_dev,
533 scsidevices[count]->sector_size);
534
535 count++;
536 }
537 }
538 #endif
539
print_writerreaderdevs()540 static void print_writerreaderdevs() {
541 gint count;
542
543 dodebug(2,"------ cdrecord writerreaderdevs-structure -----\n");
544 count = 0;
545 while(writerreaderdevs[count] != NULL) {
546 dodebug(2, "devnr=%d (%s) [%s %s %s] (ssize: %d)\n",
547 writerreaderdevs[count]->devnr,
548 writerreaderdevs[count]->devicestr,
549 writerreaderdevs[count]->vendor,
550 writerreaderdevs[count]->model,
551 writerreaderdevs[count]->rev,
552 writerreaderdevs[count]->sector_size);
553 dodebug(2, " readmax: %d, cdrmax: %d, dvdmax: %d, is_cdrwriter: %d, is_dvdreader: %d, is_dvdwriter: %d\n",
554 writerreaderdevs[count]->writer_readmaxspeed,
555 writerreaderdevs[count]->writer_cdrmaxspeed,
556 writerreaderdevs[count]->writer_dvdmaxspeed,
557 writerreaderdevs[count]->is_cdrwriter,
558 writerreaderdevs[count]->is_dvdreader,
559 writerreaderdevs[count]->is_dvdwriter,
560 writerreaderdevs[count]->sector_size);
561 dodebug(2, " writer_flags: %s\n",
562 writerreaderdevs[count]->writer_flags);
563 dodebug(2, " writer_modes: %s\n",
564 writerreaderdevs[count]->writer_modes);
565
566 count++;
567 }
568 }
569
570
571 /* create a new writer/reader entry */
572
add_writerreader(scsi_devices_t * scsidev,gchar * transport,GtkWidget * txt)573 static gint add_writerreader(scsi_devices_t *scsidev, gchar *transport, GtkWidget *txt) {
574 gchar tmp[MAXLINE];
575 gchar tmp2[MAXLINE];
576 gchar drvflags[MAXLINE], drvmodes[MAXLINE];
577 gint readmax, cdrmax, dvdmax, iscdr, isdvdr, isdvdrom;
578 gint count;
579 gint mmap_error;
580 gint i;
581 static const gchar *writemodes[] = WRITE_MODES;
582
583 /* first search last entry of writerreader struct */
584 count = 0;
585 while(writerreaderdevs[count] != NULL) {
586 if (count == MAXDEVICES-1) {
587 return 0;
588 }
589 count++;
590 }
591
592 /* only add type WORM and CD-ROM types */
593 if (scsidev->type != 4 && scsidev->type != 5) {
594 return 0;
595 }
596
597 /* build device string */
598 if (scsidev->alt_dev == -1) {
599 g_snprintf(tmp,MAXLINE,"%s%d,%d,%d",
600 transport, scsidev->bus, scsidev->id, 0);
601 } else {
602 strncpy(tmp, transport, MAXLINE);
603 }
604
605 /* check if this device already exists */
606 if (get_writerreaderdevs_index_from_devstr(tmp) != -1) {
607 if (txt) {
608 g_snprintf(tmp2,MAXLINE,"([%s] %s %s %s)\n",
609 tmp, scsidev->vendor,
610 scsidev->model, scsidev->rev);
611 convert_for_gtk2_textwidget(tmp2);
612 gtk_text_insert(GTK_TEXT(txt), NULL, NULL, NULL, tmp2, strlen(tmp2));
613 wait_and_process_events();
614 }
615 return 0;
616 }
617
618 /* create a new entry */
619 writerreaderdevs[count]=g_new0(writerreader_devices_t,1);
620 writerreaderdevs[count]->devnr = scsidev->devnr;
621 writerreaderdevs[count]->devicestr = g_strdup(tmp);
622 strncpy(writerreaderdevs[count]->vendor, scsidev->vendor,9);
623 strncpy(writerreaderdevs[count]->model, scsidev->model,17);
624 strncpy(writerreaderdevs[count]->rev, scsidev->rev,5);
625 writerreaderdevs[count]->sector_size = scsidev->sector_size;
626
627 getmodesflags(tmp, drvflags, drvmodes);
628 writerreaderdevs[count]->writer_flags = g_strdup(drvflags);
629 writerreaderdevs[count]->writer_modes = g_strdup(drvmodes);
630
631 /* get more detailed information about this device */
632 mmap_error=getdevicecap(tmp, &readmax, &cdrmax, &dvdmax, &iscdr, &isdvdrom, &isdvdr);
633 writerreaderdevs[count]->writer_readmaxspeed = readmax;
634 writerreaderdevs[count]->writer_cdrmaxspeed = cdrmax;
635 writerreaderdevs[count]->writer_dvdmaxspeed = dvdmax;
636 writerreaderdevs[count]->is_cdrwriter = iscdr;
637 writerreaderdevs[count]->is_dvdreader = isdvdrom;
638 writerreaderdevs[count]->is_dvdwriter = isdvdr;
639
640
641 /* workaround for non-mcc drives */
642 if (writerreaderdevs[count]->is_cdrwriter == 0) {
643 /* not detected as writer, but got write modes? */
644 if (strlen(drvmodes) > 0) {
645 /* assume its really a writer then */
646 writerreaderdevs[count]->is_cdrwriter = 1;
647 }
648 }
649
650 /* set defaults for other fields */
651 writerreaderdevs[count]->writer_drvmode = -1;
652 writerreaderdevs[count]->writer_speed = cdrmax;
653 writerreaderdevs[count]->writer_fifo = 4096;
654
655 /* get the first supported mode for that writer */
656 i = 0;
657 while (writemodes[i]) {
658 if (writemode_supported(i, scsidev->devnr)) {
659 writerreaderdevs[count]->writer_mode = i;
660 break;
661 }
662 i++;
663 }
664
665 writerreaderdevs[count]->audioread_interface = 0;
666 writerreaderdevs[count]->audioread_speed = readmax;
667 writerreaderdevs[count]->audioread_overlap = 0;
668 writerreaderdevs[count]->audioread_sectorburst = 75;
669 writerreaderdevs[count]->audioread_useparanoia = 0;
670 writerreaderdevs[count]->audioread_paranoiaretries = 20;
671
672 /* add to dialog window */
673 if (txt) {
674 g_snprintf(tmp2,MAXLINE,"[%s] %s %s %s\n",
675 tmp, scsidev->vendor,
676 scsidev->model, scsidev->rev);
677 convert_for_gtk2_textwidget(tmp2);
678 gtk_text_insert(GTK_TEXT(txt), NULL, NULL, NULL, tmp2, strlen(tmp2));
679 wait_and_process_events();
680 }
681
682 return mmap_error;
683 }
684
685
686 /* does scan for a single device only */
687 /* return 1 when new device was found */
688
scanbus_single(gchar * dev,gint newdevnr,GtkWidget * txt)689 static gint scanbus_single(gchar *dev, gint newdevnr, GtkWidget *txt) {
690 gchar line[MAXLINE];
691 gchar tmp[MAXLINE];
692 gchar tmp2[MAXLINE];
693 FILE *fpin;
694 scsi_devices_t **scsidevices;
695 gint found;
696
697 scsidevices = g_new0(scsi_devices_t *, MAXDEVICES);
698 scsicount = 0;
699
700 get_wrap_path_cdrecord(line);
701
702 /* make sure we escape any critical chars in input */
703 strncpy(tmp2,dev,MAXLINE);
704 convert_escape(tmp2);
705
706 g_snprintf(tmp,MAXLINE," -scanbus dev= \"%s\" 2>&1",tmp2);
707 strcat(line,tmp);
708
709 dodebug(1, "calling: %s\n", line);
710 if ((fpin = popen(line,"r")) == NULL) {
711 g_error("popen error\n");
712 }
713
714 for (;;) {
715 if (fgets(line,MAXLINE,fpin) == NULL)
716 break;
717 dodebug(10,"scanbus: %s",line);
718 parse_scan(line, newdevnr, 0, scsidevices);
719 }
720
721 if (pclose(fpin) == -1) {
722 g_error("pclose error\n");
723 }
724
725 found = 0;
726 if (scsidevices[0]) {
727 add_writerreader(scsidevices[0], dev, txt);
728 g_free(scsidevices[0]);
729 found = 1;
730 }
731 g_free(scsidevices);
732
733 return found;
734 }
735
736
737 #if (defined(__MACH__) && defined(__APPLE__))
738
739 /* interpret output of -inq and sort into memory structure */
740 /* if idx != -1 then we run in manual-device-mode */
741
parse_inq(gchar * line,gint idx,scsi_devices_t ** scsidevices)742 static void parse_inq(gchar *line, gint idx, scsi_devices_t **scsidevices) {
743 gchar tmp[MAXLINE];
744 gchar tmp2[MAXLINE];
745 gchar *p;
746 gchar s_vendor[9];
747 gchar s_model[17];
748 gchar s_rev[5];
749 gint s_removable;
750 gint s_type;
751
752
753 if (strncmp("Device type",line,11) == 0) {
754 p = strtok(line,":");
755 if (p) {
756 p = strtok(NULL,"");
757 if (p) {
758 strcpy(tmp,p);
759 strip_string(tmp);
760 if (strncmp(tmp,"Removable",9) == 0) {
761 s_removable = 1;
762 strcpy(tmp2,tmp+10);
763 strcpy(tmp,tmp2);
764 } else {
765 s_removable = 0;
766 }
767
768 s_type = get_scsi_type(tmp);
769
770 /* allocate entry now */
771 scsidevices[scsicount]=g_new(scsi_devices_t,1);
772 scsidevices[scsicount]->sector_size = DATASECTORSIZE;
773 scsidevices[scsicount]->devnr = idx;
774 scsidevices[scsicount]->alt_dev = idx;
775 scsidevices[scsicount]->transport = 0;
776 scsidevices[scsicount]->bus = 0;
777 scsidevices[scsicount]->id = idx;
778 scsidevices[scsicount]->removable = s_removable;
779 scsidevices[scsicount]->type = s_type;
780 }
781 }
782 }
783
784 if (strncmp("Vendor_info",line,11) == 0) {
785 p = strtok(line,":");
786 if (p) {
787 p = strtok(NULL,"");
788 if (p) {
789 strcpy(tmp2,p);
790 extract_singlequoted(tmp2);
791
792 strcpy(s_vendor," ");
793 if (strlen(tmp2) <= 8) {
794 strncpy(s_vendor,tmp2,strlen(tmp2));
795 } else {
796 /* strip if to long */
797 strncpy(s_vendor,tmp2,8);
798 }
799 s_vendor[8] = '\0';
800
801 if (scsidevices[scsicount]) {
802 strcpy(scsidevices[scsicount]->vendor,s_vendor);
803 }
804 }
805 }
806 }
807
808 if (strncmp("Identifikation",line,14) == 0) {
809 p = strtok(line,":");
810 if (p) {
811 p = strtok(NULL,"");
812 if (p) {
813 strcpy(tmp2,p);
814 extract_singlequoted(tmp2);
815
816 strcpy(s_model," ");
817 if (strlen(tmp2) <= 16) {
818 strncpy(s_model,tmp2,strlen(tmp2));
819 } else {
820 strncpy(s_model,tmp2,16);
821 }
822 s_model[16] = '\0';
823
824 if (scsidevices[scsicount]) {
825 strcpy(scsidevices[scsicount]->model,s_model);
826 }
827 }
828 }
829 }
830
831 if (strncmp("Revision",line,8) == 0) {
832 p = strtok(line,":");
833 if (p) {
834 p = strtok(NULL,"");
835 if (p) {
836 strcpy(tmp2,p);
837 extract_singlequoted(tmp2);
838
839 strcpy(s_rev," ");
840 if (strlen(tmp2) <= 4) {
841 strncpy(s_rev,tmp2,strlen(tmp2));
842 } else {
843 strncpy(s_rev,tmp2,4);
844 }
845 s_rev[4] = '\0';
846
847 if (scsidevices[scsicount]) {
848 strcpy(scsidevices[scsicount]->rev,s_rev);
849 scsicount++;
850 }
851 }
852 }
853 }
854
855 if (scsicount >= MAXDEVICES) {
856 g_error("Error: More than %d devices scanned\n",MAXDEVICES);
857 }
858 }
859
860
861 /* does scan for a single device only via inq call (osX) */
862
scanbus_via_inq(gchar * dev,gint newdevnr,GtkWidget * txt)863 static gint scanbus_via_inq(gchar *dev, gint newdevnr, GtkWidget *txt) {
864 gchar line[MAXLINE];
865 gchar tmp[MAXLINE];
866 gchar tmp2[MAXLINE];
867 FILE *fpin;
868 scsi_devices_t **scsidevices;
869 gint found;
870
871 scsidevices = g_new0(scsi_devices_t *, MAXDEVICES);
872 scsicount = 0;
873
874 get_wrap_path_cdrecord(line);
875
876 /* make sure we escape any critical chars in input */
877 strncpy(tmp2,dev,MAXLINE);
878 convert_escape(tmp2);
879
880 g_snprintf(tmp,MAXLINE," -inq dev= \"%s\" 2>&1",tmp2);
881 strcat(line,tmp);
882
883 dodebug(1, "calling: %s\n", line);
884 if ((fpin = popen(line,"r")) == NULL) {
885 g_error("popen error\n");
886 }
887
888 for (;;) {
889 if (fgets(line,MAXLINE,fpin) == NULL)
890 break;
891 dodebug(10,"scanbus: %s",line);
892 parse_inq(line, newdevnr, scsidevices);
893 }
894
895 if (pclose(fpin) == -1) {
896 g_error("pclose error\n");
897 }
898
899 found = 0;
900 if (scsidevices[0]) {
901 add_writerreader(scsidevices[0], dev, txt);
902 g_free(scsidevices[0]);
903 found = 1;
904 }
905 g_free(scsidevices);
906
907 return found;
908 }
909
910 #endif
911
912 /* scanbus scsi */
913
scan_traditional(GtkWidget * txt)914 static void scan_traditional(GtkWidget *txt) {
915 gchar line[MAXLINE];
916 FILE *fpin;
917 gint count, errcount, ret;
918 scsi_devices_t **scsidevices;
919
920 scsidevices = g_new0(scsi_devices_t *, MAXDEVICES);
921 scsicount = 0;
922
923 /* traditional scanning first */
924 get_wrap_path_cdrecord(line);
925 strcat(line," -scanbus 2>&1");
926
927 dodebug(1, "calling: %s\n", line);
928 if ((fpin = popen(line,"r")) == NULL) {
929 g_error("popen error\n");
930 }
931
932 for (;;) {
933 if (fgets(line,MAXLINE,fpin) == NULL)
934 break;
935 dodebug(10,"scanbus: %s",line);
936 parse_scan(line, -1, 0, scsidevices);
937 }
938
939 if (pclose(fpin) == -1) {
940 g_error("pclose error\n");
941 }
942
943 /* add the found devices to the writerreader structure */
944 count = 0;
945 errcount = 0;
946 while(scsidevices[count] != NULL) {
947 errcount+=add_writerreader(scsidevices[count],"", txt);
948 g_free(scsidevices[count]);
949 count++;
950 }
951 g_free(scsidevices);
952
953 /* historic mmap error check */
954 if (errcount > 0) {
955 ret = show_dialog(ICO_WARN, _("Warning: The cdrtools binaries you have installed are\nnot compatible with your system. You will NOT be\nable to read or write CDs. Please read the FAQ\non www.xcdroast.org for more information."), T_ANYWAY, _("Exit"), NULL, 1);
956 if (ret == 1)
957 gtk_exit(1);
958 }
959 }
960
961
962 /* alternative transport method scanning */
963 /* valid transport choices for now: ATAPI USCSI REMOTE */
964
scan_other(gchar * transport,gint transid,GtkWidget * txt)965 static gint scan_other(gchar *transport, gint transid, GtkWidget *txt) {
966 gchar line[MAXLINE];
967 gchar tmp[MAXLINE];
968 FILE *fpin;
969 gint count;
970 scsi_devices_t **scsidevices;
971
972 scsidevices = g_new0(scsi_devices_t *, MAXDEVICES);
973 scsicount = 0;
974
975 get_wrap_path_cdrecord(line);
976 g_snprintf(tmp,MAXLINE," dev=%s -scanbus 2>&1", transport);
977 strcat(line, tmp);
978
979 dodebug(1, "calling: %s\n", line);
980 if ((fpin = popen(line,"r")) == NULL) {
981 g_error("popen error\n");
982 }
983
984 for (;;) {
985 if (fgets(line,MAXLINE,fpin) == NULL)
986 break;
987 dodebug(10,"scanbus (%s): %s", transport, line);
988 parse_scan(line, -1, transid, scsidevices);
989 }
990
991 if (pclose(fpin) == -1) {
992 g_error("pclose error\n");
993 }
994
995 /* add the found devices to the writerreader structure */
996 count = 0;
997 g_snprintf(tmp,MAXLINE,"%s:", transport);
998 while(scsidevices[count] != NULL) {
999 add_writerreader(scsidevices[count], tmp, txt);
1000 g_free(scsidevices[count]);
1001 count++;
1002 }
1003 g_free(scsidevices);
1004
1005 return count;
1006 }
1007
1008
1009 /* new scanbus version */
1010
scanbus_new(GtkWidget * txt,gint scanparam)1011 void scanbus_new(GtkWidget *txt, gint scanparam) {
1012 gchar tmp[MAXLINE];
1013 GdkFont *boldfont;
1014 gint doscanbus;
1015 gint i, devnr;
1016
1017 /* allocate memory */
1018 if (!writerreaderdevs) {
1019 writerreaderdevs = g_new0(writerreader_devices_t *, MAXDEVICES);
1020 }
1021
1022 boldfont = get_some_font(BOLDFONT);
1023 doscanbus = 1;
1024
1025 /* output status texts? */
1026 if (txt) {
1027 strncpy(tmp,_("Starting to scan for devices...\n"), MAXLINE);
1028 convert_for_gtk2_textwidget(tmp);
1029 gtk_text_insert(GTK_TEXT(txt), boldfont, NULL, NULL, tmp, strlen(tmp));
1030 wait_and_process_events();
1031 }
1032
1033 /* check if we have to do full scanbus, or only partial */
1034 if (alt_scsidevices[0] != NULL) {
1035 i = 0;
1036 while (alt_scsidevices[i] != NULL) {
1037 /* look for a free device number (greater 8192) */
1038 for (devnr = 8192; devnr < 8192 + MAXDEVICES; devnr++) {
1039 if (get_writerreaderdevs_index(devnr) == -1) {
1040 break;
1041 }
1042 }
1043 scanbus_single(alt_scsidevices[i], devnr, txt);
1044 i++;
1045 }
1046
1047 /* trigger not to scan the bus any futher */
1048 doscanbus = 0;
1049 }
1050
1051 #if (defined(__MACH__) && defined(__APPLE__))
1052
1053 /* special handling for osX */
1054 /* try fixed list of devices */
1055 alt_scsidevices[0] = g_strdup("IOCompactDiscServices");
1056 alt_scsidevices[1] = g_strdup("IOCompactDiscServices/2");
1057 alt_scsidevices[2] = g_strdup("IOCompactDiscServices/3");
1058 alt_scsidevices[3] = g_strdup("IODVDServices");
1059 alt_scsidevices[4] = g_strdup("IODVDServices/2");
1060 alt_scsidevices[5] = g_strdup("IODVDServices/3");
1061
1062 i = 0;
1063 while (alt_scsidevices[i] != NULL) {
1064 scanbus_via_inq(alt_scsidevices[i], 4096+i, txt);
1065 i++;
1066 }
1067
1068 /* trigger not to scan the bus any futher */
1069 doscanbus = 0;
1070 #endif
1071
1072 if (doscanbus) {
1073 /* scan for scsi devices */
1074 scan_traditional(txt);
1075
1076 /* scan for alternatives */
1077 #if defined(linux)
1078 if (scanparam) {
1079 scan_other("ATA", 1, txt);
1080 }
1081 #endif
1082 #if defined(sun)
1083 if (scanparam) {
1084 scan_other("USCSI", 2, txt);
1085 }
1086 #endif
1087 }
1088
1089 if (txt) {
1090 strncpy(tmp,_("Scan finished.\n"), MAXLINE);
1091 convert_for_gtk2_textwidget(tmp);
1092 gtk_text_insert(GTK_TEXT(txt), boldfont, NULL, NULL, tmp, strlen(tmp));
1093 wait_and_process_events();
1094 }
1095
1096 gdk_font_unref(boldfont);
1097
1098
1099 if (debug) print_writerreaderdevs();
1100
1101 }
1102
1103
1104
1105 /* scan for remote scsi devices */
1106
scanbus_rscsi(gchar * devstr,GtkWidget * txt)1107 void scanbus_rscsi(gchar *devstr, GtkWidget *txt) {
1108 gchar tmp[MAXLINE];
1109 GdkFont *boldfont;
1110 gint found;
1111 gint i, highest;
1112
1113 /* allocate memory */
1114 if (!writerreaderdevs) {
1115 writerreaderdevs = g_new0(writerreader_devices_t *, MAXDEVICES);
1116 }
1117
1118 boldfont = get_some_font(BOLDFONT);
1119
1120 /* output status texts? */
1121 if (txt) {
1122 strncpy(tmp,_("Starting to scan for remote devices...\n"), MAXLINE);
1123 convert_for_gtk2_textwidget(tmp);
1124 gtk_text_insert(GTK_TEXT(txt), boldfont, NULL, NULL, tmp, strlen(tmp));
1125 wait_and_process_events();
1126 }
1127
1128 /* look for highest free devnr - but at least a multiple of 16384 */
1129 i = 0;
1130 highest = -1;
1131 while(writerreaderdevs[i] != NULL) {
1132 if (writerreaderdevs[i]->devnr > highest) {
1133 highest = writerreaderdevs[i]->devnr;
1134 }
1135 i++;
1136 }
1137 highest++;
1138
1139 /* when we scan multiple times always arange a new block to play safe */
1140 highest = ((highest/16384)+1)*16384;
1141
1142 found = scan_other(devstr, highest/1024, txt);
1143
1144 if (txt) {
1145 if (found == 0) {
1146 strncpy(tmp,_("No devices found - check your remote scsi setup.\n"), MAXLINE);
1147 convert_for_gtk2_textwidget(tmp);
1148 gtk_text_insert(GTK_TEXT(txt), NULL, NULL, NULL, tmp, strlen(tmp));
1149 }
1150 strncpy(tmp,_("Scan finished.\n"), MAXLINE);
1151 convert_for_gtk2_textwidget(tmp);
1152 gtk_text_insert(GTK_TEXT(txt), boldfont, NULL, NULL, tmp, strlen(tmp));
1153 wait_and_process_events();
1154 }
1155
1156 gdk_font_unref(boldfont);
1157
1158
1159 if (debug) print_writerreaderdevs();
1160 }
1161
1162
1163 /* special version where we scan only for a single device */
1164
scanbus_new_single(gchar * devstr,GtkWidget * txt)1165 void scanbus_new_single(gchar *devstr, GtkWidget *txt) {
1166 gchar tmp[MAXLINE];
1167 GdkFont *boldfont;
1168 gint devnr, found;
1169
1170 /* allocate memory */
1171 if (!writerreaderdevs) {
1172 writerreaderdevs = g_new0(writerreader_devices_t *, MAXDEVICES);
1173 }
1174
1175 boldfont = get_some_font(BOLDFONT);
1176
1177 /* output status texts? */
1178 if (txt) {
1179 strncpy(tmp,_("Starting to scan for devices...\n"), MAXLINE);
1180 convert_for_gtk2_textwidget(tmp);
1181 gtk_text_insert(GTK_TEXT(txt), boldfont, NULL, NULL, tmp, strlen(tmp));
1182 wait_and_process_events();
1183 }
1184
1185 /* look for a free device number (greater 8192) */
1186 for (devnr = 8192; devnr < 8192 + MAXDEVICES; devnr++) {
1187 if (get_writerreaderdevs_index(devnr) == -1) {
1188 break;
1189 }
1190 }
1191 found = scanbus_single(devstr, devnr, txt);
1192
1193 if (txt) {
1194 if (!found) {
1195 strncpy(tmp,_("Device not found.\n"), MAXLINE);
1196 convert_for_gtk2_textwidget(tmp);
1197 gtk_text_insert(GTK_TEXT(txt), NULL, NULL, NULL, tmp, strlen(tmp));
1198 }
1199 strncpy(tmp,_("Scan finished.\n"), MAXLINE);
1200 convert_for_gtk2_textwidget(tmp);
1201 gtk_text_insert(GTK_TEXT(txt), boldfont, NULL, NULL, tmp, strlen(tmp));
1202 wait_and_process_events();
1203 }
1204
1205 gdk_font_unref(boldfont);
1206
1207
1208 if (debug) print_writerreaderdevs();
1209 }
1210
1211
1212 /* interpret output of driver=help and sort into memory structure */
1213
parse_driver(gchar * line)1214 static void parse_driver(gchar *line) {
1215 gchar tmp[MAXLINE];
1216 gchar tmp2[MAXLINE];
1217 gchar drv[MAXLINE];
1218 gchar *p1;
1219 gint n;
1220 if (strncmp(line,"Driver types:",13) != 0 ) {
1221
1222 strcpy(tmp,line);
1223 p1=strtok(tmp," ");
1224 strcpy(drv,p1);
1225 /* now drv contains the driver name */
1226
1227 p1=strtok(NULL,"");
1228 strcpy(tmp2,p1);
1229 strip_string(tmp2);
1230 /* now tmp2 contains the description */
1231
1232 /* cut "driver for" away */
1233 if (strncmp(tmp2,"driver for ",11) == 0 ){
1234 strcpy(tmp,tmp2+11);
1235 strcpy(tmp2,tmp);
1236 }
1237
1238 /* allocate structure */
1239 drivers[drvcount]=g_new(writer_driver_t,1);
1240
1241 n = strlen(drv)+1;
1242 drivers[drvcount]->driver=g_new(gchar,n);
1243 strcpy(drivers[drvcount]->driver,drv);
1244
1245 n = strlen(tmp2)+1;
1246 drivers[drvcount]->desc=g_new(gchar,n);
1247 strcpy(drivers[drvcount]->desc,tmp2);
1248
1249 drvcount++;
1250 if (drvcount >= MAXDRIVERS) {
1251 g_error("Error: More than %d writer devices found\n",MAXDRIVERS);
1252 }
1253 }
1254 }
1255
1256
1257 /* print memory-structure with drivers (debug purposes) */
1258
print_drivers()1259 static void print_drivers() {
1260 gint count;
1261
1262 dodebug(2,"------ cdrecord drivers-structure -----\n");
1263 count = 0;
1264 while(drivers[count] != NULL) {
1265 dodebug(2, "%s:%s\n",
1266 drivers[count]->driver,
1267 drivers[count]->desc);
1268
1269 count++;
1270 }
1271 }
1272
1273
1274 /* call cdrecord driver=help */
1275
scandrivers()1276 void scandrivers() {
1277 gchar line[MAXLINE];
1278 FILE *fpin;
1279
1280 /* allocate memory */
1281 drivers = g_new0(writer_driver_t *,MAXDRIVERS);
1282 drvcount = 0;
1283
1284 get_wrap_path_cdrecord(line);
1285 strcat(line," driver=help 2>&1");
1286
1287 dodebug(1, "calling: %s\n", line);
1288 if ((fpin = popen(line,"r")) == NULL) {
1289 g_error("popen error\n");
1290 }
1291
1292 for (;;) {
1293 if (fgets(line,MAXLINE,fpin) == NULL)
1294 break;
1295 dodebug(10, "driverlist: %s",line);
1296 parse_driver(line);
1297 }
1298
1299 if (pclose(fpin) == -1) {
1300 g_error("pclose error\n");
1301 }
1302
1303 if (debug) print_drivers();
1304 }
1305
1306
1307 /* print memory-structure with charsets (debug purposes) */
1308
print_charsets()1309 static void print_charsets() {
1310 gint count;
1311 gchar tmp[MAXLINE];
1312
1313 dodebug(2,"------ mkisofs-charsets-structure -----\n");
1314 count = 0;
1315 strcpy(tmp,"");
1316 while(charset_types[count] != NULL) {
1317
1318 strcat(tmp,charset_types[count]);
1319
1320 if ((count+1) % 6) {
1321 strcat(tmp, ", ");
1322 } else {
1323 dodebug(2, "%s\n", tmp);
1324 strcpy(tmp,"");
1325 }
1326 count++;
1327 }
1328 if (strcmp(tmp,"") != 0)
1329 dodebug(2, "%s\n", tmp);
1330 }
1331
1332
1333 /* call mkisofs -input-charset help */
1334
scancharsets()1335 void scancharsets() {
1336 gchar line[MAXLINE];
1337 FILE *fpin;
1338 gint start,count,backcount;
1339 gchar **tmp_types;
1340
1341 /* allocate memory */
1342 charset_types = g_new0(gchar *,MAXCHARSETS+1);
1343 tmp_types = g_new0(gchar *,MAXCHARSETS+1);
1344
1345 start = 0;
1346 count = 0;
1347
1348 get_wrap_path("MKISOFS",line);
1349 strcat(line," -input-charset help 2>&1");
1350
1351 dodebug(1, "calling: %s\n", line);
1352 if ((fpin = popen(line,"r")) == NULL) {
1353 g_error("popen error\n");
1354 }
1355
1356 for (;;) {
1357 if (fgets(line,MAXLINE,fpin) == NULL)
1358 break;
1359 /* wait for Known charsets.... line */
1360 if (strncmp("Known",line,5) == 0) {
1361 start = 1;
1362 continue;
1363 }
1364 if (start) {
1365 dodebug(10, "mkisofs charsets: %s",line);
1366
1367 tmp_types[count] = g_strdup(strip_string(line));
1368 count++;
1369 if (count >= MAXCHARSETS) {
1370 g_error("Error: More than %d input charsets found\n",MAXCHARSETS);
1371 }
1372 }
1373 }
1374
1375 tmp_types[count] = g_strdup("default");
1376
1377 if (pclose(fpin) == -1) {
1378 g_error("pclose error\n");
1379 }
1380
1381 /* now the types list is reversed, make it right */
1382 backcount = count;
1383 count = 0;
1384 while(backcount >= 0) {
1385 charset_types[count] = tmp_types[backcount];
1386 count++;
1387 backcount--;
1388 }
1389 g_free(tmp_types);
1390
1391 if (debug) print_charsets();
1392 }
1393
1394
1395 /* call cdrecord -prcap to get some device information */
1396 /* also checks for mmap errors and return 1 if one occured */
1397
getdevicecap(gchar * dev,gint * readmax,gint * cdrmax,gint * dvdmax,gint * iscdr,gint * isdvdrom,gint * isdvdr)1398 static gint getdevicecap(gchar *dev, gint *readmax, gint *cdrmax, gint *dvdmax, gint *iscdr, gint *isdvdrom, gint *isdvdr) {
1399 gchar tmp[MAXLINE];
1400 gchar line[MAXLINE];
1401 gint tmpnr, errcount;
1402 FILE *fpin;
1403 gchar *p;
1404
1405 /* set reasonable defaults */
1406 *readmax = 0;
1407 *cdrmax = 0;
1408 *dvdmax = 0;
1409 *iscdr = 0;
1410 *isdvdr = 0;
1411 *isdvdrom = 0;
1412
1413 if (!dev) return 0;
1414
1415 get_wrap_path_cdrecord(tmp);
1416 g_snprintf(line, MAXLINE, "%s dev= \"%s\" -prcap 2>&1", tmp, dev);
1417
1418 dodebug(1, "calling: %s\n", line);
1419 if ((fpin = popen(line,"r")) == NULL) {
1420 g_error("popen error\n");
1421 }
1422
1423 errcount = 0;
1424 for (;;) {
1425 if (fgets(line,MAXLINE,fpin) == NULL)
1426 break;
1427 dodebug(10, "prcap: %s",line);
1428
1429 /* line with mmap error? */
1430 if (strstr(line,"annot get mmap for")) {
1431 errcount++;
1432 }
1433
1434 if (strstr(line, "Does write CD-R media")) {
1435 *iscdr = 1;
1436 }
1437 if (strstr(line, "Does read DVD-ROM media")) {
1438 *isdvdrom = 1;
1439 }
1440 if (strstr(line, "Does write DVD-R media")) {
1441 *isdvdr = 1;
1442 }
1443 if (strstr(line, "Maximum read speed:")) {
1444 p = strtok(line,"(");
1445 if (p) {
1446 p = strtok(NULL,")");
1447 if (p) {
1448 strcpy(tmp,p);
1449 sscanf(tmp,"CD %3dx, DVD %3d",
1450 readmax, &tmpnr);
1451 }
1452 }
1453 } else
1454 if (strstr(line, "Maximum write speed:")) {
1455 p = strtok(line,"(");
1456 if (p) {
1457 p = strtok(NULL,")");
1458 if (p) {
1459 strcpy(tmp,p);
1460 sscanf(tmp,"CD %3dx, DVD %3d",
1461 cdrmax, dvdmax);
1462 }
1463 }
1464 }
1465 }
1466
1467 if (pclose(fpin) == -1) {
1468 g_error("pclose error\n");
1469 }
1470
1471 if (errcount > 0) {
1472 return 1;
1473 } else {
1474 return 0;
1475 }
1476 }
1477
1478
1479 /* get driverflags and modes from drive */
1480
getmodesflags(gchar * dev,gchar * drvflags,gchar * drvmodes)1481 void getmodesflags(gchar *dev, gchar *drvflags, gchar *drvmodes) {
1482 gchar tmp[MAXLINE];
1483 gchar line[MAXLINE];
1484 FILE *fpin;
1485 gchar *p;
1486
1487 strcpy(drvflags,"");
1488 strcpy(drvmodes,"");
1489
1490 if (!dev) return;
1491
1492 get_wrap_path("CDRECORD", tmp);
1493 g_snprintf(line, MAXLINE, "%s dev= \"%s\" -v -checkdrive 2>&1", tmp, dev);
1494
1495 dodebug(1, "calling: %s\n", line);
1496 if ((fpin = popen(line,"r")) == NULL) {
1497 g_error("popen error\n");
1498 }
1499 for (;;) {
1500 if (fgets(line,MAXLINE,fpin) == NULL)
1501 break;
1502 dodebug(10, "checkdrive: %s",line);
1503
1504 if (strstr(line, "Driver flags :")) {
1505 p = strtok(line,":");
1506 if (p) {
1507 p = strtok(NULL,"");
1508 if (p) {
1509 strncpy(tmp,p,MAXLINE);
1510 strip_string(tmp);
1511 strncpy(drvflags,tmp,MAXLINE);
1512 }
1513 }
1514 } else
1515 if (strstr(line, "Supported modes:")) {
1516 p = strtok(line,":");
1517 if (p) {
1518 p = strtok(NULL,"");
1519 if (p) {
1520 strncpy(tmp,p,MAXLINE);
1521 strip_string(tmp);
1522 strncpy(drvmodes,tmp,MAXLINE);
1523 }
1524 }
1525 }
1526 }
1527
1528 if (pclose(fpin) == -1) {
1529 g_error("pclose error\n");
1530 }
1531 }
1532
1533
parse_freespace(gchar * line,gchar * fs)1534 static gint parse_freespace(gchar *line, gchar *fs) {
1535 gchar tmp[MAXLINE];
1536 gchar *p1;
1537
1538 /* skip first line(s) */
1539 if (index(line,'/')) {
1540 strcpy(tmp,line);
1541 #if defined (aix)
1542 /* filesystem label */
1543 p1=strtok(tmp," ");
1544 if (fs != NULL) {
1545 /* get the filesystem */
1546 strcpy(fs,p1);
1547 }
1548 /* size of filesystem */
1549 p1=strtok(NULL," ");
1550 if (p1 == NULL) {
1551 g_error("df -k output syntax error\n");
1552 }
1553 /* available blocks */
1554 p1=strtok(NULL," ");
1555 if (p1 == NULL) {
1556 g_error("df -k output syntax error\n");
1557 }
1558 return (atoi(p1));
1559 #elif defined (hpux)
1560 /* mountpoint */
1561 p1=strtok(tmp,"(");
1562 if (p1 == NULL) {
1563 g_error("df -b output syntax error\n");
1564 }
1565 /* filesystem label */
1566 p1=strtok(NULL,")");
1567 if (fs != NULL) {
1568 /* get the filesystem - avoid "(" at the beginning */
1569 strcpy(fs,p1);
1570 }
1571 /* size in kb */
1572 p1=strtok(NULL,": ");
1573 if (p1 == NULL) {
1574 g_error("df -b output syntax error\n");
1575 }
1576 return (atoi(p1));
1577 #else
1578
1579 /* skip the first 4 fields in output to come to "available" */
1580
1581 /* are we handling the first line of two?*/
1582 p1=strtok(tmp," ");
1583
1584 if (dfrun == 0) {
1585 if (fs != NULL) {
1586 /* get the filesystem */
1587 strcpy(fs,p1);
1588 }
1589
1590 p1=strtok(NULL," ");
1591 if (p1 == NULL) {
1592 /* ok..output splitted on two lines */
1593 dfrun = 1;
1594 return -1;
1595 }
1596 }
1597 p1=strtok(NULL," ");
1598 if (p1 == NULL) {
1599 g_error("df -k output syntax error\n");
1600 }
1601 p1=strtok(NULL," ");
1602 if (p1 == NULL) {
1603 g_error("df -k output syntax error\n");
1604 }
1605 return (atoi(p1));
1606 #endif
1607 }
1608 return -1;
1609 }
1610
1611
1612 /* get free diskspace. return in 1024byte blocks or -1 if not valid */
1613 /* return filesystem if not set to NULL */
1614 /* will handle if output is in two lines...like when the filesystem
1615 output is longer that 20 chars - e.g. on nfs-links */
1616 /* will handle df-output like:
1617
1618 (Solaris)
1619 Filesystem kbytes used avail capacity Mounted on
1620 fileserv:/export/home
1621 17502608 11609120 5718464 67% /export/home
1622
1623 OR
1624
1625 (Linux)
1626 Filesystem 1024-blocks Used Available Capacity Mounted on
1627 /dev/sda3 2494898 1606489 759428 68% /
1628
1629 Syst�me de
1630 fichiers 1K-blocs Utilis� Disponible U.% Mont� sur
1631 /dev/hda6 10080488 8043456 1524964 85% /
1632
1633 OR
1634
1635 (AIX)
1636 Filesystem 1024-blocks Free %Used Iused %Iused Mounted on
1637 /dev/hd4 8192 2968 64% 1319 33% /
1638 /dev/hd2 573440 31644 95% 22280 16% /usr
1639
1640 OR
1641
1642 (HP-UXs df -b)
1643 /tmp (/dev/vg00/lvol4 ) : 188158 Kbytes free
1644 /usr (/dev/vg00/lvol5 ) : 286696 Kbytes free
1645
1646
1647 */
1648
get_free_space(gchar * path,gchar * filesystem)1649 gint get_free_space(gchar *path, gchar *filesystem) {
1650 gchar line[MAXLINE];
1651 FILE *fpin;
1652 gint space;
1653
1654 space = -1;
1655 dfrun = 0;
1656
1657 if (is_directory(path) != 1) {
1658 return -1;
1659 }
1660
1661 if (stat_file(DF)) {
1662 strcpy(line,DF);
1663 strcat(line," \"");
1664 strcat(line,path);
1665 strcat(line,"\"");
1666 } else {
1667 strcpy(line,DF2);
1668 strcat(line," \"");
1669 strcat(line,path);
1670 strcat(line,"\"");
1671 }
1672
1673 dodebug(1, "calling: %s\n", line);
1674 if ((fpin = popen(line,"r")) == NULL) {
1675 g_error("popen error\n");
1676 }
1677
1678 for (;;) {
1679 if (fgets(line,MAXLINE,fpin) == NULL)
1680 break;
1681 dodebug(10,"df: %s",line);
1682 space = parse_freespace(line,filesystem);
1683 }
1684
1685 if (pclose(fpin) == -1) {
1686 g_error("pclose error\n");
1687 }
1688
1689 if (filesystem != NULL) {
1690 dodebug(2, "filesystem lookup for %s = %d blocks, fs = %s\n",
1691 path, space, filesystem);
1692 } else {
1693 dodebug(2, "filesystem lookup for %s = %d blocks, fs = %s\n",
1694 path, space, "(NULL)");
1695 }
1696
1697 return space;
1698 }
1699
1700
1701 /* get a list of all audio-devices found on a system. This has to be
1702 done platform dependent */
1703
get_dsp_devices()1704 GList *get_dsp_devices() {
1705 GList *dsp;
1706 GList *loop;
1707 #if !(defined(__MACH__) && defined(__APPLE__))
1708 struct stat buf;
1709 #endif
1710
1711 #if defined(sun) || defined(aix) || defined(__OpenBSD__)
1712 gchar *audiodev;
1713 #endif
1714 dsp = NULL;
1715
1716 #if defined(linux) || defined(__FreeBSD__)
1717 /* for linux check if /dev/dsp or /dev/dsp1 exist */
1718
1719 if (stat("/dev/dsp",&buf) == 0) {
1720 dsp = g_list_append(dsp,"/dev/dsp");
1721 }
1722 if (stat("/dev/dsp1",&buf) == 0) {
1723 dsp = g_list_append(dsp,"/dev/dsp1");
1724 }
1725 #endif
1726 #if defined(sun) || defined(__OpenBSD__)
1727 /* check if the user has any special audio-hardware running,
1728 which set the AUDIODEV-environment-variable */
1729 audiodev = getenv("AUDIODEV");
1730 if (audiodev != NULL) {
1731
1732 if (stat(audiodev,&buf) == 0) {
1733 dsp = g_list_append(dsp,g_strdup(audiodev));
1734 }
1735 } else {
1736 audiodev = "";
1737 }
1738 if (strcmp(audiodev,"/dev/audio") != 0) {
1739
1740 if (stat("/dev/audio",&buf) == 0) {
1741 dsp = g_list_append(dsp,"/dev/audio");
1742 }
1743 }
1744 #endif
1745 #ifdef aix
1746 audiodev = getenv ("AUDIODEV");
1747 if (audiodev != NULL) {
1748
1749 if (stat (audiodev, &buf) == 0) {
1750 dsp = g_list_append (dsp, g_strdup(audiodev));
1751 }
1752 }
1753 /* Try to use the device of a machine with PCI bus */
1754 if (stat ("/dev/paud0/1", &buf) == 0) {
1755 dsp = g_list_append (dsp, "/dev/paud0/1");
1756 }
1757 /* Try to use the device of a machine with MCA bus */
1758 if (stat ("/dev/baud0/1", &buf) == 0) {
1759 dsp = g_list_append (dsp, "/dev/baud0/1");
1760 }
1761 #endif
1762 #ifdef hpux
1763 # ifndef hpux_alib
1764
1765 /* for HP-UX check if /dev/audio exists - I've never seen */
1766 /* other audio devices under HP-UX */
1767
1768 if (stat("/dev/audio",&buf) == 0) {
1769 dsp = g_list_append(dsp,"/dev/audio");
1770 }
1771 # else
1772 /* for HP-UX with the Alib we dont need to check if the */
1773 /* device exists - we actually do not know even the device */
1774 dsp = g_list_append(dsp,"AUDIO ENVIRONMENT");
1775 # endif
1776 #endif
1777
1778 #if (defined(__MACH__) && defined(__APPLE__))
1779
1780 /* on macosX we always should have the build-in-audio device */
1781 dsp = g_list_append(dsp,"Apple CoreAudio");
1782 #endif
1783
1784 #if defined(__sgi)
1785 {
1786 int i, rv;
1787 ALvalue devs [16];
1788 ALpv q [1];
1789 char devLabel [32];
1790
1791 /*
1792 * Fetch the list of available output audio devices.
1793 */
1794 q[0].param = AL_TYPE;
1795 q[0].value.i = AL_OUTPUT_DEVICE_TYPE;
1796 if ((rv = alQueryValues(AL_SYSTEM, AL_DEVICES, devs, 16, q, 1)) >= 0) {
1797
1798 for (i = 0; i < rv; i++) {
1799 q[0].param = AL_LABEL;
1800 q[0].value.ptr = devLabel;
1801 q[0].sizeIn = 32;
1802 alGetParams(devs[i].i, q, 1);
1803 if (alIsSubtype(AL_DEVICE_TYPE, devs[i].i)) {
1804 dsp = g_list_append(dsp, g_strdup(devLabel));
1805 }
1806 }
1807 }
1808 }
1809 #endif
1810
1811 /* do some debug output */
1812 if (debug) {
1813 loop = g_list_first(dsp);
1814 while(loop) {
1815 if (loop->data != NULL)
1816 dodebug(10, "dspscan: %s\n",
1817 (gchar *) loop->data);
1818 loop = loop->next;
1819 }
1820 }
1821
1822 return g_list_first(dsp);
1823 }
1824
1825
1826 /* take a dsp-device and find the fitting mixer-device */
1827
gen_mix_from_dspdev(gchar * dsp,gchar * ret)1828 gchar *gen_mix_from_dspdev(gchar *dsp, gchar *ret) {
1829 #if !(defined(__MACH__) && defined(__APPLE__))
1830 gchar tmp[MAXLINE];
1831 # ifndef aix
1832 struct stat buf;
1833 # endif
1834 #endif
1835 #if defined(linux) || defined(__FreeBSD__)
1836 gchar tmp2[MAXLINE];
1837 #endif
1838
1839 strcpy(ret,"");
1840
1841 #if defined(linux) || defined(__FreeBSD__)
1842
1843 if (strncmp(dsp,"/dev/dsp",8) == 0) {
1844 strcpy(tmp,dsp+8);
1845 g_snprintf(tmp2,MAXLINE,"/dev/mixer%s",tmp);
1846
1847 /* does device exist? */
1848 if (stat(tmp2,&buf) == 0) {
1849 strcpy(ret,tmp2);
1850 }
1851 }
1852 #endif
1853 #if defined(sun) || defined(__OpenBSD__)
1854
1855 g_snprintf(tmp,MAXLINE,"%s%s",dsp,"ctl");
1856
1857 /* does device exist? */
1858 if (stat(tmp,&buf) == 0) {
1859 strcpy(ret,tmp);
1860 }
1861 #endif
1862 #ifdef aix
1863 /* The gain will be set via ioctl and the usual */
1864 /* output device */
1865 g_snprintf(tmp,MAXLINE,"%s",dsp);
1866 strcpy(ret,tmp);
1867 #endif
1868 #ifdef hpux
1869 # ifndef hpux_alib
1870 g_snprintf(tmp,MAXLINE,"%s%s",dsp,"Ctl");
1871
1872 /* does device exist? */
1873 if (stat(tmp,&buf) == 0) {
1874 strcpy(ret,tmp);
1875 }
1876 # else
1877 /* We have no control or mixer device -> all is */
1878 /* done via the Aserver-daemon and its API */
1879 strcpy(ret, "ASERVER");
1880 # endif
1881 #endif
1882
1883 dodebug(10, "mixer: %s\n", ret);
1884 return ret;
1885 }
1886
1887
1888 /* call uname -a to get a nice system-id-string */
1889
get_uname_info(gchar * str)1890 gchar *get_uname_info(gchar *str) {
1891 FILE *fpin;
1892
1893 if (stat_file(UNAME)) {
1894 dodebug(1, "calling: %s\n", UNAME);
1895 if ((fpin = popen(UNAME,"r")) == NULL) {
1896 g_error("popen error\n");
1897 }
1898 } else {
1899 dodebug(1, "calling: %s\n", UNAME2);
1900 if ((fpin = popen(UNAME2,"r")) == NULL) {
1901 g_error("popen error\n");
1902 }
1903 }
1904
1905 strcpy(str,"");
1906 fgets(str,MAXLINE,fpin);
1907
1908 if (pclose(fpin) == -1) {
1909 g_error("pclose error\n");
1910 }
1911
1912 dodebug(10, "uname: %s\n", str);
1913
1914 return str;
1915 }
1916
1917
1918 /* Save the setup-configuration to a file - all strings are converted
1919 in a printable form first: return 0 if ok, or 1 on error */
1920
save_setup_config(gchar * confdir,gchar * fname)1921 gint save_setup_config(gchar *confdir, gchar *fname) {
1922 FILE *fd;
1923 gchar tmp[MAXLINE];
1924 gchar tmp2[MAXLINE];
1925 GList *loop;
1926 gint count;
1927
1928 /* no confdir? treat path absolute */
1929 if (strcmp(confdir,"") == 0) {
1930 strncpy(tmp,fname,MAXLINE);
1931 } else {
1932
1933 /* now check if the confdir exists */
1934 if (!is_directory(confdir)) {
1935 /* try to create directory */
1936 mkdir(confdir, 0700);
1937 dodebug(2, "trying to mkdir %s\n", confdir);
1938 }
1939
1940 g_snprintf(tmp,MAXLINE,"%s/%s", confdir, fname);
1941 }
1942
1943 dodebug(1, "Opening %s for writing\n", tmp);
1944 dolog(3, "Saving config file %s\n", tmp);
1945
1946 fd = fopen(tmp,"w");
1947
1948 if (fd == NULL) {
1949 /* error opening file */
1950 return 1;
1951 }
1952
1953 /* write the config-file header */
1954 fputs("#\n",fd);
1955 g_snprintf(tmp,MAXLINE,"# X-CD-Roast %s Configuration-File\n",XCDROAST_VERSION);
1956 fputs(tmp,fd);
1957 fputs("#\n",fd);
1958 fputs("# Automatically created by the X-CD-Roast-Setup\n",fd);
1959 fputs("# Don't edit! (Unless you REALLY know what you are doing)\n",fd);
1960 fputs("#\n\n",fd);
1961
1962 /* write data */
1963 g_snprintf(tmp,MAXLINE,"VERSION = \"%s\"\n",XCDROAST_VERSION);
1964 fputs(tmp,fd);
1965 g_snprintf(tmp,MAXLINE,"PLATFORM = \"%s\"\n",system_platform);
1966 fputs(tmp,fd);
1967 g_snprintf(tmp,MAXLINE,"WRITER_DEVNR = %d\n",setupdata.writer_devnr);
1968 fputs(tmp,fd);
1969 g_snprintf(tmp,MAXLINE,"READER_DEVNR = %d\n",setupdata.reader_devnr);
1970 fputs(tmp,fd);
1971
1972 fputs("#\n",fd);
1973
1974 /* write hardware structure */
1975 count = 0;
1976 while(writerreaderdevs[count] != NULL) {
1977
1978 g_snprintf(tmp,MAXLINE,"WRITERREADER_DEVNR = %d\n",writerreaderdevs[count]->devnr);
1979 fputs(tmp,fd);
1980
1981 strcpy(tmp2,writerreaderdevs[count]->devicestr);
1982 g_snprintf(tmp,MAXLINE,"WRITERREADER_DEVICESTR = \"%s\"\n",convert_escape(tmp2));
1983 fputs(tmp,fd);
1984
1985 strcpy(tmp2,writerreaderdevs[count]->vendor);
1986 g_snprintf(tmp,MAXLINE,"WRITERREADER_VENDOR = \"%s\"\n",convert_escape(tmp2));
1987 fputs(tmp,fd);
1988 strcpy(tmp2,writerreaderdevs[count]->model);
1989 g_snprintf(tmp,MAXLINE,"WRITERREADER_MODEL = \"%s\"\n",convert_escape(tmp2));
1990 fputs(tmp,fd);
1991 strcpy(tmp2,writerreaderdevs[count]->rev);
1992 g_snprintf(tmp,MAXLINE,"WRITERREADER_REV = \"%s\"\n",convert_escape(tmp2));
1993 fputs(tmp,fd);
1994
1995 g_snprintf(tmp,MAXLINE,"WRITERREADER_READMAXSPEED = %d\n",writerreaderdevs[count]->writer_readmaxspeed);
1996 fputs(tmp,fd);
1997 g_snprintf(tmp,MAXLINE,"WRITERREADER_CDRMAXSPEED = %d\n",writerreaderdevs[count]->writer_cdrmaxspeed);
1998 fputs(tmp,fd);
1999 g_snprintf(tmp,MAXLINE,"WRITERREADER_DVDMAXSPEED = %d\n",writerreaderdevs[count]->writer_dvdmaxspeed);
2000 fputs(tmp,fd);
2001
2002 strcpy(tmp2,writerreaderdevs[count]->writer_flags);
2003 g_snprintf(tmp,MAXLINE,"WRITERREADER_WRITER_FLAGS = \"%s\"\n",convert_escape(tmp2));
2004 fputs(tmp,fd);
2005 strcpy(tmp2,writerreaderdevs[count]->writer_modes);
2006 g_snprintf(tmp,MAXLINE,"WRITERREADER_WRITER_MODES = \"%s\"\n",convert_escape(tmp2));
2007 fputs(tmp,fd);
2008
2009 g_snprintf(tmp,MAXLINE,"WRITERREADER_IS_CDRWRITER = %d\n",writerreaderdevs[count]->is_cdrwriter);
2010 fputs(tmp,fd);
2011 g_snprintf(tmp,MAXLINE,"WRITERREADER_IS_DVDWRITER = %d\n",writerreaderdevs[count]->is_dvdwriter);
2012 fputs(tmp,fd);
2013 g_snprintf(tmp,MAXLINE,"WRITERREADER_IS_DVDREADER = %d\n",writerreaderdevs[count]->is_dvdreader);
2014 fputs(tmp,fd);
2015 g_snprintf(tmp,MAXLINE,"WRITERREADER_SECTOR_SIZE = %d\n",writerreaderdevs[count]->sector_size);
2016 fputs(tmp,fd);
2017
2018 g_snprintf(tmp,MAXLINE,"WRITERREADER_DRVMODE = %d\n",writerreaderdevs[count]->writer_drvmode);
2019 fputs(tmp,fd);
2020 g_snprintf(tmp,MAXLINE,"WRITERREADER_MODE = %d\n",writerreaderdevs[count]->writer_mode);
2021 fputs(tmp,fd);
2022 g_snprintf(tmp,MAXLINE,"WRITERREADER_SPEED = %d\n",writerreaderdevs[count]->writer_speed);
2023 fputs(tmp,fd);
2024 g_snprintf(tmp,MAXLINE,"WRITERREADER_FIFO = %d\n",writerreaderdevs[count]->writer_fifo);
2025 fputs(tmp,fd);
2026 g_snprintf(tmp,MAXLINE,"WRITERREADER_AUDIOREAD_INTERFACE = %d\n",writerreaderdevs[count]->audioread_interface);
2027 fputs(tmp,fd);
2028 g_snprintf(tmp,MAXLINE,"WRITERREADER_AUDIOREAD_SPEED = %d\n",writerreaderdevs[count]->audioread_speed);
2029 fputs(tmp,fd);
2030 g_snprintf(tmp,MAXLINE,"WRITERREADER_AUDIOREAD_OVERLAP = %d\n",writerreaderdevs[count]->audioread_overlap);
2031 fputs(tmp,fd);
2032 g_snprintf(tmp,MAXLINE,"WRITERREADER_AUDIOREAD_SECTORBURST = %d\n",writerreaderdevs[count]->audioread_sectorburst);
2033 fputs(tmp,fd);
2034 g_snprintf(tmp,MAXLINE,"WRITERREADER_AUDIOREAD_USEPARANOIA = %d\n",writerreaderdevs[count]->audioread_useparanoia);
2035 fputs(tmp,fd);
2036 g_snprintf(tmp,MAXLINE,"WRITERREADER_AUDIOREAD_PARANOIARETRIES = %d\n",writerreaderdevs[count]->audioread_paranoiaretries);
2037 fputs(tmp,fd);
2038
2039
2040 fputs("#\n",fd);
2041 count++;
2042 }
2043
2044 loop = g_list_first(setupdata.image_dirs);
2045 while(loop) {
2046 strcpy(tmp2,(gchar *)loop->data);
2047 g_snprintf(tmp,MAXLINE,"IMAGE_DIRS = \"%s\"\n",convert_escape(tmp2));
2048 fputs(tmp,fd);
2049 loop = loop->next;
2050 }
2051
2052 strcpy(tmp2,setupdata.dsp_device);
2053 g_snprintf(tmp,MAXLINE,"DSP_DEVICE = \"%s\"\n",convert_escape(tmp2));
2054 fputs(tmp,fd);
2055 strcpy(tmp2,setupdata.mix_device);
2056 g_snprintf(tmp,MAXLINE,"MIX_DEVICE = \"%s\"\n",convert_escape(tmp2));
2057 fputs(tmp,fd);
2058 g_snprintf(tmp,MAXLINE,"NOTIFY_VIA = %d\n",setupdata.notify_via);
2059 fputs(tmp,fd);
2060 g_snprintf(tmp,MAXLINE,"NOTIFY_AT = %d\n",setupdata.notify_at);
2061 fputs(tmp,fd);
2062
2063 strcpy(tmp2,setupdata.cddb_host);
2064 g_snprintf(tmp,MAXLINE,"CDDB_HOST = \"%s\"\n",convert_escape(tmp2));
2065 fputs(tmp,fd);
2066 g_snprintf(tmp,MAXLINE,"CDDB_PORT = %d\n",setupdata.cddb_port);
2067 fputs(tmp,fd);
2068 strcpy(tmp2,setupdata.cddb_proxy_host);
2069 g_snprintf(tmp,MAXLINE,"CDDB_PROXY_HOST = \"%s\"\n",convert_escape(tmp2));
2070 fputs(tmp,fd);
2071 g_snprintf(tmp,MAXLINE,"CDDB_PROXY_PORT = %d\n",setupdata.cddb_proxy_port);
2072 fputs(tmp,fd);
2073 g_snprintf(tmp,MAXLINE,"CDDB_USE_HTTP = %d\n",setupdata.cddb_use_http);
2074 fputs(tmp,fd);
2075 g_snprintf(tmp,MAXLINE,"CDDB_USE_PROXY = %d\n",setupdata.cddb_use_proxy);
2076 fputs(tmp,fd);
2077
2078 strcpy(tmp2,setupdata.logfile);
2079 g_snprintf(tmp,MAXLINE,"LOGFILE = \"%s\"\n",convert_escape(tmp2));
2080 fputs(tmp,fd);
2081 g_snprintf(tmp,MAXLINE,"LOGLEVEL = %d\n",setupdata.loglevel);
2082 fputs(tmp,fd);
2083
2084 strcpy(tmp2,setupdata.language);
2085 g_snprintf(tmp,MAXLINE,"LANGUAGE = \"%s\"\n",convert_escape(tmp2));
2086 fputs(tmp,fd);
2087
2088 g_snprintf(tmp,MAXLINE,"OPTION_TOOLTIPS = %d\n",setupdata.option_tooltips);
2089 fputs(tmp,fd);
2090 g_snprintf(tmp,MAXLINE,"OPTION_AUTORAISE = %d\n",setupdata.option_autoraise);
2091 fputs(tmp,fd);
2092 g_snprintf(tmp,MAXLINE,"OPTION_SAVEPOS = %d\n",setupdata.option_savepos);
2093 fputs(tmp,fd);
2094 g_snprintf(tmp,MAXLINE,"OPTION_PERSONIMAGE = %d\n",setupdata.option_personimage);
2095 fputs(tmp,fd);
2096 g_snprintf(tmp,MAXLINE,"OPTION_OVERWRITEWARN = %d\n",setupdata.option_overwritewarn);
2097 fputs(tmp,fd);
2098 g_snprintf(tmp,MAXLINE,"OPTION_AUTODELETE = %d\n",setupdata.option_autodelete);
2099 fputs(tmp,fd);
2100 g_snprintf(tmp,MAXLINE,"OPTION_TITLEPROGRESS = %d\n",setupdata.option_titleprogress);
2101 fputs(tmp,fd);
2102 g_snprintf(tmp,MAXLINE,"OPTION_DISPLAYCDTEXT = %d\n",setupdata.option_displaycdtext);
2103 fputs(tmp,fd);
2104 g_snprintf(tmp,MAXLINE,"OPTION_SELECTIONMODE = %d\n",setupdata.option_selectionmode);
2105 fputs(tmp,fd);
2106
2107 strcpy(tmp2,setupdata.ProDVDkey);
2108 g_snprintf(tmp,MAXLINE,"PRODVD_KEY = \"%s\"\n",convert_escape(tmp2));
2109 fputs(tmp,fd);
2110
2111 /* save geometry data? */
2112 if (setupdata.option_savepos) {
2113 g_snprintf(tmp,MAXLINE,"GEOMETRY_MAINWINDOW_X = %d\n", setupdata.mainwindow.x);
2114 fputs(tmp,fd);
2115 g_snprintf(tmp,MAXLINE,"GEOMETRY_MAINWINDOW_Y = %d\n", setupdata.mainwindow.y);
2116 fputs(tmp,fd);
2117 g_snprintf(tmp,MAXLINE,"GEOMETRY_MAINWINDOW_WIDTH = %d\n", setupdata.mainwindow.width);
2118 fputs(tmp,fd);
2119 g_snprintf(tmp,MAXLINE,"GEOMETRY_MAINWINDOW_HEIGHT = %d\n", setupdata.mainwindow.height);
2120 fputs(tmp,fd);
2121
2122 g_snprintf(tmp,MAXLINE,"GEOMETRY_BURNWINDOW_X = %d\n", setupdata.burnwindow.x);
2123 fputs(tmp,fd);
2124 g_snprintf(tmp,MAXLINE,"GEOMETRY_BURNWINDOW_Y = %d\n", setupdata.burnwindow.y);
2125 fputs(tmp,fd);
2126 g_snprintf(tmp,MAXLINE,"GEOMETRY_BURNWINDOW_WIDTH = %d\n", setupdata.burnwindow.width);
2127 fputs(tmp,fd);
2128 g_snprintf(tmp,MAXLINE,"GEOMETRY_BURNWINDOW_HEIGHT = %d\n", setupdata.burnwindow.height);
2129 fputs(tmp,fd);
2130 }
2131
2132 /* do save the following information only when root */
2133 if (isroot()) {
2134
2135 g_snprintf(tmp,MAXLINE,"ROOT_USERS_ACCESS = %d\n",setupdata.root_users_access);
2136 fputs(tmp,fd);
2137
2138 loop = g_list_first(setupdata.root_users_lists);
2139 while(loop) {
2140 strcpy(tmp2,(gchar *)loop->data);
2141 g_snprintf(tmp,MAXLINE,"ROOT_USERS_LISTS = \"%s\"\n",convert_escape(tmp2));
2142 fputs(tmp,fd);
2143 loop = loop->next;
2144 }
2145
2146 g_snprintf(tmp,MAXLINE,"ROOT_HOSTS_ACCESS = %d\n",setupdata.root_hosts_access);
2147 fputs(tmp,fd);
2148
2149 loop = g_list_first(setupdata.root_hosts_lists);
2150 while(loop) {
2151 strcpy(tmp2,(gchar *)loop->data);
2152 g_snprintf(tmp,MAXLINE,"ROOT_HOSTS_LISTS = \"%s\"\n",convert_escape(tmp2));
2153 fputs(tmp,fd);
2154 loop = loop->next;
2155 }
2156
2157 g_snprintf(tmp,MAXLINE,"ROOT_OPTION_CHANGE_WRITER = %d\n",setupdata.root_option_change_writer);
2158 fputs(tmp,fd);
2159 g_snprintf(tmp,MAXLINE,"ROOT_OPTION_CHANGE_WRITEPARAM = %d\n",setupdata.root_option_change_writeparam);
2160 fputs(tmp,fd);
2161 g_snprintf(tmp,MAXLINE,"ROOT_OPTION_CHANGE_READER = %d\n",setupdata.root_option_change_reader);
2162 fputs(tmp,fd);
2163 g_snprintf(tmp,MAXLINE,"ROOT_OPTION_CHANGE_READPARAM = %d\n",setupdata.root_option_change_readparam);
2164 fputs(tmp,fd);
2165 g_snprintf(tmp,MAXLINE,"ROOT_OPTION_CHANGE_IMAGEDIRS = %d\n",setupdata.root_option_change_imagedirs);
2166 fputs(tmp,fd);
2167 g_snprintf(tmp,MAXLINE,"ROOT_OPTION_CHANGE_LOGOPTIONS = %d\n",setupdata.root_option_change_logoptions);
2168 fputs(tmp,fd);
2169 }
2170
2171 if (fclose(fd) != 0) {
2172 /* error closing file */
2173 return 1;
2174 }
2175
2176 return 0;
2177 }
2178
2179
2180 /* Load the setup-configuration
2181 return 0 if ok, or 1 on error */
2182 /* when rootconf is set, load all from file, else only what we are
2183 allow */
2184
load_setup_config(gchar * fname,gint rootconf)2185 gint load_setup_config(gchar *fname, gint rootconf) {
2186 FILE *fd;
2187 gchar line[MAXLINE];
2188 gchar id[MAXLINE];
2189 gchar value[MAXLINE];
2190 gchar tmp[MAXLINE];
2191 GList *tmp_image_dirs;
2192 gint count, i, newadded;
2193
2194 /* allocate memory if required */
2195 if (!writerreaderdevs) {
2196 writerreaderdevs = g_new0(writerreader_devices_t *, MAXDEVICES);
2197 }
2198
2199 count = -1;
2200 newadded = 0;
2201 tmp_image_dirs = NULL;
2202
2203 /* prepare some data */
2204 if (rootconf) {
2205 free_glist(&setupdata.image_dirs);
2206 }
2207 if (rootconf) {
2208 free_glist(&setupdata.root_users_lists);
2209 free_glist(&setupdata.root_hosts_lists);
2210 }
2211
2212 dodebug(1, "Opening config file %s for reading\n", fname);
2213 dolog(3, "Loading config file %s\n", fname);
2214
2215 if ((fd = fopen(fname,"r")) == NULL) {
2216 /* error opening file */
2217 return 1;
2218 }
2219
2220 for (;;) {
2221 if (fgets(line,MAXLINE,fd) == NULL)
2222 break;
2223
2224 /* special case here to protect pro-dvd-key */
2225 if (strstr(line, "PRODVD_KEY") && strlen(line) > 50) {
2226 strncpy(tmp,line,50);
2227 tmp[50] = '\0';
2228 dodebug(10,"config: %s...\n", tmp);
2229 } else {
2230 dodebug(10,"config: %s", line);
2231 }
2232
2233 /* skip empty or hashed lines */
2234 strip_string(line);
2235 if (*line == '#' || *line == '\0')
2236 continue;
2237
2238 /* parse lines */
2239 if (parse_config_line(line,id,value)) {
2240 g_error("syntax error in config-file\n");
2241 }
2242
2243 if (strcmp("VERSION",id) == 0) {
2244 strcpy(xcdroast_version_loaded,value);
2245 }
2246 if (strcmp("PLATFORM",id) == 0) {
2247 ;
2248 }
2249
2250 if (rootconf || setupdata.root_option_change_writer) {
2251 if (strcmp("WRITER_DEVNR",id) == 0) {
2252 setupdata.writer_devnr = atoi(value);
2253 }
2254 }
2255 if (rootconf || setupdata.root_option_change_reader) {
2256 if (strcmp("READER_DEVNR",id) == 0) {
2257 setupdata.reader_devnr = atoi(value);
2258 }
2259 }
2260
2261 /* marker for a new device - must be first entry! */
2262 if (strcmp("WRITERREADER_DEVNR",id) == 0) {
2263 i = get_writerreaderdevs_index(atoi(value));
2264
2265 if (i == -1) {
2266 /* new device */
2267 if (rootconf || (setupdata.root_option_change_writer &&
2268 setupdata.root_option_change_reader)) {
2269
2270 count = get_last_writerreaderdevs_index() +1;
2271 writerreaderdevs[count]=g_new0(writerreader_devices_t,1);
2272 writerreaderdevs[count]->devnr = atoi(value);
2273 newadded = 1;
2274 } else {
2275 /* no permission to add a new device */
2276 /* ignore */
2277 count = -1;
2278 newadded = 0;
2279 }
2280 } else {
2281 /* we seen such a device already */
2282 count = i;
2283 newadded = 0;
2284 }
2285 }
2286
2287 /* only load such data for newly allocated devices */
2288 if (newadded) {
2289
2290 if (strcmp("WRITERREADER_DEVICESTR",id) == 0) {
2291 if (count >= 0 && writerreaderdevs[count]) {
2292 writerreaderdevs[count]->devicestr = g_strdup(value);
2293 }
2294 }
2295 if (strcmp("WRITERREADER_VENDOR",id) == 0) {
2296 if (count >= 0 && writerreaderdevs[count]) {
2297 strncpy(writerreaderdevs[count]->vendor, value, 9);
2298 }
2299 }
2300 if (strcmp("WRITERREADER_MODEL",id) == 0) {
2301 if (count >= 0 && writerreaderdevs[count]) {
2302 strncpy(writerreaderdevs[count]->model, value, 17);
2303 }
2304 }
2305 if (strcmp("WRITERREADER_REV",id) == 0) {
2306 if (count >= 0 && writerreaderdevs[count]) {
2307 strncpy(writerreaderdevs[count]->rev, value, 5);
2308 }
2309 }
2310 if (strcmp("WRITERREADER_READMAXSPEED",id) == 0) {
2311 if (count >= 0 && writerreaderdevs[count]) {
2312 writerreaderdevs[count]->writer_readmaxspeed = atoi(value);
2313 }
2314 }
2315 if (strcmp("WRITERREADER_CDRMAXSPEED",id) == 0) {
2316 if (count >= 0 && writerreaderdevs[count]) {
2317 writerreaderdevs[count]->writer_cdrmaxspeed = atoi(value);
2318 }
2319 }
2320 if (strcmp("WRITERREADER_DVDMAXSPEED",id) == 0) {
2321 if (count >= 0 && writerreaderdevs[count]) {
2322 writerreaderdevs[count]->writer_dvdmaxspeed = atoi(value);
2323 }
2324 }
2325 if (strcmp("WRITERREADER_WRITER_FLAGS",id) == 0) {
2326 if (count >= 0 && writerreaderdevs[count]) {
2327 writerreaderdevs[count]->writer_flags = g_strdup(value);
2328 }
2329 }
2330 if (strcmp("WRITERREADER_WRITER_MODES",id) == 0) {
2331 if (count >= 0 && writerreaderdevs[count]) {
2332 writerreaderdevs[count]->writer_modes = g_strdup(value);
2333 }
2334 }
2335 if (strcmp("WRITERREADER_IS_CDRWRITER",id) == 0) {
2336 if (count >= 0 && writerreaderdevs[count]) {
2337 writerreaderdevs[count]->is_cdrwriter = atoi(value);
2338 }
2339 }
2340 if (strcmp("WRITERREADER_IS_DVDREADER",id) == 0) {
2341 if (count >= 0 && writerreaderdevs[count]) {
2342 writerreaderdevs[count]->is_dvdreader = atoi(value);
2343 }
2344 }
2345 if (strcmp("WRITERREADER_IS_DVDWRITER",id) == 0) {
2346 if (count >= 0 && writerreaderdevs[count]) {
2347 writerreaderdevs[count]->is_dvdwriter = atoi(value);
2348 }
2349 }
2350 if (strcmp("WRITERREADER_SECTOR_SIZE",id) == 0) {
2351 if (count >= 0 && writerreaderdevs[count]) {
2352 writerreaderdevs[count]->sector_size = atoi(value);
2353 }
2354 }
2355 }
2356
2357 if (rootconf || newadded || setupdata.root_option_change_writeparam) {
2358
2359 if (strcmp("WRITERREADER_DRVMODE",id) == 0) {
2360 if (count >= 0 && writerreaderdevs[count]) {
2361 writerreaderdevs[count]->writer_drvmode = atoi(value);
2362 }
2363 }
2364 if (strcmp("WRITERREADER_MODE",id) == 0) {
2365 if (count >= 0 && writerreaderdevs[count]) {
2366 writerreaderdevs[count]->writer_mode = atoi(value);
2367 }
2368 }
2369 if (strcmp("WRITERREADER_SPEED",id) == 0) {
2370 if (count >= 0 && writerreaderdevs[count]) {
2371 writerreaderdevs[count]->writer_speed = atoi(value);
2372 }
2373 }
2374 if (strcmp("WRITERREADER_FIFO",id) == 0) {
2375 if (count >= 0 && writerreaderdevs[count]) {
2376 writerreaderdevs[count]->writer_fifo = atoi(value);
2377 }
2378 }
2379 }
2380
2381 if (rootconf || newadded || setupdata.root_option_change_readparam) {
2382
2383 if (strcmp("WRITERREADER_AUDIOREAD_INTERFACE",id) == 0) {
2384 if (count >= 0 && writerreaderdevs[count]) {
2385 writerreaderdevs[count]->audioread_interface = atoi(value);
2386 }
2387 }
2388 if (strcmp("WRITERREADER_AUDIOREAD_SPEED",id) == 0) {
2389 if (count >= 0 && writerreaderdevs[count]) {
2390 writerreaderdevs[count]->audioread_speed = atoi(value);
2391 }
2392 }
2393 if (strcmp("WRITERREADER_AUDIOREAD_OVERLAP",id) == 0) {
2394 if (count >= 0 && writerreaderdevs[count]) {
2395 writerreaderdevs[count]->audioread_overlap = atoi(value);
2396 }
2397 }
2398 if (strcmp("WRITERREADER_AUDIOREAD_SECTORBURST",id) == 0) {
2399 if (count >= 0 && writerreaderdevs[count]) {
2400 writerreaderdevs[count]->audioread_sectorburst = atoi(value);
2401 }
2402 }
2403 if (strcmp("WRITERREADER_AUDIOREAD_USEPARANOIA",id) == 0) {
2404 if (count >= 0 && writerreaderdevs[count]) {
2405 writerreaderdevs[count]->audioread_useparanoia = atoi(value);
2406 }
2407 }
2408 if (strcmp("WRITERREADER_AUDIOREAD_PARANOIARETRIES",id) == 0) {
2409 if (count >= 0 && writerreaderdevs[count]) {
2410 writerreaderdevs[count]->audioread_paranoiaretries = atoi(value);
2411 }
2412 }
2413 }
2414
2415 if (rootconf) {
2416 if (strcmp("IMAGE_DIRS",id) == 0) {
2417 setupdata.image_dirs = g_list_append(setupdata.image_dirs, g_strdup(value));
2418 }
2419 } else {
2420 /* user config - load to tmp list */
2421 if (strcmp("IMAGE_DIRS",id) == 0) {
2422 tmp_image_dirs = g_list_append(tmp_image_dirs, g_strdup(value));
2423 }
2424 }
2425 if (strcmp("DSP_DEVICE",id) == 0) {
2426 g_free(setupdata.dsp_device);
2427 setupdata.dsp_device = g_strdup(value);
2428 }
2429 if (strcmp("MIX_DEVICE",id) == 0) {
2430 g_free(setupdata.mix_device);
2431 setupdata.mix_device = g_strdup(value);
2432 }
2433 if (strcmp("NOTIFY_VIA",id) == 0) {
2434 setupdata.notify_via = atoi(value);
2435 }
2436 if (strcmp("NOTIFY_AT",id) == 0) {
2437 setupdata.notify_at = atoi(value);
2438 }
2439
2440 if (strcmp("CDDB_HOST",id) == 0) {
2441 g_free(setupdata.cddb_host);
2442 setupdata.cddb_host = g_strdup(value);
2443 }
2444 if (strcmp("CDDB_PORT",id) == 0) {
2445 setupdata.cddb_port = atoi(value);
2446 }
2447 if (strcmp("CDDB_PROXY_HOST",id) == 0) {
2448 g_free(setupdata.cddb_proxy_host);
2449 setupdata.cddb_proxy_host = g_strdup(value);
2450 }
2451 if (strcmp("CDDB_PROXY_PORT",id) == 0) {
2452 setupdata.cddb_proxy_port = atoi(value);
2453 }
2454 if (strcmp("CDDB_USE_HTTP",id) == 0) {
2455 setupdata.cddb_use_http = atoi(value);
2456 }
2457 if (strcmp("CDDB_USE_PROXY",id) == 0) {
2458 setupdata.cddb_use_proxy = atoi(value);
2459 }
2460
2461 if (rootconf || setupdata.root_option_change_logoptions) {
2462 if (strcmp("LOGFILE",id) == 0) {
2463 g_free(setupdata.logfile);
2464 setupdata.logfile = g_strdup(value);
2465 }
2466 if (strcmp("LOGLEVEL",id) == 0) {
2467 setupdata.loglevel = atoi(value);
2468 }
2469 }
2470
2471 if (strcmp("LANGUAGE",id) == 0) {
2472 g_free(setupdata.language);
2473 setupdata.language = g_strdup(value);
2474
2475 /* check if that value is an integer */
2476 if (atoi(value) != 0 || strcmp(value,"0") == 0) {
2477 /* it is, so set empty language */
2478 /* (we want to be backward compatible) */
2479 g_free(setupdata.language);
2480 setupdata.language = g_strdup("");
2481 }
2482 }
2483
2484 if (strcmp("OPTION_TOOLTIPS",id) == 0) {
2485 setupdata.option_tooltips = atoi(value);
2486 }
2487 if (strcmp("OPTION_AUTORAISE",id) == 0) {
2488 setupdata.option_autoraise = atoi(value);
2489 }
2490 if (strcmp("OPTION_SAVEPOS",id) == 0) {
2491 setupdata.option_savepos = atoi(value);
2492 }
2493 if (strcmp("OPTION_PERSONIMAGE",id) == 0) {
2494 setupdata.option_personimage = atoi(value);
2495 }
2496 if (strcmp("OPTION_OVERWRITEWARN",id) == 0) {
2497 setupdata.option_overwritewarn = atoi(value);
2498 }
2499 if (strcmp("OPTION_AUTODELETE",id) == 0) {
2500 setupdata.option_autodelete = atoi(value);
2501 }
2502 if (strcmp("OPTION_TITLEPROGRESS",id) == 0) {
2503 setupdata.option_titleprogress = atoi(value);
2504 }
2505 if (strcmp("OPTION_DISPLAYCDTEXT",id) == 0) {
2506 setupdata.option_displaycdtext = atoi(value);
2507 }
2508 if (strcmp("OPTION_SELECTIONMODE",id) == 0) {
2509 setupdata.option_selectionmode = atoi(value);
2510 }
2511 if (strcmp("PRODVD_KEY",id) == 0) {
2512 /* dont overwrite evtuelly set value with empty key */
2513 if (strcmp(value,"") != 0) {
2514 g_free(setupdata.ProDVDkey);
2515 setupdata.ProDVDkey = g_strdup(value);
2516 }
2517 }
2518 if (setupdata.option_savepos) {
2519 if (strcmp("GEOMETRY_MAINWINDOW_X",id) == 0) {
2520 setupdata.mainwindow.x = atoi(value);
2521 }
2522 if (strcmp("GEOMETRY_MAINWINDOW_Y",id) == 0) {
2523 setupdata.mainwindow.y = atoi(value);
2524 }
2525 if (strcmp("GEOMETRY_MAINWINDOW_WIDTH",id) == 0) {
2526 setupdata.mainwindow.width = atoi(value);
2527 }
2528 if (strcmp("GEOMETRY_MAINWINDOW_HEIGHT",id) == 0) {
2529 setupdata.mainwindow.height = atoi(value);
2530 }
2531
2532 if (strcmp("GEOMETRY_BURNWINDOW_X",id) == 0) {
2533 setupdata.burnwindow.x = atoi(value);
2534 }
2535 if (strcmp("GEOMETRY_BURNWINDOW_Y",id) == 0) {
2536 setupdata.burnwindow.y = atoi(value);
2537 }
2538 if (strcmp("GEOMETRY_BURNWINDOW_WIDTH",id) == 0) {
2539 setupdata.burnwindow.width = atoi(value);
2540 }
2541 if (strcmp("GEOMETRY_BURNWINDOW_HEIGHT",id) == 0) {
2542 setupdata.burnwindow.height = atoi(value);
2543 }
2544 }
2545
2546 /* do load the following information only when root */
2547 if (rootconf) {
2548 if (strcmp("ROOT_USERS_ACCESS",id) == 0) {
2549 setupdata.root_users_access = atoi(value);
2550 }
2551 if (strcmp("ROOT_USERS_LISTS",id) == 0) {
2552 setupdata.root_users_lists = g_list_append(setupdata.root_users_lists, g_strdup(value));
2553 }
2554 if (strcmp("ROOT_HOSTS_ACCESS",id) == 0) {
2555 setupdata.root_hosts_access = atoi(value);
2556 }
2557 if (strcmp("ROOT_HOSTS_LISTS",id) == 0) {
2558 setupdata.root_hosts_lists = g_list_append(setupdata.root_hosts_lists, g_strdup(value));
2559 }
2560
2561 if (strcmp("ROOT_OPTION_CHANGE_WRITER",id) == 0) {
2562 setupdata.root_option_change_writer = atoi(value);
2563 }
2564 if (strcmp("ROOT_OPTION_CHANGE_WRITEPARAM",id) == 0) {
2565 setupdata.root_option_change_writeparam = atoi(value);
2566 }
2567 if (strcmp("ROOT_OPTION_CHANGE_READER",id) == 0) {
2568 setupdata.root_option_change_reader = atoi(value);
2569 }
2570 if (strcmp("ROOT_OPTION_CHANGE_READPARAM",id) == 0) {
2571 setupdata.root_option_change_readparam = atoi(value);
2572 }
2573 if (strcmp("ROOT_OPTION_CHANGE_IMAGEDIRS",id) == 0) {
2574 setupdata.root_option_change_imagedirs = atoi(value);
2575 }
2576 if (strcmp("ROOT_OPTION_CHANGE_LOGOPTIONS",id) == 0) {
2577 setupdata.root_option_change_logoptions = atoi(value);
2578 }
2579 }
2580 }
2581 /* now handle image dirs */
2582 if (!rootconf) {
2583 /* are we allowed to change image dirs? */
2584 if (setupdata.root_option_change_imagedirs) {
2585 /* had we configured some yet? */
2586 if (g_list_length(tmp_image_dirs) > 0) {
2587 /* use user one */
2588 copy_glist(&setupdata.image_dirs,
2589 tmp_image_dirs);
2590 }
2591 }
2592 }
2593
2594 /* free temporary list */
2595 free_glist(&tmp_image_dirs);
2596
2597 if (fclose(fd) != 0) {
2598 /* error closing file */
2599 return 1;
2600 }
2601
2602 return 0;
2603 }
2604
2605
2606 /* parse a detailed toc line */
2607
parse_toc_line(gchar * line)2608 static void parse_toc_line(gchar *line) {
2609 gchar tmp[MAXLINE];
2610 gchar tmp2[MAXLINE];
2611 gchar tmp3[MAXLINE];
2612 gchar old_cddb_title[MAXLINE];
2613 gchar old_cdtext_title[MAXLINE];
2614 gchar old_cdtext_artist[MAXLINE];
2615 gchar *p1;
2616 gint min,sec,frm;
2617 gint ret;
2618
2619 /* to much tracks? */
2620 if (tocnr >= MAXTRACKS) {
2621 g_error("over %d tracks in toc\n",MAXTRACKS);
2622 }
2623
2624 strcpy(old_cddb_title,"");
2625 strcpy(old_cdtext_title,"");
2626 strcpy(old_cdtext_artist,"");
2627
2628 /* allocate memory for new line (free first old memory)*/
2629 if (trackinfo[tocnr] != NULL) {
2630 g_free(trackinfo[tocnr]->volname);
2631
2632 /* backup old cdtext */
2633 if (trackinfo[tocnr]->title) {
2634 strncpy(old_cdtext_title, trackinfo[tocnr]->title, MAXLINE);
2635 }
2636 g_free(trackinfo[tocnr]->title);
2637 /* backup old cdtext */
2638 if (trackinfo[tocnr]->artist) {
2639 strncpy(old_cdtext_artist, trackinfo[tocnr]->artist, MAXLINE);
2640 }
2641 g_free(trackinfo[tocnr]->artist);
2642
2643 /* backup old cddb-title */
2644 if (trackinfo[tocnr]->cddb_ttitle != NULL) {
2645 strncpy(old_cddb_title, trackinfo[tocnr]->cddb_ttitle, MAXLINE);
2646 }
2647 g_free(trackinfo[tocnr]->cddb_ttitle);
2648 g_free(trackinfo[tocnr]);
2649 }
2650 trackinfo[tocnr] = g_new0(track_info_t,1);
2651
2652 /* when the cd is still the same as last time, restore cddb-title */
2653 if (cd_is_still_the_same == 1) {
2654 /* got a backuped title? */
2655 if (strcmp(old_cddb_title,"") != 0) {
2656 trackinfo[tocnr]->cddb_ttitle = g_strdup(old_cddb_title);
2657 }
2658 }
2659
2660 /* now we are prepared to fill structure */
2661 strcpy(tmp,line+1);
2662 p1 = strtok(tmp,":");
2663 if (p1 == NULL) {
2664 g_error("Unexpected output in cdda2wav toc-output\n");
2665 }
2666 trackinfo[tocnr]->track_nr = atoi(p1);
2667 trackinfo[tocnr]->isosize = -1;
2668
2669 /* reststring into tmp2 - strip to remove leading spaces */
2670 p1 = strtok(NULL,"");
2671 strcpy(tmp2,p1);
2672 strip_string(tmp2);
2673
2674 p1 = strtok(tmp2," ");
2675 trackinfo[tocnr]->start_sec = atoi(p1);
2676
2677 p1 = strtok(NULL,"");
2678 if (p1 == NULL) {
2679 g_error("Unexpected output in cdda2wav toc-output\n");
2680 }
2681 strcpy(tmp,p1);
2682 strip_string(tmp);
2683
2684 /* now get tracklength - convert to frames */
2685 p1 = strtok(tmp," ");
2686 sscanf(p1,"%d:%d.%d",&min,&sec,&frm);
2687 trackinfo[tocnr]->size = (min*60+sec)*75 + frm;
2688
2689 /* tracktype */
2690 p1 = strtok(NULL," ");
2691 if (strncmp(p1,"data",4) == 0) {
2692 /* data-track */
2693 trackinfo[tocnr]->type = 0;
2694
2695 p1 = strtok(NULL," ");
2696 if (strncmp(p1,"uninterrupted",13) == 0) {
2697 trackinfo[tocnr]->rec_type = 1;
2698 } else {
2699 trackinfo[tocnr]->rec_type = 0;
2700 }
2701
2702 p1 = strtok(NULL," ");
2703 if (strncmp(p1,"copydenied",10) == 0) {
2704 trackinfo[tocnr]->copyperm = 0;
2705 } else {
2706 trackinfo[tocnr]->copyperm = 1;
2707 }
2708 if (cd_is_still_the_same == 1) {
2709 /* use cached cd-text */
2710 trackinfo[tocnr]->title = g_strdup(old_cdtext_title);
2711 trackinfo[tocnr]->artist = g_strdup(old_cdtext_artist);
2712 }
2713 } else {
2714 /* audio-track */
2715 trackinfo[tocnr]->type = 1;
2716
2717 p1 = strtok(NULL," ");
2718 if (strncmp(p1,"linear",6) == 0) {
2719 trackinfo[tocnr]->preemp = 0;
2720 } else {
2721 trackinfo[tocnr]->preemp = 1;
2722 }
2723
2724 p1 = strtok(NULL," ");
2725 if (strncmp(p1,"copydenied",10) == 0) {
2726 trackinfo[tocnr]->copyperm = 0;
2727 } else {
2728 trackinfo[tocnr]->copyperm = 1;
2729 }
2730
2731 p1 = strtok(NULL," ");
2732 if (strncmp(p1,"stereo",6) == 0) {
2733 trackinfo[tocnr]->stereo = 1;
2734 } else {
2735 trackinfo[tocnr]->stereo = 0;
2736 }
2737
2738 p1 = strtok(NULL," ");
2739 p1 = strtok(NULL,"");
2740 if (p1) {
2741 strcpy(tmp2,p1);
2742 strip_string(tmp2);
2743 ret = decode_title_artist(tmp2,tmp,tmp3);
2744 if (ret != 0) {
2745 g_error("got unexpected artist/title\n");
2746 }
2747
2748 if (cd_is_still_the_same == 1) {
2749 if (tmp[0] == '\0') {
2750 /* no new data, use cached */
2751 trackinfo[tocnr]->title = g_strdup(old_cdtext_title);
2752 } else {
2753 trackinfo[tocnr]->title = g_strdup(tmp);
2754 }
2755 if (tmp3[0] == '\0') {
2756 /* no new data, use cached */
2757 trackinfo[tocnr]->artist = g_strdup(old_cdtext_artist);
2758 } else {
2759 trackinfo[tocnr]->artist = g_strdup(tmp3);
2760 }
2761 } else {
2762 trackinfo[tocnr]->title = g_strdup(tmp);
2763 trackinfo[tocnr]->artist = g_strdup(tmp3);
2764 }
2765 } else {
2766 trackinfo[tocnr]->title = g_strdup("");
2767 trackinfo[tocnr]->artist = g_strdup("");
2768 }
2769 }
2770
2771
2772 tocnr++;
2773 }
2774
2775
2776 /* print memory-structure with toc-data (debug purposes) */
2777
print_cdinfo()2778 static void print_cdinfo() {
2779 gint i;
2780 gchar *p1, *p2, *p3, *p4;
2781 gchar tmp[] = "(NULL)";
2782
2783 dodebug(2,"------ cdinfo-structure -----\n");
2784 dodebug(2,"nr_tracks: %d\n",cdinfo.nr_tracks);
2785 dodebug(2,"total_size: %d\n",cdinfo.total_size);
2786 dodebug(2,"cddb_discid: %s\n",cdinfo.cddb_discid);
2787 dodebug(2,"have_cdtext: %d, have_cdextra: %d\n",cdinfo.have_cdtext,
2788 cdinfo.have_cdextra);
2789 if (cdinfo.title != NULL && cdinfo.artist != NULL) {
2790 dodebug(2,"title/artist: %s/%s\n",cdinfo.title,cdinfo.artist);
2791 } else {
2792 dodebug(2,"title/artist: (NULL)/(NULL)\n");
2793 }
2794 if (cdinfo.cddb_dtitle != NULL) {
2795 dodebug(2,"cddb_dtitle: %s\n",cdinfo.cddb_dtitle);
2796 } else {
2797 dodebug(2,"cddb_dtitle: (NULL)\n");
2798 }
2799 dodebug(2,"leadout: %d\n", cdinfo.leadout);
2800
2801 for (i = 0; i < cdinfo.nr_tracks; i++) {
2802
2803 dodebug(2,"track: %d start: %d size: %d\n",trackinfo[i]->track_nr,
2804 trackinfo[i]->start_sec, trackinfo[i]->size);
2805 dodebug(2," type: %d, rec_type: %d, preemp: %d, copyperm: %d, stereo: %d\n",
2806 trackinfo[i]->type, trackinfo[i]->rec_type,
2807 trackinfo[i]->preemp, trackinfo[i]->copyperm,
2808 trackinfo[i]->stereo);
2809 /* check if we have any null-pointers lying around */
2810 p1 = trackinfo[i]->title;
2811 p2 = trackinfo[i]->artist;
2812 p3 = trackinfo[i]->cddb_ttitle;
2813 p4 = trackinfo[i]->volname;
2814 if (p1 == NULL) p1 = tmp;
2815 if (p2 == NULL) p2 = tmp;
2816 if (p3 == NULL) p3 = tmp;
2817 if (p4 == NULL) p4 = tmp;
2818
2819 dodebug(2," title/artist: %s/%s cddb_title: %s volname: %s\n",
2820 p1, p2, p3, p4);
2821 }
2822 }
2823
2824
2825 /* interpret line for line the output of cdda2wav */
2826
parse_toc(gchar * line)2827 static gint parse_toc(gchar *line) {
2828 gchar tmp[MAXLINE];
2829 gchar tmp2[MAXLINE];
2830 gchar tmp3[MAXLINE];
2831 gchar *p,*p1;
2832 gint min,sec,frm;
2833 gint ret;
2834 gint mmaperror;
2835
2836 mmaperror = 0;
2837
2838 /* initial state */
2839 if (tocstate == 0) {
2840 /* mmap error? */
2841 if (strstr(line,"annot get mmap for")) {
2842 mmaperror = 1;
2843 }
2844
2845 /* first look for "Tracks" line */
2846 if (strncmp(line,"Tracks:",7) == 0) {
2847 strcpy(tmp,line+7);
2848 p1 = strtok(tmp," ");
2849 strcpy(tmp2,p1);
2850 cdinfo.nr_tracks = atoi(tmp2);
2851 p1 = strtok(NULL,"");
2852 strcpy(tmp2,p1);
2853 sscanf(tmp2,"%d:%d.%d",&min,&sec,&frm);
2854 cdinfo.total_size = (min*60+sec)*75 + frm;
2855 }
2856 if (strncmp(line,"CDINDEX",7) == 0) {
2857 /* we dont support cdindex right now */
2858 ;
2859 }
2860 if (strncmp(line,"CDDB",4) == 0) {
2861 strcpy(tmp,line+15);
2862 strip_string(tmp);
2863 strcpy(cdinfo.cddb_discid,tmp);
2864
2865 /* check if the cd we have in the drive is the same
2866 as the last cd we got */
2867 if (strcmp(cdinfo_cddb_title_bak, cdinfo.cddb_discid) == 0) {
2868 cd_is_still_the_same = 1;
2869 }
2870
2871 /* finished with state 0 */
2872 tocstate = 1;
2873 }
2874
2875 /* get next line from output */
2876 return mmaperror;
2877 }
2878
2879 /* cd-text state */
2880 if (tocstate == 1) {
2881 if (strncmp(line,"CD-Text: detected",17) == 0) {
2882 cdinfo.have_cdtext = 1;
2883 }
2884 if (strncmp(line,"CD-Text: not detected",21) == 0) {
2885 cdinfo.have_cdtext = 0;
2886 }
2887
2888 /* ignore any cd-text-output for now */
2889 ;
2890
2891 if (strncmp(line,"CD-Extra: ",10) == 0) {
2892 /* see this as endmarker of cd-text section */
2893 tocstate = 2;
2894 }
2895
2896 /* dont return here because we may need the current line */
2897 }
2898
2899 /* cd-extra state */
2900 if (tocstate == 2) {
2901 if (strncmp(line,"CD-Extra: detected",18) == 0) {
2902 cdinfo.have_cdextra = 1;
2903 }
2904 if (strncmp(line,"CD-Extra: not detected",22) == 0) {
2905 cdinfo.have_cdextra = 0;
2906 }
2907
2908 /* ignore any cd-extra-output for now */
2909 ;
2910
2911 if (strstr(line,"Album title:") != NULL) {
2912 /* see this as endmarker of cd-extra section */
2913 tocstate = 3;
2914 }
2915 /* dont return here because we may need the current line */
2916 }
2917
2918 /* toc-listing mode */
2919 if (tocstate == 3) {
2920 if ((p = strstr(line,"Album title:")) != NULL) {
2921 strcpy(tmp,p+13);
2922 strip_string(tmp);
2923 ret = decode_title_artist(tmp,tmp2,tmp3);
2924 if (ret != 0) {
2925 g_error("got unexpected artist/title\n");
2926 }
2927 g_free(cdinfo.title);
2928 cdinfo.title = g_strdup(tmp2);
2929 g_free(cdinfo.artist);
2930 cdinfo.artist = g_strdup(tmp3);
2931 }
2932
2933 /* now the most complex part: the toc-list itself */
2934 if (line[0] == 'T' && line[3] == ':') {
2935 parse_toc_line(line);
2936 }
2937
2938 if (strncmp(line,"Leadout:",8) == 0) {
2939 strcpy(tmp,line+8);
2940 strip_string(tmp);
2941 cdinfo.leadout = atoi(tmp);
2942 }
2943 }
2944
2945 return 0;
2946 }
2947
2948
2949 /* called when reading the TOC of ATAPI cdroms takes to long */
2950
getcdtoc_atapi_timeout_func(gpointer data)2951 static gint getcdtoc_atapi_timeout_func(gpointer data) {
2952
2953 getcdtoc_atapi_timeout_dialog = show_dialog_wait(ICO_INFO,
2954 _("Checking drive for a medium.\n\nUsing scsi-emulation for that drive would speed up\nthis considerably. Please note that inserting a\nmedium would also reduce the wait time."));
2955
2956 return (FALSE);
2957 }
2958
2959
getcdtoc_out(gpointer data,gint source,GdkInputCondition cond)2960 static void getcdtoc_out(gpointer data, gint source, GdkInputCondition cond) {
2961 gint n;
2962 gint ret;
2963 gchar line[MAXLINE];
2964
2965
2966 /* read output of getcdtoc */
2967 n = read_line_wait(source, line, MAXLINE);
2968
2969 /* getcdtoc finished */
2970 if (n <= 0) {
2971 gtk_input_remove(readcdda_callback);
2972
2973 /* pick up return status of child */
2974 wait(&ret);
2975
2976 /* tell our caller that we are done here */
2977 read_done = WEXITSTATUS(ret);
2978
2979 return;
2980 }
2981
2982 dodebug(10,"readtoc: %s\n", line);
2983
2984 count_mmaperror += parse_toc(line);
2985 }
2986
2987
2988 /* call cdda2wav -J to get the cd-toc */
2989 /* add ATAPI long-delay warning window */
2990
get_cd_toc(gint devnr)2991 void get_cd_toc(gint devnr) {
2992 gchar line[MAXLINE];
2993 gchar tmp[MAXLINE];
2994 gchar tmp2[MAXLINE];
2995 gint ret, dvdsize, read_out;
2996 gchar old_cdtext_title[MAXLINE];
2997 gchar old_cdtext_artist[MAXLINE];
2998 gint getcdtoc_timeout;
2999
3000 /* get bus,id,lun string */
3001 if (convert_devnr2busid(devnr,tmp) != 0) {
3002 g_error("non existing cdrom?");
3003 }
3004
3005 getcdtoc_atapi_timeout_dialog = NULL;
3006 getcdtoc_timeout = 0;
3007
3008 /* ATAPI device? (only on linux) */
3009 if (strstr(tmp, "ATAPI")) {
3010 /* if it does take longer than 5 seconds, display warning */
3011 getcdtoc_timeout = gtk_timeout_add(5000,
3012 getcdtoc_atapi_timeout_func, NULL);
3013 }
3014
3015 /* check if cd is loaded */
3016 if (!check_medium_loaded(devnr)) {
3017 /* not loaded */
3018 cdinfo.nr_tracks = -1;
3019
3020 if (getcdtoc_timeout) {
3021 /* remove timeout, if it did not kick in yet */
3022 gtk_timeout_remove(getcdtoc_timeout);
3023 }
3024 if (getcdtoc_atapi_timeout_dialog) {
3025 /* and remove the dialog wait window */
3026 show_dialog_wait_remove(getcdtoc_atapi_timeout_dialog);
3027 }
3028
3029 return;
3030 }
3031
3032 cdinfo.have_cdtext = -1;
3033 cdinfo.have_cdextra = -1;
3034 cdinfo.nr_tracks = -1;
3035
3036 read_done = 999;
3037 tocstate = 0;
3038 tocnr = 0;
3039 cd_is_still_the_same = 0;
3040 count_mmaperror = 0;
3041
3042
3043 /* backup cddb-value to check if the new cd is the same as
3044 the last we read */
3045 strncpy(cdinfo_cddb_title_bak, cdinfo.cddb_discid, MAXLINE);
3046
3047 /* backup current cd-text album info */
3048 if (cdinfo.title) {
3049 strncpy(old_cdtext_title, cdinfo.title, MAXLINE);
3050 } else {
3051 strcpy(old_cdtext_title, "");
3052 }
3053 if (cdinfo.artist) {
3054 strncpy(old_cdtext_artist, cdinfo.artist, MAXLINE);
3055 } else {
3056 strcpy(old_cdtext_artist, "");
3057 }
3058
3059 /* build command line */
3060 get_wrap_path("CDDA2WAV",tmp2);
3061 g_snprintf(line,MAXLINE,"%s -D \"%s\" -J -g -Q -H -v toc,summary,sectors,titles", tmp2,tmp);
3062
3063 dodebug(1,"spawning: %s\n", line);
3064
3065 readcdda_pid = full_dpl_pipe3(NULL,NULL,&read_out,line,0);
3066 readcdda_pid2 = -1;
3067
3068 fcntl(read_out, F_SETFL, O_NONBLOCK);
3069
3070 readcdda_callback = gdk_input_add(read_out, GDK_INPUT_READ,
3071 (GdkInputFunction) getcdtoc_out, NULL);
3072
3073 /* now wait until toc is read */
3074 while (read_done == 999) {
3075 wait_and_process_events();
3076 }
3077
3078 close(read_out);
3079
3080 ret = read_done;
3081
3082 /* error while reading tracks? */
3083 if (ret != 0 && cdinfo.nr_tracks != tocnr) {
3084 cdinfo.nr_tracks = -2;
3085 }
3086
3087 /* cd loaded but not readable = empty recordable? */
3088 if (ret != 0 && cdinfo.nr_tracks < 1 ) {
3089 cdinfo.nr_tracks = -2;
3090 }
3091
3092 /* if cd changed, clear out cddb_dtitle */
3093 if (cd_is_still_the_same == 0) {
3094 g_free(cdinfo.cddb_dtitle);
3095 cdinfo.cddb_dtitle = NULL;
3096 } else {
3097 /* cd stayed the same, restore album cd-text */
3098 if (cdinfo.title[0] == '\0' && old_cdtext_title[0] != '\0') {
3099 g_free(cdinfo.title);
3100 cdinfo.title = g_strdup(old_cdtext_title);
3101 }
3102 if (cdinfo.artist[0] == '\0' && old_cdtext_artist[0] != '\0') {
3103 g_free(cdinfo.artist);
3104 cdinfo.artist = g_strdup(old_cdtext_artist);
3105 }
3106 }
3107
3108 /* now a workaround for a broken cdda2wav when it comes to
3109 read the toc of a DVD - use cdrecord -toc instead */
3110 if (cdinfo.nr_tracks == 1 && (cdinfo.leadout == 1151850 || cdinfo.leadout == 1151849 || cdinfo.leadout == 449849)) {
3111 /* this is slow, so only use it in that rare case */
3112 dvdsize = get_cdrecord_toc(devnr);
3113 if (dvdsize > 0) {
3114 /* overwrite faulty values by the real ones */
3115 cdinfo.leadout = dvdsize;
3116 trackinfo[0]->size = dvdsize;
3117
3118 /* 1152000 is 256:00.00 which is not right */
3119 /* 449999 is 100:00.00 -1 frame */
3120 /* if (cdinfo.total_size == 1152000 || cdinfo.total_size == 1151999 || cdinfo.total_size == 449999) {
3121 cdinfo.total_size = dvdsize + 150;
3122 } */
3123 cdinfo.total_size = dvdsize + 150;
3124 }
3125 }
3126
3127 /* have we hit the mmap error? */
3128 if (count_mmaperror > 0) {
3129 ret = show_dialog(ICO_WARN, _("Warning: The cdrtools binaries you have installed are\nnot compatible with your system. You will NOT be\nable to read or write CDs. Please read the FAQ\non www.xcdroast.org for more information."), T_ANYWAY, _("Exit"), NULL, 1);
3130 if (ret == 1)
3131 gtk_exit(1);
3132 }
3133
3134 if (getcdtoc_timeout) {
3135 /* remove timeout, if it did not kick in yet */
3136 gtk_timeout_remove(getcdtoc_timeout);
3137 }
3138 if (getcdtoc_atapi_timeout_dialog) {
3139 /* and remove the dialog wait window */
3140 show_dialog_wait_remove(getcdtoc_atapi_timeout_dialog);
3141 }
3142
3143 if (debug) print_cdinfo();
3144
3145 }
3146
3147
3148 /* start subprocess and reroute stdin and stdout */
3149 /* use /bin/sh to spawn subprocess */
3150
full_dpl_pipe_shell(gint * out,gint * in,gchar * cmd)3151 pid_t full_dpl_pipe_shell(gint *out, gint *in, gchar *cmd) {
3152 gint fd1[2], fd2[2];
3153 pid_t pid;
3154
3155 if (pipe(fd1) <0 || pipe(fd2) <0) {
3156 g_error("pipe error\n");
3157 }
3158
3159 if (( pid = fork()) < 0) {
3160 g_error("fork error\n");
3161 } else
3162 if (pid > 0) {
3163 /* parent */
3164 close(fd1[0]);
3165 close(fd2[1]);
3166
3167 /* return new stdout/stdin of child */
3168 if (in != NULL)
3169 *in = fd1[1];
3170 else
3171 close(fd1[1]);
3172
3173 if (out != NULL)
3174 *out = fd2[0];
3175 else
3176 close(fd2[0]);
3177
3178 } else {
3179
3180 /* needed for correct rights in nonroot mode */
3181 /* fix_guid(); */
3182
3183 /* child */
3184 close(fd1[1]);
3185 close(fd2[0]);
3186
3187 /* reroute stdin from child */
3188 if (fd1[0] != STDIN_FILENO) {
3189 if (dup2(fd1[0], STDIN_FILENO) != STDIN_FILENO) {
3190 g_error("dup2 error on stdin\n");
3191 }
3192 close(fd1[0]);
3193 }
3194 /* reroute stdout from child */
3195 if (fd2[1] != STDOUT_FILENO) {
3196 if (dup2(fd2[1], STDOUT_FILENO) != STDOUT_FILENO) {
3197 g_error("dup2 error on stdout\n");
3198 }
3199 close(fd2[1]);
3200 }
3201
3202 /* startup child */
3203 if (execl("/bin/sh", "sh", "-c", cmd ,(void *)NULL) < 0) {
3204 g_error("execl error\n");
3205 }
3206
3207 }
3208
3209 return(pid);
3210 }
3211
3212
3213 /* rebuild a cmdline-string into a list of arguments..handle quotes and
3214 escaped chars nicely */
3215
rebuild_cmdline(char ** arglist,gchar * cmd,gchar * callpath)3216 static void rebuild_cmdline(char **arglist, gchar *cmd, gchar *callpath) {
3217 gchar tmp[MAXLINE*10];
3218 gchar *p;
3219 gint n, count, start, in_quotes;
3220 gchar oldc, c;
3221
3222 n = 0;
3223 count = 0;
3224 start = 0;
3225 in_quotes = 0;
3226 oldc = '\0';
3227 for (n = 0; n <= strlen(cmd); n++) {
3228 c = cmd[n];
3229
3230 /* quotes found? search for closing quote */
3231 /* ignore escaped quotes */
3232 if (c == '\"' && oldc != '\\') {
3233 if (in_quotes == 0) {
3234 in_quotes = 1;
3235 } else {
3236 /* end-quote found */
3237 in_quotes = 0;
3238 }
3239 }
3240 oldc = c;
3241
3242 /* space is delimitor between args */
3243 if (in_quotes == 0 && (c == ' ' || c == '\0')) {
3244 strncpy(tmp,cmd+start,n-start);
3245 tmp[n-start] = '\0';
3246
3247 /* skip empty args */
3248 if (n-start == 0) {
3249 continue;
3250 }
3251 strip_string(tmp);
3252
3253 /* tmp does contain now our substr -
3254 remove surrounding quotes if any and
3255 remove any escaped-chars */
3256 if (tmp[0] == '\"') {
3257 p = tmp + 1;
3258 } else {
3259 p = tmp;
3260 }
3261
3262 if (tmp[strlen(tmp)-1] == '\"') {
3263 tmp[strlen(tmp)-1] = '\0';
3264 }
3265 escape_parse(p);
3266
3267 /* empty unquoted string? skip */
3268 if (p == tmp && strcmp(p,"") == 0) {
3269 continue;
3270 }
3271
3272 arglist[count] = g_strdup(p);
3273 count++;
3274 start = n+1;
3275 }
3276
3277 if (count >= MAXPIPEARGS) {
3278 g_error("Error: More than %d cmd arguments given\n",MAXPIPEARGS);
3279 }
3280 }
3281
3282 /* now remove path from first argument */
3283 strncpy(callpath,arglist[0], MAXLINE);
3284 strncpy(tmp,arglist[0], MAXLINE*10);
3285 p = rindex(tmp,'/');
3286 if (p != NULL) {
3287 g_free(arglist[0]);
3288 arglist[0] = g_strdup(p+1);
3289 }
3290
3291 /* now arglist is finished */
3292
3293 /* output generated argument-list */
3294 if (debug) {
3295 dodebug(11,"----- created argument array for execv -----\n");
3296 count = 0;
3297 dodebug(11,":%s:\n",callpath);
3298 while(arglist[count]) {
3299 dodebug(11,":%s:\n",arglist[count]);
3300 count++;
3301 }
3302 }
3303 }
3304
3305
3306
3307 /* create a bidirectional pipe */
3308
my_s_pipe(gint fd[2],gint use_socketpair)3309 static gint my_s_pipe(gint fd[2], gint use_socketpair) {
3310
3311 if (use_socketpair == 1) {
3312 #if defined(HAVE_SOCKETPAIR) && HAVE_SOCKETPAIR == 1
3313 return (socketpair(AF_UNIX, SOCK_STREAM, 0, fd));
3314 #else
3315 /* socketpair not available - fallback */
3316 return (pipe(fd));
3317 #endif
3318 } else {
3319 return (pipe(fd));
3320 }
3321 }
3322
3323
3324 /* start subprocess and reroute stdin, stderr and stdout */
3325 /* does NOT use the shell as spawner */
3326
full_dpl_pipe3(gint * out,gint * in,gint * err,gchar * cmd,gint use_socketpair)3327 static pid_t full_dpl_pipe3(gint *out, gint *in, gint *err, gchar *cmd,
3328 gint use_socketpair) {
3329 gint fd1[2], fd2[2], fd3[2];
3330 gchar **arglist;
3331 gchar callpath[MAXLINE];
3332 pid_t pid;
3333 gint count;
3334
3335 /* rebuild cmdline to array of args for execv */
3336 arglist = g_new0(gchar *, MAXPIPEARGS);
3337 rebuild_cmdline(arglist, cmd, callpath);
3338
3339 /* do the pipe-stuff */
3340 if (my_s_pipe(fd1, use_socketpair) < 0 ||
3341 my_s_pipe(fd2, use_socketpair) < 0 ||
3342 my_s_pipe(fd3, use_socketpair) < 0) {
3343 g_error("pipe error\n");
3344 }
3345
3346 if (( pid = fork()) < 0) {
3347 g_error("fork error\n");
3348 } else
3349 if (pid > 0) {
3350 /* parent */
3351 close(fd1[0]);
3352 close(fd2[1]);
3353 close(fd3[1]);
3354
3355 /* return new stdout/stdin/stderr of child */
3356 if (in != NULL)
3357 *in = fd1[1];
3358 else
3359 close(fd1[1]);
3360
3361 if (out != NULL)
3362 *out = fd2[0];
3363 else
3364 close(fd2[0]);
3365
3366 if (err != NULL)
3367 *err = fd3[0];
3368 else
3369 close(fd3[0]);
3370 } else {
3371
3372 /* needed for correct rights in nonroot mode */
3373 /* fix_guid(); */
3374
3375 /* child */
3376 close(fd1[1]);
3377 close(fd2[0]);
3378 close(fd3[0]);
3379
3380 /* reroute stdin from child */
3381 if (fd1[0] != STDIN_FILENO) {
3382 if (dup2(fd1[0], STDIN_FILENO) != STDIN_FILENO) {
3383 g_error("dup2 error on stdin\n");
3384 }
3385 close(fd1[0]);
3386 }
3387 /* reroute stdout from child */
3388 if (fd2[1] != STDOUT_FILENO) {
3389 if (dup2(fd2[1], STDOUT_FILENO) != STDOUT_FILENO) {
3390 g_error("dup2 error on stdout\n");
3391 }
3392 close(fd2[1]);
3393 }
3394 /* reroute stderr from child */
3395 if (fd3[1] != STDERR_FILENO) {
3396 if (dup2(fd3[1], STDERR_FILENO) != STDERR_FILENO) {
3397 g_error("dup2 error on stderr\n");
3398 }
3399 close(fd3[1]);
3400 }
3401
3402 /* startup child */
3403 if (execv(callpath,arglist) < 0) {
3404 g_error("execv error\n");
3405 }
3406
3407 }
3408
3409 /* free arglist */
3410 count = 0;
3411 while(arglist[count]) {
3412 g_free(arglist[count]);
3413 count++;
3414 }
3415 g_free(arglist);
3416
3417 return(pid);
3418 }
3419
3420
3421 /* start two subprocesses and connect stdout of the first with stdin
3422 of the second (proc1 | proc2) and reroute stdin and stderr of the
3423 first and stdout and stderr of the second */
3424 /* returns pidnr1 and pidnr2 */
3425
full_dpl_pipe4(pid_t * pidnr1,pid_t * pidnr2,gint * in1,gint * err1,gchar * cmd,gint * out2,gint * err2,gchar * cmd2,gint use_socketpair)3426 static void full_dpl_pipe4(pid_t *pidnr1, pid_t *pidnr2, gint *in1, gint *err1,
3427 gchar *cmd, gint *out2, gint *err2, gchar *cmd2,
3428 gint use_socketpair) {
3429 gint fd1[2], fd2[2], fd3[2], fd4[2], pipefd[2];
3430 gchar **arglist;
3431 gchar **arglist2;
3432 gchar callpath[MAXLINE];
3433 gchar callpath2[MAXLINE];
3434 pid_t pid, pid2;
3435 gint count;
3436
3437 /* rebuild cmdline to array of args for execv */
3438 arglist = g_new0(gchar *, MAXPIPEARGS);
3439 arglist2 = g_new0(gchar *, MAXPIPEARGS);
3440 rebuild_cmdline(arglist, cmd, callpath);
3441 rebuild_cmdline(arglist2, cmd2, callpath2);
3442
3443 /* do the pipe-stuff */
3444 if (my_s_pipe(fd1, use_socketpair) < 0 ||
3445 my_s_pipe(fd2, use_socketpair) < 0 ||
3446 my_s_pipe(fd3, use_socketpair) < 0 ||
3447 my_s_pipe(fd4, use_socketpair) < 0 ||
3448 my_s_pipe(pipefd, use_socketpair) < 0) {
3449 g_error("pipe error\n");
3450 }
3451
3452 /* fork for first process */
3453 if (( pid = fork()) < 0) {
3454 g_error("fork error\n");
3455 } else
3456 if (pid > 0) {
3457 /* parent */
3458 close(fd1[0]);
3459 close(fd2[1]);
3460 close(pipefd[1]);
3461
3462 /* return new fds of child */
3463 if (in1 != NULL)
3464 *in1 = fd1[1];
3465 else
3466 close(fd1[1]);
3467
3468 if (err1 != NULL)
3469 *err1 = fd2[0];
3470 else
3471 close(fd2[0]);
3472
3473 } else {
3474 /* needed for correct rights in nonroot mode */
3475 /* fix_guid(); */
3476
3477 /* child */
3478 close(fd1[1]);
3479 close(fd2[0]);
3480 close(pipefd[0]);
3481
3482 /* reroute stdin from child */
3483 if (fd1[0] != STDIN_FILENO) {
3484 if (dup2(fd1[0], STDIN_FILENO) != STDIN_FILENO) {
3485 g_error("dup2 error on stdin\n");
3486 }
3487 close(fd1[0]);
3488 }
3489
3490 /* reroute stderr from child */
3491 if (fd2[1] != STDERR_FILENO) {
3492 if (dup2(fd2[1], STDERR_FILENO) != STDERR_FILENO) {
3493 g_error("dup2 error on stderr\n");
3494 }
3495 close(fd2[1]);
3496 }
3497
3498 /* reroute stdout from child to second child */
3499 if (pipefd[1] != STDOUT_FILENO) {
3500 if (dup2(pipefd[1], STDOUT_FILENO) != STDOUT_FILENO) {
3501 g_error("dup2 error on stdout\n");
3502 }
3503 close(pipefd[1]);
3504 }
3505
3506 /* startup first child */
3507 if (execv(callpath,arglist) < 0) {
3508 g_error("execv error\n");
3509 }
3510 }
3511
3512
3513 /* fork for second process */
3514 if (( pid2 = fork()) < 0) {
3515 g_error("fork error\n");
3516 } else
3517 if (pid2 > 0) {
3518 /* parent */
3519 close(fd3[1]);
3520 close(fd4[1]);
3521 close(pipefd[0]);
3522
3523 /* return new fds of child */
3524 if (out2 != NULL)
3525 *out2 = fd3[0];
3526 else
3527 close(fd3[0]);
3528
3529 if (err2 != NULL)
3530 *err2 = fd4[0];
3531 else
3532 close(fd4[0]);
3533
3534 } else {
3535
3536 /* needed for correct rights in nonroot mode */
3537 /* fix_guid(); */
3538
3539 /* child */
3540 close(fd3[0]);
3541 close(fd4[0]);
3542 close(pipefd[1]);
3543
3544 /* reroute stdin from first child */
3545 if (pipefd[0] != STDIN_FILENO) {
3546 if (dup2(pipefd[0], STDIN_FILENO) != STDIN_FILENO) {
3547 g_error("dup2 error on stdin\n");
3548 }
3549 close(pipefd[0]);
3550 }
3551
3552 /* reroute stderr from child */
3553 if (fd4[1] != STDERR_FILENO) {
3554 if (dup2(fd4[1], STDERR_FILENO) != STDERR_FILENO) {
3555 g_error("dup2 error on stdout\n");
3556 }
3557 close(fd4[1]);
3558 }
3559
3560 /* reroute stdout from child to second child */
3561 if (fd3[1] != STDOUT_FILENO) {
3562 if (dup2(fd3[1], STDOUT_FILENO) != STDOUT_FILENO) {
3563 g_error("dup2 error on stdout\n");
3564 }
3565 close(fd3[1]);
3566 }
3567
3568 /* startup second child */
3569 if (execv(callpath2,arglist2) < 0) {
3570 g_error("execv error\n");
3571 }
3572 }
3573
3574 /* free arglists */
3575 count = 0;
3576 while(arglist[count]) {
3577 g_free(arglist[count]);
3578 count++;
3579 }
3580 g_free(arglist);
3581 count = 0;
3582 while(arglist2[count]) {
3583 g_free(arglist2[count]);
3584 count++;
3585 }
3586 g_free(arglist2);
3587
3588 /* return pids by call by reference */
3589 *pidnr1 = pid;
3590 *pidnr2 = pid2;
3591 }
3592
3593
3594 /* get the master-volume */
3595 /* return val 0..100 or -1 or error */
3596
query_mixer()3597 gint query_mixer() {
3598 #if !(defined(__MACH__) && defined(__APPLE__))
3599 gint mix;
3600 #endif
3601 #if defined(linux) || defined(__FreeBSD__)
3602 gint val;
3603 #endif
3604 #if defined(sun) || defined(__OpenBSD__)
3605 audio_info_t ainfo;
3606 #endif
3607 #ifdef hpux
3608 # ifndef hpux_alib
3609 struct audio_gain again;
3610 # endif
3611 #endif
3612
3613
3614 if (strcmp(setupdata.mix_device,"") == 0) {
3615 /* no mixer found - ignore */
3616 return -1;
3617 }
3618
3619 #if defined(linux) || defined(__FreeBSD__)
3620
3621 dodebug(10,"quering mixer %s\n", setupdata.mix_device);
3622 mix = open(setupdata.mix_device, O_RDWR);
3623 if (mix < 0) {
3624 g_warning("Can't open mixer-device %s\n", setupdata.mix_device);
3625 return -1;
3626 }
3627
3628 if (ioctl(mix,MIXER_READ(0),&val) == -1) {
3629 g_warning("Error reading mixer\n");
3630 return -1;
3631 }
3632
3633 close(mix);
3634
3635 /* average val of both channels */
3636 return ((val & 0x7f) + ((val >> 8) & 0x7f))/2;
3637
3638 #endif
3639 #if defined(sun) || defined(__OpenBSD__)
3640
3641 dodebug(10,"quering mixer %s\n", setupdata.mix_device);
3642 mix = open(setupdata.mix_device, O_RDONLY);
3643 if (mix < 0) {
3644 g_warning("Can't open mixer-device %s\n", setupdata.mix_device);
3645 return -1;
3646 }
3647
3648 if (ioctl(mix, AUDIO_GETINFO, &ainfo) == -1) {
3649 g_warning("Error reading mixer\n");
3650 return -1;
3651 }
3652
3653 close(mix);
3654
3655 return ((gint) ((gfloat) ainfo.play.gain / 2.55));
3656
3657 #endif
3658 #ifdef aix
3659 /* Due we are using the raw aix audio api, we */
3660 /* are not able to query the gain settings :-( */
3661 /* set the gain to the max. value and return 100 */
3662 memset ( & achange, '\0', sizeof (achange));
3663 memset ( & acontrol, '\0', sizeof (acontrol));
3664
3665 /* Initialise with the max gain =2147418112 */
3666 achange.balance = 0x3fff0000;
3667 achange.balance_delay = 0;
3668 achange.volume = 2147418112;
3669 achange.volume_delay = 0;
3670 achange.input = AUDIO_IGNORE;
3671 achange.output = AUDIO_IGNORE;
3672 achange.output = AUDIO_IGNORE;
3673 achange.treble = AUDIO_IGNORE;
3674 achange.bass = AUDIO_IGNORE;
3675 achange.pitch = AUDIO_IGNORE;
3676 achange.monitor = AUDIO_IGNORE;
3677 achange.dev_info = (char *) NULL;
3678 acontrol.ioctl_request = AUDIO_CHANGE;
3679 acontrol.position = 0;
3680 acontrol.request_info = (char *) & achange;
3681
3682 if ((mix = open(setupdata.mix_device, O_RDONLY)) == -1) {
3683 g_warning("Can't open mixer-device %s\n", setupdata.mix_device);
3684 return -1;
3685 }
3686 if (ioctl (mix, AUDIO_CONTROL, & acontrol) == -1) {
3687 g_warning("Error reading mixer\n");
3688 return -1;
3689 }
3690 close(mix);
3691
3692 return (100);
3693 #endif
3694 #ifdef hpux
3695 # ifndef hpux_alib
3696 dodebug(10,"quering mixer %s\n", setupdata.mix_device);
3697 if ((mix = open(setupdata.mix_device, O_RDONLY)) == -1) {
3698 g_warning("Can't open mixer-device %s\n", setupdata.mix_device);
3699 return -1;
3700 }
3701 if (ioctl(mix, AUDIO_GET_GAINS, &again) == -1) {
3702 g_warning("Error reading mixer\n");
3703 return -1;
3704 }
3705 close(mix);
3706 return ((gint) ((gfloat) (again.transmit_gain - AUDIO_OFF_GAIN)
3707 / (gfloat) (AUDIO_MAX_GAIN - AUDIO_OFF_GAIN) * 100.0));
3708 # else
3709 /* The audio tranmission gains are set by some */
3710 /* environment variables or a fancy program */
3711 /* like the AudioCP */
3712 return (0);
3713 # endif
3714 #endif
3715
3716 return 0;
3717 }
3718
3719
3720 /* set the master-volume */
3721 /* returns 0 on ok, -1 on error */
3722
set_mixer(gint val)3723 gint set_mixer(gint val) {
3724 #if !(defined(__MACH__) && defined(__APPLE__))
3725 gint mix;
3726 #endif
3727 #if defined(sun) || defined(__OpenBSD__)
3728 audio_info_t ainfo;
3729 #endif
3730 #ifdef aix
3731 audio_change achange;
3732 audio_control acontrol;
3733 #endif
3734 #ifdef hpux
3735 # ifndef hpux_alib
3736 struct audio_gain again;
3737 # endif
3738 #endif
3739
3740 if (strcmp(setupdata.mix_device,"") == 0) {
3741 /* no mixer found - ignore */
3742 return -1;
3743 }
3744
3745 #if defined(linux) || defined(__FreeBSD__)
3746
3747 dodebug(10,"setting mixer %s to %d\n", setupdata.mix_device, val);
3748 mix = open(setupdata.mix_device, O_RDWR);
3749 if (mix < 0) {
3750 g_warning("Can't open mixer-device\n");
3751 return -1;
3752 }
3753
3754 val |= val << 8;
3755 if (ioctl(mix, MIXER_WRITE(0), &val) == -1) {
3756 g_warning("Error writing mixer\n");
3757 return -1;
3758 }
3759
3760 close(mix);
3761
3762 #endif
3763 #if defined(sun) || defined(__OpenBSD__)
3764
3765 dodebug(10,"setting mixer %s to %d\n", setupdata.mix_device, val);
3766 mix = open(setupdata.mix_device, O_WRONLY);
3767 if (mix < 0) {
3768 g_warning("Can't open mixer-device %s\n", setupdata.mix_device);
3769 return -1;
3770 }
3771
3772 AUDIO_INITINFO(&ainfo);
3773 ainfo.play.gain = (gint) (2.55 * (gfloat) val);
3774
3775 if (ioctl(mix, AUDIO_SETINFO, &ainfo) == -1) {
3776 g_warning("Error writing mixer\n");
3777 return -1;
3778 }
3779
3780 close(mix);
3781 #endif
3782 #ifdef aix
3783 memset ( & achange, '\0', sizeof (achange));
3784 memset ( & acontrol, '\0', sizeof (acontrol));
3785
3786 /* Initialise with the max gain =2147418112 */
3787 achange.balance = AUDIO_IGNORE;
3788 achange.balance_delay = AUDIO_IGNORE;
3789 achange.volume = (long) (21474181.12 * (gfloat) val);
3790 achange.volume_delay = 0;
3791 achange.input = AUDIO_IGNORE;
3792 achange.output = AUDIO_IGNORE;
3793 achange.output = AUDIO_IGNORE;
3794 achange.treble = AUDIO_IGNORE;
3795 achange.bass = AUDIO_IGNORE;
3796 achange.pitch = AUDIO_IGNORE;
3797 achange.monitor = AUDIO_IGNORE;
3798 achange.dev_info = (char *) NULL;
3799 acontrol.ioctl_request = AUDIO_CHANGE;
3800 acontrol.position = 0;
3801 acontrol.request_info = (char *) & achange;
3802
3803 if ((mix = open(setupdata.mix_device, O_RDONLY)) == -1) {
3804 g_warning("Can't open mixer-device %s\n", setupdata.mix_device);
3805 return -1;
3806 }
3807 if (ioctl (mix, AUDIO_CONTROL, & acontrol) == -1) {
3808 g_warning("Error reading mixer\n");
3809 return -1;
3810 }
3811 close (mix);
3812 #endif
3813 #ifdef hpux
3814 # ifndef hpux_alib
3815 dodebug(10,"setting mixer %s to %d\n", setupdata.mix_device, val);
3816 if ((mix = open(setupdata.mix_device, O_RDWR)) == -1) {
3817 g_warning("Can't open mixer-device %s\n", setupdata.mix_device);
3818 return -1;
3819 }
3820 /* Query the receive/transmit/monitor gains */
3821 again.channel_mask = AUDIO_CHANNEL_0 | AUDIO_CHANNEL_1;
3822 ioctl(mix,AUDIO_GET_GAINS,&again);
3823
3824 /* Calculate the new transmit gain */
3825 again.cgain[0].transmit_gain = AUDIO_OFF_GAIN
3826 + (gfloat) ((AUDIO_MAX_GAIN - AUDIO_OFF_GAIN) * val) * 0.01;
3827 again.cgain[1].transmit_gain = again.cgain[0].transmit_gain;
3828 again.channel_mask = AUDIO_CHANNEL_0 | AUDIO_CHANNEL_1;
3829
3830 /* Set the new gains (only transmit gain actually changed) */
3831 if (ioctl(mix, AUDIO_SET_GAINS, &again) == -1) {
3832 g_warning("Error setting audio gain\n");
3833 return -1;
3834 }
3835 close(mix);
3836 # else
3837 /* The audio tranmission gains are set by some */
3838 /* environment variables or a fancy program */
3839 /* like the AudioCP */
3840 return 0;
3841 # endif
3842 #endif
3843
3844 return 0;
3845 }
3846
3847
3848 /* send SIGINT to a cdda2wav/readcd/cdrecord process (btw to its child)
3849 and hope that it terminates at it own */
3850
kill_readcdda()3851 void kill_readcdda() {
3852
3853 /* stop any timers watching for cdrecord output */
3854 if (cdrtimer) {
3855 gtk_timeout_remove(cdrtimer);
3856 cdrtimer = 0;
3857 }
3858
3859 if (readcdda_pid != -1) {
3860
3861 dodebug(2,"sending SIGINT to %d\n", (gint) readcdda_pid);
3862 kill(readcdda_pid, SIGINT);
3863 }
3864 if (readcdda_pid2 != -1) {
3865
3866 dodebug(2,"sending SIGINT to %d\n", (gint) readcdda_pid2);
3867 kill(readcdda_pid2, SIGINT);
3868 }
3869 }
3870
3871
3872 /* in bulk mode update the info-label of read tracks */
3873
update_bulk_readlabel()3874 static void update_bulk_readlabel() {
3875 gchar tmp[MAXLINE];
3876 gchar tmp2[MAXLINE];
3877 gint frms;
3878
3879 frms = writeparams.frames[read_tracknr];
3880 convert_frames2mbminstring(frms, tmp);
3881 g_snprintf(tmp2,MAXLINE,_("Reading audio track %d/%d [%s]"), read_tracknr,
3882 writeparams.nrtracks, tmp);
3883 gtk_label_set_text(GTK_LABEL(readtrack_info_label), tmp2);
3884 }
3885
3886
3887 /* parse output of cdda2wav and update sliders */
3888
read_cdda2wav_out(gpointer data,gint source,GdkInputCondition cond)3889 static void read_cdda2wav_out(gpointer data, gint source, GdkInputCondition cond) {
3890 gint n;
3891 gint ret;
3892 gchar line[MAXLINE];
3893 gchar tmp[MAXLINE];
3894 gchar tmp2[MAXLINE];
3895 gchar *p;
3896 gint val, tnr, bulk;
3897 gfloat pval, pval2;
3898
3899 /* called for bulk or not? */
3900 bulk = GPOINTER_TO_INT(data);
3901
3902 /* read output of cdda */
3903 n = read_line(source, line, MAXLINE);
3904
3905 /* cdda-finished? */
3906 if (n <= 0) {
3907 gtk_input_remove(readcdda_callback);
3908
3909 /* pick up return status of child */
3910 wait(&ret);
3911
3912 /* tell our caller that we are done here */
3913 read_done = WEXITSTATUS(ret);
3914 return;
3915 }
3916
3917 strip_string(line);
3918 dodebug(10,"cdda2wav: %s\n", line);
3919
3920 /* scanning for indexes? */
3921 if (strncmp(line,"index scan:", 11) == 0) {
3922 strcpy(tmp,line+11);
3923 p = strtok(tmp,".");
3924 if (p != NULL) {
3925 tnr = atoi(p);
3926 } else {
3927 tnr = 0;
3928 }
3929 g_snprintf(tmp,MAXLINE,_("Scanning track %d for indices..."),tnr);
3930 gtk_label_set_text(GTK_LABEL(readtrack_info_label),tmp);
3931 }
3932
3933 /* found indices? */
3934 if (strncmp(line,"track", 5) == 0) {
3935 strcpy(tmp,line);
3936 /* just output until first comma - looks nicer */
3937 p = strtok(tmp,",");
3938 if (p != NULL) {
3939 strcpy(tmp2,p);
3940 } else {
3941 strcpy(tmp2,tmp);
3942 }
3943 strcat(tmp2,"\n");
3944 convert_for_gtk2_textwidget(tmp2);
3945 gtk_text_insert(GTK_TEXT(readtrack_textview),
3946 fixedfont,NULL,NULL, tmp2, strlen(tmp2));
3947 }
3948
3949 /* scanning for MCN? */
3950 if (strncmp(line,"scanning for MCN", 16) == 0) {
3951 gtk_label_set_text(GTK_LABEL(readtrack_info_label),_("Scanning for MCN (Media Catalog Number)..."));
3952 }
3953
3954 /* scanning for ISRC? */
3955 if (strncmp(line,"scanning for ISRCs:", 19) == 0) {
3956 strcpy(tmp,line+20);
3957 p = strtok(tmp,".");
3958 if (p != NULL) {
3959 tnr = atoi(p);
3960 } else {
3961 tnr = 0;
3962 }
3963 g_snprintf(tmp,MAXLINE,_("Scanning track %d for ISRC..."),tnr);
3964 gtk_label_set_text(GTK_LABEL(readtrack_info_label),tmp);
3965 }
3966
3967 /* done with scanning? */
3968 if (strncmp(line,"recording", 9) == 0) {
3969 if (bulk == 0) {
3970 /* restore original info text */
3971 gtk_label_set_text(GTK_LABEL(readtrack_info_label),
3972 readtrack_info_string);
3973 } else {
3974 update_bulk_readlabel();
3975 }
3976 }
3977
3978 /* look for a percent value */
3979 if (line[strlen(line)-1] == '%') {
3980 /* skip leading linefeed if any */
3981 if (line[0] == '\r')
3982 line[0] = ' ';
3983
3984 /* look for last space */
3985 p = rindex(line,' ');
3986 if (p != NULL)
3987 strcpy(tmp,p);
3988 else
3989 strcpy(tmp,line);
3990
3991 tmp[strlen(tmp)-1] = '\0';
3992 strip_string(tmp);
3993 val = atoi(tmp);
3994 pval = (gfloat)val/100;
3995 if (pval > 1.0) pval = 1.0;
3996 gtk_progress_set_percentage(GTK_PROGRESS(readtrack_pbar1),
3997 pval);
3998
3999 /* now calculate how much percent he have at all */
4000 if (bulk == 0) {
4001 pval2 = (pct_so_far + (pval * pct_this_track)) /100;
4002 if (pval2 > 1.0) pval2 = 1.0;
4003 } else {
4004 pval2 = (writeparams.pct_so_far_arr[read_tracknr] +
4005 (pval * writeparams.pct_this_track_arr[read_tracknr]))/100;
4006 }
4007
4008 gtk_progress_set_percentage(GTK_PROGRESS(readtrack_pbar2),
4009 pval2);
4010 set_xcdr_title(toplevel, viewmode_dialog, (gint)(pval2*100+0.5));
4011
4012 /* now update info for small view */
4013 g_snprintf(tmp,MAXLINE,"%d%% / %d%%",(gint)(pval*100+0.5),
4014 (gint)(pval2*100+0.5));
4015 gtk_label_set_text(GTK_LABEL(readtrack_small_info2),tmp);
4016
4017 return;
4018 }
4019
4020 /* track successfully recorded? */
4021 if (strlen(line) > strlen("successfully recorded")) {
4022 strcpy(tmp, line+strlen(line)-strlen("successfully recorded"));
4023 if (strcmp(tmp, "successfully recorded") == 0 ||
4024 strcmp(tmp, "recorded successfully") == 0) {
4025 gtk_progress_set_percentage(GTK_PROGRESS(readtrack_pbar1), 1.0);
4026 /* look for last % */
4027 p = rindex(line,'%');
4028 if (p != NULL) {
4029 strcpy(tmp,p+1);
4030 strip_string(tmp);
4031 } else
4032 strcpy(tmp,line);
4033
4034 /* strips the 100% value from the string */
4035 strip_string(tmp);
4036 strcpy(line,tmp);
4037
4038 if (bulk == 1) {
4039 /* in bulkmode this means we switched tracks */
4040 read_tracknr++;
4041 update_bulk_readlabel();
4042 }
4043 }
4044 }
4045
4046 /* get subprocess pid */
4047 if (strncmp(line,"child pid", 9) == 0) {
4048 strcpy(tmp, line+12);
4049 readcdda_pid= (pid_t) atoi(tmp);
4050 return;
4051 }
4052
4053 /* error-text? do display these in the next block */
4054 if (strncmp(line,"Error",5) == 0 || strstr(line,"open audio sample file") != NULL) {
4055 read_output_ctrl = 1;
4056 }
4057
4058 /* forward most other output to textview-window */
4059 if (strncmp(line,"record",6) == 0 || read_output_ctrl == 1) {
4060 read_output_ctrl = 1;
4061 /* skip lines that do not interest us */
4062 if (strncmp(line,"percent_done",12) == 0) {
4063 return;
4064 }
4065 if (strncmp(line,"overlap:min",11) == 0) {
4066 return;
4067 }
4068 strcat(line,"\n");
4069 convert_for_gtk2_textwidget(line);
4070 gtk_text_insert(GTK_TEXT(readtrack_textview),
4071 fixedfont,NULL,NULL, line, strlen(line));
4072 }
4073 }
4074
4075
4076 /* parse dummy output of cdda2wav */
4077 /* output stdout of cdda2wav where never should any data be delivered */
4078
read_cdda2wav_dummyout(gpointer data,gint source,GdkInputCondition cond)4079 static void read_cdda2wav_dummyout(gpointer data, gint source, GdkInputCondition cond) {
4080 gint n;
4081 gchar line[MAXLINE];
4082
4083 /* read output of cdda */
4084 n = read_line(source, line, MAXLINE);
4085
4086 /* cdda-finished? */
4087 if (n <= 0) {
4088 gtk_input_remove(readcdda_callback2);
4089 return;
4090 }
4091
4092 strcat(line,"\n");
4093 convert_for_gtk2_textwidget(line);
4094 gtk_text_insert(GTK_TEXT(readtrack_textview),
4095 fixedfont,NULL,NULL, line, strlen(line));
4096 }
4097
4098
4099 /* call cdda2wav to read an audio-track
4100 return 0 on success, 1 on error */
4101
read_audio_track(gint devnr,gint starttrack,gint endtrack,gint kbyte,gchar * fname,gint startoffset,gint endoffset,gint nrtracks,gfloat percent,gfloat percent_done,gint viewtrack)4102 gint read_audio_track(gint devnr, gint starttrack, gint endtrack, gint kbyte,
4103 gchar *fname, gint startoffset, gint endoffset,
4104 gint nrtracks, gfloat percent, gfloat percent_done,
4105 gint viewtrack) {
4106 gchar cmd[MAXLINE];
4107 gchar tmp[MAXLINE];
4108 gchar tmp2[MAXLINE];
4109 gchar tmp3[MAXLINE];
4110 gchar tmp4[MAXLINE];
4111 gchar tmp5[MAXLINE];
4112 gchar tmp6[MAXLINE];
4113 gchar tmpfname[MAXLINE];
4114 gint read_in, read_out, read_dummy;
4115
4116 /* if another read running, ignore */
4117 if (read_done == 999) {
4118 return -1;
4119 }
4120
4121 /* no filename given? */
4122 if (fname == NULL) {
4123 return 1;
4124 }
4125 strncpy(tmpfname, fname, MAXLINE);
4126
4127 /* mark our read-process as running */
4128 read_done = 999;
4129 read_output_ctrl = 0;
4130 readcdda_pid = -1;
4131 readcdda_pid2 = -1;
4132 read_abort_mark = 0;
4133
4134 /* set info-label */
4135 convert_kbytes2mbminstring(kbyte, tmp);
4136 g_snprintf(tmp2,MAXLINE,_("Reading audio track %d/%d [%s]"), viewtrack, nrtracks, tmp);
4137 gtk_label_set_text(GTK_LABEL(readtrack_info_label),tmp2);
4138 strcpy(readtrack_info_string, tmp2);
4139
4140 g_snprintf(tmp2,MAXLINE,_("Reading %d/%d:"), viewtrack, nrtracks);
4141 gtk_label_set_text(GTK_LABEL(readtrack_small_info),tmp2);
4142
4143 /* get bus,id,lun string */
4144 if (convert_devnr2busid(devnr,tmp) != 0) {
4145 g_error("non existing cdrom?");
4146 }
4147
4148 /* some stuff to have our slider moving smoothly no matter how
4149 big the tracks are */
4150 pct_so_far = percent_done;
4151 pct_this_track = percent;
4152
4153 /* build command line */
4154 if (endtrack != 0) {
4155 g_snprintf(tmp2,MAXLINE,"%d+%d",starttrack,endtrack);
4156 } else {
4157 g_snprintf(tmp2,MAXLINE,"%d",starttrack);
4158 }
4159
4160 /* set speed only when not zero */
4161 if (get_cur_audioread_speed() > 0) {
4162 g_snprintf(tmp3,MAXLINE,"-S %d", get_cur_audioread_speed());
4163 } else {
4164 strcpy(tmp3,"");
4165 }
4166
4167 /* have to scan for indexes? */
4168 if (curset.indexscan != 0) {
4169 strcpy(tmp4,"-i 1 -v all");
4170 } else {
4171 strcpy(tmp4,"-v toc,summary,sectors,titles");
4172 }
4173
4174
4175 if (get_cur_audioread_useparanoia()) {
4176 g_snprintf(tmp6, MAXLINE, "-paranoia -paraopts=retries=%d", get_cur_audioread_paranoiaretries());
4177 } else {
4178 strcpy(tmp6,"");
4179 }
4180
4181 get_wrap_path("CDDA2WAV",tmp5);
4182 g_snprintf(cmd,MAXLINE,
4183 "%s -D \"%s\" -g -O wav -t %s %s %s -P %d -n %d %s \"%s\"",
4184 tmp5,tmp,tmp2,tmp3,tmp4,
4185 get_cur_audioread_overlap(), get_cur_audioread_sectorburst(),
4186 tmp6,
4187 convert_escape(tmpfname));
4188
4189 dodebug(1, "spawning: %s\n",cmd);
4190 dolog(2,"Read audio track %s\n", fname);
4191 dolog(3,"Executing: %s\n",cmd);
4192
4193 /* start child and get new fds */
4194 readcdda_pid = full_dpl_pipe3(&read_dummy,&read_in,&read_out,cmd,0);
4195 readcdda_pid2 = -1;
4196
4197 /* set output to nonblocking - otherwise our callback would block */
4198 fcntl(read_out, F_SETFL, O_NONBLOCK);
4199 fcntl(read_dummy, F_SETFL, O_NONBLOCK);
4200
4201 /* catch output of child */
4202 readcdda_callback = gdk_input_add(read_out, GDK_INPUT_READ,
4203 (GdkInputFunction) read_cdda2wav_out, GINT_TO_POINTER(0));
4204 readcdda_callback2 = gdk_input_add(read_dummy, GDK_INPUT_READ,
4205 (GdkInputFunction) read_cdda2wav_dummyout,NULL);
4206
4207 /* now wait until track is read */
4208 while (read_done == 999) {
4209 wait_and_process_events();
4210 }
4211
4212 close(read_out);
4213 close(read_in);
4214 close(read_dummy);
4215
4216 gtk_text_insert(GTK_TEXT(readtrack_textview),
4217 fixedfont,NULL,NULL, "\n", 1);
4218
4219 /* error while reading? */
4220 if (read_done != 0 && read_abort_mark == 0) {
4221 g_snprintf(tmp,MAXLINE,_("Error reading audio track %d/%d"), starttrack, nrtracks);
4222 gtk_label_set_text(GTK_LABEL(readtrack_info_label),tmp);
4223 gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Read-Error:"));
4224 return 1;
4225 }
4226 /* aborted? */
4227 if (read_abort_mark == 1) {
4228 gtk_label_set_text(GTK_LABEL(readtrack_info_label),_("Read aborted..."));
4229 return 1;
4230 }
4231
4232 return 0;
4233 }
4234
4235
4236 /* call cdda2wav to read all audio tracks from a cd */
4237
start_bulk_read_action(gint devnr,gfloat percent_done,gint startnr)4238 gint start_bulk_read_action(gint devnr, gfloat percent_done, gint startnr) {
4239 GList *loop;
4240 track_read_param_t *trackparam;
4241 char tmp[MAXLINE];
4242 char tmptmp[MAXLINE];
4243 char tmp3[MAXLINE];
4244 char tmp4[MAXLINE];
4245 char tmp5[MAXLINE];
4246 char tmp6[MAXLINE];
4247 char cmd[MAXLINE*10]; /* extra big buffer for very long cdrecord options */
4248 gint read_in, read_out, read_dummy;
4249 gint tracknr;
4250
4251 /* if another read running, ignore */
4252 if (read_done == 999) {
4253 return -1;
4254 }
4255
4256 /* mark our read-process as running */
4257 read_done = 999;
4258 read_output_ctrl = 0;
4259 pct_so_far = percent_done;
4260 read_tracknr = startnr;
4261 readcdda_pid = -1;
4262 readcdda_pid2 = -1;
4263 read_abort_mark = 0;
4264
4265 /* init track-label */
4266 gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Initializing CD-Reader..."));
4267 strcpy(readtrack_info_string, "");
4268
4269 /* reset writeparams-arrays */
4270 /* lets reuse this structure - even when we just read now */
4271 g_free(writeparams.tracktype);
4272 g_free(writeparams.frames);
4273 g_free(writeparams.pct_so_far_arr);
4274 g_free(writeparams.pct_this_track_arr);
4275 writeparams.tracktype = g_new0(gint,MAXTRACKS);
4276 writeparams.frames = g_new0(gint,MAXTRACKS);
4277 writeparams.pct_so_far_arr = g_new0(gfloat,MAXTRACKS);
4278 writeparams.pct_this_track_arr = g_new0(gfloat,MAXTRACKS);
4279 writeparams.nrtracks = 0;
4280 writeparams.simulation = curset.writesimul;
4281
4282 /* get bus,id,lun string */
4283 if (convert_devnr2busid(devnr,tmp) != 0) {
4284 g_error("non existing cdrom?");
4285 }
4286
4287 /* set speed only when not zero */
4288 if (get_cur_audioread_speed() > 0) {
4289 g_snprintf(tmp3,MAXLINE,"-S %d", get_cur_audioread_speed());
4290 } else {
4291 strcpy(tmp3,"");
4292 }
4293
4294 /* have to scan for indexes? */
4295 if (curset.indexscan != 0) {
4296 strcpy(tmp4,"-v all");
4297 } else {
4298 strcpy(tmp4,"-v toc,summary,sectors,titles");
4299 }
4300
4301 if (get_cur_audioread_useparanoia()) {
4302 g_snprintf(tmp6, MAXLINE, "-paranoia -paraopts=retries=%d", get_cur_audioread_paranoiaretries());
4303 } else {
4304 strcpy(tmp6,"");
4305 }
4306
4307 get_wrap_path("CDDA2WAV",tmp5);
4308 g_snprintf(cmd,MAXLINE,
4309 "%s -D \"%s\" -g -O wav %s %s -P %d -n %d %s -B",
4310 tmp5,tmp,tmp3,tmp4,
4311 get_cur_audioread_overlap(), get_cur_audioread_sectorburst(),
4312 tmp6);
4313
4314 tracknr = startnr;
4315 /* now add all track-filenames (only audio) */
4316 loop = g_list_first(trackreadset.trackparams);
4317 while(loop) {
4318 trackparam = loop->data;
4319 if (trackparam->trackfile != NULL &&
4320 trackparam->tracktype == 1) {
4321 strcpy(tmptmp, trackparam->trackfile);
4322 g_snprintf(tmp, MAXLINE, " \"%s\"",
4323 convert_escape(tmptmp));
4324 strcat(cmd, tmp);
4325
4326 /* fill up percent values for percentbar */
4327 writeparams.tracktype[tracknr] = trackparam->tracktype;
4328 writeparams.frames[tracknr] = trackparam->frames;
4329 writeparams.pct_this_track_arr[tracknr] = trackparam->percent;
4330 writeparams.pct_so_far_arr[tracknr] = pct_so_far;
4331 pct_so_far += trackparam->percent;
4332 writeparams.nrtracks++;
4333 tracknr++;
4334
4335 }
4336 loop = loop->next;
4337 }
4338 /* correct full nr of tracks (so we have the full count of tracks) */
4339 writeparams.nrtracks+=startnr-1;
4340
4341 dodebug(1, "spawning: %s\n",cmd);
4342 dolog(2,"Read all audio tracks\n");
4343 dolog(3,"Executing: %s\n",cmd);
4344
4345 /* start child and get new fds */
4346 readcdda_pid = full_dpl_pipe3(&read_dummy,&read_in,&read_out,cmd,0);
4347 readcdda_pid2 = -1;
4348
4349 /* set output to nonblocking - otherwise our callback would block */
4350 fcntl(read_out, F_SETFL, O_NONBLOCK);
4351
4352 /* catch output of child */
4353 readcdda_callback = gdk_input_add(read_out, GDK_INPUT_READ,
4354 (GdkInputFunction) read_cdda2wav_out, GINT_TO_POINTER(1));
4355 readcdda_callback2 = gdk_input_add(read_dummy, GDK_INPUT_READ,
4356 (GdkInputFunction) read_cdda2wav_dummyout,NULL);
4357
4358 /* now wait until track is read */
4359 while (read_done == 999) {
4360 wait_and_process_events();
4361 }
4362
4363 close(read_out);
4364 close(read_in);
4365 close(read_dummy);
4366
4367 gtk_text_insert(GTK_TEXT(readtrack_textview),
4368 fixedfont,NULL,NULL, "\n", 1);
4369
4370 /* error while reading? */
4371 if (read_done != 0 && read_abort_mark == 0) {
4372 g_snprintf(tmp,MAXLINE,_("Error reading audio track %d/%d"), read_tracknr,
4373 writeparams.nrtracks);
4374 gtk_label_set_text(GTK_LABEL(readtrack_info_label),tmp);
4375 gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Read-Error:"));
4376 return 1;
4377 }
4378 /* aborted? */
4379 if (read_abort_mark == 1) {
4380 gtk_label_set_text(GTK_LABEL(readtrack_info_label),_("Read aborted..."));
4381 return 1;
4382 }
4383
4384 return 0;
4385 }
4386
4387
4388 /* parse output of readcd and update sliders */
4389
read_readcd_out(gpointer data,gint source,GdkInputCondition cond)4390 static void read_readcd_out(gpointer data, gint source, GdkInputCondition cond) {
4391 gint n;
4392 gint ret;
4393 gchar line[MAXLINE];
4394 gchar tmp[MAXLINE];
4395 gchar tmp2[MAXLINE];
4396 gint val;
4397 gfloat pval, pval2;
4398
4399 /* read output of readcd */
4400 n = read_line(source, line, MAXLINE);
4401
4402 /* readcd-finished? */
4403 if (n <= 0) {
4404 gtk_input_remove(readcdda_callback);
4405
4406 /* pick up return status of child */
4407 wait(&ret);
4408
4409 /* tell our caller that we are done here */
4410 if (WEXITSTATUS(ret) == 0 && read_output_ctrl == 0) {
4411 /* readcd does return status 0 when killed - override */
4412 read_done = 1;
4413 } else {
4414 read_done = WEXITSTATUS(ret);
4415 }
4416 return;
4417 }
4418
4419 dodebug(10,"readcd: %s\n", line);
4420
4421 /* look for end value */
4422 if (strncmp(line,"end:",4) == 0) {
4423 strcpy(tmp,line+4);
4424 strip_string(tmp);
4425 readcd_endsector = atoi(tmp);
4426 return;
4427 }
4428
4429 /* look for a percent value */
4430 if (strncmp(line,"addr:",5) == 0) {
4431 /* skip leading linefeed if any */
4432 if (line[0] == '\r')
4433 strcpy(tmp,line+6);
4434 else
4435 strcpy(tmp,line+5);
4436
4437 strip_string(tmp);
4438 strcpy(tmp2,strtok(tmp," "));
4439 val = atoi(tmp2) - readcd_startsector;
4440
4441 /* if not set yet, do nothing */
4442 if (readcd_endsector == 0)
4443 return;
4444
4445 pval = (gfloat)val/(gfloat)(readcd_endsector - readcd_startsector);
4446 if (pval > 1.0) pval = 1.0;
4447
4448 gtk_progress_set_percentage(GTK_PROGRESS(readtrack_pbar1),
4449 pval);
4450
4451 /* now calculate how much percent he has at all */
4452 pval2 = (pct_so_far + (pval * pct_this_track)) /100;
4453 if (pval2 > 1.0) pval2 = 1.0;
4454 gtk_progress_set_percentage(GTK_PROGRESS(readtrack_pbar2),
4455 pval2);
4456 set_xcdr_title(toplevel,viewmode_dialog,(gint)(pval2*100+0.5));
4457
4458 /* now update info for small view */
4459 g_snprintf(tmp,MAXLINE,"%d%% / %d%%",(gint)(pval*100+0.5),
4460 (gint)(pval2*100+0.5));
4461 gtk_label_set_text(GTK_LABEL(readtrack_small_info2),tmp);
4462
4463 return;
4464 }
4465
4466 /* look if last expected line from readcd came */
4467 if (strncmp(line,"Read",4) == 0) {
4468 /* ok...now we can expect that we were not aborted */
4469 if (read_output_ctrl != 2) {
4470 read_output_ctrl = 1;
4471 }
4472 }
4473
4474 /* look if we got an read error */
4475 if (line[0] == '.') {
4476 gtk_label_set_text(GTK_LABEL(readtrack_info_label),_("Failed to read sector - retrying"));
4477 gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Retrying..."));
4478 }
4479
4480 /* now look if the got an error which could not corrected */
4481 if (strstr(line,"not corrected")) {
4482 read_output_ctrl = 2;
4483 }
4484
4485 /* write error on disk? */
4486 if (strstr(line,"annot write")) {
4487 read_output_ctrl = 2;
4488 }
4489
4490 /* some blocked output of tracks came through */
4491 if (strstr(line, " cnt: ")) {
4492 /* kick it */
4493 return;
4494 }
4495
4496 /* forward most other output to textview-window */
4497 strcat(line,"\n");
4498 convert_for_gtk2_textwidget(line);
4499 gtk_text_insert(GTK_TEXT(readtrack_textview),
4500 fixedfont,NULL,NULL, line, strlen(line));
4501 }
4502
4503
4504 /* call readcd to read a data-track
4505 return 0 on success, 1 on error */
4506
read_data_track(gint devnr,gint starttrack,gint kbyte,gchar * fname,gint startoffset,gint endoffset,gint nrtracks,gfloat percent,gfloat percent_done,gint viewtrack)4507 gint read_data_track(gint devnr, gint starttrack, gint kbyte,
4508 gchar *fname, gint startoffset, gint endoffset,
4509 gint nrtracks, gfloat percent, gfloat percent_done,
4510 gint viewtrack) {
4511 gchar cmd[MAXLINE];
4512 gchar tmp[MAXLINE];
4513 gchar tmptmp[MAXLINE];
4514 gchar tmp2[MAXLINE];
4515 gchar tmp3[MAXLINE];
4516 gint read_in, read_out, sectsize;
4517
4518 /* if another read running, ignore */
4519 if (read_done == 999) {
4520 return -1;
4521 }
4522
4523 /* no filename given? */
4524 if (fname == NULL) {
4525 return 1;
4526 }
4527
4528 /* mark our read-process as running */
4529 read_done = 999;
4530 readcdda_pid = -1;
4531 readcdda_pid2 = -1;
4532 read_output_ctrl = 0;
4533 readcd_startsector = startoffset;
4534 readcd_endsector = 0;
4535 read_abort_mark = 0;
4536
4537 /* set info-label */
4538 convert_kbytes2mbminstring(kbyte, tmp);
4539 g_snprintf(tmp2,MAXLINE,_("Reading data track %d/%d [%s]"), viewtrack, nrtracks, tmp);
4540 gtk_label_set_text(GTK_LABEL(readtrack_info_label),tmp2);
4541
4542 g_snprintf(tmp2,MAXLINE,_("Reading %d/%d:"), viewtrack, nrtracks);
4543 gtk_label_set_text(GTK_LABEL(readtrack_small_info),tmp2);
4544
4545 /* get bus,id,lun string */
4546 if (convert_devnr2busid_dev(devnr,tmp) != 0) {
4547 g_error("non existing cdrom?");
4548 }
4549
4550 /* some stuff to have our slider moving smoothly no matter how
4551 big the tracks are */
4552 pct_so_far = percent_done;
4553 pct_this_track = percent;
4554
4555 /* now check which sectorsize we got */
4556 sectsize = get_sectorsize(devnr);
4557 if (sectsize == 2352) {
4558 /* workaround for buggy drives */
4559 endoffset = ((endoffset * DATASECTORSIZE) / sectsize) + 1;
4560 }
4561
4562 get_wrap_path("READCD",tmp3);
4563 strcpy(tmptmp,fname);
4564 g_snprintf(cmd,MAXLINE,
4565 "%s %s sectors=%d-%d -s retries=32 f= \"%s\"",
4566 tmp3, tmp, startoffset, endoffset,
4567 convert_escape(tmptmp));
4568 dodebug(1, "spawning: %s\n",cmd);
4569 dolog(2,"Read data track %s\n", fname);
4570 dolog(3,"Executing: %s\n",cmd);
4571
4572 /* start child and get new fds */
4573 readcdda_pid = full_dpl_pipe3(NULL,&read_in,&read_out,cmd,0);
4574 readcdda_pid2 = -1;
4575
4576 /* set output to nonblocking - otherwise our callback would block */
4577 fcntl(read_out, F_SETFL, O_NONBLOCK);
4578
4579 /* catch output of child */
4580 readcdda_callback = gdk_input_add(read_out, GDK_INPUT_READ,
4581 (GdkInputFunction) read_readcd_out, NULL);
4582
4583 /* now wait until track is read */
4584 while (read_done == 999) {
4585 wait_and_process_events();
4586 }
4587
4588 close(read_out);
4589 close(read_in);
4590
4591 gtk_text_insert(GTK_TEXT(readtrack_textview),
4592 fixedfont,NULL,NULL, "\n", 1);
4593
4594 /* error while reading? */
4595 if ((read_done != 0 && read_abort_mark == 0) || read_output_ctrl == 2) {
4596 g_snprintf(tmp,MAXLINE,_("Error reading data track %d/%d"), starttrack, nrtracks);
4597 gtk_label_set_text(GTK_LABEL(readtrack_info_label),tmp);
4598 gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Read-Error:"));
4599 return 1;
4600 }
4601 /* aborted? */
4602 if (read_abort_mark == 1) {
4603 gtk_label_set_text(GTK_LABEL(readtrack_info_label),_("Read aborted..."));
4604 return 1;
4605 }
4606
4607 return 0;
4608 }
4609
4610
checkmedium_out(gpointer data,gint source,GdkInputCondition cond)4611 static void checkmedium_out(gpointer data, gint source, GdkInputCondition cond) {
4612 gint n;
4613 gint ret, devnr, sectsize;
4614 gchar tmp[MAXLINE];
4615 gchar line[MAXLINE];
4616 gchar *p;
4617
4618
4619 /* read output of readcd */
4620 n = read_line(source, line, MAXLINE);
4621
4622 /* readcd finished */
4623 if (n <= 0) {
4624 gtk_input_remove(readcdda_callback);
4625
4626 /* pick up return status of child */
4627 wait(&ret);
4628
4629 /* tell our caller that we are done here */
4630 read_done = WEXITSTATUS(ret);
4631
4632 return;
4633 }
4634
4635 dodebug(10,"check_medium_loaded: %s\n", line);
4636
4637 /* got the message that no medium is present?
4638 in this case, ignore return code */
4639 if (strstr(line,"medium not present")) {
4640 checkmedium_found = 1;
4641 }
4642 if (strstr(line,"Device not ready")) {
4643 checkmedium_found = 1;
4644 }
4645
4646 /* get a line about sectorsize? */
4647 if (strstr(line,"Sectorsize:")) {
4648 /* extract the bytes given there */
4649 strcpy(tmp,line+12);
4650 p = strtok(tmp," ");
4651 if (p) {
4652 sectsize = atoi(p);
4653 dodebug(10,"-> Detected sectorsize of %d bytes\n", sectsize);
4654 devnr = GPOINTER_TO_INT(data);
4655 set_sectorsize(devnr,sectsize);
4656 }
4657 }
4658 }
4659
4660
4661 /* checks if a disk is loaded in drive
4662 return 0 if not, 1 if loaded and ready */
4663
check_medium_loaded(gint devnr)4664 static gint check_medium_loaded(gint devnr) {
4665 gchar tmp[MAXLINE];
4666 gchar tmp2[MAXLINE];
4667 gchar line[MAXLINE];
4668 gint read_out;
4669
4670 checkmedium_found = 0;
4671 read_done = 999;
4672
4673 /* get bus,id,lun string */
4674 if (convert_devnr2busid_dev(devnr,tmp) != 0) {
4675 g_error("non existing cdrom?");
4676 }
4677
4678 /* build command line */
4679 get_wrap_path("READCD",tmp2);
4680 g_snprintf(line,MAXLINE,"%s %s f=- sectors=0-0",
4681 tmp2,tmp);
4682
4683 dodebug(1, "spawning: %s\n", line);
4684
4685 readcdda_pid = full_dpl_pipe3(NULL,NULL,&read_out,line,0);
4686 readcdda_pid2 = -1;
4687
4688 readcdda_callback = gdk_input_add(read_out, GDK_INPUT_READ,
4689 (GdkInputFunction) checkmedium_out, GINT_TO_POINTER(devnr));
4690
4691 /* now wait until toc is read */
4692 while (read_done == 999) {
4693 wait_and_process_events();
4694 }
4695
4696 close(read_out);
4697
4698 dodebug(10, "medium loaded return code: %d\n", read_done);
4699
4700 if (read_done == 0 && checkmedium_found == 0)
4701 return 1;
4702 else
4703 return 0;
4704 }
4705
4706
4707 /* save the contents of a text-widget to a file
4708 return 0 on success, 1 on error */
4709
save_text2file(char * fname,GtkWidget * txt)4710 gint save_text2file(char *fname, GtkWidget *txt) {
4711 gchar *buf;
4712 gint n;
4713 gint fd;
4714
4715 /* get text from textwidget */
4716 n = gtk_text_get_length(GTK_TEXT(txt));
4717 buf = gtk_editable_get_chars(GTK_EDITABLE(txt),0,n);
4718
4719 dodebug(2, "saving extended output to %s\n", fname);
4720 dolog(3, "Saving extended output to %s\n", fname);
4721
4722 /* write to file */
4723 fd = open(fname,O_WRONLY | O_CREAT);
4724 if (fd < 0) {
4725 g_warning("Can't open file %s for writing\n",fname);
4726 return 1;
4727 }
4728
4729 if (write(fd,buf,n) != n) {
4730 g_warning("Can't write file %s\n",fname);
4731 return 1;
4732 }
4733
4734 g_free(buf);
4735 close(fd);
4736 chmod(fname,0644);
4737
4738 return 0;
4739 }
4740
4741
4742 /* write the toc-file when copying full CDs */
4743
write_copy_cd_toc_file(gchar * tocfile)4744 gint write_copy_cd_toc_file(gchar *tocfile) {
4745 GList *loop;
4746 track_read_param_t *trackparam;
4747 FILE *fd;
4748 time_t acttime;
4749 gchar timestr[MAXLINE];
4750 gint tracknr;
4751 gchar tmp[MAXLINE];
4752 gchar tmp2[MAXLINE];
4753
4754 if (tocfile == NULL) return 1;
4755
4756 dodebug(2, "writing cd toc file %s\n", tocfile);
4757
4758 /* is a link? */
4759 if (check_islink(tocfile, NULL)) {
4760 g_warning("Warning, won't overwrite a link at %s\n", tocfile);
4761 return 1;
4762 }
4763
4764 /* write to file */
4765 fd = fopen(tocfile,"w");
4766
4767 if (fd == NULL) {
4768 g_warning("Can't open file %s for writing\n",tocfile);
4769 return 1;
4770 }
4771
4772 /* get current time */
4773 acttime = time((time_t *) 0);
4774 strcpy(timestr,ctime(&acttime));
4775 timestr[strlen(timestr)-1] = '\0';
4776
4777 /* write header */
4778
4779 fputs("#\n",fd);
4780 g_snprintf(tmp,MAXLINE,"# X-CD-Roast %s - TOC-File\n",XCDROAST_VERSION);
4781 fputs(tmp,fd);
4782 g_snprintf(tmp,MAXLINE,"# created: %s\n", timestr);
4783 fputs(tmp,fd);
4784 g_snprintf(tmp,MAXLINE,"# by: %s@%s\n", username, hostname);
4785 fputs(tmp,fd);
4786 fputs("#\n",fd);
4787
4788 /* write disk-info */
4789
4790 convert_frames2minstring(cdinfo.total_size, tmp2);
4791 g_snprintf(tmp,MAXLINE,"# Tracks: %d [%s]\n",
4792 cdinfo.nr_tracks, tmp2);
4793 fputs(tmp,fd);
4794 if (cdinfo.title && cdinfo.artist) {
4795 g_snprintf(tmp,MAXLINE,"# title/artist: %s / %s\n",
4796 cdinfo.title, cdinfo.artist);
4797 fputs(tmp,fd);
4798 }
4799 if (cdinfo.cddb_dtitle != NULL) {
4800 g_snprintf(tmp,MAXLINE,"# cddb: %s\n", cdinfo.cddb_dtitle);
4801 fputs(tmp,fd);
4802 }
4803 fputs("#\n",fd);
4804
4805 /* generate disk-title */
4806 if (cdinfo.cddb_dtitle != NULL) {
4807 strcpy(tmp2,cdinfo.cddb_dtitle);
4808 g_snprintf(tmp,MAXLINE,"cdtitle = \"%s\"\n", convert_escape(tmp2));
4809 } else
4810 if (cdinfo.title && cdinfo.artist && cdinfo.title[0] != '\0') {
4811 g_snprintf(tmp2,MAXLINE,"%s / %s",
4812 cdinfo.title, cdinfo.artist);
4813 g_snprintf(tmp,MAXLINE,"cdtitle = \"%s\"\n", convert_escape(tmp2));
4814 } else {
4815 /* no title available? */
4816 /* if data-track get track-label (better than nothing) */
4817 /* get first track */
4818 loop = g_list_first(trackreadset.trackparams);
4819 if (loop) {
4820 trackparam = loop->data;
4821 tracknr = trackparam->trackinfo_index;
4822 if (trackinfo[tracknr]->title != NULL) {
4823 strcpy(tmp2,trackinfo[tracknr]->title);
4824 } else {
4825 strcpy(tmp2,"");
4826 }
4827 g_snprintf(tmp,MAXLINE,"cdtitle = \"%s\"\n",
4828 convert_escape(tmp2));
4829 } else {
4830 g_snprintf(tmp,MAXLINE,"cdtitle = \"\"\n");
4831 }
4832 }
4833 fputs(tmp,fd);
4834 g_snprintf(tmp,MAXLINE,"cdsize = %d\n",cdinfo.total_size);
4835 fputs(tmp,fd);
4836 g_snprintf(tmp,MAXLINE,"discid = \"%s\"\n",cdinfo.cddb_discid);
4837 fputs(tmp,fd);
4838
4839
4840 /* write a section for each track */
4841
4842 loop = g_list_first(trackreadset.trackparams);
4843 while (loop) {
4844 trackparam = loop->data;
4845
4846 tracknr = trackparam->trackinfo_index;
4847
4848 /* make sure to get some NULLs wasted */
4849 if (trackinfo[tracknr]->title == NULL) {
4850 trackinfo[tracknr]->title = g_strdup("");
4851 }
4852 if (trackinfo[tracknr]->artist == NULL) {
4853 trackinfo[tracknr]->artist = g_strdup("");
4854 }
4855
4856 fputs("\n",fd);
4857 if (trackinfo[tracknr]->type == 0) {
4858 convert_frames2mbstring(trackinfo[tracknr]->size, tmp2);
4859 g_snprintf(tmp,MAXLINE,"# data: %s [%"LL_FORMAT" bytes / %s]\n",
4860 trackinfo[tracknr]->title,
4861 (gint64) trackinfo[tracknr]->size * DATASECTORSIZE,
4862 tmp2);
4863 fputs(tmp,fd);
4864 } else {
4865 convert_frames2minstring(trackinfo[tracknr]->size, tmp2);
4866 g_snprintf(tmp,MAXLINE,"# audio: %s / %s [%"LL_FORMAT" bytes / %s]\n",
4867 trackinfo[tracknr]->title,
4868 trackinfo[tracknr]->artist,
4869 (gint64) trackinfo[tracknr]->size * CDDAFRAME, tmp2);
4870 fputs(tmp,fd);
4871 if (trackinfo[tracknr]->cddb_ttitle != NULL) {
4872 g_snprintf(tmp,MAXLINE,"# cddb: %s\n",
4873 trackinfo[tracknr]->cddb_ttitle);
4874 fputs(tmp,fd);
4875 }
4876 }
4877
4878 g_snprintf(tmp,MAXLINE,"track = %02d\n", trackparam->starttrack);
4879 fputs(tmp,fd);
4880 g_snprintf(tmp,MAXLINE,"type = %d\n", trackinfo[tracknr]->type);
4881 fputs(tmp,fd);
4882 g_snprintf(tmp,MAXLINE,"size = %d\n", trackinfo[tracknr]->size);
4883 fputs(tmp,fd);
4884 g_snprintf(tmp,MAXLINE,"startsec = %d\n", trackinfo[tracknr]->start_sec);
4885 fputs(tmp,fd);
4886
4887 if (trackparam->trackfile != NULL) {
4888 strcpy(tmp2, trackparam->trackfile);
4889 } else {
4890 strcpy(tmp2,"");
4891 }
4892 g_snprintf(tmp,MAXLINE,"file = \"%s\"\n",
4893 convert_escape(tmp2));
4894 fputs(tmp,fd);
4895
4896 loop = loop->next;
4897 }
4898
4899 if (fclose(fd) != 0) {
4900 /* error closing file */
4901 return 1;
4902 }
4903
4904 return 0;
4905 }
4906
4907
4908 /* print trackparams-structure for debug reasons */
4909
print_trackreadset()4910 void print_trackreadset() {
4911 GList *loop;
4912 track_read_param_t *trackparam;
4913
4914 dodebug(2,"------ trackreadset-structure -----\n");
4915 dodebug(2,"nrtracks: %d\n",trackreadset.nrtracks);
4916 dodebug(2,"cdsize: %d\n",trackreadset.cdsize);
4917 dodebug(2,"tocfile: %s\n",trackreadset.tocfile);
4918 dodebug(2,"cdtitle: %s\n",trackreadset.cdtitle);
4919
4920 loop = g_list_first(trackreadset.trackparams);
4921 while(loop) {
4922 trackparam = loop->data;
4923 dodebug(2,"\ntrackinfo_index: %d\n", trackparam->trackinfo_index);
4924 dodebug(2,"starttrack: %d\n", trackparam->starttrack);
4925 dodebug(2,"endtrack: %d\n", trackparam->endtrack);
4926 dodebug(2,"tracktype: %d\n", trackparam->tracktype);
4927 dodebug(2,"start_sec: %d\n", trackparam->start_sec);
4928 dodebug(2,"startoffset: %d\n", trackparam->startoffset);
4929 dodebug(2,"endoffset: %d\n", trackparam->endoffset);
4930 dodebug(2,"percent: %f\n", trackparam->percent);
4931 dodebug(2,"kbyte: %d\n", trackparam->kbyte);
4932 dodebug(2,"frames: %d\n", trackparam->frames);
4933 if (trackparam->trackfile != NULL) {
4934 dodebug(2,"trackfile: %s\n", trackparam->trackfile);
4935 } else {
4936 dodebug(2,"trackfile: (NULL)\n");
4937 }
4938 loop = loop->next;
4939 }
4940 }
4941
4942
4943 /* read the toc-file when copying full CDs */
4944
read_copy_cd_toc_file(gchar * tocfile)4945 gint read_copy_cd_toc_file(gchar *tocfile) {
4946 FILE *fd;
4947 GList *loop;
4948 track_read_param_t *trackparam;
4949 gchar line[MAXLINE];
4950 gchar id[MAXLINE];
4951 gchar value[MAXLINE];
4952 gint cdsize;
4953 gfloat per;
4954
4955 /* keep compiler shut about uninitialized warning */
4956 trackparam = NULL;
4957
4958 /* prepare trackreadset for refilling */
4959 loop = g_list_first(trackreadset.trackparams);
4960 while (loop) {
4961 trackparam = loop->data;
4962 g_free(trackparam->trackfile);
4963 g_free(trackparam);
4964 loop = loop->next;
4965 }
4966 g_list_free(trackreadset.trackparams);
4967 trackreadset.trackparams = NULL;
4968
4969 trackreadset.nrtracks = 0;
4970 trackreadset.cdsize = 0;
4971 cdsize = 0;
4972 g_free(trackreadset.tocfile);
4973 trackreadset.tocfile=g_strdup(tocfile);
4974 g_free(trackreadset.cdtitle);
4975 trackreadset.cdtitle = g_strdup("");
4976
4977 dodebug(2, "reading cd toc file %s\n", tocfile);
4978 /* open file */
4979 fd = fopen(tocfile,"r");
4980
4981 if (fd == NULL) {
4982 g_warning("Can't open file %s for reading\n",tocfile);
4983 return 1;
4984 }
4985
4986 for (;;) {
4987 if (fgets(line,MAXLINE,fd) == NULL)
4988 break;
4989
4990 dodebug(10,"read tocfile: %s", line);
4991 /* skip empty or hashed lines */
4992 strip_string(line);
4993 if (*line == '#' || *line == '\0')
4994 continue;
4995
4996 /* parse lines */
4997 if (parse_config_line(line,id,value)) {
4998 dodebug(10,"invalid line in tocfile");
4999 fclose(fd);
5000 return 1;
5001 }
5002
5003 if (strcmp("cdtitle",id) == 0) {
5004 g_free(trackreadset.cdtitle);
5005 trackreadset.cdtitle = g_strdup(value);
5006 }
5007 if (strcmp("discid",id) == 0) {
5008 g_free(trackreadset.cd_discid);
5009 trackreadset.cd_discid = g_strdup(value);
5010 }
5011 if (strcmp("cdsize",id) == 0) {
5012 trackreadset.cdsize = atoi(value);
5013 }
5014 if (strcmp("track",id) == 0) {
5015 /* allocate memory */
5016 trackparam = g_new0(track_read_param_t,1);
5017 trackparam->trackinfo_index = -1;
5018 trackparam->starttrack = atoi(value);
5019 trackparam->endtrack = 0;
5020 trackreadset.nrtracks++;
5021 }
5022 if (strcmp("type",id) == 0) {
5023 trackparam->tracktype = atoi(value);
5024 }
5025 if (strcmp("size",id) == 0) {
5026 trackparam->frames = atoi(value);
5027 cdsize += trackparam->frames;
5028 }
5029 if (strcmp("startsec",id) == 0) {
5030 trackparam->start_sec = atoi(value);
5031 }
5032 if (strcmp("file",id) == 0) {
5033 g_free(trackparam->trackfile);
5034 trackparam->trackfile = g_strdup(value);
5035
5036 trackreadset.trackparams = g_list_append(
5037 trackreadset.trackparams, trackparam);
5038 }
5039
5040 }
5041
5042 if (fclose(fd) != 0) {
5043 /* error closing file */
5044 return 1;
5045 }
5046
5047 /* ok..all data read - now calculate the percentages */
5048 loop = g_list_first(trackreadset.trackparams);
5049 while(loop) {
5050 trackparam = loop->data;
5051 per = (gfloat)trackparam->frames / cdsize;
5052 trackparam->percent = per;
5053
5054 loop = loop->next;
5055 }
5056
5057 if (debug > 1)
5058 print_trackreadset();
5059
5060 return 0;
5061 }
5062
5063
5064 /* write the info-file for each read track */
5065
write_inf_file(track_read_param_t * trackparam)5066 gint write_inf_file(track_read_param_t *trackparam) {
5067 FILE *fd;
5068 time_t acttime;
5069 gchar timestr[MAXLINE];
5070 gchar tmp[MAXLINE];
5071 gchar tmp2[MAXLINE];
5072 gchar *p;
5073 gint tracknr;
5074
5075 /* get current time */
5076 acttime = time((time_t *) 0);
5077 strcpy(timestr,ctime(&acttime));
5078 timestr[strlen(timestr)-1] = '\0';
5079
5080 if (trackparam->trackfile == NULL) {
5081 return 1;
5082 }
5083
5084 /* generate filename */
5085 /* (remove extension and put .xinf there) */
5086 strncpy(tmp,trackparam->trackfile,MAXLINE - 4);
5087 p = rindex(tmp,'.');
5088 if (!p) return 1;
5089 *p = '\0';
5090 strcpy(tmp2,tmp);
5091 strcat(tmp2,XCDROAST_INFO_EXT);
5092
5093 dodebug(1,"writing inffile %s\n", tmp2);
5094
5095 /* is a link? */
5096 if (check_islink(tmp2, NULL)) {
5097 g_warning("Warning, won't overwrite a link at %s\n", tmp2);
5098 return 1;
5099 }
5100
5101 /* write to file */
5102 fd = fopen(tmp2,"w");
5103
5104 if (fd == NULL) {
5105 g_warning("Can't open file %s for writing\n",tmp2);
5106 return 1;
5107 }
5108
5109 /* write header */
5110 fputs("#\n",fd);
5111 g_snprintf(tmp,MAXLINE,"# X-CD-Roast %s - INF-File\n",XCDROAST_VERSION);
5112 fputs(tmp,fd);
5113 g_snprintf(tmp,MAXLINE,"# created: %s\n", timestr);
5114 fputs(tmp,fd);
5115 g_snprintf(tmp,MAXLINE,"# by: %s@%s\n", username, hostname);
5116 fputs(tmp,fd);
5117 fputs("#\n",fd);
5118
5119 tracknr = trackparam->trackinfo_index;
5120
5121 g_snprintf(tmp,MAXLINE,"file = \"%s\"\n",trackparam->trackfile);
5122 fputs(tmp,fd);
5123 g_snprintf(tmp,MAXLINE,"track = %d of %d\n",
5124 trackinfo[tracknr]->track_nr,
5125 cdinfo.nr_tracks);
5126 fputs(tmp,fd);
5127 if (trackinfo[tracknr]->title) {
5128 strcpy(tmp2,trackinfo[tracknr]->title);
5129 } else {
5130 strcpy(tmp2,"");
5131 }
5132 g_snprintf(tmp,MAXLINE,"title = \"%s\"\n",convert_escape(tmp2));
5133 fputs(tmp,fd);
5134 if (trackinfo[tracknr]->artist) {
5135 strcpy(tmp2,trackinfo[tracknr]->artist);
5136 } else {
5137 strcpy(tmp2,"");
5138 }
5139 g_snprintf(tmp,MAXLINE,"artist = \"%s\"\n",convert_escape(tmp2));
5140 fputs(tmp,fd);
5141 if (trackinfo[tracknr]->cddb_ttitle != NULL) {
5142 strcpy(tmp2,trackinfo[tracknr]->cddb_ttitle);
5143 g_snprintf(tmp,MAXLINE,"cddb_ttitle = \"%s\"\n",
5144 convert_escape(tmp2));
5145 fputs(tmp,fd);
5146 }
5147 g_snprintf(tmp,MAXLINE,"size = %d\n", trackinfo[tracknr]->size);
5148 fputs(tmp,fd);
5149 g_snprintf(tmp,MAXLINE,"type = %d\n", trackinfo[tracknr]->type);
5150 fputs(tmp,fd);
5151 g_snprintf(tmp,MAXLINE,"rec_type = %d\n", trackinfo[tracknr]->rec_type);
5152 fputs(tmp,fd);
5153 g_snprintf(tmp,MAXLINE,"preemp = %d\n", trackinfo[tracknr]->preemp);
5154 fputs(tmp,fd);
5155 g_snprintf(tmp,MAXLINE,"copyperm = %d\n", trackinfo[tracknr]->copyperm);
5156 fputs(tmp,fd);
5157 g_snprintf(tmp,MAXLINE,"stereo = %d\n", trackinfo[tracknr]->stereo);
5158 fputs(tmp,fd);
5159 fputs("# from CD:\n",fd);
5160 if (cdinfo.title) {
5161 strcpy(tmp2,cdinfo.title);
5162 } else {
5163 strcpy(tmp2,"");
5164 }
5165 g_snprintf(tmp,MAXLINE,"cd_title = \"%s\"\n",convert_escape(tmp2));
5166 fputs(tmp,fd);
5167 if (cdinfo.artist) {
5168 strcpy(tmp2,cdinfo.artist);
5169 } else {
5170 strcpy(tmp2,"");
5171 }
5172 g_snprintf(tmp,MAXLINE,"cd_artist = \"%s\"\n",convert_escape(tmp2));
5173 fputs(tmp,fd);
5174 if (cdinfo.cddb_dtitle != NULL) {
5175 strncpy(tmp2,cdinfo.cddb_dtitle, MAXLINE);
5176 g_snprintf(tmp,MAXLINE,"cd_cddb_dtitle = \"%s\"\n",
5177 convert_escape(tmp2));
5178 fputs(tmp,fd);
5179 }
5180
5181 strncpy(tmp2,cdinfo.cddb_discid, MAXLINE);
5182 g_snprintf(tmp,MAXLINE,"cd_discid = \"%s\"\n",
5183 convert_escape(tmp2));
5184 fputs(tmp,fd);
5185
5186 if (fclose(fd) != 0) {
5187 /* error closing file */
5188 return 1;
5189 }
5190
5191 return 0;
5192 }
5193
5194
5195 /* read the titles/artists from an inf-file */
5196
get_inf_tracktitle(gchar * path,image_files_t * entry)5197 gint get_inf_tracktitle(gchar *path, image_files_t *entry) {
5198 FILE *fd;
5199 gchar line[MAXLINE];
5200 gchar id[MAXLINE];
5201 gchar value[MAXLINE];
5202 gchar tmp[MAXLINE];
5203 gchar tmp2[MAXLINE];
5204 gchar *p;
5205 gint istoc;
5206
5207 /* generate filename */
5208 /* (remove extension and put .inf there) */
5209 istoc = 0;
5210 strncpy(tmp,path,MAXLINE - 4);
5211 p = rindex(tmp,'.');
5212 if (!p) return 1;
5213 if (strcmp(p,".toc") == 0) {
5214 /* we are currently handling a toc file */
5215 istoc = 1;
5216 }
5217 *p = '\0';
5218 strcpy(tmp2,tmp);
5219 strcat(tmp2,XCDROAST_INFO_EXT);
5220
5221 if (istoc)
5222 strcpy(tmp2,path);
5223
5224 dodebug(1, "reading titles from %s\n", tmp2);
5225
5226 if ((fd = fopen(tmp2,"r")) == NULL) {
5227 return 1;
5228 }
5229
5230 for (;;) {
5231 if (fgets(line,MAXLINE,fd) == NULL)
5232 break;
5233
5234 dodebug(10,"inffile: %s", line);
5235
5236 /* skip empty or hashed lines */
5237 strip_string(line);
5238 if (*line == '#' || *line == '\0')
5239 continue;
5240
5241 /* parse lines */
5242 if (parse_config_line(line,id,value)) {
5243 dodebug(10,"invalid line in infofile");
5244 fclose(fd);
5245 return 1;
5246 }
5247
5248 /* if we are handling a toc file only the title entry
5249 is interesting */
5250 if (istoc) {
5251 if (strcmp("cdtitle",id) == 0) {
5252 g_free(entry->cddb_ttitle);
5253 entry->cddb_ttitle = g_strdup(value);
5254 break;
5255 }
5256 }
5257
5258 if (strcmp("track",id) == 0) {
5259 /* extract track nr */
5260 p = strtok(value," ");
5261 if (p != NULL) {
5262 entry->from_track = atoi(p);
5263 }
5264 }
5265
5266 if (strcmp("title",id) == 0) {
5267 g_free(entry->title);
5268 entry->title = g_strdup(value);
5269 }
5270 if (strcmp("artist",id) == 0) {
5271 g_free(entry->artist);
5272 entry->artist = g_strdup(value);
5273 }
5274 if (strcmp("cddb_ttitle",id) == 0) {
5275 g_free(entry->cddb_ttitle);
5276 entry->cddb_ttitle = g_strdup(value);
5277 }
5278 if (strcmp("cd_discid",id) == 0) {
5279 g_free(entry->cd_discid);
5280 entry->cd_discid = g_strdup(value);
5281 }
5282 if (strcmp("last_session_start",id) == 0) {
5283 entry->last_session_start = atoi(value);
5284 }
5285 if (strcmp("next_session_start",id) == 0) {
5286 entry->next_session_start = atoi(value);
5287 }
5288 }
5289
5290 if (fclose(fd) != 0) {
5291 return 1;
5292 }
5293
5294 return 0;
5295 }
5296
5297
5298 /* call cdrecord -prcap */
5299
fill_device_info(gint devnr,GtkWidget * txt)5300 void fill_device_info(gint devnr, GtkWidget *txt) {
5301 gchar line[MAXLINE];
5302 gchar tmp[MAXLINE];
5303 gchar tmp2[MAXLINE];
5304 gchar tmp3[MAXLINE];
5305 FILE *fpin;
5306 gchar *p;
5307 gint errcount;
5308
5309 /* get bus,id,lun string */
5310 if (convert_devnr2busid_dev(devnr,tmp) != 0) {
5311 g_error("non existing cdrom?");
5312 }
5313
5314 /* build command line */
5315 get_wrap_path_cdrecord(tmp3);
5316 g_snprintf(line,MAXLINE,"%s %s -prcap 2>&1",
5317 tmp3,tmp);
5318
5319 dodebug(1, "calling: %s\n", line);
5320 dolog(3, "Executing: %s\n", line);
5321
5322 if ((fpin = popen(line,"r")) == NULL) {
5323 g_error("popen error\n");
5324 }
5325
5326 errcount = 0;
5327 for (;;) {
5328 if (fgets(line,MAXLINE,fpin) == NULL)
5329 break;
5330 strcpy(tmp,line);
5331
5332 dodebug(10, "prcap: %s", line);
5333
5334 /* error condition? */
5335 p = strtok(tmp,":");
5336 if (p != NULL) {
5337 p = strtok(NULL,"");
5338 if (p != NULL) {
5339 strcpy(tmp2,p);
5340 strip_string(tmp2);
5341 if (strncmp(tmp2,"I/O error",9) == 0) {
5342 errcount++;
5343 /* more then once an i/o-error? */
5344 if (errcount > 1)
5345 break;
5346 }
5347 }
5348 }
5349 convert_for_gtk2_textwidget(line);
5350 gtk_text_insert(GTK_TEXT(txt),
5351 fixedfont,NULL,NULL, line, strlen(line));
5352 }
5353
5354 if (pclose(fpin) == -1) {
5355 g_error("pclose error\n");
5356 }
5357 }
5358
5359
5360 /* eject CD in drive */
5361
eject_cd(gint devnr)5362 void eject_cd(gint devnr) {
5363 gchar line[MAXLINE];
5364 gchar tmp[MAXLINE];
5365 gchar tmp2[MAXLINE];
5366 gchar tmp3[MAXLINE];
5367 FILE *fpin;
5368 gchar *p;
5369 gint errcount;
5370
5371 /* get bus,id,lun string */
5372 if (convert_devnr2busid_dev(devnr,tmp) != 0) {
5373 g_error("non existing cdrom?");
5374 }
5375
5376 /* build command line */
5377 get_wrap_path_cdrecord(tmp3);
5378 g_snprintf(line,MAXLINE,"%s %s -eject 2>&1",
5379 tmp3,tmp);
5380
5381 dodebug(1, "calling: %s\n", line);
5382
5383 if ((fpin = popen(line,"r")) == NULL) {
5384 g_error("popen error\n");
5385 }
5386
5387 /* do actually nothing here ... */
5388 errcount = 0;
5389 for (;;) {
5390 if (fgets(line,MAXLINE,fpin) == NULL)
5391 break;
5392 strcpy(tmp,line);
5393
5394 /* error condition? */
5395 p = strtok(tmp,":");
5396 if (p != NULL) {
5397 p = strtok(NULL,"");
5398 if (p != NULL) {
5399 strcpy(tmp2,p);
5400 strip_string(tmp2);
5401 if (strncmp(tmp2,"I/O error",9) == 0) {
5402 errcount++;
5403 /* more then once an i/o-error? */
5404 if (errcount > 1)
5405 break;
5406 }
5407 }
5408 }
5409 }
5410
5411 if (pclose(fpin) == -1) {
5412 g_error("pclose error\n");
5413 }
5414 }
5415
5416
5417 /* load CD in drive */
5418
load_cd(gint devnr)5419 void load_cd(gint devnr) {
5420 gchar line[MAXLINE];
5421 gchar tmp[MAXLINE];
5422 gchar tmp2[MAXLINE];
5423 gchar tmp3[MAXLINE];
5424 FILE *fpin;
5425 gchar *p;
5426 gint errcount;
5427
5428 /* get bus,id,lun string */
5429 if (convert_devnr2busid_dev(devnr,tmp) != 0) {
5430 g_error("non existing cdrom?");
5431 }
5432
5433 /* build command line */
5434 get_wrap_path_cdrecord(tmp3);
5435 g_snprintf(line,MAXLINE,"%s %s -load 2>&1",
5436 tmp3,tmp);
5437
5438 dodebug(1, "calling: %s\n", line);
5439
5440 if ((fpin = popen(line,"r")) == NULL) {
5441 g_error("popen error\n");
5442 }
5443
5444 /* do actually nothing here ... */
5445 errcount = 0;
5446 for (;;) {
5447 if (fgets(line,MAXLINE,fpin) == NULL)
5448 break;
5449 strcpy(tmp,line);
5450
5451 /* error condition? */
5452 p = strtok(tmp,":");
5453 if (p != NULL) {
5454 p = strtok(NULL,"");
5455 if (p != NULL) {
5456 strcpy(tmp2,p);
5457 strip_string(tmp2);
5458 if (strncmp(tmp2,"I/O error",9) == 0) {
5459 errcount++;
5460 /* more then once an i/o-error? */
5461 if (errcount > 1)
5462 break;
5463 }
5464 }
5465 }
5466 }
5467
5468 if (pclose(fpin) == -1) {
5469 g_error("pclose error\n");
5470 }
5471 }
5472
5473
5474 /* use cdrecord to get the leadout of a TOC */
5475 /* (used for DVDs where cddawav fails ) */
5476
get_cdrecord_toc(gint devnr)5477 static gint get_cdrecord_toc(gint devnr) {
5478 gchar line[MAXLINE];
5479 gchar tmp[MAXLINE];
5480 gchar tmp2[MAXLINE];
5481 gchar tmp3[MAXLINE];
5482 gchar *p;
5483 FILE *fpin;
5484 gint found;
5485
5486 /* get bus,id,lun string */
5487 if (convert_devnr2busid_dev(devnr,tmp) != 0) {
5488 g_error("non existing cdrom?");
5489 }
5490
5491 found = 0;
5492
5493 /* build command line */
5494 get_wrap_path_cdrecord(tmp3);
5495 g_snprintf(line,MAXLINE,"%s %s -toc 2>&1",
5496 tmp3,tmp);
5497
5498 dodebug(1, "calling: %s\n", line);
5499
5500 if ((fpin = popen(line,"r")) == NULL) {
5501 g_error("popen error\n");
5502 }
5503
5504 for (;;) {
5505 if (fgets(line,MAXLINE,fpin) == NULL)
5506 break;
5507 strcpy(tmp,line);
5508 dodebug(10, "cdrecord -toc: %s", line);
5509 }
5510
5511 if (pclose(fpin) == -1) {
5512 g_error("pclose error\n");
5513 }
5514
5515 /* tmp is now the last line of the output */
5516 if (strncmp(tmp,"track:lout", 10) == 0) {
5517
5518 /* extract leadout sector */
5519 p = strtok(tmp,"(");
5520 if (p) {
5521 strncpy(tmp2,p,MAXLINE);
5522 p = rindex(tmp2,':');
5523 if (p) {
5524 strcpy(tmp,p+1);
5525 strip_string(tmp);
5526 found = atoi(tmp);
5527 }
5528 }
5529 }
5530
5531 return found;
5532 }
5533
5534
5535 /* call cdrecord -atip */
5536
get_atip_info(gint devnr,GtkWidget * txt)5537 void get_atip_info(gint devnr, GtkWidget *txt) {
5538 gchar line[MAXLINE];
5539 gchar tmp[MAXLINE];
5540 gchar tmp2[MAXLINE];
5541 gchar tmp3[MAXLINE];
5542 gchar *p;
5543 FILE *fpin;
5544 gint found_atip,errcount;
5545
5546 found_atip = 0;
5547
5548 /* get bus,id,lun string */
5549 if (convert_devnr2busid_dev(devnr,tmp) != 0) {
5550 g_error("non existing cdrom?");
5551 }
5552
5553 get_wrap_path("CDRECORD", tmp3);
5554 g_snprintf(line,MAXLINE,"%s %s -atip 2>&1",
5555 tmp3,tmp);
5556
5557 dodebug(1,"calling: %s\n", line);
5558 dolog(3, "Executing: %s\n", line);
5559
5560 if ((fpin = popen(line,"r")) == NULL) {
5561 g_error("popen error\n");
5562 }
5563
5564 /* syntax for dvd-atip is different */
5565 if (is_dvdwriter(curset.writer_devnr)) {
5566 found_atip = 1;
5567 }
5568
5569 errcount = 0;
5570 for (;;) {
5571 if (fgets(line,MAXLINE,fpin) == NULL)
5572 break;
5573 strcpy(tmp,line);
5574
5575 dodebug(10,"atip: %s", line),
5576
5577 /* error condition? */
5578 p = strtok(tmp,":");
5579 if (p != NULL) {
5580 p = strtok(NULL,"");
5581 if (p != NULL) {
5582 strcpy(tmp2,p);
5583 strip_string(tmp2);
5584 if (strncmp(tmp2,"I/O error",9) == 0) {
5585 errcount++;
5586 /* more then once an i/o-error? */
5587 if (errcount > 1)
5588 break;
5589 }
5590 }
5591 }
5592
5593 /* look for atip-signature */
5594 if (strncmp(line,"ATIP",4) == 0) {
5595 found_atip = 1;
5596 }
5597 if (found_atip) {
5598 gtk_text_insert(GTK_TEXT(txt),
5599 fixedfont,NULL,NULL, line, strlen(line));
5600 }
5601 }
5602
5603 /* no atip-information available? */
5604 if (found_atip == 0) {
5605 /* generate error-message */
5606 strncpy(line,_("\nNo ATIP-Information available.\n\n(Possible reasons: No CD-R/RW loaded or your device\n does not support reading ATIP info)"),MAXLINE);
5607 convert_for_gtk2_textwidget(line);
5608 gtk_text_insert(GTK_TEXT(txt),
5609 NULL,NULL,NULL, line, strlen(line));
5610 }
5611
5612 if (pclose(fpin) == -1) {
5613 g_error("pclose error\n");
5614 }
5615 }
5616
5617
5618 /* get output of cdrecord -msinfo */
5619
read_msinfo_out(gpointer data,gint source,GdkInputCondition cond)5620 static void read_msinfo_out(gpointer data, gint source, GdkInputCondition cond) {
5621 gint n;
5622 gint ret;
5623 gchar line[MAXLINE];
5624 gchar tmp[MAXLINE];
5625 gint nr1, nr2;
5626 gchar *p;
5627
5628 n = read_line(source, line, MAXLINE);
5629
5630 /* finished? */
5631 if (n <= 0) {
5632 gtk_input_remove(readcdda_callback);
5633 gtk_input_remove(readcdda_callback2);
5634
5635 /* pick up return status of child */
5636 wait(&ret);
5637
5638 read_done = WEXITSTATUS(ret);
5639
5640 dodebug(10,"Finished in read_msinfo_out with status: %d\n",
5641 read_done);
5642 return;
5643 }
5644
5645 dodebug(10, "msinfo (stdout): %s\n", line);
5646
5647 /* look for the reload media command */
5648 if (strcmp(line,"Re-load disk and hit <CR>") == 0) {
5649 cdrecord_reload = 1;
5650 return;
5651 }
5652
5653 strcpy(tmp, line);
5654
5655 /* parse msinfo output */
5656 p = strtok(tmp,",");
5657 if (p) {
5658 nr1 = atoi(p);
5659 p = strtok(NULL,"");
5660 if (p) {
5661 nr2 = atoi(p);
5662
5663 /* if parsing was sucessful use new values */
5664 msinfo_nr1 = nr1;
5665 msinfo_nr2 = nr2;
5666 }
5667 }
5668 }
5669
5670
5671 /* get output of cdrecord -msinfo (stderr) */
5672
read_msinfo_stderr(gpointer data,gint source,GdkInputCondition cond)5673 static void read_msinfo_stderr(gpointer data, gint source, GdkInputCondition cond) {
5674 gint n;
5675 gint ret;
5676 gchar line[MAXLINE];
5677
5678
5679 n = read_line(source, line, MAXLINE);
5680
5681 /* finished? */
5682 if (n <= 0) {
5683 gtk_input_remove(readcdda_callback);
5684 gtk_input_remove(readcdda_callback2);
5685
5686 /* pick up return status of child */
5687 wait(&ret);
5688
5689 read_done = WEXITSTATUS(ret);
5690
5691 return;
5692 }
5693
5694 dodebug(10, "msinfo (stderr): %s\n", line);
5695 }
5696
5697
5698 /* call cdrecord -msinfo */
5699 /* returns the start sector and the next writeable adress */
5700 /* or both values -1 when no offset could be found...*/
5701
get_msinfo_info(gint devnr,gint * nr1,gint * nr2)5702 void get_msinfo_info(gint devnr, gint *nr1, gint *nr2) {
5703 gchar line[MAXLINE];
5704 gchar tmp[MAXLINE];
5705 gchar tmp3[MAXLINE];
5706 gint read_out, read_err;
5707
5708 /* if another msinfo running, ignore */
5709 if (read_done == 999) {
5710 return;
5711 }
5712
5713 /* mark our msinfo-process as running */
5714 read_done = 999;
5715 read_output_ctrl = 0;
5716 readerr_count = 0;
5717 cdrecord_reload = 0;
5718 msinfo_nr1 = -1;
5719 msinfo_nr2 = -1;
5720
5721 /* get bus,id,lun string */
5722 if (convert_devnr2busid_dev(devnr,tmp) != 0) {
5723 g_error("non existing cdrom?");
5724 }
5725
5726 /* build command line */
5727 get_wrap_path_cdrecord(tmp3);
5728 g_snprintf(line,MAXLINE,"%s %s -msinfo",
5729 tmp3,tmp);
5730
5731 dodebug(1,"calling: %s\n", line);
5732 dolog(3, "Executing: %s\n", line);
5733
5734 readcdda_pid = full_dpl_pipe3(&read_out,&cdrecord_stdin,&read_err,line,1);
5735 readcdda_pid2 = -1;
5736
5737 fcntl(read_out, F_SETFL, O_NONBLOCK);
5738 fcntl(read_err, F_SETFL, O_NONBLOCK);
5739
5740 readcdda_callback = gdk_input_add(read_out, GDK_INPUT_READ,
5741 (GdkInputFunction) read_msinfo_out, NULL);
5742 readcdda_callback2 = gdk_input_add(read_err, GDK_INPUT_READ,
5743 (GdkInputFunction) read_msinfo_stderr, NULL);
5744
5745 /* now wait until msinfo is finished */
5746 while (read_done == 999) {
5747 wait_and_process_events();
5748
5749 /* check if writer is waiting for reload medium */
5750 if (cdrecord_reload > 0) {
5751 cdrecord_reload = 0;
5752 show_dialog(ICO_WARN, _("Please reload the CD-R in the writer"), T_OK, NULL, NULL, -1);
5753
5754 /* now send CR to cdrecord to let it continue */
5755 if (write(cdrecord_stdin, "\n", 1) != 1) {
5756 g_warning("write error to cdrecord pipe\n");
5757 }
5758 }
5759
5760 }
5761
5762 close(read_err);
5763 close(read_out);
5764 close(cdrecord_stdin);
5765
5766 dodebug(2,"received msinfo: %d,%d\n", msinfo_nr1, msinfo_nr2);
5767
5768 /* workaround for drives reporting 0,0 instead of -1,-1 */
5769 if (msinfo_nr1 == 0 && msinfo_nr2 == 0) {
5770 msinfo_nr1 = -1;
5771 msinfo_nr2 = -1;
5772 }
5773
5774 *nr1 = msinfo_nr1;
5775 *nr2 = msinfo_nr2;
5776 }
5777
5778
5779 /* interpret output of blank=help and sort into memory structure */
5780
parse_blankmode(gchar * line)5781 static void parse_blankmode(gchar *line) {
5782 gchar tmp[MAXLINE];
5783 gchar tmp2[MAXLINE];
5784 gchar drv[MAXLINE];
5785 gchar *p1;
5786 gint n;
5787
5788 if (strncmp(line,"Blanking options:",17) != 0 ) {
5789
5790 strcpy(tmp,line);
5791 strip_string(tmp);
5792
5793 p1=strtok(tmp," \t");
5794 strcpy(drv,p1);
5795 /* now drv contains the driver name */
5796
5797 p1=strtok(NULL,"");
5798 strcpy(tmp2,p1);
5799 strip_string(tmp2);
5800 /* now tmp2 contains the description */
5801
5802 /* now get the description of last mode to ensure
5803 we dont have double modes */
5804 if (drvcount != 0) {
5805 if (strcmp(tmp2,blankmodes[drvcount-1]->desc) == 0) {
5806 /* double drive mode - ignore */
5807 return;
5808 }
5809 }
5810
5811 /* allocate structure */
5812 blankmodes[drvcount]=g_new(writer_driver_t,1);
5813
5814 n = strlen(drv)+1;
5815 blankmodes[drvcount]->driver=g_new(gchar,n);
5816 strcpy(blankmodes[drvcount]->driver,drv);
5817
5818 n = strlen(tmp2)+1;
5819 blankmodes[drvcount]->desc=g_new(gchar,n);
5820 strcpy(blankmodes[drvcount]->desc,tmp2);
5821
5822 drvcount++;
5823 if (drvcount >= MAXBLANKMODES) {
5824 g_error("Error: More than %d blank modes found\n",
5825 MAXBLANKMODES);
5826 }
5827 }
5828 }
5829
5830
5831 /* print memory-structure with drivers (debug purposes) */
5832
print_blankmodes()5833 static void print_blankmodes() {
5834 gint count;
5835
5836 dodebug(2,"--------- cdrecord blankmodes-structure --------\n");
5837 count = 0;
5838 while(blankmodes[count] != NULL) {
5839 dodebug(2,"%s:%s\n",
5840 blankmodes[count]->driver,
5841 blankmodes[count]->desc);
5842
5843 count++;
5844 }
5845 }
5846
5847
5848 /* call cdrecord blank=help */
5849
scanblankmodes()5850 void scanblankmodes() {
5851 gchar line[MAXLINE];
5852 FILE *fpin;
5853
5854 /* allocate memory */
5855 blankmodes = g_new0(writer_driver_t *,MAXBLANKMODES);
5856 drvcount = 0;
5857
5858 get_wrap_path_cdrecord(line);
5859 strcat(line," blank=help 2>&1");
5860
5861 dodebug(1, "calling: %s\n", line);
5862
5863 if ((fpin = popen(line,"r")) == NULL) {
5864 g_error("popen error\n");
5865 }
5866
5867 for (;;) {
5868 if (fgets(line,MAXLINE,fpin) == NULL)
5869 break;
5870 dodebug(10, "blankmodes: %s", line);
5871 parse_blankmode(line);
5872 }
5873
5874 if (pclose(fpin) == -1) {
5875 g_error("pclose error\n");
5876 }
5877
5878
5879 if (debug) print_blankmodes();
5880 }
5881
5882
5883 /* open a file and read one sector into a memory-buffer */
5884 /* return 1 on success */
5885
read_info_sector_from_file(gchar * isoname,gchar * buf,gint bsize)5886 gint read_info_sector_from_file(gchar *isoname, gchar *buf, gint bsize) {
5887 gint fd;
5888
5889 dodebug(1, "read iso header from %s\n", isoname);
5890
5891 fd = open (isoname, O_RDONLY, 0);
5892 if (fd == -1) {
5893 return 0;
5894 }
5895
5896 /* forward to info-sector */
5897 if(lseek(fd, 32768, SEEK_SET) < 0) {
5898 close(fd);
5899 return 0;
5900 }
5901
5902 /* read one sector */
5903 if (read(fd, buf, bsize) != bsize) {
5904 close(fd);
5905 return 0;
5906 }
5907
5908 close(fd);
5909 return 1;
5910 }
5911
5912
5913 /* call readcd to read the info-sector from a data-track into a
5914 memory buffer. return 1 if all ok */
5915
read_info_sector_from_dev(gint devnr,gchar * buf,gint bsize,gint startsector)5916 gint read_info_sector_from_dev(gint devnr, gchar *buf, gint bsize, gint startsector) {
5917 gchar tmp[MAXLINE];
5918 gchar tmp2[MAXLINE];
5919 gchar cmd[MAXLINE];
5920 FILE *fpin;
5921 gint s1, s2;
5922
5923 /* get bus,id,lun string */
5924 if (convert_devnr2busid_dev(devnr,tmp) != 0) {
5925 g_error("non existing cdrom?");
5926 }
5927
5928 s1 = startsector+16;
5929 s2 = startsector+17;
5930
5931 /* build command-line */
5932 get_wrap_path("READCD",tmp2);
5933 g_snprintf(cmd,MAXLINE,"%s %s sectors=%d-%d -s f=- 2>/dev/null",
5934 tmp2, tmp, s1, s2);
5935
5936 dodebug(1, "calling: %s\n", cmd);
5937
5938 if ((fpin = popen(cmd,"r")) == NULL) {
5939 g_error("popen error\n");
5940 }
5941
5942 /* read into buffer */
5943 if (fread(buf, bsize, 1, fpin) != 1) {
5944 pclose(fpin);
5945 return 0;
5946 }
5947
5948 if (pclose(fpin) == -1) {
5949 g_error("pclose error\n");
5950 }
5951
5952 return 1;
5953 }
5954
5955
5956 /* get output of cdrecord -blank */
5957
read_blank_out(gpointer data,gint source,GdkInputCondition cond)5958 static void read_blank_out(gpointer data, gint source, GdkInputCondition cond) {
5959 gint n;
5960 gint ret;
5961 gchar line[MAXLINE];
5962 gchar tmp[MAXLINE];
5963
5964 n = read_line(source, line, MAXLINE);
5965
5966 /* finished? */
5967 if (n <= 0) {
5968
5969 gtk_input_remove(readcdda_callback);
5970 gtk_input_remove(readcdda_callback2);
5971
5972 /* pick up return status of child */
5973 wait(&ret);
5974
5975 read_done = WEXITSTATUS(ret);
5976
5977 /* perhaps the are-you-sure-you-want-to-abort dialog
5978 is still running? remove to be sure we can continue */
5979 if (dialog_done == 999) {
5980 dialog_done = -1;
5981 }
5982
5983 /* or cdrecord died by signal? e.g. SIGALRM */
5984 if (WIFSIGNALED(ret) && read_done == 0) {
5985
5986 /* most likely invalid prodvd key */
5987 if (curset.isProDVD) {
5988 strncpy(tmp, "\nReceived ALARM from cdrecord-ProDVD. Aborting blank...\nInvalid ProDVD key?\n", MAXLINE);
5989
5990 convert_for_gtk2_textwidget(tmp);
5991 gtk_text_insert(GTK_TEXT(readtrack_textview),
5992 fixedfont,NULL,NULL,tmp, strlen(tmp));
5993 read_done = 1;
5994 }
5995 }
5996
5997 dodebug(10,"Finished in read_blank_out with status: %d\n",
5998 read_done);
5999 return;
6000 }
6001
6002 dodebug(10, "blank (stdout): %s\n", line);
6003
6004 strip_string(line);
6005
6006 /* look for the reload media command */
6007 if (strcmp(line,"Re-load disk and hit <CR>") == 0) {
6008 cdrecord_reload = 1;
6009 /* if there was a fileselector running, cancel it */
6010 dialog_done3 = -1;
6011 return;
6012 }
6013
6014 /* skip all lines that end with "seconds." */
6015 if (n > 8) {
6016 if (strstr(line, "seconds.")) {
6017 return;
6018 }
6019 }
6020
6021 strcpy(tmp,line);
6022 strcat(tmp,"\n");
6023
6024 convert_for_gtk2_textwidget(tmp);
6025 gtk_text_insert(GTK_TEXT(readtrack_textview),
6026 fixedfont,NULL,NULL,tmp, strlen(tmp));
6027
6028 }
6029
6030
6031 /* get output of cdrecord -blank (stderr) */
6032
read_blank_stderr(gpointer data,gint source,GdkInputCondition cond)6033 static void read_blank_stderr(gpointer data, gint source, GdkInputCondition cond) {
6034 gint n;
6035 gint ret;
6036 gchar line[MAXLINE];
6037 gchar tmp[MAXLINE];
6038 gchar tmp2[MAXLINE];
6039 gchar *p;
6040
6041 n = read_line(source, line, MAXLINE);
6042
6043 /* finished? */
6044 if (n <= 0) {
6045
6046 gtk_input_remove(readcdda_callback);
6047 gtk_input_remove(readcdda_callback2);
6048
6049 /* pick up return status of child */
6050 wait(&ret);
6051
6052 read_done = WEXITSTATUS(ret);
6053
6054 /* perhaps the are-you-sure-you-want-to-abort dialog
6055 is still running? remove to be sure we can continue */
6056 if (dialog_done == 999) {
6057 dialog_done = -1;
6058 }
6059
6060 dodebug(10,"Finished in read_blank_stderr with status: %d\n",
6061 read_done);
6062
6063 return;
6064 }
6065
6066 dodebug(10, "blank (stderr): %s\n", line);
6067
6068 /* check if we have an medium-i/o-error */
6069 strcpy(tmp,line);
6070 p = strtok(tmp,":");
6071 if (p != NULL) {
6072 p = strtok(NULL,"");
6073 if (p != NULL) {
6074 strcpy(tmp2,p);
6075 strip_string(tmp2);
6076 if (strncmp(tmp2,"I/O error",9) == 0) {
6077 readerr_count++;
6078 /* more then once an i/o-error? */
6079 if (readerr_count > 1) {
6080 kill_readcdda();
6081 dialog_done2 = 999;
6082 read_output_ctrl = 2;
6083 }
6084 }
6085 }
6086 }
6087
6088 /* check if we got an error because of no disk */
6089 if (n > 21) {
6090 strcpy(tmp, line+(strlen(line)-21));
6091 if (strcmp(tmp, "No disk / Wrong disk!") == 0) {
6092 /* mark we got no disk */
6093 read_output_ctrl = 2;
6094 }
6095 }
6096
6097 strcpy(tmp,line);
6098 strcat(tmp,"\n");
6099
6100 convert_for_gtk2_textwidget(tmp);
6101 gtk_text_insert(GTK_TEXT(readtrack_textview),
6102 fixedfont,NULL,NULL,tmp, strlen(tmp));
6103
6104 }
6105
6106
6107 /* call cdrecord -blank */
6108
start_blanking_process(gint devnr,GtkWidget * text_window)6109 gint start_blanking_process(gint devnr, GtkWidget *text_window) {
6110 char tmp[MAXLINE];
6111 char tmp2[MAXLINE];
6112 char tmp3[MAXLINE];
6113 char tmp4[MAXLINE];
6114 char tmp5[MAXLINE];
6115 char tmp6[MAXLINE];
6116 char cmd[MAXLINE];
6117 gint read_out, read_err;
6118 gint ret;
6119
6120 /* if another blank running, ignore */
6121 if (read_done == 999) {
6122 return -1;
6123 }
6124
6125 /* mark our blanking-process as running */
6126 read_done = 999;
6127 read_output_ctrl = 0;
6128 readerr_count = 0;
6129 cdrecord_reload = 0;
6130
6131 /* save text-window */
6132 readtrack_textview = text_window;
6133
6134 /* get bus,id,lun string */
6135 if (convert_devnr2busid_dev(devnr,tmp) != 0) {
6136 g_error("non existing cdrom?");
6137 }
6138
6139 /* get blankmode and settings */
6140 strcpy(tmp2, blankmodes[curset.blankmode]->driver);
6141
6142 strcpy(tmp3,"");
6143 if (curset.blank_force) {
6144 strcat(tmp3, "-force ");
6145 }
6146 if (curset.blank_eject) {
6147 strcat(tmp3, "-eject ");
6148 }
6149 if (curset.writeignsize == 1) {
6150 strcat(tmp3,"-ignsize ");
6151 }
6152 if (curset.writeimmed == 1) {
6153 strcat(tmp3,"-immed ");
6154 }
6155
6156 if (get_cur_writer_speed() >= 0) {
6157 g_snprintf(tmp4,MAXLINE,"speed=%d ", get_cur_writer_speed());
6158 strcat(tmp3, tmp4);
6159 }
6160
6161 get_wrap_path("CDRECORD", tmp5);
6162
6163 g_snprintf(cmd, MAXLINE,
6164 "%s %s gracetime=%d -v %sblank=%s",
6165 tmp5, tmp, get_gracetime(), tmp3, tmp2);
6166
6167 dodebug(1, "spawning: %s\n",cmd);
6168 dolog(1, "Blanking CD with mode %s\n",tmp2);
6169 dolog(3, "Executing: %s\n", cmd);
6170
6171 readcdda_pid = full_dpl_pipe3(&read_out,&cdrecord_stdin,&read_err,cmd,1);
6172 readcdda_pid2 = -1;
6173
6174 fcntl(read_out, F_SETFL, O_NONBLOCK);
6175 fcntl(read_err, F_SETFL, O_NONBLOCK);
6176
6177 readcdda_callback = gdk_input_add(read_out, GDK_INPUT_READ,
6178 (GdkInputFunction) read_blank_out, NULL);
6179 readcdda_callback2 = gdk_input_add(read_err, GDK_INPUT_READ,
6180 (GdkInputFunction) read_blank_stderr, NULL);
6181
6182 /* now wait until blank is finished */
6183 while (read_done == 999) {
6184 wait_and_process_events();
6185
6186 /* check if writer is waiting for reload medium */
6187 if (cdrecord_reload > 0) {
6188 cdrecord_reload = 0;
6189 show_dialog(ICO_WARN, _("Please reload the CD-R in the writer"), T_OK, NULL, NULL, -1);
6190
6191 /* now send CR to cdrecord to let it continue */
6192 if (write(cdrecord_stdin, "\n", 1) != 1) {
6193 g_warning("write error to cdrecord pipe\n");
6194 }
6195 }
6196
6197 /* check if somebody clicked on cancel */
6198 if (dialog_done2 != 999) {
6199 ret = show_dialog(ICO_WARN, _("Are you sure you want to abort the writing?\nAborting may damage the CD-RW and may require that you have\nto power-cycle the burner to get working again."),
6200 T_YES, T_NO, NULL, 1);
6201 if (ret == 0) {
6202 /* really abort */
6203 kill_readcdda();
6204 /* mark we aborted */
6205 read_output_ctrl = 1;
6206 dialog_done2 = 999;
6207 } else {
6208 /* not abort - undo button press */
6209 dialog_done2 = 999;
6210 }
6211 }
6212 }
6213
6214 close(read_err);
6215 close(read_out);
6216 close(cdrecord_stdin);
6217
6218 /* no disk */
6219 if (read_output_ctrl == 2) {
6220 gtk_text_insert(GTK_TEXT(readtrack_textview),
6221 fixedfont,NULL,NULL,"\n",1);
6222
6223 strncpy(tmp6, _("No disk or wrong disk loaded."), MAXLINE);
6224 convert_for_gtk2_textwidget(tmp6);
6225 gtk_text_insert(GTK_TEXT(readtrack_textview),
6226 fixedfont,NULL,NULL,tmp6,strlen(tmp6));
6227 gtk_text_insert(GTK_TEXT(readtrack_textview),
6228 fixedfont,NULL,NULL,"\n\n",2);
6229 }
6230
6231 /* error while blanking */
6232 if (read_done != 0) {
6233 return 1;
6234 }
6235
6236 /* we killed the process */
6237 if (read_output_ctrl == 1) {
6238 return 2;
6239 }
6240
6241 return 0;
6242 }
6243
6244
6245 /* a timer function to see if there is output from cdrecord within a given
6246 time */
6247
cdrtimer_callback(gpointer data)6248 static gint cdrtimer_callback(gpointer data) {
6249 time_t acttime;
6250 gint diff;
6251 gint ret;
6252
6253 /* how many time passed since the last output of cdrecord? */
6254 acttime = time((time_t *) 0);
6255 diff = (gint) (acttime - cdrcmdtimer);
6256
6257 /* we counting down seconds, but not receiving output since over 5? */
6258 if (diff > 5) {
6259 gtk_timeout_remove(cdrtimer);
6260 cdrtimer = 0;
6261
6262 dodebug(10,"cdrecord.prodvd output-timer run out - assume termination.\n");
6263 /* force termination of cdrecord.prodvd */
6264 read_write_out(NULL, -1, 0);
6265
6266 /* if mkisofs is marked as running, kill it too */
6267 if (mkisofs_pid != -1) {
6268 dodebug(2,"sending SIGINT to mkisofs (pid %d)\n",
6269 (gint) mkisofs_pid);
6270 kill(mkisofs_pid, SIGINT);
6271 waitpid(mkisofs_pid, &ret, 0);
6272 }
6273
6274 return(FALSE);
6275 }
6276
6277 return(TRUE);
6278 }
6279
6280
6281 /* special case to try to get some last output from stderr after
6282 cdrecord terminated */
6283
read_write_stderr_last(gint source)6284 static void read_write_stderr_last(gint source) {
6285 gint n;
6286 gchar line[MAXLINE];
6287 gchar tmp[MAXLINE];
6288
6289 /* get as many output left in the pipe as possible */
6290 while (1) {
6291 n = read_line(source, line, MAXLINE);
6292
6293 if (n <= 0) {
6294 /* pipe empty */
6295 return;
6296 }
6297
6298 dodebug(10,"cdrecord (stderr-last): %s\n", line);
6299
6300 strcpy(tmp,line);
6301 strcat(tmp,"\n");
6302
6303 convert_for_gtk2_textwidget(tmp);
6304 gtk_text_insert(GTK_TEXT(readtrack_textview),
6305 fixedfont,NULL,NULL,tmp, strlen(tmp));
6306 }
6307 }
6308
6309
6310 /* get output of cdrecord */
6311
read_write_out(gpointer data,gint source,GdkInputCondition cond)6312 static void read_write_out(gpointer data, gint source, GdkInputCondition cond) {
6313 gint n;
6314 gint ret;
6315 gchar line[MAXLINE];
6316 gchar tmp[MAXLINE];
6317 gchar tmp2[MAXLINE];
6318 gchar *p, *p2;
6319 gint tnr, donemb, fullmb, fifoval, intbufval;
6320 gfloat pval, pval2, pval3, pval4, avgspd;
6321 static gint writecompleted;
6322 gint cdrecord_stderr;
6323
6324 if (source != -1) {
6325 n = read_line(source, line, MAXLINE);
6326 } else {
6327 /* force finish */
6328 n = -1;
6329 }
6330
6331 /* finished? */
6332 if (n <= 0) {
6333 if (data) {
6334 /* try to get some last output from stderr */
6335 cdrecord_stderr = GPOINTER_TO_INT(data);
6336 read_write_stderr_last(cdrecord_stderr);
6337 }
6338
6339 dodebug(10,"cdrecord (stdout): EOF\n");
6340 gtk_input_remove(readcdda_callback);
6341 gtk_input_remove(readcdda_callback2);
6342
6343 /* pick up return status of child */
6344 waitpid((pid_t)readcdda_pid, &ret, WNOHANG);
6345
6346 read_done = WEXITSTATUS(ret);
6347
6348 if (writecompleted == 1 && read_done == 0) {
6349 /* set total progress bar to 100% */
6350 gtk_progress_set_percentage(
6351 GTK_PROGRESS(readtrack_pbar2), 1.0);
6352 set_xcdr_title(toplevel,viewmode_dialog,100);
6353
6354 /* and small view too */
6355 g_snprintf(tmp,MAXLINE,"%d%% / %d%%",100,100);
6356 gtk_label_set_text(
6357 GTK_LABEL(readtrack_small_info2),tmp);
6358 }
6359
6360 /* perhaps the are-you-sure-you-want-to-abort dialog
6361 is still running? remove to be sure we can continue */
6362 if (dialog_done == 999) {
6363 dialog_done = -1;
6364 }
6365
6366 /* or cdrecord died by signal? e.g. SIGALRM */
6367 if (WIFSIGNALED(ret) && read_done == 0) {
6368
6369 /* most likely invalid prodvd key */
6370 if (curset.isProDVD && curset.cdrtype > 1000) {
6371 read_done = 2;
6372 }
6373 }
6374
6375 dodebug(10,"Finished in read_write_out with status: %d\n",
6376 read_done);
6377 return;
6378 }
6379
6380 dodebug(10,"cdrecord (stdout): %s\n", line);
6381 cdrcmdtimer = time((time_t *) 0);
6382
6383 strip_string(line);
6384
6385 /* look for the reload media command */
6386 if (strcmp(line,"Re-load disk and hit <CR>") == 0) {
6387 cdrecord_reload = 1;
6388 /* if there was a fileselector running, cancel it */
6389 dialog_done3 = -1;
6390 return;
6391 }
6392
6393 /* cdrecord will wait for SIGUSR1 while waiting for reload? */
6394 if (strstr(line, "send SIGUSR1 to continue")) {
6395 cdrecord_reload = 2;
6396 return;
6397 }
6398
6399 /* prodvd and beginning to write soon? */
6400 if (curset.isProDVD && curset.cdrtype > 1000) {
6401 if (strstr(line,"Last chance to quit")) {
6402 cdrtimer = gtk_timeout_add(1000,
6403 cdrtimer_callback, NULL);
6404 }
6405
6406 /* if we get that far, we are sure we are over the key
6407 check */
6408 if (strstr(line,"1 second")) {
6409 if (cdrtimer) {
6410 gtk_timeout_remove(cdrtimer);
6411 cdrtimer = 0;
6412 }
6413 }
6414 }
6415
6416 /* skip all lines that contain "seconds." */
6417 if (n > 8) {
6418 if (strstr(line, "seconds.")) {
6419 /* mark we are now ready to rumble */
6420 read_output_ctrl = 3;
6421
6422 /* starting the write here */
6423 writecompleted = 0;
6424 return;
6425 }
6426 }
6427
6428 /* track lines */
6429 if (read_output_ctrl > 0 && strncmp(line,"Track",5) == 0 &&
6430 !strstr(line,"audio") && !strstr(line,"data")) {
6431
6432 /* parser */
6433 avgspd = 0.0;
6434 strcpy(tmp, line+6);
6435 p = strtok(tmp,":");
6436 if (p == NULL) return;
6437 tnr = atoi(p);
6438 p = strtok(NULL," ");
6439 if (p == NULL) return;
6440 if ((strncmp(p,"Total",5) != 0) &&
6441 (strncmp(p,"writing",7) != 0)) {
6442 /* not the Total bytes written line? */
6443 donemb = atoi(p);
6444
6445 p = strtok(NULL," ");
6446 p = strtok(NULL," ");
6447 if (p == NULL) return;
6448 fullmb = atoi(p);
6449
6450 p = strtok(NULL,"%");
6451 p2 = strtok(NULL,"");
6452 if (p2 == NULL) {
6453 /* no fifo value available - start of track */
6454 fifoval = 0;
6455 intbufval = 0;
6456 avgspd = 0.0;
6457 if (writeparams.tracktype[tnr] == 0) {
6458 /* data track */
6459 convert_frames2mbstring(
6460 writeparams.frames[tnr],tmp);
6461 g_snprintf(tmp2,MAXLINE, _("Writing data track %d/%d [%s]"),
6462 tnr,
6463 writeparams.nrtracks, tmp);
6464 if (writeparams.simulation)
6465 strcat(tmp2,_(" [Simulation]"));
6466 gtk_label_set_text(
6467 GTK_LABEL(readtrack_info_label),
6468 tmp2);
6469 } else {
6470 /* audio track */
6471 convert_frames2minstring(
6472 writeparams.frames[tnr],tmp);
6473 g_snprintf(tmp2,MAXLINE, _("Writing audio track %d/%d [%s]"),
6474 tnr,
6475 writeparams.nrtracks, tmp);
6476 if (writeparams.simulation)
6477 strcat(tmp2,_(" [Simulation]"));
6478 gtk_label_set_text(
6479 GTK_LABEL(readtrack_info_label),
6480 tmp2);
6481 }
6482 /* small view label */
6483 g_snprintf(tmp2,MAXLINE, _("Writing %d/%d:"),
6484 tnr, writeparams.nrtracks);
6485 gtk_label_set_text(
6486 GTK_LABEL(readtrack_small_info),tmp2);
6487 } else {
6488 /* extract fifo value */
6489 strcpy(tmp2,p);
6490 p = rindex(tmp2,' ');
6491 if (p == NULL) return;
6492 fifoval = atoi(p);
6493
6494 /* extract buf/spd value */
6495 strcpy(tmp2,p2);
6496 p = strtok(tmp2,"%");
6497 if (p) {
6498 p2 = strtok(NULL,"");
6499 strcpy(tmp,p);
6500 p = rindex(tmp,' ');
6501 if (p == NULL) return;
6502 if (strstr(tmp, "buf")) {
6503 intbufval = atoi(p);
6504 } else {
6505 /* no buf value? speed next */
6506 intbufval = 0;
6507 strcpy(tmp2,tmp);
6508 p2 = tmp2;
6509 }
6510 if (p2) {
6511 strcpy(tmp,p2);
6512 p = strtok(tmp,"x");
6513 if (p) {
6514 strcpy(tmp2,p);
6515 p = rindex(tmp2,' ');
6516 if (p == NULL) return;
6517 avgspd = (gfloat)atof(p);
6518 }
6519 }
6520 } else {
6521 intbufval = 0;
6522 avgspd = 0.0;
6523 }
6524 }
6525 /* done with parsing */
6526
6527 /* calculate current track progressbar values */
6528 if (fullmb != 0) {
6529 pval = (gfloat)donemb/(gfloat)fullmb;
6530 if (pval > 1.0) pval = 1.0;
6531
6532 gtk_progress_set_percentage(
6533 GTK_PROGRESS(readtrack_pbar1), pval);
6534 } else {
6535 pval = 0.0;
6536 }
6537
6538 /* calculate total track progressbar */
6539 pval2 = (writeparams.pct_so_far_arr[tnr] +
6540 (pval * writeparams.pct_this_track_arr[tnr]));
6541 /* go only up to 99% */
6542 if (pval2 >= 0.99) pval2 = 0.99;
6543
6544 if (writeparams.nrtracks != 1) {
6545 gtk_progress_set_percentage(
6546 GTK_PROGRESS(readtrack_pbar2), pval2);
6547 set_xcdr_title(toplevel,viewmode_dialog,(gint)(pval2*100+0.5));
6548 } else {
6549 /* just one track? total is the same as track */
6550 if (pval < 1.0) {
6551 gtk_progress_set_percentage(
6552 GTK_PROGRESS(readtrack_pbar2),
6553 pval);
6554 set_xcdr_title(toplevel,viewmode_dialog,(gint)(pval*100+0.5));
6555 } else {
6556 gtk_progress_set_percentage(
6557 GTK_PROGRESS(readtrack_pbar2),
6558 0.99);
6559 set_xcdr_title(toplevel,viewmode_dialog,99);
6560 }
6561 }
6562
6563 /* fifo value */
6564 pval3 = (gfloat)fifoval /100;
6565 if (pval3 > 1.0) pval3 = 1.0;
6566 gtk_progress_set_percentage(
6567 GTK_PROGRESS(readtrack_pbar3), pval3);
6568
6569 /* add internal buffer and average speed too */
6570 pval4 = (gfloat)intbufval /100;
6571 if (pval4 > 1.0) pval4 = 1.0;
6572 gtk_progress_set_percentage(
6573 GTK_PROGRESS(readtrack_pbar4), pval4);
6574
6575 if (avgspd > 0.0) {
6576 g_snprintf(tmp,MAXLINE,"%.1fx",avgspd);
6577 gtk_label_set_text(GTK_LABEL(readtrack_spd), tmp);
6578 }
6579
6580 /* now update info for small view */
6581 g_snprintf(tmp,MAXLINE,"%d%% / %d%%",
6582 (gint)(pval*100+0.5), (gint)(pval2*100+0.5));
6583 gtk_label_set_text(
6584 GTK_LABEL(readtrack_small_info2),tmp);
6585
6586 return;
6587 }
6588 }
6589
6590 /* fixating */
6591 if (strncmp(line,"Fixating...",11) == 0) {
6592 gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Fixating..."));
6593 /* ok, write is finished I guess */
6594 writecompleted = 1;
6595 }
6596
6597 /* avg speed line */
6598 if (strncmp(line,"Average write speed", 19) == 0) {
6599 strcpy(tmp,line);
6600 p = strtok(tmp,"x");
6601 if (p) {
6602 strcpy(tmp2,p);
6603 p = rindex(tmp2,' ');
6604 if (p) {
6605 avgspd = (gfloat)atof(p);
6606 g_snprintf(tmp,MAXLINE,"%.1fx",avgspd);
6607 gtk_label_set_text(GTK_LABEL(readtrack_spd), tmp);
6608 }
6609 }
6610 }
6611
6612 strcpy(tmp,line);
6613 strcat(tmp,"\n");
6614
6615 convert_for_gtk2_textwidget(tmp);
6616 gtk_text_insert(GTK_TEXT(readtrack_textview),
6617 fixedfont,NULL,NULL,tmp, strlen(tmp));
6618
6619 }
6620
6621
read_write_stderr(gpointer data,gint source,GdkInputCondition cond)6622 static void read_write_stderr (gpointer data, gint source, GdkInputCondition cond) {
6623 gint n;
6624 gint ret;
6625 gchar line[MAXLINE];
6626 gchar tmp[MAXLINE];
6627 gchar tmp2[MAXLINE];
6628 gchar *p;
6629
6630 n = read_line(source, line, MAXLINE);
6631
6632 /* finished? */
6633 if (n <= 0) {
6634 dodebug(10,"cdrecord (stderr): EOF\n");
6635 gtk_input_remove(readcdda_callback);
6636 gtk_input_remove(readcdda_callback2);
6637
6638 /* pick up return status of child */
6639 waitpid((pid_t)readcdda_pid, &ret, WNOHANG);
6640
6641 read_done = WEXITSTATUS(ret);
6642
6643 /* perhaps the are-you-sure-you-want-to-abort dialog
6644 is still running? remove to be sure we can continue */
6645 if (dialog_done == 999) {
6646 dialog_done = -1;
6647 }
6648
6649 return;
6650 }
6651
6652 dodebug(10,"cdrecord (stderr): %s\n", line);
6653
6654 /* check if we have an medium-i/o-error */
6655 strcpy(tmp,line);
6656 p = strtok(tmp,":");
6657 if (p != NULL) {
6658 p = strtok(NULL,"");
6659 if (p != NULL) {
6660 strcpy(tmp2,p);
6661 strip_string(tmp2);
6662 if (strncmp(tmp2,"I/O error",9) == 0) {
6663 readerr_count++;
6664 /* more then once an i/o-error? */
6665 if (readerr_count > 1) {
6666 kill_readcdda();
6667 dialog_done2 = 999;
6668 read_output_ctrl = 2;
6669 }
6670 }
6671 /* check also if cannot send CUE sheet */
6672 if (strncmp(tmp2,"Cannot send CUE sheet", 21) == 0) {
6673 read_output_ctrl = 4;
6674 }
6675 /* check for common error on TAO only devices */
6676 if (strncmp(tmp2,"Cannot open new session.",24) == 0 && get_cur_writemode() == 0) {
6677 read_output_ctrl = 4;
6678 }
6679 /* check Medium error/buffer underrun */
6680 if (strncmp(tmp2,"Input/output error",18) == 0) {
6681 read_output_ctrl = 5;
6682 }
6683 }
6684 }
6685
6686
6687 /* check if we got an error because of no disk */
6688 if (n > 21) {
6689 strcpy(tmp, line+(strlen(line)-21));
6690 if (strcmp(tmp, "No disk / Wrong disk!") == 0) {
6691 /* mark we got no disk */
6692 read_output_ctrl = 2;
6693 }
6694 }
6695
6696 strcpy(tmp,line);
6697 strcat(tmp,"\n");
6698
6699 convert_for_gtk2_textwidget(tmp);
6700 gtk_text_insert(GTK_TEXT(readtrack_textview),
6701 fixedfont,NULL,NULL,tmp, strlen(tmp));
6702 }
6703
6704
6705 /* display an error when useing prodvd and cdrecord aborts */
6706
display_invalid_prodvdkey()6707 static void display_invalid_prodvdkey() {
6708
6709 if (curset.isProDVD && curset.cdrtype > 1000) {
6710 show_dialog(ICO_WARN, _("cdrecord-ProDVD terminated.\n\nMost likely because you have entered\nan invalid key. Please check if it is correct."), T_OK, NULL, NULL, 0);
6711 }
6712 }
6713
6714
6715 /* call cdrecord to write some tracks */
6716
start_write_action(gint devnr)6717 gint start_write_action(gint devnr) {
6718 GList *loop;
6719 track_read_param_t *trackparam;
6720 gchar tmp[MAXLINE];
6721 gchar tmptmp[MAXLINE];
6722 gchar tmp2[MAXLINE];
6723 gchar tmp3[MAXLINE];
6724 gchar cmd[MAXLINE*10]; /* extra big buffer for very long cdrecord options */
6725 gchar outcmd[MAXLINE];
6726 gint read_out, read_err;
6727 gint ret, tracknr;
6728 gint varirec_on, tmp_writer_speed;
6729 gint wrmode;
6730
6731 /* if another write running, ignore */
6732 if (read_done == 999) {
6733 return -1;
6734 }
6735
6736 /* mark our write-process as running */
6737 read_done = 999;
6738 read_output_ctrl = 0;
6739 pct_so_far = 0.0;
6740 cdrecord_reload = 0;
6741 cdrtimer = 0;
6742
6743 strcpy(outcmd,"");
6744
6745 /* set info label */
6746 gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Initializing CD-Writer..."));
6747
6748 /* reset writeparams-arrays */
6749 g_free(writeparams.tracktype);
6750 g_free(writeparams.frames);
6751 g_free(writeparams.pct_so_far_arr);
6752 g_free(writeparams.pct_this_track_arr);
6753 writeparams.tracktype = g_new0(gint,MAXTRACKS);
6754 writeparams.frames = g_new0(gint,MAXTRACKS);
6755 writeparams.pct_so_far_arr = g_new0(gfloat,MAXTRACKS);
6756 writeparams.pct_this_track_arr = g_new0(gfloat,MAXTRACKS);
6757 writeparams.nrtracks = 0;
6758 writeparams.simulation = curset.writesimul;
6759
6760 /* get bus,id,lun string */
6761 if (convert_devnr2busid_dev(devnr,tmp) != 0) {
6762 g_error("non existing cdrom?");
6763 }
6764
6765 /* get driveropts */
6766 varirec_on = do_driveropts(tmp3, curset.writer_devnr);
6767
6768 /* build command line */
6769 get_wrap_path_cdrecord(tmp2);
6770 g_snprintf(cmd, MAXLINE*10,
6771 "%s %s gracetime=%d fs=%dk %s -v -useinfo",
6772 tmp2, tmp, get_gracetime(), get_cur_writer_fifo(), tmp3);
6773
6774 if (get_cur_writer_drvmode() >= 0) {
6775 if (drivers[get_cur_writer_drvmode()] != NULL) {
6776 g_snprintf(tmp,MAXLINE," driver=%s",
6777 drivers[get_cur_writer_drvmode()]->driver);
6778 strcat(cmd,tmp);
6779 }
6780 }
6781
6782 /* special case with varirec - always use 4x here */
6783 if (varirec_on) {
6784 tmp_writer_speed = 4;
6785 } else {
6786 tmp_writer_speed = get_cur_writer_speed();
6787 }
6788 if (get_cur_writer_speed() >= 0) {
6789 g_snprintf(tmp,MAXLINE," speed=%d", tmp_writer_speed);
6790 strcat(cmd, tmp);
6791 }
6792
6793 if (curset.multisession == 0) {
6794 wrmode = get_cur_writemode();
6795 if (wrmode == 0) {
6796 strcat(cmd," -dao");
6797 }
6798 if (wrmode == 2) {
6799 strcat(cmd," defpregap=0");
6800 }
6801 if (wrmode == 3) {
6802 strcat(cmd," -raw96r");
6803 }
6804 if (wrmode == 4) {
6805 strcat(cmd," -raw96p");
6806 }
6807 if (wrmode == 5) {
6808 strcat(cmd," -raw16");
6809 }
6810 }
6811
6812 if (curset.writesimul == 1) {
6813 strcat(cmd," -dummy");
6814 }
6815 if (curset.writeeject == 1) {
6816 strcat(cmd," -eject");
6817 }
6818 if (curset.nofixate == 1) {
6819 strcat(cmd," -nofix");
6820 }
6821 if (curset.multisession == 1) {
6822 if (is_a_sony(devnr)) {
6823 strcat(cmd," -multi -data");
6824 } else {
6825 strcat(cmd," -multi");
6826 }
6827 }
6828 if (curset.writepad == 1) {
6829 strcat(cmd," -pad");
6830 }
6831 if (curset.writeswap == 1) {
6832 strcat(cmd," -swab");
6833 }
6834 if (curset.writeoverburn == 1) {
6835 strcat(cmd," -overburn");
6836 }
6837 if (curset.writeignsize == 1) {
6838 strcat(cmd," -ignsize");
6839 }
6840 if (curset.writeimmed == 1) {
6841 strcat(cmd," -immed");
6842 }
6843 if (curset.writecdtext == 1) {
6844 strcat(cmd," -text");
6845 }
6846
6847 /* now loop through all tracks to write */
6848 loop = g_list_first(trackreadset.trackparams);
6849 while(loop) {
6850 trackparam = loop->data;
6851
6852 if (trackparam->tracktype == 0) {
6853 /* datatrack */
6854 strcat(cmd," -data");
6855 } else {
6856 /* audiotrack */
6857 strcat(cmd," -audio");
6858 }
6859 if (trackparam->trackfile != NULL) {
6860 strcpy(tmptmp, trackparam->trackfile);
6861 g_snprintf(tmp, MAXLINE, " \"%s\"",
6862 convert_escape(tmptmp));
6863 strcat(cmd, tmp);
6864 }
6865
6866 /* save partial command line to view in progress window */
6867 if (strcmp(outcmd,"") == 0) {
6868 g_snprintf(outcmd, MAXLINE,"Calling: %s ...\n\n", cmd);
6869 }
6870
6871 /* fill up percent values for nice progressbar movement */
6872 tracknr = trackparam->starttrack;
6873 writeparams.tracktype[tracknr] = trackparam->tracktype;
6874 writeparams.frames[tracknr] = trackparam->frames;
6875 writeparams.pct_this_track_arr[tracknr] = trackparam->percent;
6876 writeparams.pct_so_far_arr[tracknr] = pct_so_far;
6877 pct_so_far += trackparam->percent;
6878 writeparams.nrtracks++;
6879
6880 loop = loop->next;
6881 }
6882
6883 dodebug(1, "spawning: %s\n",cmd);
6884 dolog(1,"Write CD with %d tracks\n", writeparams.nrtracks);
6885 dolog(3,"Executing: %s\n", cmd);
6886
6887 /* output command to get better debug output */
6888 gtk_text_insert(GTK_TEXT(readtrack_textview),
6889 fixedfont,NULL,NULL,outcmd, strlen(outcmd));
6890
6891 /* yes...command line is done */
6892 readcdda_pid = full_dpl_pipe3(&read_out,&cdrecord_stdin,&read_err,cmd,1);
6893 readcdda_pid2 = -1;
6894 mkisofs_pid = -1;
6895
6896 fcntl(read_out, F_SETFL, O_NONBLOCK);
6897 fcntl(read_err, F_SETFL, O_NONBLOCK);
6898
6899 readcdda_callback = gdk_input_add(read_out, GDK_INPUT_READ,
6900 (GdkInputFunction) read_write_out, GINT_TO_POINTER(read_err));
6901 readcdda_callback2 = gdk_input_add(read_err, GDK_INPUT_READ,
6902 (GdkInputFunction) read_write_stderr, NULL);
6903
6904 /* now wait until write is finished */
6905 while (read_done == 999) {
6906 wait_and_process_events();
6907
6908 /* check if writer is waiting for reload medium */
6909 if (cdrecord_reload > 0) {
6910 cdrecord_reload = 0;
6911 show_dialog(ICO_WARN, _("Please reload the CD-R in the writer"), T_OK, NULL, NULL, -1);
6912
6913 /* now send CR to cdrecord to let it continue */
6914 if (write(cdrecord_stdin, "\n", 1) != 1) {
6915 g_warning("write error to cdrecord pipe\n");
6916 }
6917 }
6918
6919 /* check if somebody clicked on cancel */
6920 if (dialog_done2 != 999) {
6921 ret = show_dialog(ICO_WARN, _("Are you sure you want to abort the writing?\nAborting may damage the CD-RW and may require that you have\nto power-cycle the burner to get working again."),
6922 T_YES, T_NO, NULL, 1);
6923 if (ret == 0) {
6924 /* really abort */
6925 kill_readcdda();
6926 /* mark we aborted */
6927 read_output_ctrl = 1;
6928 dialog_done2 = 999;
6929 } else {
6930 /* not abort - undo button press */
6931 dialog_done2 = 999;
6932 }
6933 }
6934 }
6935
6936 close(read_err);
6937 close(read_out);
6938 close(cdrecord_stdin);
6939
6940 /* no disk */
6941 if (read_output_ctrl == 2) {
6942 gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("No disk or wrong disk loaded."));
6943 return 1;
6944 }
6945 /* cannot send cue sheet */
6946 if (read_output_ctrl == 4) {
6947 show_dialog(ICO_WARN,_("Your CD-Writer did not accept the CUE sheet needed for\nDAO writing. This could mean that cdrecord does not support DAO\nwith your writer. Select TAO mode and try again."),T_OK, NULL, NULL, 0);
6948 }
6949
6950 /* aborted write ? */
6951 if (read_output_ctrl == 1) {
6952 gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Writing aborted..."));
6953 gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Write-Error:"));
6954 return 1;
6955 }
6956
6957 /* error while writing ?*/
6958 if (read_done != 0 || read_output_ctrl == 5) {
6959 gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Error writing tracks"));
6960 gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Write-Error:"));
6961 if (read_done == 2) {
6962 /* invalid cdrecord key - show window */
6963 display_invalid_prodvdkey();
6964 }
6965 return 1;
6966 } else {
6967 /* all ok */
6968 gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Tracks successfully written"));
6969 gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Successful:"));
6970 return 0;
6971 }
6972 }
6973
6974
6975 /* call cdda2wav to only create temporary .inf files - and let xcdroast
6976 patch CD-Text data into them if requested */
6977
create_onthefly_inf_files(gint devnr)6978 static void create_onthefly_inf_files(gint devnr) {
6979 GList *loop;
6980 track_read_param_t *trackparam;
6981 char tmp[MAXLINE];
6982 char tmptmp[MAXLINE];
6983 char tmp4[MAXLINE];
6984 char tmp5[MAXLINE];
6985 char line[MAXLINE];
6986 char cmd[MAXLINE*10]; /* extra big buffer for very long cdrecord options */
6987 FILE *fpin;
6988 gint ret, i, orgcdtextused;
6989 gchar title[MAXLINE], artist[MAXLINE];
6990 gchar cdtitle[MAXLINE], cdartist[MAXLINE];
6991
6992 /* get bus,id,lun string */
6993 if (convert_devnr2busid(devnr,tmp) != 0) {
6994 g_error("non existing cdrom?");
6995 }
6996
6997 /* have to scan for indexes? */
6998 if (curset.indexscan != 0) {
6999 strcpy(tmp4,"-v all");
7000 } else {
7001 strcpy(tmp4,"-v toc,summary,sectors,titles");
7002 }
7003
7004 get_wrap_path("CDDA2WAV",tmp5);
7005 g_snprintf(cmd,MAXLINE,
7006 "%s -D \"%s\" %s -info-only -B", tmp5,tmp,tmp4);
7007
7008 /* now add all track-filenames (only audio) */
7009 loop = g_list_first(trackreadset.trackparams);
7010 while(loop) {
7011 trackparam = loop->data;
7012 if (trackparam->trackfile != NULL &&
7013 trackparam->tracktype == 1) {
7014 strcpy(tmptmp, trackparam->trackfile);
7015 g_snprintf(tmp, MAXLINE, " \"%s\"",
7016 convert_escape(tmptmp));
7017 strcat(cmd, tmp);
7018 }
7019 loop = loop->next;
7020 }
7021 strcat(cmd, " 2>&1");
7022
7023 dodebug(1,"calling: %s\n", cmd);
7024 if ((fpin = popen(cmd,"r")) == NULL) {
7025 g_error("popen error\n");
7026 }
7027
7028 for (;;) {
7029 if (fgets(line,MAXLINE,fpin) == NULL)
7030 break;
7031 dodebug(10,"cdda2wav_info_only: %s", line);
7032 }
7033
7034 ret = pclose(fpin);
7035 if (ret == -1) {
7036 g_error("pclose error\n");
7037 }
7038
7039 /* info files now (hopefully) created */
7040
7041 /* check for invalid mcn or isrc infoormation */
7042 loop = g_list_first(trackreadset.trackparams);
7043 while(loop) {
7044 trackparam = loop->data;
7045 if (trackparam->trackfile != NULL &&
7046 trackparam->tracktype == 1) {
7047
7048 /* silently fix any broken .inf file */
7049 if (check_valid_isrc_mcn(trackparam->trackfile)) {
7050 clear_isrc_mcn_from_inffile(trackparam->trackfile);
7051 }
7052 }
7053 loop = loop->next;
7054 }
7055
7056 /* patch updated cd-text info */
7057 if (curset.writecdtext) {
7058
7059 /* get title and artist for the given CD */
7060 strcpy(cdtitle,"");
7061 strcpy(cdartist,"");
7062 orgcdtextused = 0;
7063 if (setupdata.option_displaycdtext) {
7064 if (cdinfo.title && cdinfo.artist && cdinfo.title[0] != '\0') {
7065 strncpy(cdtitle, cdinfo.title, MAXLINE);
7066 strncpy(cdartist, cdinfo.artist, MAXLINE);
7067 orgcdtextused = 1;
7068 }
7069 }
7070 if (orgcdtextused == 0) {
7071 if (cdinfo.cddb_dtitle) {
7072 get_artist_and_title_from_cddb(cdinfo.cddb_dtitle,
7073 cdartist, cdtitle);
7074 } else {
7075 /* try cd-text as fallback */
7076 if (cdinfo.title && cdinfo.artist &&
7077 cdinfo.title[0] != '\0') {
7078 strncpy(cdtitle, cdinfo.title, MAXLINE);
7079 strncpy(cdartist, cdinfo.artist, MAXLINE); }
7080 }
7081 }
7082
7083 /*
7084 g_print("cdtitle/artist %s %s\n", cdtitle, cdartist);
7085 */
7086 loop = g_list_first(trackreadset.trackparams);
7087 while(loop) {
7088 trackparam = loop->data;
7089 if (trackparam->trackfile != NULL &&
7090 trackparam->tracktype == 1) {
7091
7092 /* get the cd-text data */
7093 i = trackparam->trackinfo_index;
7094 strcpy(title,"");
7095 strcpy(artist,"");
7096 orgcdtextused = 0;
7097 if (setupdata.option_displaycdtext) {
7098 if (trackinfo[i]->title != NULL &&
7099 trackinfo[i]->title[0] != '\0' ) {
7100 /* cd-text found.. use it */
7101 strncpy(title, trackinfo[i]->title, MAXLINE);
7102 orgcdtextused = 1;
7103 }
7104 if (trackinfo[i]->artist != NULL &&
7105 trackinfo[i]->artist[0] != '\0' ) {
7106 strncpy(artist, trackinfo[i]->artist, MAXLINE);
7107 }
7108 }
7109 /* no cd-text in use? try cddb */
7110 if (orgcdtextused == 0) {
7111 if (trackinfo[i]->cddb_ttitle != NULL) {
7112 /* use cddb-information */
7113 strncpy(title, trackinfo[i]->cddb_ttitle,
7114 MAXLINE);
7115 } else {
7116 /* fall back to try cd-text again */
7117 if (trackinfo[i]->title != NULL &&
7118 trackinfo[i]->title[0] != '\0' ) {
7119 strncpy(title, trackinfo[i]->title, MAXLINE);
7120 }
7121 if (trackinfo[i]->artist != NULL &&
7122 trackinfo[i]->artist[0] != '\0' ) {
7123 strncpy(artist, trackinfo[i]->artist, MAXLINE);
7124 }
7125 }
7126 }
7127
7128 /* now we have all cd-text info for the given track */
7129 edit_xinf_for_cd_text2(trackparam->trackfile, title, artist, cdtitle, cdartist);
7130
7131 }
7132 loop = loop->next;
7133 }
7134 }
7135 }
7136
7137
7138 /* after the on-the-fly write remove the temporary-inf files again */
7139
remove_onthefly_inf_files()7140 static void remove_onthefly_inf_files() {
7141 GList *loop;
7142 track_read_param_t *trackparam;
7143 char tmptmp[MAXLINE];
7144
7145 loop = g_list_first(trackreadset.trackparams);
7146 while(loop) {
7147 trackparam = loop->data;
7148 if (trackparam->trackfile != NULL &&
7149 trackparam->tracktype == 1) {
7150 strcpy(tmptmp, trackparam->trackfile);
7151 remove_tmp_writetracks_tocfile(tmptmp);
7152 }
7153 loop = loop->next;
7154 }
7155 }
7156
7157
7158 /* call cdrecord to write a cd on the fly */
7159 /* works currently only for cds with a single data-track and pure
7160 audio CDs */
7161
start_write_onthefly_action(gint read_devnr,gint write_devnr)7162 gint start_write_onthefly_action(gint read_devnr, gint write_devnr) {
7163 GList *loop;
7164 track_read_param_t *trackparam;
7165 gchar tmp[MAXLINE];
7166 gchar tmp2[MAXLINE];
7167 gchar tmp3[MAXLINE];
7168 gchar tmp4[MAXLINE];
7169 gchar atmp3[MAXLINE];
7170 gchar tmptmp[MAXLINE];
7171 gchar atmp6[MAXLINE];
7172 gchar cmd[MAXLINE*10]; /* extra big buffer for very long cdrecord options */
7173 gchar cmd2[MAXLINE*10];
7174 gchar outcmd[MAXLINE];
7175 gchar tmpprefix[MAXLINE];
7176 gint read_out, read_err, read_err2;
7177 gint ret, tracknr, i;
7178 pid_t pid1, pid2;
7179 gint endsector, sectsize;
7180 gint varirec_on, tmp_writer_speed;
7181 gint wrmode;
7182 gint datacount, audiocount;
7183 gint isaudiocd;
7184 gfloat per;
7185
7186 /* if another write running, ignore */
7187 if (read_done == 999) {
7188 return -1;
7189 }
7190
7191 /* what we got to do here? */
7192 datacount = 0;
7193 audiocount = 0;
7194 isaudiocd = 0;
7195 for (i = 0; i < cdinfo.nr_tracks; i++) {
7196 if (trackinfo[i]->type == 0) {
7197 datacount++;
7198 } else {
7199 audiocount++;
7200 }
7201 }
7202 if (datacount == 0 && audiocount > 0) {
7203 isaudiocd = 1;
7204 }
7205 /* special case - cd extra? */
7206 if (datacount == 1 && audiocount > 0 && trackinfo[0]->type == 1) {
7207 /* treat just like an audio cd - ignore data track */
7208 isaudiocd = 1;
7209 }
7210
7211 /* fetch a prefix we might need */
7212 generate_tmp_prefix_name(tmpprefix);
7213
7214 /* audio on the fly - rebuild our structure for the tracks to read */
7215 if (isaudiocd) {
7216
7217 clear_trackreadset();
7218 trackreadset.nrtracks = cdinfo.nr_tracks;
7219
7220 /* create a list of temporary track files */
7221 for(i=0; i<cdinfo.nr_tracks; i++) {
7222
7223 trackparam = g_new0(track_read_param_t,1);
7224 trackparam->trackinfo_index = i;
7225 trackparam->starttrack = trackinfo[i]->track_nr;
7226 trackparam->endtrack = 0;
7227 trackparam->tracktype = trackinfo[i]->type;
7228 per = (gfloat)trackinfo[i]->size * 100.0 / cdinfo.total_size;
7229 trackparam->percent = per/100.0;
7230 trackparam->frames = trackinfo[i]->size;
7231
7232 g_snprintf(tmp,MAXLINE, "%s-%02d.inf",
7233 tmpprefix, i);
7234 trackparam->trackfile = g_strdup(tmp);
7235
7236 trackreadset.trackparams = g_list_append(
7237 trackreadset.trackparams, trackparam);
7238 }
7239
7240 create_onthefly_inf_files(read_devnr);
7241 }
7242
7243 /* mark our write-process as running */
7244 read_done = 999;
7245 read_output_ctrl = 0;
7246 pct_so_far = 0.0;
7247 cdrecord_reload = 0;
7248 cdrtimer = 0;
7249 endsector = 0;
7250 sectsize = 0;
7251 strcpy(outcmd,"");
7252
7253 /* set info label */
7254 gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Initializing CD-Writer..."));
7255
7256 /* reset writeparams-arrays */
7257 g_free(writeparams.tracktype);
7258 g_free(writeparams.frames);
7259 g_free(writeparams.pct_so_far_arr);
7260 g_free(writeparams.pct_this_track_arr);
7261 writeparams.tracktype = g_new0(gint,MAXTRACKS);
7262 writeparams.frames = g_new0(gint,MAXTRACKS);
7263 writeparams.pct_so_far_arr = g_new0(gfloat,MAXTRACKS);
7264 writeparams.pct_this_track_arr = g_new0(gfloat,MAXTRACKS);
7265 writeparams.nrtracks = 0;
7266 writeparams.simulation = curset.writesimul;
7267
7268
7269 /* build command line of readprocess */
7270
7271
7272 if (!isaudiocd) {
7273
7274 /* get bus,id,lun string */
7275 if (convert_devnr2busid_dev(read_devnr,tmp) != 0) {
7276 g_error("non existing cdrom?");
7277 }
7278 /* because we have only a single track on the cd this is our
7279 endsector to read */
7280 endsector = cdinfo.leadout - 2;
7281
7282 sectsize = get_sectorsize(read_devnr);
7283 if (sectsize == 2352) {
7284 /* workaround for buggy drives */
7285 endsector = ((endsector * DATASECTORSIZE) / sectsize) + 1;
7286 }
7287
7288 get_wrap_path("READCD", tmp2);
7289 g_snprintf(cmd,MAXLINE,
7290 "%s %s sectors=0-%d -s f=-",
7291 tmp2, tmp, endsector);
7292
7293 } else {
7294 /* audio CD */
7295
7296 /* get bus,id,lun string */
7297 if (convert_devnr2busid(read_devnr,tmp) != 0) {
7298 g_error("non existing cdrom?");
7299 }
7300
7301 /* set speed only when not zero */
7302 if (get_cur_audioread_speed() > 0) {
7303 g_snprintf(atmp3,MAXLINE,"-S %d", get_cur_audioread_speed());
7304 } else {
7305 strcpy(atmp3,"");
7306 }
7307 if (get_cur_audioread_useparanoia()) {
7308 g_snprintf(atmp6, MAXLINE, "-paranoia -paraopts=retries=%d", get_cur_audioread_paranoiaretries());
7309 } else {
7310 strcpy(atmp6,"");
7311 }
7312
7313 get_wrap_path("CDDA2WAV", tmp2);
7314 g_snprintf(cmd,MAXLINE,
7315 "%s -D \"%s\" -g -Oraw %s -P %d -n %d %s -no-infofile -B -",
7316 tmp2,tmp,atmp3,
7317 get_cur_audioread_overlap(), get_cur_audioread_sectorburst(),
7318 atmp6);
7319 }
7320
7321
7322 /* build command line of write process */
7323
7324 /* get bus,id,lun string */
7325 if (convert_devnr2busid_dev(write_devnr,tmp) != 0) {
7326 g_error("non existing cdrom?");
7327 }
7328
7329 /* get driveropts */
7330 varirec_on = do_driveropts(tmp4, curset.writer_devnr);
7331
7332 get_wrap_path_cdrecord(tmp3);
7333 g_snprintf(cmd2, MAXLINE*10,
7334 "%s %s gracetime=%d fs=%dk %s -v -useinfo",
7335 tmp3, tmp, get_gracetime(), get_cur_writer_fifo(), tmp4);
7336
7337 if (get_cur_writer_drvmode() >= 0) {
7338 if (drivers[get_cur_writer_drvmode()] != NULL) {
7339 g_snprintf(tmp,MAXLINE," driver=%s",
7340 drivers[get_cur_writer_drvmode()]->driver);
7341 strcat(cmd2,tmp);
7342 }
7343 }
7344
7345 /* special case with varirec - always use 4x here */
7346 if (varirec_on) {
7347 tmp_writer_speed = 4;
7348 } else {
7349 tmp_writer_speed = get_cur_writer_speed();
7350 }
7351 if (get_cur_writer_speed() >= 0) {
7352 g_snprintf(tmp,MAXLINE," speed=%d", tmp_writer_speed);
7353 strcat(cmd2, tmp);
7354 }
7355 if (curset.multisession == 0) {
7356 wrmode = get_cur_writemode();
7357 if (wrmode == 0) {
7358 strcat(cmd2," -dao");
7359 }
7360 if (wrmode == 2) {
7361 strcat(cmd2," defpregap=0");
7362 }
7363 if (wrmode == 3) {
7364 strcat(cmd2," -raw96r");
7365 }
7366 if (wrmode == 4) {
7367 strcat(cmd2," -raw96p");
7368 }
7369 if (wrmode == 5) {
7370 strcat(cmd2," -raw16");
7371 }
7372 }
7373 if (curset.writesimul == 1) {
7374 strcat(cmd2," -dummy");
7375 }
7376 if (curset.writeeject == 1) {
7377 strcat(cmd2," -eject");
7378 }
7379 if (curset.nofixate == 1) {
7380 strcat(cmd2," -nofix");
7381 }
7382 #if 0
7383 /* allow multisession only for data */
7384 if (curset.multisession == 1) {
7385 if (is_a_sony(write_devnr)) {
7386 strcat(cmd2," -multi -data");
7387 } else {
7388 strcat(cmd2," -multi");
7389 }
7390 }
7391 #endif
7392 if (curset.writepad == 1) {
7393 strcat(cmd2," -pad");
7394 }
7395 if (curset.writeswap == 1) {
7396 strcat(cmd2," -swab");
7397 }
7398 if (curset.writeoverburn == 1) {
7399 strcat(cmd2," -overburn");
7400 }
7401 if (curset.writeignsize == 1) {
7402 strcat(cmd2," -ignsize");
7403 }
7404 if (curset.writeimmed == 1) {
7405 strcat(cmd2," -immed");
7406 }
7407 if (curset.writecdtext == 1) {
7408 strcat(cmd2," -text");
7409 }
7410
7411 if (!isaudiocd) {
7412 /* now add track-specification: one data track, known length */
7413 if (sectsize == SUNDATASECTORSIZE) {
7414 g_snprintf(tmp, MAXLINE, " tsize=%db", endsector);
7415 } else {
7416 g_snprintf(tmp, MAXLINE, " tsize=%ds", endsector);
7417 }
7418
7419 strcat(cmd2, tmp);
7420 strcat(cmd2," -waiti -data -");
7421
7422 /* fill up percent values for nice progressbar movement */
7423 tracknr = 1;
7424 writeparams.tracktype[tracknr] = 0; /* data */
7425 writeparams.frames[tracknr] = endsector;
7426 writeparams.pct_this_track_arr[tracknr] = 1.0;
7427 writeparams.pct_so_far_arr[tracknr] = 0.0;
7428 writeparams.nrtracks = 1;
7429
7430 } else {
7431
7432 strcat(cmd2," -waiti -audio");
7433
7434 /* audio mode - add info-file list */
7435 loop = g_list_first(trackreadset.trackparams);
7436 while(loop) {
7437 trackparam = loop->data;
7438 if (trackparam->trackfile != NULL &&
7439 trackparam->tracktype == 1) {
7440 strcpy(tmptmp, trackparam->trackfile);
7441 g_snprintf(tmp, MAXLINE, " \"%s\"",
7442 convert_escape(tmptmp));
7443 strcat(cmd2, tmp);
7444 }
7445 /* fill up percent values for nice progressbar movement */
7446 tracknr = trackparam->starttrack;
7447 writeparams.tracktype[tracknr] = trackparam->tracktype;
7448 writeparams.frames[tracknr] = trackparam->frames;
7449 writeparams.pct_this_track_arr[tracknr] = trackparam->percent;
7450 writeparams.pct_so_far_arr[tracknr] = pct_so_far;
7451 pct_so_far += trackparam->percent;
7452 writeparams.nrtracks++;
7453
7454 loop = loop->next;
7455 }
7456
7457 }
7458
7459 /* save partial command line to view in progress window */
7460 g_snprintf(outcmd, MAXLINE,"Calling: %s\n\n", cmd2);
7461
7462 dodebug(1, "spawning: %s | %s \n",cmd, cmd2);
7463 dolog(1,"Write CD on the fly\n");
7464 dolog(3,"Executing: %s | %s\n", cmd, cmd2);
7465
7466 /* output command to get better debug output */
7467 gtk_text_insert(GTK_TEXT(readtrack_textview),
7468 fixedfont,NULL,NULL,outcmd, strlen(outcmd));
7469
7470 /* yes...command line is done */
7471 full_dpl_pipe4(&pid1,&pid2,NULL,&read_err,cmd,&read_out,&read_err2,cmd2,1);
7472 mkisofs_pid = -1;
7473 readcdda_pid = pid2;
7474 readcdda_pid2 = pid1;
7475
7476 fcntl(read_out, F_SETFL, O_NONBLOCK);
7477 fcntl(read_err, F_SETFL, O_NONBLOCK);
7478 fcntl(read_err2, F_SETFL, O_NONBLOCK);
7479
7480 readcdda_callback = gdk_input_add(read_out, GDK_INPUT_READ,
7481 (GdkInputFunction) read_write_out, GINT_TO_POINTER(read_err2));
7482 readcdda_callback2 = gdk_input_add(read_err2, GDK_INPUT_READ,
7483 (GdkInputFunction) read_write_stderr, NULL);
7484 readcdda_callback3 = gdk_input_add(read_err, GDK_INPUT_READ,
7485 (GdkInputFunction) verify_readcd_err, GINT_TO_POINTER(pid1));
7486
7487 /* now wait until write is finished */
7488 while (read_done == 999) {
7489 wait_and_process_events();
7490
7491 /* check if writer is waiting for reload medium */
7492 if (cdrecord_reload > 0) {
7493 show_dialog(ICO_WARN, _("Please reload the CD-R in the writer"), T_OK, NULL, NULL, -1);
7494
7495 /* now send CR to cdrecord to let it continue */
7496 if (cdrecord_reload == 1) {
7497 if (write(read_err2, "\n", 1) != 1) {
7498 g_warning("write error to cdrecord pipe\n");
7499 }
7500 }
7501
7502 /* cdrecord also accepts a SIGUSR1 to continue */
7503 /* send wakeup signal */
7504 if (cdrecord_reload == 2) {
7505 dodebug(1,"Sending SIGUSR1 to cdrecord (pid: %d) after reload.\n", (gint) pid2);
7506 kill(pid2, SIGUSR1);
7507 }
7508 cdrecord_reload = 0;
7509 }
7510
7511 /* check if somebody clicked on cancel */
7512 if (dialog_done2 != 999) {
7513 ret = show_dialog(ICO_WARN, _("Are you sure you want to abort the writing?\nAborting may damage the CD-RW and may require that you have\nto power-cycle the burner to get working again."),
7514 T_YES, T_NO, NULL, 1);
7515 if (ret == 0) {
7516 /* really abort */
7517 kill_readcdda();
7518 /* mark we aborted */
7519 read_output_ctrl = 1;
7520 dialog_done2 = 999;
7521 } else {
7522 /* not abort - undo button press */
7523 dialog_done2 = 999;
7524 }
7525 }
7526 }
7527
7528 close(read_err2);
7529 close(read_err);
7530 close(read_out);
7531
7532 /* remove temporary inf files */
7533 if (isaudiocd) {
7534 remove_onthefly_inf_files();
7535 }
7536
7537 /* no disk */
7538 if (read_output_ctrl == 2) {
7539 gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("No disk or wrong disk loaded."));
7540 return 1;
7541 }
7542
7543 /* cannot send cue sheet */
7544 if (read_output_ctrl == 4) {
7545 show_dialog(ICO_WARN,_("Your CD-Writer did not accept the CUE sheet needed for\nDAO writing. This could mean that cdrecord does not support DAO\nwith your writer. Select TAO mode and try again."),T_OK, NULL, NULL, 0);
7546 }
7547
7548 /* aborted write ? */
7549 if (read_output_ctrl == 1) {
7550 gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Writing aborted..."));
7551 gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Write-Error:"));
7552 return 1;
7553 }
7554
7555 /* error while reading ?*/
7556 if (read_done != 0 || read_output_ctrl == 5) {
7557 gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Error writing tracks"));
7558 gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Write-Error:"));
7559 if (read_done == 2) {
7560 /* invalid cdrecord key - show window */
7561 display_invalid_prodvdkey();
7562 }
7563 return 1;
7564 } else {
7565 /* all ok */
7566 gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Tracks successfully written"));
7567 gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Successful:"));
7568 return 0;
7569 }
7570 }
7571
7572
7573 /* call cdrecord to fixate a disk */
7574
start_write_fixate_only(gint devnr)7575 gint start_write_fixate_only(gint devnr) {
7576 char tmp[MAXLINE];
7577 char tmp2[MAXLINE];
7578 char cmd[MAXLINE*10]; /* extra big buffer for very long cdrecord options */
7579 gint read_out, read_err;
7580 gint ret;
7581 gint wrmode;
7582
7583 /* if another write running, ignore */
7584 if (read_done == 999) {
7585 return -1;
7586 }
7587
7588 /* mark our write-process as running */
7589 read_done = 999;
7590 read_output_ctrl = 0;
7591 pct_so_far = 0.0;
7592 cdrecord_reload = 0;
7593 cdrtimer = 0;
7594
7595 /* set info label */
7596 gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Initializing CD-Writer..."));
7597
7598 /* get bus,id,lun string */
7599 if (convert_devnr2busid_dev(devnr,tmp) != 0) {
7600 g_error("non existing cdrom?");
7601 }
7602
7603 /* build command line */
7604 get_wrap_path_cdrecord(tmp2);
7605 g_snprintf(cmd, MAXLINE*10,
7606 "%s %s gracetime=%d -v -fix", tmp2, tmp, get_gracetime());
7607
7608 if (get_cur_writer_drvmode() >= 0) {
7609 if (drivers[get_cur_writer_drvmode()] != NULL) {
7610 g_snprintf(tmp,MAXLINE," driver=%s",
7611 drivers[get_cur_writer_drvmode()]->driver);
7612 strcat(cmd,tmp);
7613 }
7614 }
7615
7616 if (get_cur_writer_speed() >= 0) {
7617 g_snprintf(tmp,MAXLINE," speed=%d", get_cur_writer_speed());
7618 strcat(cmd, tmp);
7619 }
7620 if (curset.multisession == 0) {
7621 wrmode = get_cur_writemode();
7622 if (wrmode == 0) {
7623 strcat(cmd," -dao");
7624 }
7625 if (wrmode == 2) {
7626 strcat(cmd," defpregap=0");
7627 }
7628 if (wrmode == 3) {
7629 strcat(cmd," -raw96r");
7630 }
7631 if (wrmode == 4) {
7632 strcat(cmd," -raw96p");
7633 }
7634 if (wrmode == 5) {
7635 strcat(cmd," -raw16");
7636 }
7637 }
7638 if (curset.writesimul == 1) {
7639 strcat(cmd," -dummy");
7640 }
7641 if (curset.writeeject == 1) {
7642 strcat(cmd," -eject");
7643 }
7644 if (curset.multisession == 1) {
7645 strcat(cmd," -multi");
7646 }
7647 if (curset.writeignsize == 1) {
7648 strcat(cmd," -ignsize");
7649 }
7650 if (curset.writeimmed == 1) {
7651 strcat(cmd," -immed");
7652 }
7653
7654 dodebug(1, "spawning: %s\n",cmd);
7655 dolog(1,"Fixate CD\n");
7656 dolog(3,"Executing: %s\n", cmd);
7657
7658 /* yes...command line is done */
7659 readcdda_pid = full_dpl_pipe3(&read_out,&cdrecord_stdin,&read_err,cmd,1);
7660 readcdda_pid2 = -1;
7661 mkisofs_pid = -1;
7662
7663 fcntl(read_out, F_SETFL, O_NONBLOCK);
7664 fcntl(read_err, F_SETFL, O_NONBLOCK);
7665
7666 readcdda_callback = gdk_input_add(read_out, GDK_INPUT_READ,
7667 (GdkInputFunction) read_write_out, GINT_TO_POINTER(read_err));
7668 readcdda_callback2 = gdk_input_add(read_err, GDK_INPUT_READ,
7669 (GdkInputFunction) read_write_stderr, NULL);
7670
7671 /* now wait until write is finished */
7672 while (read_done == 999) {
7673 wait_and_process_events();
7674
7675 /* check if writer is waiting for reload medium */
7676 if (cdrecord_reload > 0) {
7677 cdrecord_reload = 0;
7678 show_dialog(ICO_WARN, _("Please reload the CD-R in the writer"), T_OK, NULL, NULL, -1);
7679
7680 /* now send CR to cdrecord to let it continue */
7681 if (write(cdrecord_stdin, "\n", 1) != 1) {
7682 g_warning("write error to cdrecord pipe\n");
7683 }
7684 }
7685
7686 /* check if somebody clicked on cancel */
7687 if (dialog_done2 != 999) {
7688 ret = show_dialog(ICO_WARN, _("Are you sure you want to abort the writing?\nAborting may damage the CD-RW and may require that you have\nto power-cycle the burner to get working again."),
7689 T_YES, T_NO, NULL, 1);
7690 if (ret == 0) {
7691 /* really abort */
7692 kill_readcdda();
7693 /* mark we aborted */
7694 read_output_ctrl = 1;
7695 dialog_done2 = 999;
7696 } else {
7697 /* not abort - undo button press */
7698 dialog_done2 = 999;
7699 }
7700 }
7701 }
7702
7703 close(read_err);
7704 close(read_out);
7705 close(cdrecord_stdin);
7706
7707 /* no disk */
7708 if (read_output_ctrl == 2) {
7709 gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("No disk or wrong disk loaded."));
7710 return 1;
7711 }
7712 /* cannot send cue sheet */
7713 if (read_output_ctrl == 4) {
7714 show_dialog(ICO_WARN,_("Your CD-Writer did not accept the CUE sheet needed for\nDAO writing. This could mean that cdrecord does not support DAO\nwith your writer. Select TAO mode and try again."),T_OK, NULL, NULL, 0);
7715 }
7716
7717 /* aborted write ? */
7718 if (read_output_ctrl == 1) {
7719 gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Writing aborted..."));
7720 gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Write-Error:"));
7721 return 1;
7722 }
7723
7724 /* error while reading ?*/
7725 if (read_done != 0 || read_output_ctrl == 5) {
7726 gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Error writing tracks"));
7727 gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Write-Error:"));
7728 if (read_done == 2) {
7729 /* invalid cdrecord key - show window */
7730 display_invalid_prodvdkey();
7731 }
7732 return 1;
7733 } else {
7734 /* all ok */
7735 gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Tracks successfully written"));
7736 gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Successful:"));
7737 return 0;
7738 }
7739 }
7740
7741
7742 /* parse output of rmtool and update sliders and textbox */
7743
read_delete_out(gpointer data,gint source,GdkInputCondition cond)7744 static void read_delete_out(gpointer data, gint source, GdkInputCondition cond) {
7745 gint n;
7746 gint ret;
7747 gchar line[MAXLINE];
7748 gchar tmp[MAXLINE];
7749 gint val;
7750 gfloat pval;
7751
7752 /* read output of readcd */
7753 n = read_line(source, line, MAXLINE);
7754
7755 /* delete finished */
7756 if (n <= 0) {
7757 gtk_input_remove(readcdda_callback);
7758
7759 /* pick up return status of child */
7760 wait(&ret);
7761
7762 /* tell our caller that we are done here */
7763 if (WEXITSTATUS(ret) == 0 && read_output_ctrl != 100) {
7764 /* aborted */
7765 read_done = 2;
7766 } else {
7767 read_done = WEXITSTATUS(ret);
7768 }
7769 return;
7770 }
7771
7772 dodebug(10,"rmtool: %s\n", line);
7773
7774 /* look for a percent value */
7775 if (line[strlen(line)-1] == '%') {
7776 strcpy(tmp,line);
7777 tmp[strlen(tmp)-1] = '\0';
7778 strip_string(tmp);
7779 val = atoi(tmp);
7780 read_output_ctrl = val;
7781 pval = (gfloat)val/100;
7782 pval = (pval*delete_count + delete_start) /delete_all;
7783 if (pval > 1.0) pval = 1.0;
7784 gtk_progress_set_percentage(
7785 GTK_PROGRESS(readtrack_pbar1), pval);
7786 set_xcdr_title(toplevel,viewmode_dialog,(gint)(pval*100+0.5));
7787 return;
7788 }
7789
7790 strcat(line,"\n");
7791 convert_for_gtk2_textwidget(line);
7792 gtk_text_insert(GTK_TEXT(readtrack_textview),
7793 fixedfont,NULL,NULL, line, strlen(line));
7794
7795 }
7796
7797
7798 /* does do the real deletion of some files */
7799
do_delete_files(gchar * cmd,gint count,gint start,gint all)7800 static gint do_delete_files(gchar *cmd, gint count, gint start, gint all) {
7801 gint read_out;
7802
7803 /* set some global vars we need for progress-bar */
7804 delete_count = count;
7805 delete_start = start;
7806 delete_all = all;
7807
7808 dodebug(1,"spawning: %s\n",cmd);
7809 dolog(2,"Deleting %d files\n", count);
7810 dolog(3,"Executing: %s\n", cmd);
7811
7812 readcdda_pid = full_dpl_pipe3(&read_out,NULL,NULL,cmd,0);
7813 readcdda_pid2 = -1;
7814
7815 fcntl(read_out, F_SETFL, O_NONBLOCK);
7816
7817 readcdda_callback = gdk_input_add(read_out, GDK_INPUT_READ,
7818 (GdkInputFunction) read_delete_out, NULL);
7819
7820
7821 /* now wait until tracks are deleted */
7822 while (read_done == 999) {
7823 wait_and_process_events();
7824 }
7825
7826 close(read_out);
7827
7828 return read_done;
7829 }
7830
7831
7832 /* do delete some tracks from the HD */
7833 /* do split the bulk in pieces of 50 files...to ensure there is no
7834 overrun of shell-arguments */
7835
start_delete_action(GList * delfiles)7836 gint start_delete_action(GList *delfiles) {
7837 GList *loop;
7838 gchar *fname;
7839 gint length, broke;
7840 gint count,lastcount;
7841 gchar tmp[MAXLINE];
7842 gchar tmptmp[MAXLINE];
7843 gchar tmp2[MAXLINE];
7844 gchar infname[MAXLINE];
7845 gchar infname2[MAXLINE];
7846 char orgcmd[MAXLINE];
7847 char cmd[MAXLINE*10];
7848 gchar *p;
7849
7850 /* if another delete running, ignore */
7851 if (read_done == 999) {
7852 return -1;
7853 }
7854
7855 read_done = 999;
7856 read_output_ctrl = 0;
7857 lastcount = 0;
7858 broke = 0;
7859
7860 gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Deleting tracks..."));
7861
7862 /* build of command line */
7863 g_snprintf(orgcmd,MAXLINE,"%s/%s ", sharedir, RMTOOL);
7864 strcpy(cmd,orgcmd);
7865
7866 length = g_list_length(delfiles);
7867 count = 0;
7868
7869 loop = g_list_first(delfiles);
7870 while(loop) {
7871 fname = (gchar *)loop->data;
7872
7873 /* remove extension and put .inf there */
7874 strncpy(tmp,fname,MAXLINE - 4);
7875 p = rindex(tmp,'.');
7876 if (p == NULL) return -1;
7877 strcpy(tmp2,p);
7878 *p = '\0';
7879 if (strcmp(tmp2,".toc") == 0) {
7880 strcpy(tmptmp,fname);
7881 g_snprintf(tmp2, MAXLINE, "\"%s\" ",
7882 convert_escape(tmptmp));
7883 } else {
7884 strcpy(infname,tmp);
7885 strcat(infname,XCDROAST_INFO_EXT);
7886 strcpy(infname2,tmp);
7887 strcat(infname2,CDDA2WAV_INFO_EXT);
7888 strcpy(tmptmp,fname);
7889 g_snprintf(tmp2, MAXLINE, "\"%s\" \"%s\" \"%s\" ",
7890 convert_escape(tmptmp),
7891 convert_escape(infname),
7892 convert_escape(infname2));
7893 }
7894 strcat(cmd,tmp2);
7895
7896 count++;
7897 if (count%50 == 0) {
7898 /* part of commandline complete */
7899 read_done = do_delete_files(cmd, count-lastcount, lastcount, length);
7900 lastcount = count;
7901 strcpy(cmd,orgcmd);
7902
7903 /* this run was successful? */
7904 if (read_done == 0) {
7905 read_done = 999;
7906 read_output_ctrl = 0;
7907 } else {
7908 broke = 1;
7909 break;
7910 }
7911 }
7912 loop = loop->next;
7913 }
7914
7915 /* any parts left over? (and no error before) */
7916 if (count%50 != 0 && broke == 0) {
7917 /* part of commandline complete */
7918 read_done = do_delete_files(cmd, count-lastcount, lastcount, length);
7919 }
7920
7921 /* all ok? */
7922 if (read_done == 0) {
7923 gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Delete successful"));
7924 } else
7925 if (read_done == 2) {
7926 /* delete canceled */
7927 gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Delete aborted..."));
7928 } else {
7929 /* some error */
7930 gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Error deleting tracks"));
7931 }
7932
7933 return 0;
7934 }
7935
7936
7937 /* parse output of verfify-tool and update sliders */
7938
verify_readcd_out(gpointer pid,gint source,GdkInputCondition cond)7939 static void verify_readcd_out(gpointer pid, gint source, GdkInputCondition cond) {
7940 gint n;
7941 gint ret;
7942 gchar line[MAXLINE];
7943 gchar tmp[MAXLINE];
7944 gint val;
7945 gfloat pval, pval2;
7946
7947 /* read output of vrfytool */
7948 n = read_line(source, line, MAXLINE);
7949
7950 /* readcd-finished? */
7951 if (n <= 0) {
7952 gtk_input_remove(readcdda_callback);
7953
7954 /* pick up return status of child */
7955 waitpid((pid_t)GPOINTER_TO_INT(pid), &ret, WNOHANG);
7956
7957 /* tell our caller that we are done here */
7958 read_done = WEXITSTATUS(ret);
7959 return;
7960 }
7961
7962 dodebug(10,"vry-readcd (stdout): %s\n", line);
7963
7964 /* look for a percent value */
7965 if (line[strlen(line)-1] == '%') {
7966
7967 strcpy(tmp,line);
7968 tmp[strlen(tmp)-1] = '\0';
7969 strip_string(tmp);
7970 val = atoi(tmp);
7971
7972 pval = (gfloat)val/100;
7973 if (pval > 1.0) pval = 1.0;
7974
7975 gtk_progress_set_percentage(GTK_PROGRESS(readtrack_pbar1),
7976 pval);
7977
7978 /* now calculate how much percent he has at all */
7979 pval2 = (pct_so_far + (pval * pct_this_track));
7980 if (pval2 > 1.0) pval2 = 1.0;
7981 gtk_progress_set_percentage(GTK_PROGRESS(readtrack_pbar2),
7982 pval2);
7983 set_xcdr_title(toplevel,viewmode_dialog,(gint)(pval2*100+0.5));
7984
7985 /* now update info for small view */
7986 g_snprintf(tmp,MAXLINE,"%d%% / %d%%",(gint)(pval*100+0.5),
7987 (gint)(pval2*100+0.5));
7988 gtk_label_set_text(GTK_LABEL(readtrack_small_info2),tmp);
7989
7990 return;
7991 }
7992
7993 /* forward all other output to textview-window */
7994 strcat(line,"\n");
7995 convert_for_gtk2_textwidget(line);
7996 gtk_text_insert(GTK_TEXT(readtrack_textview),
7997 fixedfont,NULL,NULL, line, strlen(line));
7998 }
7999
8000
8001 /* do just swallow all output we get from stderr... and wait if the
8002 process terminated */
8003
verify_readcd_err(gpointer pid,gint source,GdkInputCondition cond)8004 static void verify_readcd_err(gpointer pid, gint source, GdkInputCondition cond) {
8005 gint n;
8006 gint ret;
8007 gchar line[MAXLINE];
8008
8009 /* read output of vrfytool */
8010 n = read_line(source, line, MAXLINE);
8011
8012 /* readcd-finished? */
8013 if (n <= 0) {
8014 gtk_input_remove(readcdda_callback3);
8015
8016 /* pick up return status of child */
8017 waitpid((pid_t)GPOINTER_TO_INT(pid), &ret, WNOHANG);
8018
8019 dodebug(10,"Finished in verify_readcd_err\n");
8020
8021 return;
8022 }
8023
8024 dodebug(10,"readcd/cdda2wav (stderr): %s\n", line);
8025 }
8026
8027
8028 /* does call readcd | vrfytool to do verifying */
8029
verify_data_track(gint devnr,gint starttrack,gint kbyte,gchar * fname,gint startoffset,gint endoffset,gint nrtracks,gfloat percent,gfloat percent_done,gint viewtrack)8030 gint verify_data_track(gint devnr, gint starttrack, gint kbyte,
8031 gchar *fname, gint startoffset, gint endoffset,
8032 gint nrtracks, gfloat percent, gfloat percent_done,
8033 gint viewtrack) {
8034 gchar cmd[MAXLINE];
8035 gchar cmd2[MAXLINE];
8036 gchar tmp[MAXLINE];
8037 gchar tmptmp[MAXLINE];
8038 gchar tmp2[MAXLINE];
8039 gchar tmp3[MAXLINE];
8040 gint read_out, read_err, sectsize;
8041 pid_t pid1, pid2;
8042
8043 /* if another read running, ignore */
8044 if (read_done == 999) {
8045 return -1;
8046 }
8047
8048 /* no filename given? */
8049 if (fname == NULL) {
8050 return 1;
8051 }
8052
8053 /* mark our read-process as running */
8054 read_done = 999;
8055 readcdda_pid = -1;
8056 readcdda_pid2 = -1;
8057 read_output_ctrl = 0;
8058 read_abort_mark = 0;
8059
8060 /* set info-label */
8061 convert_kbytes2mbminstring(kbyte, tmp);
8062 g_snprintf(tmp2,MAXLINE,_("Verifying data track %d/%d [%s]"), viewtrack, nrtracks, tmp);
8063 gtk_label_set_text(GTK_LABEL(readtrack_info_label),tmp2);
8064
8065 g_snprintf(tmp2,MAXLINE,_("Verifying %d/%d:"), viewtrack, nrtracks);
8066 gtk_label_set_text(GTK_LABEL(readtrack_small_info),tmp2);
8067
8068 /* get bus,id,lun string */
8069 if (convert_devnr2busid_dev(devnr,tmp) != 0) {
8070 g_error("non existing cdrom?");
8071 }
8072
8073 /* some stuff to have our slider moving smoothly no matter how
8074 big the tracks are */
8075 pct_so_far = percent_done;
8076 pct_this_track = percent;
8077
8078 /* now check which sectorsize we got */
8079 sectsize = get_sectorsize(devnr);
8080 if (sectsize == 2352) {
8081 /* workaround for buggy drives */
8082 endoffset = ((endoffset * DATASECTORSIZE) / sectsize) + 1;
8083 }
8084
8085 get_wrap_path("READCD", tmp3);
8086 g_snprintf(cmd,MAXLINE,
8087 "%s %s sectors=%d-%d -s f=-",
8088 tmp3, tmp, startoffset, endoffset);
8089
8090 strcpy(tmptmp, fname);
8091
8092 /* always verify in 512 bytes blocks */
8093 g_snprintf(cmd2,MAXLINE,"%s/%s -b \"%s\" -",
8094 sharedir, VRFYTOOL, convert_escape(tmptmp));
8095
8096 dodebug(1, "spawning: %s | %s\n",cmd,cmd2);
8097 dolog(2, "Verify data track %s\n", fname);
8098 dolog(3, "Executing: %s | %s\n", cmd, cmd2);
8099
8100 /* start childs and get new fds */
8101 full_dpl_pipe4(&pid1,&pid2,NULL,&read_err,cmd,&read_out,NULL,cmd2,0);
8102 readcdda_pid = pid1;
8103 readcdda_pid2 = -1;
8104
8105 /* set output to nonblocking - otherwise our callback would block */
8106 fcntl(read_out, F_SETFL, O_NONBLOCK);
8107 fcntl(read_err, F_SETFL, O_NONBLOCK);
8108
8109 /* catch output of child */
8110 readcdda_callback = gdk_input_add(read_out, GDK_INPUT_READ,
8111 (GdkInputFunction) verify_readcd_out, GINT_TO_POINTER(pid2));
8112 readcdda_callback3 = gdk_input_add(read_err, GDK_INPUT_READ,
8113 (GdkInputFunction) verify_readcd_err, GINT_TO_POINTER(pid1));
8114
8115 /* now wait until track is read */
8116 while (read_done == 999) {
8117 wait_and_process_events();
8118 }
8119
8120 close(read_out);
8121 close(read_err);
8122
8123 gtk_text_insert(GTK_TEXT(readtrack_textview),
8124 fixedfont,NULL,NULL, "\n", 1);
8125
8126 /* error while reading? */
8127 if (read_done != 0 && read_abort_mark == 0) {
8128 g_snprintf(tmp,MAXLINE,_("Verifying data track %d/%d failed"), starttrack, nrtracks);
8129 gtk_label_set_text(GTK_LABEL(readtrack_info_label),tmp);
8130 gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Verify-Error:"));
8131 return 1;
8132 }
8133 /* compare aborted? */
8134 if (read_abort_mark != 0) {
8135 gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Verify aborted..."));
8136 return 2;
8137 }
8138
8139 return 0;
8140 }
8141
8142
8143 /* does call cdda2wav | vrfytool to do verifying */
8144
verify_audio_track(gint devnr,gint starttrack,gint endtrack,gint kbyte,gchar * fname,gint startoffset,gint endoffset,gint nrtracks,gfloat percent,gfloat percent_done,gint viewtrack)8145 gint verify_audio_track(gint devnr, gint starttrack, gint endtrack, gint kbyte,
8146 gchar *fname, gint startoffset, gint endoffset,
8147 gint nrtracks, gfloat percent, gfloat percent_done,
8148 gint viewtrack) {
8149 gchar cmd[MAXLINE];
8150 gchar cmd2[MAXLINE];
8151 gchar tmp[MAXLINE];
8152 gchar tmptmp[MAXLINE];
8153 gchar tmp2[MAXLINE];
8154 gchar tmp3[MAXLINE];
8155 gchar tmp4[MAXLINE];
8156 gchar tmp6[MAXLINE];
8157 gint read_out, read_err;
8158 pid_t pid1, pid2;
8159
8160 /* if another read running, ignore */
8161 if (read_done == 999) {
8162 return -1;
8163 }
8164
8165 /* no filename given? */
8166 if (fname == NULL) {
8167 return 1;
8168 }
8169
8170 /* mark our read-process as running */
8171 read_done = 999;
8172 readcdda_pid = -1;
8173 readcdda_pid2 = -1;
8174 read_output_ctrl = 0;
8175 read_abort_mark = 0;
8176
8177 /* set info-label */
8178 convert_kbytes2mbminstring(kbyte, tmp);
8179 g_snprintf(tmp2,MAXLINE,_("Verifying audio track %d/%d [%s]"), viewtrack, nrtracks, tmp);
8180 gtk_label_set_text(GTK_LABEL(readtrack_info_label),tmp2);
8181
8182 g_snprintf(tmp2,MAXLINE,_("Verifying %d/%d:"), viewtrack, nrtracks);
8183 gtk_label_set_text(GTK_LABEL(readtrack_small_info),tmp2);
8184
8185 /* get bus,id,lun string */
8186 if (convert_devnr2busid(devnr,tmp) != 0) {
8187 g_error("non existing cdrom?");
8188 }
8189
8190 /* some stuff to have our slider moving smoothly no matter how
8191 big the tracks are */
8192 pct_so_far = percent_done;
8193 pct_this_track = percent;
8194
8195 /* build command line */
8196 if (endtrack != 0) {
8197 g_snprintf(tmp2,MAXLINE,"%d+%d",starttrack,endtrack);
8198 } else {
8199 g_snprintf(tmp2,MAXLINE,"%d",starttrack);
8200 }
8201
8202 /* set speed only when not zero */
8203 if (get_cur_audioread_speed() > 0) {
8204 g_snprintf(tmp3,MAXLINE,"-S %d", get_cur_audioread_speed());
8205 } else {
8206 strcpy(tmp3,"");
8207 }
8208
8209 if (get_cur_audioread_useparanoia()) {
8210 g_snprintf(tmp6, MAXLINE, "-paranoia -paraopts=retries=%d", get_cur_audioread_paranoiaretries());
8211 } else {
8212 strcpy(tmp6,"");
8213 }
8214
8215 get_wrap_path("CDDA2WAV", tmp4);
8216 g_snprintf(cmd,MAXLINE,
8217 "%s -D \"%s\" -g -H -v toc -O wav -t %s %s -P %d -n %d %s -",
8218 tmp4,tmp,tmp2,tmp3,
8219 get_cur_audioread_overlap(), get_cur_audioread_sectorburst(),
8220 tmp6);
8221
8222 strcpy(tmptmp,fname);
8223 g_snprintf(cmd2,MAXLINE,"%s/%s -a \"%s\" -",
8224 sharedir, VRFYTOOL, convert_escape(tmptmp));
8225
8226 dodebug(1, "spawning: %s | %s\n",cmd,cmd2);
8227 dolog(2, "Verify audio track %s\n", fname);
8228 dolog(3, "Executing: %s | %s\n", cmd, cmd2);
8229
8230 /* start childs and get new fds */
8231 full_dpl_pipe4(&pid1,&pid2,NULL,&read_err,cmd,&read_out,NULL,cmd2,0);
8232 readcdda_pid = pid1;
8233 readcdda_pid2 = -1;
8234
8235 /* set output to nonblocking - otherwise our callback would block */
8236 fcntl(read_out, F_SETFL, O_NONBLOCK);
8237 fcntl(read_err, F_SETFL, O_NONBLOCK);
8238
8239 /* catch output of child */
8240 readcdda_callback = gdk_input_add(read_out, GDK_INPUT_READ,
8241 (GdkInputFunction) verify_readcd_out, GINT_TO_POINTER(pid2));
8242 readcdda_callback3 = gdk_input_add(read_err, GDK_INPUT_READ,
8243 (GdkInputFunction) verify_readcd_err, GINT_TO_POINTER(pid1));
8244
8245 /* now wait until track is read */
8246 while (read_done == 999) {
8247 wait_and_process_events();
8248 }
8249
8250 close(read_out);
8251 close(read_err);
8252
8253 gtk_text_insert(GTK_TEXT(readtrack_textview),
8254 fixedfont,NULL,NULL, "\n", 1);
8255
8256 /* error while reading? */
8257 if (read_done != 0 && read_abort_mark == 0) {
8258 g_snprintf(tmp,MAXLINE,_("Verifying audio track %d/%d failed"), starttrack, nrtracks);
8259 gtk_label_set_text(GTK_LABEL(readtrack_info_label),tmp);
8260 gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Verify-Error:"));
8261 return 1;
8262 }
8263 /* compare aborted? */
8264 if (read_abort_mark != 0) {
8265 gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Verify aborted..."));
8266 return 2;
8267 }
8268
8269 return 0;
8270 }
8271
8272
8273 /* parse output of cddbtool and update textbox */
8274
read_cddbtool_out(gpointer data,gint source,GdkInputCondition cond)8275 static void read_cddbtool_out(gpointer data, gint source, GdkInputCondition cond) {
8276 gint n;
8277 gint ret;
8278 gint code, mode;
8279 gchar line[MAXLINE];
8280 gchar tmp[MAXLINE];
8281 gchar *p;
8282 gchar *rowdata[1];
8283
8284 /* mode 0 for cd, mode 1 for tocfile, mode 2 for on-the-fly */
8285 mode = GPOINTER_TO_INT(data);
8286
8287 /* read output of readcd */
8288 n = read_line(source, line, MAXLINE);
8289
8290 /* cddbtool finished */
8291 if (n <= 0) {
8292 gtk_input_remove(readcdda_callback);
8293
8294 /* pick up return status of child */
8295 wait(&ret);
8296
8297 read_done = WEXITSTATUS(ret);
8298 return;
8299 }
8300
8301 dodebug(10, "cddbtool: %s\n", line);
8302
8303 /* got we the number of matches? */
8304 if (line[0] == '%') {
8305 strcpy(tmp,line+1);
8306 matchnr = atoi(tmp);
8307 return;
8308 }
8309
8310 /* got we a entry for the match list? */
8311 if (line[0] == '#') {
8312 /* end-delimitor found */
8313 if (strncmp(line,"#--",3) == 0) {
8314 /* now see if we have only one match - preselect */
8315 if (matchnr == 1) {
8316 gtk_clist_select_row(cddb_clist,0,0);
8317 }
8318 return;
8319 }
8320 /* add this to the clist */
8321 strcpy(tmp,line);
8322 if (extract_quoted(tmp) != 0)
8323 return;
8324
8325 /* now add decoded string to clist */
8326 rowdata[0] = convert_for_gtk2(tmp);
8327 gtk_clist_append(cddb_clist,rowdata);
8328 return;
8329 }
8330
8331 /* get output id of read line */
8332 strcpy(tmp,line);
8333 p = strtok(tmp,":");
8334 if (p == NULL) {
8335 return;
8336 }
8337 code = atoi(p);
8338
8339 strcpy(tmp,"");
8340
8341 /* display fitting text */
8342 switch(code) {
8343 case 0:
8344 g_snprintf(tmp,MAXLINE,_("Connecting to %s:%d"),
8345 setupdata.cddb_host, setupdata.cddb_port);
8346 break;
8347 case 1:
8348 strcpy(tmp,_("Connect ok: Sending handshake"));
8349 break;
8350 case 2:
8351 strcpy(tmp,_("Sending CDDB-query"));
8352 break;
8353 case 3:
8354 strcpy(tmp,_("No matches found - unknown CD"));
8355 break;
8356 case 4:
8357 /* close matches */
8358 if (matchnr == 1) {
8359 strcpy(tmp,_("Found one close match"));
8360 } else {
8361 g_snprintf(tmp,MAXLINE,_("Found %d close matches - Please select"), matchnr);
8362 }
8363 break;
8364 case 5:
8365 /* exact matches */
8366 if (matchnr == 1) {
8367 strcpy(tmp,_("Found one exact match"));
8368 } else {
8369 g_snprintf(tmp,MAXLINE,_("Found %d exact matches - Please select"), matchnr);
8370 }
8371 break;
8372 case 6:
8373 strcpy(tmp,_("Requesting data - Please wait"));
8374 break;
8375 case 7:
8376 /* got disc-title */
8377 strcpy(tmp,line);
8378 if (extract_quoted(tmp) != 0)
8379 return;
8380
8381 /* we want title first, then artist */
8382 if (mode == 0) {
8383 switch_artist_title(tmp);
8384 g_free(cdinfo.cddb_dtitle);
8385 cdinfo.cddb_dtitle = g_strdup(tmp);
8386
8387 dolog(3, "CDDB lookup done for %s\n", cdinfo.cddb_dtitle);
8388 } else {
8389 cdtext_set_dtitle(tmp);
8390 dolog(3, "CDDB lookup done for %s\n", tmp);
8391 }
8392
8393 /* recycle matchnr-var as track-counter */
8394 matchnr = 0;
8395
8396 return;
8397 case 8:
8398 /* got track-title */
8399 strcpy(tmp,line);
8400 if (extract_quoted(tmp) != 0)
8401 return;
8402
8403 if (mode == 0) {
8404 if (matchnr >= cdinfo.nr_tracks) {
8405 g_warning("invalid track count from cddb-server\n");
8406 return;
8407 }
8408
8409 g_free(trackinfo[matchnr]->cddb_ttitle);
8410 trackinfo[matchnr]->cddb_ttitle = g_strdup(tmp);
8411 } else {
8412 cdtext_set_ttitle(tmp, matchnr+1);
8413 }
8414 matchnr++;
8415 return;
8416
8417 /* Error-codes */
8418 case -1:
8419 strcpy(tmp,_("Error: Hostname lookup failure"));
8420 break;
8421 case -2:
8422 strcpy(tmp,_("Error: Can't open stream socket"));
8423 break;
8424 case -3:
8425 strcpy(tmp,_("Error: Connection refused"));
8426 break;
8427 case -4:
8428 strcpy(tmp,_("Error: No response from server"));
8429 break;
8430 case -5:
8431 strcpy(tmp,_("Error: No answer within timeout"));
8432 break;
8433 case -6:
8434 strcpy(tmp,_("Handshake failed - No valid CDDB-server?"));
8435 break;
8436 case -7:
8437 strcpy(tmp,_("Error: CDDB-query failed"));
8438 break;
8439 case -8:
8440 strcpy(tmp,_("Error: CDDB-read failed"));
8441 break;
8442 case -9:
8443 strcpy(tmp,_("Warning: CDDB-logout failed"));
8444 break;
8445 case -10:
8446 strcpy(tmp,_("Error: CDDB write error on socket"));
8447 break;
8448 case -11:
8449 strcpy(tmp,_("Error: CDDB read error on socket"));
8450 break;
8451 }
8452
8453 gtk_label_set_text(GTK_LABEL(cddb_info_label), tmp);
8454 }
8455
8456
8457 /* do lookup the cddb-database */
8458 /* mode = 0, cddb lookup based on CD
8459 mode = 1, cddb lookup based on toc-file
8460 mode = 2, cddb lookup based on CD but called from edit-cdtext */
8461
start_cddb_lookup_action(gint mode)8462 gint start_cddb_lookup_action(gint mode) {
8463 gchar tmp[MAXLINE];
8464 gchar tmp2[MAXLINE];
8465 gchar tmp_cddbhost[MAXLINE];
8466 gchar tmp_cddbproxy[MAXLINE];
8467 char cmd[MAXLINE];
8468 track_read_param_t *trackparam;
8469 GList *loop;
8470 gint read_out;
8471 gint i;
8472
8473 /* if another lookup running, ignore */
8474 if (read_done == 999) {
8475 return -1;
8476 }
8477
8478 read_done = 999;
8479 read_output_ctrl = 0;
8480 matchnr = 0;
8481
8482 /* build of command line */
8483 if (mode == 0 || mode == 2) {
8484 g_snprintf(tmp,MAXLINE,"cddb query %s %d ",
8485 cdinfo.cddb_discid, cdinfo.nr_tracks);
8486 for (i = 0; i < cdinfo.nr_tracks; i++) {
8487 g_snprintf(tmp2,MAXLINE,"%d ",
8488 trackinfo[i]->start_sec + 150);
8489 strcat(tmp,tmp2);
8490 }
8491 g_snprintf(tmp2,MAXLINE,"%d",cdinfo.total_size / 75);
8492 strcat(tmp,tmp2);
8493 } else {
8494 /* get data from toc file */
8495 g_snprintf(tmp,MAXLINE,"cddb query %s %d ",
8496 trackreadset.cd_discid, trackreadset.nrtracks);
8497 loop = g_list_first(trackreadset.trackparams);
8498 for (i = 0; i < trackreadset.nrtracks; i++) {
8499 trackparam = loop->data;
8500 if (trackparam) {
8501 g_snprintf(tmp2,MAXLINE,"%d ",
8502 trackparam->start_sec + 150);
8503 strcat(tmp,tmp2);
8504 } else {
8505 g_warning("trackreadset corruption detected.\n");
8506 }
8507 loop = loop->next;
8508 }
8509 g_snprintf(tmp2,MAXLINE,"%d",trackreadset.cdsize / 75);
8510 strcat(tmp,tmp2);
8511 }
8512
8513 strncpy(tmp_cddbhost, setupdata.cddb_host, MAXLINE);
8514 convert_escape(tmp_cddbhost);
8515 strncpy(tmp_cddbproxy, setupdata.cddb_proxy_host, MAXLINE);
8516 convert_escape(tmp_cddbproxy);
8517
8518 if (setupdata.cddb_use_http == 0) {
8519 g_snprintf(cmd,MAXLINE,
8520 "%s/%s -s \"%s\" -p %d -u \"%s\" -h \"%s\" -q \"%s\"",
8521 sharedir, CDDBTOOL, tmp_cddbhost, setupdata.cddb_port,
8522 username, hostname, tmp);
8523 } else {
8524 /* we want to use http */
8525 if (setupdata.cddb_use_proxy == 0) {
8526 /* but no proxy */
8527 g_snprintf(cmd,MAXLINE,
8528 "%s/%s -s \"%s\" -u \"%s\" -h \"%s\" -H -q \"%s\"",
8529 sharedir, CDDBTOOL, tmp_cddbhost,
8530 username, hostname, tmp);
8531 } else {
8532 /* http with proxy */
8533 g_snprintf(cmd,MAXLINE,
8534 "%s/%s -s \"%s\" -u \"%s\" -h \"%s\" -U \"%s\" -P %d -q \"%s\"",
8535 sharedir, CDDBTOOL, tmp_cddbhost,
8536 username, hostname, tmp_cddbproxy,
8537 setupdata.cddb_proxy_port, tmp);
8538 }
8539 }
8540 dodebug(1, "spawning: %s\n",cmd);
8541 if (mode == 0 || mode == 2) {
8542 dolog(2, "CDDB lookup for discid %s\n", cdinfo.cddb_discid);
8543 } else {
8544 dolog(2, "CDDB lookup for discid %s (from toc-file)\n", trackreadset.cd_discid);
8545 }
8546 dolog(3, "Executing: %s\n", cmd);
8547
8548 readcdda_pid = full_dpl_pipe3(&read_out,&cddb_in,NULL,cmd,0);
8549 readcdda_pid2 = -1;
8550
8551 fcntl(read_out, F_SETFL, O_NONBLOCK);
8552
8553 readcdda_callback = gdk_input_add(read_out, GDK_INPUT_READ,
8554 (GdkInputFunction) read_cddbtool_out, GINT_TO_POINTER(mode));
8555
8556
8557 /* now wait until track is read */
8558 while (read_done == 999) {
8559 wait_and_process_events();
8560 }
8561
8562 close(read_out);
8563 close(cddb_in);
8564
8565 return read_done;
8566 }
8567
8568
8569 /* the user selected a specific row on cddb-window */
8570
continue_cddb_lookup_action(gint match)8571 gint continue_cddb_lookup_action(gint match) {
8572 gchar tmp[MAXLINE];
8573
8574 dodebug(2, "sending %d to cddbtool\n", match);
8575
8576 /* send this match back to our cddbtool-process */
8577 g_snprintf(tmp,MAXLINE,"%d\n",match);
8578 if (write(cddb_in, tmp, strlen(tmp)) != strlen(tmp)) {
8579 g_warning("write error to cddbtool pipe\n");
8580 return 1;
8581 }
8582 return 0;
8583 }
8584
8585
8586 /* call wavplay test.wav */
8587
test_dspdevice_play()8588 void test_dspdevice_play() {
8589 gchar line[MAXLINE];
8590 FILE *fpin;
8591
8592 /* allocate memory */
8593 g_snprintf(line,MAXLINE,"%s/%s -d \"%s\" \"%s/%s\" 2>&1", sharedir,
8594 WAVPLAY, setupdata.dsp_device, sharedir, DSPTESTSOUND);
8595
8596 dodebug(1, "calling: %s\n", line);
8597
8598 if ((fpin = popen(line,"r")) == NULL) {
8599 g_error("popen error\n");
8600 }
8601
8602 for (;;) {
8603 if (fgets(line,MAXLINE,fpin) == NULL)
8604 break;
8605 dodebug(10, "dsptest: %s", line);
8606 }
8607
8608 if (pclose(fpin) == -1) {
8609 g_error("pclose error\n");
8610 }
8611
8612 }
8613
8614
8615 /* Save the current iso-options to a file - all strings are converted
8616 in a printable form first: return 0 if ok, or 1 on error */
8617
save_isooptions_file(gchar * confdir,gchar * fname)8618 gint save_isooptions_file(gchar *confdir, gchar *fname) {
8619 FILE *fd;
8620 gchar tmp[MAXLINE];
8621 gint i;
8622
8623 /* now check if the confdir exists */
8624 if (!is_directory(confdir)) {
8625 /* try to create directory */
8626 mkdir(confdir, 0700);
8627 dodebug(2, "trying to mkdir %s\n", confdir);
8628 }
8629
8630 g_snprintf(tmp,MAXLINE,"%s/%s", confdir, fname);
8631
8632 dodebug(1, "Opening %s for writing\n", tmp);
8633 dolog(3, "Saving isooptions file %s\n", tmp);
8634
8635 fd = fopen(tmp,"w");
8636
8637 if (fd == NULL) {
8638 /* error opening file */
8639 return 1;
8640 }
8641
8642 /* write the config-file header */
8643 fputs("#\n",fd);
8644 g_snprintf(tmp,MAXLINE,"# X-CD-Roast %s Iso-Options-File\n",XCDROAST_VERSION);
8645 fputs(tmp,fd);
8646 fputs("#\n",fd);
8647 fputs("# Automatically created by the X-CD-Roast-Setup\n",fd);
8648 fputs("# Don't edit! (Unless you REALLY know what you are doing)\n",fd);
8649 fputs("#\n\n",fd);
8650
8651 /* write data */
8652 g_snprintf(tmp,MAXLINE,"VERSION = \"%s\"\n",XCDROAST_VERSION);
8653 fputs(tmp,fd);
8654 g_snprintf(tmp,MAXLINE,"PLATFORM = \"%s\"\n",system_platform);
8655 fputs(tmp,fd);
8656
8657 for (i=0; i<24; i++) {
8658 g_snprintf(tmp,MAXLINE,"OPT_%d = %d\n", i,
8659 masterparam.opt[i]);
8660 fputs(tmp,fd);
8661 }
8662
8663 g_snprintf(tmp,MAXLINE,"IN_CHARSET = \"%s\"\n",
8664 charset_types[masterparam.charset]);
8665 fputs(tmp,fd);
8666 g_snprintf(tmp,MAXLINE,"OUT_CHARSET = \"%s\"\n",
8667 charset_types[masterparam.outcharset]);
8668 fputs(tmp,fd);
8669
8670 g_snprintf(tmp,MAXLINE,"SHOW_ONLY_DIRS = %d\n",
8671 masterparam.show_only_dirs);
8672 fputs(tmp,fd);
8673 g_snprintf(tmp,MAXLINE,"SHOW_HIDDEN_FILES = %d\n",
8674 masterparam.show_hidden_files);
8675 fputs(tmp,fd);
8676
8677 if (fclose(fd) != 0) {
8678 /* error closing file */
8679 return 1;
8680 }
8681
8682 return 0;
8683 }
8684
8685
8686 /* Load the iso-options-default file
8687 return 0 if ok, or 1 on error */
8688
load_isooptions_file(gchar * fname)8689 gint load_isooptions_file(gchar *fname) {
8690 FILE *fd;
8691 gchar line[MAXLINE];
8692 gchar id[MAXLINE];
8693 gchar value[MAXLINE];
8694 gchar tmp[MAXLINE];
8695 gint optval, optnr, i;
8696
8697 if ((fd = fopen(fname,"r")) == NULL) {
8698 /* error opening file */
8699 dodebug(1, "Failed to open iso options file %s\n", fname);
8700 dolog(3, "Failed loading iso options file %s\n", fname);
8701 return 1;
8702 }
8703
8704 dodebug(1, "Opening iso options file %s for reading\n", fname);
8705 dolog(3, "Loading iso options file %s\n", fname);
8706
8707 for (;;) {
8708 if (fgets(line,MAXLINE,fd) == NULL)
8709 break;
8710
8711 dodebug(10,"isooptions: %s", line),
8712
8713 /* skip empty or hashed lines */
8714 strip_string(line);
8715 if (*line == '#' || *line == '\0')
8716 continue;
8717
8718 /* parse lines */
8719 if (parse_config_line(line,id,value)) {
8720 g_error("syntax error in isooptions-file\n");
8721 }
8722
8723 if (strncmp("OPT_",id,4) == 0) {
8724 strcpy(tmp,id+4);
8725 optnr = atoi(tmp);
8726 optval = atoi(value);
8727 if (optnr < 24)
8728 masterparam.opt[optnr] = optval;
8729 }
8730
8731 if (strncmp("IN_CHARSET",id,7) == 0) {
8732 masterparam.charset = 0;
8733 i = 0;
8734 while (charset_types[i] != NULL) {
8735 if (strcmp(charset_types[i],value) == 0) {
8736 masterparam.charset = i;
8737 break;
8738 }
8739 i++;
8740 }
8741 }
8742 if (strncmp("OUT_CHARSET",id,7) == 0) {
8743 masterparam.outcharset = 0;
8744 i = 0;
8745 while (charset_types[i] != NULL) {
8746 if (strcmp(charset_types[i],value) == 0) {
8747 masterparam.outcharset = i;
8748 break;
8749 }
8750 i++;
8751 }
8752 }
8753
8754 if (strcmp("SHOW_ONLY_DIRS",id) == 0) {
8755 masterparam.show_only_dirs = atoi(value);
8756 }
8757 if (strcmp("SHOW_HIDDEN_FILES",id) == 0) {
8758 masterparam.show_hidden_files = atoi(value);
8759 }
8760
8761 }
8762
8763 if (fclose(fd) != 0) {
8764 /* error closing file */
8765 return 1;
8766 }
8767
8768 return 0;
8769 }
8770
8771
8772 /* Save the current iso-headers to a file - all strings are converted
8773 in a printable form first: return 0 if ok, or 1 on error */
8774
save_isoheaders_file(gchar * confdir,gchar * fname)8775 gint save_isoheaders_file(gchar *confdir, gchar *fname) {
8776 FILE *fd;
8777 gchar tmp[MAXLINE];
8778 gchar tmp2[MAXLINE];
8779
8780 /* now check if the confdir exists */
8781 if (!is_directory(confdir)) {
8782 /* try to create directory */
8783 mkdir(confdir, 0700);
8784 dodebug(2, "trying to mkdir %s\n", confdir);
8785 }
8786
8787 g_snprintf(tmp,MAXLINE,"%s/%s", confdir, fname);
8788
8789 dodebug(1, "Opening %s for writing\n", tmp);
8790 dolog(3, "Saving isoheaders file %s\n", tmp);
8791
8792 fd = fopen(tmp,"w");
8793
8794 if (fd == NULL) {
8795 /* error opening file */
8796 return 1;
8797 }
8798
8799 /* write the config-file header */
8800 fputs("#\n",fd);
8801 g_snprintf(tmp,MAXLINE,"# X-CD-Roast %s Iso-Headers-File\n",XCDROAST_VERSION);
8802 fputs(tmp,fd);
8803 fputs("#\n",fd);
8804 fputs("# Automatically created by the X-CD-Roast-Setup\n",fd);
8805 fputs("# Don't edit! (Unless you REALLY know what you are doing)\n",fd);
8806 fputs("#\n\n",fd);
8807
8808 /* write data */
8809 g_snprintf(tmp,MAXLINE,"VERSION = \"%s\"\n",XCDROAST_VERSION);
8810 fputs(tmp,fd);
8811 g_snprintf(tmp,MAXLINE,"PLATFORM = \"%s\"\n",system_platform);
8812 fputs(tmp,fd);
8813
8814 strcpy(tmp2,masterparam.publisher);
8815 g_snprintf(tmp,MAXLINE,"PUBLISHER = \"%s\"\n",convert_escape(tmp2));
8816 fputs(tmp,fd);
8817 strcpy(tmp2,masterparam.preparer);
8818 g_snprintf(tmp,MAXLINE,"PREPARER = \"%s\"\n",convert_escape(tmp2));
8819 fputs(tmp,fd);
8820 /*
8821 strcpy(tmp2,masterparam.application);
8822 g_snprintf(tmp,MAXLINE,"APPLICATION = \"%s\"\n",convert_escape(tmp2));
8823 fputs(tmp,fd);
8824 */
8825 strcpy(tmp2,masterparam.abstract);
8826 g_snprintf(tmp,MAXLINE,"ABSTRACT = \"%s\"\n",convert_escape(tmp2));
8827 fputs(tmp,fd);
8828 strcpy(tmp2,masterparam.biblio);
8829 g_snprintf(tmp,MAXLINE,"BIBLIO = \"%s\"\n",convert_escape(tmp2));
8830 fputs(tmp,fd);
8831 strcpy(tmp2,masterparam.copyright);
8832 g_snprintf(tmp,MAXLINE,"COPYRIGHT = \"%s\"\n",convert_escape(tmp2));
8833 fputs(tmp,fd);
8834
8835 if (fclose(fd) != 0) {
8836 /* error closing file */
8837 return 1;
8838 }
8839
8840 return 0;
8841 }
8842
8843
8844 /* Load the iso-headers-default file
8845 return 0 if ok, or 1 on error */
8846
load_isoheaders_file(gchar * fname)8847 gint load_isoheaders_file(gchar *fname) {
8848 FILE *fd;
8849 gchar line[MAXLINE];
8850 gchar id[MAXLINE];
8851 gchar value[MAXLINE];
8852
8853 if ((fd = fopen(fname,"r")) == NULL) {
8854 /* error opening file */
8855 dodebug(1, "Failed to open iso headers file %s\n", fname);
8856 dolog(3, "Failed loading iso headers file %s\n", fname);
8857 return 1;
8858 }
8859
8860 dodebug(1, "Opening iso headers file %s for reading\n", fname);
8861 dolog(3, "Loading iso headers file %s\n", fname);
8862
8863 for (;;) {
8864 if (fgets(line,MAXLINE,fd) == NULL)
8865 break;
8866
8867 dodebug(10,"isoheaders: %s", line),
8868
8869 /* skip empty or hashed lines */
8870 strip_string(line);
8871 if (*line == '#' || *line == '\0')
8872 continue;
8873
8874 /* parse lines */
8875 if (parse_config_line(line,id,value)) {
8876 g_error("syntax error in isoheaders-file\n");
8877 }
8878
8879 if (strcmp("PUBLISHER",id) == 0) {
8880 g_free(masterparam.publisher);
8881 masterparam.publisher = g_strdup(value);
8882 }
8883 if (strcmp("PREPARER",id) == 0) {
8884 g_free(masterparam.preparer);
8885 masterparam.preparer = g_strdup(value);
8886 }
8887 if (strcmp("APPLICATION",id) == 0) {
8888 g_free(masterparam.application);
8889 masterparam.application = g_strdup(value);
8890 }
8891 if (strcmp("ABSTRACT",id) == 0) {
8892 g_free(masterparam.abstract);
8893 masterparam.abstract = g_strdup(value);
8894 }
8895 if (strcmp("BIBLIO",id) == 0) {
8896 g_free(masterparam.biblio);
8897 masterparam.biblio = g_strdup(value);
8898 }
8899 if (strcmp("COPYRIGHT",id) == 0) {
8900 g_free(masterparam.copyright);
8901 masterparam.copyright = g_strdup(value);
8902 }
8903 }
8904
8905 if (fclose(fd) != 0) {
8906 /* error closing file */
8907 return 1;
8908 }
8909
8910 return 0;
8911 }
8912
8913
8914 /* print master dirs and excludes (debug purposes) */
8915
print_master_dirs()8916 static void print_master_dirs() {
8917 GList *loop;
8918 mstr_redirect_t *mstr;
8919 gchar *p;
8920
8921 dodebug(2,"------ directories to master -----\n");
8922 loop = g_list_first(masterparam.mstr_redir);
8923 while (loop) {
8924 mstr = (mstr_redirect_t *) loop->data;
8925
8926 if (mstr) {
8927 if (mstr->mstr_path && !mstr->redir_path) {
8928 dodebug(2,"master-dir: %s\n", mstr->mstr_path);
8929 }
8930 if (mstr->mstr_path && mstr->redir_path) {
8931 dodebug(2,"master-dir: %s -> %s\n",
8932 mstr->mstr_path, mstr->redir_path);
8933 }
8934 }
8935 loop = loop->next;
8936 }
8937
8938 dodebug(2,"------ directories to excluded from master -----\n");
8939 loop = g_list_first(masterparam.exclude_paths);
8940 while (loop) {
8941 p = (gchar *)loop->data;
8942 if (p) {
8943 dodebug(2,"master-exclude: %s\n", p);
8944 }
8945 loop = loop->next;
8946 }
8947 }
8948
8949
8950 /* build mkisofs-commandline */
8951
build_mkisofs_cmdline(gchar * ret,gint printsize,gchar * outfile,gint verbose)8952 static void build_mkisofs_cmdline(gchar *ret, gint printsize, gchar *outfile, gint verbose) {
8953 gchar line[MAXLINE*10];
8954 gchar tmp[MAXLINE];
8955 gchar tmp2[MAXLINE];
8956 gchar tmp3[MAXLINE];
8957 gchar tmp34[MAXLINE];
8958 gchar tmp35[MAXLINE];
8959 gchar tmp4[MAXLINE];
8960 gchar tmp5[MAXLINE];
8961 gchar tmp6[MAXLINE];
8962 gchar tmp7[MAXLINE];
8963 gchar tmptmp[MAXLINE];
8964 gchar tmptmp2[MAXLINE];
8965 gchar tmptmp3[MAXLINE];
8966 GList *loop;
8967 mstr_redirect_t *mstr;
8968 gchar *p;
8969 FILE *fd;
8970 gint pathcount;
8971
8972 /* check first if we got our temporary files? */
8973 if (!master_fname1 || !master_fname2) {
8974 g_warning("no temporary files for master? aborting...\n");
8975
8976 /* return some command that will fail eventually gracefully */
8977 strcpy(ret, "false");
8978 return;
8979 }
8980
8981 if (debug > 1) {
8982 print_master_dirs();
8983 }
8984
8985 get_wrap_path("MKISOFS",tmp);
8986
8987 /* extract iso-options */
8988 if (verbose) {
8989 strcpy(tmp2,"-gui -v ");
8990 } else {
8991 strcpy(tmp2," ");
8992 }
8993
8994 if (masterparam.opt[0]) {
8995 strcat(tmp2,"-r ");
8996 }
8997 if (masterparam.opt[1]) {
8998 strcat(tmp2,"-J ");
8999 }
9000 if (masterparam.charset != 0) {
9001 strcat(tmp2,"-input-charset ");
9002 strcat(tmp2,charset_types[masterparam.charset]);
9003 strcat(tmp2," ");
9004 }
9005 if (masterparam.outcharset != 0) {
9006 strcat(tmp2,"-output-charset ");
9007 strcat(tmp2,charset_types[masterparam.outcharset]);
9008 strcat(tmp2," ");
9009 }
9010 if (masterparam.opt[2]) {
9011 strcat(tmp2,"-R ");
9012 }
9013 if (masterparam.opt[3]) {
9014 strcat(tmp2,"-f ");
9015 }
9016 if (masterparam.opt[4]) {
9017 strcat(tmp2,"-l ");
9018 }
9019 if (masterparam.opt[5]) {
9020 strcat(tmp2,"-T ");
9021 }
9022 if (masterparam.opt[6]) {
9023 strcat(tmp2,"-D ");
9024 }
9025 if (masterparam.opt[7]) {
9026 strcat(tmp2,"-allow-leading-dots ");
9027 }
9028 if (masterparam.opt[8]) {
9029 strcat(tmp2,"-d ");
9030 }
9031 if (masterparam.opt[9]) {
9032 strcat(tmp2,"-N ");
9033 }
9034 if (masterparam.opt[10]) {
9035 strcat(tmp2,"-U ");
9036 }
9037 if (masterparam.opt[11]) {
9038 strcat(tmp2,"-no-bak ");
9039 }
9040 if (masterparam.opt[12]) {
9041 strcat(tmp2,"-hide-rr-moved ");
9042 }
9043 if (masterparam.opt[13]) {
9044 strcat(tmp2,"-hide-joliet-trans-tbl ");
9045 }
9046 if (masterparam.opt[14]) {
9047 strcat(tmp2,"-no-rr ");
9048 }
9049 if (masterparam.opt[15]) {
9050 strcat(tmp2,"-no-iso-translate ");
9051 }
9052 if (masterparam.opt[16]) {
9053 strcat(tmp2,"-joliet-long ");
9054 }
9055 if (masterparam.opt[17]) {
9056 strcat(tmp2,"-allow-lowercase ");
9057 }
9058 if (masterparam.opt[18]) {
9059 strcat(tmp2,"-allow-multidot ");
9060 }
9061 if (masterparam.opt[19]) {
9062 strcat(tmp2,"-max-iso9660-filenames ");
9063 }
9064 if (masterparam.opt[20]) {
9065 strcat(tmp2,"-relaxed-filenames ");
9066 }
9067 if (masterparam.opt[21]) {
9068 strcat(tmp2,"-dvd-video ");
9069 }
9070 if (masterparam.opt[23] > 0) {
9071 g_snprintf(tmptmp3,MAXLINE,"-iso-level %d ",
9072 masterparam.opt[23]);
9073 strcat(tmp2,tmptmp3);
9074 }
9075
9076 if (printsize) {
9077 strcat(tmp2,"-print-size ");
9078 }
9079
9080 /* extract bootable stuff */
9081 strcpy(tmp3,"");
9082
9083 if (masterparam.bootable == 1) {
9084 /* el torito */
9085 if (masterparam.boot_image && masterparam.boot_catalog) {
9086 strcpy(tmptmp, masterparam.boot_image);
9087 strcpy(tmptmp2, masterparam.boot_catalog);
9088 g_snprintf(tmp3,MAXLINE,"-b \"%s\" -c \"%s\"",
9089 convert_escape(tmptmp),
9090 convert_escape(tmptmp2));
9091
9092 switch(masterparam.boot_type) {
9093 case 1:
9094 strcat(tmp3," -hard-disk-boot");
9095 break;
9096 case 2:
9097 strcat(tmp3," -no-emul-boot");
9098 if (masterparam.boot_load_size >= 0) {
9099 g_snprintf(tmptmp,MAXLINE," -boot-load-size %d", masterparam.boot_load_size);
9100 strcat(tmp3, tmptmp);
9101 }
9102 break;
9103 case 3:
9104 strcat(tmp3," -no-boot");
9105 break;
9106 default:
9107 break;
9108 }
9109
9110 if (masterparam.boot_info_table) {
9111 strcat(tmp3," -boot-info-table");
9112 }
9113 }
9114 }
9115 if (masterparam.bootable == 2) {
9116 /* sparc boot */
9117 if (masterparam.sparc_boot) {
9118 strcpy(tmptmp, masterparam.sparc_boot);
9119 g_snprintf(tmp3,MAXLINE,"-B \"%s\"",
9120 convert_escape(tmptmp));
9121 }
9122 }
9123
9124 /* multisession info */
9125 strcpy(tmp35,"");
9126
9127 if (curset.multisession == 1) {
9128 if (masterparam.next_session_start != -1) {
9129
9130 if (convert_devnr2busid(curset.writer_devnr,tmp34) != 0) {
9131 g_error("failed to get devicenr for writer in build_mkisofs_cmdline\n");
9132 }
9133
9134 /* appending a session to an audio CD? */
9135 if (cdinfo.nr_tracks > 0 && trackinfo[0]->type == 1) {
9136 /* dont import old session */
9137 g_snprintf(tmp35,MAXLINE,"-C %d,%d ",
9138 masterparam.last_session_start,
9139 masterparam.next_session_start);
9140 } else {
9141 g_snprintf(tmp35,MAXLINE,"-C %d,%d -M \"%s\"",
9142 masterparam.last_session_start,
9143 masterparam.next_session_start,
9144 tmp34);
9145 }
9146 }
9147 }
9148
9149 /* extract headers */
9150 strcpy(tmp4,"");
9151
9152 if (masterparam.volid) {
9153 strcpy(tmptmp, masterparam.volid);
9154 g_snprintf(tmp5,MAXLINE,"-V \"%s\" ",
9155 convert_escape(tmptmp));
9156 strcat(tmp4,tmp5);
9157 }
9158 if (masterparam.publisher) {
9159 strcpy(tmptmp, masterparam.publisher);
9160 g_snprintf(tmp5,MAXLINE,"-publisher \"%s\" ",
9161 convert_escape(tmptmp));
9162 strcat(tmp4,tmp5);
9163 }
9164 if (masterparam.preparer) {
9165 strcpy(tmptmp, masterparam.preparer);
9166 g_snprintf(tmp5,MAXLINE,"-preparer \"%s\" ",
9167 convert_escape(tmptmp));
9168 strcat(tmp4,tmp5);
9169 }
9170 /*
9171 if (masterparam.application) {
9172 strcpy(tmptmp, masterparam.application);
9173 g_snprintf(tmp5,MAXLINE,"-A \"%s\" ",
9174 convert_escape(tmptmp));
9175 strcat(tmp4,tmp5);
9176 }
9177 */
9178 if (masterparam.abstract) {
9179 strcpy(tmptmp, masterparam.abstract);
9180 g_snprintf(tmp5,MAXLINE,"-abstract \"%s\" ",
9181 convert_escape(tmptmp));
9182 strcat(tmp4,tmp5);
9183 }
9184 if (masterparam.biblio) {
9185 strcpy(tmptmp, masterparam.biblio);
9186 g_snprintf(tmp5,MAXLINE,"-biblio \"%s\" ",
9187 convert_escape(tmptmp));
9188 strcat(tmp4,tmp5);
9189 }
9190 if (masterparam.copyright) {
9191 strcpy(tmptmp, masterparam.copyright);
9192 g_snprintf(tmp5,MAXLINE,"-copyright \"%s\" ",
9193 convert_escape(tmptmp));
9194 strcat(tmp4,tmp5);
9195 }
9196
9197 /* now the excluded directories */
9198 /* write to temporary file */
9199 strcpy(tmp6,"");
9200
9201 fd = fopen(master_fname2,"w");
9202 if (!fd) {
9203 g_warning("failed to open %s for writing! aborting...\n",
9204 master_fname2);
9205 strcpy(ret,"false");
9206 return;
9207 }
9208
9209 loop = g_list_first(masterparam.exclude_paths);
9210 while (loop) {
9211 p = (gchar *)loop->data;
9212 if (p) {
9213 strcpy(tmptmp,p);
9214 g_snprintf(tmp5,MAXLINE,"%s\n",
9215 convert_escape(tmptmp));
9216 fputs(tmp5,fd);
9217 }
9218 loop = loop->next;
9219 }
9220 fclose(fd);
9221
9222 /* if we actually got excludes, add the tmp-excl file */
9223 if (g_list_length(masterparam.exclude_paths) != 0) {
9224 strcpy(tmptmp,master_fname2);
9225 g_snprintf(tmp5,MAXLINE,"-exclude-list \"%s\" ",
9226 convert_escape(tmptmp));
9227 strcat(tmp6,tmp5);
9228 }
9229
9230 /* output-file given? */
9231 if (outfile) {
9232 strcpy(tmptmp,outfile);
9233 g_snprintf(tmp5,MAXLINE,"-o \"%s\" ",
9234 convert_escape(tmptmp));
9235 strcat(tmp6,tmp5);
9236 }
9237
9238 /* the last are the master-paths with redirects */
9239 strcpy(tmp7,"");
9240
9241 fd = fopen(master_fname1,"w");
9242 if (!fd) {
9243 g_warning("failed to open %s for writing! aborting...\n",
9244 master_fname1);
9245 strcpy(ret,"false");
9246 return;
9247 }
9248
9249 /* the first path is to be added on the command line..all others
9250 to temporary file */
9251 pathcount = 0;
9252 loop = g_list_first(masterparam.mstr_redir);
9253 while (loop) {
9254 mstr = (mstr_redirect_t *) loop->data;
9255 if (mstr) {
9256 if (mstr->mstr_path && !mstr->redir_path) {
9257 /* no redir available */
9258 strcpy(tmptmp,mstr->mstr_path);
9259 if (pathcount == 0) {
9260 g_snprintf(tmp5,MAXLINE,"\"%s\" ",
9261 convert_escape3(tmptmp));
9262 strcat(tmp7,tmp5);
9263 } else {
9264 /* write to file */
9265 g_snprintf(tmp5,MAXLINE,"%s\n",
9266 convert_escape2(tmptmp));
9267 fputs(tmp5,fd);
9268 }
9269 }
9270 if (mstr->mstr_path && mstr->redir_path) {
9271 strcpy(tmptmp,mstr->mstr_path);
9272 strcpy(tmptmp2,mstr->redir_path);
9273 if (pathcount == 0) {
9274 g_snprintf(tmp5,MAXLINE,"\"%s=%s\" ",
9275 convert_escape3(tmptmp2),
9276 convert_escape3(tmptmp));
9277 strcat(tmp7,tmp5);
9278 } else {
9279 /* write to file */
9280 g_snprintf(tmp5,MAXLINE,"%s=%s\n",
9281 convert_escape2(tmptmp2),
9282 convert_escape2(tmptmp));
9283 fputs(tmp5,fd);
9284 }
9285 }
9286 pathcount++;
9287 }
9288 loop = loop->next;
9289 }
9290 fclose(fd);
9291
9292 /* if we got more than one path add master-file */
9293 if (g_list_length(masterparam.mstr_redir) > 1) {
9294 strcpy(tmptmp,master_fname1);
9295 g_snprintf(tmp5,MAXLINE,"-path-list \"%s\" ",
9296 convert_escape(tmptmp));
9297 strcat(tmp6,tmp5);
9298 }
9299
9300 /* now put all together */
9301 g_snprintf(line,MAXLINE*10, "%s %s %s %s %s %s -graft-points %s",
9302 tmp, tmp2, tmp3, tmp35, tmp4, tmp6, tmp7);
9303
9304 strcpy(ret,line);
9305 }
9306
9307
9308 /* get output of mkisofs */
9309
read_mkisofs_out(gpointer data,gint source,GdkInputCondition cond)9310 static void read_mkisofs_out(gpointer data, gint source, GdkInputCondition cond) {
9311 gint n;
9312 gchar line[MAXLINE];
9313 gchar tmp[MAXLINE];
9314
9315 n = read_line(source, line, MAXLINE);
9316
9317 /* finished? */
9318 if (n <= 0) {
9319 return;
9320 }
9321
9322 dodebug(10, "mkisofs (stdout): %s\n", line);
9323
9324
9325 strcpy(tmp,line);
9326 strcat(tmp,"\n");
9327
9328 convert_for_gtk2_textwidget(tmp);
9329 gtk_text_insert(GTK_TEXT(readtrack_textview),
9330 fixedfont,NULL,NULL,tmp, strlen(tmp));
9331 }
9332
9333
9334 /* get output of mkisofs (stderr) */
9335
read_mkisofs_stderr(gpointer data,gint source,GdkInputCondition cond)9336 static void read_mkisofs_stderr(gpointer data, gint source, GdkInputCondition cond) {
9337 gint n;
9338 gint ret;
9339 gchar line[MAXLINE];
9340 gchar tmp[MAXLINE];
9341 gchar *p;
9342
9343 n = read_line(source, line, MAXLINE);
9344
9345 /* finished? */
9346 if (n <= 0) {
9347 gtk_input_remove(readcdda_callback);
9348 gtk_input_remove(readcdda_callback2);
9349
9350 /* pick up return status of child */
9351 wait(&ret);
9352
9353 read_done = WEXITSTATUS(ret);
9354
9355 return;
9356 }
9357
9358 dodebug(10, "mkisofs (stderr): %s\n", line);
9359
9360 if (strncmp(line, "Total extents",13) == 0) {
9361 strcpy(tmp,line);
9362 p = strtok(tmp,"=");
9363 if (p) {
9364 p = strtok(NULL,"");
9365 if (p) {
9366 masterparam.session_size = atoi(p);
9367 }
9368 }
9369 }
9370
9371 strcpy(tmp,line);
9372 strcat(tmp,"\n");
9373
9374 convert_for_gtk2_textwidget(tmp);
9375 gtk_text_insert(GTK_TEXT(readtrack_textview),
9376 fixedfont,NULL,NULL,tmp, strlen(tmp));
9377
9378 }
9379
9380
9381 /* call mkisofs -print-size */
9382
fill_mkisofs_check_info(GtkWidget * text_window)9383 gint fill_mkisofs_check_info(GtkWidget *text_window) {
9384 gchar cmd[MAXLINE*10];
9385 gint read_out, read_err;
9386 gchar tmp[MAXLINE];
9387
9388 /* if another process running, ignore */
9389 if (read_done == 999) {
9390 return -1;
9391 }
9392
9393 /* mark our process as running */
9394 read_done = 999;
9395 read_output_ctrl = 0;
9396 readerr_count = 0;
9397
9398 /* be sure to overwrite old value */
9399 masterparam.session_size = 0;
9400
9401 /* save text-window */
9402 readtrack_textview = text_window;
9403
9404 /* get commandline */
9405 build_mkisofs_cmdline(cmd,1,NULL,masterparam.opt[22]);
9406
9407 dodebug(1, "spawning: %s\n",cmd);
9408 dolog(1, "Getting size of mkisofs-image\n");
9409 dolog(3, "Executing: %s\n", cmd);
9410
9411 readcdda_pid = full_dpl_pipe3(&read_out,NULL,&read_err,cmd,0);
9412 readcdda_pid2 = -1;
9413
9414 fcntl(read_out, F_SETFL, O_NONBLOCK);
9415 fcntl(read_err, F_SETFL, O_NONBLOCK);
9416
9417 readcdda_callback = gdk_input_add(read_out, GDK_INPUT_READ,
9418 (GdkInputFunction) read_mkisofs_out, NULL);
9419 readcdda_callback2 = gdk_input_add(read_err, GDK_INPUT_READ,
9420 (GdkInputFunction) read_mkisofs_stderr, NULL);
9421
9422 /* now wait until get_size is finished */
9423 while (read_done == 999) {
9424 wait_and_process_events();
9425
9426 /* check if somebody clicked on cancel */
9427 if (dialog_done != 999) {
9428 kill_readcdda();
9429 /* mark we aborted */
9430 read_output_ctrl = 1;
9431 dialog_done = 999;
9432 }
9433 }
9434
9435 close(read_err);
9436 close(read_out);
9437
9438
9439 /* we killed the process */
9440 if (read_output_ctrl == 1) {
9441 strncpy(tmp, _("\nScanning aborted!\n"), MAXLINE);
9442 convert_for_gtk2_textwidget(tmp);
9443 gtk_text_insert(GTK_TEXT(readtrack_textview),
9444 fixedfont,NULL,NULL,tmp, strlen(tmp));
9445 return 2;
9446 }
9447
9448 return 0;
9449 }
9450
9451
9452 /* get output of mkisofs */
9453
read_master_out(gpointer data,gint source,GdkInputCondition cond)9454 static void read_master_out(gpointer data, gint source, GdkInputCondition cond) {
9455 gint n;
9456 gint ret;
9457 gchar line[MAXLINE];
9458 gchar tmp[MAXLINE];
9459 gchar tmp2[MAXLINE];
9460 gchar *p, *p2;
9461 gfloat pval;
9462
9463 n = read_line(source, line, MAXLINE);
9464
9465 /* finished? */
9466 if (n <= 0) {
9467 gtk_input_remove(readcdda_callback);
9468
9469 /* pick up return status of child */
9470 wait(&ret);
9471
9472 read_done = WEXITSTATUS(ret);
9473 return;
9474 }
9475
9476 dodebug(10,"mkisofs: %s\n", line);
9477
9478 /* see if we finished with mastering - set to 100% */
9479 if (strncmp(line,"Total translation table size", 28) == 0) {
9480 gtk_progress_set_percentage( GTK_PROGRESS(readtrack_pbar1),
9481 1.0);
9482 set_xcdr_title(toplevel,viewmode_dialog,100);
9483 gtk_label_set_text(GTK_LABEL(readtrack_small_info2),
9484 "100%");
9485 /* mark we are really finished */
9486 read_output_ctrl = 3;
9487 }
9488
9489 /* we are finished with scanning directories - update infotext */
9490 if (read_output_ctrl == 1) {
9491 /* update only once */
9492 read_output_ctrl = 2;
9493
9494 convert_kbytes2mbstring(masterparam.session_size * 2, tmp);
9495 g_snprintf(tmp2,MAXLINE,_("Mastering data track [%s]"), tmp);
9496 gtk_label_set_text(GTK_LABEL(readtrack_info_label),tmp2);
9497
9498 gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Mastering:"));
9499 }
9500
9501
9502 /* see if we got a percentage value and set progress bar */
9503 strcpy(tmp,line);
9504 p = strtok(tmp,",");
9505 if (p != NULL) {
9506 p2 = strtok(NULL,"");
9507 if (p2 != NULL) {
9508 strcpy(tmp2,p2);
9509 strip_string(tmp2);
9510 if (strncmp(tmp2,"estimate finish",15) == 0) {
9511 /* ok..its a percentage line */
9512 if (read_output_ctrl == 0) {
9513 read_output_ctrl = 1;
9514 }
9515 strcpy(tmp2,p);
9516 p = strtok(tmp2,"%");
9517 if (p != NULL) {
9518 strcpy(tmp,p);
9519 pval = atof(tmp);
9520 pval = pval/100;
9521 if (pval > 1.0) pval = 1.0;
9522 gtk_progress_set_percentage(
9523 GTK_PROGRESS(readtrack_pbar1),
9524 pval);
9525 set_xcdr_title(toplevel,viewmode_dialog,(gint)(pval*100+0.5));
9526 /* update small view */
9527 g_snprintf(tmp,MAXLINE,"%d%%",
9528 (gint)(pval*100+0.5));
9529 gtk_label_set_text(
9530 GTK_LABEL(readtrack_small_info2),
9531 tmp);
9532 return;
9533 }
9534 }
9535 }
9536 }
9537
9538 /* forward most other output to textview-window */
9539 strcat(line,"\n");
9540 gtk_text_insert(GTK_TEXT(readtrack_textview),
9541 fixedfont,NULL,NULL, line, strlen(line));
9542
9543 }
9544
9545
9546 /* call mkisofs to master a image */
9547
start_master_action()9548 gint start_master_action() {
9549 char cmd[MAXLINE*10]; /* extra big buffer for very long cdrecord options */
9550 gint read_dummy, read_err;
9551
9552 /* if another write running, ignore */
9553 if (read_done == 999) {
9554 return -1;
9555 }
9556
9557 /* mark our write-process as running */
9558 read_done = 999;
9559 read_output_ctrl = 0;
9560 read_abort_mark = 0;
9561
9562 /* set info label */
9563 gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Scanning master directories..."));
9564
9565 /* build command line */
9566 build_mkisofs_cmdline(cmd, 0, masterparam.image_filename, masterparam.opt[22]);
9567
9568 dodebug(1, "spawning: %s\n",cmd);
9569 dolog(1,"Master image %s\n", masterparam.image_filename);
9570 dolog(3,"Executing: %s\n", cmd);
9571
9572 /* yes...command line is done */
9573 readcdda_pid = full_dpl_pipe3(&read_dummy,NULL,&read_err,cmd,0);
9574 readcdda_pid2 = -1;
9575
9576 fcntl(read_dummy, F_SETFL, O_NONBLOCK);
9577 fcntl(read_err, F_SETFL, O_NONBLOCK);
9578
9579 readcdda_callback = gdk_input_add(read_err, GDK_INPUT_READ,
9580 (GdkInputFunction) read_master_out, NULL);
9581 readcdda_callback2 = gdk_input_add(read_dummy, GDK_INPUT_READ,
9582 (GdkInputFunction) read_cdda2wav_dummyout, NULL);
9583
9584 /* now wait until write is finished */
9585 while (read_done == 999) {
9586 wait_and_process_events();
9587 }
9588
9589 close(read_err);
9590 close(read_dummy);
9591
9592 /* aborted master ? */
9593 if (read_abort_mark == 1) {
9594 gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Mastering aborted..."));
9595 return 1;
9596 }
9597
9598 /* all ok? */
9599 if (read_done == 0 && read_output_ctrl == 3) {
9600 gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Mastering successful"));
9601 } else {
9602 /* some error? */
9603 gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Error mastering data track"));
9604 gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Master-Error:"));
9605 }
9606
9607 return 0;
9608 }
9609
9610
9611 /* do just swallow all output we get from stderr... and wait if the
9612 process terminated */
9613
mkisofs_err(gpointer pid,gint source,GdkInputCondition cond)9614 static void mkisofs_err(gpointer pid, gint source, GdkInputCondition cond) {
9615 gint n;
9616 gint ret;
9617 gchar line[MAXLINE];
9618
9619 n = read_line(source, line, MAXLINE);
9620
9621 /* readcd-finished? */
9622 if (n <= 0) {
9623 gtk_input_remove(readcdda_callback3);
9624
9625 /* pick up return status of child */
9626 waitpid((pid_t)GPOINTER_TO_INT(pid), &ret, WNOHANG);
9627
9628 dodebug(10,"Finished in mkisofs_err\n");
9629
9630 return;
9631 }
9632
9633 dodebug(10,"mkisofs (stderr): %s\n", line);
9634 }
9635
9636
9637
9638 /* call cdrecord to write a master-image on the fly */
9639
start_onthefly_master_action(gint write_devnr)9640 gint start_onthefly_master_action(gint write_devnr) {
9641 gchar tmp[MAXLINE];
9642 gchar tmp3[MAXLINE];
9643 gchar tmp4[MAXLINE];
9644 gchar cmd[MAXLINE*10]; /* extra big buffer for very long mkisofs options */
9645 gchar cmd2[MAXLINE*10];
9646 gchar outcmd[MAXLINE];
9647 gint read_out, read_err, read_err2;
9648 gint ret, tracknr;
9649 pid_t pid1, pid2;
9650 gint varirec_on, tmp_writer_speed;
9651 gint wrmode;
9652
9653 /* if another write running, ignore */
9654 if (read_done == 999) {
9655 return -1;
9656 }
9657
9658 /* mark our write-process as running */
9659 read_done = 999;
9660 read_output_ctrl = 0;
9661 pct_so_far = 0.0;
9662 cdrecord_reload = 0;
9663 cdrtimer = 0;
9664
9665 strcpy(outcmd,"");
9666
9667 /* set info label */
9668 gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Initializing CD-Writer..."));
9669
9670 /* reset writeparams-arrays */
9671 g_free(writeparams.tracktype);
9672 g_free(writeparams.frames);
9673 g_free(writeparams.pct_so_far_arr);
9674 g_free(writeparams.pct_this_track_arr);
9675 writeparams.tracktype = g_new0(gint,MAXTRACKS);
9676 writeparams.frames = g_new0(gint,MAXTRACKS);
9677 writeparams.pct_so_far_arr = g_new0(gfloat,MAXTRACKS);
9678 writeparams.pct_this_track_arr = g_new0(gfloat,MAXTRACKS);
9679 writeparams.nrtracks = 0;
9680 writeparams.simulation = curset.writesimul;
9681
9682 /* build command line of masterprocess */
9683 build_mkisofs_cmdline(cmd, 0, NULL, 0);
9684
9685 /* build command line of write process */
9686
9687 /* get bus,id,lun string */
9688 if (convert_devnr2busid_dev(write_devnr,tmp) != 0) {
9689 g_error("non existing cdrom?");
9690 }
9691
9692 /* get driveropts */
9693 varirec_on = do_driveropts(tmp4, curset.writer_devnr);
9694
9695 get_wrap_path_cdrecord(tmp3);
9696 g_snprintf(cmd2, MAXLINE*10,
9697 "%s %s gracetime=%d fs=%dk -v %s ",
9698 tmp3, tmp, get_gracetime(), get_cur_writer_fifo(), tmp4);
9699
9700 if (get_cur_writer_drvmode() >= 0) {
9701 if (drivers[get_cur_writer_drvmode()] != NULL) {
9702 g_snprintf(tmp,MAXLINE," driver=%s",
9703 drivers[get_cur_writer_drvmode()]->driver);
9704 strcat(cmd2,tmp);
9705 }
9706 }
9707
9708 /* special case with varirec - always use 4x here */
9709 if (varirec_on) {
9710 tmp_writer_speed = 4;
9711 } else {
9712 tmp_writer_speed = get_cur_writer_speed();
9713 }
9714
9715 if (get_cur_writer_speed() >= 0) {
9716 g_snprintf(tmp,MAXLINE," speed=%d", tmp_writer_speed);
9717 strcat(cmd2, tmp);
9718 }
9719
9720 /* Ignore write-mode in multisession-mode */
9721 if (curset.multisession == 0) {
9722 wrmode = get_cur_writemode();
9723 if (wrmode == 0) {
9724 strcat(cmd2," -dao");
9725 }
9726 if (wrmode == 2) {
9727 strcat(cmd2," defpregap=0");
9728 }
9729 if (wrmode == 3) {
9730 strcat(cmd2," -raw96r");
9731 }
9732 if (wrmode == 4) {
9733 strcat(cmd2," -raw96p");
9734 }
9735 if (wrmode == 5) {
9736 strcat(cmd2," -raw16");
9737 }
9738 }
9739
9740 if (curset.writesimul == 1) {
9741 strcat(cmd2," -dummy");
9742 }
9743 if (curset.writeeject == 1) {
9744 strcat(cmd2," -eject");
9745 }
9746 if (curset.nofixate == 1) {
9747 strcat(cmd2," -nofix");
9748 }
9749 if (curset.multisession == 1) {
9750 if (is_a_sony(write_devnr)) {
9751 strcat(cmd2," -multi -data");
9752 } else {
9753 strcat(cmd2," -multi");
9754 }
9755 }
9756 if (curset.writepad == 1) {
9757 strcat(cmd2," -pad");
9758 }
9759 if (curset.writeswap == 1) {
9760 strcat(cmd2," -swab");
9761 }
9762 if (curset.writeoverburn == 1) {
9763 strcat(cmd2," -overburn");
9764 }
9765 if (curset.writeignsize == 1) {
9766 strcat(cmd2," -ignsize");
9767 }
9768 if (curset.writeimmed == 1) {
9769 strcat(cmd2," -immed");
9770 }
9771
9772 /* now add track-specification: one data track */
9773 g_snprintf(tmp, MAXLINE, " -waiti tsize=%ds",
9774 masterparam.session_size);
9775 strcat(cmd2, tmp);
9776 strcat(cmd2," -");
9777
9778 /* save command line to view in progress window */
9779 g_snprintf(outcmd,MAXLINE, "Calling: %s\n\n", cmd2);
9780
9781 /* fill up percent values for nice progressbar movement */
9782 tracknr = 1;
9783 writeparams.tracktype[tracknr] = 0; /* data */
9784 writeparams.frames[tracknr] = masterparam.session_size;
9785 writeparams.pct_this_track_arr[tracknr] = 1.0;
9786 writeparams.pct_so_far_arr[tracknr] = 0.0;
9787 writeparams.nrtracks = 1;
9788
9789 dodebug(1, "spawning: %s | %s \n",cmd, cmd2);
9790 dolog(1,"Master CD on the fly\n");
9791 dolog(3,"Executing: %s | %s\n", cmd, cmd2);
9792
9793 /* output command to get better debug output */
9794 gtk_text_insert(GTK_TEXT(readtrack_textview),
9795 fixedfont,NULL,NULL,outcmd, strlen(outcmd));
9796
9797 /* yes...command line is done */
9798 full_dpl_pipe4(&pid1,&pid2,NULL,&read_err,cmd,&read_out,&read_err2,cmd2,0);
9799 mkisofs_pid = pid1;
9800 readcdda_pid = pid2;
9801 readcdda_pid2 = -1;
9802
9803 fcntl(read_out, F_SETFL, O_NONBLOCK);
9804 fcntl(read_err, F_SETFL, O_NONBLOCK);
9805 fcntl(read_err2, F_SETFL, O_NONBLOCK);
9806
9807 readcdda_callback = gdk_input_add(read_out, GDK_INPUT_READ,
9808 (GdkInputFunction) read_write_out, GINT_TO_POINTER(read_err2));
9809 readcdda_callback2 = gdk_input_add(read_err2, GDK_INPUT_READ,
9810 (GdkInputFunction) read_write_stderr, NULL);
9811 readcdda_callback3 = gdk_input_add(read_err, GDK_INPUT_READ,
9812 (GdkInputFunction) mkisofs_err, GINT_TO_POINTER(pid1));
9813
9814 /* now wait until write is finished */
9815 while (read_done == 999) {
9816 wait_and_process_events();
9817
9818 /* check if writer is waiting for reload medium */
9819 if (cdrecord_reload > 0) {
9820 show_dialog(ICO_WARN, _("Please reload the CD-R in the writer"), T_OK, NULL, NULL, -1);
9821
9822 /* now send CR to cdrecord to let it continue */
9823 if (cdrecord_reload == 1) {
9824 if (write(read_err2, "\n", 1) != 1) {
9825 g_warning("write error to cdrecord pipe\n");
9826 }
9827 }
9828
9829 /* cdrecord also accepts a SIGUSR1 to continue */
9830 /* send wakeup signal */
9831 if (cdrecord_reload == 2) {
9832 dodebug(1,"Sending SIGUSR1 to cdrecord (pid: %d) after reload.\n", (gint) pid2);
9833 kill(pid2, SIGUSR1);
9834 }
9835 cdrecord_reload = 0;
9836 }
9837
9838 /* check if somebody clicked on cancel */
9839 if (dialog_done2 != 999) {
9840 ret = show_dialog(ICO_WARN, _("Are you sure you want to abort the writing?\nAborting may damage the CD-RW and may require that you have\nto power-cycle the burner to get working again."),
9841 T_YES, T_NO, NULL, 1);
9842 if (ret == 0) {
9843 /* really abort */
9844 kill_readcdda();
9845 /* mark we aborted */
9846 read_output_ctrl = 1;
9847 dialog_done2 = 999;
9848 } else {
9849 /* not abort - undo button press */
9850 dialog_done2 = 999;
9851 }
9852 }
9853 }
9854
9855 close(read_err2);
9856 close(read_err);
9857 close(read_out);
9858
9859 /* no disk */
9860 if (read_output_ctrl == 2) {
9861 gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("No disk or wrong disk loaded."));
9862 return 1;
9863 }
9864
9865 /* cannot send cue sheet */
9866 if (read_output_ctrl == 4) {
9867 show_dialog(ICO_WARN,_("Your CD-Writer did not accept the CUE sheet needed for\nDAO writing. This could mean that cdrecord does not support DAO\nwith your writer. Select TAO mode and try again."),T_OK, NULL, NULL, 0);
9868 }
9869
9870 /* aborted write ? */
9871 if (read_output_ctrl == 1) {
9872 gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Writing aborted..."));
9873 gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Write-Error:"));
9874 return 1;
9875 }
9876
9877 /* error while reading ?*/
9878 if (read_done != 0 || read_output_ctrl == 5) {
9879 gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Error writing tracks"));
9880 gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Write-Error:"));
9881 if (read_done == 2) {
9882 /* invalid cdrecord key - show window */
9883 display_invalid_prodvdkey();
9884 }
9885 return 1;
9886 } else {
9887 /* all ok */
9888 gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Tracks successfully written"));
9889 gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Successful:"));
9890 return 0;
9891 }
9892 }
9893
9894
9895 /* check the version of cdrecord */
9896 /* return 1 if not correct (to old) */
9897
check_version_cdrecord(gchar * match,gchar * found,gint * isProDVD)9898 gint check_version_cdrecord(gchar *match, gchar *found, gint *isProDVD) {
9899 gchar line[MAXLINE];
9900 gchar vline[MAXLINE];
9901 gchar ver[MAXLINE];
9902 FILE *fpin;
9903 gchar *p;
9904
9905 *isProDVD = 0;
9906 strcpy(ver,"");
9907 get_wrap_path("CDRECORD",line);
9908 strcat(line," -version 2>/dev/null");
9909
9910 dodebug(1, "calling: %s\n", line);
9911 if ((fpin = popen(line,"r")) == NULL) {
9912 g_error("popen error\n");
9913 }
9914
9915 strcpy(line,"");
9916 strcpy(vline,"");
9917 for (;;) {
9918 if (fgets(line,MAXLINE,fpin) == NULL)
9919 break;
9920 dodebug(10,"got: %s",line);
9921
9922 /* only get first line */
9923 if (strcmp(vline,"") == 0) {
9924 strncpy(vline, line, MAXLINE);
9925 }
9926 if (strstr(line, "This version is an unofficial (modified) version with DVD support")) {
9927 dodebug(1, "WARNING: Inoffical cdrecord version found!\n", line);
9928 *isProDVD = 1;
9929 }
9930 }
9931
9932 if (pclose(fpin) == -1) {
9933 g_error("pclose error\n");
9934 }
9935
9936 if (strcmp(vline,"") == 0 || strstr(vline,"sh:") != NULL) {
9937 /* failed to open - permission denied */
9938 return 2;
9939 }
9940
9941 /* now line contains the version string of cdrecord */
9942 /* try to extract the version number */
9943
9944 p = strstr(vline,"release");
9945 if (p != NULL) {
9946 p = strtok(p+8, " ");
9947 if (p != NULL) {
9948 strcpy(ver,p);
9949 }
9950 } else {
9951 p = strstr(vline, "ProDVD");
9952 if (p != NULL) {
9953 *isProDVD = 1;
9954 p = strtok(p, " ");
9955 if (p != NULL) {
9956 p = strtok(NULL, " ");
9957 if (p != NULL) {
9958 strcpy(ver,p);
9959 }
9960 }
9961 }
9962 if (strcmp(ver,"") == 0) {
9963 p = strstr(vline,"Cdrecord");
9964 if (p != NULL) {
9965 p = strtok(p+7, " ");
9966 if (p != NULL) {
9967 p = strtok(NULL, " ");
9968 if (p) {
9969 strcpy(ver,p);
9970 }
9971 }
9972 }
9973 }
9974 }
9975
9976 /* not even a version-string found */
9977 if (strcmp(ver,"") == 0) {
9978 strcpy(found,"-unknown-");
9979 return 1;
9980 }
9981
9982 /* check if the version is new enough to support
9983 on the fly audio */
9984 if (compare_versions(ver,CDRECORD_VERSION_WITH_ONTHFLYAUDIO) >= 0) {
9985 support_ontheflyaudio = 1;
9986 }
9987
9988 /* now compare the version string */
9989 if (compare_versions(ver,match) >= 0) {
9990 strcpy(found,ver);
9991 return 0;
9992 } else {
9993 strcpy(found,ver);
9994 return 1;
9995 }
9996 }
9997
9998 /* check the version of mkisofs */
9999 /* return 1 if not correct (to old) */
10000
check_version_mkisofs(gchar * match,gchar * found)10001 gint check_version_mkisofs(gchar *match, gchar *found) {
10002 gchar line[MAXLINE];
10003 gchar ver[MAXLINE];
10004 FILE *fpin;
10005 gchar *p;
10006
10007 strcpy(ver,"");
10008 get_wrap_path("MKISOFS",line);
10009 strcat(line," -version 2>/dev/null");
10010
10011 dodebug(1, "calling: %s\n", line);
10012 if ((fpin = popen(line,"r")) == NULL) {
10013 g_error("popen error\n");
10014 }
10015
10016 strcpy(line,"");
10017 for (;;) {
10018 if (fgets(line,MAXLINE,fpin) == NULL)
10019 break;
10020 dodebug(10,"got: %s",line);
10021 }
10022
10023 if (pclose(fpin) == -1) {
10024 g_error("pclose error\n");
10025 }
10026
10027 if (strcmp(line,"") == 0 || strstr(line,"sh:") != NULL) {
10028 /* failed to open - permission denied */
10029 return 2;
10030 }
10031
10032
10033 /* now line contains the version string of mkisofs */
10034 /* try to extract the version number */
10035
10036 p = strstr(line,"mkisofs");
10037 if (p != NULL) {
10038 p = strtok(p+8, " ");
10039 if (p != NULL) {
10040 strcpy(ver,p);
10041 }
10042 }
10043
10044 /* not even a version-string found */
10045 if (strcmp(ver,"") == 0) {
10046 strcpy(found,"-unknown-");
10047 return 1;
10048 }
10049
10050 /* now compare the version string */
10051 if (compare_versions(ver,match) >= 0) {
10052 strcpy(found,ver);
10053 return 0;
10054 } else {
10055 strcpy(found,ver);
10056 return 1;
10057 }
10058 }
10059
10060 /* check the version of cdda2wav */
10061 /* return 1 if not correct (to old) */
10062
check_version_cdda2wav(gchar * match,gchar * found)10063 gint check_version_cdda2wav(gchar *match, gchar *found) {
10064 gchar line[MAXLINE];
10065 gchar vline[MAXLINE];
10066 gchar ver[MAXLINE];
10067 FILE *fpin;
10068 gchar *p;
10069
10070 strcpy(ver,"");
10071 get_wrap_path("CDDA2WAV",line);
10072 strcat(line," -version 2>&1");
10073
10074 dodebug(1, "calling: %s\n", line);
10075 if ((fpin = popen(line,"r")) == NULL) {
10076 g_error("popen error\n");
10077 }
10078
10079 strcpy(line,"");
10080 strcpy(vline,"");
10081 for (;;) {
10082 if (fgets(line,MAXLINE,fpin) == NULL)
10083 break;
10084 dodebug(10,"got: %s",line);
10085
10086 /* only get first line */
10087 if (strcmp(vline,"") == 0) {
10088 strncpy(vline, line, MAXLINE);
10089 }
10090 }
10091
10092 if (pclose(fpin) == -1) {
10093 g_error("pclose error\n");
10094 }
10095
10096 if (strcmp(vline,"") == 0 || strstr(vline,"sh:") != NULL) {
10097 /* failed to open - permission denied */
10098 return 2;
10099 }
10100
10101 /* now vline contains the version string of cdda2wav */
10102 /* try to extract the version number */
10103
10104 p = strstr(vline,"version");
10105 if (p != NULL) {
10106 p = strtok(p+8, " _");
10107 if (p != NULL) {
10108 strcpy(ver,p);
10109 }
10110 } else {
10111 p = strstr(vline,"cdda2wav");
10112 if (p != NULL) {
10113 p = strtok(p+9, " ");
10114 if (p != NULL) {
10115 strcpy(ver,p);
10116 }
10117 }
10118 }
10119
10120 /* not even a version-string found */
10121 if (strcmp(ver,"") == 0) {
10122 strcpy(found,"-unknown-");
10123 return 1;
10124 }
10125
10126 /* now compare the version string */
10127 if (compare_versions(ver,match) >= 0) {
10128 strcpy(found,ver);
10129 return 0;
10130 } else {
10131 strcpy(found,ver);
10132 return 1;
10133 }
10134 }
10135
10136
10137 /* check the version of readcd */
10138 /* return 1 if not correct (to old) */
10139
check_version_readcd(gchar * match,gchar * found)10140 gint check_version_readcd(gchar *match, gchar *found) {
10141 gchar line[MAXLINE];
10142 gchar ver[MAXLINE];
10143 FILE *fpin;
10144 gchar *p;
10145
10146 strcpy(ver,"");
10147 get_wrap_path("READCD",line);
10148 strcat(line," -version 2>/dev/null");
10149
10150 dodebug(1, "calling: %s\n", line);
10151 if ((fpin = popen(line,"r")) == NULL) {
10152 g_error("popen error\n");
10153 }
10154
10155 strcpy(line,"");
10156 for (;;) {
10157 if (fgets(line,MAXLINE,fpin) == NULL)
10158 break;
10159 dodebug(10,"got: %s",line);
10160 }
10161
10162 if (pclose(fpin) == -1) {
10163 g_error("pclose error\n");
10164 }
10165
10166 if (strcmp(line,"") == 0 || strstr(line,"sh:") != NULL) {
10167 /* failed to open - permission denied */
10168 return 2;
10169 }
10170
10171
10172 /* now line contains the version string of readcd */
10173 /* try to extract the version number */
10174
10175 p = strstr(line,"readcd");
10176 if (p != NULL) {
10177 p = strtok(p+7, " ");
10178 if (p != NULL) {
10179 strcpy(ver,p);
10180 }
10181 }
10182
10183 /* not even a version-string found */
10184 if (strcmp(ver,"") == 0) {
10185 strcpy(found,"-unknown-");
10186 return 1;
10187 }
10188
10189 /* now compare the version string */
10190 if (compare_versions(ver,match) >= 0) {
10191 strcpy(found,ver);
10192 return 0;
10193 } else {
10194 strcpy(found,ver);
10195 return 1;
10196 }
10197 }
10198
10199
10200 /* check the version of the wrapper */
10201 /* return 1 if not correct */
10202 /* return 2 if user denied */
10203 /* return 3 if rootconfig unreadable */
10204
check_version_wrapper(gchar * tmp)10205 gint check_version_wrapper(gchar *tmp) {
10206 gchar line[MAXLINE];
10207 gchar xcdrver[MAXLINE];
10208 gchar sharever[MAXLINE];
10209 gchar prefixver[MAXLINE];
10210 FILE *fpin;
10211 gint ret;
10212 gint unreadable;
10213
10214 strcpy(xcdrver,"-unknown-");
10215 strcpy(sharever,"-unknown-");
10216 strcpy(prefixver,"-unknown-");
10217 strncpy(line,tmp, MAXLINE);
10218 strcat(line," -V");
10219 ret = 0;
10220 unreadable = 0;
10221
10222 dodebug(1, "calling: %s\n", line);
10223 if ((fpin = popen(line,"r")) == NULL) {
10224 g_error("popen error\n");
10225 }
10226
10227 strcpy(line,"");
10228 for (;;) {
10229 if (fgets(line,MAXLINE,fpin) == NULL)
10230 break;
10231 dodebug(10,"got: %s",line);
10232
10233 if (strncmp(line,"X-CD-Roast ", 11) == 0) {
10234 strcpy(xcdrver,line+11);
10235 }
10236 if (strncmp(line,"sharedir: ", 10) == 0) {
10237 strcpy(sharever,line+10);
10238 }
10239 if (strncmp(line,"prefixdir: ", 11) == 0) {
10240 strcpy(prefixver,line+11);
10241 }
10242 if (strncmp(line,"Warning: rootconfig unreadable", 30) == 0) {
10243 unreadable = 1;
10244 }
10245 }
10246
10247 if (pclose(fpin) == -1) {
10248 g_error("pclose error\n");
10249 }
10250
10251 strip_string(xcdrver);
10252 strip_string(sharever);
10253 strip_string(prefixver);
10254
10255 if (strcmp(xcdrver,"ACCESS DENIED") == 0) {
10256 return 2;
10257 }
10258 if (unreadable) {
10259 return 3;
10260 }
10261 if (strcmp(xcdrver,XCDROAST_VERSION) != 0) {
10262 fprintf(stderr, "CRITICAL: Wrapper %s from\n\tVersion %s instead of %s\n",
10263 tmp, xcdrver, XCDROAST_VERSION);
10264 ret = 1;
10265 }
10266 if (strcmp(sharever,sharedir) != 0) {
10267 fprintf(stderr, "WARNING: Wrapper %s configured\n\tsharedir %s instead of %s\n",
10268 tmp, sharever, sharedir);
10269 ret = 0;
10270 }
10271 if (strcmp(prefixver,prefixdir) != 0) {
10272 fprintf(stderr, "CRITICAL: Wrapper %s configured\n\tprefixdir %s instead of %s\n",
10273 tmp, prefixver, prefixdir);
10274 ret = 1;
10275 }
10276
10277 return ret;
10278 }
10279
10280
10281 /* check if this user is allowed to write in the given directory */
10282 /* uses the wrapper to have real conditions */
10283 /* return 0 if writeable, 1 if not */
10284
is_dir_writeable(gchar * dir)10285 gint is_dir_writeable(gchar *dir) {
10286 gchar line[MAXLINE];
10287 gchar tmp[MAXLINE];
10288 FILE *fpin;
10289 gint stat;
10290
10291 get_wrap_path("WRITETEST", tmp);
10292 g_snprintf(line,MAXLINE,"%s \"%s\"", tmp, dir);
10293
10294 dodebug(1, "calling: %s\n", line);
10295 if ((fpin = popen(line,"r")) == NULL) {
10296 g_error("popen error\n");
10297 }
10298
10299 for (;;) {
10300 if (fgets(line,MAXLINE,fpin) == NULL)
10301 break;
10302 }
10303
10304 stat = pclose(fpin);
10305 if (stat == -1) {
10306 g_error("pclose error\n");
10307 }
10308
10309 return (WEXITSTATUS(stat));
10310 }
10311
10312
10313 /* return the commands to use to activate non-root-mode */
10314 /* return 0 if all checks ok */
10315
get_commands_to_change_nrm(gchar * ret,gint mode)10316 gint get_commands_to_change_nrm(gchar *ret, gint mode) {
10317 gchar tmp[MAXLINE];
10318 gchar bin[MAXLINE];
10319 gint groupaddok;
10320 gchar cmd_chown[MAXLINE], cmd_chmod[MAXLINE];
10321 #if 0
10322 gchar cmd_chgrp[MAXLINE];
10323 nonroot_flags_t *entry;
10324 GList *nrs_vals, *loop;
10325 gchar tmp2[MAXLINE];
10326 #endif
10327
10328 strcpy(ret,"");
10329 groupaddok = 0;
10330
10331 /* check if basic commands are available */
10332 get_chown_cmd(cmd_chown);
10333 if (cmd_chown[0] == '\0') {
10334 strcat(ret,"\nError: No chown command found");
10335 return 1;
10336 }
10337
10338 #if 0
10339 get_chgrp_cmd(cmd_chgrp);
10340 if (cmd_chgrp[0] == '\0') {
10341 strcat(ret,"\nError: No chgrp command found");
10342 return 1;
10343 }
10344 #endif
10345
10346 get_chmod_cmd(cmd_chmod);
10347 if (cmd_chmod[0] == '\0') {
10348 strcat(ret,"\nError: No chmod command found");
10349 return 1;
10350 }
10351
10352 /* activate non-root-mode */
10353 if (mode == 0) {
10354 #if 0
10355 /* check if we need to create a group for the wrapper */
10356 if (!check_group_exists(NONROOTMODEGROUP)) {
10357 /* we have to create a group here */
10358 if (stat(GROUPADD,&buf) == 0) {
10359 if (buf.st_mode & S_IEXEC) {
10360 /* groupadd exists and is an exectable */
10361 groupaddok = 1;
10362 }
10363 }
10364 if (!groupaddok) {
10365 g_snprintf(tmp,MAXLINE,_("Warning: No \"groupadd\" command found on your system.\n - Edit \"/etc/group\" and add a group \"%s\" manually.\n Please try again then."), NONROOTMODEGROUP);
10366 strcat(ret,tmp);
10367 /* abort, without group its no way for us */
10368 return 1;
10369 } else {
10370 /* create command to create new group */
10371 #if defined(__FreeBSD__)
10372 g_snprintf(tmp,MAXLINE,"%s groupadd -n %s\n", GROUPADD, NONROOTMODEGROUP);
10373 #else
10374 g_snprintf(tmp,MAXLINE,"%s %s\n", GROUPADD, NONROOTMODEGROUP);
10375 #endif
10376 strcat(ret,tmp);
10377 }
10378 }
10379 #endif
10380
10381 /* set the correct permissions to the wrapper */
10382 g_snprintf(bin,MAXLINE,"%s/%s", sharedir, WRAPPER);
10383 g_snprintf(tmp,MAXLINE,"%s root %s\n", cmd_chown, bin);
10384 strcat(ret,tmp);
10385 #if 0
10386 g_snprintf(tmp,MAXLINE,"%s %s %s\n", cmd_chgrp, NONROOTMODEGROUP, bin);
10387 strcat(ret,tmp);
10388 #endif
10389 /* old nonroot mode - 2755 */
10390 g_snprintf(tmp,MAXLINE,"%s 4755 %s\n", cmd_chmod, bin);
10391 strcat(ret,tmp);
10392
10393
10394 #if 0
10395 /* set correct permissions for cdrtools */
10396 get_spawn_path(CDRECORD,bin);
10397 g_snprintf(tmp,MAXLINE,"%s root %s\n", cmd_chown, bin);
10398 strcat(ret,tmp);
10399 g_snprintf(tmp,MAXLINE,"%s %s %s\n", cmd_chgrp, NONROOTMODEGROUP, bin);
10400 strcat(ret,tmp);
10401 g_snprintf(tmp,MAXLINE,"%s 4710 %s\n", cmd_chmod, bin);
10402 strcat(ret,tmp);
10403
10404 get_spawn_path(CDRECORDPRODVD,bin);
10405 if (is_file(bin)) {
10406 g_snprintf(tmp,MAXLINE,"%s root %s\n", cmd_chown, bin);
10407 strcat(ret,tmp);
10408 g_snprintf(tmp,MAXLINE,"%s %s %s\n", cmd_chgrp, NONROOTMODEGROUP, bin);
10409 strcat(ret,tmp);
10410 g_snprintf(tmp,MAXLINE,"%s 4710 %s\n", cmd_chmod, bin);
10411 strcat(ret,tmp);
10412 }
10413
10414 get_spawn_path(MKISOFS,bin);
10415 g_snprintf(tmp,MAXLINE,"%s root %s\n", cmd_chown, bin);
10416 strcat(ret,tmp);
10417 g_snprintf(tmp,MAXLINE,"%s %s %s\n", cmd_chgrp, NONROOTMODEGROUP, bin);
10418 strcat(ret,tmp);
10419 g_snprintf(tmp,MAXLINE,"%s 4710 %s\n", cmd_chmod, bin);
10420 strcat(ret,tmp);
10421
10422 get_spawn_path(READCD,bin);
10423 g_snprintf(tmp,MAXLINE,"%s root %s\n", cmd_chown, bin);
10424 strcat(ret,tmp);
10425 g_snprintf(tmp,MAXLINE,"%s %s %s\n", cmd_chgrp, NONROOTMODEGROUP, bin);
10426 strcat(ret,tmp);
10427 g_snprintf(tmp,MAXLINE,"%s 4710 %s\n", cmd_chmod, bin);
10428 strcat(ret,tmp);
10429
10430 get_spawn_path(CDDA2WAV,bin);
10431 g_snprintf(tmp,MAXLINE,"%s root %s\n", cmd_chown, bin);
10432 strcat(ret,tmp);
10433 g_snprintf(tmp,MAXLINE,"%s %s %s\n", cmd_chgrp, NONROOTMODEGROUP, bin);
10434 strcat(ret,tmp);
10435 g_snprintf(tmp,MAXLINE,"%s 4710 %s\n", cmd_chmod, bin);
10436 strcat(ret,tmp);
10437 #endif
10438
10439 } else {
10440 /* deactivate non-root-mode */
10441
10442 #if 0
10443 nrs_vals = NULL;
10444 /* try to load original flags from file */
10445 load_nonrootvalues(configdir, NONROOTBAK, &nrs_vals);
10446
10447 /* loop through all values */
10448 loop = g_list_first(nrs_vals);
10449 while(loop) {
10450 entry = (nonroot_flags_t *)loop->data;
10451
10452 return_user_name(entry->uid, tmp2);
10453 g_snprintf(tmp,MAXLINE,"%s %s %s\n", cmd_chown,
10454 tmp2, entry->path);
10455 strcat(ret,tmp);
10456 return_group_name(entry->gid, tmp2);
10457 g_snprintf(tmp,MAXLINE,"%s %s %s\n", cmd_chgrp,
10458 tmp2, entry->path);
10459 strcat(ret,tmp);
10460 g_snprintf(tmp,MAXLINE,"%s %o %s\n", cmd_chmod,
10461 (gint) entry->mode, entry->path);
10462 strcat(ret,tmp);
10463
10464 loop = loop->next;
10465 }
10466 free_nonrootvalues(&nrs_vals);
10467 #endif
10468 g_snprintf(bin,MAXLINE,"%s/%s", sharedir, WRAPPER);
10469 g_snprintf(tmp,MAXLINE,"%s 755 %s\n", cmd_chmod, bin);
10470 strcat(ret,tmp);
10471 }
10472 return 0;
10473 }
10474
10475
10476 /* save the current file owners and permissions to a file */
10477 #if 0
10478 gint save_current_nonrootvalues(gchar *confdir, gchar *fname) {
10479 gchar bin[MAXLINE];
10480 gchar tmp[MAXLINE];
10481 gchar share[MAXLINE];
10482 struct stat buf;
10483 uid_t uid;
10484 gid_t gid;
10485 mode_t mode;
10486 FILE *fd;
10487
10488 /* make sharedir absolute if is not yet */
10489 if (sharedir[0] != '/') {
10490 getcwd(tmp,MAXLINE);
10491 g_snprintf(share,MAXLINE,"%s/%s", tmp, sharedir);
10492 } else {
10493 strcpy(share,sharedir);
10494 }
10495
10496 /* first create directory to store nonrootconfig */
10497 if (!is_directory(confdir)) {
10498 /* try to create directory */
10499 mkdir(confdir, 0700);
10500 dodebug(2, "trying to mkdir %s\n", confdir);
10501 }
10502 g_snprintf(tmp,MAXLINE,"%s/%s", confdir, fname);
10503
10504 dodebug(1, "Opening %s for writing\n", tmp);
10505
10506 fd = fopen(tmp,"w");
10507 if (fd == NULL) {
10508 /* error opening file */
10509 return 1;
10510 }
10511
10512 /* write the config-file header */
10513 fputs("#\n",fd);
10514 g_snprintf(tmp,MAXLINE,"# X-CD-Roast %s Non-Root-Mode Configuration\n",XCDROAST_VERSION);
10515 fputs(tmp,fd);
10516 fputs("#\n",fd);
10517 fputs("# Contains the files with their flags before they got changed\n",fd);
10518 fputs("# by X-CD-Roast Non-Root-Mode activation.\n", fd);
10519 fputs("# Used to restore the original values when disabling Non-Root-Mode.\n",fd);
10520 fputs("#\n",fd);
10521
10522 /* get details about the wrapper */
10523 g_snprintf(bin,MAXLINE,"%s/%s", share, WRAPPER);
10524 if (stat(bin,&buf) == 0) {
10525 uid = buf.st_uid;
10526 gid = buf.st_gid;
10527 mode = buf.st_mode & 07777;
10528
10529 g_snprintf(tmp,MAXLINE,"%s: %d %d 0%o\n", bin,
10530 (gint) uid, (gint) gid, (gint) mode);
10531 fputs(tmp,fd);
10532 }
10533
10534 /* now the cdrtools - make path absolute */
10535 get_spawn_path(CDRECORD,bin);
10536 if (bin[0] != '/') {
10537 getcwd(tmp,MAXLINE);
10538 g_snprintf(bin2,MAXLINE,"%s/%s", tmp, bin);
10539 } else {
10540 strcpy(bin2,bin);
10541 }
10542 if (stat(bin2,&buf) == 0) {
10543 uid = buf.st_uid;
10544 gid = buf.st_gid;
10545 mode = buf.st_mode & 07777;
10546
10547 g_snprintf(tmp,MAXLINE,"%s: %d %d 0%o\n", bin2,
10548 (gint) uid, (gint) gid, (gint) mode);
10549 fputs(tmp,fd);
10550 }
10551
10552 get_spawn_path(MKISOFS,bin);
10553 if (bin[0] != '/') {
10554 getcwd(tmp,MAXLINE);
10555 g_snprintf(bin2,MAXLINE,"%s/%s", tmp, bin);
10556 } else {
10557 strcpy(bin2,bin);
10558 }
10559 if (stat(bin2,&buf) == 0) {
10560 uid = buf.st_uid;
10561 gid = buf.st_gid;
10562 mode = buf.st_mode & 07777;
10563
10564 g_snprintf(tmp,MAXLINE,"%s: %d %d 0%o\n", bin2,
10565 (gint) uid, (gint) gid, (gint) mode);
10566 fputs(tmp,fd);
10567 }
10568
10569 get_spawn_path(READCD,bin);
10570 if (bin[0] != '/') {
10571 getcwd(tmp,MAXLINE);
10572 g_snprintf(bin2,MAXLINE,"%s/%s", tmp, bin);
10573 } else {
10574 strcpy(bin2,bin);
10575 }
10576 if (stat(bin2,&buf) == 0) {
10577 uid = buf.st_uid;
10578 gid = buf.st_gid;
10579 mode = buf.st_mode & 07777;
10580
10581 g_snprintf(tmp,MAXLINE,"%s: %d %d 0%o\n", bin2,
10582 (gint) uid, (gint) gid, (gint) mode);
10583 fputs(tmp,fd);
10584 }
10585
10586 get_spawn_path(CDDA2WAV,bin);
10587 if (bin[0] != '/') {
10588 getcwd(tmp,MAXLINE);
10589 g_snprintf(bin2,MAXLINE,"%s/%s", tmp, bin);
10590 } else {
10591 strcpy(bin2,bin);
10592 }
10593 if (stat(bin2,&buf) == 0) {
10594 uid = buf.st_uid;
10595 gid = buf.st_gid;
10596 mode = buf.st_mode & 07777;
10597
10598 g_snprintf(tmp,MAXLINE,"%s: %d %d 0%o\n", bin2,
10599 (gint) uid, (gint) gid, (gint) mode);
10600 fputs(tmp,fd);
10601 }
10602 if (fclose(fd) != 0) {
10603 /* error closing file */
10604 return 1;
10605 }
10606
10607 return 0;
10608
10609 }
10610 #endif
10611
10612
10613 /* run a simple non-output-command and return exit status */
10614
simple_exec(gchar * cmd)10615 gint simple_exec(gchar *cmd) {
10616 gchar line[MAXLINE];
10617 FILE *fpin;
10618 gint stat;
10619
10620 dodebug(1, "calling: %s\n", cmd);
10621 if ((fpin = popen(cmd,"r")) == NULL) {
10622 g_error("popen error\n");
10623 }
10624
10625 for (;;) {
10626 if (fgets(line,MAXLINE,fpin) == NULL)
10627 break;
10628 }
10629
10630 stat = pclose(fpin);
10631 if (stat == -1) {
10632 return -1;
10633 }
10634
10635 return (WEXITSTATUS(stat));
10636 }
10637
10638
10639 /* load nonroot-values from file */
10640 /* if some values not found, generate default */
10641
10642 #if 0
10643
10644 gint load_nonrootvalues(gchar *confdir, gchar *fname, GList **ret) {
10645 gchar tmp[MAXLINE];
10646 gchar line[MAXLINE];
10647 gchar path[MAXLINE];
10648 FILE *fd;
10649 gchar *p;
10650 gint uid, gid, mode;
10651 gint foundwrapper, foundcdrecord, foundmkisofs, foundcdda2wav, foundreadcd;
10652
10653 foundwrapper = 0;
10654 foundcdrecord = 0;
10655 foundmkisofs = 0;
10656 foundcdda2wav = 0;
10657 foundreadcd = 0;
10658
10659 g_snprintf(tmp,MAXLINE,"%s/%s", confdir, fname);
10660
10661 /* open file */
10662 if ((fd = fopen(tmp,"r")) != NULL) {
10663
10664 dodebug(1, "Opened %s for reading\n", tmp);
10665
10666
10667 for (;;) {
10668 if (fgets(line,MAXLINE,fd) == NULL)
10669 break;
10670
10671 dodebug(10,"non-root-values: %s", line),
10672
10673 /* skip empty or hashed lines */
10674 strip_string(line);
10675 if (*line == '#' || *line == '\0')
10676 continue;
10677
10678 uid = -1;
10679 gid = -1;
10680 mode = -1;
10681
10682 /* extract path */
10683 strncpy(path,line,MAXLINE);
10684 p = rindex(path,':');
10685 if (p) {
10686 *p = '\0';
10687
10688 strncpy(tmp, p+1, MAXLINE);
10689 strip_string(tmp);
10690
10691 /* extract uid, gid and mode */
10692 p = strtok(tmp," ");
10693 if (p) {
10694 uid = atoi(p);
10695 p = strtok(NULL," ");
10696 if (p) {
10697 gid = atoi(p);
10698 p = strtok(NULL,"");
10699 if (p) {
10700 mode = strtol(p, (char **)NULL, 8);
10701 }
10702 }
10703 }
10704 } else {
10705 *path = '\0';
10706 }
10707
10708 /* all data extracted successfully? */
10709 if (*path != '\0' && uid != -1 && gid != -1 && mode != -1) {
10710
10711 add_to_nonrootvalues(ret, path, uid, gid, mode);
10712
10713 /* check what entry we just added */
10714 if (strstr(path, WRAPPER)) {
10715 foundwrapper = 1;
10716 }
10717 if (strstr(path, CDRECORD)) {
10718 foundcdrecord = 1;
10719 }
10720 if (strstr(path, MKISOFS)) {
10721 foundmkisofs = 1;
10722 }
10723 if (strstr(path, READCD)) {
10724 foundreadcd = 1;
10725 }
10726 if (strstr(path, CDDA2WAV)) {
10727 foundcdda2wav = 1;
10728 }
10729 }
10730
10731 }
10732
10733 fclose(fd);
10734 }
10735
10736 /* now we read the file (or not, if it was not found) and add
10737 default values for any things we are missing */
10738 if (!foundwrapper) {
10739 g_snprintf(path,MAXLINE,"%s/%s", sharedir, WRAPPER);
10740 add_to_nonrootvalues(ret, path, 0, 0, 0755);
10741 }
10742 if (!foundcdrecord) {
10743 get_spawn_path(CDRECORD,path);
10744 add_to_nonrootvalues(ret, path, 0, 0, 0755);
10745 }
10746 if (!foundmkisofs) {
10747 get_spawn_path(MKISOFS,path);
10748 add_to_nonrootvalues(ret, path, 0, 0, 0755);
10749 }
10750 if (!foundreadcd) {
10751 get_spawn_path(READCD,path);
10752 add_to_nonrootvalues(ret, path, 0, 0, 0755);
10753 }
10754 if (!foundcdda2wav) {
10755 get_spawn_path(CDDA2WAV,path);
10756 add_to_nonrootvalues(ret, path, 0, 0, 0755);
10757 }
10758
10759 return 0;
10760 }
10761 #endif
10762
10763 /* reads the .xinf file for a given track and writes a new .inf file
10764 with the updated cd-text information */
10765
edit_xinf_for_cd_text(gchar * trackfile,gchar * tocfile)10766 void edit_xinf_for_cd_text(gchar *trackfile, gchar *tocfile) {
10767 gchar xinfname[MAXLINE], infname[MAXLINE];
10768 gchar tmp[MAXLINE];
10769 gchar *p;
10770 FILE *fd;
10771 gchar line[MAXLINE];
10772 gchar id[MAXLINE];
10773 gchar value[MAXLINE];
10774 gchar title[MAXLINE], artist[MAXLINE], cddbtitle[MAXLINE];
10775 gchar cdtitle[MAXLINE], cdartist[MAXLINE];
10776
10777 /*
10778 g_print("tocfile: %s, file: %s\n", tocfile, trackfile);
10779 */
10780
10781 /* generate xinf and inf filenames */
10782 strncpy(tmp,trackfile,MAXLINE - 4);
10783 p = rindex(tmp,'.');
10784 if (!p) return;
10785 *p = '\0';
10786 strcpy(xinfname,tmp);
10787 strcpy(infname,tmp);
10788 strcat(xinfname,XCDROAST_INFO_EXT);
10789 strcat(infname,".inf");
10790
10791 dodebug(10, "reading cdtext from %s\n", xinfname);
10792
10793 if ((fd = fopen(xinfname,"r")) == NULL) {
10794 return;
10795 }
10796
10797 strcpy(title,"");
10798 strcpy(artist,"");
10799 strcpy(cddbtitle,"");
10800
10801 for (;;) {
10802 if (fgets(line,MAXLINE,fd) == NULL)
10803 break;
10804
10805 /* skip empty or hashed lines */
10806 strip_string(line);
10807 if (*line == '#' || *line == '\0')
10808 continue;
10809
10810 /* parse lines */
10811 if (parse_config_line(line,id,value)) {
10812 dodebug(10,"invalid line in infofile");
10813 fclose(fd);
10814 return;
10815 }
10816
10817 if (strcmp("title",id) == 0) {
10818 strncpy(title, value, MAXLINE);
10819 }
10820 if (strcmp("artist",id) == 0) {
10821 strncpy(artist, value, MAXLINE);
10822 }
10823 if (strcmp("cddb_ttitle",id) == 0) {
10824 strncpy(cddbtitle, value, MAXLINE);
10825 }
10826 }
10827
10828 if (fclose(fd) != 0) {
10829 return;
10830 }
10831
10832
10833 /* decide if we use cddb info rather than cd-text info? */
10834 if (strcmp(title,"") == 0) {
10835 if (strcmp(cddbtitle,"") != 0) {
10836 /* no title, but cddb given */
10837 strncpy(title, cddbtitle, MAXLINE);
10838 }
10839 }
10840
10841 strcpy(cdtitle,"");
10842 strcpy(cdartist,"");
10843
10844 /* now read toc file for cd-title/artist */
10845 if (strcmp(tocfile,"-") != 0) {
10846 dodebug(10, "reading cdtext from %s\n", tocfile);
10847
10848 fd = fopen(tocfile,"r");
10849
10850 if (fd) {
10851 for (;;) {
10852 if (fgets(line,MAXLINE,fd) == NULL)
10853 break;
10854
10855 /* skip empty or hashed lines */
10856 strip_string(line);
10857 if (*line == '#' || *line == '\0')
10858 continue;
10859
10860 /* parse lines */
10861 if (parse_config_line(line,id,value)) {
10862 dodebug(10,"invalid line in toc");
10863 fclose(fd);
10864 return;
10865 }
10866 if (strcmp("cdtitle",id) == 0) {
10867 strncpy(tmp, value, MAXLINE);
10868 get_artist_and_title_from_cddb(
10869 tmp, cdartist, cdtitle);
10870 }
10871 }
10872 fclose(fd);
10873 }
10874 }
10875
10876 /* now we have read all the info from the xinf and toc file */
10877
10878 /* edit the original .inf file */
10879 edit_xinf_for_cd_text2(infname, title, artist, cdtitle, cdartist);
10880 }
10881
10882
10883 /* patch the given cd-text information the the inffile */
10884
edit_xinf_for_cd_text2(gchar * infname,gchar * title,gchar * artist,gchar * cdtitle,gchar * cdartist)10885 static void edit_xinf_for_cd_text2(gchar *infname, gchar *title, gchar *artist, gchar *cdtitle, gchar *cdartist) {
10886 gchar tmpinfname[MAXLINE];
10887 gchar tmp[MAXLINE];
10888 gchar line[MAXLINE];
10889 FILE *fd, *fd2;
10890 gchar timestr[MAXLINE];
10891 gint found, found2, found3, found4;
10892 time_t acttime;
10893
10894 dodebug(10, "cd-text info: %s, %s, %s, %s\n", title, artist, cdtitle, cdartist);
10895
10896 /* get current time */
10897 acttime = time((time_t *) 0);
10898 strcpy(timestr,ctime(&acttime));
10899 timestr[strlen(timestr)-1] = '\0';
10900
10901 g_snprintf(tmpinfname,MAXLINE,"%s-%d", infname, (gint) getpid());
10902
10903 /* now modify the original inf file */
10904 fd = fopen(infname,"r");
10905 if (!fd) {
10906 /* no inf file? - generate one */
10907 fd2 = fopen(infname,"w");
10908 if (!fd2) return;
10909
10910 /* write releveant data to new inf file */
10911 g_snprintf(tmp,MAXLINE,"#created by X-CD-Roast %s at %s\n", XCDROAST_VERSION, timestr);
10912 fputs(tmp, fd2);
10913 fputs("#\n",fd2);
10914
10915 g_snprintf(tmp,MAXLINE,"Performer=\t'%s'\n", artist);
10916 fputs(tmp, fd2);
10917
10918 g_snprintf(tmp,MAXLINE,"Albumtitle=\t'%s'\n", cdtitle);
10919 fputs(tmp, fd2);
10920
10921 g_snprintf(tmp,MAXLINE,"Tracktitle=\t'%s'\n", title);
10922 fputs(tmp, fd2);
10923
10924 g_snprintf(tmp,MAXLINE,"Albumperformer=\t'%s'\n", cdartist);
10925 fputs(tmp, fd2);
10926
10927 fclose(fd2);
10928
10929 dodebug(10, "created cd-text-info as %s\n", infname);
10930 } else {
10931 /* inf file openend - open now tmpfile */
10932 fd2 = fopen(tmpinfname,"w");
10933 if (!fd2) {
10934 fclose(fd);
10935 return;
10936 }
10937
10938 found = 0;
10939 found2 = 0;
10940 found3 = 0;
10941 found4 = 0;
10942
10943 for (;;) {
10944 if (fgets(line,MAXLINE,fd) == NULL)
10945 break;
10946
10947 /* write modifcation date of xcdroast in new file */
10948 if (strncmp(line,"#created", 8) == 0) {
10949 fputs(line, fd2);
10950 g_snprintf(tmp,MAXLINE,"#modified by X-CD-Roast %s at %s\n", XCDROAST_VERSION, timestr);
10951 fputs(tmp, fd2);
10952 continue;
10953 }
10954
10955 /* skip old modfied lines */
10956 if (strncmp(line,"#modified by X-CD-Roast", 23) == 0) {
10957 continue;
10958 }
10959
10960 /* replace performer */
10961 if (strncmp(line,"Performer=", 10) == 0) {
10962 g_snprintf(tmp,MAXLINE,"Performer=\t'%s'\n", artist);
10963 fputs(tmp, fd2);
10964 found = 1;
10965 continue;
10966 }
10967
10968 /* replace title */
10969 if (strncmp(line,"Tracktitle=", 11) == 0) {
10970 g_snprintf(tmp,MAXLINE,"Tracktitle=\t'%s'\n", title);
10971 fputs(tmp, fd2);
10972 found2 = 1;
10973 continue;
10974 }
10975
10976 /* replace albumtitle */
10977 if (strncmp(line,"Albumtitle=", 11) == 0) {
10978 g_snprintf(tmp,MAXLINE,"Albumtitle=\t'%s'\n", cdtitle);
10979 fputs(tmp, fd2);
10980 found3 = 1;
10981 continue;
10982 }
10983
10984 /* replace albumperformer */
10985 if (strncmp(line,"Albumperformer=", 11) == 0) {
10986 g_snprintf(tmp,MAXLINE,"Albumperformer=\t'%s'\n", cdartist);
10987 fputs(tmp, fd2);
10988 found4 = 1;
10989 continue;
10990 }
10991
10992 fputs(line,fd2);
10993 }
10994
10995 /* could not replace all the original lines? add any
10996 missing now */
10997 if (found == 0) {
10998 g_snprintf(tmp,MAXLINE,"Performer=\t'%s'\n", artist);
10999 fputs(tmp, fd2);
11000 }
11001 if (found3 == 0) {
11002 g_snprintf(tmp,MAXLINE,"Albumtitle=\t'%s'\n", cdtitle);
11003 fputs(tmp, fd2);
11004 }
11005 if (found2 == 0) {
11006 g_snprintf(tmp,MAXLINE,"Tracktitle=\t'%s'\n", title);
11007 fputs(tmp, fd2);
11008 }
11009 if (found4 == 0) {
11010 g_snprintf(tmp,MAXLINE,"Albumperformer=\t'%s'\n", cdartist);
11011 fputs(tmp, fd2);
11012 }
11013
11014 fclose(fd2);
11015 fclose(fd);
11016
11017 /* now move the temporary file over the original inf file */
11018 move_textfile(tmpinfname, infname);
11019
11020 dodebug(10, "modified cd-text-info in %s\n", infname);
11021 }
11022
11023 }
11024
11025
11026 /* does overwrite the artist and title information in the given toc file */
11027
edit_title_artist_in_toc_file(gchar * tocfile,gchar * title,gchar * artist)11028 void edit_title_artist_in_toc_file(gchar *tocfile, gchar *title, gchar *artist) {
11029 FILE *fd, *fd2;
11030 gchar line[MAXLINE];
11031 gchar tmp[MAXLINE];
11032 gchar tmptitle[MAXLINE];
11033 gchar tmpartist[MAXLINE];
11034 gchar tmptocfile[MAXLINE];
11035 gint found;
11036 struct stat buf;
11037
11038 /* check first if file exists before overwriting it */
11039 if (lstat(tocfile, &buf) == 0) {
11040
11041 /* file real and owner is also yourself? */
11042 if (buf.st_uid != getuid() || S_ISLNK(buf.st_mode)) {
11043 dodebug(1, "cannot edit tocfile %s, because file already exists and it belongs not to us, or is a link\n", tocfile);
11044 return;
11045 }
11046 }
11047
11048 found = 0;
11049 g_snprintf(tmptocfile,MAXLINE,"%s-%d", tocfile, (gint) getpid());
11050
11051 dodebug(10, "updating toc file %s with new title/artist\n", tocfile);
11052
11053 /* open toc file for reading */
11054 if ((fd = fopen(tocfile,"r")) == NULL) {
11055 /* no file? */
11056 return;
11057 }
11058
11059 /* open temporary tocfile to copy */
11060 if ((fd2 = fopen(tmptocfile,"w")) == NULL) {
11061 /* no file? */
11062 fclose(fd);
11063 return;
11064 }
11065
11066 /* copy all lines and change the one with the cdtitle */
11067 for (;;) {
11068 if (fgets(line,MAXLINE,fd) == NULL)
11069 break;
11070
11071 /* replace the line with the cdtitle */
11072 if (strncmp(line,"cdtitle", 7) == 0) {
11073 strncpy(tmptitle, title, MAXLINE);
11074 strncpy(tmpartist, artist, MAXLINE);
11075 g_snprintf(tmp,MAXLINE,"cdtitle = \"%s / %s\"\n", convert_escape(tmptitle), convert_escape(tmpartist));
11076 fputs(tmp, fd2);
11077 found = 1;
11078 continue;
11079 }
11080
11081 fputs(line,fd2);
11082 }
11083
11084 /* no line with cdtitle found? */
11085 if (found == 0) {
11086 /* add it */
11087 g_snprintf(tmp,MAXLINE,"cdtitle = \"%s / %s\"\n", title, artist);
11088 fputs(tmp, fd2);
11089 }
11090 fclose(fd2);
11091 fclose(fd);
11092
11093 /* now move the temporary file over the original inf file */
11094 move_textfile(tmptocfile, tocfile);
11095
11096 }
11097
11098
11099 /* edits or creates a xinf file with updated information of title and artist */
11100
edit_title_artist_in_xinf_file(gchar * trackfile,gchar * title,gchar * artist)11101 void edit_title_artist_in_xinf_file(gchar *trackfile, gchar *title, gchar *artist) {
11102 FILE *fd, *fd2;
11103 gchar line[MAXLINE];
11104 gchar tmp[MAXLINE];
11105 gchar tmptitle[MAXLINE];
11106 gchar tmpartist[MAXLINE];
11107 gchar xinfname[MAXLINE];
11108 gchar tmpxinfname[MAXLINE];
11109 gint found, found2;
11110 gchar *p;
11111 time_t acttime;
11112 gchar timestr[MAXLINE];
11113
11114 /* get current time */
11115 acttime = time((time_t *) 0);
11116 strcpy(timestr,ctime(&acttime));
11117 timestr[strlen(timestr)-1] = '\0';
11118
11119 found = 0;
11120 found2 = 0;
11121
11122 strncpy(tmp,trackfile,MAXLINE - 4);
11123 p = rindex(tmp,'.');
11124 if (!p) return;
11125 *p = '\0';
11126 strcpy(xinfname,tmp);
11127 strcat(xinfname,XCDROAST_INFO_EXT);
11128 g_snprintf(tmpxinfname,MAXLINE,"%s-%d", xinfname, (gint) getpid());
11129
11130 /* try to open the xinf file */
11131 if ((fd = fopen(xinfname,"r")) == NULL) {
11132 /* no such file? try to create a new */
11133 fd = fopen(xinfname,"w");
11134 if (!fd) return;
11135
11136 dodebug(10, "creating xinf-file %s with new title/artist\n", xinfname);
11137
11138 /* write header */
11139 fputs("#\n",fd);
11140 g_snprintf(tmp,MAXLINE,"# X-CD-Roast %s - INF-File\n",XCDROAST_VERSION);
11141 fputs(tmp,fd);
11142 g_snprintf(tmp,MAXLINE,"# created: %s\n", timestr);
11143 fputs(tmp,fd);
11144 g_snprintf(tmp,MAXLINE,"# by: %s@%s\n", username, hostname);
11145 fputs(tmp,fd);
11146 fputs("#\n",fd);
11147
11148 g_snprintf(tmp,MAXLINE,"file = \"%s\"\n",trackfile);
11149 fputs(tmp,fd);
11150 strncpy(tmptitle, title, MAXLINE);
11151 g_snprintf(tmp,MAXLINE,"title = \"%s\"\n",convert_escape(tmptitle));
11152 fputs(tmp,fd);
11153 strncpy(tmpartist, artist, MAXLINE);
11154 g_snprintf(tmp,MAXLINE,"artist = \"%s\"\n",convert_escape(tmpartist));
11155 fputs(tmp,fd);
11156
11157 fclose(fd);
11158 return;
11159 }
11160
11161 /* open temporary xinffile to copy */
11162 if ((fd2 = fopen(tmpxinfname,"w")) == NULL) {
11163 /* no file? */
11164 fclose(fd);
11165 return;
11166 }
11167
11168 /* copy a lines and change the one with the cdtitle */
11169 for (;;) {
11170 if (fgets(line,MAXLINE,fd) == NULL)
11171 break;
11172
11173 /* replace the line with the title */
11174 if (strncmp(line,"title", 5) == 0) {
11175 strncpy(tmptitle, title, MAXLINE);
11176 g_snprintf(tmp,MAXLINE,"title = \"%s\"\n", convert_escape(tmptitle));
11177 fputs(tmp, fd2);
11178 found = 1;
11179 continue;
11180 }
11181
11182 /* replace the line with the artist */
11183 if (strncmp(line,"artist", 6) == 0) {
11184 strncpy(tmpartist, artist, MAXLINE);
11185 g_snprintf(tmp,MAXLINE,"artist = \"%s\"\n", convert_escape(tmpartist));
11186 fputs(tmp, fd2);
11187 found2 = 1;
11188 continue;
11189 }
11190
11191 fputs(line,fd2);
11192 }
11193
11194 /* lines missing? add them */
11195 if (found == 0) {
11196 strncpy(tmptitle, title, MAXLINE);
11197 g_snprintf(tmp,MAXLINE,"title = \"%s\"\n", convert_escape(tmptitle));
11198 fputs(tmp, fd2);
11199 }
11200 if (found2 == 0) {
11201 strncpy(tmpartist, artist, MAXLINE);
11202 g_snprintf(tmp,MAXLINE,"artist = \"%s\"\n", convert_escape(tmpartist));
11203 fputs(tmp, fd2);
11204 }
11205
11206 fclose(fd2);
11207 fclose(fd);
11208
11209 dodebug(10, "updated xinf-file %s with new title/artist\n", xinfname);
11210
11211 /* now move the temporary file over the original inf file */
11212 move_textfile(tmpxinfname, xinfname);
11213 }
11214
11215
11216 /* will write a temporary toc file just to save the album title and performer
11217 of the tracks to be written in the write-tracks menu */
11218
create_tmp_writetracks_tocfile(gchar * tocfile)11219 gint create_tmp_writetracks_tocfile(gchar *tocfile) {
11220 FILE *fd;
11221 time_t acttime;
11222 gchar timestr[MAXLINE];
11223 gchar tmp[MAXLINE];
11224 struct stat buf;
11225
11226 if (tocfile == NULL) return 1;
11227
11228 /* check first if file exists before overwriting it */
11229 if (lstat(tocfile, &buf) == 0) {
11230
11231 /* file real and owner is also yourself? */
11232 if (buf.st_uid != getuid() || S_ISLNK(buf.st_mode)) {
11233 dodebug(1, "cannot create temporary tocfile %s, because file already exists and it belongs not to us, or is a link\n", tocfile);
11234 return 1;
11235 }
11236 }
11237
11238 dodebug(8, "creating temporary tocfile %s\n", tocfile);
11239 fd = fopen(tocfile,"w");
11240
11241 if (fd == NULL) {
11242 g_warning("Can't open file %s for writing\n",tocfile);
11243 return 1;
11244 }
11245
11246 /* get current time */
11247 acttime = time((time_t *) 0);
11248 strcpy(timestr,ctime(&acttime));
11249 timestr[strlen(timestr)-1] = '\0';
11250
11251 /* write header */
11252 fputs("#\n",fd);
11253 g_snprintf(tmp,MAXLINE,"# X-CD-Roast %s - temporary TOC-File\n",XCDROAST_VERSION);
11254 fputs(tmp,fd);
11255 g_snprintf(tmp,MAXLINE,"# created: %s\n", timestr);
11256 fputs(tmp,fd);
11257 g_snprintf(tmp,MAXLINE,"# by: %s@%s\n", username, hostname);
11258 fputs(tmp,fd);
11259 fputs("#\n",fd);
11260
11261 /* write empty cdtitle */
11262 g_snprintf(tmp,MAXLINE,"cdtitle = \"\"\n");
11263 fputs(tmp,fd);
11264
11265 fclose(fd);
11266
11267 return 0;
11268 }
11269
11270
11271 /* removes the temporary tocfile again */
11272 /* makes plenty of security checks to remove only a "sane" file */
11273
remove_tmp_writetracks_tocfile(gchar * tocfile)11274 static void remove_tmp_writetracks_tocfile(gchar *tocfile) {
11275 struct stat buf;
11276
11277 /* check first if file exists before delting it */
11278 if (lstat(tocfile, &buf) == 0) {
11279
11280 /* file real and owner is also yourself? */
11281 if (buf.st_uid == getuid() && !S_ISLNK(buf.st_mode)) {
11282
11283 dodebug(2, "removing temporary file %s\n", tocfile);
11284 unlink(tocfile);
11285 } else {
11286 g_warning("Trying to remove file %s which does not belong us or is a link!\n", tocfile);
11287 }
11288 }
11289 }
11290
11291
11292 /* just read the line with the cdtitle from a tocfile and returns it */
11293
get_cdtitle_from_tmp_tocfile(gchar * tocfile,gchar * cdtitle)11294 void get_cdtitle_from_tmp_tocfile(gchar *tocfile, gchar *cdtitle) {
11295 FILE *fd;
11296 gchar line[MAXLINE];
11297 gchar id[MAXLINE];
11298 gchar value[MAXLINE];
11299
11300 strcpy(cdtitle, "");
11301
11302 dodebug(2, "reading temporary toc file %s\n", tocfile);
11303 fd = fopen(tocfile,"r");
11304
11305 if (fd == NULL) {
11306 return;
11307 }
11308
11309 for (;;) {
11310 if (fgets(line,MAXLINE,fd) == NULL)
11311 break;
11312
11313 dodebug(10,"read tocfile: %s", line);
11314 /* skip empty or hashed lines */
11315 strip_string(line);
11316 if (*line == '#' || *line == '\0')
11317 continue;
11318
11319 /* parse lines */
11320 if (parse_config_line(line,id,value)) {
11321 dodebug(10,"invalid line in tocfile");
11322 fclose(fd);
11323 return;
11324 }
11325
11326 if (strcmp("cdtitle",id) == 0) {
11327 strncpy(cdtitle, value, MAXLINE);
11328 }
11329 }
11330
11331 fclose(fd);
11332 }
11333
11334
11335 /* saves the current list of paths to master to a file */
11336
save_master_list(gchar * fname)11337 gint save_master_list(gchar *fname) {
11338 FILE *fd;
11339 gchar tmp[MAXLINE];
11340 gchar tmpexcl[MAXLINE];
11341 gchar tmppath1[MAXLINE];
11342 gchar tmppath2[MAXLINE];
11343 struct stat buf;
11344 gint ret;
11345 time_t acttime;
11346 gchar timestr[MAXLINE];
11347 mstr_redirect_t *mstr;
11348 gchar *excl;
11349 GList *loop;
11350
11351 /* first check if this file does already exist */
11352 if (lstat(fname, &buf) == 0) {
11353 g_snprintf(tmp,1024,_("File %s already exists.\nAre you sure you want to overwrite it?"), fname);
11354 ret = show_dialog(ICO_WARN, tmp, T_OK, T_CANCEL, NULL, 1);
11355 if (ret == 1) {
11356 return -1;
11357 }
11358 }
11359
11360 dodebug(1, "Opening %s for writing (master paths)\n", fname);
11361
11362 fd = fopen(fname,"w");
11363 if (fd == NULL) {
11364 /* error opening file */
11365 return 1;
11366 }
11367
11368 /* get current time */
11369 acttime = time((time_t *) 0);
11370 strcpy(timestr,ctime(&acttime));
11371 timestr[strlen(timestr)-1] = '\0';
11372
11373 /* write header */
11374
11375 fputs("#\n",fd);
11376 g_snprintf(tmp,MAXLINE,"# X-CD-Roast %s - Master-Paths\n",XCDROAST_VERSION);
11377 fputs(tmp,fd);
11378 g_snprintf(tmp,MAXLINE,"# created: %s\n", timestr);
11379 fputs(tmp,fd);
11380 g_snprintf(tmp,MAXLINE,"# by: %s@%s\n", username, hostname);
11381 fputs(tmp,fd);
11382 fputs("#\n",fd);
11383
11384 /* get all paths */
11385 loop = g_list_first(masterparam.mstr_redir);
11386 while (loop) {
11387 mstr = (mstr_redirect_t *) loop->data;
11388 if (mstr) {
11389 if (mstr->mstr_path && !mstr->redir_path) {
11390 strncpy(tmppath1, mstr->mstr_path, MAXLINE);
11391 g_snprintf(tmp,MAXLINE,"ADD1 = \"%s\"\n", convert_escape(tmppath1));
11392 } else
11393 if (mstr->mstr_path && mstr->redir_path) {
11394 strncpy(tmppath1, mstr->mstr_path, MAXLINE);
11395 strncpy(tmppath2, mstr->redir_path, MAXLINE);
11396 g_snprintf(tmp,MAXLINE,"ADD2 = \"%s\",\"%s\"\n", convert_escape(tmppath1), convert_escape(tmppath2));
11397 }
11398 fputs(tmp,fd);
11399 }
11400 loop = loop->next;
11401 }
11402
11403 /* get exclude-dirs */
11404 loop = g_list_first(masterparam.exclude_paths);
11405 while (loop) {
11406 excl = (gchar *)loop->data;
11407 if (excl) {
11408 strncpy(tmpexcl, excl, MAXLINE);
11409 g_snprintf(tmp,MAXLINE,"EXCL = \"%s\"\n", convert_escape(tmpexcl));
11410 fputs(tmp,fd);
11411 }
11412 loop = loop->next;
11413 }
11414
11415 if (fclose(fd) != 0) {
11416 /* error closing file */
11417 return 1;
11418 }
11419
11420 return 0;
11421 }
11422
11423
11424 /* loads the master-paths from a file */
11425
load_master_list(gchar * fname)11426 gint load_master_list(gchar *fname) {
11427 FILE *fd;
11428 gchar line[MAXLINE];
11429 gchar id[MAXLINE];
11430 gchar value[MAXLINE];
11431 gchar value2[MAXLINE];
11432 mstr_redirect_t *mstr;
11433
11434 dodebug(1, "Opening config file %s for reading (master paths)\n", fname);
11435
11436 if ((fd = fopen(fname,"r")) == NULL) {
11437 /* error opening file */
11438 return 1;
11439 }
11440
11441 /* could open the file, now clear the master data */
11442 clear_mstr_glist(&masterparam.mstr_redir);
11443 free_glist(&masterparam.exclude_paths);
11444
11445
11446 for (;;) {
11447 if (fgets(line,MAXLINE,fd) == NULL)
11448 break;
11449
11450 dodebug(10,"master-paths: %s", line),
11451
11452 /* skip empty or hashed lines */
11453 strip_string(line);
11454 if (*line == '#' || *line == '\0')
11455 continue;
11456
11457 /* parse lines */
11458 if (parse_config_line(line,id,value)) {
11459 g_warning("syntax error in master-paths-file\n");
11460 continue;
11461 }
11462
11463 if (strcmp("ADD1", id) == 0) {
11464 if (strcmp(value,"") != 0) {
11465 /* add this value to the list */
11466 mstr = g_new0(mstr_redirect_t,1);
11467 mstr->mstr_path = g_strdup(value);
11468 masterparam.mstr_redir = g_list_append(masterparam.mstr_redir, mstr);
11469 }
11470 }
11471 if (strcmp("ADD2", id) == 0) {
11472 parse_config_line2(line,id,value,value2);
11473 if (strcmp(value,"") != 0) {
11474 /* add this value to the list */
11475 mstr = g_new0(mstr_redirect_t,1);
11476 mstr->mstr_path = g_strdup(value);
11477 masterparam.mstr_redir = g_list_append(masterparam.mstr_redir, mstr);
11478 /* add add redirection if given */
11479 if (strcmp(value2,"") != 0) {
11480 add_redir_mstr_glist(
11481 &masterparam.mstr_redir,
11482 value, value2);
11483 }
11484 }
11485 }
11486 if (strcmp("EXCL", id) == 0) {
11487 if (strcmp(value,"") != 0) {
11488 /* add exclude */
11489 masterparam.exclude_paths = g_list_append(
11490 masterparam.exclude_paths,
11491 g_strdup(value));
11492 }
11493 }
11494 }
11495
11496 if (fclose(fd) != 0) {
11497 /* error closing file */
11498 return 1;
11499 }
11500
11501 return 0;
11502 }
11503
11504
11505 /* writes an info-file with the multisession-information after a
11506 track was mastered */
11507
write_inf_file_for_master(gchar * fname,gint tracknr)11508 gint write_inf_file_for_master(gchar *fname, gint tracknr) {
11509 FILE *fd;
11510 time_t acttime;
11511 gchar timestr[MAXLINE];
11512 gchar tmp[MAXLINE];
11513 gchar tmp2[MAXLINE];
11514 gchar *p;
11515
11516 /* get current time */
11517 acttime = time((time_t *) 0);
11518 strcpy(timestr,ctime(&acttime));
11519 timestr[strlen(timestr)-1] = '\0';
11520
11521 if (!fname || !*fname) {
11522 return 1;
11523 }
11524
11525 /* generate filename */
11526 /* (remove extension and put .xinf there) */
11527 strncpy(tmp,fname,MAXLINE -4);
11528 p = rindex(tmp,'.');
11529 if (!p) return 1;
11530 *p = '\0';
11531 strcpy(tmp2,tmp);
11532 strcat(tmp2,XCDROAST_INFO_EXT);
11533
11534 dodebug(1,"writing inffile %s\n", tmp2);
11535
11536 /* is a link? */
11537 if (check_islink(tmp2, NULL)) {
11538 g_warning("Warning, won't overwrite a link at %s\n", tmp2);
11539 return 1;
11540 }
11541
11542 /* write to file */
11543 fd = fopen(tmp2,"w");
11544
11545 if (fd == NULL) {
11546 g_warning("Can't open file %s for writing\n",tmp2);
11547 return 1;
11548 }
11549
11550 /* write header */
11551 fputs("#\n",fd);
11552 g_snprintf(tmp,MAXLINE,"# X-CD-Roast %s - INF-File\n",XCDROAST_VERSION);
11553 fputs(tmp,fd);
11554 g_snprintf(tmp,MAXLINE,"# created: %s\n", timestr);
11555 fputs(tmp,fd);
11556 g_snprintf(tmp,MAXLINE,"# by: %s@%s\n", username, hostname);
11557 fputs(tmp,fd);
11558 fputs("#\n",fd);
11559
11560 g_snprintf(tmp,MAXLINE,"file = \"%s\"\n",fname);
11561 fputs(tmp,fd);
11562 g_snprintf(tmp,MAXLINE,"track = %d of %d\n",
11563 tracknr, tracknr);
11564 fputs(tmp,fd);
11565
11566 g_snprintf(tmp,MAXLINE,"size = %d\n", masterparam.session_size);
11567 fputs(tmp,fd);
11568 g_snprintf(tmp,MAXLINE,"type = %d\n", 0);
11569 fputs(tmp,fd);
11570 g_snprintf(tmp,MAXLINE,"last_session_start = %d\n", masterparam.last_session_start);
11571 fputs(tmp,fd);
11572 g_snprintf(tmp,MAXLINE,"next_session_start = %d\n", masterparam.next_session_start);
11573 fputs(tmp,fd);
11574
11575 if (fclose(fd) != 0) {
11576 /* error closing file */
11577 return 1;
11578 }
11579
11580 return 0;
11581 }
11582
11583
11584 /* Save the current write-options to a file
11585 return 0 if ok, or 1 on error */
11586
save_writeoptions_file(gchar * confdir,gchar * fname)11587 gint save_writeoptions_file(gchar *confdir, gchar *fname) {
11588 FILE *fd;
11589 gchar tmp[MAXLINE];
11590
11591 /* now check if the confdir exists */
11592 if (!is_directory(confdir)) {
11593 /* try to create directory */
11594 mkdir(confdir, 0700);
11595 dodebug(2, "trying to mkdir %s\n", confdir);
11596 }
11597
11598 g_snprintf(tmp,MAXLINE,"%s/%s", confdir, fname);
11599
11600 dodebug(1, "Opening %s for writing\n", tmp);
11601 dolog(3, "Saving write-options file %s\n", tmp);
11602
11603 fd = fopen(tmp,"w");
11604
11605 if (fd == NULL) {
11606 /* error opening file */
11607 return 1;
11608 }
11609
11610 /* write the config-file header */
11611 fputs("#\n",fd);
11612 g_snprintf(tmp,MAXLINE,"# X-CD-Roast %s Write-Options-File\n",XCDROAST_VERSION);
11613 fputs(tmp,fd);
11614 fputs("#\n",fd);
11615 fputs("# Automatically created by the X-CD-Roast-Setup\n",fd);
11616 fputs("# Don't edit! (Unless you REALLY know what you are doing)\n",fd);
11617 fputs("#\n\n",fd);
11618
11619 /* write data */
11620 g_snprintf(tmp,MAXLINE,"VERSION = \"%s\"\n",XCDROAST_VERSION);
11621 fputs(tmp,fd);
11622 g_snprintf(tmp,MAXLINE,"PLATFORM = \"%s\"\n",system_platform);
11623 fputs(tmp,fd);
11624
11625 g_snprintf(tmp,MAXLINE,"WRITE_SIMUL = %d\n", curset.writesimul);
11626 fputs(tmp,fd);
11627 g_snprintf(tmp,MAXLINE,"WRITE_EJECT = %d\n", curset.writeeject);
11628 fputs(tmp,fd);
11629 g_snprintf(tmp,MAXLINE,"WRITE_PAD = %d\n", curset.writepad);
11630 fputs(tmp,fd);
11631 g_snprintf(tmp,MAXLINE,"WRITE_SWAP = %d\n", curset.writeswap);
11632 fputs(tmp,fd);
11633 g_snprintf(tmp,MAXLINE,"WRITE_NOFIXATE = %d\n", curset.nofixate);
11634 fputs(tmp,fd);
11635 g_snprintf(tmp,MAXLINE,"WRITE_CDTEXT = %d\n", curset.writecdtext);
11636 fputs(tmp,fd);
11637 g_snprintf(tmp,MAXLINE,"WRITE_OVERBURN = %d\n", curset.writeoverburn);
11638 fputs(tmp,fd);
11639 g_snprintf(tmp,MAXLINE,"WRITE_BURNFREE = %d\n", curset.writeburnfree);
11640 fputs(tmp,fd);
11641 g_snprintf(tmp,MAXLINE,"WRITE_AUDIOMASTER = %d\n", curset.writeaudiomaster);
11642 fputs(tmp,fd);
11643 g_snprintf(tmp,MAXLINE,"WRITE_FORCESPEED = %d\n", curset.writeforcespeed);
11644 fputs(tmp,fd);
11645 g_snprintf(tmp,MAXLINE,"WRITE_VARIREC = %d\n", curset.writevarirec);
11646 fputs(tmp,fd);
11647 g_snprintf(tmp,MAXLINE,"WRITE_IGNSIZE = %d\n", curset.writeignsize);
11648 fputs(tmp,fd);
11649 g_snprintf(tmp,MAXLINE,"WRITE_IMMED = %d\n", curset.writeimmed);
11650 fputs(tmp,fd);
11651
11652 if (fclose(fd) != 0) {
11653 /* error closing file */
11654 return 1;
11655 }
11656
11657 return 0;
11658 }
11659
11660
11661 /* Load the write-options-default file
11662 return 0 if ok, or 1 on error */
11663
load_writeoptions_file(gchar * fname)11664 gint load_writeoptions_file(gchar *fname) {
11665 FILE *fd;
11666 gchar line[MAXLINE];
11667 gchar id[MAXLINE];
11668 gchar value[MAXLINE];
11669
11670 if ((fd = fopen(fname,"r")) == NULL) {
11671 /* error opening file */
11672 dodebug(1, "Failed to open write options file %s\n", fname);
11673 dolog(3, "Failed loading write options file %s\n", fname);
11674 return 1;
11675 }
11676
11677 dodebug(1, "Opening write options file %s for reading\n", fname);
11678 dolog(3, "Loading write options file %s\n", fname);
11679
11680 for (;;) {
11681 if (fgets(line,MAXLINE,fd) == NULL)
11682 break;
11683
11684 dodebug(10,"isooptions: %s", line),
11685
11686 /* skip empty or hashed lines */
11687 strip_string(line);
11688 if (*line == '#' || *line == '\0')
11689 continue;
11690
11691 /* parse lines */
11692 if (parse_config_line(line,id,value)) {
11693 g_error("syntax error in isooptions-file\n");
11694 }
11695
11696 if (strcmp("WRITE_SIMUL", id) == 0) {
11697 curset.writesimul = atoi(value);
11698 }
11699 if (strcmp("WRITE_EJECT", id) == 0) {
11700 curset.writeeject = atoi(value);
11701 }
11702 if (strcmp("WRITE_PAD", id) == 0) {
11703 curset.writepad = atoi(value);
11704 }
11705 if (strcmp("WRITE_SWAP", id) == 0) {
11706 curset.writeswap = atoi(value);
11707 }
11708 if (strcmp("WRITE_NOFIXATE", id) == 0) {
11709 curset.nofixate = atoi(value);
11710 }
11711 if (strcmp("WRITE_CDTEXT", id) == 0) {
11712 curset.writecdtext = atoi(value);
11713 }
11714 if (strcmp("WRITE_OVERBURN", id) == 0) {
11715 curset.writeoverburn = atoi(value);
11716 }
11717 if (strcmp("WRITE_BURNFREE", id) == 0) {
11718 curset.writeburnfree = atoi(value);
11719 }
11720 if (strcmp("WRITE_AUDIOMASTER", id) == 0) {
11721 curset.writeaudiomaster = atoi(value);
11722 }
11723 if (strcmp("WRITE_FORCESPEED", id) == 0) {
11724 curset.writeforcespeed = atoi(value);
11725 }
11726 if (strcmp("WRITE_VARIREC", id) == 0) {
11727 curset.writevarirec = atoi(value);
11728 }
11729 if (strcmp("WRITE_IGNSIZE", id) == 0) {
11730 curset.writeignsize = atoi(value);
11731 }
11732 if (strcmp("WRITE_IMMED", id) == 0) {
11733 curset.writeimmed = atoi(value);
11734 }
11735 }
11736
11737 if (fclose(fd) != 0) {
11738 /* error closing file */
11739 return 1;
11740 }
11741
11742 return 0;
11743 }
11744
11745
11746 /* remove the temporarary toc files */
11747
remove_tmp_xcdr_files()11748 void remove_tmp_xcdr_files() {
11749 gchar tmptoc[MAXLINE];
11750
11751 /* delete tmp masterfiles first */
11752 generate_tmp_tocfile_name(tmptoc);
11753 remove_tmp_writetracks_tocfile(tmptoc);
11754 if (master_fname1) {
11755 remove_tmp_writetracks_tocfile(master_fname1);
11756 g_free(master_fname1);
11757 master_fname1 = NULL;
11758 }
11759 if (master_fname2) {
11760 remove_tmp_writetracks_tocfile(master_fname2);
11761 g_free(master_fname2);
11762 master_fname2 = NULL;
11763 }
11764 }
11765
11766
11767 /* used on OS X only - find out the pid of the autodiskmount daemon */
11768 /* return -1 when not found */
11769
get_autodiskmount_pid()11770 gint get_autodiskmount_pid() {
11771 gchar line[MAXLINE];
11772 FILE *fpin;
11773 gchar *p;
11774 gint pid;
11775
11776 g_snprintf(line,MAXLINE,"/bin/ps -ax | /usr/bin/fgrep autodiskmount");
11777
11778 dodebug(1, "calling: %s\n", line);
11779 if ((fpin = popen(line,"r")) == NULL) {
11780 g_error("popen error\n");
11781 }
11782
11783 pid = -1;
11784 for (;;) {
11785 if (fgets(line,MAXLINE,fpin) == NULL)
11786 break;
11787 strip_string(line);
11788
11789 /* line found that not contains grep? should be the one */
11790 if (!strstr(line, "grep")) {
11791 p = strtok(line, " \t");
11792 if (p && pid == -1) {
11793 /* save first match */
11794 pid = atoi(p);
11795 }
11796 }
11797 }
11798
11799 if (pclose(fpin) == -1) {
11800 g_error("pclose error\n");
11801 }
11802
11803 return pid;
11804 }
11805
11806
11807 /* run a single command with sudo and return the exitstatus. */
11808
run_sudo_command(gchar * cmd)11809 gint run_sudo_command(gchar *cmd) {
11810 gchar line[MAXLINE], tmp[MAXLINE];
11811 FILE *fpin;
11812 gint stat,ret;
11813
11814 g_snprintf(line, MAXLINE, "%s -S %s", SUDO, cmd);
11815
11816 if ((fpin = popen(line,"w")) == NULL) {
11817 g_error("popen error\n");
11818 }
11819
11820 /* send password */
11821 g_snprintf(tmp, MAXLINE, "%s\n", curset.sudo_passwd);
11822 fputs(tmp, fpin);
11823
11824 /* command should be executed as root now */
11825
11826 ret = pclose(fpin);
11827 stat = WEXITSTATUS(ret);
11828
11829 dodebug(1, "Executed command \"%s\" with sudo. (exitstatus %d)\n", cmd, stat);
11830
11831 return stat;
11832 }
11833
11834
11835 /* check .inf file for a given audio track for invalid ISRC and MCN entries */
11836 /* return 0 when all ok (or file not found), 1 when invalid data found */
11837
check_valid_isrc_mcn(gchar * tname)11838 gint check_valid_isrc_mcn(gchar *tname) {
11839 gchar tmp[MAXLINE];
11840 gchar tmp2[MAXLINE];
11841 gchar line[MAXLINE];
11842 gchar id[MAXLINE];
11843 gchar value[MAXLINE];
11844 gchar *p;
11845 FILE *fd;
11846 gint errfound;
11847
11848 errfound = 0;
11849
11850 /* generate filename of .inf file */
11851 strncpy(tmp,tname,MAXLINE - 3);
11852 p = rindex(tmp,'.');
11853 if (!p) return 0;
11854 *p = '\0';
11855 strcpy(tmp2,tmp);
11856 strcat(tmp2,".inf");
11857
11858 if ((fd = fopen(tmp2,"r")) == NULL) {
11859 /* file not found or readable - thats ok */
11860 return 0;
11861 }
11862
11863 dodebug(11, "Checking %s for invalid ISRC or MCN\n", tmp2);
11864
11865 for (;;) {
11866 if (fgets(line,MAXLINE,fd) == NULL)
11867 break;
11868
11869 /* skip empty or hashed lines */
11870 strip_string(line);
11871 if (*line == '#' || *line == '\0')
11872 continue;
11873
11874 if (parse_config_line(line,id,value)) {
11875 continue;
11876 }
11877
11878 if (strcmp("MCN",id) == 0) {
11879 errfound += verify_mcn(value);
11880 }
11881 if (strcmp("ISRC",id) == 0) {
11882 errfound += verify_isrc(value);
11883 }
11884 }
11885
11886 fclose(fd);
11887
11888 if (errfound > 0) {
11889 /* invalid data found */
11890 return 1;
11891 } else {
11892 return 0;
11893 }
11894 }
11895
11896
11897 /* comment the ISRC and MCN numbers in a given track inf file */
11898 /* return 0 if we were able to do so, 1 on error */
11899
clear_isrc_mcn_from_inffile(gchar * tname)11900 gint clear_isrc_mcn_from_inffile(gchar *tname) {
11901 gchar tmp[MAXLINE];
11902 gchar tmp2[MAXLINE];
11903 gchar tmpname[MAXLINE];
11904 gchar line[MAXLINE];
11905 gchar *p;
11906 FILE *fd, *fd2;
11907 gint stat;
11908 time_t acttime;
11909 gchar timestr[MAXLINE];
11910
11911 /* get current time */
11912 acttime = time((time_t *) 0);
11913 strcpy(timestr,ctime(&acttime));
11914 timestr[strlen(timestr)-1] = '\0';
11915
11916 /* generate filename of .inf file */
11917 strncpy(tmp,tname,MAXLINE - 3);
11918 p = rindex(tmp,'.');
11919 if (!p) return 0;
11920 *p = '\0';
11921 strcpy(tmp2,tmp);
11922 strcat(tmp2,".inf");
11923 g_snprintf(tmpname,MAXLINE,"%s-%d", tmp2, (gint) getpid());
11924
11925 /* try to open the inf file */
11926 if ((fd = fopen(tmp2,"r")) == NULL) {
11927 /* no source file - thats ok */
11928 return 0;
11929 }
11930
11931 /* create temporary file */
11932 if ((fd2 = fopen(tmpname,"w")) == NULL) {
11933 fclose(fd);
11934 /* we couldnt create the working copy? report error */
11935 return 1;
11936 }
11937
11938 /* copy a lines and change the one with ISRC and MCN */
11939 for (;;) {
11940 if (fgets(line,MAXLINE,fd) == NULL)
11941 break;
11942
11943 /* write modifcation date of xcdroast in new file */
11944 if (strncmp(line,"#created", 8) == 0) {
11945 fputs(line, fd2);
11946 g_snprintf(tmp,MAXLINE,"#modified by X-CD-Roast %s at %s\n", XCDROAST_VERSION, timestr);
11947 fputs(tmp, fd2);
11948 continue;
11949 }
11950
11951 /* skip old modfied lines */
11952 if (strncmp(line,"#modified by X-CD-Roast", 23) == 0) {
11953 continue;
11954 }
11955
11956 if (strncmp(line,"ISRC=", 5) == 0) {
11957 g_snprintf(tmp,MAXLINE,"# %s", line);
11958 fputs(tmp, fd2);
11959 continue;
11960 }
11961 if (strncmp(line,"MCN=", 4) == 0) {
11962 g_snprintf(tmp,MAXLINE,"# %s", line);
11963 fputs(tmp, fd2);
11964 continue;
11965 }
11966
11967 fputs(line,fd2);
11968 }
11969
11970 /* finished modified copy */
11971 fclose(fd2);
11972 fclose(fd);
11973
11974 dodebug(10, "cleared inf-file %s from invalid ISRC or MCN id\n", tmp2);
11975
11976 /* now move the temporary file over the original inf file */
11977 stat = move_textfile(tmpname, tmp2);
11978
11979 if (stat == 1) {
11980 /* remove temporary file if move failed */
11981 unlink(tmpname);
11982 }
11983
11984 return stat;
11985 }
11986
11987