1 /*
2 xtools.c
3 27.3.99 tn
4 */
5
6 #ifdef HAVE_CONFIG_H
7 # include <config.h>
8 #endif
9
10 #include "largefile.h"
11
12 #if HAVE_LOCALE_H
13 #include <locale.h>
14 #else
15 # define setlocale(Category, Locale)
16 #endif
17 #include "gettext.h"
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <sys/stat.h>
22 #include <unistd.h>
23 #include <string.h>
24 #include <strings.h>
25 #include <dirent.h>
26 #include <fcntl.h>
27 #include <sys/types.h>
28 #include <errno.h>
29 #include <ctype.h>
30 #include <grp.h>
31 #include <pwd.h>
32
33 #if ENABLE_NLS
34 # define _(String) gettext (String)
35 # define N_(String) gettext_noop (String)
36 #else
37 # define _(String) (String)
38 # define N_(String) (String)
39 #endif
40
41 #include <gtk/gtk.h>
42 #include <gdk/gdk.h>
43 #include "xcdrdata.h"
44 #include "xcdroast.h"
45 #include "main.h"
46
47 extern gint debug;
48 extern writerreader_devices_t **writerreaderdevs;
49 extern gchar **alt_scsidevices;
50 extern setup_data_t setupdata;
51 extern cd_info_t cdinfo;
52 extern track_info_t **trackinfo;
53 extern GList *imagelist;
54 extern current_set_t curset;
55 extern track_read_set_t trackreadset;
56 extern GList *tocfiles;
57 extern GList *writelist;
58 extern gint bigfonts;
59 extern gint oldfontcode;
60 extern gchar sharedir[MAXLINE];
61 extern gchar prefixdir[MAXLINE];
62 extern gint c_locale_is_utf8;
63
define_tooltip(GtkWidget * widget,gchar * ttext)64 void define_tooltip(GtkWidget *widget, gchar *ttext) {
65 GtkTooltips *tip;
66
67 #ifdef YELLOW_TIPS
68 GdkColor bg;
69 GtkStyle *style;
70 #endif
71 /* tooltips wanted? */
72 if (setupdata.option_tooltips == 0) {
73 return;
74 }
75
76 tip = gtk_tooltips_new();
77 gtk_tooltips_set_tip(tip,widget,ttext,NULL);
78
79 /* set tip color (yellow) */
80
81 /*
82 *** Commented by C.W.Huang :
83 *** Why set tip color by hand? It should be set by the theme.
84 *** Due to an unknown feature or bug of gtk_widget_set_style(),
85 *** GdkFont of the tip will be changed so multibyte characters
86 *** cannot be displayed correctly!
87 */
88 #ifdef YELLOW_TIPS
89
90 gtk_tooltips_force_window(tip);
91 if (!gdk_color_parse(TOOLTIPCOL,&bg)) {
92 g_warning("Can't parse color %s\n",TOOLTIPCOL);
93 return;
94 }
95 if (!gdk_color_alloc(gtk_widget_get_colormap(tip->tip_window),&bg)) {
96 g_warning("Cant allocate color %s\n",TOOLTIPCOL);
97 return;
98 }
99 style = gtk_style_copy(gtk_widget_get_style(tip->tip_window));
100 style->bg[GTK_STATE_NORMAL] = bg;
101 gtk_widget_set_style(tip->tip_window, style);
102 #endif
103 }
104
105
106 /* sets the font and color for a label widget.
107 if color/font is NULL then don't set color/font */
108
set_font_and_color(GtkWidget * widget,gchar * font,gchar * color)109 void set_font_and_color(GtkWidget *widget, gchar *font, gchar *color) {
110
111 #if GTK_MAJOR_VERSION < 2
112 GtkStyle *style;
113 GdkColor c;
114 gchar tmp[MAXLINE];
115 gchar *p;
116
117 style=gtk_style_copy(gtk_widget_get_style(widget));
118
119 if (font != NULL) {
120 gdk_font_unref(style->font);
121
122 /* make copy of string, because we use strtok later */
123 strncpy(tmp,font,MAXLINE);
124
125 /* for unknown reasons in some locales the fonts do
126 not work correcly bold or italic when using fontset */
127 if (oldfontcode) {
128
129 /* now use only the definition up to the first comma */
130 p = strtok(tmp,",");
131 if (p) {
132 style->font = gdk_font_load(p);
133 } else {
134 style->font = gdk_font_load(font);
135 }
136 } else {
137 style->font = gdk_fontset_load(tmp);
138 }
139
140 /* check if valid font */
141 if (style->font == NULL) {
142 g_warning("Font %s not found\n",tmp);
143 return;
144 }
145 }
146
147 if (color != NULL) {
148 if (!gdk_color_parse(color,&c)) {
149 g_warning("Can't parse color %s\n",color);
150 return;
151 }
152
153 if (!gdk_color_alloc(gtk_widget_get_colormap(widget),&c)) {
154 g_warning("Cant allocate color %s\n",color);
155 return;
156 }
157
158 style->fg[GTK_STATE_NORMAL] = c;
159 }
160
161 gtk_widget_set_style(GTK_WIDGET(widget),style);
162
163 #else
164 /* version for GTK 2 */
165
166 gchar *orglabel;
167 gchar *newlabel;
168 gint length;
169
170 newlabel = NULL;
171 orglabel = (gchar *)gtk_label_get_text(GTK_LABEL(widget));
172
173 if (font && strcmp(font, BOLDFONT) == 0 && !color) {
174 length = strlen(orglabel) + strlen("<b></b>") + 1;
175 newlabel = (gchar *) g_new0(gchar *, length);
176 g_snprintf(newlabel, length, "<b>%s</b>", orglabel);
177 }
178 if (font && strcmp(font, BIGFONT) == 0 && !color) {
179 length = strlen(orglabel) + strlen("<span size=\"xx-large\"></span>") + 1;
180 newlabel = (gchar *) g_new0(gchar *, length);
181 g_snprintf(newlabel, length, "<span size=\"xx-large\">%s</span>", orglabel);
182 }
183 if (color && !font) {
184 length = strlen(orglabel) + strlen("<span color=\"\"></span>") + strlen(color) + 1;
185 newlabel = (gchar *) g_new0(gchar *, length);
186 g_snprintf(newlabel, length, "<span color=\"%s\">%s</span>", color, orglabel);
187 }
188 if (font && strcmp(font, BOLDFONT) == 0 && color) {
189 length = strlen(orglabel) + strlen("<b><span color=\"\"></span></b>") + strlen(color) + 1;
190 newlabel = (gchar *) g_new0(gchar *, length);
191 g_snprintf(newlabel, length, "<b><span color=\"%s\">%s</span></b>", color, orglabel);
192 }
193 if (font && strcmp(font, BIGFONT) == 0 && color) {
194 length = strlen(orglabel) + strlen("<span color=\"\" size=\"xx-large\"></span>") + strlen(color) + 1;
195 newlabel = (gchar *) g_new0(gchar *, length);
196 g_snprintf(newlabel, length, "<span color=\"%s\" size=\"xx-large\">%s</span>", color, orglabel);
197 }
198
199 if (newlabel) {
200 gtk_label_set_text(GTK_LABEL(widget),newlabel);
201 gtk_label_set_use_markup (GTK_LABEL(widget), TRUE);
202 g_free(newlabel);
203 }
204 #endif
205 }
206
207
208 /* set font and color for a frame */
209
set_font_and_color_frame(GtkWidget * widget,gchar * font,gchar * color)210 void set_font_and_color_frame(GtkWidget *widget, gchar *font, gchar *color) {
211
212 #if GTK_MAJOR_VERSION < 2
213 /* gtk1 version is identical to label version */
214 set_font_and_color(widget, font, color);
215 #else
216
217 set_font_and_color(gtk_frame_get_label_widget(GTK_FRAME(widget)), font, color);
218
219 #endif
220 }
221
222 /* sets the color for a label widget.
223 if color is NULL then don't set color/font */
224
set_labelcolor(GtkWidget * widget,gchar * color)225 void set_labelcolor(GtkWidget *widget, gchar *color) {
226 GtkStyle *style;
227 GdkColor c;
228
229 style=gtk_style_copy(gtk_widget_get_style(widget));
230
231 if (color != NULL) {
232 if (!gdk_color_parse(color,&c)) {
233 g_warning("Can't parse color %s\n",color);
234 return;
235 }
236
237 if (!gdk_color_alloc(gtk_widget_get_colormap(widget),&c)) {
238 g_warning("Cant allocate color %s\n",color);
239 return;
240 }
241
242 style->fg[GTK_STATE_NORMAL] = c;
243 }
244
245 gtk_widget_set_style(GTK_WIDGET(widget),style);
246 }
247
248
249 /* sets a certain row in a clist to a font */
250
set_clist_row_font(GtkCList * clist,gint row,gchar * ffont)251 void set_clist_row_font(GtkCList *clist, gint row, gchar *ffont) {
252
253 #if GTK_MAJOR_VERSION < 2
254 GtkStyle *style;
255 gchar tmp[MAXLINE];
256 gchar *p;
257
258 style=gtk_style_copy(gtk_widget_get_style(GTK_WIDGET(clist)));
259
260 /* make copy of string, because we use strtok later */
261 strncpy(tmp,ffont,MAXLINE);
262
263 gdk_font_unref(style->font);
264 /* for unknown reasons in some locales the fonts do
265 not work correcly bold or italic when using fontset */
266 if (oldfontcode) {
267 /* now use only the definition up to the first comma */
268 p = strtok(tmp,",");
269 if (p) {
270 style->font = gdk_font_load(p);
271 } else {
272 style->font = gdk_font_load(ffont);
273 }
274 } else {
275 style->font = gdk_fontset_load(tmp);
276 }
277
278 /* check if valid font */
279 if (style->font == NULL) {
280 g_warning("Font %s not found\n",tmp);
281 return;
282 }
283
284 gtk_clist_set_row_style(clist,row,style);
285 #else
286 /* version for GTK 2 */
287
288 GtkStyle *style;
289
290 style=gtk_style_copy(gtk_widget_get_style(GTK_WIDGET(clist)));
291
292 if (ffont && strcmp(ffont, SLANTFONT) == 0) {
293 pango_font_description_set_style(style->font_desc,
294 PANGO_STYLE_ITALIC);
295 }
296 if (ffont && strcmp(ffont, BOLDFONT) == 0) {
297 pango_font_description_set_weight(style->font_desc,
298 PANGO_WEIGHT_BOLD);
299 }
300
301 gtk_clist_set_row_style(clist,row,style);
302
303 #endif
304
305 }
306
307
308 /* colors a certain row in a clist */
309
set_clist_row_color(GtkCList * clist,gint row,gchar * color)310 void set_clist_row_color(GtkCList *clist, gint row, gchar *color) {
311 GtkStyle *style;
312 GdkColor c;
313
314 style=gtk_style_copy(gtk_widget_get_style(GTK_WIDGET(clist)));
315
316 if (!gdk_color_parse(color,&c)) {
317 g_warning("Can't parse color %s\n",color);
318 return;
319 }
320
321 if (!gdk_color_alloc(gtk_widget_get_colormap(GTK_WIDGET(clist)),&c)) {
322 g_warning("Cant allocate color %s\n",color);
323 return;
324 }
325 style->fg[GTK_STATE_NORMAL] = c;
326
327 gtk_clist_set_row_style(clist,row,style);
328 }
329
330
331 /* return the given font (you have to unref it later) */
332
get_some_font(gchar * fontstr)333 GdkFont *get_some_font(gchar *fontstr) {
334 gchar tmp[MAXLINE];
335 gchar *p;
336 GdkFont *font;
337
338 strncpy(tmp,fontstr,MAXLINE);
339
340 if (oldfontcode) {
341 /* now use only the definition up to the first comma */
342 p = strtok(tmp,",");
343 if (p) {
344 font = gdk_font_load(p);
345 /* for some reason the defaul fixed font seems not to work - hard core here another font for ancient systems */
346 /* font = gdk_font_load("-*-*-medium-r-normal-*-*-120-*-*-*-*-*-*"); */
347 } else {
348 font = gdk_font_load(fontstr);
349 }
350 } else {
351 font = gdk_fontset_load(tmp);
352 }
353
354 return font;
355 }
356
357
358 /* free a simple glist structure */
359
free_glist(GList ** list)360 void free_glist(GList **list) {
361 GList *loop;
362 gchar *dir;
363
364 loop = g_list_first(*list);
365 while(loop) {
366 dir = loop->data;
367 g_free(dir);
368 loop = loop->next;
369 }
370 g_list_free(*list);
371 *list = NULL;
372 }
373
374
375 /* copy a simple glist (which has only strings as elements) */
376
copy_glist(GList ** dst,GList * src)377 void copy_glist(GList **dst, GList *src) {
378 GList *loop;
379 gchar *dir;
380
381 /* clear target list */
382 free_glist(dst);
383
384 loop = g_list_first(src);
385 while(loop) {
386 dir = loop->data;
387 *dst = g_list_append(*dst,g_strdup(dir));
388 loop = loop->next;
389 }
390 }
391
392
393 /* remove a string-element from a glist */
394
del_glist_link(GList ** list,gchar * str)395 void del_glist_link(GList **list, gchar *str) {
396 GList *loop;
397 gchar *dir;
398
399 if (str == NULL)
400 return;
401
402 loop = g_list_first(*list);
403 while(loop) {
404 dir = loop->data;
405 if (dir && strcmp(str,dir) == 0) {
406 g_free(dir);
407 *list = g_list_remove_link(*list, loop);
408 return;
409 }
410 loop = loop->next;
411 }
412 }
413
414
415 /* check if a string-element is in a glist */
416 /* return 1 if found, 0 if not */
417
check_in_glist(GList ** list,gchar * str)418 gint check_in_glist(GList **list, gchar *str) {
419 GList *loop;
420 gchar *dir;
421
422 if (str == NULL)
423 return 0;
424
425 loop = g_list_first(*list);
426 while(loop) {
427 dir = loop->data;
428 if (dir && strcmp(str,dir) == 0) {
429 return 1;
430 }
431 loop = loop->next;
432 }
433 return 0;
434 }
435
436
437 /* check if a path is in a master-path-glist */
438 /* return 1 if found, 0 if not */
439
check_in_mstr_glist(GList ** list,gchar * str)440 gint check_in_mstr_glist(GList **list, gchar *str) {
441 GList *loop;
442 mstr_redirect_t *mstr;
443 gchar *dir;
444
445 if (str == NULL)
446 return 0;
447
448 loop = g_list_first(*list);
449 while(loop) {
450 mstr = (mstr_redirect_t *) loop->data;
451 if (mstr) {
452 dir = mstr->mstr_path;
453 } else {
454 dir = NULL;
455 }
456 if (dir && strcmp(str,dir) == 0) {
457 return 1;
458 }
459 loop = loop->next;
460 }
461 return 0;
462 }
463
464
465 /* remove a string-element from a master-glist */
466 /* if there is a redir-path, remove only this and return */
467 /* (unless del_both is set, where the whole entry is removed) */
468 /* del_both == -1, only remove link if possible */
469
del_mstr_glist_link(GList ** list,gchar * str,gint del_both)470 void del_mstr_glist_link(GList **list, gchar *str, gint del_both) {
471 GList *loop;
472 mstr_redirect_t *mstr;
473 gchar *dir;
474
475 if (str == NULL)
476 return;
477
478 loop = g_list_first(*list);
479 while(loop) {
480 mstr = (mstr_redirect_t *) loop->data;
481 if (mstr) {
482 dir = mstr->mstr_path;
483 } else {
484 dir = NULL;
485 }
486
487 if (dir && strcmp(str,dir) == 0) {
488 /* found link */
489 if (mstr->redir_path) {
490 /* remove redir-path only */
491 g_free(mstr->redir_path);
492 mstr->redir_path = NULL;
493
494 if (del_both == 0)
495 return;
496 }
497 if (del_both == -1) return;
498
499 g_free(dir);
500 g_free(mstr);
501 *list = g_list_remove_link(*list, loop);
502 return;
503 }
504 loop = loop->next;
505 }
506 }
507
508
509 /* clear a mstr_glist */
510
clear_mstr_glist(GList ** list)511 void clear_mstr_glist(GList **list) {
512 GList *loop;
513 mstr_redirect_t *mstr;
514
515 loop = g_list_first(*list);
516 while(loop) {
517 mstr = (mstr_redirect_t *) loop->data;
518 if (mstr) {
519 if (mstr->mstr_path)
520 g_free(mstr->mstr_path);
521 if (mstr->redir_path)
522 g_free(mstr->redir_path);
523 g_free(mstr);
524 }
525 loop = loop->next;
526 }
527 g_list_free(*list);
528 *list = NULL;
529 }
530
531
532 /* add a redir path to the master-glist */
533
add_redir_mstr_glist(GList ** list,gchar * str,gchar * new)534 void add_redir_mstr_glist(GList **list, gchar *str, gchar *new) {
535 GList *loop;
536 mstr_redirect_t *mstr;
537 gchar *dir;
538
539 if (str == NULL)
540 return;
541
542 loop = g_list_first(*list);
543 while(loop) {
544 mstr = (mstr_redirect_t *) loop->data;
545 if (mstr) {
546 dir = mstr->mstr_path;
547 } else {
548 dir = NULL;
549 }
550 if (dir && strcmp(str,dir) == 0) {
551 /* found link */
552 if (mstr->redir_path) {
553 /* remove redir-path first */
554 g_free(mstr->redir_path);
555 }
556 /* now set new value */
557 mstr->redir_path = g_strdup(new);
558 return;
559 }
560 loop = loop->next;
561 }
562 }
563
564
565 /* get a string in the form bla => foo and return only bla */
566
extract_mstr_path_from_clist(gchar * in,gchar * out)567 void extract_mstr_path_from_clist(gchar *in, gchar *out) {
568 gint found;
569 guint i;
570
571 if (in == NULL || out == NULL)
572 return;
573
574 if (strlen(in) == 0) {
575 strcpy(out,"");
576 return;
577 }
578
579 found = -1;
580
581 for (i = 0; i < strlen(in)-1; i++) {
582 if ((in[i] == '=') && (in[i+1] == '>')) {
583 found = i;
584 break;
585 }
586 }
587
588 if (found == -1) {
589 /* nothing found - return original string */
590 strcpy(out,in);
591 } else {
592 strncpy(out,in,found);
593 out[found] = '\0';
594 }
595 strip_string(out);
596
597 /* internally we use not utf8, convert back from widget */
598 convert_for_gtk2_filename(out);
599 }
600
601
602 /* get the redir path from the master-glist */
603
get_redir_path_from_mstr_glist(GList ** list,gchar * str,gchar * ret)604 void get_redir_path_from_mstr_glist(GList **list, gchar *str, gchar *ret) {
605 GList *loop;
606 mstr_redirect_t *mstr;
607 gchar *dir;
608
609 if (str == NULL)
610 return;
611
612 loop = g_list_first(*list);
613 while(loop) {
614 mstr = (mstr_redirect_t *) loop->data;
615 if (mstr) {
616 dir = mstr->mstr_path;
617 } else {
618 dir = NULL;
619 }
620 if (dir && strcmp(str,dir) == 0) {
621 /* found link */
622 if (mstr->redir_path) {
623 strcpy(ret, mstr->redir_path);
624 } else {
625 strcpy(ret, "");
626 }
627 return;
628 }
629 loop = loop->next;
630 }
631 strcpy(ret, "");
632 }
633
634
635 /* set scsi-sector-size for a given device */
636
set_sectorsize(gint devnr,gint size)637 void set_sectorsize(gint devnr, gint size) {
638 gint i;
639
640 i = 0;
641 while(writerreaderdevs[i] != NULL) {
642 if (devnr == writerreaderdevs[i]->devnr) {
643 writerreaderdevs[i]->sector_size = size;
644 return;
645 }
646 i++;
647 }
648 }
649
650
651 /* get scsi-sector-size for a given device */
652
get_sectorsize(gint devnr)653 gint get_sectorsize(gint devnr) {
654 gint i;
655
656 i = 0;
657 while(writerreaderdevs[i] != NULL) {
658 if (devnr == writerreaderdevs[i]->devnr) {
659 return(writerreaderdevs[i]->sector_size);
660 }
661 i++;
662 }
663
664 return DATASECTORSIZE;
665 }
666
667
668 /* convert the devnr to a device-string. return 1 if devnr not found */
669
convert_devnr2devstring(gint devnr,gchar * str)670 gint convert_devnr2devstring(gint devnr, gchar *str) {
671 gint i;
672 gchar tmp[MAXLINE];
673
674 i = 0;
675 while(writerreaderdevs[i] != NULL) {
676 if (devnr == writerreaderdevs[i]->devnr) {
677 if (!writerreaderdevs[i]->devicestr) {
678 g_error("empty device string?");
679 }
680 g_snprintf(tmp,MAXLINE,"%s %s [%s]",
681 writerreaderdevs[i]->vendor,
682 writerreaderdevs[i]->model,
683 writerreaderdevs[i]->devicestr);
684 strcpy(str,tmp);
685 return 0;
686 }
687 i++;
688 }
689
690 strcpy(str,"");
691 return 1;
692 }
693
694
695 /* convert the devnr to a vendor-string. return 1 if devnr not found */
696
convert_devnr2vendor(gint devnr,gchar * str)697 gint convert_devnr2vendor(gint devnr, gchar *str) {
698 gint i;
699
700 i = 0;
701 while(writerreaderdevs[i] != NULL) {
702 if (devnr == writerreaderdevs[i]->devnr) {
703 strcpy(str,writerreaderdevs[i]->vendor);
704 return 0;
705 }
706 i++;
707 }
708 strcpy(str,"");
709 return 1;
710 }
711
712
713 /* convert the devnr to a model-string. return 1 if devnr not found */
714
convert_devnr2model(gint devnr,gchar * str)715 gint convert_devnr2model(gint devnr, gchar *str) {
716 gint i;
717
718 i = 0;
719 while(writerreaderdevs[i] != NULL) {
720 if (devnr == writerreaderdevs[i]->devnr) {
721 strcpy(str,writerreaderdevs[i]->model);
722 return 0;
723 }
724 i++;
725 }
726 strcpy(str,"");
727 return 1;
728 }
729
730
731 /* convert the devnr to a bus/id/lun-string. return 1 if devnr not found */
732
convert_devnr2busid(gint devnr,gchar * str)733 gint convert_devnr2busid(gint devnr, gchar *str) {
734 gint i;
735
736 i = 0;
737 while(writerreaderdevs[i] != NULL) {
738 if (devnr == writerreaderdevs[i]->devnr) {
739 if (!writerreaderdevs[i]->devicestr) {
740 g_error("empty device string?");
741 }
742 strncpy(str,
743 writerreaderdevs[i]->devicestr,
744 MAXLINE);
745 convert_escape(str);
746 return 0;
747 }
748 i++;
749 }
750 strcpy(str,"");
751 return 1;
752 }
753
754
755 /* save as convert_devnr2busid(), but return with dev= component */
756
convert_devnr2busid_dev(gint devnr,gchar * str)757 gint convert_devnr2busid_dev(gint devnr, gchar *str) {
758 gint i;
759 gchar tmp[MAXLINE];
760
761 i = 0;
762 while(writerreaderdevs[i] != NULL) {
763 if (devnr == writerreaderdevs[i]->devnr) {
764 if (!writerreaderdevs[i]->devicestr) {
765 g_error("empty device string?");
766 }
767 strncpy(tmp,
768 writerreaderdevs[i]->devicestr,
769 MAXLINE);
770 convert_escape(tmp);
771 g_snprintf(str,MAXLINE,"dev= \"%s\"",tmp);
772 return 0;
773 }
774 i++;
775 }
776 strcpy(str,"");
777 return 1;
778 }
779
780
781 /* convert kilobytes to MB/min string */
782 /* displays MB when using 2048b sectors. min like stored audiotracks on the
783 hard drive - this is not correct when displaying the minutesize of DATA
784 tracks. */
785
convert_kbytes2mbminstring(gint kbytes,gchar * str)786 void convert_kbytes2mbminstring(gint kbytes, gchar *str) {
787 gint mb;
788 gint min;
789 gint sec;
790 gint frames;
791 gint frms;
792 gint64 tmpsize;
793
794 mb = kbytes/1024;
795
796 #if 0
797 /* we have a problem here, that we hit gint overflow on
798 large values - in this case round a little inexact */
799 if (mb < 2000) {
800 /* correct value */
801 frames = (kbytes*1024)/CDDAFRAME;
802 } else {
803 /* rounded value */
804 frames = (kbytes/CDDAFRAME)*1024;
805 }
806 #endif
807 /* new code using 64 bit values */
808 tmpsize = (gint64)kbytes * 1024;
809 frames = (gint) ((gint64)tmpsize/CDDAFRAME);
810
811 min = frames/(60*75);
812 sec = (frames%(60*75))/75;
813 frms = (frames%75);
814 /* csec = (4*(frames%75)+1)/3; */
815
816 g_snprintf(str,MAXLINE,"%dMB / %d:%02d.%02d",mb,min,sec,frms);
817 }
818
819
820 /* convert kilobytes to MB/min string */
821 /* displays MB when using 2048b sectors. min like the size of track after
822 burned. The only correct min size display when burning data tracks */
823
convert_kbytes2mbcorrectminstring(gint kbytes,gchar * str)824 void convert_kbytes2mbcorrectminstring(gint kbytes, gchar *str) {
825 gint mb;
826 gint min;
827 gint sec;
828 gint frames;
829 gint frms;
830
831 mb = kbytes/1024;
832 frames = kbytes/2;
833 min = frames/(60*75);
834 sec = (frames%(60*75))/75;
835 frms = (frames%75);
836 /* csec = (4*(frames%75)+1)/3; */
837
838 g_snprintf(str,MAXLINE,"%dMB / %d:%02d.%02d",mb,min,sec,frms);
839 }
840
841
842 /* convert frames to MB/min string */
843 /* should only be used for audio or full disk info */
844
convert_frames2mbminstring(gint frames,gchar * str)845 void convert_frames2mbminstring(gint frames, gchar *str) {
846 gint mb;
847 gint min;
848 gint sec;
849 gint frms;
850 gint64 tmpsize;
851
852 #if 0
853 mb = ((frames/1024)*CDDAFRAME)/1024;
854 /* mb = ((frames/1024)*DATASECTORSIZE)/1024; */
855 #endif
856 /* use 64 bit values */
857 tmpsize = (gint64)frames * CDDAFRAME;
858 mb = (gint) ((gint64)tmpsize >> 20);
859
860 min = frames/(60*75);
861 sec = (frames%(60*75))/75;
862 frms = (frames%75);
863 /* csec = (4*(frames%75)+1)/3; */
864
865 g_snprintf(str,MAXLINE,"%dMB / %d:%02d.%02d",mb,min,sec,frms);
866 }
867
868
869 /* convert frames/sectors to MB string */
870 /* note - this is only true for DATA-tracks */
871
convert_frames2mbstring(gint frames,gchar * str)872 void convert_frames2mbstring(gint frames, gchar *str) {
873 gint mb;
874
875 mb = frames*(DATASECTORSIZE/1024)/1024;
876 g_snprintf(str,MAXLINE,"%dMB",mb);
877 }
878
879
880 /* convert kbytes to MB string */
881
convert_kbytes2mbstring(gint kbytes,gchar * str)882 void convert_kbytes2mbstring(gint kbytes, gchar *str) {
883 gint mb;
884
885 mb = kbytes/1024;
886 g_snprintf(str,MAXLINE,"%dMB",mb);
887 }
888
889
890 /* convert frames to min string */
891
convert_frames2minstring(gint frames,gchar * str)892 void convert_frames2minstring(gint frames, gchar *str) {
893 gint min;
894 gint sec;
895 gint frms;
896
897 min = frames/(60*75);
898 sec = (frames%(60*75))/75;
899 frms = (frames%75);
900 /* csec = (4*(frames%75)+1)/3; */
901
902 g_snprintf(str,MAXLINE,"%d:%02d.%02d",min,sec,frms);
903 }
904
905
906 /* creates a label that is right justified. Useful when
907 packing into a table */
908
rightjust_gtk_label_new(gchar * txt)909 GtkWidget *rightjust_gtk_label_new(gchar *txt) {
910 GtkWidget *align;
911 GtkWidget *label;
912
913 /* create right justify alignment */
914 align = gtk_alignment_new(1.0,0.5,0,0);
915 label = gtk_label_new(txt);
916 gtk_container_add(GTK_CONTAINER(align),label);
917 gtk_widget_show(label);
918
919 return align;
920 }
921
922
923 /* creates a label that is left justified. Useful when
924 packing into a table */
925
leftjust_gtk_label_new(gchar * txt)926 GtkWidget *leftjust_gtk_label_new(gchar *txt) {
927 GtkWidget *align;
928 GtkWidget *label;
929
930 /* create left justify alignment */
931 align = gtk_alignment_new(0.0,0.5,0,0);
932 label = gtk_label_new(txt);
933 gtk_container_add(GTK_CONTAINER(align),label);
934 gtk_widget_show(label);
935
936 return align;
937 }
938
939
940 /* get some info about our image-file */
941
analyze_imgfile(gchar * path,gchar * file,GList ** retlist)942 static void analyze_imgfile(gchar *path, gchar *file, GList **retlist) {
943 struct stat buf;
944 image_files_t *entry;
945 gchar tmp[MAXLINE];
946 gchar volid[MAXLINE];
947 off_t size;
948 gint type,readable,isosize;
949 gint fd;
950
951 strncpy(tmp,path,MAXLINE-strlen(file)-2);
952 strcat(tmp,"/");
953 strcat(tmp,file);
954
955 stat(tmp,&buf);
956
957 /* check if regular file or link */
958 if (S_ISLNK(buf.st_mode) != 1 && S_ISREG(buf.st_mode) != 1) {
959 /* its not..so ignore */
960 return;
961 }
962
963 /* readable for us? */
964 fd = open(tmp, O_RDONLY,0);
965 if (fd == -1) {
966 readable = 0;
967 } else {
968 readable = 1;
969 close(fd);
970 }
971
972 size = (off_t) buf.st_size;
973
974 isosize = 0;
975
976 /* now do some tests about file-contents */
977 if (strncmp(file+strlen(file)-4,".toc",4) == 0) {
978 type = 4;
979 } else if (strncmp(file+strlen(file)-4,".wav",4) == 0) {
980 /* wav-file */
981 if (check_wav_file(tmp) == 0) {
982 /* invalid wav */
983 type = 2;
984 } else {
985 /* valid wav */
986 type = 1;
987 }
988 } else {
989 /* data-file */
990 isosize = check_iso_file(-1,tmp,volid,0);
991 if (isosize == 0) {
992 /* unknown data */
993 type = 3;
994 } else {
995 /* iso9660 */
996 type = 0;
997 }
998 }
999
1000 /* allocate memory and fill structure */
1001 entry = g_new(image_files_t,1);
1002 entry->path = g_strdup(tmp);
1003 entry->mtime = buf.st_mtime;
1004 entry->size = (off_t) size;
1005 entry->type = type;
1006 entry->readable = readable;
1007 entry->from_track = 0;
1008 if (type == 0) {
1009 entry->volname = g_strdup(volid);
1010 } else {
1011 entry->volname = NULL;
1012 }
1013 entry->title = NULL;
1014 entry->artist = NULL;
1015 entry->cddb_ttitle = NULL;
1016 entry->cd_discid = NULL;
1017
1018 entry->isosize = isosize;
1019 entry->last_session_start = -1;
1020 entry->next_session_start = -1;
1021
1022 /* find if there is some information in the inf-file */
1023 get_inf_tracktitle(tmp, entry);
1024
1025 /* add to list */
1026 *retlist = g_list_append(*retlist, entry);
1027 }
1028
1029
1030 /* scans a directory for files matching the known extensions */
1031 /* return 0 if ok, 1 on problem */
1032
get_img_files(gchar * path,GList ** retlist)1033 gint get_img_files(gchar *path, GList **retlist) {
1034 gchar *img_ext[] = IMG_EXTENSIONS;
1035 struct dirent *ent;
1036 DIR *dir;
1037 gint i,len,len2;
1038
1039 dir = opendir(path);
1040
1041 /* invalid directory */
1042 if (dir == NULL)
1043 return 1;
1044
1045 /* scan a directory */
1046 while ( (ent = readdir(dir)) ) {
1047 /* does the extension match? */
1048 for(i = 0; img_ext[i] != NULL; i++) {
1049 len = strlen(img_ext[i]);
1050 len2 = strlen(ent->d_name);
1051
1052 /* skip to short filenames */
1053 if (len2 < len) continue;
1054
1055 if (strncmp((ent->d_name)+len2-len,img_ext[i],len) == 0) {
1056 /* we found a match */
1057 analyze_imgfile(path,ent->d_name,retlist);
1058 }
1059 }
1060 }
1061
1062 closedir(dir);
1063 return 0;
1064 }
1065
1066
1067 /* print imagelist-memory-structure (debug purpose) */
1068
print_imagelist()1069 void print_imagelist() {
1070 GList *loop;
1071 image_files_t *entry;
1072
1073 dodebug(2,"--------- imagelist glist ---------\n");
1074 loop = g_list_first(imagelist);
1075 while (loop) {
1076 entry = loop->data;
1077 dodebug(2,"path: %s, %"LL_FORMAT", %d, %d, %d (%d,%d)\n",entry->path,
1078 (gint64)entry->size, entry->type, entry->readable,
1079 entry->isosize, entry->last_session_start,
1080 entry->next_session_start);
1081 if (entry->volname != NULL) {
1082 dodebug(2, "\tvolname: %s\n", entry->volname);
1083 }
1084
1085 loop = loop->next;
1086 }
1087 }
1088
1089
1090 /* sort the imagelist according to file names */
1091
sort_imagelist()1092 void sort_imagelist() {
1093 GList *first, *last, *list1, *list2;
1094 image_files_t *ent1, *ent2, *ent3;
1095
1096 first = g_list_first(imagelist);
1097 last = g_list_last(imagelist);
1098 for (list1 = first; list1 != last; list1 = list1->next) {
1099 for (list2 = last; list2 != list1; list2 = list2->prev) {
1100 ent1 = (image_files_t *) list1->data;
1101 ent2 = (image_files_t *) list2->data;
1102
1103 if(strcmp(ent1->path,ent2->path) > 0) {
1104 ent3 = ent1;
1105 list1->data = list2->data;
1106 list2->data = ent3;
1107 }
1108 }
1109 }
1110 }
1111
1112
1113 /* search all image-directories and create a list of matching files */
1114 /* return number of matching files */
1115
scan_imagedirs()1116 gint scan_imagedirs() {
1117 GList *loop;
1118 gchar tmp[MAXLINE];
1119 image_files_t *entry;
1120
1121 /* free the old image-list first */
1122 loop = g_list_first(imagelist);
1123 while (loop) {
1124 entry = loop->data;
1125 g_free(entry->path);
1126 g_free(entry->volname);
1127 g_free(entry->title);
1128 g_free(entry->artist);
1129 g_free(entry->cddb_ttitle);
1130 g_free(entry->cd_discid);
1131 g_free(entry);
1132
1133 loop = loop->next;
1134 }
1135 g_list_free(imagelist);
1136 imagelist = NULL;
1137
1138 loop = g_list_first(setupdata.image_dirs);
1139 while (loop) {
1140 /* image-dir extracted */
1141 strncpy(tmp,(gchar *)loop->data, MAXLINE);
1142 get_img_files(tmp,&imagelist);
1143
1144 loop = loop->next;
1145 }
1146
1147 /* sort the image-list */
1148 sort_imagelist();
1149
1150 /* now we have a complete image-list */
1151 if (debug) print_imagelist();
1152
1153 return (g_list_length(imagelist));
1154 }
1155
1156
1157 /* return a string saying which type of CD we are currently handling */
1158 /* mode = 0: used check cd in drive, mode = 1: check trackreadset for
1159 writing */
1160
determine_cd_type(gchar * ret,gint mode)1161 gint determine_cd_type(gchar *ret, gint mode) {
1162 gint i;
1163 gint audio,data;
1164 gint type;
1165 gchar tmp[MAXLINE];
1166 GList *loop;
1167 track_read_param_t *trackparam;
1168
1169 /* unknown type */
1170 type = -1;
1171
1172 /* count tracks */
1173 audio = 0;
1174 data = 0;
1175 trackparam = NULL;
1176
1177
1178 if (mode == 0) {
1179 /* check cdinfo-structure */
1180 for (i = 0; i < cdinfo.nr_tracks; i++) {
1181 if (trackinfo[i]->type == 0) {
1182 data++;
1183 } else {
1184 audio++;
1185 }
1186 }
1187 } else {
1188 /* check trackreadset-structure */
1189 loop = g_list_first(trackreadset.trackparams);
1190 while(loop) {
1191 trackparam = loop->data;
1192 if (trackparam->tracktype == 0) {
1193 data++;
1194 } else {
1195 audio++;
1196 }
1197
1198 loop = loop->next;
1199 }
1200 /* now point trackparam back to first track for later use */
1201 loop = g_list_first(trackreadset.trackparams);
1202 if (loop) trackparam = loop->data;
1203 else trackparam = NULL;
1204 }
1205
1206 /* pure data-cd */
1207 if (data == 1 && audio == 0) {
1208 type = 0;
1209 } else
1210 /* pure audio-cd */
1211 if (data == 0 && audio > 0) {
1212 type = 1;
1213 } else
1214 /* mixed-mode */
1215 if (mode == 0 && data == 1 && audio > 0 && trackinfo[0]->type == 0) {
1216 type = 2;
1217 } else
1218 if (mode == 1 && data == 1 && audio > 0 && trackparam->tracktype == 0) {
1219 type = 2;
1220 } else
1221 /* cd-extra */
1222 if (mode == 0 && data == 1 && audio > 0 && cdinfo.have_cdextra) {
1223 type = 3;
1224 } else
1225 if (mode == 1 && data == 1 && audio > 0 && trackparam->tracktype == 1) {
1226 /* one data, at least one audio and first track audio */
1227 type = 3;
1228 } else
1229 /* multisession */
1230 if (data > 1 && audio == 0) {
1231 type = 4;
1232 }
1233
1234 /* enough for now */
1235 switch (type) {
1236 case 0:
1237 if ((mode == 0 && cdinfo.total_size < 450000) ||
1238 (mode == 1 && trackreadset.cdsize < 450000)) {
1239 strncpy(tmp,_("Data-CD"),MAXLINE);
1240 } else {
1241 strncpy(tmp,_("Data-DVD"),MAXLINE);
1242 }
1243 break;
1244 case 1:
1245 strncpy(tmp,_("Audio-CD"),MAXLINE);
1246 break;
1247 case 2:
1248 strncpy(tmp,_("Mixed-Mode-CD"),MAXLINE);
1249 break;
1250 case 3:
1251 strncpy(tmp,_("CD-Extra"),MAXLINE);
1252 break;
1253 case 4:
1254 strncpy(tmp,_("Multisession-CD"),MAXLINE);
1255 break;
1256 default:
1257 strncpy(tmp,_("Unknown"),MAXLINE);
1258 break;
1259 }
1260
1261 /* return value */
1262 strncpy(ret,tmp,MAXLINE);
1263 return (type);
1264 }
1265
1266
1267 /* calculate free space dependent of current image-dir setting */
1268 /* return free kbytes and kbytes free in biggest imagedir */
1269
determine_free_space(gint * biggestfree)1270 gint determine_free_space(gint *biggestfree) {
1271 gchar tmp[MAXLINE];
1272 gchar path[MAXLINE];
1273 GList *loop;
1274 gint free, getfree;
1275 gint maxfree;
1276
1277 /* get image-path */
1278 if (curset.image_index == -1) {
1279 strncpy(path,"",MAXLINE);
1280 } else {
1281 strncpy(path,(gchar *)g_list_nth_data(setupdata.image_dirs,
1282 curset.image_index), MAXLINE);
1283
1284 /* this dir writeable? */
1285 if (is_dir_writeable(path) == 1) {
1286 /* its not */
1287 *biggestfree = 0;
1288 return 0;
1289 }
1290 }
1291
1292 free = 0;
1293 maxfree = 0;
1294 if (strcmp(path,"") != 0) {
1295 free = get_free_space(path,NULL);
1296 maxfree = free;
1297 } else {
1298 /* automatic setting - add all available space */
1299 loop = g_list_first(setupdata.image_dirs);
1300 while(loop) {
1301 strncpy(tmp,(gchar *)loop->data,MAXLINE);
1302
1303 /* this dir writeable? */
1304 if (is_dir_writeable(tmp) == 1) {
1305 /* no? skip */
1306 loop = loop->next;
1307 continue;
1308 }
1309
1310 getfree = get_free_space(tmp,NULL);
1311 free += getfree;
1312 /* get biggest block */
1313 if (getfree > maxfree)
1314 maxfree = getfree;
1315 loop = loop->next;
1316 }
1317 }
1318
1319 if (free < 0) {
1320 g_warning("Invalid image-path setting?\n");
1321 free = 0;
1322 maxfree = 0;
1323 }
1324
1325 *biggestfree = maxfree;
1326 return free;
1327 }
1328
1329
1330 /* does look where to save the tracks before reading them.
1331 Checks available diskspace and the image-directory-settings.
1332 return 0 if ok, 1 on error/disk full, 2 if no writeable dir found */
1333 /* return 3 if we are about to overwrite a link */
1334 /* return via call by reference the size (in kbytes) that will be
1335 free due overwriting old files. Also return the freed size on
1336 the directory with the most space available */
1337
allocate_track_filenames(gint * overwrite,gint * overwritebiggest)1338 gint allocate_track_filenames(gint *overwrite, gint *overwritebiggest) {
1339 gchar tmp[MAXLINE];
1340 gchar biggestpath[MAXLINE];
1341 gchar path[MAXLINE];
1342 gchar ext[MAXLINE];
1343 track_read_param_t *trackparam;
1344 GList *loop, *loop2;
1345 gint free;
1346 gint size, tmpkbyte;
1347 gint ret;
1348 image_dir_free_t *freedir;
1349 GList *freedirs;
1350 struct stat buf;
1351 gint overwritefree, overwritefreebiggest;
1352 gint maxfree;
1353
1354 dodebug(10,"calling allocate_track_filenames\n");
1355
1356 overwritefree = 0;
1357 overwritefreebiggest = 0;
1358 ret = 0;
1359 freedirs = NULL;
1360 maxfree = 0;
1361 strcpy(biggestpath,"");
1362
1363 /* build image-path/free structure */
1364 if (curset.image_index == -1) {
1365 /* automatic setting */
1366 loop = g_list_first(setupdata.image_dirs);
1367 while(loop) {
1368 strncpy(path,(gchar *)loop->data,MAXLINE);
1369
1370 /* this dir writeable? */
1371 if (is_dir_writeable(path) == 1) {
1372 /* no? skip */
1373 loop = loop->next;
1374 continue;
1375 }
1376 free = get_free_space(path,NULL);
1377 freedir = g_new(image_dir_free_t,1);
1378 freedir->path = g_strdup(path);
1379 freedir->free = free;
1380 freedirs = g_list_append(freedirs,freedir);
1381
1382 /* path with biggest available block? */
1383 if (free > maxfree) {
1384 maxfree = free;
1385 strncpy(biggestpath,path,MAXLINE);
1386 }
1387 loop = loop->next;
1388 }
1389 /* no dirs writeable */
1390 if (freedirs == NULL) {
1391 *overwrite = 0;
1392 *overwritebiggest = 0;
1393 return 2;
1394 }
1395 } else {
1396 /* single path */
1397 strncpy(path,(gchar *)g_list_nth_data(setupdata.image_dirs,
1398 curset.image_index), MAXLINE);
1399 /* this dir writeable? */
1400 if (is_dir_writeable(path) == 1) {
1401 *overwrite = 0;
1402 *overwritebiggest = 0;
1403 return 2;
1404 }
1405 free = get_free_space(path,NULL);
1406 freedir = g_new(image_dir_free_t,1);
1407 freedir->path = g_strdup(path);
1408 freedir->free = free;
1409 freedirs = g_list_append(freedirs,freedir);
1410 maxfree = free;
1411 strncpy(biggestpath,path,MAXLINE);
1412 }
1413 /* now we have a structure with all path we are allowed to
1414 save data in and how much space is available there */
1415
1416 /* loop through all available tracks */
1417 loop = g_list_first(trackreadset.trackparams);
1418 while (loop) {
1419 trackparam = loop->data;
1420
1421 if (trackparam->tracktype == 0)
1422 strcpy(ext,"iso");
1423 else
1424 strcpy(ext,"wav");
1425
1426 /* how much space needs this track? */
1427 size = trackparam->kbyte;
1428
1429 strcpy(path,"");
1430
1431 /* where is enough space for it? */
1432 loop2 = g_list_first(freedirs);
1433 while (loop2) {
1434 freedir = loop2->data;
1435
1436 /* build temporary filename */
1437 g_snprintf(tmp,MAXLINE, "%s/%s-%02d.%s", freedir->path,
1438 curset.file_prefix,
1439 trackparam->starttrack, ext);
1440
1441 /* already a file with this name on hd? */
1442 if (stat(tmp,&buf) == 0) {
1443
1444 /* is a link? */
1445 if (check_islink(tmp, NULL)) {
1446 g_warning("Possibly overwriting a link at %s - not allowed.\n", tmp);
1447 return 3;
1448 }
1449
1450 /* file exists */
1451 tmpkbyte = (gint) ((off_t)buf.st_size >> 10);
1452 if (tmpkbyte == 0) {
1453 /* file smaller than one kb? */
1454 /* assume 1 kb then */
1455 tmpkbyte = 1;
1456 }
1457 overwritefree += tmpkbyte;
1458
1459 /* file in directory with most space? */
1460 if (strcmp(freedir->path,biggestpath) == 0) {
1461 overwritefreebiggest += tmpkbyte;
1462 }
1463 } else {
1464 tmpkbyte = 0;
1465 }
1466
1467 /* enough free? consider space that is freed
1468 when we overwrite a file (tmpkbyte) */
1469 if (size < (freedir->free + tmpkbyte)) {
1470 /* found freespace */
1471 strncpy(path,freedir->path,MAXLINE);
1472 freedir->free-=size - tmpkbyte;
1473 break;
1474 }
1475
1476 loop2 = loop2->next;
1477 }
1478
1479 /* no free space found? */
1480 if (strcmp(path,"") == 0) {
1481 /* mark we found an error */
1482 ret = 1;
1483 }
1484
1485 /* tmp does contain now our valid filename */
1486 g_free(trackparam->trackfile);
1487 trackparam->trackfile = g_strdup(tmp);
1488
1489 loop = loop->next;
1490 }
1491
1492 /* free image-path/free structure */
1493 loop2 = g_list_first(freedirs);
1494 while (loop2) {
1495 freedir = loop2->data;
1496 g_free(freedir->path);
1497 g_free(freedir);
1498 loop2 = loop2->next;
1499 }
1500 g_list_free(freedirs);
1501
1502 *overwrite = overwritefree;
1503 *overwritebiggest = overwritefreebiggest;
1504
1505 if (debug > 1) {
1506 print_trackreadset();
1507 }
1508
1509 return ret;
1510 }
1511
1512
1513 /* does scan the image-structure for toc-files.
1514 Takes current image-dir-setting into account. Return number
1515 of found toc files or 0. Newest file is on top */
1516
scan_for_toc_files()1517 gint scan_for_toc_files() {
1518 GList *loop;
1519 image_files_t *entry;
1520 gchar basename[MAXLINE];
1521 gchar ipath[MAXLINE];
1522 gchar *p;
1523 time_t fdate;
1524
1525 /* clear old list */
1526 g_list_free(tocfiles);
1527 tocfiles = NULL;
1528 fdate = 0;
1529
1530 loop = g_list_first(imagelist);
1531 while (loop) {
1532 entry = loop->data;
1533
1534 /* toc-file */
1535 if (entry->type == 4) {
1536
1537 /* get the basedir */
1538 strncpy(basename,entry->path,MAXLINE);
1539 p = rindex(basename,'/');
1540 *p = '\0';
1541 if (strcmp(basename,"") == 0) {
1542 strcpy(basename,"/");
1543 }
1544
1545 /* now check if the basedir fits in the currently
1546 set image-path */
1547 if (curset.image_index != -1) {
1548 strncpy(ipath, (gchar *)g_list_nth_data(
1549 setupdata.image_dirs,
1550 curset.image_index), MAXLINE);
1551
1552 /* does not fit - skip */
1553 if (strcmp(ipath, basename) != 0) {
1554 loop = loop->next;
1555 continue;
1556 }
1557 }
1558
1559 /* if new file newer than the old one */
1560 if (entry->mtime < fdate) {
1561 /* append at back */
1562 tocfiles = g_list_append(tocfiles,entry->path);
1563 } else {
1564 /* prepend at front */
1565 tocfiles = g_list_prepend(tocfiles,entry->path);
1566 fdate = entry->mtime;
1567 }
1568 }
1569
1570 loop = loop->next;
1571 }
1572
1573 return g_list_length(tocfiles);
1574 }
1575
1576
1577 /* this function is called whenever a dialog window idles on the screen
1578 and we want that events are processed and if there are no events
1579 no CPU-time is wasted */
1580
wait_and_process_events()1581 void wait_and_process_events() {
1582
1583 while (gtk_events_pending())
1584 gtk_main_iteration();
1585 usleep(100);
1586 }
1587
1588
1589 /* check if all files scheduled for writing does exist and have
1590 the right size. Return 0 if all ok, 1 if all files there but with
1591 wrong size, 2 if files missing and 3 if no permission to read/invalid,
1592 4 when audio files with wrong isrc or mcn found */
1593
check_write_files(gint nosizecheck)1594 gint check_write_files(gint nosizecheck) {
1595 GList *loop;
1596 track_read_param_t *trackparam;
1597 struct stat buf;
1598 off_t size;
1599 gint sumframes;
1600 gint fd;
1601 gint errsize, diff, invalidisrcmcn;
1602
1603 sumframes = 0;
1604 errsize = 0;
1605 invalidisrcmcn = 0;
1606 loop = g_list_first(trackreadset.trackparams);
1607 while(loop) {
1608 trackparam = loop->data;
1609
1610 if (stat(trackparam->trackfile, &buf) != 0) {
1611 /* no such file */
1612 return 2;
1613 }
1614
1615 /* check if regular file or link */
1616 if (S_ISLNK(buf.st_mode) != 1 && S_ISREG(buf.st_mode) != 1) {
1617 /* its not */
1618 return 3;
1619 }
1620
1621 /* readable for us? */
1622 fd = open(trackparam->trackfile, O_RDONLY,0);
1623 if (fd == -1) {
1624 return 3;
1625 } else {
1626 close(fd);
1627 }
1628
1629 if (trackparam->tracktype == 0) {
1630 /* datatrack */
1631 size = (off_t) ((off_t)trackparam->frames * DATASECTORSIZE);
1632 sumframes += trackparam->frames;
1633 } else {
1634 /* audiotrack */
1635
1636 /* check if ISRC/MCN info is valid */
1637 invalidisrcmcn += check_valid_isrc_mcn(trackparam->trackfile);
1638
1639 size = (off_t) ((off_t)trackparam->frames * CDDAFRAME);
1640 sumframes += trackparam->frames;
1641 }
1642
1643 /* check size of file - allow a offset of 4096 bytes */
1644 /* and offset of 152*2048 (leadout+runout sectors) */
1645 /* (and allow offset of 44 bytes (wavheader)) */
1646 diff = (gint) abs((off_t) size - (off_t) buf.st_size);
1647 if (diff != 0 && diff != 4096 && diff != 152*2048 && diff != 44) {
1648 /* a file with wrong size found? */
1649 errsize++;
1650 }
1651 loop = loop->next;
1652 }
1653 /* g_print("sumframes: %d\n", sumframes); */
1654
1655 if (invalidisrcmcn > 0) {
1656 return 4;
1657 }
1658
1659 if (errsize == 0 || nosizecheck) {
1660 /* all ok */
1661 return 0;
1662 } else {
1663 /* files with wrong sizes */
1664 return 1;
1665 }
1666 }
1667
1668
1669 /* correct any problem in an .inf file with an invalid ISRC or MCN number.
1670 Return 1 if there was a problem. (like permission denied) */
1671
clear_isrc_mcn_from_tracks()1672 gint clear_isrc_mcn_from_tracks() {
1673 GList *loop;
1674 track_read_param_t *trackparam;
1675 gint stat;
1676
1677 stat = 0;
1678 loop = g_list_first(trackreadset.trackparams);
1679 while(loop) {
1680 trackparam = loop->data;
1681
1682 if (check_valid_isrc_mcn(trackparam->trackfile)) {
1683 /* ok, thats one of the bad files */
1684 stat += clear_isrc_mcn_from_inffile(trackparam->trackfile);
1685 }
1686
1687 loop = loop->next;
1688 }
1689
1690 if (stat > 0) {
1691 return 1;
1692 } else {
1693 return 0;
1694 }
1695 }
1696
1697
1698 /* get the size of a track given by filename from imagelist (in bytes) */
1699 /* or -1 when not found */
1700
get_size_from_imagelist(gchar * tname)1701 off_t get_size_from_imagelist(gchar *tname) {
1702 GList *loop;
1703 image_files_t *entry;
1704
1705 loop = g_list_first(imagelist);
1706 while (loop) {
1707 entry = loop->data;
1708
1709 if (strcmp(tname,entry->path) == 0) {
1710 return ((off_t) entry->size);
1711 }
1712 loop = loop->next;
1713 }
1714
1715 return (off_t)-1;
1716 }
1717
1718
1719 /* get the type of a track given by filename from imagelist */
1720 /* or -1 when not found */
1721
get_type_from_imagelist(gchar * tname)1722 gint get_type_from_imagelist(gchar *tname) {
1723 GList *loop;
1724 image_files_t *entry;
1725
1726 loop = g_list_first(imagelist);
1727 while (loop) {
1728 entry = loop->data;
1729
1730 if (strcmp(tname,entry->path) == 0) {
1731 return (entry->type);
1732 }
1733 loop = loop->next;
1734 }
1735
1736 return -1;
1737 }
1738
1739
1740 /* get the number of a track given by filename from imagelist */
1741 /* or -1 when not found */
1742
get_tracknr_from_imagelist(gchar * tname)1743 gint get_tracknr_from_imagelist(gchar *tname) {
1744 GList *loop;
1745 image_files_t *entry;
1746
1747 loop = g_list_first(imagelist);
1748 while (loop) {
1749 entry = loop->data;
1750
1751 if (strcmp(tname,entry->path) == 0) {
1752 return (entry->from_track);
1753 }
1754 loop = loop->next;
1755 }
1756
1757 return -1;
1758 }
1759
1760
1761 /* get the msinfo values from imagelist */
1762
get_msinfo_from_imagelist(gchar * tname,gint * nr1,gint * nr2)1763 void get_msinfo_from_imagelist(gchar *tname, gint *nr1, gint *nr2) {
1764 GList *loop;
1765 image_files_t *entry;
1766
1767 loop = g_list_first(imagelist);
1768 while (loop) {
1769 entry = loop->data;
1770
1771 if (strcmp(tname,entry->path) == 0) {
1772
1773 *nr1 = entry->last_session_start;
1774 *nr2 = entry->next_session_start;
1775 }
1776 loop = loop->next;
1777 }
1778 }
1779
1780
get_entry_from_imagelist(gchar * tname)1781 image_files_t *get_entry_from_imagelist(gchar *tname) {
1782 GList *loop;
1783 image_files_t *entry;
1784
1785 loop = g_list_first(imagelist);
1786 while (loop) {
1787 entry = loop->data;
1788
1789 if (tname && strcmp(tname,entry->path) == 0) {
1790 return entry;
1791 }
1792 loop = loop->next;
1793 }
1794 return NULL;
1795 }
1796
1797
1798 /* get the discid of a track given by filename from imagelist */
1799 /* or 1 when not found */
1800
get_discid_from_imagelist(gchar * tname,gchar * ret)1801 gint get_discid_from_imagelist(gchar *tname, gchar *ret) {
1802 GList *loop;
1803 image_files_t *entry;
1804
1805 loop = g_list_first(imagelist);
1806 while (loop) {
1807 entry = loop->data;
1808
1809 if (strcmp(tname,entry->path) == 0) {
1810
1811 if (entry->cd_discid == NULL)
1812 return 1;
1813
1814 strcpy(ret, entry->cd_discid);
1815 return 0;
1816 }
1817 loop = loop->next;
1818 }
1819
1820 return 1;
1821 }
1822
1823
1824 /* get the volname of a track given by filename from imagelist */
1825 /* or 1 when not found */
1826
get_volname_from_imagelist(gchar * tname,gchar * ret)1827 gint get_volname_from_imagelist(gchar *tname, gchar *ret) {
1828 GList *loop;
1829 image_files_t *entry;
1830
1831 loop = g_list_first(imagelist);
1832 while (loop) {
1833 entry = loop->data;
1834
1835 if (strcmp(tname,entry->path) == 0) {
1836
1837 if (entry->volname == NULL)
1838 return 1;
1839
1840 strcpy(ret, entry->volname);
1841 return 0;
1842 }
1843 loop = loop->next;
1844 }
1845
1846 return 1;
1847 }
1848
1849
1850 /* is valid wav-file and in cd-quality? */
1851 /* return 1 if, 0 if not */
1852
check_wav_file(gchar * wavname)1853 gint check_wav_file(gchar *wavname) {
1854 gint fd;
1855
1856 fd = open (wavname, O_RDONLY, 0);
1857 if (fd == -1) {
1858 return 0;
1859 }
1860
1861 if (!is_std_wav_file(fd, NULL)) {
1862 /* no wav at all or not cd-quality */
1863 close(fd);
1864 return 0;
1865 }
1866
1867 /* passed all tests */
1868 close(fd);
1869 return 1;
1870 }
1871
1872
1873 /* small thing for iso-check */
1874
empty(gchar c)1875 static gint empty(gchar c) {
1876 return (c == 0 || c == ' ');
1877 }
1878
1879
1880 /* check if valid iso9660-image */
1881 /* return number of sectors if, 0 if not */
1882 /* if isoname set to NULL then query drive directly */
1883
check_iso_file(gint devnr,gchar * isoname,gchar * volid,gint startsec)1884 gint check_iso_file(gint devnr, gchar *isoname, gchar *volid, gint startsec) {
1885 gchar buf[DATASECTORSIZE];
1886 gchar tmp[MAXLINE];
1887 gchar c;
1888 gint i,j,k,count;
1889 gint volsize;
1890
1891 if (isoname != NULL) {
1892 /* read from file */
1893 if (read_info_sector_from_file(isoname,buf,sizeof(buf)) == 0) {
1894 return 0;
1895 }
1896 } else {
1897 /* read from device */
1898 if (read_info_sector_from_dev(devnr,buf,sizeof(buf), startsec) == 0) {
1899 return 0;
1900 }
1901 }
1902
1903 /* search iso9660-signature */
1904 if (strncmp(buf, "\001CD001\001", 8) != 0) {
1905 return 0;
1906 }
1907
1908 /* ok, we got an iso9660-image.
1909 As a bonus extract volumne-name if requested */
1910 if (volid != NULL) {
1911 count = 0;
1912 for(i = 40; i < 72; i++) {
1913 if (empty(buf[i]))
1914 continue;
1915 for (j = i+1; j < 72; j++) {
1916 if (!buf[j] || (j < 72-1
1917 && empty(buf[j]) && empty(buf[j+1])))
1918 break;
1919 }
1920 for (k = i; k < j; k++) {
1921 c = buf[k];
1922 if (isprint((gint)c) || isspace((gint)c)) {
1923 tmp[count++] = c;
1924 }
1925 }
1926 i = j;
1927 }
1928 tmp[count] = '\0';
1929 strcpy(volid,tmp);
1930 }
1931
1932 /* now also extract the size of the image */
1933 volsize = ((buf[80] & 0xff) |
1934 ((buf[81] & 0xff) << 8) |
1935 ((buf[82] & 0xff) << 16) |
1936 ((buf[83] & 0xff) << 24));
1937
1938 return volsize;
1939 }
1940
1941
1942 /* get cd toc and do read the iso9660-volid if possible */
1943
get_cd_toc_and_volid(gint devnr)1944 void get_cd_toc_and_volid(gint devnr) {
1945 gint i, volsize;
1946 gchar tmp[MAXLINE];
1947 GtkWidget *tmpdialog;
1948
1949 /* create dialog, just to grab the focus on it and make
1950 xcdroast not longer "clickable" */
1951 tmpdialog = my_gtk_dialog_new();
1952 gtk_grab_add(tmpdialog);
1953
1954 get_cd_toc(devnr);
1955
1956 gtk_grab_remove(GTK_WIDGET(tmpdialog));
1957 gtk_widget_destroy(tmpdialog);
1958
1959 /* no cd loaded? */
1960 if (cdinfo.nr_tracks <= 0) {
1961 return;
1962 }
1963 strcpy(tmp,"");
1964
1965 /* scan every data track */
1966 #ifdef SCANEVERYTRACK
1967 for (i = 0; i < cdinfo.nr_tracks; i++) {
1968 #else
1969 for (i = 0; i < 1; i++) {
1970 #endif
1971
1972 if (trackinfo[i]->type == 0) {
1973 /* get iso-header for current track */
1974 strcpy(tmp,"");
1975 volsize = check_iso_file(devnr, NULL, tmp,
1976 trackinfo[i]->start_sec);
1977 if (strcmp(tmp,"") != 0) {
1978 g_free(trackinfo[i]->volname);
1979 trackinfo[i]->volname = g_strdup(tmp);
1980 }
1981 trackinfo[i]->isosize = volsize;
1982 }
1983 }
1984
1985 /* now set disk-title to iso9660-volname because thats all we
1986 got at the moment */
1987
1988 /* last label still in buffer? */
1989 if (strcmp(tmp,"") != 0) {
1990 /* now check we have currently another title */
1991 if (cdinfo.cddb_dtitle == NULL) {
1992 /* no? then use iso-header as title */
1993 cdinfo.cddb_dtitle = g_strdup(tmp);
1994 }
1995 }
1996 }
1997
1998
1999 /* do output debug messages */
2000
2001 void dodebug(gint debuglevel, gchar *fmt, ...) {
2002 va_list ap;
2003 gchar tmp[MAXLINE*21];
2004 gchar *p;
2005 guint i;
2006
2007 /* output message when debuglevel is high enough */
2008 if (debuglevel <= debug) {
2009
2010 /* put together the variable argument list */
2011 va_start(ap,fmt);
2012 vsprintf(tmp, fmt, ap);
2013 va_end(ap);
2014
2015 /* remove first linefeed if any */
2016 p = index(tmp,'\r');
2017 if (p != NULL)
2018 *p = ' ';
2019
2020 /* remove \b if any */
2021 for (i = 0; i < strlen(tmp); i++) {
2022 if (tmp[i] == '\b') {
2023 tmp[i] = ' ';
2024 }
2025 }
2026
2027 fprintf(stderr,"DGB%d: %s",debuglevel,tmp);
2028 }
2029 }
2030
2031
2032 /* do write to logfile */
2033
2034 void dolog(gint loglevel, gchar *fmt, ...) {
2035 va_list ap;
2036 gchar tmp[MAXLINE*21]; /* two buffers up to 10k plus saveguard */
2037 gchar tmp2[MAXLINE];
2038 char timestr[MAXLINE];
2039 time_t acttime;
2040 FILE *lfile;
2041
2042 /* output message when loglevel is high enough */
2043 if (loglevel <= setupdata.loglevel && strcmp(setupdata.logfile,"")) {
2044
2045 /* put together the variable argument list */
2046 va_start(ap,fmt);
2047 vsprintf(tmp, fmt, ap);
2048 va_end(ap);
2049
2050 acttime = time((time_t *) 0);
2051 strncpy(timestr,ctime(&acttime),MAXLINE);
2052
2053 /* remove last \n from timestr */
2054 timestr[strlen(timestr)-1] = 0;
2055
2056 strncpy(tmp2, setupdata.logfile,MAXLINE);
2057 check_tilde(tmp2);
2058
2059 lfile = fopen(tmp2,"a");
2060
2061 if (lfile == NULL) {
2062 g_warning("Can't open logfile %s for writing\n",
2063 tmp2);
2064 return;
2065 }
2066
2067 if (!fprintf(lfile,"%s XCDR %s: %s", timestr,
2068 XCDROAST_VERSION, tmp)) {
2069 g_warning("Error appending to logfile\n");
2070 }
2071 fclose(lfile);
2072 }
2073 }
2074
2075
2076 /* notify-beep function */
2077 /* type: 1 = completed task, 2 = warnings */
2078
2079 void dobeep(gint type) {
2080 gint doit;
2081
2082 doit = 0;
2083
2084 switch (setupdata.notify_at) {
2085 case 0:
2086 /* we want no beep */
2087 return;
2088
2089 case 1:
2090 /* always */
2091 doit = 1;
2092 break;
2093 case 2:
2094 /* on completion */
2095 if (type == 1)
2096 doit = 1;
2097 break;
2098 case 3:
2099 /* warnings only */
2100 if (type == 2)
2101 doit = 1;
2102 break;
2103 default:
2104 return;
2105 }
2106
2107 /* ok..we have to play a sound */
2108 if (doit == 1) {
2109 if (setupdata.notify_via == 0) {
2110 /* dspdevice */
2111 if (strcmp(setupdata.dsp_device,"") != 0) {
2112 test_dspdevice_play();
2113 }
2114 } else {
2115 /* internal speaker */
2116 gdk_beep();
2117 }
2118 }
2119 }
2120
2121
2122 /* check if the image-dirs fit to our partitions */
2123 /* return 0 if ok, 1 when there were errors (and we edited the list) */
2124
2125 gint verify_loaded_config2 () {
2126 GList *loop, *loop2;
2127 GList *fslist;
2128 gchar dir[MAXLINE];
2129 gchar fs[MAXLINE];
2130 gint free;
2131 gint fsuse;
2132 gint dirsok;
2133
2134 /* now check if all the loaded image-dir exists and are each on
2135 a own partition */
2136
2137 fslist = NULL;
2138 dirsok = 0;
2139 loop = g_list_first(setupdata.image_dirs);
2140 while (loop) {
2141 strncpy(dir,(gchar *)loop->data,MAXLINE);
2142 /* get filesystem for this dir */
2143 free = get_free_space(dir,fs);
2144 if (free == -1) {
2145 /* no such directory */
2146 /* mark to remove this entry from the list...*/
2147 g_free(loop->data);
2148 loop->data = NULL;
2149 dirsok = 1;
2150 } else {
2151 /* check if this dir is already in use */
2152 /* if not, add to fs-list */
2153 fsuse = 0;
2154 loop2 = g_list_first(fslist);
2155 while (loop2) {
2156 if (strcmp(fs, (gchar *)loop2->data) == 0) {
2157 fsuse = 1;
2158 }
2159 loop2 = loop2->next;
2160 }
2161 if (fsuse == 0) {
2162 /* not already used */
2163 fslist = g_list_append(fslist, g_strdup(fs));
2164 } else {
2165 /* remove this entry from list */
2166 g_free(loop->data);
2167 loop->data = NULL;
2168 dirsok = 1;
2169 }
2170 }
2171
2172 loop = loop->next;
2173 }
2174
2175 /* free our temporary list */
2176 free_glist(&fslist);
2177
2178 /* now really remove the marked dirs from list */
2179 loop = g_list_first(setupdata.image_dirs);
2180 while (loop) {
2181 loop2 = loop->next;
2182 if (loop->data == NULL) {
2183 setupdata.image_dirs =
2184 g_list_remove_link(setupdata.image_dirs, loop);
2185 }
2186 loop = loop2;
2187 }
2188
2189 return dirsok;
2190 }
2191
2192
2193 /* check if this track match the inserted cd (verify tracks) */
2194 /* return 0 if all ok, 1 on some error, 2 if file does not match to cd
2195 and 3 if we dont want verify audio (checking for readable not necessary
2196 because unreadable tracks are not displayed in verify menu */
2197
2198 gint check_vrfy_track(gchar *fname) {
2199 gchar tmp[MAXLINE];
2200
2201 /* get the discid */
2202 if (get_discid_from_imagelist(fname,tmp) != 0) {
2203 /* no discid found in info-file? */
2204 return 1;
2205 }
2206
2207 /* compare with current cd */
2208 if (strcmp(tmp, cdinfo.cddb_discid) != 0) {
2209 return 2;
2210 }
2211
2212 /* check if its an audio track and we want to verify them */
2213 if (curset.noaudioverify == 1 &&
2214 get_type_from_imagelist(fname) == 1) {
2215 return 3;
2216 }
2217 /* all ok */
2218 return 0;
2219 }
2220
2221
2222 /* build a trackname for image-lists */
2223
2224 void assign_trackname(gchar *titlestr, image_files_t *entry) {
2225
2226 /* see if there is cd text for this track */
2227 if (entry->title && entry->artist &&
2228 strcmp(entry->title,"") && strcmp(entry->artist,"")) {
2229 g_snprintf(titlestr,MAXLINE,"%s / %s",
2230 entry->title, entry->artist);
2231 } else
2232 if (entry->title && strcmp(entry->title,"")) {
2233 strcpy(titlestr, entry->title);
2234 } else
2235 if (entry->cddb_ttitle && strcmp(entry->cddb_ttitle,"")) {
2236 strcpy(titlestr, entry->cddb_ttitle);
2237 } else
2238 if (entry->volname && strcmp(entry->volname,"")) {
2239 g_snprintf(titlestr,MAXLINE,"%s / ISO9660",
2240 entry->volname);
2241 }
2242 }
2243
2244
2245 /* check if a filename is on the writelist */
2246
2247 gint is_on_writelist(gchar *file) {
2248 GList *loop;
2249 gchar *track;
2250
2251 loop = g_list_first(writelist);
2252 while (loop) {
2253 track = loop->data;
2254 if (track && strcmp(track, file) == 0) {
2255 return 1;
2256 }
2257 loop = loop->next;
2258 }
2259 return 0;
2260 }
2261
2262
2263 /* free trackreadset */
2264
2265 void clear_trackreadset() {
2266 GList *loop;
2267 track_read_param_t *trackparam;
2268
2269 loop = g_list_first(trackreadset.trackparams);
2270 while (loop) {
2271 trackparam = loop->data;
2272 g_free(trackparam->trackfile);
2273 g_free(trackparam);
2274 loop = loop->next;
2275 }
2276 if (trackreadset.trackparams)
2277 g_list_free(trackreadset.trackparams);
2278 trackreadset.trackparams = NULL;
2279 g_free(trackreadset.tocfile);
2280 trackreadset.tocfile = g_strdup("");
2281 g_free(trackreadset.cdtitle);
2282 trackreadset.cdtitle = g_strdup("");
2283 g_free(trackreadset.cd_discid);
2284 trackreadset.cd_discid = g_strdup("");
2285 trackreadset.nrtracks = 0;
2286 trackreadset.cdsize = 0;
2287 }
2288
2289
2290 /* transform coordinates when bigfonts are used */
2291
2292 gint tbf(gint koord) {
2293
2294 if (bigfonts == 1) {
2295 return (koord * XCDR_TOPLEVEL_X1)/XCDR_TOPLEVEL_X0;
2296 } else {
2297 return koord;
2298 }
2299 }
2300
2301
2302 /* sort a glist of strings */
2303
2304 void sort_glist(GList *filelist) {
2305 GList *first, *last, *list1, *list2;
2306 gchar *str1, *str2, *str3;
2307
2308 first = g_list_first(filelist);
2309 last = g_list_last(filelist);
2310 for (list1 = first; list1 != last; list1 = list1->next) {
2311 for (list2 = last; list2 != list1; list2 = list2->prev) {
2312 str1 = (gchar *) list1->data;
2313 str2 = (gchar *) list2->data;
2314
2315 if (strcmp (str1, str2) > 0) {
2316 str3 = str1;
2317 list1->data = list2->data;
2318 list2->data = str3;
2319 }
2320 }
2321 }
2322 }
2323
2324
2325 /* sort a glist of integers */
2326
2327 void sort_int_glist(GList *intlist) {
2328 GList *first, *last, *list1, *list2;
2329 gint int1, int2, int3;
2330
2331 first = g_list_first(intlist);
2332 last = g_list_last(intlist);
2333 for (list1 = first; list1 != last; list1 = list1->next) {
2334 for (list2 = last; list2 != list1; list2 = list2->prev) {
2335 int1 = GPOINTER_TO_INT(list1->data);
2336 int2 = GPOINTER_TO_INT(list2->data);
2337
2338 if (int1 > int2) {
2339 int3 = int1;
2340 /*
2341 GPOINTER_TO_INT(list1->data) =
2342 GPOINTER_TO_INT(list2->data);
2343 GPOINTER_TO_INT(list2->data) = int3;
2344 */
2345 list1->data = list2->data;
2346 list2->data = GINT_TO_POINTER(int3);
2347 }
2348 }
2349 }
2350 }
2351
2352
2353 /* determine path for helper apps */
2354
2355 void get_spawn_path(gchar *app, gchar *ret) {
2356 struct stat buf;
2357
2358 /* when path is with a leading slash (absolute), do nothing */
2359 if (app[0] == '/') {
2360 strcpy(ret,app);
2361 return;
2362 }
2363
2364 /* otherwise its relative - add sharedir first */
2365 g_snprintf(ret,MAXLINE,"%s/%s", sharedir, app);
2366
2367 /* now check if this file does exist */
2368 if (stat(ret,&buf) != 0) {
2369 /* it does not, so try the fallback */
2370 g_snprintf(ret,MAXLINE,"%s/%s", prefixdir, app);
2371 }
2372 return;
2373 }
2374
2375
2376 /* reroute a command through the wrapper */
2377 /* cmd is one of "CDRECORD", "MKISOFS", "CDDA2WAV", "READCD"
2378 or "CDRECORDPRODVD" */
2379
2380 gchar *get_wrap_path(gchar *cmd, gchar *ret) {
2381 gchar tmp[MAXLINE];
2382
2383 g_snprintf(tmp,MAXLINE,"%s/%s %s", sharedir, WRAPPER, cmd);
2384 strncpy(ret, tmp, MAXLINE);
2385
2386 return ret;
2387 }
2388
2389 /* reroute the cdrecord command through the wrapper */
2390
2391 gchar *get_wrap_path_cdrecord(gchar *ret) {
2392 gchar tmp[MAXLINE];
2393
2394 g_snprintf(tmp,MAXLINE,"%s/%s %s", sharedir, WRAPPER,
2395 "CDRECORD");
2396 strncpy(ret, tmp, MAXLINE);
2397
2398 return ret;
2399 }
2400
2401
2402 /* returns the gracetime to use */
2403
2404 gint get_gracetime() {
2405
2406 if (curset.isProDVD && curset.cdrtype > 1000) {
2407 /* use 10 seconds for prodvd, because the keycheck
2408 can take a while... */
2409 return 10;
2410 } else {
2411 /* for normal version 2 seconds is enough */
2412 return 2;
2413 }
2414 }
2415
2416
2417 /* find a path with enough space to save a mkisofs-image */
2418 /* return 0 if found, 1 on error/disk-full, return 2 if no writeable dir */
2419 /* return 3 if we would overwrite a link -> possible exploitable */
2420 /* size is given in kbyte */
2421 /* return via call by reference the size (in kbytes) that will be
2422 free due overwriting old files. Also return the freed size on
2423 the directory with the most space available */
2424
2425 gint allocate_master_filename(gint size, gint nr, gchar **return_fname,
2426 gint *overwrite, gint *overwritebiggest) {
2427 gchar tmp[MAXLINE];
2428 gchar biggestpath[MAXLINE];
2429 gchar path[MAXLINE];
2430 GList *freedirs;
2431 struct stat buf;
2432 GList *loop, *loop2;
2433 image_dir_free_t *freedir;
2434 gint free,maxfree,tmpkbyte;
2435 gint overwritefree, overwritefreebiggest;
2436 gint ret;
2437
2438 overwritefree = 0;
2439 overwritefreebiggest = 0;
2440 ret = 0;
2441 freedirs = NULL;
2442 maxfree = 0;
2443 strcpy(biggestpath,"");
2444
2445 /* build image-path/free structure */
2446 if (curset.image_index == -1) {
2447 /* automatic setting */
2448 loop = g_list_first(setupdata.image_dirs);
2449 while(loop) {
2450 strncpy(path,(gchar *)loop->data, MAXLINE);
2451
2452 /* this dir writeable? */
2453 if (is_dir_writeable(path) == 1) {
2454 /* no? skip */
2455 loop = loop->next;
2456 continue;
2457 }
2458 free = get_free_space(path,NULL);
2459 freedir = g_new(image_dir_free_t,1);
2460 freedir->path = g_strdup(path);
2461 freedir->free = free;
2462 freedirs = g_list_append(freedirs,freedir);
2463
2464 /* path with biggest available block? */
2465 if (free > maxfree) {
2466 maxfree = free;
2467 strncpy(biggestpath,path,MAXLINE);
2468 }
2469 loop = loop->next;
2470 }
2471 /* no dirs writeable */
2472 if (freedirs == NULL) {
2473 *overwrite = 0;
2474 *overwritebiggest = 0;
2475 return 2;
2476 }
2477 } else {
2478 /* single path */
2479 strncpy(path,(gchar *)g_list_nth_data(setupdata.image_dirs,
2480 curset.image_index), MAXLINE);
2481
2482 /* this dir writeable? */
2483 if (is_dir_writeable(path) == 1) {
2484 *overwrite = 0;
2485 *overwritebiggest = 0;
2486 return 2;
2487 }
2488 free = get_free_space(path,NULL);
2489 freedir = g_new(image_dir_free_t,1);
2490 freedir->path = g_strdup(path);
2491 freedir->free = free;
2492 freedirs = g_list_append(freedirs,freedir);
2493 maxfree = free;
2494 strncpy(biggestpath,path,MAXLINE);
2495 }
2496 /* now we have a structure with all path we are allowed to
2497 save data in and how much space is available there */
2498
2499 strcpy(path,"");
2500
2501 /* look in which path we have space */
2502 loop2 = g_list_first(freedirs);
2503 while (loop2) {
2504 freedir = loop2->data;
2505
2506 /* build temporary filename */
2507 g_snprintf(tmp,MAXLINE, "%s/%s-%02d.%s", freedir->path,
2508 curset.file_prefix, nr, "iso");
2509
2510 /* already a file with this name on hd? */
2511 if (stat(tmp,&buf) == 0) {
2512
2513 /* is a link? */
2514 if (check_islink(tmp, NULL)) {
2515 g_warning("Possibly overwriting a link at %s - not allowed.\n", tmp);
2516 return 3;
2517 }
2518
2519 /* file exists */
2520 tmpkbyte = (gint) ((off_t)buf.st_size >> 10);
2521 if (tmpkbyte == 0) {
2522 /* file smaller than one kb? */
2523 /* assume 1 kb then */
2524 tmpkbyte = 1;
2525 }
2526 overwritefree += tmpkbyte;
2527
2528 /* file in directory with most space? */
2529 if (strcmp(freedir->path,biggestpath) == 0) {
2530 overwritefreebiggest += tmpkbyte;
2531 }
2532 } else {
2533 tmpkbyte = 0;
2534 }
2535
2536 /* enough free? consider space that is freed
2537 when we overwrite a file (tmpkbyte) */
2538 if (size < (freedir->free + tmpkbyte)) {
2539 /* found freespace */
2540 strncpy(path,freedir->path,MAXLINE);
2541 freedir->free-=size - tmpkbyte;
2542 break;
2543 }
2544 loop2 = loop2->next;
2545 }
2546
2547 /* no free space found? */
2548 if (strcmp(path,"") == 0) {
2549 ret = 1;
2550 dodebug(1,"allocate_master_filename: no free space\n");
2551 } else {
2552 /* found a file */
2553 if (return_fname != NULL) {
2554 g_free(*return_fname);
2555 *return_fname = g_strdup(tmp);
2556 }
2557 dodebug(1,"allocate_master_filename: got %s\n", tmp);
2558 }
2559
2560 /* free image-path/free structure */
2561 loop2 = g_list_first(freedirs);
2562 while (loop2) {
2563 freedir = loop2->data;
2564 g_free(freedir->path);
2565 g_free(freedir);
2566 loop2 = loop2->next;
2567 }
2568 g_list_free(freedirs);
2569
2570 *overwrite = overwritefree;
2571 *overwritebiggest = overwritefreebiggest;
2572
2573 return ret;
2574 }
2575
2576
2577 /* checks if the current writer does support SANYO burnproof or something
2578 like that */
2579
2580 gint does_support_burnproof(gint devnr) {
2581 gint i;
2582 gchar *flags;
2583
2584 i = get_writerreaderdevs_index(devnr);
2585 if (i == -1)
2586 return 0;
2587
2588 flags = writerreaderdevs[i]->writer_flags;
2589 if (!flags)
2590 return 0;
2591
2592 if (strstr(flags,"BURNFREE"))
2593 return 1;
2594
2595 return 0;
2596 }
2597
2598 /* checks if the current writer does support Plextor VariRec */
2599
2600 gint does_support_varirec(gint devnr) {
2601 gint i;
2602 gchar *flags;
2603
2604 i = get_writerreaderdevs_index(devnr);
2605 if (i == -1)
2606 return 0;
2607
2608 flags = writerreaderdevs[i]->writer_flags;
2609 if (!flags)
2610 return 0;
2611
2612 if (strstr(flags,"VARIREC"))
2613 return 1;
2614
2615 return 0;
2616 }
2617
2618 /* checks if the current writer does support Yamaha audiomaster */
2619
2620 gint does_support_audiomaster(gint devnr) {
2621 gint i;
2622 gchar *flags;
2623
2624 i = get_writerreaderdevs_index(devnr);
2625 if (i == -1)
2626 return 0;
2627
2628 flags = writerreaderdevs[i]->writer_flags;
2629 if (!flags)
2630 return 0;
2631
2632 if (strstr(flags,"AUDIOMASTER"))
2633 return 1;
2634
2635 return 0;
2636 }
2637
2638 /* checks if the current writer does support forcespeed */
2639
2640 gint does_support_forcespeed(gint devnr) {
2641 gint i;
2642 gchar *flags;
2643
2644 i = get_writerreaderdevs_index(devnr);
2645 if (i == -1)
2646 return 0;
2647
2648 flags = writerreaderdevs[i]->writer_flags;
2649 if (!flags)
2650 return 0;
2651
2652 if (strstr(flags,"FORCESPEED"))
2653 return 1;
2654
2655 return 0;
2656 }
2657
2658
2659 /* check if a given group-id matches a groupname */
2660
2661 gint match_group_name(gid_t gid, gchar *group) {
2662 struct group *grp;
2663
2664 /* get structure containing name of group */
2665 grp = getgrgid(gid);
2666
2667 if (grp && grp->gr_name) {
2668 dodebug(3,"Matching gid = %d (%s)\n", gid, grp->gr_name);
2669 if (strncmp(grp->gr_name,group,strlen(group)) == 0) {
2670 /* does match */
2671 return 1;
2672 }
2673 }
2674 return 0;
2675 }
2676
2677
2678 /* return string with group name */
2679
2680 void return_group_name(gid_t gid, gchar *ret) {
2681 struct group *grp;
2682
2683 /* get structure containing name of group */
2684 grp = getgrgid(gid);
2685
2686 if (grp && grp->gr_name) {
2687 strncpy(ret,grp->gr_name,MAXLINE);
2688 return;
2689 }
2690
2691 /* unable to get grp name? return id as text */
2692 g_snprintf(ret,MAXLINE,"%d", (gint) gid);
2693 return;
2694 }
2695
2696
2697 /* return string with username name */
2698
2699 void return_user_name(uid_t uid, gchar *ret) {
2700 struct passwd *pw;
2701
2702 pw = getpwuid(uid);
2703
2704 if (pw && pw->pw_name) {
2705 strncpy(ret,pw->pw_name,MAXLINE);
2706 return;
2707 }
2708
2709 /* unable to get grp name? return id as text */
2710 g_snprintf(ret,MAXLINE,"%d", (gint) uid);
2711 return;
2712 }
2713
2714
2715 /* return 1 if a group exists (by group name) */
2716
2717 gint check_group_exists(gchar *name) {
2718 struct group *grp;
2719
2720 grp = getgrnam(name);
2721
2722 if (grp)
2723 return 1;
2724 else
2725 return 0;
2726 }
2727
2728
2729 /* parse the alternate device string (if any) */
2730
2731 void parse_alt_devs(gchar *str) {
2732 gint i;
2733 gchar *p;
2734 gchar tmp[MAXLINE];
2735
2736 /* allocate memory */
2737 alt_scsidevices = g_new0(gchar *,MAXDEVICES);
2738 i = 0;
2739
2740 if (str == NULL) {
2741 /* no devices, return */
2742 return;
2743 }
2744
2745 dodebug(2,"----- list of manually choosen device names -----\n");
2746
2747 /* get list of devices */
2748 p = strtok(str,";");
2749 while (p) {
2750 strncpy(tmp,p,MAXLINE);
2751 strip_string(tmp);
2752
2753 alt_scsidevices[i] = g_strdup(tmp);
2754 dodebug(2,"alt_device: %d - \"%s\"\n",i, tmp);
2755
2756 p = strtok(NULL,";");
2757 i++;
2758 if (i >= MAXDEVICES) {
2759 g_error("Error: More than %d devices given\n",MAXDEVICES);
2760 }
2761 }
2762
2763 return;
2764 }
2765
2766
2767 /* return the path to the chmod command */
2768
2769 void get_chmod_cmd(gchar *cmd) {
2770 struct stat buf;
2771 gchar tmp[MAXLINE], tmp2[MAXLINE];
2772 gchar *p1;
2773
2774 /* if path is set absolute dont search for it */
2775 strncpy(tmp, CHMOD, MAXLINE);
2776 if (tmp[0] == '/') {
2777 if (stat(CHMOD,&buf) == 0) {
2778 strncpy(cmd, CHMOD, MAXLINE);
2779 } else {
2780 strcpy(cmd,"");
2781 }
2782 return;
2783 }
2784
2785 strncpy(tmp,CHOWNGRPMOD_PATH,MAXLINE);
2786
2787 /* loop through path and try each one */
2788 p1 = strtok(tmp,":");
2789 while (p1) {
2790 g_snprintf(tmp2,MAXLINE,"%s/%s", p1, CHMOD);
2791 if (stat(tmp2,&buf) == 0) {
2792 strncpy(cmd, tmp2, MAXLINE);
2793 return;
2794 }
2795 p1 = strtok(NULL,":");
2796 }
2797
2798 /* not found */
2799 strcpy(cmd,"");
2800 return;
2801 }
2802
2803
2804 /* return the path to the chgrp command */
2805
2806 void get_chgrp_cmd(gchar *cmd) {
2807 struct stat buf;
2808 gchar tmp[MAXLINE], tmp2[MAXLINE];
2809 gchar *p1;
2810
2811 /* if path is set absolute dont search for it */
2812 strncpy(tmp, CHGRP, MAXLINE);
2813 if (tmp[0] == '/') {
2814 if (stat(CHGRP,&buf) == 0) {
2815 strncpy(cmd, CHGRP, MAXLINE);
2816 } else {
2817 strcpy(cmd,"");
2818 }
2819 return;
2820 }
2821
2822 strncpy(tmp,CHOWNGRPMOD_PATH,MAXLINE);
2823
2824 /* loop through path and try each one */
2825 p1 = strtok(tmp,":");
2826 while (p1) {
2827 g_snprintf(tmp2,MAXLINE,"%s/%s", p1, CHGRP);
2828 if (stat(tmp2,&buf) == 0) {
2829 strncpy(cmd, tmp2, MAXLINE);
2830 return;
2831 }
2832 p1 = strtok(NULL,":");
2833 }
2834
2835 /* not found */
2836 strcpy(cmd,"");
2837 return;
2838 }
2839
2840
2841 /* return the path to the chown command */
2842
2843 void get_chown_cmd(gchar *cmd) {
2844 struct stat buf;
2845 gchar tmp[MAXLINE], tmp2[MAXLINE];
2846 gchar *p1;
2847
2848 /* if path is set absolute dont search for it */
2849 strncpy(tmp, CHOWN, MAXLINE);
2850 if (tmp[0] == '/') {
2851 if (stat(CHOWN,&buf) == 0) {
2852 strncpy(cmd, CHOWN, MAXLINE);
2853 } else {
2854 strcpy(cmd,"");
2855 }
2856 return;
2857 }
2858
2859 strncpy(tmp,CHOWNGRPMOD_PATH,MAXLINE);
2860
2861 /* loop through path and try each one */
2862 p1 = strtok(tmp,":");
2863 while (p1) {
2864 g_snprintf(tmp2,MAXLINE,"%s/%s", p1, CHOWN);
2865 if (stat(tmp2,&buf) == 0) {
2866 strncpy(cmd, tmp2, MAXLINE);
2867 return;
2868 }
2869 p1 = strtok(NULL,":");
2870 }
2871
2872 /* not found */
2873 strcpy(cmd,"");
2874 return;
2875 }
2876
2877
2878 /* allocate an entry in the nonrootval-list */
2879
2880 void add_to_nonrootvalues(GList **list, gchar *path, gint uid, gint gid, gint mode) {
2881 nonroot_flags_t *entry;
2882
2883 entry = g_new0(nonroot_flags_t, 1);
2884 if (entry) {
2885 entry->path = g_strdup(path);
2886 entry->uid = (uid_t)uid;
2887 entry->gid = (gid_t)gid;
2888 entry->mode = (mode_t)mode;
2889
2890 *list = g_list_append(*list, entry);
2891 }
2892 }
2893
2894
2895 /* free the nonrootvalues glist */
2896
2897 void free_nonrootvalues(GList **list) {
2898 GList *loop;
2899 nonroot_flags_t *entry;
2900
2901 loop = g_list_first(*list);
2902 while(loop) {
2903 entry = (nonroot_flags_t *)loop->data;
2904 g_free(entry->path);
2905 g_free(entry);
2906
2907 loop = loop->next;
2908 }
2909 g_list_free(*list);
2910 *list = NULL;
2911 }
2912
2913
2914 /* split the DTITLE line from cddb to artist and title */
2915
2916 void get_artist_and_title_from_cddb(gchar *dtitle, gchar *artist, gchar *title) {
2917 gchar *p;
2918 gint len;
2919
2920 p = index(dtitle, '/');
2921 if (p) {
2922 len = p - dtitle;
2923 if (len > MAXLINE)
2924 len = MAXLINE;
2925 strncpy(title, dtitle,len);
2926 title[len] = '\0';
2927 strip_string(title);
2928
2929 strncpy(artist, p+1, MAXLINE);
2930 strip_string(artist);
2931 } else {
2932 strncpy(title, dtitle, MAXLINE);
2933 strip_string(title);
2934 strcpy(artist,"");
2935 }
2936 }
2937
2938
2939 /* switch artist <-> title in a cddb string */
2940
2941 void switch_artist_title(gchar *dtitle) {
2942 gchar title[MAXLINE];
2943 gchar artist[MAXLINE];
2944
2945 get_artist_and_title_from_cddb(dtitle, title, artist);
2946 g_snprintf(dtitle, MAXLINE, "%s / %s", title, artist);
2947 }
2948
2949
2950 /* open the xinf-file for the given track and extract artist and title */
2951 /* fallback to cddb if no title given */
2952
2953 void get_title_artist_from_xinf(gchar *file, gchar *artist, gchar *title) {
2954 image_files_t *entry;
2955
2956 entry = g_new(image_files_t,1);
2957 entry->path = NULL;
2958 entry->volname = NULL;
2959 entry->title = NULL;
2960 entry->artist = NULL;
2961 entry->cddb_ttitle = NULL;
2962 entry->cd_discid = NULL;
2963
2964 /* open file and extract data */
2965 get_inf_tracktitle(file, entry);
2966
2967 if (entry->title && *entry->title) {
2968 strncpy(title, entry->title, MAXLINE);
2969 } else {
2970 /* try cddb title */
2971 if (entry->cddb_ttitle) {
2972 strncpy(title, entry->cddb_ttitle, MAXLINE);
2973 }
2974 }
2975 if (entry->artist) {
2976 strncpy(artist, entry->artist, MAXLINE);
2977 }
2978
2979 /* free entry again */
2980 g_free(entry->path);
2981 g_free(entry->volname);
2982 g_free(entry->title);
2983 g_free(entry->artist);
2984 g_free(entry->cddb_ttitle);
2985 g_free(entry->cd_discid);
2986 g_free(entry);
2987 }
2988
2989
2990 /* returns a file name for the tocfile used in the write-tracks dialog */
2991
2992 void generate_tmp_tocfile_name(gchar *tocfile) {
2993
2994 g_snprintf(tocfile, MAXLINE, "%s/xcdr-wrtrk-%d.ttoc",
2995 TMP_XCDR_DIR, (gint) getpid());
2996 }
2997
2998
2999 /* returns a prefix used in the copy audio on-the-fly dialog */
3000
3001 void generate_tmp_prefix_name(gchar *tmpprefix) {
3002
3003 g_snprintf(tmpprefix, MAXLINE, "%s/xcdr-tmp-%d",
3004 TMP_XCDR_DIR, (gint) getpid());
3005 }
3006
3007
3008 /* returns a unique filenames that is not in use yet */
3009 /* or empty string on error */
3010
3011 void generate_tmp_file_name(gchar *ext, gchar *file1) {
3012 gchar randchars[] = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
3013 gint i, done, length, count, ind;
3014 gchar tmp[MAXLINE];
3015 gchar fname[MAXLINE];
3016 struct stat buf;
3017
3018 done = 0;
3019 count = 0;
3020 length = strlen(randchars);
3021
3022 /* try 10 times to get a unique filename..then give up */
3023 while (count < 10) {
3024 /* gen random string */
3025 for (i = 0; i < 4; i++) {
3026 ind = (gint)((gfloat)length*rand()/(RAND_MAX+1.0));
3027 tmp[i] = randchars[ind];
3028 }
3029 tmp[4] = '\0';
3030
3031 g_snprintf(fname, MAXLINE, "%s/xcdr%s.%s", TMP_XCDR_DIR,
3032 tmp,ext);
3033
3034 /* already such a file on disk? */
3035 if (stat(fname,&buf)) {
3036 /* no its not - good for us! */
3037 done = 1;
3038 break;
3039 }
3040 count++;
3041 }
3042
3043 if (done == 0) {
3044 strcpy(file1,"");
3045 } else {
3046 strncpy(file1,fname,MAXLINE);
3047 }
3048 }
3049
3050
3051 /* create a 0 byte file */
3052
3053 gint write_empty_file(gchar *fname) {
3054 FILE *fd;
3055
3056 fd = fopen(fname,"w");
3057 if (!fd) return 1;
3058
3059 dodebug(2,"creating temporary file %s\n", fname);
3060
3061 fclose(fd);
3062 return 0;
3063 }
3064
3065
3066 /* check if our writer is from sony..needed for some multisession checks */
3067
3068 gint is_a_sony(gint devnr) {
3069 gchar tmp[MAXLINE];
3070
3071 strcpy(tmp,"");
3072 convert_devnr2vendor(devnr, tmp);
3073
3074 if (strncasecmp(tmp,"SONY",4) == 0) {
3075 return 1;
3076 }
3077
3078 return 0;
3079 }
3080
3081
3082 /* parse a version id like 1.11a23 into the structure (1.11 is also ok) */
3083 /* returns 1 on failure */
3084
3085 gint parse_version_str(gchar *str, version_id_t *ver) {
3086 gchar tmp[MAXLINE];
3087 gchar *p,*q,*r;
3088
3089 ver->major = ver->minor = ver->patch = ver->branch = 0;
3090 ver->devel='h';
3091
3092 strncpy(tmp, str, MAXLINE);
3093 p = tmp;
3094 for(p=tmp; (*p != 0) && (!isdigit((int) *p ) );p++); // scan for first digit
3095 if(*p)
3096 {
3097 q = strstr(p,".");
3098 if(q) // then there's a minor version number
3099 {
3100 *q++ = 0;
3101 r = strstr(q,".");
3102 if(r) // then there's a second dot - call it branch number
3103 {
3104 *r++ = 0;
3105 ver->branch = atoi(r);
3106 }
3107 ver->minor = atoi(q);
3108 if(r)q=r; // skip to after branch number if there was one
3109 }
3110 ver->major = atoi(p);
3111 if(q)p=q; // skip to after minor (and maybe branch)
3112 for( q=p; (*q != 0) && (isdigit((int) *q ));q++);
3113 if(*q)
3114 ver->devel = tolower(*q++);
3115 else
3116 q=p;
3117 if(*q)
3118 {
3119 if(isdigit((int) *q)) ver->patch = atoi(q);
3120 }
3121 return 0;
3122 }
3123 return 1;
3124 }
3125
3126
3127 /* compares two version strings. Return -1 when older, 0 when equal
3128 and 1 when newer */
3129
3130 gint compare_versions(gchar *gotversion, gchar *minimal_version) {
3131 version_id_t ver0, ver1;
3132 unsigned long bigver0, bigver1;
3133
3134 /* convert version strings into compareable values */
3135 if (parse_version_str(gotversion, &ver0))
3136 return -1;
3137 if (parse_version_str(minimal_version, &ver1))
3138 return -1;
3139
3140 /* calculate a big pure numeric version str */
3141 bigver0 = ver0.major * 10000000 + ver0.minor * 100000 +
3142 ver0.branch * 1000 +
3143 (ver0.devel - 'a') * 100 + ver0.patch;
3144 bigver1 = ver1.major * 10000000 + ver1.minor * 100000 +
3145 ver1.branch * 1000 +
3146 (ver1.devel - 'a') * 100 + ver1.patch;
3147
3148 if (bigver1 == bigver0) return 0;
3149 if (bigver1 < bigver0) return 1;
3150
3151 return -1;
3152 }
3153
3154
3155 /* searches a list of directories for the biggest common path
3156 compontent e.g. /home/tn/bla and /home/tn/src would result in
3157 -> /home/tn */
3158
3159 void get_common_path_component(GList *dirs, gchar *common) {
3160 GList *loop;
3161 gchar tmp[MAXLINE];
3162 gchar match[MAXLINE];
3163 gint i,len;
3164 gchar *p;
3165
3166 loop = g_list_first(dirs);
3167 /* init match str */
3168 strncpy(match, loop->data, MAXLINE);
3169 while (loop) {
3170 strncpy(tmp, loop->data, MAXLINE);
3171
3172 /* which str is shorter? */
3173 if (strlen(tmp) > strlen(match)) {
3174 len = strlen(match);
3175 } else {
3176 len = strlen(tmp);
3177 }
3178 for (i = 0; i < len; i++) {
3179 /* search until mismatch */
3180 if (tmp[i] != match[i]) {
3181 break;
3182 }
3183 }
3184 /* found shortest common path */
3185 match[i] = '\0';
3186
3187 /* now match again */
3188 loop = loop->next;
3189 }
3190
3191 /* match contains now the longest common paths..remove now
3192 any non directory parts at the end */
3193 p = rindex(match,'/');
3194 if (p) {
3195 *p = '\0';
3196 }
3197 strncpy(common, match, MAXLINE);
3198 }
3199
3200
3201 /* return driveropts string for cdrecord */
3202 /* return 1 if varirec is enabled */
3203
3204 gint do_driveropts(gchar *out, gint devnr) {
3205 gchar tmp[MAXLINE];
3206 gchar tmp2[MAXLINE];
3207 gint varirecon;
3208
3209 varirecon = 0;
3210 strcpy(tmp,"");
3211 if (does_support_burnproof(devnr)) {
3212 if (curset.writeburnfree) {
3213 strcat(tmp,"burnfree");
3214 } else {
3215 strcat(tmp,"noburnfree");
3216 }
3217 }
3218 if (does_support_audiomaster(devnr)) {
3219 if (curset.writeaudiomaster) {
3220 if (tmp[0] != '\0')
3221 strcat(tmp,",");
3222 strcat(tmp,"audiomaster");
3223 }
3224 }
3225 if (does_support_forcespeed(devnr)) {
3226 if (tmp[0] != '\0')
3227 strcat(tmp,",");
3228 if (curset.writeforcespeed) {
3229 strcat(tmp,"forcespeed");
3230 } else {
3231 strcat(tmp,"noforcespeed");
3232 }
3233 }
3234 if (does_support_varirec(devnr)) {
3235 if (curset.writevarirec < 50) {
3236 if (tmp[0] != '\0')
3237 strcat(tmp,",");
3238 g_snprintf(tmp2,MAXLINE,"varirec=%d", curset.writevarirec);
3239 strcat(tmp,tmp2);
3240 varirecon = 1;
3241 }
3242 }
3243
3244 if (tmp[0] != '\0') {
3245 /* added some options? */
3246 strcpy(tmp2, "driveropts=");
3247 strcat(tmp2, tmp);
3248 } else {
3249 strcpy(tmp2,"");
3250 }
3251 strncpy(out, tmp2, MAXLINE);
3252
3253 return varirecon;
3254 }
3255
3256
3257 /* return index in writerreaderdevs structure for given devnr */
3258 /* -1 when not found */
3259
3260 gint get_writerreaderdevs_index(gint devnr) {
3261 gint i, found;
3262
3263 i = 0;
3264 found = 0;
3265 while(writerreaderdevs[i] != NULL) {
3266 if (writerreaderdevs[i]->devnr == devnr) {
3267 found = 1;
3268 break;
3269 }
3270 i++;
3271 }
3272
3273 if (found) {
3274 return i;
3275 } else {
3276 return -1;
3277 }
3278 }
3279
3280
3281 /* return 1 if the device devnr supports the given write mode */
3282
3283 gint writemode_supported(gint mode, gint devnr) {
3284 gint i;
3285 gchar *modes;
3286
3287 i = get_writerreaderdevs_index(devnr);
3288 if (i == -1)
3289 return 1;
3290
3291 modes = writerreaderdevs[i]->writer_modes;
3292 if (!modes)
3293 return 1;
3294
3295 /* no modes? allow all in this case */
3296 if (strlen(modes) == 0)
3297 return 1;
3298
3299 switch(mode) {
3300
3301 case 0:
3302 if (strstr(modes, "DAO"))
3303 return 1;
3304 /* SAO in the middle of the mode string? */
3305 if (strstr(modes, "SAO "))
3306 return 1;
3307 /* SAO at the end of the string? */
3308 if (strlen(modes) >= 3 &&
3309 strcmp((modes + strlen(modes) - 3), "SAO") == 0)
3310 return 1;
3311 break;
3312 case 1:
3313 case 2:
3314 if (strstr(modes, "TAO"))
3315 return 1;
3316 break;
3317 case 3:
3318 if (strstr(modes,"RAW/R96R"))
3319 return 1;
3320 break;
3321 case 4:
3322 if (strstr(modes,"RAW/R96P"))
3323 return 1;
3324 break;
3325 case 5:
3326 if (strstr(modes,"RAW/R16"))
3327 return 1;
3328 break;
3329 default:
3330 return 0;
3331 }
3332 return 0;
3333 }
3334
3335
3336 /* free all of the current writerreader structure and reset all */
3337
3338 void free_writerreader_data() {
3339 gint i;
3340
3341 i = 0;
3342 while(writerreaderdevs[i] != NULL) {
3343 /* free first string data */
3344 g_free(writerreaderdevs[i]->devicestr);
3345 g_free(writerreaderdevs[i]->writer_flags);
3346 g_free(writerreaderdevs[i]->writer_modes);
3347
3348 g_free(writerreaderdevs[i]);
3349
3350 i++;
3351 }
3352
3353 g_free(writerreaderdevs);
3354 writerreaderdevs = NULL;
3355
3356 /* set devicenumbers back to default -1 */
3357 setupdata.writer_devnr = -1;
3358 setupdata.reader_devnr = -1;
3359 curset.writer_devnr = -1;
3360 curset.reader_devnr = -1;
3361
3362 return;
3363 }
3364
3365
3366 /* remove a device from the structure */
3367
3368 void remove_from_writerreader_data(gint devnr) {
3369 gint startindex, endindex;
3370 gint i;
3371
3372 startindex = -1;
3373 i = 0;
3374 while(writerreaderdevs[i] != NULL) {
3375 if (writerreaderdevs[i]->devnr == devnr) {
3376 startindex = i;
3377 }
3378 i++;
3379 }
3380 endindex = i - 1;
3381
3382 if (startindex == -1 || endindex == -1) {
3383 /* nothing to do */
3384 return;
3385 }
3386
3387 /* erase entry from memory */
3388 g_free(writerreaderdevs[startindex]->devicestr);
3389 g_free(writerreaderdevs[startindex]->writer_flags);
3390 g_free(writerreaderdevs[startindex]->writer_modes);
3391 g_free(writerreaderdevs[startindex]);
3392
3393 /* shift data to fill empty place */
3394 for (i = startindex; i < endindex; i++) {
3395 writerreaderdevs[i] = writerreaderdevs[i+1];
3396 }
3397
3398 /* last entry is now zero */
3399 writerreaderdevs[endindex] = NULL;
3400
3401 /* set devicenumbers back to default -1 if required */
3402 if (setupdata.writer_devnr == devnr)
3403 setupdata.writer_devnr = -1;
3404 if (setupdata.reader_devnr == devnr)
3405 setupdata.reader_devnr = -1;
3406 if (curset.writer_devnr == devnr)
3407 curset.writer_devnr = -1;
3408 if (curset.reader_devnr == devnr)
3409 curset.reader_devnr = -1;
3410 }
3411
3412
3413 /* returns the last used index - or -1 if no entries at all */
3414
3415 gint get_last_writerreaderdevs_index() {
3416 gint count;
3417
3418 count = 0;
3419 while(writerreaderdevs[count] != NULL) {
3420 if (count == MAXDEVICES-1) {
3421 g_error("To many devices");
3422 }
3423 count++;
3424 }
3425 count--;
3426
3427 return count;
3428 }
3429
3430
3431 /* saves the size of the given window in the burnwindow-geometry */
3432
3433 void store_win_geometry(GtkWidget *win) {
3434
3435 if (setupdata.option_savepos) {
3436 gdk_window_get_root_origin(win->window,
3437 &setupdata.burnwindow.x,
3438 &setupdata.burnwindow.y);
3439 gdk_window_get_size(win->window,
3440 &setupdata.burnwindow.width,
3441 &setupdata.burnwindow.height);
3442 }
3443 }
3444
3445
3446 /* set the size of a given window from burnwindow-geometry */
3447
3448 gint set_win_geometry(GtkWidget *win) {
3449 gint result;
3450
3451 result = 0;
3452 if (setupdata.option_savepos &&
3453 setupdata.burnwindow.width != -1 &&
3454 setupdata.burnwindow.height != -1 &&
3455 setupdata.burnwindow.x != -1 &&
3456 setupdata.burnwindow.y != -1) {
3457
3458 gtk_widget_realize(win);
3459 gdk_window_move_resize(win->window,
3460 setupdata.burnwindow.x,
3461 setupdata.burnwindow.y,
3462 setupdata.burnwindow.width,
3463 setupdata.burnwindow.height);
3464 gtk_widget_set_uposition(win,
3465 setupdata.burnwindow.x,
3466 setupdata.burnwindow.y);
3467 result = 1;
3468 }
3469
3470 return result;
3471 }
3472
3473
3474 /* set or reset the xcdroast title bar for both toplevel and one dialog
3475 window - adds a percent counter if requsted */
3476
3477 void set_xcdr_title(GtkWidget *dialog, GtkWidget *dialog2, gint val) {
3478 char tmp[MAXLINE];
3479
3480 if (val >= 0 && val <= 100 && setupdata.option_titleprogress) {
3481 g_snprintf(tmp, MAXLINE, "%d%% %s %s", val,
3482 T_XCDROAST, XCDROAST_VERSION);
3483 } else {
3484 g_snprintf(tmp, MAXLINE, "%s %s",
3485 T_XCDROAST, XCDROAST_VERSION);
3486 }
3487
3488 if (dialog)
3489 gtk_window_set_title(GTK_WINDOW(dialog), tmp);
3490 if (dialog2)
3491 gtk_window_set_title(GTK_WINDOW(dialog2), tmp);
3492 }
3493
3494
3495 /* returns the devnr of a given devicestr or -1 when not found */
3496
3497 gint get_writerreaderdevs_index_from_devstr(gchar *devstr) {
3498 gint count;
3499
3500 count = 0;
3501 while(writerreaderdevs[count] != NULL) {
3502 if (strncmp(writerreaderdevs[count]->devicestr, devstr, MAXLINE)== 0) {
3503 return count;
3504 }
3505 count++;
3506 }
3507
3508 return -1;
3509 }
3510
3511
3512 /* return whether we have a empty CD-R or DVD-R in the drive */
3513 /* we are sure that there IS a medium there - but we dont know which type */
3514 /* check only if device is dvdwriter and we have prodvd installed */
3515
3516 gchar *return_media_type(gint devnr) {
3517 gchar drvflags[MAXLINE], drvmodes[MAXLINE];
3518 gchar tmp[MAXLINE];
3519 gint isdvd,i;
3520
3521 isdvd = 0;
3522 i = get_writerreaderdevs_index(devnr);
3523
3524 if (i >= 0 && curset.isProDVD && writerreaderdevs[i]->is_dvdwriter) {
3525 if (convert_devnr2busid(devnr,tmp) != 0) {
3526 g_error("non existing cdrom?");
3527 }
3528 getmodesflags(tmp, drvflags, drvmodes);
3529
3530 /* if drvflags contains the flag DVD we have a DVD loaded */
3531 if (strstr(drvflags,"DVD ")) {
3532 isdvd = 1;
3533 }
3534 }
3535 if (isdvd) {
3536 return _("Empty DVD+-R/RW");
3537 } else {
3538 return _("Empty CD-R/RW");
3539 }
3540 }
3541
3542
3543 /* return please-insert-media text CD or DVD version */
3544
3545 gchar *pleaseinsertmedia() {
3546
3547 if (curset.cdrtype < 1000) {
3548 return _("Please insert a CD-R/RW in the CD-Writer.");
3549 } else {
3550 return _("Please insert a DVD+-R/RW in the DVD-Writer.");
3551 }
3552 }
3553
3554
3555 /* return if we can write dvds with the given device */
3556
3557 gint is_dvdwriter(gint devnr) {
3558 gint i;
3559
3560 i = get_writerreaderdevs_index(devnr);
3561
3562 if (i >= 0 && writerreaderdevs[i]->is_dvdwriter) {
3563 return 1;
3564 }
3565 return 0;
3566 }
3567
3568
3569 /* return a new dialog widget */
3570
3571 GtkWidget *my_gtk_dialog_new() {
3572
3573 #if GTK_MAJOR_VERSION < 2
3574 return gtk_window_new(GTK_WINDOW_DIALOG);
3575 #else
3576 return gtk_window_new(GTK_WINDOW_TOPLEVEL);
3577 #endif
3578 }
3579
3580
3581 /* convert a given string to utf8, when it is not already */
3582 /* used for strings we got from the system or from cddb */
3583
3584 gchar *convert_for_gtk2(gchar *str) {
3585
3586 #if GTK_MAJOR_VERSION < 2
3587 /* do nothing when using gtk1 */
3588 return str;
3589 #else
3590 gchar *utfstr;
3591 gsize in, out;
3592
3593 if (g_utf8_validate(str, strlen(str), NULL)) {
3594 /* we are already uft8? */
3595 return str;
3596 }
3597
3598 utfstr = NULL;
3599 utfstr = g_locale_to_utf8(str, strlen(str), &in, &out, NULL);
3600
3601 if (utfstr) {
3602 /* overwrite old string with new */
3603 strncpy(str,utfstr,MAXLINE);
3604 }
3605 return str;
3606 #endif
3607 }
3608
3609
3610 /* the classic text-widget is unable to handle utf text */
3611
3612 gchar *convert_for_gtk2_textwidget(gchar *str) {
3613
3614 #if GTK_MAJOR_VERSION < 2
3615 /* do nothing when using gtk1 */
3616 return str;
3617 #else
3618 gchar *locstr;
3619 gsize in, out;
3620
3621 locstr = g_locale_from_utf8(str, strlen(str), &in, &out, NULL);
3622 if (locstr) {
3623 strncpy(str, locstr, MAXLINE);
3624 }
3625 return str;
3626 #endif
3627 }
3628
3629
3630 /* get a filename from an GTK2 widget */
3631
3632 gchar *convert_for_gtk2_filename(gchar *str) {
3633
3634 #if GTK_MAJOR_VERSION < 2
3635 /* do nothing when using gtk1 */
3636 return str;
3637 #else
3638 gchar *locstr;
3639 gsize in, out;
3640
3641 /* ok, if your filesystem is already UTF8 we are not
3642 allowed to change the filenames here. */
3643 if (c_locale_is_utf8)
3644 return str;
3645
3646 #ifdef BROKEN_GTK2_LOCALE
3647 /* on my redhat 7.3 system it does only work that way, but
3648 on other systems the correct way is in the #else branch */
3649 locstr = g_locale_from_utf8(str, strlen(str), &in, &out, NULL);
3650 #else
3651 locstr = g_filename_from_utf8(str, strlen(str), &in, &out, NULL);
3652 #endif
3653 if (locstr) {
3654 strncpy(str, locstr, MAXLINE);
3655 }
3656 return str;
3657 #endif
3658 }
3659
3660
3661 /* return the gtk2 stock icon fitting to our requested self made icon */
3662
3663 gchar *lookup_stock_icon(gchar *icon) {
3664
3665 #if GTK_MAJOR_VERSION < 2
3666 /* do nothing when using gtk1 */
3667 return icon;
3668 #else
3669
3670 if (strncmp(icon, ICO_ERROR, MAXLINE) == 0)
3671 return GTK_STOCK_DIALOG_ERROR;
3672 if (strncmp(icon, ICO_INFO, MAXLINE) == 0)
3673 return GTK_STOCK_DIALOG_INFO;
3674 if (strncmp(icon, ICO_WARN, MAXLINE) == 0)
3675 return GTK_STOCK_DIALOG_WARNING;
3676 if (strncmp(icon, ICO_QUEST, MAXLINE) == 0)
3677 return GTK_STOCK_DIALOG_QUESTION;
3678
3679 /* not found? */
3680 return NULL;
3681 #endif
3682 }
3683
3684