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