1 /* cdrecord.c
2 * Copyright (C) 2004, 2005 Sylvain Cresto <scresto@gmail.com>
3 *
4 * This file is part of graveman!
5 *
6 * graveman! is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or
9 * (at your option) any later version.
10 *
11 * graveman! is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with program; see the file COPYING. If not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
19 * MA 02111-1307, USA.
20 *
21 * URL: http://www.nongnu.org/graveman/
22 *
23 */
24
25 #include "graveman.h"
26
27 /* communication avec cdrecord */
28
29 #define SCANDEVICE "scsibus"
30 #define CDRECORD_NOSUCHFILE "No read access for"
31 #define CDRECORD_COPY "Track"
32 #define CDRECORD_OF "of"
33 #define CDRECORD_MB "MB"
34 #define CDRECORD_FIFO "fifo"
35 #define CDRECORD_BUF "buf"
36 #define CDRECORD_STATUS "fifo was "
37 #define CDRECORD_ERRORDISK "No disk / Wrong disk"
38 #define CDRECORD_INAPPROPRIATE "Inappropriate audio coding"
39 #define CDRECORD_INPUTOUTPUT_ERROR "Input/output error."
40 #define CDRECORD_FIXATING "Fixating..."
41 #define CDRECORD_BLANKING "Blanking "
42 #define CDRECORD_BAD_RECORDER "Sorry, no CD/DVD-Recorder or unsupported CD/DVD-Recorder found"
43 #define CDRECORD_CANNOT_OPEN "Cannot open"
44
45 /* support du materiel */
46 #define CDRECORD_NOT_READ_CD "Does not read CD-R media"
47 #define CDRECORD_READ_CD "Does read CD-R media"
48 #define CDRECORD_NOT_WRITE_CDR "Does not write CD-R media"
49 #define CDRECORD_WRITE_CDR "Does write CD-R media"
50 #define CDRECORD_NOT_WRITE_CDRW "Does not write CD-RW media"
51 #define CDRECORD_WRITE_CDRW "Does write CD-RW media"
52 #define CDRECORD_READ_DVD "Does read DVD-ROM media"
53 #define CDRECORD_WRITE_DVD "Does write DVD-R media"
54 #define CDRECORD_NOT_WRITE_DVD "Does not write DVD-R media"
55 #define CDRECORD_NOT_WRITE_DUMMY "Does not support test writing"
56 #define CDRECORD_MAX_CDREAD_SPEED "Maximum read speed:"
57 #define CDRECORD_MAX_CDREAD_SPEED_CD "(CD"
58 #define CDRECORD_MAX_CDREAD_SPEED_DVD " DVD "
59 #define CDRECORD_BURNFREE "Prepare writer to use BURN-Free technology"
60
61 /* effacer un cdrw ou cloturer un cdr */
62 #define CDRECORD_BLANKING_TIME "Blanking time:"
63 #define CDRECORD_CANNOT_BLANK "Cannot blank disk, aborting"
64 #define CDRECORD_INCOMPATIBLE_MEDIUM "cannot format medium - incmedium"
65 #define CDRECORD_FIXATING_TIME "Fixating time:"
66
67
68 /* definition de tous les type de bus */
69 Tsearchdrive listesearchdrives[] = {
70 { "", "", "SCSI", 110 }, /* scsi (sg) */
71 #if LINUX_IDE /* pure ide devices with linux */
72 { "dev=/dev/hda", "/dev/hda", "IDE", 100 },
73 { "dev=/dev/hdb", "/dev/hdb", "IDE", 100 },
74 { "dev=/dev/hdc", "/dev/hdc", "IDE", 100 },
75 { "dev=/dev/hdd", "/dev/hdd", "IDE", 100 },
76 { "dev=/dev/hde", "/dev/hde", "IDE", 100 },
77 { "dev=/dev/hdf", "/dev/hdf", "IDE", 100 },
78 { "dev=/dev/hdg", "/dev/hdg", "IDE", 100 },
79 { "dev=/dev/hdh", "/dev/hdh", "IDE", 100 },
80 { "dev=/dev/hdi", "/dev/hdi", "IDE", 100 },
81 { "dev=/dev/hdj", "/dev/hdj", "IDE", 100 },
82 #endif
83 #if LINUX_SCSI /* SCSI alias with linux */
84 { "dev=/dev/scd0", "/dev/scd0", "SCSI-D", 90 },
85 { "dev=/dev/scd1", "/dev/scd1", "SCSI-D", 90 },
86 { "dev=/dev/scd2", "/dev/scd2", "SCSI-D", 90 },
87 { "dev=/dev/scd3", "/dev/scd3", "SCSI-D", 90 },
88 { "dev=/dev/scd4", "/dev/scd4", "SCSI-D", 90 },
89 { "dev=/dev/scd5", "/dev/scd5", "SCSI-D", 90 },
90 { "dev=/dev/scd6", "/dev/scd6", "SCSI-D", 90 },
91 { "dev=/dev/sr0", "/dev/sr0", "SCSI-S", 92 },
92 { "dev=/dev/sr1", "/dev/sr1", "SCSI-S", 92 },
93 { "dev=/dev/sr2", "/dev/sr2", "SCSI-S", 92 },
94 { "dev=/dev/sr3", "/dev/sr3", "SCSI-S", 92 },
95 { "dev=/dev/sr4", "/dev/sr4", "SCSI-S", 92 },
96 { "dev=/dev/sr5", "/dev/sr5", "SCSI-S", 92 },
97 { "dev=/dev/sr6", "/dev/sr6", "SCSI-S", 92 },
98 { "dev=/dev/sg0", "/dev/sg0", "SCSI-G", 94 },
99 { "dev=/dev/sg1", "/dev/sg1", "SCSI-G", 94 },
100 { "dev=/dev/sg2", "/dev/sg2", "SCSI-G", 94 },
101 { "dev=/dev/sg3", "/dev/sg3", "SCSI-G", 94 },
102 { "dev=/dev/sg4", "/dev/sg4", "SCSI-G", 94 },
103 { "dev=/dev/sg5", "/dev/sg5", "SCSI-G", 94 },
104 { "dev=/dev/sg6", "/dev/sg6", "SCSI-G", 94 },
105 { "dev=/dev/sga", "/dev/sga", "SCSI-g", 96 },
106 { "dev=/dev/sgb", "/dev/sgb", "SCSI-g", 96 },
107 { "dev=/dev/sgc", "/dev/sgc", "SCSI-g", 96 },
108 { "dev=/dev/sgd", "/dev/sgd", "SCSI-g", 96 },
109 { "dev=/dev/sge", "/dev/sge", "SCSI-g", 96 },
110 { "dev=/dev/sgf", "/dev/sgf", "SCSI-g", 96 },
111 { "dev=/dev/sgg", "/dev/sgg", "SCSI-g", 96 },
112 #endif
113 { "dev=ATA:", "ATA:", "ATA", 60 }, /* ide sg */
114 { "dev=ATAPI:", "ATAPI:", "ATAPI", 40 }, /* ide */
115 { NULL, NULL, NULL, 0}
116 };
117
118 gboolean cdrecord_grave_callback(GIOChannel *Astd, GIOCondition Acond, gpointer Adata);
119
get_title(gint Anbrgravure,gint Acurcd,gboolean Adosimul)120 static gchar *get_title(gint Anbrgravure, gint Acurcd, gboolean Adosimul)
121 {
122 gchar *Ltxt = NULL;
123 if (Anbrgravure==1) {
124 if (!Adosimul) {
125 Ltxt = g_strdup(_("Writing in progress..."));
126 } else {
127 Ltxt = g_strdup(_("Simulated CD writing in progress..."));
128 }
129 } else {
130 if (!Adosimul) {
131 Ltxt = g_strdup_printf(_("Writing CD %d/%d in progress..."), Acurcd, Anbrgravure);
132 } else {
133 Ltxt = g_strdup_printf(_("Simulated CD writing %d/%d in progress..."), Acurcd, Anbrgravure);
134 }
135 }
136
137 return Ltxt;
138 }
139
140 /* recherche des lecteurs */
cdrecord_extractlecteur(gchar * Achaine,gchar ** Adev,gchar ** Amarque,gchar ** Amodel,gchar ** Aquoi)141 gboolean cdrecord_extractlecteur(gchar *Achaine, gchar **Adev, gchar **Amarque, gchar **Amodel,
142 gchar **Aquoi)
143 {
144 gchar *s = Achaine;
145 gint Lnbnbr = 0;
146 gint Lnbvirg = 0;
147 gint Lsize = 0;
148
149 while (isdigit(*s) || *s==',') {
150 if (*(s++)==',') { Lnbvirg++; } else { Lnbnbr++; }
151 }
152 if (!*s) return FALSE;
153 *(s++)=0;
154 g_strstrip(s);
155
156 if (*s && Lnbvirg == 2 && Lnbnbr>2) {
157 gchar **Linfo = g_strsplit(s, "'", 10);
158 Lsize = sc_strcountv(Linfo);
159 sc_strstripv(Linfo);
160
161 if (Lsize>=6) {
162 *Adev = g_strdup(Achaine);
163 *Amarque = _UTF8(Linfo[1]);
164 *Amodel = _UTF8(Linfo[3]);
165 *Aquoi = _UTF8(Linfo[6]);
166 }
167
168 g_strfreev(Linfo);
169 }
170 return Lsize >= 6 ? TRUE : FALSE;
171 }
172
173 /* callback detection des lecteurs et graveurs */
scan_callback(GIOChannel * Astd,GIOCondition Acond,gpointer Adata)174 gboolean scan_callback(GIOChannel *Astd, GIOCondition Acond, gpointer Adata)
175 {
176 GIOStatus Lstatus;
177 Tgrave *Lg = (Tgrave *)Adata;
178 gint *Lcont = (gint *)sc_grave_get_data(Lg, "cont");
179 Tsearchdrive *Ldrivedesc = (Tsearchdrive *)sc_grave_get_data(Lg, "drivedesc");
180 gchar *Lbuffer = NULL;
181 gchar *Lmodel, *Lmarque, *Ldev, *Lquoi;
182
183 /* fin du callback lorsque l'on recoi un signal comme quoi le pipe est ferme */
184 if (Acond == G_IO_HUP || Acond == G_IO_ERR) {
185 *Lcont = 2;
186 return FALSE;
187 }
188
189 Lstatus = g_io_channel_read_line(Astd, &Lbuffer, NULL, NULL, NULL);
190 if (!Lbuffer) {
191 if (Lstatus == G_IO_STATUS_EOF) {
192 *Lcont = 2;
193 return FALSE;
194 } else
195 return TRUE;
196 }
197
198 g_strstrip(Lbuffer);
199 _DEB("scan lecteur = %s\n", Lbuffer);
200 if (strstr(Lbuffer, CDRECORD_CANNOT_OPEN)) {
201 *Lcont = 2;
202 return FALSE;
203 }
204
205 if (cdrecord_extractlecteur(Lbuffer, &Ldev, &Lmarque, &Lmodel, &Lquoi) == TRUE) {
206
207 matos_insert_or_update_drive(Ldev, Lmarque, Lmodel, Lquoi, Ldrivedesc);
208
209 _DEB("oui un lecteur");
210
211 g_free(Lquoi);
212 g_free(Lmodel);
213 g_free(Lmarque);
214 g_free(Ldev);
215 }
216
217 g_free(Lbuffer);
218
219 return TRUE;
220 }
221
222 /* scan des lecteurs */
cdrecord_scan_for_drives(Tgrave * Ag,GError ** Aerror)223 gboolean cdrecord_scan_for_drives(Tgrave *Ag, GError **Aerror)
224 {
225 gchar **Lcmd;
226 gchar *Lcommandline;
227 gint Lpid, g_out, g_err, Lnbrarg;
228 gboolean Lbolstatus;
229 GIOChannel *Lcom;
230 gboolean Lstatus;
231 guint Lcomevent;
232 Tsearchdrive *Lcurentry;
233 gint *Lcont = (gint *)sc_grave_get_data(Ag, "cont");
234 gboolean *Labort = (gboolean *)sc_grave_get_data(Ag, "gabort");
235
236 free_drives(FALSE);
237 for (Lcurentry = listesearchdrives; Lcurentry->detectline && *Labort == FALSE; Lcurentry++) {
238
239 Lcommandline = g_strdup_printf("%s -scanbus %s", conf_get_string("cdrecord"), Lcurentry->detectline);
240 _DEB("commande =%s\n", Lcommandline);
241 Lstatus = g_shell_parse_argv(Lcommandline, &Lnbrarg, &Lcmd, Aerror);
242 g_free(Lcommandline);
243 if (Lstatus == FALSE) return FALSE;
244
245 *Lcont = 3;
246 sc_grave_set_data(Ag, Lcurentry, "drivedesc");
247
248 Lbolstatus = g_spawn_async_with_pipes(NULL, Lcmd, NULL, /* env argument */
249 (GSpawnFlags ) (0),
250 NULL, NULL, &Lpid, NULL, &g_out, &g_err, Aerror);
251 g_strfreev(Lcmd);
252
253 if (Lbolstatus == FALSE) {
254 g_warning("ERROR EXECUTION !\n");
255 return FALSE;
256 }
257
258 Lcom = g_io_channel_unix_new( g_out );
259 g_io_channel_set_encoding (Lcom, NULL, NULL);
260 g_io_channel_set_flags( Lcom, G_IO_FLAG_NONBLOCK, NULL );
261 Lcomevent = g_io_add_watch (Lcom, (G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI),
262 scan_callback,
263 Ag);
264 while (*Lcont==3) {
265 gtk_main_iteration();
266 }
267
268 g_source_remove(Lcomevent);
269
270 g_io_channel_shutdown(Lcom, FALSE, NULL);
271 g_io_channel_unref(Lcom);
272 g_spawn_close_pid(Lpid);
273 sc_grave_del_data(Ag, "drivedesc");
274 }
275
276 return TRUE;
277 }
278
279 /* mise a jour capacit� du lecteur */
cdrecord_maj_drive_info(Tdriveinfo * Adrive,gchar * Adev,GError ** Aerror)280 gboolean cdrecord_maj_drive_info(Tdriveinfo *Adrive, gchar *Adev, GError **Aerror)
281 {
282 gchar *Lcommandline, *Lout = NULL, *Lerr = NULL;
283 gchar *scd = NULL, *sdvd = NULL, *f;
284 gint Lexit = 0;
285 gboolean Lstatus;
286
287 Lcommandline = g_strdup_printf("%s -prcap dev=%s", conf_get_string("cdrecord"),
288 Adev ? Adev : DRIVE_DEV(Adrive));
289
290 _DEB("==================%s\n", Lcommandline);
291 Lstatus = g_spawn_command_line_sync(Lcommandline, &Lout, &Lerr, &Lexit, Aerror);
292 g_free(Lcommandline);
293 if (Lstatus == FALSE || !Lout || !Lerr || !*Lout) {
294 g_free(Lout);
295 g_free(Lerr);
296 return FALSE;
297 }
298
299 if (strstr(Lout, CDRECORD_READ_CD)) Adrive->type |= _READ_CDR;
300 if (strstr(Lout, CDRECORD_WRITE_CDR)) Adrive->type |= _WRITE_CDR;
301 if (strstr(Lout, CDRECORD_WRITE_CDRW)) Adrive->type |= _WRITE_CDRW;
302 if (strstr(Lout, CDRECORD_READ_DVD)) Adrive->type |= _READ_DVD;
303 if (strstr(Lout, CDRECORD_WRITE_DVD)) Adrive->type |= _WRITE_DVD;
304
305 /* vitesse de lecture maximum CD */
306 if ((scd=strstr(Lout, CDRECORD_MAX_CDREAD_SPEED))) {
307 scd+=strlen(CDRECORD_MAX_CDREAD_SPEED);
308 if ((scd=strstr(scd, CDRECORD_MAX_CDREAD_SPEED_CD))) {
309 scd=ltrim(scd+strlen(CDRECORD_MAX_CDREAD_SPEED_CD));
310 }
311 f=scd;
312 while (isdigit(*f)) f++;
313 *(f++)=0;
314
315 if ((sdvd=strstr(f, CDRECORD_MAX_CDREAD_SPEED_DVD))) {
316 sdvd=ltrim(sdvd+strlen(CDRECORD_MAX_CDREAD_SPEED_DVD));
317 }
318 f=sdvd;
319 while (isdigit(*f)) f++;
320 *(f++)=0;
321 }
322
323 g_free(Lout);
324 g_free(Lerr);
325
326 if (!scd) return FALSE;
327
328 Adrive->vitesse = atoi(scd); /* vitesse de lecture ou de gravure maximum */
329 Adrive->vitessedvd = sdvd ? atoi(sdvd) : -1;
330 _DEB("== le type => %d\n", Adrive->type);
331 _DEB("== donc la vitesse de lecture => %d\n", Adrive->vitesse );
332
333
334 /* ok maintenant on regarde si le lecteur supporte le burnfree, si oui on l'utilisera
335 * lors des gravures */
336 Lcommandline = g_strdup_printf("%s -checkdrive dev=%s driveropts=help", conf_get_string("cdrecord"),
337 Adev ? Adev : DRIVE_DEV(Adrive));
338 _DEB("==================%s\n", Lcommandline);
339 Lstatus = g_spawn_command_line_sync(Lcommandline, &Lout, &Lerr, &Lexit, Aerror);
340 g_free(Lcommandline);
341 if (Lstatus == TRUE) {
342 if (strstr(Lout, CDRECORD_BURNFREE)) Adrive->type |= _BURN_FREE;
343 }
344 g_free(Lout);
345 g_free(Lerr);
346
347 return TRUE;
348 }
349
350 /* recherche les parametres supllementaires a passer a cdrecord */
burn_data_getextrapara(Tgrave * Ag)351 gchar *burn_data_getextrapara(Tgrave *Ag)
352 {
353 gchar *Lformat = get_combo_value(sc_grave_get_widget(Ag, "dataformat"));
354 gchar *Lmodburn = get_combo_value(sc_grave_get_widget(Ag, "datamodburn"));
355 gchar *Lreturn;
356
357 Lreturn = g_strdup_printf("-%s %s%s", Lformat, Lmodburn && *Lmodburn ? "-" : "", Lmodburn);
358
359 g_free(Lmodburn); g_free(Lformat);
360
361 return Lreturn;
362 }
363
get_blank_type(Tgrave * Ag,gint Atypemedia)364 static gchar *get_blank_type(Tgrave *Ag, gint Atypemedia)
365 {
366 gboolean *Luseautoblank = (gboolean *) sc_grave_get_data(Ag, "useautoblank");
367
368 if (!*Luseautoblank || (!(Atypemedia & _MEDIA_CDRW))) return g_strdup("");
369
370 return g_strdup_printf("blank=%s", conf_get_boolean("fastblank") == TRUE ? "fast" : "all");
371 }
372
373 /* copie d'une image iso */
burn_from_image(gchar * Aop,Tgrave * Ag,GError ** Aerror)374 gboolean burn_from_image(gchar *Aop, Tgrave *Ag, GError **Aerror) {
375 gchar **Lcmd;
376 gchar *Lcommandline, *Ltxt;
377 GIOChannel *Lcom, *Lcomerr;
378 guint Lcomevent, Lcomerrevent;
379 gint *Lcont = (gint *) sc_grave_get_data(Ag, "cont");
380 gboolean *Labort = (gboolean *) sc_grave_get_data(Ag, "gabort");
381 GtkWindow *Lwindow = GTK_WINDOW(sc_grave_get_data(Ag, "window_burn"));
382 gboolean Lsimul = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sc_grave_get_widgetv(Ag, "%ssimul", Aop)));
383 gint Lnbrgravure = gtk_spin_button_get_value(GTK_SPIN_BUTTON(sc_grave_get_widgetv(Ag, "nbrcd%s", Aop)));
384 gboolean *Loperationstatus = (gboolean *)sc_grave_get_data(Ag, "operationstatus");
385 gboolean Lwanteject = conf_get_boolean("eject");
386 gchar *Liso = (gchar *)sc_grave_get_data(Ag, "iso"); /* image iso */
387 gint *Lpid = (gint *) sc_grave_get_data(Ag, "pid");
388 gboolean Ldosimul;
389 GtkWidget *Lvitesse = sc_grave_get_widgetv(Ag, "dst%sspeed", Aop);
390 GtkLabel *Ltitle = GTK_LABEL(sc_grave_get_data(Ag, "gravetitle"));
391 GtkToggleButton *Lbtnnotfix = GTK_TOGGLE_BUTTON(sc_grave_get_widgetv(Ag, "%snotfix", Aop));
392 gboolean Lnotfix = Lbtnnotfix ? gtk_toggle_button_get_active(Lbtnnotfix) : FALSE;
393 gchar *Lextrapara = sc_grave_get_data(Ag, "extrapara");
394 gboolean Lmulti = FALSE;
395 gint *Ldone = (gint *)sc_grave_get_data(Ag, "done"); /* fais */
396 gint Lcurcd;
397 gint Lnbrpass=1;
398 gchar *Lbufvitesse, *Lblank;
399 gchar Llasttrack[_BUF_SIZE] = "00";
400 gint g_out, g_err, Lnbrarg;
401 gboolean Lstatus = FALSE;
402 gboolean Leject = FALSE;
403 GtkToggleButton *Ltbtn = NULL;
404 Tdriveinfo *Ldevice = NULL;
405 gchar Lgravident[_BUF_SIZE];
406 gint Lmediadetect1 = _MEDIA_CDRW;
407
408 g_snprintf(Lgravident, sizeof(Lgravident)-1, "dst%scombo", Aop);
409
410 Ldevice = matos_get_drive_info(Ag, Lgravident);
411
412 Lbufvitesse = get_combo_value(Lvitesse);
413
414 if ((Ltbtn = GTK_TOGGLE_BUTTON(sc_grave_get_widgetv(Ag, "%smulti", Aop))))
415 Lmulti =gtk_toggle_button_get_active(Ltbtn);
416
417 _DEB("on veut graver %d cd simul(%d)", Lnbrgravure, Lsimul ? 1 : 0);
418
419 for (Lcurcd=1; Lcurcd<= Lnbrgravure;
420 ((Lsimul && Lnbrpass>1) || (!Lsimul)) ? ( Lcurcd++, Lnbrpass=1 ) : ( Lnbrpass++ )) {
421
422 Ldosimul = (Lsimul && Lnbrpass==1);
423 if (Lcurcd > 1 && !Ldosimul) {
424 /* copie sur un nouveau cd, on demande a l'utilisateur d'inserer le
425 * nouveau cd vierge */
426 GSList *Llmediarequis1 = sc_grave_get_data(Ag, "mediarequis1");
427 gint *Lmediatitle1 = sc_grave_get_data(Ag, "mediatitle1");
428 gchar *Ltxt = sc_grave_get_data(Ag, "medialabel");
429 gboolean Lstatus;
430 Tgrave *Ldialoghash;
431 GtkWidget *Lconfirm;
432 gint Lrep;
433
434 eject_cd(DRIVE_DEV(Ldevice), NULL);
435 Lstatus = waiting_for_user(*Lmediatitle1, Ag, Llmediarequis1 , &Lmediadetect1, Ldevice);
436
437 if (Lstatus==FALSE) {
438 /* si c'est non alors on arrete */
439 *Labort = TRUE; Lstatus = TRUE; break;
440 }
441
442 Ldialoghash = create_dialog_confirm_operation(GTK_WIDGET(Lwindow), Ltxt,
443 DRIVE_CDRW_WRITER(Ldevice) == TRUE &&
444 ((Lmediadetect1 & _MEDIA_CDRW) && (Lmediadetect1 & _MEDIA_NOBLANK)) ?
445 _("Blank CD-RW before writing") : NULL, conf_get_boolean("autoblank"));
446
447 Lconfirm = sc_grave_get_data(Ldialoghash, "window");
448 Lrep = gtk_dialog_run(GTK_DIALOG(Lconfirm));
449
450 if (Lrep != GTK_RESPONSE_YES) {
451 /* si c'est non alors on arrete */
452 *Labort = TRUE; Lstatus = TRUE;
453 } else if (DRIVE_CDRW_WRITER(Ldevice) == TRUE) {
454 gboolean *Luseautoblank = (gboolean *) sc_grave_get_data(Ag, "useautoblank");
455 GtkCheckButton *Labcheck = GTK_CHECK_BUTTON(sc_grave_get_widget(Ldialoghash, "checkbox"));
456 *Luseautoblank = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Labcheck));
457 }
458 gtk_widget_destroy(Lconfirm);
459
460 if (*Labort == TRUE) break;
461 }
462
463 /* faut il ejecter le CD-R apres l'operation ?
464 * oui si l'utilisateur a cocher la case "ejecter le cd" ou
465 * si il faut realiser d'autre gravure sur d'autres CD-R */
466 Leject = ((Lcurcd > 1 && (Lwanteject || Lcurcd<Lnbrgravure)) || (Lcurcd == 1 && !Ldosimul && Lwanteject));
467
468 *Loperationstatus = FALSE;
469
470 _DEB("gravure du cd [%d]", Lcurcd);
471 Ltxt = get_title(Lnbrgravure, Lcurcd, Ldosimul);
472 gtk_label_set_text(Ltitle, Ltxt);
473 g_free(Ltxt);
474
475 Lblank = get_blank_type(Ag, Lmediadetect1);
476
477 /* try to umount device before device access */
478 matos_umount_device(Ldevice, NULL);
479
480 Lcommandline = g_strdup_printf("%s dev=%s -v gracetime=2 %s%s %s %s %s %s %s %s %s %s '%s' %s",
481 conf_get_string("cdrecord"), DRIVE_DEV(Ldevice),
482 *Lbufvitesse != '0' ? "speed=" : "", *Lbufvitesse != '0' ? Lbufvitesse : "",
483 Ldosimul ? " -dummy" : "", /* simulation ? */
484 Ldosimul || Lnotfix ? " -nofix" : "", /* fixer le cd apres ecriture ? */
485 Lmulti ? " -multi" : "", /* multi-session */
486 Leject ? "-eject" : "", /* ejecter le cd apres l'operation */
487 Lblank,
488 Lextrapara && *Lextrapara ? Lextrapara : "", /* parametre supplementaire tel que le mode d'ecriture */
489 conf_get_boolean("overburn") ? "-overburn" : "",
490 conf_get_string("cdrecordpara"),
491 Liso,
492 DRIVE_BURN_FREE(Ldevice) ? "driveropts=burnfree" : ""
493 );
494 g_free(Lblank);
495
496 _DEB("execution [%s]\n", Lcommandline);
497
498 Lstatus = g_shell_parse_argv(Lcommandline, &Lnbrarg, &Lcmd, Aerror);
499 g_free(Lcommandline);
500 if (Lstatus == FALSE) {
501 break;
502 }
503
504 Lstatus = g_spawn_async_with_pipes(NULL, Lcmd, NULL, /* env argument */
505 (GSpawnFlags ) (G_SPAWN_DO_NOT_REAP_CHILD),
506 NULL, NULL, Lpid, NULL, &g_out, &g_err, Aerror);
507 g_strfreev(Lcmd);
508
509 if (Lstatus == FALSE) {
510 g_warning("ERROR EXECUTION !\n");
511 break;
512 }
513
514 *Lcont = 1;
515 sc_grave_set_data(Ag, &Llasttrack, "lasttrack");
516 Lcom = g_io_channel_unix_new( g_out );
517 g_io_channel_set_encoding (Lcom, NULL, NULL);
518 g_io_channel_set_buffered(Lcom, FALSE);
519 g_io_channel_set_flags( Lcom, G_IO_FLAG_NONBLOCK, NULL );
520 Lcomevent = g_io_add_watch (Lcom, (G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI),
521 cdrecord_grave_callback, Ag);
522
523 Lcomerr = g_io_channel_unix_new( g_err );
524 g_io_channel_set_encoding (Lcomerr, NULL, NULL);
525 g_io_channel_set_buffered(Lcomerr, FALSE);
526 g_io_channel_set_flags( Lcomerr, G_IO_FLAG_NONBLOCK, NULL );
527 Lcomerrevent = g_io_add_watch (Lcomerr, (G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI),
528 cdrecord_grave_callback, Ag);
529
530 while (*Lcont > 0 && *Labort == FALSE) {
531 gtk_main_iteration();
532 }
533 exit_prog(*Lpid, FALSE, Aerror, NULL);
534
535 g_source_remove(Lcomevent);
536 g_source_remove(Lcomerrevent);
537
538 g_io_channel_shutdown(Lcomerr, FALSE, NULL);
539 g_io_channel_unref(Lcomerr);
540 g_io_channel_shutdown(Lcom, FALSE, NULL);
541 g_io_channel_unref(Lcom);
542 g_spawn_close_pid(*Lpid);
543 *Lpid = 0;
544
545 sc_grave_del_data(Ag, "lasttrack");
546
547 if (*Aerror) {
548 _DEB("IL Y A UNE ERREUR !!");
549 Lstatus = FALSE;
550 break;
551 }
552
553 if (*Loperationstatus == FALSE) {
554 /* cdrecord n'a pas reussi a grave le cd mais on n'a intercepte aucune erreur ! argh!
555 * dans tous les cas ce n'est pas normal, on genere une erreur */
556 g_set_error(Aerror, GRAVEMAN_ERROR, _ERR_UNKNOWN_ERROR,
557 _("Communication error with cdrecord. Check that you have access to cdrecord release 2.0 !"));
558 Lstatus = FALSE;
559 break;
560 }
561
562 if (Ldosimul) {
563 /* fin de la simulation, tout s'est apparement bien passe
564 * on demande confirmation avent de commencer la vrai gravure */
565 gint Lrep;
566 GtkWidget *Lconfirm = gtk_message_dialog_new(Lwindow,
567 GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION,
568 GTK_BUTTONS_YES_NO,
569 _("Simulation successful. Do you want to write the CD for real?"));
570 Lrep = gtk_dialog_run(GTK_DIALOG(Lconfirm));
571 gtk_widget_destroy(Lconfirm);
572 if (Lrep == GTK_RESPONSE_NO) {
573 /* si c'est non alors on arrete */
574 *Labort = TRUE;
575 Lstatus = TRUE;
576 break;
577 }
578 }
579
580 (*Ldone)++;
581 strcpy(Llasttrack, "00");
582 }
583
584 g_free(Lbufvitesse);
585
586 return Lstatus;
587 }
588
589 /* mise a jour du label d'avancement */
maj_audio_title(GtkLabel * Alabel,gchar * Apiste,gchar * Avitesse,gdouble Amoafaire,gdouble Amofait)590 void maj_audio_title(GtkLabel *Alabel, gchar *Apiste, gchar *Avitesse, gdouble Amoafaire, gdouble Amofait)
591 {
592 gchar *Ltxt = NULL;
593 if (Amoafaire != 0) {
594 Ltxt = g_strdup_printf(_("Writing track %s - %.0f MB of %.0f MB at %s"), Apiste ? Apiste : "-",
595 Amofait, Amoafaire, Avitesse ? Avitesse : "-");
596 } else {
597 Ltxt = g_strdup_printf(_("Writing track %s at %s"), Apiste ? Apiste : "-", Avitesse ? Avitesse : "-");
598 }
599
600 gtk_label_set_text(Alabel, Ltxt);
601 g_free(Ltxt);
602 }
603
604 /* callback appele lorsque cdrecord grave les pistes */
cdrecord_grave_callback(GIOChannel * Astd,GIOCondition Acond,gpointer Adata)605 gboolean cdrecord_grave_callback(GIOChannel *Astd, GIOCondition Acond, gpointer Adata)
606 {
607 GIOStatus Lstatus;
608 Tgrave *Lg = (Tgrave *)Adata;
609 gchar Lbuffer[_BUF_SIZE];
610 gint *Lcont = (gint *) sc_grave_get_data(Lg, "cont"); /* on traite encore des donnees ? */
611 GError **Lerreur = (GError **) sc_grave_get_data(Lg, "gerror"); /* pointeur erreur */
612 gint *Ltodo = (gint *) sc_grave_get_data(Lg, "todo"); /* nombre de piste a traiter */
613 gint *Ldone = (gint *) sc_grave_get_data(Lg, "done"); /* nombre de piste deja traite */
614 gchar *Llasttrack = (gchar *) sc_grave_get_data(Lg, "lasttrack"); /* precedente piste traite */
615 gchar *f, *e;
616 gchar *Ltxt;
617 gchar Lsbuf[200];
618 gdouble Ltotaldone = 1, Ltotaltodo, Lfifo, Lpct, Lgbuf = 0, Ltava;
619 gsize Llu = 0;
620 gchar *Ltracknum;
621
622 GtkLabel *Ltitle = GTK_LABEL(sc_grave_get_data(Lg, "gravetitle"));
623 GtkProgressBar *Lprogressbar = GTK_PROGRESS_BAR(sc_grave_get_data(Lg, "pb_total"));
624 GtkProgressBar *Lprogressbar2 = GTK_PROGRESS_BAR(sc_grave_get_data(Lg, "pb_step"));
625 GtkProgressBar *LprogressbarFifo = GTK_PROGRESS_BAR(sc_grave_get_data(Lg, "pb_fifo"));
626 GtkProgressBar *LprogressbarBuffer = GTK_PROGRESS_BAR(sc_grave_get_data(Lg, "pb_buffer"));
627
628 /* fin du callback lorsque l'on recoi un signal comme quoi le pipe est ferme */
629 if (Acond == G_IO_HUP || Acond == G_IO_ERR) {
630 (*Lcont) = 0;
631 return FALSE;
632 }
633
634 *Lbuffer = 0;
635 Lstatus = g_io_channel_read_chars(Astd, Lbuffer, _BUF_SIZE-1, &Llu, NULL);
636 if (!*Lbuffer || Lstatus == G_IO_STATUS_ERROR || Lstatus == G_IO_STATUS_AGAIN) {
637 return FALSE;
638 }
639 Lbuffer[Llu]=0;
640 _DEB("===>%s", Lbuffer);
641
642 if ((f=strstr(Lbuffer, CDRECORD_COPY))) {
643 /* copie en cours */
644
645 /* champ deja grave */
646 f=f+strlen(CDRECORD_COPY);
647 Ltracknum = f;
648 if (!(f=strchr(f, ':'))) return TRUE;
649 *(f++)=0;
650 g_strstrip(Ltracknum);
651
652 if (!(e = strstr(f, CDRECORD_OF))) return TRUE;
653
654
655 *e=0; e=e+strlen(CDRECORD_OF);
656 Ltotaldone = atof(ltrim(f));
657
658 /* champ total a graver */
659 f=e;
660 if (!(e=strstr(f, CDRECORD_MB))) {
661 maj_audio_title(Ltitle, Ltracknum, NULL, 0, Ltotaldone);
662 return TRUE;
663 }
664 *e=0; e=e+strlen(CDRECORD_MB);
665 Ltotaltodo = atof(ltrim(f));
666
667 /* champ fifo */
668 if (!(f=strstr(e, CDRECORD_FIFO))) {
669 maj_audio_title(Ltitle, Ltracknum, NULL, Ltotaltodo, Ltotaldone);
670 return TRUE;
671 }
672 f=f+strlen(CDRECORD_FIFO);
673
674 if ((e = strchr(++f, ')'))) {
675 *e++=0;
676 } else {
677 e = f;
678 }
679 Lfifo = atof(ltrim(f));
680
681 /* champ buf */
682 if (!(f=strstr(e, CDRECORD_BUF))) {
683 maj_audio_title(Ltitle, Ltracknum, NULL, Ltotaltodo, Ltotaldone);
684 return TRUE;
685 }
686 f=f+strlen(CDRECORD_BUF);
687
688 if ((e = strchr(++f, ']'))) {
689 *e++=0;
690 Lgbuf = atof(ltrim(f));
691 } else {
692 e = f;
693 }
694
695 e=ltrim(e);
696 if ((f=strchr(e, 'x'))) {
697 *(++f)=0;
698 maj_audio_title(Ltitle, Ltracknum, e, Ltotaltodo, Ltotaldone);
699 }
700
701 /* barres de progression */
702 /* avancement operation */
703 Lpct = (1.0/Ltotaltodo) * Ltotaldone;
704 maj_progress(Lprogressbar2, Lpct);
705
706 /* avancement total */
707 if (*Ltracknum && (!*Llasttrack || strcmp(Llasttrack, Ltracknum))) {
708 if (strcmp(Llasttrack, "00")) *Ldone=(*Ldone)+1;
709 g_strlcpy(Llasttrack, Ltracknum, _BUF_SIZE - 1);
710 }
711 Ltava = (1.0/ (*Ltodo)) * ((*Ldone)-1+Lpct);
712 maj_progress(Lprogressbar, Ltava);
713
714 /* barre fifo */
715 g_snprintf(Lsbuf, sizeof(Lsbuf)-1, "%.0f%%", Lfifo);
716 gtk_progress_bar_set_fraction(LprogressbarFifo, Lfifo * 0.01);
717 gtk_progress_bar_set_text(LprogressbarFifo, Lsbuf);
718
719 /* barre buffer */
720 g_snprintf(Lsbuf, sizeof(Lsbuf)-1, "%.0f%%", Lgbuf);
721 gtk_progress_bar_set_fraction(LprogressbarBuffer, Lgbuf * 0.01);
722 gtk_progress_bar_set_text(LprogressbarBuffer, Lsbuf);
723
724 } else if (strstr(Lbuffer, CDRECORD_FIXATING)) {
725 /* cloture du cd */
726 gtk_label_set_text(Ltitle, _("Fixating..."));
727 } else if (strstr(Lbuffer, CDRECORD_BLANKING)) {
728 /* blanking disk */
729 gtk_label_set_text(Ltitle, _("Blanking CD-RW..."));
730 } else if ((f=strstr(Lbuffer, CDRECORD_STATUS))) {
731 gboolean *Lstatus = (gboolean *) sc_grave_get_data(Lg, "operationstatus");
732 /* bug 11803
733 * cause des problems apparements, a tester ..
734 f=f+strlen(CDRECORD_STATUS);
735 fin de la gravure
736 if (*f != '0') {
737 g_set_error(Lerreur, GRAVEMAN_ERROR, _ERR_BUF_EMPTY, _("Error writing tracks, buffer was empty !"));
738 return FALSE;
739 } */
740 /* ok tout s'est bien passe ! */
741 *Lstatus = TRUE;
742 } else if (strstr(Lbuffer, CDRECORD_INPUTOUTPUT_ERROR)) {
743 /* erreur entre sortie */
744 g_set_error(Lerreur, GRAVEMAN_ERROR, _ERR_NO_CD, _("Error writing CD !"));
745 (*Lcont) = 0;
746 return FALSE;
747 } else if (strstr(Lbuffer, CDRECORD_CANNOT_BLANK)) {
748 g_set_error(Lerreur, GRAVEMAN_ERROR, _ERR_CANNOT_BLANK, _("Cannot blank disk, aborting."));
749 (*Lcont) = 0;
750 return FALSE;
751 } else if ((strstr(Lbuffer, CDRECORD_ERRORDISK)) || (strstr(Lbuffer, CDRECORD_INCOMPATIBLE_MEDIUM))) {
752 /* erreur pas de cd vierge */
753 g_set_error(Lerreur, GRAVEMAN_ERROR, _ERR_NO_CD, _("Error, a CD-R/CD-RW is required in the cd recorder !"));
754 (*Lcont) = 0;
755 return FALSE;
756 } else if (strstr(Lbuffer, CDRECORD_BAD_RECORDER)) {
757 /* erreur pas de cd vierge */
758 g_set_error(Lerreur, GRAVEMAN_ERROR, _ERR_BAD_RECORDER, _("CD recorder unsupported !"));
759 (*Lcont) = 0;
760 return FALSE;
761 } else if ((strstr(Lbuffer, CDRECORD_INAPPROPRIATE))) {
762 /* erreur fichier audio non compatible */
763 g_snprintf(Lsbuf, sizeof(Lsbuf)-1, _("Error with track %.0f: inappropriate audio coding !"), Ltotaldone);
764 g_set_error(Lerreur, GRAVEMAN_ERROR, _ERR_INAPPROPRIATE_DATA, Lsbuf);
765 (*Lcont) = 0;
766 return FALSE;
767 } else if ((f=strstr(Lbuffer, CDRECORD_NOSUCHFILE))) {
768 /* erreur fichier image iso source introuvable ! */
769 g_snprintf(Lsbuf, sizeof(Lsbuf)-1, _("Cannot open iso image !"));
770 g_set_error(Lerreur, GRAVEMAN_ERROR, _ERR_INAPPROPRIATE_DATA, Lsbuf);
771 (*Lcont) = 0;
772 return FALSE;
773 } else if ((f=strstr(Lbuffer, conf_get_string("cdrecord")))) {
774 f=f+strlen(conf_get_string("cdrecord"))+1;
775 if (*(f++)==':') {
776 /* erreur cdrecord */
777 Ltxt = _UTF8(f);
778 g_set_error(Lerreur, GRAVEMAN_ERROR, _ERR_INAPPROPRIATE_DATA, Ltxt);
779 g_free(Ltxt);
780 (*Lcont) = 0;
781 return FALSE;
782 }
783 }
784
785 return TRUE;
786 }
787
gravepiste(Tgrave * Ag,GError ** Aerror)788 gboolean gravepiste(Tgrave *Ag, GError **Aerror) {
789 GtkWindow *Lwindow = GTK_WINDOW(sc_grave_get_data(Ag, "window_burn"));
790 GtkLabel *Ltitle = GTK_LABEL(sc_grave_get_data(Ag, "gravetitle"));
791 GtkWidget *Lvitesse = sc_grave_get_widget(Ag, "dstaudiospeed");
792 gchar *Lrepertoire = (gchar *)sc_grave_get_data(Ag, "tmpdir");
793 gboolean *Loperationstatus = (gboolean *)sc_grave_get_data(Ag, "operationstatus");
794 gboolean *Labort = (gboolean *) sc_grave_get_data(Ag, "gabort");
795 gchar *Lbuftitle = NULL;
796 gchar **Lcmd;
797 gchar *Lcommandline;
798 GIOChannel *Lcom, *Lcomerr;
799 guint Lcomevent, Lcomerrevent;
800 gint *Lcont = (gint *) sc_grave_get_data(Ag, "cont"); /* on traite encore des donnees ? */
801 /* nombre d'element total */
802 gint *Ldone = (gint *)sc_grave_get_data(Ag, "done"); /* fais */
803 gint *Ltodo = (gint *) sc_grave_get_data(Ag, "todo");
804 gint *Lpid = (gint *) sc_grave_get_data(Ag, "pid");
805
806 gint g_out, g_err, Lnbrarg;
807 gboolean Lstatus = FALSE;
808 gchar *Lbufvitesse;
809 Tdriveinfo *Ldevice = matos_get_drive_info(Ag, "dstaudiocombo");
810 gboolean Lsimul = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sc_grave_get_widget(Ag, "audiosimul")));
811 gboolean Lnotfix = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sc_grave_get_widget(Ag, "audionotfix")));
812 gboolean Ldaomode = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sc_grave_get_widget(Ag, "audiodao")));
813 gint Lnbrgravure = gtk_spin_button_get_value(GTK_SPIN_BUTTON(sc_grave_get_widget(Ag, "nbrcdaudio")));
814 gboolean Lwanteject = conf_get_boolean("eject");
815 gint Lcurcd;
816 gboolean Ldosimul;
817 gint Lnbrpass=1;
818 gchar *Lfileslist, *Lblank;
819 gboolean Leject = FALSE;
820 gchar Llasttrack[_BUF_SIZE] = "00";
821 gint Lmediadetect1 = _MEDIA_CDRW;
822
823 Lfileslist = make_audio_fileslist(*Ltodo);
824 Lbufvitesse = get_combo_value(Lvitesse);
825
826 *Ltodo = (*Ltodo) * ((Lnbrgravure) + (Lsimul ? 1 : 0));
827
828
829 for (Lcurcd=1; Lcurcd<= Lnbrgravure;
830 ((Lsimul && Lnbrpass>1) || (!Lsimul)) ? ( Lcurcd++, Lnbrpass=1 ) : ( Lnbrpass++ )) {
831 *Loperationstatus = FALSE;
832 Ldosimul = (Lsimul && Lnbrpass==1);
833
834 if (Lcurcd > 1 && !Ldosimul) {
835 /* copie sur un nouveau cd, on demande a l'utilisateur d'inserer le
836 * nouveau cd vierge */
837 GSList *Llmediarequis1 = sc_grave_get_data(Ag, "mediarequis1");
838 gint *Lmediatitle1 = sc_grave_get_data(Ag, "mediatitle1");
839 gchar *Ltxt = sc_grave_get_data(Ag, "medialabel");
840 gboolean Lstatus;
841 Tgrave *Ldialoghash;
842 GtkWidget *Lconfirm;
843 gint Lrep;
844
845 eject_cd(DRIVE_DEV(Ldevice), NULL);
846 Lstatus = waiting_for_user(*Lmediatitle1, Ag, Llmediarequis1 , &Lmediadetect1, Ldevice);
847
848 if (Lstatus==FALSE) {
849 /* si c'est non alors on arrete */
850 *Labort = TRUE; Lstatus = TRUE; break;
851 }
852
853 Ldialoghash = create_dialog_confirm_operation(GTK_WIDGET(Lwindow), Ltxt,
854 DRIVE_CDRW_WRITER(Ldevice) == TRUE &&
855 ((Lmediadetect1 & _MEDIA_CDRW) && (Lmediadetect1 & _MEDIA_NOBLANK)) ?
856 _("Blank CD-RW before writing") : NULL, conf_get_boolean("autoblank"));
857
858 Lconfirm = sc_grave_get_data(Ldialoghash, "window");
859 Lrep = gtk_dialog_run(GTK_DIALOG(Lconfirm));
860
861 if (Lrep != GTK_RESPONSE_YES) {
862 /* si c'est non alors on arrete */
863 *Labort = TRUE; Lstatus = TRUE;
864 } else if (DRIVE_CDRW_WRITER(Ldevice) == TRUE) {
865 gboolean *Luseautoblank = (gboolean *) sc_grave_get_data(Ag, "useautoblank");
866 GtkCheckButton *Labcheck = GTK_CHECK_BUTTON(sc_grave_get_widget(Ldialoghash, "checkbox"));
867 *Luseautoblank = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Labcheck));
868 }
869 gtk_widget_destroy(Lconfirm);
870
871 if (*Labort == TRUE) break;
872 }
873
874 Lbuftitle = get_title(Lnbrgravure, Lcurcd, Ldosimul);
875 gtk_label_set_text(GTK_LABEL(Ltitle), Lbuftitle);
876 g_free(Lbuftitle);
877
878 /* faut il ejecter le CD-R apres l'operation ?
879 * oui si l'utilisateur a cocher la case "ejecter le cd" ou
880 * si il faut realiser d'autre gravure sur d'autres CD-R */
881 Leject = ((Lcurcd > 1 && (Lwanteject || Lcurcd<Lnbrgravure)) || (Lcurcd == 1 && !Ldosimul && Lwanteject));
882
883 Lblank = get_blank_type(Ag, Lmediadetect1);
884 Lcommandline = g_strdup_printf("%s dev=%s -v gracetime=2 %s%s %s%s %s %s %s %s %s -pad -audio %s %s",
885 conf_get_string("cdrecord"), DRIVE_DEV(Ldevice),
886 *Lbufvitesse == '0' ? "" : "speed=", *Lbufvitesse == '0' ? "" : Lbufvitesse,
887 Ldosimul ? " -dummy" : "", /* simulation ? */
888 Ldosimul || Lnotfix ? " -nofix" : "", /* fixer le cd apres ecriture ? */
889 Ldaomode ? " -dao" : "", /* ecriture en mode DAO, pas de pause entre les pistes */
890 Leject ? "-eject" : "", /* ejecter le cd apres l'operation */
891 ((Lsimul && Lnbrpass != 2) || (!Lsimul)) ? Lblank : "", /* effacer le cdrw avant ?
892 * on efface pas le cd apres la simulation vu que l'operation
893 * a �t� faite juste avant */
894 conf_get_string("cdrecordpara"),
895 conf_get_boolean("overburn") ? "-overburn" : "",
896 Lfileslist,
897 DRIVE_BURN_FREE(Ldevice) ? "driveropts=burnfree" : ""
898 );
899 g_free(Lblank);
900 _DEB("execution [%s]\n", Lcommandline);
901 Lstatus = g_shell_parse_argv(Lcommandline, &Lnbrarg, &Lcmd, Aerror);
902 g_free(Lcommandline);
903 if (Lstatus == FALSE) {
904 break;
905 }
906
907 /* try to umount device before device access */
908 matos_umount_device(Ldevice, NULL);
909
910 Lstatus = g_spawn_async_with_pipes(Lrepertoire, Lcmd, NULL, /* env argument */
911 (GSpawnFlags ) (G_SPAWN_DO_NOT_REAP_CHILD),
912 NULL, NULL, Lpid, NULL, &g_out, &g_err, Aerror);
913 g_strfreev(Lcmd);
914
915 if (Lstatus == FALSE) {
916 g_warning("ERROR EXECUTION !\n");
917 break;
918 }
919
920 *Lcont = 1;
921 sc_grave_set_data(Ag, &Llasttrack, "lasttrack");
922 Lcom = g_io_channel_unix_new( g_out );
923 g_io_channel_set_encoding (Lcom, NULL, NULL);
924 g_io_channel_set_buffered(Lcom, FALSE);
925 g_io_channel_set_flags( Lcom, G_IO_FLAG_NONBLOCK, NULL );
926 Lcomevent = g_io_add_watch (Lcom, (G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI),
927 cdrecord_grave_callback, Ag);
928
929 Lcomerr = g_io_channel_unix_new( g_err );
930 g_io_channel_set_encoding (Lcomerr, NULL, NULL);
931 g_io_channel_set_buffered(Lcomerr, FALSE);
932 g_io_channel_set_flags( Lcomerr, G_IO_FLAG_NONBLOCK, NULL );
933 Lcomerrevent = g_io_add_watch (Lcomerr, (G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI),
934 cdrecord_grave_callback, Ag);
935
936 while (*Lcont>0 && *Labort == FALSE) {
937 gtk_main_iteration();
938 }
939 exit_prog(*Lpid, FALSE, Aerror, NULL);
940
941 g_source_remove(Lcomerrevent);
942 g_source_remove(Lcomevent);
943
944 g_io_channel_shutdown(Lcomerr, FALSE, NULL);
945 g_io_channel_unref(Lcomerr);
946 g_io_channel_shutdown(Lcom, FALSE, NULL);
947 g_io_channel_unref(Lcom);
948 g_spawn_close_pid(*Lpid);
949 *Lpid = 0;
950
951 sc_grave_del_data(Ag, "lasttrack");
952
953 if (*Aerror) {
954 Lstatus = FALSE;
955 break;
956 }
957 if (*Loperationstatus == FALSE) {
958 /* cdrecord n'a pas reussi a grave le cd mais on n'a intercepte aucune erreur ! argh!
959 * dans tous les cas ce n'est pas normal, on genere une erreur */
960 g_set_error(Aerror, GRAVEMAN_ERROR, _ERR_UNKNOWN_ERROR,
961 _("Communication error with cdrecord. Check that you have access to cdrecord release 2.0 !"));
962 Lstatus = FALSE;
963 break;
964 }
965
966 if (Ldosimul) {
967 /* fin de la simulation, tout s'est apparement bien passe
968 * on demande confirmation avent de commencer la vrai gravure */
969 gint Lrep;
970 GtkWidget *Lconfirm = gtk_message_dialog_new(Lwindow,
971 GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION,
972 GTK_BUTTONS_YES_NO,
973 _("Simulation successful. Do you want to write the CD for real?"));
974 Lrep = gtk_dialog_run(GTK_DIALOG(Lconfirm));
975 gtk_widget_destroy(Lconfirm);
976 if (Lrep == GTK_RESPONSE_NO) {
977 /* si c'est non alors on arrete */
978 *Labort = TRUE;
979 Lstatus = TRUE;
980 break;
981 }
982 }
983 (*Ldone)++;
984 strcpy(Llasttrack, "00");
985 }
986
987 g_free(Lbufvitesse);
988 g_free(Lfileslist);
989
990 return Lstatus;
991 }
992
common_blankorfix_callback(GIOChannel * Astd,GIOCondition Acond,gpointer Adata)993 gboolean common_blankorfix_callback(GIOChannel *Astd, GIOCondition Acond, gpointer Adata)
994 {
995 GIOStatus Lstatus;
996 Tgrave *Lg = (Tgrave *)Adata;
997 gint *Lcont = (gint *) sc_grave_get_data(Lg, "cont"); /* on traite encore des donnees ? */
998 gchar *Lbuffer = NULL;
999 /* fin du callback lorsque l'on recoi un signal comme quoi le pipe est ferme */
1000 if (Acond == G_IO_HUP || Acond == G_IO_ERR) {
1001 (*Lcont) = 1;
1002 return FALSE;
1003 }
1004
1005 Lstatus = g_io_channel_read_line(Astd, &Lbuffer, NULL, NULL, NULL);
1006 if (!Lbuffer) return TRUE;
1007
1008 _DEB("===>%s", Lbuffer);
1009
1010 if (!strcmp(Lbuffer, CDRECORD_BLANKING_TIME)) {
1011 /* fin de l'operation: effacer un cdrw */
1012 gboolean *Loperationstatus = (gboolean *)sc_grave_get_data(Lg, "operationstatus");
1013 *Loperationstatus = TRUE;
1014 } else if (!strcmp(Lbuffer, CDRECORD_FIXATING_TIME)) {
1015 /* fin de l'operation: cloturer un cdr */
1016 gboolean *Loperationstatus = (gboolean *)sc_grave_get_data(Lg, "operationstatus");
1017 *Loperationstatus = TRUE;
1018 } else if (strstr(Lbuffer, CDRECORD_CANNOT_BLANK)) {
1019 GError **Lerreur = (GError **) sc_grave_get_data(Lg, "gerror"); /* pointeur erreur */
1020 if (!*Lerreur)
1021 g_set_error(Lerreur, GRAVEMAN_ERROR, _ERR_CANNOT_BLANK, _("Cannot blank disk, aborting."));
1022 } else if (strstr(Lbuffer, CDRECORD_INCOMPATIBLE_MEDIUM)) {
1023 /* hum, erreur */
1024 GError **Lerreur = (GError **) sc_grave_get_data(Lg, "gerror"); /* pointeur erreur */
1025 if (!*Lerreur)
1026 g_set_error(Lerreur, GRAVEMAN_ERROR, _ERR_INCOMPATIBLE_MEDIUM, _("Cannot blank disk, this is not a CD-RW !"));
1027 } else if (strstr(Lbuffer, CDRECORD_ERRORDISK)) {
1028 /* erreur pas de cd */
1029 GError **Lerreur = (GError **) sc_grave_get_data(Lg, "gerror"); /* pointeur erreur */
1030 if (!*Lerreur)
1031 g_set_error(Lerreur, GRAVEMAN_ERROR, _ERR_NO_CD, _("Error, a CD-R/CD-RW is required in the cd recorder !"));
1032 }
1033
1034 g_free(Lbuffer);
1035 return TRUE;
1036 }
1037
1038 /* cloturer un cdr*/
perform_fix_cd(Tgrave * Ag,GError ** Aerror)1039 gboolean perform_fix_cd(Tgrave *Ag, GError **Aerror)
1040 {
1041 gchar **Lcmd;
1042 gchar *Lcommandline;
1043 gboolean Lstatus = FALSE;
1044 GIOChannel *Lcom, *Lcomerr;
1045 guint Lcomevent, Lcomerrevent;
1046 gint g_out, g_err, Lnbrarg;
1047 gint *Lcont = sc_grave_get_data(Ag, "cont");
1048 Tdriveinfo *Ldevice = matos_get_drive_info(Ag, "dstothercombo");
1049
1050 /* pid de cdrecord */
1051 gint *Lpid = (gint *) sc_grave_get_data(Ag, "pid");
1052
1053 Lcommandline = g_strdup_printf("%s dev=%s -v -fix", conf_get_string("cdrecord"), DRIVE_DEV(Ldevice));
1054
1055 _DEB("execution [%s]\n", Lcommandline);
1056 Lstatus = g_shell_parse_argv(Lcommandline, &Lnbrarg, &Lcmd, Aerror);
1057 g_free(Lcommandline);
1058
1059 if (Lstatus == FALSE) {
1060 return FALSE;
1061 }
1062
1063 /* try to umount device before device access */
1064 matos_umount_device(Ldevice, NULL);
1065
1066 Lstatus = g_spawn_async_with_pipes(NULL, Lcmd, NULL, /* env argument */
1067 (GSpawnFlags ) (G_SPAWN_DO_NOT_REAP_CHILD),
1068 NULL, NULL, Lpid, NULL, &g_out, &g_err, Aerror);
1069 g_strfreev(Lcmd);
1070
1071 if (Lstatus == FALSE) {
1072 g_warning("ERROR EXECUTION !\n");
1073 return FALSE;
1074 }
1075 Lcom = g_io_channel_unix_new( g_out );
1076 g_io_channel_set_encoding (Lcom, NULL, NULL);
1077 g_io_channel_set_flags( Lcom, G_IO_FLAG_NONBLOCK, NULL );
1078 Lcomevent = g_io_add_watch (Lcom, (G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI),
1079 common_blankorfix_callback, Ag);
1080
1081 Lcomerr = g_io_channel_unix_new( g_err );
1082 g_io_channel_set_encoding (Lcomerr, NULL, NULL);
1083 g_io_channel_set_flags( Lcomerr, G_IO_FLAG_NONBLOCK, NULL );
1084 Lcomerrevent = g_io_add_watch (Lcomerr, (G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI),
1085 common_blankorfix_callback, Ag);
1086 _DEB("cont vaut => %d\n", *Lcont);
1087 while (*Lcont > 1) {
1088 gtk_main_iteration();
1089 }
1090 _DEB("fin !!!\n");
1091 while (*Lcont > 0) { while(gtk_events_pending()) gtk_main_iteration(); }
1092
1093 exit_prog(*Lpid, FALSE, Aerror, NULL);
1094
1095 g_source_remove(Lcomerrevent);
1096 g_source_remove(Lcomevent);
1097
1098 g_io_channel_shutdown(Lcomerr, FALSE, NULL);
1099 g_io_channel_unref(Lcomerr);
1100 g_io_channel_shutdown(Lcom, FALSE, NULL);
1101 g_io_channel_unref(Lcom);
1102 g_spawn_close_pid(*Lpid);
1103 *Lpid = 0;
1104
1105 return *Aerror ? FALSE : TRUE;
1106 }
1107
1108
1109 /* ejecter un CD */
eject_cd(gchar * Adev,GError ** Aerror)1110 void eject_cd(gchar *Adev, GError **Aerror)
1111 {
1112 gchar *Lcommandline = g_strdup_printf("%s -eject dev=%s", conf_get_string("cdrecord"), Adev);
1113 _DEB("EJECT %s\n", Adev);
1114
1115 g_spawn_command_line_sync(Lcommandline, NULL, NULL, NULL, Aerror);
1116
1117 g_free(Lcommandline);
1118 }
1119
1120 /* effacer un cdrw */
perform_erase_cdrw(Tgrave * Ag,GError ** Aerror)1121 gboolean perform_erase_cdrw(Tgrave *Ag, GError **Aerror)
1122 {
1123 gchar **Lcmd;
1124 gchar *Lcommandline;
1125 gboolean Lstatus = FALSE;
1126 GIOChannel *Lcom, *Lcomerr;
1127 guint Lcomevent, Lcomerrevent;
1128 gint g_out, g_err, Lnbrarg;
1129 gint *Lcont = sc_grave_get_data(Ag, "cont");
1130 Tdriveinfo *Ldevice = matos_get_drive_info(Ag, "dstothercombo");
1131 gboolean *Lfastblank = sc_grave_get_data(Ag, "usefastblank");
1132
1133 /* pid de cdrecord */
1134 gint *Lpid = (gint *) sc_grave_get_data(Ag, "pid");
1135
1136 Lcommandline = g_strdup_printf("%s dev=%s -v gracetime=2 blank=%s",
1137 conf_get_string("cdrecord"), DRIVE_DEV(Ldevice), (*Lfastblank == TRUE ? "fast" : "all"));
1138
1139 _DEB("execution [%s]\n", Lcommandline);
1140 Lstatus = g_shell_parse_argv(Lcommandline, &Lnbrarg, &Lcmd, Aerror);
1141 g_free(Lcommandline);
1142
1143 if (Lstatus == FALSE) {
1144 return FALSE;
1145 }
1146
1147 /* try to umount device before device access */
1148 matos_umount_device(Ldevice, NULL);
1149
1150 Lstatus = g_spawn_async_with_pipes(NULL, Lcmd, NULL, /* env argument */
1151 (GSpawnFlags ) (G_SPAWN_DO_NOT_REAP_CHILD),
1152 NULL, NULL, Lpid, NULL, &g_out, &g_err, Aerror);
1153 g_strfreev(Lcmd);
1154
1155 if (Lstatus == FALSE) {
1156 g_warning("ERROR EXECUTION !\n");
1157 return FALSE;
1158 }
1159 Lcom = g_io_channel_unix_new( g_out );
1160 g_io_channel_set_encoding (Lcom, NULL, NULL);
1161 g_io_channel_set_flags( Lcom, G_IO_FLAG_NONBLOCK, NULL );
1162 Lcomevent = g_io_add_watch (Lcom, (G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI),
1163 common_blankorfix_callback, Ag);
1164
1165 Lcomerr = g_io_channel_unix_new( g_err );
1166 g_io_channel_set_encoding (Lcomerr, NULL, NULL);
1167 g_io_channel_set_flags( Lcomerr, G_IO_FLAG_NONBLOCK, NULL );
1168 Lcomerrevent = g_io_add_watch (Lcomerr, (G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI),
1169 common_blankorfix_callback, Ag);
1170 _DEB("cont vaut => %d\n", *Lcont);
1171 while (*Lcont > 1) {
1172 gtk_main_iteration();
1173 }
1174 _DEB("fin !!!\n");
1175 while (*Lcont > 0) { while(gtk_events_pending()) gtk_main_iteration(); }
1176
1177 exit_prog(*Lpid, FALSE, Aerror, NULL);
1178
1179 g_source_remove(Lcomerrevent);
1180 g_source_remove(Lcomevent);
1181
1182 g_io_channel_shutdown(Lcomerr, FALSE, NULL);
1183 g_io_channel_unref(Lcomerr);
1184 g_io_channel_shutdown(Lcom, FALSE, NULL);
1185 g_io_channel_unref(Lcom);
1186 g_spawn_close_pid(*Lpid);
1187 *Lpid = 0;
1188
1189 return *Aerror ? FALSE : TRUE;
1190 }
1191
cdrecord_mediainfo_callback(GIOChannel * Astd,GIOCondition Acond,gpointer Adata)1192 gboolean cdrecord_mediainfo_callback(GIOChannel *Astd, GIOCondition Acond, gpointer Adata)
1193 {
1194 GIOStatus Lstatus;
1195 Tgrave *Lg = (Tgrave *)Adata;
1196 gint *Lcont = (gint *) sc_grave_get_data(Lg, "cont"); /* on traite encore des donnees ? */
1197 gchar *Ltrouve = (gchar *) sc_grave_get_data(Lg, "msinfo");
1198 gchar *Lbuffer = NULL;
1199 gchar *s;
1200 gint Lniveau = 0;
1201
1202 /* fin du callback lorsque l'on recoi un signal comme quoi le pipe est ferme */
1203 if (Acond == G_IO_HUP || Acond == G_IO_ERR) {
1204 *Lcont = 0;
1205 return FALSE;
1206 }
1207 Lstatus = g_io_channel_read_line(Astd, &Lbuffer, NULL, NULL, NULL);
1208
1209 for (s=Lbuffer; *s; s++) {
1210 if (isdigit(*s)) {
1211 if (Lniveau == 2) {
1212 Lniveau = 3;
1213 } else if (Lniveau == 0) {
1214 Lniveau = 1;
1215 }
1216 } else if (*s==',') {
1217 if (Lniveau == 1) {
1218 Lniveau = 2;
1219 } else {
1220 Lniveau = 0;
1221 break;
1222 }
1223 } else {
1224 if (Lniveau != 3) Lniveau = 0;
1225 break;
1226 }
1227 }
1228
1229 if (Lniveau == 3) {
1230 g_strlcpy(Ltrouve, Lbuffer, _BUF_SIZE-1);
1231 }
1232
1233 g_free(Lbuffer);
1234
1235 return TRUE;
1236 }
1237
1238 /* retourne les informations sur le disque courant pour par exemple
1239 * continuer une gravure multi session */
cdrecord_get_mediainfo(Tgrave * Ag,Tdriveinfo * Adevice,GError ** Aerror)1240 gchar *cdrecord_get_mediainfo(Tgrave *Ag, Tdriveinfo *Adevice, GError **Aerror)
1241 {
1242 gchar **Lcmd;
1243 gchar *Lcommandline;
1244 gint *Lpid = (gint *) sc_grave_get_data(Ag, "pid");
1245 gint *Lcont = (gint *)sc_grave_get_data(Ag, "cont");
1246 gboolean *Labort = (gboolean *) sc_grave_get_data(Ag, "gabort");
1247 gboolean Lstatus = FALSE;
1248 gchar Lmsinfo[_BUF_SIZE] = "";
1249 GIOChannel *Lcom;
1250 guint Lcomevent;
1251 gint Lnbrarg, g_out, g_err;
1252 guint Ltimeout;
1253
1254 (*Lcont) = 2;
1255 Ltimeout = g_timeout_add(500, encours_callback, Ag);
1256
1257 sc_grave_set_data(Ag, &Lmsinfo, "msinfo");
1258
1259 Lcommandline = g_strdup_printf("%s dev=%s -msinfo", conf_get_string("cdrecord"), DRIVE_DEV(Adevice));
1260 _DEB("1execution [%s]", Lcommandline);
1261 Lstatus = g_shell_parse_argv(Lcommandline, &Lnbrarg, &Lcmd, Aerror);
1262 g_free(Lcommandline);
1263 if (Lstatus != FALSE) {
1264 *Lcont = 2;
1265
1266 Lstatus = g_spawn_async_with_pipes(NULL, Lcmd, NULL, (GSpawnFlags) (G_SPAWN_DO_NOT_REAP_CHILD),
1267 NULL, NULL, Lpid, NULL, &g_out, &g_err, Aerror);
1268
1269 Lcom = g_io_channel_unix_new( g_out );
1270 g_io_channel_set_encoding (Lcom, NULL, NULL);
1271 g_io_channel_set_flags( Lcom, G_IO_FLAG_NONBLOCK, NULL );
1272 Lcomevent = g_io_add_watch (Lcom, (G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI),
1273 cdrecord_mediainfo_callback, Ag);
1274
1275 while (*Lcont > 0 && *Labort == FALSE) {
1276 gtk_main_iteration();
1277 }
1278 exit_prog(*Lpid, FALSE, Aerror, NULL);
1279
1280 g_source_remove(Lcomevent);
1281 g_io_channel_shutdown(Lcom, FALSE, NULL);
1282 g_io_channel_unref(Lcom);
1283 g_spawn_close_pid(*Lpid);
1284 }
1285 g_strfreev(Lcmd);
1286
1287 sc_grave_del_data(Ag, "msinfo");
1288
1289 /* attente de la fin du timeout */
1290 g_source_remove(Ltimeout);
1291 sc_chomp(Lmsinfo);
1292 _DEB("msinfo = [%s]\n", Lmsinfo);
1293
1294 return *Lmsinfo ? g_strdup(Lmsinfo) : NULL;
1295 }
1296
1297
1298 /*
1299 * vim:et:ts=8:sts=2:sw=2
1300 */
1301