/*
io.c
All the functions that interact with hardware and subprocesses
and file IO.
28.3.99 tn
*/
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <time.h>
#ifdef linux
#include <sys/soundcard.h>
#include <sys/ioctl.h>
#endif
#ifdef sun
#include <sys/audioio.h>
#endif
#ifdef hpux
#include <sys/audio.h>
#endif
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <glib.h>
#include "xcdroast.h"
#include "main.h"
scsi_devices_t **scsidevices;
gint scsicount;
gint busnr;
cd_info_t cdinfo;
track_info_t **trackinfo;
gint tocstate;
gint tocnr;
writer_driver_t **drivers;
writer_driver_t **blankmodes;
writer_driver_t **drv_options;
gint drvcount;
gint drvoptcount;
gint dfrun;
gint readcdda_callback;
gint readcdda_callback2;
gint readcdda_callback3;
gint read_done;
gint read_output_ctrl;
gint read_abort_mark;
gint read_tracknr;
gchar readtrack_info_string[1024];
gfloat pct_so_far, pct_this_track;
write_track_param_t writeparams;
pid_t readcdda_pid;
gint readcd_startsector, readcd_endsector;
gint readerr_count;
gint matchnr;
gint cddb_in;
gchar cdinfo_cddb_title_bak[MAXLINE];
gint cd_is_still_the_same;
gint cdrecord_stdin, cdrecord_reload;
gchar xcdroast_version_loaded[MAXLINE];
extern gint debug;
extern gint ignorescanbus;
extern gint dialog_done2, dialog_done, dialog_done3;
extern setup_data_t setupdata;
extern track_read_set_t trackreadset;
extern current_set_t curset;
extern gchar *system_platform;
extern GtkWidget *readtrack_info_label, *readtrack_textview;
extern GtkWidget *readtrack_pbar1, *readtrack_pbar2, *readtrack_pbar3;
extern GtkWidget *readtrack_small_info, *readtrack_small_info2;
extern gchar hostname[MAXLINE];
extern gchar username[MAXLINE];
extern gchar sharedir[MAXLINE];
extern GtkWidget *cddb_info_label;
extern GtkCList *cddb_clist;
extern master_param_t masterparam;
void verify_readcd_err(gpointer pid, gint source, GdkInputCondition cond);
/* convert device-type-names back to numeric */
/* -1 means unknown */
gint get_scsi_type(gchar *type) {
if (strcmp(type,"Disk") == 0) {
return 0;
}
if (strcmp(type,"Tape") == 0) {
return 1;
}
if (strcmp(type,"Printer") == 0) {
return 2;
}
if (strcmp(type,"Processor") == 0) {
return 3;
}
if (strcmp(type,"WORM") == 0) {
return 4;
}
if (strcmp(type,"CD-ROM") == 0) {
return 5;
}
if (strcmp(type,"Scanner") == 0) {
return 6;
}
if (strcmp(type,"Optical Storage") == 0) {
return 7;
}
if (strcmp(type,"Juke Box") == 0) {
return 8;
}
if (strcmp(type,"Communication") == 0) {
return 9;
}
return -1;
}
/* convert the scsi-type-number back to string */
void get_scsi_type_string(gchar *str, gint type, gint removeable) {
switch(type) {
case 0:
if (removeable == 0) {
strcpy(str,text(250));
} else {
strcpy(str,text(251));
}
break;
case 1:
strcpy(str,text(252));
break;
case 2:
strcpy(str,text(253));
break;
case 3:
strcpy(str,text(254));
break;
case 4:
strcpy(str,text(255));
break;
case 5:
strcpy(str,text(256));
break;
case 6:
strcpy(str,text(257));
break;
case 7:
strcpy(str,text(258));
break;
case 8:
strcpy(str,text(259));
break;
case 9:
strcpy(str,text(260));
break;
default:
strcpy(str,"");
break;
}
}
/* get model-str dynamic..some devices dont use all 16 chars */
gint get_model_str(gchar *model, gchar *in) {
gint i;
for (i = 0; i < strlen(in); i++) {
if (in[i] == '\'') {
strncpy(model, in, i);
strncat(model," ",16-i);
model[16] = '\0';
return (i+3);
}
}
return 0;
}
/* interpret output of -scanbus and sort into memory structure */
void parse_scan(gchar *line) {
gchar tmp[MAXLINE];
gchar tmp2[MAXLINE];
gchar *p1, *p2;
gint s_id;
gchar s_vendor[9];
gchar s_model[17];
gchar s_rev[5];
gint s_removable;
gint s_type;
gint increment;
/* skip header */
if (strncmp(line,"Cdrecord",8) == 0) {
return;
}
if (strncmp(line,"scsibus",7) == 0 ) {
/* set current scsibus nr */
strcpy(tmp,line+7);
p1=strtok(tmp,":");
strcpy(tmp2,p1);
/* now tmp2 contains the current busnr as string */
busnr = atoi(tmp2);
return;
}
/* a line with an error message? */
get_spawn_path(CDRECORD,tmp);
if (strncmp(line, tmp, strlen(tmp)) == 0) {
return;
}
/* a line with device-info found (by checking for ")")*/
p1 = index(line,')');
if (p1 != NULL) {
strip_string(line);
/* get scsi-id */
p1=strtok(line,")");
strcpy(tmp,p1);
strcpy(tmp2,p1);
/* look for last tab or last space in tmp and remove
everything before */
p1=rindex(tmp2,'\t');
p2=rindex(tmp2,' ');
if (p1 > p2) {
/* last interesting char was a tab - cut here */
if (p1 != NULL) {
strcpy(tmp,p1+1);
}
} else {
/* last interesting char was a space - cut here */
if (p2 != NULL) {
strcpy(tmp,p2+1);
}
}
s_id = atoi(tmp);
/* strip host-id from scsi-id-number */
s_id = s_id % 100;
p1=strtok(NULL,"'");
strcpy(tmp,p1);
strip_string(tmp);
if (*tmp == '*') {
/* no device found */
return;
}
if (*tmp == 'H') {
/* HOST ADAPTER found */
/* treat as no device for now */
return;
}
/* get full rest of line */
p1=strtok(NULL,"");
strcpy(tmp,p1);
if (*tmp == '\'') {
/* empty device found? ignore */
return;
}
/* get vendor */
strncpy(s_vendor,tmp,8);
s_vendor[8] = '\0';
if (tmp[8] != '\'') {
g_error("cdrecord -scanbus output syntax error\n");
}
/* get model */
strcpy(tmp2,tmp+11);
strcpy(tmp,tmp2);
increment = get_model_str(s_model,tmp);
if (s_model[16] != '\0') {
g_error("cdrecord -scanbus output syntax error\n");
}
/* get revision */
strcpy(tmp2,tmp+increment);
strcpy(tmp,tmp2);
/* empty revision? */
if (strncmp(tmp,"'",1) == 0) {
strcpy(s_rev,"");
increment = 2;
} else {
strncpy(s_rev,tmp,4);
s_rev[4] = '\0';
if (tmp[4] != '\'') {
g_error("cdrecord -scanbus output syntax error\n");
}
increment = 6;
}
/* get type */
strcpy(tmp2,tmp+increment);
strcpy(tmp,tmp2);
strip_string(tmp);
if (strncmp(tmp,"Removable",9) == 0) {
s_removable = 1;
strcpy(tmp2,tmp+10);
strcpy(tmp,tmp2);
} else {
s_removable = 0;
}
s_type = get_scsi_type(tmp);
/* allocate and fill structure */
scsidevices[scsicount]=g_new(scsi_devices_t,1);
scsidevices[scsicount]->devnr = busnr*32+s_id;
scsidevices[scsicount]->bus = busnr;
scsidevices[scsicount]->id = s_id;
strcpy(scsidevices[scsicount]->vendor,s_vendor);
strcpy(scsidevices[scsicount]->model,s_model);
strcpy(scsidevices[scsicount]->rev,s_rev);
scsidevices[scsicount]->removable = s_removable;
scsidevices[scsicount]->type = s_type;
scsicount++;
if (scsicount >= MAXDEVICES) {
g_error("Error: More than %d devices scanned\n",MAXDEVICES);
}
}
}
/* print memory-structure with scsidevices (debug purposes) */
void print_scsidevices() {
gint count;
dodebug(2,"------ cdrecord scsidevices-structure -----\n");
count = 0;
while(scsidevices[count] != NULL) {
dodebug(2,"%d:%d %s %s %s %d,%d\n",
scsidevices[count]->bus,
scsidevices[count]->id,
scsidevices[count]->vendor,
scsidevices[count]->model,
scsidevices[count]->rev,
scsidevices[count]->removable,
scsidevices[count]->type);
count++;
}
}
/* call cdrecord -scanbus */
/* does rely very strict on the output-format... does use fixed length
deleminitors to be sure that quotes within an id-string will handled
fine - therefore no strtok usage */
void scanbus() {
gchar line[MAXLINE];
FILE *fpin;
/* allocate memory */
scsidevices = g_new0(scsi_devices_t *,MAXDEVICES);
scsicount = 0;
get_spawn_path(CDRECORD,line);
strcat(line," -scanbus 2>&1");
dodebug(1, "calling: %s\n", line);
if ((fpin = popen(line,"r")) == NULL) {
g_error("popen error\n");
}
for (;;) {
if