1 /*
2 	main.c
3 	13.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 <string.h>
21 #include <stdlib.h>
22 #include <signal.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 
26 #if ENABLE_NLS
27 # define _(String) gettext (String)
28 # define N_(String) gettext_noop (String)
29 #else
30 # define _(String) (String)
31 # define N_(String) (String)
32 #endif
33 
34 #include <gtk/gtk.h>
35 #include <gdk/gdk.h>
36 #include <gdk-pixbuf/gdk-pixbuf.h>
37 #include <gdk/gdkprivate.h>
38 #include "xcdrdata.h"
39 #include "xcdroast.h"
40 #include "main.h"
41 #include "../xpms/xcdricon.xpm"
42 
43 GtkWidget *toplevel;
44 GtkWidget *splitspace;
45 GtkWidget *sidespace;
46 GtkWidget *workspace;
47 setup_data_t setupdata;
48 current_set_t curset;
49 
50 gint debug;
51 gint submenu;
52 gint bigfonts;
53 gint oldfontcode;
54 gint altdevscan;
55 gint no_versioncheck;
56 
57 static gint lastxsize, lastysize;
58 
59 extern gchar sharedir[MAXLINE];
60 extern gchar rootconfig[MAXLINE];
61 extern gchar xcdroast_version_loaded[MAXLINE];
62 
63 
64 
65 /* exit-button handler */
66 
menu_exit(GtkWidget * widget,gpointer data)67 static void menu_exit(GtkWidget *widget, gpointer data) {
68 gint ret;
69 
70 	ret = show_dialog(ICO_QUEST,_("Really quit X-CD-Roast?"),
71 		T_YES,T_NO,NULL,0);
72 
73 	if (ret == 0) {
74 		dolog(1,"Exiting...\n");
75 		remove_tmp_xcdr_files();
76 		gtk_main_quit();
77 	}
78 }
79 
menu_exit_now(GtkWidget * widget,gpointer data)80 static void menu_exit_now(GtkWidget *widget, gpointer data) {
81 
82 	dolog(1,"Exiting...\n");
83 	gtk_main_quit();
84 
85 }
86 
87 
88 /* replacement of gtk_exit with more cleanups */
89 
my_do_gtk_exit(gint code,gint textonly)90 static void my_do_gtk_exit(gint code, gint textonly) {
91 
92 #if (defined(__MACH__) && defined(__APPLE__))
93 	show_restart_autodiskmount(textonly);
94 #endif
95 
96 	gtk_exit(code);
97 }
98 
99 
100 /* set the width of the sidebar - relative to width of toplevel */
101 
set_sidebar_width()102 void set_sidebar_width() {
103 gint x, y;
104 gint val;
105 
106 	/* check if we are already realized */
107 	if (GTK_WIDGET(toplevel)->window == NULL) {
108 		val = 150;
109 	} else {
110 		/* set relative to new size */
111 		gdk_window_get_size(GTK_WIDGET(toplevel)->window,&x,&y);
112 
113 		/* workaround for a little gtk bug - in some chases
114  		   the current window size is reported wrongly as 200x200 */
115 		if (x == 200 && y == 200) {
116 			if (bigfonts == 0)
117 				x = XCDR_TOPLEVEL_X0;
118 			else
119 				x = XCDR_TOPLEVEL_X1;
120 		}
121 		val = (x*150)/790;
122 	}
123 
124 	gtk_widget_set_usize(sidespace,val,0);
125 }
126 
127 
128 /* called everytime some window resizes - we check if the toplevel
129    changed and set the sidebar to the value we want. This way
130    we can dynamically resize and the layout does not change */
131 
resize_handler(GtkWidget * widget,gpointer data)132 static void resize_handler(GtkWidget *widget, gpointer data) {
133 gint x, y;
134 
135 	/* check if we are already realized */
136 	if (GTK_WIDGET(toplevel)->window == NULL)
137 		return;
138 
139 	gdk_window_get_size(GTK_WIDGET(toplevel)->window,&x,&y);
140 
141 	/* size of toplevel changed? */
142 	if (x != lastxsize || y != lastysize) {
143 		/* remember new size */
144 		lastxsize = x;
145 		lastysize = y;
146 
147 		/* set sidebar width to new value */
148 		set_sidebar_width();
149 	}
150 }
151 
152 
153 /* setup-button handler */
154 
menu_setup(GtkWidget * widget,gpointer data)155 static void menu_setup(GtkWidget *widget, gpointer data) {
156 
157 	dolog(2,"Entering setup\n");
158 	create_setup();
159 }
160 
161 
162 /* duplicate-button handler */
163 
menu_duplicate(GtkWidget * widget,gpointer data)164 static void menu_duplicate(GtkWidget *widget, gpointer data) {
165 
166 	dolog(2,"Entering duplicate cd\n");
167 	create_duplicate();
168 }
169 
170 
171 /* create-button handler */
172 
menu_create(GtkWidget * widget,gpointer data)173 static void menu_create(GtkWidget *widget, gpointer data) {
174 
175 	dolog(2,"Entering create cd\n");
176 	create_create();
177 }
178 
179 
180 /* set the pixmap icon */
181 
set_wm_icon()182 static void set_wm_icon() {
183 GtkStyle *style;
184 GdkBitmap *bitmap;
185 GdkPixmap *pixmap;
186 GdkColormap *colormap;
187 GdkColor wait_color={0,0,0,0};
188 
189 	style=gtk_widget_get_style(GTK_WIDGET(toplevel));
190 	pixmap=gdk_pixmap_create_from_xpm_d(GTK_WIDGET(toplevel)->window,
191 		&bitmap, &style->bg[GTK_STATE_NORMAL], xcdricon_xpm);
192 	colormap = gtk_widget_get_colormap(GTK_WIDGET(toplevel));
193 	gdk_color_alloc (colormap, &wait_color);
194 	gdk_window_set_icon(GTK_WIDGET(toplevel)->window, (GdkWindow *)NULL,  pixmap, bitmap);
195 }
196 
197 
198 /* draw the main-menu */
199 
create_main(gint confignotloaded)200 void create_main(gint confignotloaded) {
201 GtkWidget *side_t;
202 GtkWidget *side_t_btn1;
203 GtkWidget *side_t_btn2;
204 GtkWidget *side_t_btn3;
205 GtkWidget *side_t_btn4;
206 GtkWidget *work_t;
207 GtkWidget *work_t_l1;
208 GtkWidget *work_t_l2;
209 GdkPixmap *p;
210 GdkBitmap *m;
211 GdkPixbuf *im;
212 GtkWidget *xcdroast_logo;
213 /*
214 GtkWidget *burnproof_logo;
215 GtkWidget *logoalign;
216 */
217 gchar tmp[MAXLINE];
218 
219 
220 	submenu = 0;
221         clear_sidespace();
222         clear_workspace();
223 
224 	side_t = gtk_table_new(10,1, TRUE);
225 	gtk_table_set_row_spacings(GTK_TABLE(side_t),10);
226 	gtk_box_pack_start(GTK_BOX(sidespace), side_t,TRUE,TRUE,0);
227 
228 	side_t_btn1 = gtk_button_new_with_label (_("Setup"));
229 	if (!curset.isProDVD) {
230 		side_t_btn2 = gtk_button_new_with_label (_("Duplicate CD"));
231 		side_t_btn3 = gtk_button_new_with_label (_("Create CD"));
232 	} else {
233 		side_t_btn2 = gtk_button_new_with_label (_("Duplicate CD/DVD"));
234 		side_t_btn3 = gtk_button_new_with_label (_("Create CD/DVD"));
235 	}
236 	side_t_btn4 = gtk_button_new_with_label (_("Exit"));
237 
238 	gtk_signal_connect (GTK_OBJECT (side_t_btn1), "clicked",
239 		GTK_SIGNAL_FUNC(menu_setup),NULL);
240 	gtk_signal_connect (GTK_OBJECT (side_t_btn2), "clicked",
241 		GTK_SIGNAL_FUNC(menu_duplicate),NULL);
242 	gtk_signal_connect (GTK_OBJECT (side_t_btn3), "clicked",
243 		GTK_SIGNAL_FUNC(menu_create),NULL);
244 	gtk_signal_connect (GTK_OBJECT (side_t_btn4), "clicked",
245 		GTK_SIGNAL_FUNC(menu_exit_now),NULL);
246 
247 	gtk_table_attach_defaults(GTK_TABLE(side_t), side_t_btn1, 0,1,4,5);
248 	gtk_widget_show(side_t_btn1);
249  	define_tooltip(side_t_btn1,_("Setup your hardware and system defaults"));
250 
251 	gtk_table_attach_defaults(GTK_TABLE(side_t), side_t_btn2, 0,1,5,6);
252 	gtk_widget_show(side_t_btn2);
253  	define_tooltip(side_t_btn2,_("Make an exact copy of a CD (data and audio)"));
254 
255 	gtk_table_attach_defaults(GTK_TABLE(side_t), side_t_btn3, 0,1,6,7);
256 	gtk_widget_show(side_t_btn3);
257  	define_tooltip(side_t_btn3,_("Create and arrange your own CD (data and audio)"));
258 
259 	gtk_table_attach_defaults(GTK_TABLE(side_t), side_t_btn4, 0,1,8,9);
260 	gtk_widget_show(side_t_btn4);
261  	define_tooltip(side_t_btn4,_("Quit X-CD-Roast"));
262 
263 	gtk_widget_show(side_t);
264 	gtk_widget_show(sidespace);
265 
266 
267 	/* draw the workspace */
268 
269 	work_t = gtk_table_new(10,10, TRUE);
270 	gtk_box_pack_start(GTK_BOX(workspace), work_t,TRUE,FALSE,0);
271 
272         /* load a gif-image and put into a pixmap */
273 	g_snprintf(tmp,MAXLINE,"%s/%s", sharedir, XCDRLOGO);
274 #if GTK_MAJOR_VERSION < 2
275         im=gdk_pixbuf_new_from_file(tmp);
276 #else
277 	im=gdk_pixbuf_new_from_file(tmp,NULL);
278 #endif
279 	if (im) {
280 		gdk_pixbuf_render_pixmap_and_mask(im, &p, &m, 128);
281         	xcdroast_logo = gtk_pixmap_new(p,m);
282 		gdk_pixbuf_unref(im);
283 	} else {
284 		xcdroast_logo = gtk_label_new("[LOGO]");
285 	}
286 	gtk_table_attach_defaults(GTK_TABLE(work_t), xcdroast_logo, 0,10,0,4);
287 	gtk_misc_set_alignment(GTK_MISC(xcdroast_logo),0.5f, 0.5f);
288 	gtk_widget_show(xcdroast_logo);
289 
290         /* load a gif-image and put into a pixmap */
291 /*
292 	g_snprintf(tmp,MAXLINE,"%s/%s", sharedir, BURNPROOFLOGO);
293         im=gdk_pixbuf_new_from_file(tmp);
294 	if (im) {
295 		gdk_pixbuf_render_pixmap_and_mask(im, &p, &m, 128);
296         	burnproof_logo = gtk_pixmap_new(p,m);
297 		gdk_pixbuf_unref(im);
298 	} else {
299 		burnproof_logo = gtk_label_new("[BURNPROOF]");
300 	}
301 	logoalign = gtk_alignment_new(1.0,1.0,0,0);
302 	gtk_container_add(GTK_CONTAINER(logoalign), burnproof_logo);
303 	gtk_table_attach_defaults(GTK_TABLE(work_t), logoalign, 0,10,9,10);
304 	gtk_widget_show(burnproof_logo);
305 	gtk_widget_show(logoalign);
306 */
307 	g_snprintf(tmp,MAXLINE,_("Version %s"),XCDROAST_VERSION);
308 	work_t_l1=gtk_label_new(tmp);
309 	gtk_label_set_justify(GTK_LABEL(work_t_l1),GTK_JUSTIFY_CENTER);
310 	gtk_table_attach_defaults(GTK_TABLE(work_t), work_t_l1, 0,10,4,5);
311 	set_font_and_color(work_t_l1,BIGFONT,"red");
312 
313 	work_t_l2=gtk_label_new(_("(c) 1996-2008 by T. Niederreiter\n\nhttp://www.xcdroast.org"));
314 	gtk_label_set_justify(GTK_LABEL(work_t_l2),GTK_JUSTIFY_CENTER);
315 	gtk_table_attach_defaults(GTK_TABLE(work_t), work_t_l2, 0,10,5,6);
316 
317 	gtk_widget_show(work_t_l1);
318 	gtk_widget_show(work_t_l2);
319 
320 	gtk_widget_show(work_t);
321 	gtk_widget_show(workspace);
322 
323 	if (confignotloaded) {
324 		gtk_widget_set_sensitive(side_t_btn2, FALSE);
325 		gtk_widget_set_sensitive(side_t_btn3, FALSE);
326 	}
327 }
328 
329 
330 /* signal handler to gracefully exit on ctrl-c */
331 
my_signal_exit(gint isignal)332 static void my_signal_exit(gint isignal) {
333 
334 	g_print("Caught SIGINT, exiting...\n");
335 	remove_tmp_xcdr_files();
336 	my_do_gtk_exit(isignal, 1);
337 }
338 
339 
340 /* main */
341 
main(gint argc,gchar * argv[])342 gint main(gint argc, gchar *argv[]) {
343 GtkWidget *w;
344 gint confignotloaded, nrm;
345 #if 0
346 gchar *keyenv;
347 #endif
348 gchar tmp[MAXLINE];
349 gchar tmp2[MAXLINE];
350 #if GTK_MAJOR_VERSION < 2
351 GtkStyle *style;
352 #else
353 PangoRectangle ink_rect;
354 PangoLayout *layout;
355 #endif
356 #if (defined(__MACH__) && defined(__APPLE__))
357 gint stat;
358 #endif
359 
360 #if ENABLE_NLS
361  #if GTK_MAJOR_VERSION < 2
362 	bindtextdomain (PACKAGE, LOCALEDIR);
363 	textdomain (PACKAGE);
364  #else
365 	bindtextdomain (PACKAGE, LOCALEDIR);
366 	bind_textdomain_codeset (PACKAGE, "utf8");
367 	textdomain (PACKAGE);
368  #endif
369 #endif
370 	gtk_set_locale();
371 	gtk_init(&argc,&argv);
372 
373 #if (defined(__MACH__) && defined(__APPLE__))
374 	/* dont use xshm on darwin -> its broken */
375 	/* from gdk-private */
376 	gdk_use_xshm = FALSE;
377 #endif
378 
379 	/* get rid of badmatch() errors */
380         gdk_rgb_init();
381         gtk_widget_set_default_visual(gdk_rgb_get_visual());
382         gtk_widget_set_default_colormap(gdk_rgb_get_cmap());
383 
384 	/* private init for xcdroast */
385 	confignotloaded = init(argc, argv, &nrm, &altdevscan);
386 
387 	w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
388 	/* save this pointer for future reference */
389 	toplevel = w;
390 
391 	lastxsize = 0;
392 	lastysize = 0;
393 
394 	/* check which font size we are running */
395 #if GTK_MAJOR_VERSION < 2
396 
397 	style = gtk_widget_get_style(toplevel);
398 	if (gdk_char_height(style->font,'|') > 12) {
399 		/* our font is higher as 12 pixels */
400 		bigfonts = 1;
401 	} else {
402 		bigfonts = 0;
403 	}
404 #else
405 
406 	/* create dummy layout just to measure the current font */
407 	layout = gtk_widget_create_pango_layout(toplevel, "|");
408 	pango_layout_get_extents(layout, NULL, &ink_rect);
409 
410 	if (PANGO_PIXELS(ink_rect.height) > 16)
411 		bigfonts = 1;
412 	else
413 		bigfonts = 0;
414 #endif
415 
416 	gtk_widget_realize(toplevel);
417 	set_wm_icon();
418 	set_xcdr_title(w, NULL, -1);
419 
420 #if (defined(__MACH__) && defined(__APPLE__))
421 	/* on Mac OS X interactively disable the autodiskmount daemon */
422 
423 	/* use altdevscan variable to disable the daemon handling at all */
424 	while (1 && altdevscan == 1) {
425 		stat = create_autodiskmount_handler();
426 
427 		if (stat == -1)
428 			continue;
429 
430 		if (stat == 1) {
431 			break;
432 		} else {
433 			gtk_exit(1);
434 		}
435 	}
436 #endif
437 
438 	if (bigfonts == 0) {
439 		/* size for 75dpi fonts */
440 		gtk_widget_set_usize(GTK_WIDGET(w),
441 			XCDR_TOPLEVEL_X0,XCDR_TOPLEVEL_Y0);
442 	} else {
443 		/* size for 100dpi fonts */
444 		gtk_widget_set_usize(GTK_WIDGET(w),
445 			XCDR_TOPLEVEL_X1,XCDR_TOPLEVEL_Y1);
446 	}
447 
448 
449 	gtk_container_border_width(GTK_CONTAINER(w),10);
450 
451 	gtk_signal_connect (GTK_OBJECT(w), "destroy",
452 		GTK_SIGNAL_FUNC (gtk_exit), NULL);
453 
454 	gtk_signal_connect (GTK_OBJECT(w), "delete_event",
455 		GTK_SIGNAL_FUNC(menu_exit), NULL);
456 
457 	gtk_signal_connect (GTK_OBJECT(w), "size_request",
458 		GTK_SIGNAL_FUNC(resize_handler), NULL);
459 
460 
461 	splitspace = gtk_hpaned_new();
462 	gtk_container_add(GTK_CONTAINER(w),splitspace);
463 #if GTK_MAJOR_VERSION < 2
464 	gtk_paned_handle_size(GTK_PANED(splitspace),0);
465 #endif
466 	gtk_paned_gutter_size(GTK_PANED(splitspace),20);
467 
468 	/* left side */
469 	sidespace = gtk_vbox_new(FALSE,0);
470 	gtk_paned_add1(GTK_PANED(splitspace), sidespace);
471 	set_sidebar_width();
472 
473 	/* right side */
474 	workspace = gtk_vbox_new(FALSE,0);
475 	gtk_paned_add2(GTK_PANED(splitspace), workspace);
476 
477         /* check if screen-size is big enough */
478 	if (check_screensize(bigfonts) && no_versioncheck == 0) {
479 		strncpy(tmp2, _("You need at least a screen resolution of\n%dx%d to run X-CD-Roast.\n\nSee the man-page on how to override that requirement.\n\nExiting now..."), MAXLINE);
480 
481 		if (bigfonts == 0) {
482 			g_snprintf(tmp,MAXLINE,tmp2, 800, 600);
483 		} else {
484 			g_snprintf(tmp,MAXLINE,tmp2, 1024, 768);
485 		}
486 		show_dialog(ICO_ERROR,tmp,T_OK,NULL,NULL,0);
487 		my_do_gtk_exit(1, 0);
488 	}
489 
490 	if (confignotloaded) {
491 #if !(defined(__MACH__) && defined(__APPLE__)) && (USE_NONROOTMODE == 1)
492 		if (isroot()) {
493 			/* scan for devices */
494 			create_device_scanning(altdevscan, 0, 1, NULL);
495 
496 			/* first start for user root - ask him about nrm */
497 			create_nonroot_configurator(nrm,0);
498 			/* now show that no configfile exists yet */
499 			show_dialog(ICO_INFO, _("No root configuration file found!\nPlease enter Setup and don't forget to add users\nwho may also use X-CD-Roast."), T_OK, NULL, NULL, 0);
500 		} else {
501 #endif
502 			/* scan for devices */
503 			create_device_scanning(altdevscan, 0, 1, NULL);
504 
505 			show_dialog(ICO_INFO, _("No configuration file found!\nPlease enter Setup."), T_OK, NULL, NULL, 0);
506 
507 #if !(defined(__MACH__) && defined(__APPLE__)) && (USE_NONROOTMODE == 1)
508 		}
509 #endif
510 	} else {
511 		/* check if the configfile is for current version of xcdroast */
512 		if (strcmp(XCDROAST_VERSION, xcdroast_version_loaded) != 0) {
513 
514 			/* first start of new version for user root - ask him about nrm */
515 #if !(defined(__MACH__) && defined(__APPLE__)) && (USE_NONROOTMODE == 1)
516 			if (isroot()) {
517 				create_nonroot_configurator(nrm,0);
518 			}
519 #endif
520 			/* scan for devices */
521 			create_device_scanning(altdevscan, 0, 1, NULL);
522 
523 			g_snprintf(tmp,MAXLINE,_("Configuration file for incorrect version %s found!\nPlease enter Setup and create an updated configuration."), xcdroast_version_loaded);
524 			show_dialog(ICO_INFO, tmp, T_OK, NULL, NULL, 0);
525 			strcpy(xcdroast_version_loaded,"");
526 			confignotloaded = 1;
527 			if (isroot()) {
528 				/* if config is from old version, we can
529 				   assume that it still got the wrong perms */
530 				/* fix them */
531 				chmod(rootconfig, 0644);
532 			}
533 		}
534 
535 		/* now check if our config is matching the current hardware */
536 #if 0
537 		if (verify_loaded_config() == 1) {
538 			/* scsi-bus changed */
539 			show_dialog(ICO_WARN, _("Something on the SCSI-Bus has changed. Please check\nyour writer and reader configuration in Setup."), T_OK, NULL, NULL, 0);
540 			strcpy(xcdroast_version_loaded,"");
541 			confignotloaded = 1;
542 		}
543 #endif
544 		if (verify_loaded_config2() == 1) {
545 			/* image-dirs changed */
546 			show_dialog(ICO_WARN, _("The image-directories do not match the current system.\nPlease check their configuration in Setup."), T_OK, NULL, NULL, 0);
547 			strcpy(xcdroast_version_loaded,"");
548 			confignotloaded = 1;
549 		}
550 
551 	}
552 
553 	create_main(confignotloaded);
554 
555 	gtk_widget_show(splitspace);
556 	gtk_widget_show(w);
557 
558 	/* set new size from config? (only works after window is shown) */
559 	if (setupdata.option_savepos &&
560 	     setupdata.mainwindow.width != -1 &&
561 	     setupdata.mainwindow.height != -1 &&
562 	     setupdata.mainwindow.x != -1 &&
563 	     setupdata.mainwindow.y != -1) {
564 
565 		gdk_window_move_resize(GTK_WIDGET(w)->window,
566 			setupdata.mainwindow.x,
567 			setupdata.mainwindow.y,
568 			setupdata.mainwindow.width,
569 			setupdata.mainwindow.height);
570 	}
571 
572 
573 
574 	/* let the screen update now */
575 	while (gtk_events_pending())
576 		gtk_main_iteration();
577 
578 	/* show disclaimer (old disclaimer nr 288) */
579 /*
580 	if (show_dialog(ICO_WARN, _("DISCLAIMER: This is just an unfinished version of the new X-CD-Roast 0.98.\nBut it is already more stable and offers more features as the current\nrelease 0.96ex. Please visit http://www.xcdroast.org for updates and\n more detailed information about this alpha-version.\n\nBut because there are still some of the important features missing,\nI do ask - do you really want to continue?"), T_YES, T_NO, NULL, 1) == 1) {
581 		my_do_gtk_exit(1, 0);
582 	}
583 */
584 
585         /* warn about non-existing LFS support in dvd mode */
586         if ((curset.isProDVD & 1) && sizeof(off_t) != 8) {
587                 show_dialog(ICO_WARN, _("Warning: Your system is not able to create files larger\nthan 2 GB. Writing DVDs will therefore not possible."), T_OK, NULL, NULL, 0);
588         }
589 
590         /* if we are in DVD mode, check if the security-key is set */
591 #if 0
592         if (curset.isProDVD == 1) {
593                 keyenv = getenv("CDR_SECURITY");
594                 if (keyenv == NULL) {
595 			show_dialog(ICO_WARN, _("Warning: You have not entered a cdrecord-ProDVD key in setup.\nPlease see the FAQ on how to obtain your free key.\nYou also have to renew the key every few months because it got an\nexpire date. You will not be able to properly write DVDs without it."), T_OK, NULL, NULL, 0);
596                 }
597 
598 	}
599 #endif
600 
601 	dolog(1,"Starting X-CD-Roast\n");
602 
603 	/* install a signal handler to catch CTRL-C */
604 	signal (SIGINT, my_signal_exit) ;
605 
606 	gtk_main();
607 
608 	my_do_gtk_exit(0, 0);
609 	return 0;
610 }
611