1 /* grip.c
2 *
3 * Copyright (c) 1998-2004 Mike Oliphant <grip@nostatic.org>
4 *
5 * http://www.nostatic.org/grip
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
20 * USA
21 */
22
23 #include <pthread.h>
24 #include <config.h>
25 #include <fcntl.h>
26 #include <stdio.h>
27 #include <unistd.h>
28 #include <sys/param.h>
29 #include <sys/types.h>
30 #include <sys/wait.h>
31 #include <time.h>
32 #include <gdk/gdkx.h> /* GDK_DISPLAY() */
33 #include "grip.h"
34 #include "discdb.h"
35 #include "cdplay.h"
36 #include "discedit.h"
37 #include "rip.h"
38 #include "common.h"
39 #include "dialog.h"
40 #include "gripcfg.h"
41 #include "xpm.h"
42 #include "parsecfg.h"
43 #include "tray.h"
44
45 static void ReallyDie(gint reply,gpointer data);
46 static void DoHelp(GtkWidget *widget,gpointer data);
47 static void MakeHelpPage(GripInfo *ginfo);
48 static void MakeAboutPage(GripGUI *uinfo);
49 static void MakeStyles(GripGUI *uinfo);
50 static void Homepage(GtkWidget *widget,gpointer data);
51 static void LoadImages(GripGUI *uinfo);
52 static void DoLoadConfig(GripInfo *ginfo);
53 void LoadProxyConfig(GripInfo *ginfo, char* proxy_env);
54 void DoSaveConfig(GripInfo *ginfo);
55
56 #define BASE_CFG_ENTRIES \
57 {"grip_version",CFG_ENTRY_STRING,256,ginfo->version},\
58 {"cd_device",CFG_ENTRY_STRING,256,ginfo->cd_device},\
59 {"force_scsi",CFG_ENTRY_STRING,256,ginfo->force_scsi},\
60 {"ripexename",CFG_ENTRY_STRING,256,ginfo->ripexename},\
61 {"ripcmdline",CFG_ENTRY_STRING,256,ginfo->ripcmdline},\
62 {"wav_filter_cmd",CFG_ENTRY_STRING,256,ginfo->wav_filter_cmd},\
63 {"disc_filter_cmd",CFG_ENTRY_STRING,256,ginfo->disc_filter_cmd},\
64 {"mp3exename",CFG_ENTRY_STRING,256,ginfo->mp3exename},\
65 {"mp3cmdline",CFG_ENTRY_STRING,256,ginfo->mp3cmdline},\
66 {"dbserver",CFG_ENTRY_STRING,256,ginfo->dbserver.name},\
67 {"ripfileformat",CFG_ENTRY_STRING,256,ginfo->ripfileformat},\
68 {"ripfileformat_multi",CFG_ENTRY_STRING,256,ginfo->ripfileformat_multi},\
69 {"mp3fileformat",CFG_ENTRY_STRING,256,ginfo->mp3fileformat},\
70 {"mp3fileformat_multi",CFG_ENTRY_STRING,256,ginfo->mp3fileformat_multi},\
71 {"mp3extension",CFG_ENTRY_STRING,10,ginfo->mp3extension},\
72 {"m3ufileformat",CFG_ENTRY_STRING,256,ginfo->m3ufileformat},\
73 {"delete_wavs",CFG_ENTRY_BOOL,0,&ginfo->delete_wavs},\
74 {"add_m3u",CFG_ENTRY_BOOL,0,&ginfo->add_m3u},\
75 {"rel_m3u",CFG_ENTRY_BOOL,0,&ginfo->rel_m3u},\
76 {"add_to_db",CFG_ENTRY_BOOL,0,&ginfo->add_to_db},\
77 {"use_proxy",CFG_ENTRY_BOOL,0,&ginfo->use_proxy},\
78 {"proxy_name",CFG_ENTRY_STRING,256,ginfo->proxy_server.name},\
79 {"proxy_port",CFG_ENTRY_INT,0,&(ginfo->proxy_server.port)},\
80 {"proxy_user",CFG_ENTRY_STRING,80,ginfo->proxy_server.username},\
81 {"proxy_pswd",CFG_ENTRY_STRING,80,ginfo->proxy_server.pswd},\
82 {"cdupdate",CFG_ENTRY_STRING,256,ginfo->cdupdate},\
83 {"user_email",CFG_ENTRY_STRING,256,ginfo->user_email},\
84 {"ripnice",CFG_ENTRY_INT,0,&ginfo->ripnice},\
85 {"mp3nice",CFG_ENTRY_INT,0,&ginfo->mp3nice},\
86 {"mp3_filter_cmd",CFG_ENTRY_STRING,256,ginfo->mp3_filter_cmd},\
87 {"doid3",CFG_ENTRY_BOOL,0,&ginfo->doid3},\
88 {"doid3v2",CFG_ENTRY_BOOL,0,&ginfo->doid3v2},\
89 {"tag_mp3_only",CFG_ENTRY_BOOL,0,&ginfo->tag_mp3_only},\
90 {"id3_comment",CFG_ENTRY_STRING,30,ginfo->id3_comment},\
91 {"max_wavs",CFG_ENTRY_INT,0,&ginfo->max_wavs},\
92 {"auto_rip",CFG_ENTRY_BOOL,0,&ginfo->auto_rip},\
93 {"eject_after_rip",CFG_ENTRY_BOOL,0,&ginfo->eject_after_rip},\
94 {"eject_delay",CFG_ENTRY_INT,0,&ginfo->eject_delay},\
95 {"delayed_encoding",CFG_ENTRY_BOOL,0,&ginfo->delayed_encoding},\
96 {"delay_before_rip",CFG_ENTRY_BOOL,0,&ginfo->delay_before_rip},\
97 {"stop_between_tracks",CFG_ENTRY_BOOL,0,&ginfo->stop_between_tracks},\
98 {"beep_after_rip",CFG_ENTRY_BOOL,0,&ginfo->beep_after_rip},\
99 {"faulty_eject",CFG_ENTRY_BOOL,0,&ginfo->faulty_eject},\
100 {"poll_drive",CFG_ENTRY_BOOL,0,&ginfo->poll_drive},\
101 {"poll_interval",CFG_ENTRY_INT,0,&ginfo->poll_interval},\
102 {"use_proxy_env",CFG_ENTRY_BOOL,0,&ginfo->use_proxy_env},\
103 {"db_cgi",CFG_ENTRY_STRING,256,ginfo->dbserver.cgi_prog},\
104 {"cddb_submit_email",CFG_ENTRY_STRING,256,ginfo->discdb_submit_email},\
105 {"discdb_encoding",CFG_ENTRY_STRING,16,ginfo->discdb_encoding},\
106 {"id3_encoding",CFG_ENTRY_STRING,16,ginfo->id3_encoding},\
107 {"id3v2_encoding",CFG_ENTRY_STRING,16,ginfo->id3v2_encoding},\
108 {"db_use_freedb",CFG_ENTRY_BOOL,0,&ginfo->db_use_freedb},\
109 {"dbserver2",CFG_ENTRY_STRING,256,ginfo->dbserver2.name},\
110 {"db2_cgi",CFG_ENTRY_STRING,256,ginfo->dbserver2.cgi_prog},\
111 {"no_interrupt",CFG_ENTRY_BOOL,0,&ginfo->no_interrupt},\
112 {"stop_first",CFG_ENTRY_BOOL,0,&ginfo->stop_first},\
113 {"play_first",CFG_ENTRY_BOOL,0,&ginfo->play_first},\
114 {"play_on_insert",CFG_ENTRY_BOOL,0,&ginfo->play_on_insert},\
115 {"automatic_cddb",CFG_ENTRY_BOOL,0,&ginfo->automatic_discdb},\
116 {"automatic_reshuffle",CFG_ENTRY_BOOL,0,&ginfo->automatic_reshuffle},\
117 {"no_lower_case",CFG_ENTRY_BOOL,0,&ginfo->sprefs.no_lower_case},\
118 {"no_underscore",CFG_ENTRY_BOOL,0,&ginfo->sprefs.no_underscore},\
119 {"non_posix_m3u_directory_paths",CFG_ENTRY_BOOL,0,&ginfo->sprefs.non_posix_m3u_directory_paths},\
120 {"allow_high_bits",CFG_ENTRY_BOOL,0,&ginfo->sprefs.allow_high_bits},\
121 {"escape",CFG_ENTRY_BOOL,0,&ginfo->sprefs.escape},\
122 {"allow_these_chars",CFG_ENTRY_STRING,256,ginfo->sprefs.allow_these_chars},\
123 {"show_tray_icon",CFG_ENTRY_BOOL,0,&ginfo->show_tray_icon},\
124 {"num_cpu",CFG_ENTRY_INT,0,&ginfo->edit_num_cpu},\
125 {"kbits_per_sec",CFG_ENTRY_INT,0,&ginfo->kbits_per_sec},\
126 {"selected_encoder",CFG_ENTRY_INT,0,&ginfo->selected_encoder},\
127 {"selected_ripper",CFG_ENTRY_INT,0,&ginfo->selected_ripper},\
128 {"play_mode",CFG_ENTRY_INT,0,&ginfo->play_mode},\
129 {"playloop",CFG_ENTRY_BOOL,0,&ginfo->playloop},\
130 {"win_width",CFG_ENTRY_INT,0,&uinfo->win_width},\
131 {"win_height",CFG_ENTRY_INT,0,&uinfo->win_height},\
132 {"win_height_edit",CFG_ENTRY_INT,0,&uinfo->win_height_edit},\
133 {"win_width_min",CFG_ENTRY_INT,0,&uinfo->win_width_min},\
134 {"win_height_min",CFG_ENTRY_INT,0,&uinfo->win_height_min},\
135 {"vol_vis",CFG_ENTRY_BOOL,0,&uinfo->volvis},\
136 {"track_edit_vis",CFG_ENTRY_BOOL,0,&uinfo->track_edit_visible},\
137 {"track_prog_vis",CFG_ENTRY_BOOL,0,&uinfo->track_prog_visible},\
138 {"volume",CFG_ENTRY_INT,0,&ginfo->volume},\
139 {"execute_after_encode_cmd",CFG_ENTRY_STRING,256,ginfo->execute_after_encode_cmd},
140
141 #define CDPAR_CFG_ENTRIES \
142 {"disable_paranoia",CFG_ENTRY_BOOL,0,&ginfo->disable_paranoia},\
143 {"disable_extra_paranoia",CFG_ENTRY_BOOL,0,&ginfo->disable_extra_paranoia},\
144 {"disable_scratch_detect",CFG_ENTRY_BOOL,0,&ginfo->disable_scratch_detect},\
145 {"disable_scratch_repair",CFG_ENTRY_BOOL,0,&ginfo->disable_scratch_repair},\
146 {"calc_gain",CFG_ENTRY_BOOL,0,&ginfo->calc_gain},
147
148 #ifdef CDPAR
149 #define CFG_ENTRIES BASE_CFG_ENTRIES CDPAR_CFG_ENTRIES
150 #else
151 #define CFG_ENTRIES BASE_CFG_ENTRIES
152 #endif
153
AppWindowStateCB(GtkWidget * widget,GdkEventWindowState * event,gpointer data)154 gboolean AppWindowStateCB(GtkWidget *widget, GdkEventWindowState *event, gpointer data)
155 {
156 GripInfo *ginfo = (GripInfo*)data;
157 GripGUI *uinfo = &(ginfo->gui_info);
158 GdkWindowState state = event->new_window_state;
159
160 if ((state & GDK_WINDOW_STATE_WITHDRAWN) || (state & GDK_WINDOW_STATE_ICONIFIED)) {
161 ginfo->app_visible = FALSE;
162 return TRUE;
163 } else {
164 ginfo->app_visible = TRUE;
165 gtk_window_get_position(GTK_WINDOW(uinfo->app), &uinfo->x, &uinfo->y);
166 return TRUE;
167 }
168
169 return FALSE;
170 }
171
GripNew(char * device,char * scsi_device,char * config_filename,gboolean force_small,gboolean local_mode,gboolean no_redirect)172 GtkWidget *GripNew(char *device,char *scsi_device,
173 char *config_filename,
174 gboolean force_small,
175 gboolean local_mode,gboolean no_redirect)
176 {
177 GtkWidget *app;
178 GripInfo *ginfo;
179 GripGUI *uinfo;
180 int major,minor,point;
181 char buf[256];
182 GList icon_list = {NULL, NULL, NULL};
183
184 icon_list.data=gdk_pixbuf_new_from_file(GNOME_ICONDIR"/grip.png", NULL);
185 gtk_window_set_default_icon_list(&icon_list);
186
187 app = gtk_window_new(GTK_WINDOW_TOPLEVEL);
188 gtk_window_set_title(GTK_WINDOW(app), _("Grip"));
189 gtk_window_set_screen(GTK_WINDOW(app), gdk_screen_get_default());
190
191 ginfo=g_new0(GripInfo,1);
192
193 gtk_object_set_user_data(GTK_OBJECT(app),(gpointer)ginfo);
194
195 uinfo=&(ginfo->gui_info);
196 uinfo->app=app;
197 uinfo->track_list=NULL;
198
199 uinfo->win_width=WINWIDTH;
200 uinfo->win_height=WINHEIGHT;
201 uinfo->win_height_edit=WINHEIGHTEDIT;
202 uinfo->win_width_min=MIN_WINWIDTH;
203 uinfo->win_height_min=MIN_WINHEIGHT;
204
205 if(config_filename && *config_filename)
206 g_snprintf(ginfo->config_filename,256,"%s",config_filename);
207 else {
208 strcpy(ginfo->config_filename,".grip");
209 }
210
211 Debug("Using config file [%s]\n",ginfo->config_filename);
212
213 DoLoadConfig(ginfo);
214
215 if(device) g_snprintf(ginfo->cd_device,256,"%s",device);
216 if(scsi_device) g_snprintf(ginfo->force_scsi,256,"%s",scsi_device);
217
218 uinfo->minimized=force_small;
219 ginfo->local_mode=local_mode;
220 ginfo->do_redirect=!no_redirect;
221
222 if(!CDInitDevice(ginfo->cd_device,&(ginfo->disc))) {
223 sprintf(buf,_("Error: Unable to initialize [%s]\n"),ginfo->cd_device);
224
225 DisplayMsg(GTK_MESSAGE_INFO, NULL, buf);
226 }
227
228 CDStat(&(ginfo->disc),TRUE);
229
230 gtk_window_set_policy(GTK_WINDOW(app),FALSE,TRUE,FALSE);
231 gtk_window_set_wmclass(GTK_WINDOW(app),"grip","Grip");
232 g_signal_connect(G_OBJECT(app),"delete_event",
233 G_CALLBACK(GripDie),NULL);
234
235 if(uinfo->minimized) {
236 gtk_widget_set_size_request(GTK_WIDGET(app),MIN_WINWIDTH,
237 MIN_WINHEIGHT);
238
239 gtk_window_resize(GTK_WINDOW(app),uinfo->win_width_min,
240 uinfo->win_height_min);
241 }
242 else {
243 gtk_widget_set_size_request(GTK_WIDGET(app),WINWIDTH,
244 WINHEIGHT);
245
246 if(uinfo->track_edit_visible) {
247 gtk_window_resize(GTK_WINDOW(app),uinfo->win_width,
248 uinfo->win_height_edit);
249 }
250 else {
251 gtk_window_resize(GTK_WINDOW(app),uinfo->win_width,
252 uinfo->win_height);
253 }
254 }
255
256 gtk_widget_realize(app);
257
258 uinfo->winbox=gtk_vbox_new(FALSE,3);
259 if(!uinfo->minimized)
260 gtk_container_border_width(GTK_CONTAINER(uinfo->winbox),3);
261
262 uinfo->notebook=gtk_notebook_new();
263
264 LoadImages(uinfo);
265 MakeStyles(uinfo);
266 MakeTrackPage(ginfo);
267 MakeRipPage(ginfo);
268 MakeConfigPage(ginfo);
269 MakeHelpPage(ginfo);
270 MakeAboutPage(uinfo);
271 ginfo->tray_icon_made = FALSE;
272 ginfo->tray_menu_sensitive = TRUE;
273
274 gtk_box_pack_start(GTK_BOX(uinfo->winbox),uinfo->notebook,TRUE,TRUE,0);
275 if(!uinfo->minimized) gtk_widget_show(uinfo->notebook);
276
277 uinfo->track_edit_box=MakeEditBox(ginfo);
278 gtk_box_pack_start(GTK_BOX(uinfo->winbox),uinfo->track_edit_box,
279 FALSE,FALSE,0);
280 if(uinfo->track_edit_visible) gtk_widget_show(uinfo->track_edit_box);
281
282
283 uinfo->playopts=MakePlayOpts(ginfo);
284 gtk_box_pack_start(GTK_BOX(uinfo->winbox),uinfo->playopts,FALSE,FALSE,0);
285 if(uinfo->track_prog_visible) gtk_widget_show(uinfo->playopts);
286
287 uinfo->controls=MakeControls(ginfo);
288 if(uinfo->minimized)
289 gtk_box_pack_start(GTK_BOX(uinfo->winbox),uinfo->controls,TRUE,TRUE,0);
290 else
291 gtk_box_pack_start(GTK_BOX(uinfo->winbox),uinfo->controls,FALSE,FALSE,0);
292 gtk_widget_show(uinfo->controls);
293
294 gtk_container_add(GTK_CONTAINER(app), uinfo->winbox);
295 gtk_widget_show(uinfo->winbox);
296 gtk_widget_show(app);
297
298 CheckNewDisc(ginfo,FALSE);
299
300 /* Check if we're running this version for the first time */
301 if(strcmp(VERSION,ginfo->version)!=0) {
302 strcpy(ginfo->version,VERSION);
303
304 sscanf(VERSION,"%d.%d.%d",&major,&minor,&point);
305
306 /* Check if we have a dev release */
307 /*if(minor%2) {
308 DisplayMsg(GTK_MESSAGE_WARNING, (GtkWindow *)ginfo->gui_info.app,
309 _("This is a development version of Grip. If you encounter problems, you are encouraged to revert to the latest stable version."));
310 }*/
311 }
312
313 g_signal_connect(app, "window-state-event", G_CALLBACK(AppWindowStateCB), ginfo);
314
315 return app;
316 }
317
GripDie(GtkWidget * widget,gpointer data)318 void GripDie(GtkWidget *widget,gpointer data)
319 {
320 GripInfo *ginfo;
321
322 ginfo=(GripInfo *)gtk_object_get_user_data(GTK_OBJECT(widget));
323
324 if(ginfo->ripping_a_disc || ginfo->encoding)
325 ReallyDie(ConfirmDialog ((GtkWindow *)ginfo->gui_info.app,
326 _("Work is in progress.\nReally shut down?")),
327 ginfo);
328 else
329 ReallyDie(0,ginfo);
330 }
331
ReallyDie(gint reply,gpointer data)332 static void ReallyDie(gint reply,gpointer data)
333 {
334 GripInfo *ginfo;
335
336 if(reply) return;
337
338 ginfo=(GripInfo *)data;
339
340 if(ginfo->ripping_a_disc) KillRip(NULL,ginfo);
341 if(ginfo->encoding) KillEncode(NULL,ginfo);
342
343 if(!ginfo->no_interrupt)
344 CDStop(&(ginfo->disc));
345
346 DoSaveConfig(ginfo);
347
348 gtk_main_quit();
349 }
350
MakeNewPage(GtkWidget * notebook,char * name)351 GtkWidget *MakeNewPage(GtkWidget *notebook,char *name)
352 {
353 GtkWidget *page;
354 GtkWidget *label;
355
356 page=gtk_frame_new(NULL);
357 gtk_widget_show(page);
358
359 label=gtk_label_new(name);
360 gtk_notebook_append_page(GTK_NOTEBOOK(notebook),page,label);
361
362 return page;
363 }
364
DoHelp(GtkWidget * widget,gpointer data)365 static void DoHelp(GtkWidget *widget, gpointer data)
366 {
367 GdkScreen *screen;
368 GError *error = NULL;
369
370 screen = gtk_widget_get_screen (widget);
371
372 gtk_show_uri(screen, "ghelp:grip", gtk_get_current_event_time(), &error);
373
374 if (error != NULL) {
375 GtkWidget *d;
376 GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
377
378 d = gtk_message_dialog_new(GTK_IS_WINDOW(toplevel) ? GTK_WINDOW(toplevel) : NULL,
379 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
380 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
381 "%s", _("Unable to open help file"));
382 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (d),
383 "%s", error->message);
384 g_signal_connect (d, "response", G_CALLBACK (gtk_widget_destroy), NULL);
385 gtk_window_present (GTK_WINDOW (d));
386
387 g_error_free (error);
388 }
389 }
390
MakeHelpPage(GripInfo * ginfo)391 static void MakeHelpPage(GripInfo *ginfo)
392 {
393 GtkWidget *help_page;
394 GtkWidget *button;
395 GtkWidget *vbox;
396
397 help_page=MakeNewPage(ginfo->gui_info.notebook,_("Help"));
398
399 vbox=gtk_vbox_new(FALSE,0);
400 gtk_container_border_width(GTK_CONTAINER(vbox),3);
401
402 button=gtk_button_new_with_label(_("Table Of Contents"));
403 gtk_signal_connect(GTK_OBJECT(button), "clicked",
404 GTK_SIGNAL_FUNC(DoHelp), NULL);
405 gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
406 gtk_widget_show(button);
407
408 gtk_container_add(GTK_CONTAINER(help_page),vbox);
409 gtk_widget_show(vbox);
410 }
411
MakeAboutPage(GripGUI * uinfo)412 void MakeAboutPage(GripGUI *uinfo)
413 {
414 GtkWidget *aboutpage;
415 GtkWidget *vbox,*vbox2,*hbox;
416 GtkWidget *label;
417 GtkWidget *logo;
418 GtkWidget *ebox;
419 GtkWidget *button;
420 gchar *versionbuf;
421
422 aboutpage=MakeNewPage(uinfo->notebook,_("About"));
423
424 ebox=gtk_event_box_new();
425 gtk_widget_set_style(ebox,uinfo->style_wb);
426
427 vbox=gtk_vbox_new(TRUE,5);
428 gtk_container_border_width(GTK_CONTAINER(vbox),3);
429
430 logo=Loadxpm(GTK_WIDGET(uinfo->app),grip_xpm);
431
432 gtk_box_pack_start(GTK_BOX(vbox),logo,FALSE,FALSE,0);
433 gtk_widget_show(logo);
434
435 vbox2=gtk_vbox_new(TRUE,0);
436
437 versionbuf = g_strdup_printf(_("Version %s"),VERSION);
438 label=gtk_label_new(versionbuf);
439 g_free(versionbuf);
440
441 gtk_widget_set_style(label,uinfo->style_wb);
442 gtk_box_pack_start(GTK_BOX(vbox2),label,FALSE,FALSE,0);
443 gtk_widget_show(label);
444
445 label=gtk_label_new("Copyright\n1998-2005, Mike Oliphant\n2016-2021, Johnny A. Solbu");
446 gtk_widget_set_style(label,uinfo->style_wb);
447 gtk_box_pack_start(GTK_BOX(vbox2),label,FALSE,FALSE,0);
448 gtk_widget_show(label);
449
450 #if defined(__sun__)
451 label=gtk_label_new("Solaris Port, David Meleedy");
452 gtk_widget_set_style(label,uinfo->style_wb);
453 gtk_box_pack_start(GTK_BOX(vbox2),label,FALSE,FALSE,0);
454 gtk_widget_show(label);
455 #endif
456
457 hbox=gtk_hbox_new(TRUE,0);
458
459 button=gtk_button_new_with_label(PACKAGE_BUGREPORT);
460 gtk_widget_set_style(button,uinfo->style_dark_grey);
461 gtk_widget_set_style(GTK_BIN(button)->child,
462 uinfo->style_dark_grey);
463 gtk_signal_connect(GTK_OBJECT(button),"clicked",
464 GTK_SIGNAL_FUNC(Homepage),uinfo);
465 gtk_box_pack_start(GTK_BOX(hbox),button,FALSE,FALSE,0);
466 gtk_widget_show(button);
467
468 gtk_box_pack_start(GTK_BOX(vbox2),hbox,FALSE,FALSE,0);
469 gtk_widget_show(hbox);
470
471
472 gtk_container_add(GTK_CONTAINER(vbox),vbox2);
473 gtk_widget_show(vbox2);
474
475 gtk_container_add(GTK_CONTAINER(ebox),vbox);
476 gtk_widget_show(vbox);
477
478 gtk_container_add(GTK_CONTAINER(aboutpage),ebox);
479 gtk_widget_show(ebox);
480 }
481
MakeStyles(GripGUI * uinfo)482 static void MakeStyles(GripGUI *uinfo)
483 {
484 GdkColor gdkblack;
485 GdkColor gdkwhite;
486 GdkColor *color_LCD;
487 GdkColor *color_dark_grey;
488
489 gdk_color_white(gdk_colormap_get_system(),&gdkwhite);
490 gdk_color_black(gdk_colormap_get_system(),&gdkblack);
491
492 color_LCD=MakeColor(33686,38273,29557);
493 color_dark_grey=MakeColor(0x4444,0x4444,0x4444);
494
495 uinfo->style_wb=MakeStyle(&gdkwhite,&gdkblack,FALSE);
496 uinfo->style_LCD=MakeStyle(color_LCD,color_LCD,FALSE);
497 uinfo->style_dark_grey=MakeStyle(&gdkwhite,color_dark_grey,TRUE);
498 }
499
Homepage(GtkWidget * widget,gpointer data)500 static void Homepage(GtkWidget *widget,gpointer data)
501 {
502 GripGUI *uinfo=(GripGUI *)data;
503 if (!gtk_show_uri(gtk_widget_get_screen (widget), PACKAGE_BUGREPORT,
504 gtk_get_current_event_time(), NULL))
505 DisplayMsg(GTK_MESSAGE_WARNING, (GtkWindow *)uinfo->app,
506 _("Error: Trying to show homepage failed."));
507 }
508
LoadImages(GripGUI * uinfo)509 static void LoadImages(GripGUI *uinfo)
510 {
511 uinfo->check_image=Loadxpm(uinfo->app,check_xpm);
512 uinfo->eject_image=Loadxpm(uinfo->app,eject_xpm);
513 uinfo->cdscan_image=Loadxpm(uinfo->app,cdscan_xpm);
514 uinfo->ff_image=Loadxpm(uinfo->app,ff_xpm);
515 uinfo->lowleft_image=Loadxpm(uinfo->app,lowleft_xpm);
516 uinfo->lowright_image=Loadxpm(uinfo->app,lowright_xpm);
517 uinfo->minmax_image=Loadxpm(uinfo->app,minmax_xpm);
518 uinfo->nexttrk_image=Loadxpm(uinfo->app,nexttrk_xpm);
519 uinfo->playpaus_image=Loadxpm(uinfo->app,playpaus_xpm);
520 uinfo->prevtrk_image=Loadxpm(uinfo->app,prevtrk_xpm);
521 uinfo->loop_image=Loadxpm(uinfo->app,loop_xpm);
522 uinfo->noloop_image=Loadxpm(uinfo->app,noloop_xpm);
523 uinfo->random_image=Loadxpm(uinfo->app,random_xpm);
524 uinfo->playlist_image=Loadxpm(uinfo->app,playlist_xpm);
525 uinfo->playnorm_image=Loadxpm(uinfo->app,playnorm_xpm);
526 uinfo->quit_image=Loadxpm(uinfo->app,quit_xpm);
527 uinfo->rew_image=Loadxpm(uinfo->app,rew_xpm);
528 uinfo->stop_image=Loadxpm(uinfo->app,stop_xpm);
529 uinfo->upleft_image=Loadxpm(uinfo->app,upleft_xpm);
530 uinfo->upright_image=Loadxpm(uinfo->app,upright_xpm);
531 uinfo->vol_image=Loadxpm(uinfo->app,vol_xpm);
532 uinfo->discdbwht_image=Loadxpm(uinfo->app,discdbwht_xpm);
533 uinfo->rotate_image=Loadxpm(uinfo->app,rotate_xpm);
534 uinfo->edit_image=Loadxpm(uinfo->app,edit_xpm);
535 uinfo->progtrack_image=Loadxpm(uinfo->app,progtrack_xpm);
536 uinfo->mail_image=Loadxpm(uinfo->app,mail_xpm);
537 uinfo->save_image=Loadxpm(uinfo->app,save_xpm);
538
539 uinfo->empty_image=NewBlankPixmap(uinfo->app);
540
541 uinfo->discdb_pix[0]=Loadxpm(uinfo->app,discdb0_xpm);
542 uinfo->discdb_pix[1]=Loadxpm(uinfo->app,discdb1_xpm);
543
544 uinfo->play_pix[0]=Loadxpm(uinfo->app,playnorm_xpm);
545 uinfo->play_pix[1]=Loadxpm(uinfo->app,random_xpm);
546 uinfo->play_pix[2]=Loadxpm(uinfo->app,playlist_xpm);
547
548 uinfo->rip_pix[0]=Loadxpm(uinfo->app,rip0_xpm);
549 uinfo->rip_pix[1]=Loadxpm(uinfo->app,rip1_xpm);
550 uinfo->rip_pix[2]=Loadxpm(uinfo->app,rip2_xpm);
551 uinfo->rip_pix[3]=Loadxpm(uinfo->app,rip3_xpm);
552
553 uinfo->mp3_pix[0]=Loadxpm(uinfo->app,enc0_xpm);
554 uinfo->mp3_pix[1]=Loadxpm(uinfo->app,enc1_xpm);
555 uinfo->mp3_pix[2]=Loadxpm(uinfo->app,enc2_xpm);
556 uinfo->mp3_pix[3]=Loadxpm(uinfo->app,enc3_xpm);
557
558 uinfo->smile_pix[0]=Loadxpm(uinfo->app,smile1_xpm);
559 uinfo->smile_pix[1]=Loadxpm(uinfo->app,smile2_xpm);
560 uinfo->smile_pix[2]=Loadxpm(uinfo->app,smile3_xpm);
561 uinfo->smile_pix[3]=Loadxpm(uinfo->app,smile4_xpm);
562 uinfo->smile_pix[4]=Loadxpm(uinfo->app,smile5_xpm);
563 uinfo->smile_pix[5]=Loadxpm(uinfo->app,smile6_xpm);
564 uinfo->smile_pix[6]=Loadxpm(uinfo->app,smile7_xpm);
565 uinfo->smile_pix[7]=Loadxpm(uinfo->app,smile8_xpm);
566 }
567
GripUpdate(GtkWidget * app)568 void GripUpdate(GtkWidget *app)
569 {
570 GripInfo *ginfo;
571 time_t secs;
572
573 ginfo=(GripInfo *)gtk_object_get_user_data(GTK_OBJECT(app));
574
575 if(ginfo->ffwding) FastFwd(ginfo);
576 if(ginfo->rewinding) Rewind(ginfo);
577
578 secs=time(NULL);
579
580 /* Make sure we don't mod by zero */
581 if(!ginfo->poll_interval)
582 ginfo->poll_interval=1;
583
584 if(ginfo->ripping|ginfo->encoding) UpdateRipProgress(ginfo);
585
586 if(!ginfo->ripping_a_disc) {
587 if(ginfo->poll_drive && !(secs%ginfo->poll_interval)) {
588 if(!ginfo->have_disc)
589 CheckNewDisc(ginfo,FALSE);
590 }
591
592 UpdateDisplay(ginfo);
593 }
594
595 UpdateTray(ginfo);
596 }
597
Busy(GripGUI * uinfo)598 void Busy(GripGUI *uinfo)
599 {
600 gdk_window_set_cursor(uinfo->app->window,uinfo->wait_cursor);
601
602 UpdateGTK();
603 }
604
UnBusy(GripGUI * uinfo)605 void UnBusy(GripGUI *uinfo)
606 {
607 gdk_window_set_cursor(uinfo->app->window,NULL);
608
609 UpdateGTK();
610 }
611
DoLoadConfig(GripInfo * ginfo)612 static void DoLoadConfig(GripInfo *ginfo)
613 {
614 GripGUI *uinfo=&(ginfo->gui_info);
615 char filename[512];
616 char renamefile[520];
617 char outputdir[256];
618 int confret;
619 CFGEntry cfg_entries[]={
620 CFG_ENTRIES
621 {"outputdir",CFG_ENTRY_STRING,256,outputdir},
622 {"",CFG_ENTRY_LAST,0,NULL}
623 };
624
625 outputdir[0]='\0';
626
627 uinfo->minimized=FALSE;
628 uinfo->volvis=FALSE;
629 uinfo->track_prog_visible=FALSE;
630 uinfo->track_edit_visible=FALSE;
631
632 uinfo->wait_cursor=gdk_cursor_new(GDK_WATCH);
633
634 uinfo->tray_icon=NULL;
635
636 uinfo->id3_genre_item_list=NULL;
637
638 *ginfo->version='\0';
639
640 strcpy(ginfo->cd_device,"/dev/cd0");
641 *ginfo->force_scsi='\0';
642
643 ginfo->local_mode=FALSE;
644 ginfo->have_disc=FALSE;
645 ginfo->tray_open=FALSE;
646 ginfo->faulty_eject=FALSE;
647 ginfo->looking_up=FALSE;
648 ginfo->play_mode=PM_NORMAL;
649 ginfo->playloop=TRUE;
650 ginfo->automatic_reshuffle=TRUE;
651 ginfo->ask_submit=FALSE;
652 ginfo->is_new_disc=FALSE;
653 ginfo->first_time=TRUE;
654 ginfo->automatic_discdb=TRUE;
655 ginfo->auto_eject_countdown=0;
656 ginfo->current_discid=0;
657 ginfo->volume=255;
658 #if defined(__FreeBSD__) || defined(__NetBSD__)
659 ginfo->poll_drive=FALSE;
660 ginfo->poll_interval=15;
661 #else
662 ginfo->poll_drive=TRUE;
663 ginfo->poll_interval=1;
664 #endif
665
666 ginfo->changer_slots=0;
667 ginfo->current_disc=0;
668
669 ginfo->proxy_server.name[0]='\0';
670 ginfo->proxy_server.port=8000;
671 ginfo->use_proxy=FALSE;
672 ginfo->use_proxy_env=FALSE;
673
674 strcpy(ginfo->dbserver.name,"gnudb.gnudb.org");
675 strcpy(ginfo->dbserver.cgi_prog,"~cddb/cddb.cgi");
676 ginfo->dbserver.port=80;
677 ginfo->dbserver.use_proxy=0;
678 ginfo->dbserver.proxy=&(ginfo->proxy_server);
679
680 strcpy(ginfo->dbserver2.name,"");
681 strcpy(ginfo->dbserver2.cgi_prog,"~cddb/cddb.cgi");
682 ginfo->dbserver2.port=80;
683 ginfo->dbserver2.use_proxy=0;
684 ginfo->dbserver2.proxy=&(ginfo->proxy_server);
685
686 strcpy(ginfo->discdb_submit_email,"submit@gnudb.org");
687 ginfo->db_use_freedb=TRUE;
688 *ginfo->user_email='\0';
689
690 strcpy(ginfo->discdb_encoding,"UTF-8");
691 strcpy(ginfo->id3_encoding,"UTF-8");
692 strcpy(ginfo->id3v2_encoding,"UTF-8");
693
694 ginfo->local_mode=FALSE;
695 ginfo->update_required=FALSE;
696 ginfo->looking_up=FALSE;
697 ginfo->ask_submit=FALSE;
698 ginfo->is_new_disc=FALSE;
699 ginfo->automatic_discdb=TRUE;
700 ginfo->play_first=TRUE;
701 ginfo->play_on_insert=FALSE;
702 ginfo->stop_first=FALSE;
703 ginfo->no_interrupt=FALSE;
704 ginfo->playing=FALSE;
705 ginfo->stopped=FALSE;
706 ginfo->ffwding=FALSE;
707 ginfo->rewinding=FALSE;
708
709 strcpy(ginfo->title_split_chars,"/");
710
711 ginfo->curr_pipe_fd=-1;
712
713 ginfo->num_cpu=1;
714 ginfo->ripping=FALSE;
715 ginfo->ripping_a_disc=FALSE;
716 ginfo->encoding=FALSE;
717 ginfo->rip_partial=FALSE;
718 ginfo->stop_rip=FALSE;
719 ginfo->stop_encode=FALSE;
720 ginfo->rip_finished=0;
721 ginfo->num_wavs=0;
722 ginfo->doencode=FALSE;
723 ginfo->encode_list=NULL;
724 ginfo->pending_list=NULL;
725 ginfo->delayed_encoding = 0;
726 ginfo->do_redirect=TRUE;
727 ginfo->selected_ripper=0;
728 #ifdef CDPAR
729 ginfo->stop_thread_rip_now=FALSE;
730 ginfo->using_builtin_cdp=TRUE;
731 ginfo->disable_paranoia=FALSE;
732 ginfo->disable_extra_paranoia=FALSE;
733 ginfo->disable_scratch_detect=FALSE;
734 ginfo->disable_scratch_repair=FALSE;
735 ginfo->calc_gain=FALSE;
736 #else
737 ginfo->using_builtin_cdp=FALSE;
738 #endif
739 ginfo->in_rip_thread=FALSE;
740 strcpy(ginfo->ripfileformat,"~/ogg/%A/%d/%n.wav");
741 strcpy(ginfo->ripfileformat_multi,"~/ogg/%A/%d/%a_%n.wav");
742 #ifdef __linux__
743 FindExeInPath("cdparanoia", ginfo->ripexename, sizeof(ginfo->ripexename));
744 strcpy(ginfo->ripcmdline,"-d %c %t:[.%s]-%t:[.%e] %w");
745 #else
746 FindExeInPath("cdda2wav", ginfo->ripexename, sizeof(ginfo->ripexename));
747 #ifdef __sun__
748 strcpy(ginfo->ripcmdline,"-x -H -t %t -O wav %w");
749 #else
750 strcpy(ginfo->ripcmdline,"-D %C -x -H -t %t -O wav %w");
751 #endif /* not sun */
752 #endif /* not linux */
753
754 ginfo->ripnice=0;
755 ginfo->max_wavs=99;
756 ginfo->auto_rip=FALSE;
757 ginfo->beep_after_rip=TRUE;
758 ginfo->eject_after_rip=TRUE;
759 ginfo->eject_delay=0;
760 ginfo->delay_before_rip=FALSE;
761 ginfo->stop_between_tracks=FALSE;
762 *ginfo->wav_filter_cmd='\0';
763 *ginfo->disc_filter_cmd='\0';
764 ginfo->selected_encoder=0;
765 strcpy(ginfo->mp3cmdline,"-o %m -a %a -l %d -t %n -b %b %w -N %t -G %G -d %y");
766 FindExeInPath("oggenc", ginfo->mp3exename, sizeof(ginfo->mp3exename));
767 strcpy(ginfo->mp3fileformat,"~/ogg/%A/%d/%t_%n.%x");
768 strcpy(ginfo->mp3fileformat_multi,"~/ogg/%A/%d/%t_%a_%n.%x");
769 strcpy(ginfo->mp3extension,"ogg");
770 ginfo->mp3nice=0;
771 *ginfo->mp3_filter_cmd='\0';
772 ginfo->delete_wavs=TRUE;
773 ginfo->add_to_db=FALSE;
774 ginfo->add_m3u=TRUE;
775 ginfo->rel_m3u=TRUE;
776 strcpy(ginfo->m3ufileformat,"~/ogg/%A-%d.m3u");
777 ginfo->kbits_per_sec=192;
778 ginfo->edit_num_cpu=1;
779 ginfo->doid3=TRUE;
780 ginfo->doid3=FALSE;
781 ginfo->tag_mp3_only=TRUE;
782 strcpy(ginfo->id3_comment,_("Created by Grip"));
783 *ginfo->cdupdate='\0';
784 ginfo->sprefs.no_lower_case=FALSE;
785 ginfo->sprefs.allow_high_bits=FALSE;
786 ginfo->sprefs.escape=FALSE;
787 ginfo->sprefs.no_underscore=FALSE;
788 ginfo->sprefs.non_posix_m3u_directory_paths=FALSE;
789 *ginfo->sprefs.allow_these_chars='\0';
790 ginfo->show_tray_icon=TRUE;
791
792 sprintf(filename,"%s/%s", g_get_home_dir(), ginfo->config_filename);
793
794 confret=LoadConfig(filename,"GRIP",2,2,cfg_entries);
795
796 if(confret<0) {
797 /* Check if the config is out of date */
798 if(confret==-2) {
799 DisplayMsg(GTK_MESSAGE_WARNING, (GtkWindow *)ginfo->gui_info.app,
800 _("Your config file is out of date -- "
801 "resetting to defaults.\n"
802 "You will need to re-configure Grip.\n"
803 "Your old config file has been saved with -old appended."));
804
805 sprintf(renamefile,"%s-old",filename);
806
807 rename(filename,renamefile);
808 }
809
810 DoSaveConfig(ginfo);
811 }
812
813 LoadRipperConfig(ginfo,ginfo->selected_ripper);
814 LoadEncoderConfig(ginfo,ginfo->selected_encoder);
815
816 /* Phase out 'outputdir' variable */
817
818 if(*outputdir) {
819 strcpy(filename,outputdir);
820 MakePath(filename);
821 strcat(filename,ginfo->mp3fileformat);
822 strcpy(ginfo->mp3fileformat,filename);
823
824 strcpy(filename,outputdir);
825 MakePath(filename);
826 strcat(filename,ginfo->mp3fileformat_multi);
827 strcpy(ginfo->mp3fileformat_multi,filename);
828
829 strcpy(filename,outputdir);
830 MakePath(filename);
831 strcat(filename,ginfo->ripfileformat);
832 strcpy(ginfo->ripfileformat,filename);
833
834 strcpy(filename,outputdir);
835 MakePath(filename);
836 strcat(filename,ginfo->ripfileformat_multi);
837 strcpy(ginfo->ripfileformat_multi,filename);
838
839 *outputdir='\0';
840 }
841
842 ginfo->dbserver2.use_proxy=ginfo->dbserver.use_proxy=ginfo->use_proxy;
843 ginfo->dbserver2.proxy=ginfo->dbserver.proxy;
844
845 ginfo->num_cpu=ginfo->edit_num_cpu;
846
847 if(!*ginfo->user_email) {
848 g_snprintf(ginfo->user_email, 256, "%s@%s", g_get_user_name(), g_get_host_name());
849 }
850
851 if(ginfo->use_proxy_env) { /* Get proxy info from "http_proxy" */
852 char * const proxy_env = g_strdup (g_getenv ("http_proxy"));
853 if(proxy_env) {
854 LoadProxyConfig(ginfo, proxy_env);
855 }
856 g_free (proxy_env);
857 }
858 }
859
860 /** Extract proxy server name and port from proxy_env and update ginfo */
LoadProxyConfig(GripInfo * const ginfo,char * proxy_env)861 void LoadProxyConfig(GripInfo * const ginfo, char* proxy_env)
862 {
863 g_assert(ginfo);
864 g_assert(proxy_env);
865
866 /* Skip the "http://" if it's present */
867 const char* SCHEME_PFX = "http://";
868 if(!strncasecmp(proxy_env, SCHEME_PFX, strlen(SCHEME_PFX))) proxy_env += strlen(SCHEME_PFX);
869
870 char *tok=strtok(proxy_env,":");
871 if(tok) strncpy(ginfo->proxy_server.name,tok,255);
872
873 /* Make sure ginfo->proxy_server.name is terminated correctly. */
874 ginfo->proxy_server.name[255] = 0;
875
876 tok=strtok(NULL,"/");
877 if(tok) ginfo->proxy_server.port=atoi(tok);
878
879 Debug(_("server is %s, port %d\n"), ginfo->proxy_server.name,
880 ginfo->proxy_server.port);
881 }
882
DoSaveConfig(GripInfo * ginfo)883 void DoSaveConfig(GripInfo *ginfo)
884 {
885 char filename[256];
886 GripGUI *uinfo=&(ginfo->gui_info);
887 CFGEntry cfg_entries[]={
888 CFG_ENTRIES
889 {"",CFG_ENTRY_LAST,0,NULL}
890 };
891
892 if(ginfo->edit_num_cpu>MAX_NUM_CPU) ginfo->edit_num_cpu=MAX_NUM_CPU;
893
894 g_snprintf(filename,256,"%s/%s", g_get_home_dir(), ginfo->config_filename);
895
896 if(!SaveConfig(filename,"GRIP",2,cfg_entries))
897 DisplayMsg(GTK_MESSAGE_WARNING, (GtkWindow *)ginfo->gui_info.app,
898 _("Error: Unable to save config file."));
899
900 SaveRipperConfig(ginfo,ginfo->selected_ripper);
901 SaveEncoderConfig(ginfo,ginfo->selected_encoder);
902 }
903
904 /* Shut down stuff (generally before an exec) */
CloseStuff(void * user_data)905 void CloseStuff(void *user_data)
906 {
907 GripInfo *ginfo;
908 int fd;
909
910 ginfo=(GripInfo *)user_data;
911
912 close(ConnectionNumber(GDK_DISPLAY()));
913 close(ginfo->disc.cd_desc);
914
915 fd=open("/dev/null",O_RDWR);
916 dup2(fd,0);
917
918 if(ginfo->do_redirect) {
919 if(ginfo->curr_pipe_fd>0) {
920 dup2(ginfo->curr_pipe_fd,1);
921 dup2(ginfo->curr_pipe_fd,2);
922
923 ginfo->curr_pipe_fd=-1;
924 }
925 else {
926 dup2(fd,1);
927 dup2(fd,2);
928 }
929 }
930
931 /* Close any other filehandles that might be around */
932 for(fd=3;fd<NOFILE;fd++) {
933 close(fd);
934 }
935 }
936