Filewatcher File Search
FTP Search
  
Directory (beta)
  
Content Search (beta)
   
pkg://xcdroast-debuginfo-0.98a15-14.fc7.ppc.rpm:614443/usr/src/debug/xcdroast-0.98alpha15/src/xtools.c  info  downloads

/*
	xtools.c
	27.3.99 tn
*/

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include "largefile.h"

#if HAVE_LOCALE_H
#include <locale.h>
#else
# define setlocale(Category, Locale) 
#endif
#include "gettext.h"

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <dirent.h>
#include <fcntl.h>
#include <sys/types.h>
#include <errno.h>
#include <ctype.h>
#include <grp.h>
#include <pwd.h>

#if ENABLE_NLS
# define _(String) gettext (String)
# define N_(String) gettext_noop (String)
#else
# define _(String) (String)
# define N_(String) (String)
#endif

#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include "xcdrdata.h"
#include "xcdroast.h"
#include "main.h"

extern gint debug;
extern writerreader_devices_t **writerreaderdevs;
extern gchar **alt_scsidevices;
extern setup_data_t setupdata;
extern cd_info_t cdinfo;
extern track_info_t **trackinfo;
extern GList *imagelist;
extern current_set_t curset;
extern track_read_set_t trackreadset;
extern GList *tocfiles;
extern GList *writelist;
extern gint bigfonts;
extern gint oldfontcode;
extern gchar sharedir[MAXLINE];
extern gchar prefixdir[MAXLINE];
extern gint c_locale_is_utf8;

void define_tooltip(GtkWidget *widget, gchar *ttext) {
GtkTooltips *tip;

#ifdef YELLOW_TIPS
GdkColor bg;
GtkStyle *style;
#endif
	/* tooltips wanted? */
	if (setupdata.option_tooltips == 0) {
		return;
	}

	tip = gtk_tooltips_new();
	gtk_tooltips_set_tip(tip,widget,ttext,NULL);

	/* set tip color (yellow) */

	/*
	*** Commented by C.W.Huang :
	*** Why set tip color by hand? It should be set by the theme.
	*** Due to an unknown feature or bug of gtk_widget_set_style(),
	*** GdkFont of the tip will be changed so multibyte characters
	*** cannot be displayed correctly!
	*/
#ifdef YELLOW_TIPS

	gtk_tooltips_force_window(tip);
	if (!gdk_color_parse(TOOLTIPCOL,&bg)) {
		g_warning("Can't parse color %s\n",TOOLTIPCOL);
		return;
	}
        if (!gdk_color_alloc(gtk_widget_get_colormap(tip->tip_window),&bg)) {
		g_warning("Cant allocate color %s\n",TOOLTIPCOL);
		return;
	}
	style = gtk_style_copy(gtk_widget_get_style(tip->tip_window));
	style->bg[GTK_STATE_NORMAL] = bg;
	gtk_widget_set_style(tip->tip_window, style);
#endif
}


/* sets the font and color for a label widget.
   if color/font is NULL then don't set color/font  */

void set_font_and_color(GtkWidget *widget, gchar *font, gchar *color) {

#if GTK_MAJOR_VERSION < 2
GtkStyle *style;
GdkColor c;
gchar tmp[MAXLINE];
gchar *p;

	style=gtk_style_copy(gtk_widget_get_style(widget));

	if (font != NULL) {
		gdk_font_unref(style->font);

		/* make copy of string, because we use strtok later */
		strncpy(tmp,font,MAXLINE);

		/* for unknown reasons in some locales the fonts do
		   not work correcly bold or italic when using fontset */
		if (oldfontcode) {

			/* now use only the definition up to the first comma */
			p = strtok(tmp,",");
			if (p) {			
				style->font = gdk_font_load(p);
			} else {
				style->font = gdk_font_load(font);
			}
		} else {
			style->font = gdk_fontset_load(tmp);
		}

        	/* check if valid font */
        	if (style->font == NULL) {
                	g_warning("Font %s not found\n",tmp);
                	return;
        	}
	}

	if (color != NULL) {
		if (!gdk_color_parse(color,&c)) {
			g_warning("Can't parse color %s\n",color);
			return;
		}

        	if (!gdk_color_alloc(gtk_widget_get_colormap(widget),&c)) {
			g_warning("Cant allocate color %s\n",color);
			return;
		}

		style->fg[GTK_STATE_NORMAL] = c;
	}
	
	gtk_widget_set_style(GTK_WIDGET(widget),style);

#else
	/* version for GTK 2 */

gchar *orglabel;
gchar *newlabel;
gint length;

	newlabel = NULL;
	orglabel = (gchar *)gtk_label_get_text(GTK_LABEL(widget));
	
	if (font && strcmp(font, BOLDFONT) == 0 && !color) {
		length = strlen(orglabel) + strlen("<b></b>") + 1;
		newlabel = (gchar *) g_new0(gchar *, length); 
		g_snprintf(newlabel, length, "<b>%s</b>", orglabel);
	}
	if (font && strcmp(font, BIGFONT) == 0 && !color) {
		length = strlen(orglabel) + strlen("<span size=\"xx-large\"></span>") + 1;
		newlabel = (gchar *) g_new0(gchar *, length); 
		g_snprintf(newlabel, length, "<span size=\"xx-large\">%s</span>", orglabel);
	}
	if (color && !font) {
		length = strlen(orglabel) + strlen("<span color=\"\"></span>") + strlen(color) + 1;
		newlabel = (gchar *) g_new0(gchar *, length); 
		g_snprintf(newlabel, length, "<span color=\"%s\">%s</span>", color, orglabel);
	}
	if (font && strcmp(font, BOLDFONT) == 0 && color) {
		length = strlen(orglabel) + strlen("<b><span color=\"\"></span></b>") + strlen(color) + 1;
		newlabel = (gchar *) g_new0(gchar *, length); 
		g_snprintf(newlabel, length, "<b><span color=\"%s\">%s</span></b>", color, orglabel);
	}
	if (font && strcmp(font, BIGFONT) == 0 && color) {
		length = strlen(orglabel) + strlen("<span color=\"\" size=\"xx-large\"></span>") + strlen(color) + 1;
		newlabel = (gchar *) g_new0(gchar *, length); 
		g_snprintf(newlabel, length, "<span color=\"%s\" size=\"xx-large\">%s</span>", color, orglabel);
	}

	if (newlabel) {
		gtk_label_set_text(GTK_LABEL(widget),newlabel);	
		gtk_label_set_use_markup (GTK_LABEL(widget), TRUE);
		g_free(newlabel);
	}
#endif
}


/* set font and color for a frame */

void set_font_and_color_frame(GtkWidget *widget, gchar *font, gchar *color) {

#if GTK_MAJOR_VERSION < 2
	/* gtk1 version is identical to label version */
	set_font_and_color(widget, font, color);
#else

	set_font_and_color(gtk_frame_get_label_widget(GTK_FRAME(widget)), font, color);

#endif
}

/* sets the color for a label widget.
   if color is NULL then don't set color/font  */

void set_labelcolor(GtkWidget *widget, gchar *color) {
GtkStyle *style;
GdkColor c;

	style=gtk_style_copy(gtk_widget_get_style(widget));

	if (color != NULL) {
		if (!gdk_color_parse(color,&c)) {
			g_warning("Can't parse color %s\n",color);
			return;
		}

        	if (!gdk_color_alloc(gtk_widget_get_colormap(widget),&c)) {
			g_warning("Cant allocate color %s\n",color);
			return;
		}

		style->fg[GTK_STATE_NORMAL] = c;
	}
	
	gtk_widget_set_style(GTK_WIDGET(widget),style);
}


/* sets a certain row in a clist to a font */

void set_clist_row_font(GtkCList *clist, gint row, gchar *ffont) {

#if GTK_MAJOR_VERSION < 2
GtkStyle *style;
gchar tmp[MAXLINE];
gchar *p;

	style=gtk_style_copy(gtk_widget_get_style(GTK_WIDGET(clist)));

	/* make copy of string, because we use strtok later */
	strncpy(tmp,ffont,MAXLINE);

	gdk_font_unref(style->font);
	/* for unknown reasons in some locales the fonts do
	   not work correcly bold or italic when using fontset */
	if (oldfontcode) {
		/* now use only the definition up to the first comma */
		p = strtok(tmp,",");
		if (p) {			
			style->font = gdk_font_load(p);
		} else {
			style->font = gdk_font_load(ffont);
		}
	} else {
		style->font = gdk_fontset_load(tmp);
	}

       	/* check if valid font */
       	if (style->font == NULL) {
               	g_warning("Font %s not found\n",tmp);
               	return;
       	}

	gtk_clist_set_row_style(clist,row,style);
#else
	/* version for GTK 2 */

GtkStyle *style;

	style=gtk_style_copy(gtk_widget_get_style(GTK_WIDGET(clist)));

	if (ffont && strcmp(ffont, SLANTFONT) == 0) {
		pango_font_description_set_style(style->font_desc,
			PANGO_STYLE_ITALIC);
	}
	if (ffont && strcmp(ffont, BOLDFONT) == 0) {
		pango_font_description_set_weight(style->font_desc, 
			PANGO_WEIGHT_BOLD);
	}
	
	gtk_clist_set_row_style(clist,row,style);

#endif

}


/* colors a certain row in a clist */

void set_clist_row_color(GtkCList *clist, gint row, gchar *color) {
GtkStyle *style;
GdkColor c;

	style=gtk_style_copy(gtk_widget_get_style(GTK_WIDGET(clist)));

	if (!gdk_color_parse(color,&c)) {
		g_warning("Can't parse color %s\n",color);
		return;
	}

       	if (!gdk_color_alloc(gtk_widget_get_colormap(GTK_WIDGET(clist)),&c)) {
		g_warning("Cant allocate color %s\n",color);
		return;
	}
	style->fg[GTK_STATE_NORMAL] = c;

	gtk_clist_set_row_style(clist,row,style);
}


/* return the given font (you have to unref it later) */

GdkFont *get_some_font(gchar *fontstr) {
gchar tmp[MAXLINE];
gchar *p;
GdkFont *font;

	strncpy(tmp,fontstr,MAXLINE);

	if (oldfontcode) {
		/* now use only the definition up to the first comma */
		p = strtok(tmp,",");
		if (p) {			
			font = gdk_font_load(p); 
			/* for some reason the defaul fixed font seems not to work - hard core here another font for ancient systems */
	/*		font = gdk_font_load("-*-*-medium-r-normal-*-*-120-*-*-*-*-*-*"); */
		} else {
			font = gdk_font_load(fontstr);
		}
	} else {
		font = gdk_fontset_load(tmp);	
	}

	return font;
}


/* free a simple glist structure */

void free_glist(GList **list) {
GList *loop;
gchar *dir;

	loop = g_list_first(*list);
	while(loop) {
		dir = loop->data;
		g_free(dir); 
		loop = loop->next;
	}
	g_list_free(*list);
	*list = NULL;	
}


/* copy a simple glist (which has only strings as elements) */

void copy_glist(GList **dst, GList *src) {
GList *loop;
gchar *dir;

	/* clear target list */
	free_glist(dst); 

	loop = g_list_first(src);
	while(loop) {
		dir = loop->data;
		*dst = g_list_append(*dst,g_strdup(dir)); 
		loop = loop->next;
	}
}


/* remove a string-element from a glist */

void del_glist_link(GList **list, gchar *str) {
GList *loop;
gchar *dir;

	if (str == NULL) 
		return;

	loop = g_list_first(*list);
	while(loop) {
		dir = loop->data;
		if (dir && strcmp(str,dir) == 0) {
			g_free(dir); 
			*list = g_list_remove_link(*list, loop);
			return;
		}
		loop = loop->next;
	}
}


/* check if a string-element is in a glist */
/* return 1 if found, 0 if not */

gint check_in_glist(GList **list, gchar *str) {
GList *loop;
gchar *dir;

	if (str == NULL) 
		return 0;

	loop = g_list_first(*list);
	while(loop) {
		dir = loop->data;
		if (dir && strcmp(str,dir) == 0) {
			return 1;
		}
		loop = loop->next;
	}
	return 0;
}


/* check if a path is in a master-path-glist */
/* return 1 if found, 0 if not */

gint check_in_mstr_glist(GList **list, gchar *str) {
GList *loop;
mstr_redirect_t *mstr;
gchar *dir;

	if (str == NULL) 
		return 0;

	loop = g_list_first(*list);
	while(loop) {
		mstr = (mstr_redirect_t *) loop->data;
		if (mstr) {
			dir = mstr->mstr_path;
		} else {
			dir = NULL;
		}
		if (dir && strcmp(str,dir) == 0) {
			return 1;
		}
		loop = loop->next;
	}
	return 0;
}


/* remove a string-element from a master-glist */
/* if there is a redir-path, remove only this and return */
/* (unless del_both is set, where the whole entry is removed) */
/* del_both == -1, only remove link if possible */

void del_mstr_glist_link(GList **list, gchar *str, gint del_both) {
GList *loop;
mstr_redirect_t *mstr;
gchar *dir;

	if (str == NULL) 
		return;

	loop = g_list_first(*list);
	while(loop) {
		mstr = (mstr_redirect_t *) loop->data;
		if (mstr) {
			dir = mstr->mstr_path;
		} else {
			dir = NULL;
		}

		if (dir && strcmp(str,dir) == 0) {
			/* found link */
			if (mstr->redir_path) {
				/* remove redir-path only */
				g_free(mstr->redir_path);
				mstr->redir_path = NULL;

				if (del_both == 0)
					return;
			}
			if (del_both == -1) return;

			g_free(dir); 
			g_free(mstr);
			*list = g_list_remove_link(*list, loop);
			return;
		}
		loop = loop->next;
	}
}


/* clear a mstr_glist */

void clear_mstr_glist(GList **list) {
GList *loop;
mstr_redirect_t *mstr;

	loop = g_list_first(*list);
	while(loop) {
		mstr = (mstr_redirect_t *) loop->data;
		if (mstr) {
			if (mstr->mstr_path) 
				g_free(mstr->mstr_path);
			if (mstr->redir_path) 
				g_free(mstr->redir_path);
			g_free(mstr);
		}
		loop = loop->next;
	}
	g_list_free(*list);
	*list = NULL;	
}


/* add a redir path to the master-glist */

void add_redir_mstr_glist(GList **list, gchar *str, gchar *new) {
GList *loop;
mstr_redirect_t *mstr;
gchar *dir;

	if (str == NULL) 
		return;

	loop = g_list_first(*list);
	while(loop) {
		mstr = (mstr_redirect_t *) loop->data;
		if (mstr) {
			dir = mstr->mstr_path;
		} else {
			dir = NULL;
		}
		if (dir && strcmp(str,dir) == 0) {
			/* found link */
			if (mstr->redir_path) {
				/* remove redir-path first */
				g_free(mstr->redir_path);
			}
			/* now set new value */
			mstr->redir_path = g_strdup(new);
			return;
		}
		loop = loop->next;
	}
}


/* get a string in the form bla => foo and return only bla */

void extract_mstr_path_from_clist(gchar *in, gchar *out) {
gint found;
guint i;

	if (in == NULL || out == NULL) 
		return;

        if (strlen(in) == 0) {
                strcpy(out,"");
                return;
        }

	found = -1;

	for (i = 0; i < strlen(in)-1; i++) {
		if ((in[i] == '=') && (in[i+1] == '>')) {
			found = i;
			break;
		}
	} 

	if (found == -1) {
		/* nothing found - return original string */
		strcpy(out,in);
	} else {
		strncpy(out,in,found);
		out[found] = '\0';
	}
	strip_string(out);

	/* internally we use not utf8, convert back from widget */
	convert_for_gtk2_filename(out);
}


/* get the redir path from the master-glist */

void get_redir_path_from_mstr_glist(GList **list, gchar *str, gchar *ret) {
GList *loop;
mstr_redirect_t *mstr;
gchar *dir;

	if (str == NULL) 
		return;

	loop = g_list_first(*list);
	while(loop) {
		mstr = (mstr_redirect_t *) loop->data;
		if (mstr) {
			dir = mstr->mstr_path;
		} else {
			dir = NULL;
		}
		if (dir && strcmp(str,dir) == 0) {
			/* found link */
			if (mstr->redir_path) {
				strcpy(ret, mstr->redir_path);
			} else {
				strcpy(ret, "");
			}
			return;
		}
		loop = loop->next;
	}
	strcpy(ret, "");
}


/* set scsi-sector-size for a given device */

void set_sectorsize(gint devnr, gint size) {
gint i;

        i = 0;
        while(writerreaderdevs[i] != NULL) {
                if (devnr == writerreaderdevs[i]->devnr) {
                        writerreaderdevs[i]->sector_size = size;
                        return;
                }
                i++;
        }
}


/* get scsi-sector-size for a given device */

gint get_sectorsize(gint devnr) {
gint i;

        i = 0;
        while(writerreaderdevs[i] != NULL) {
                if (devnr == writerreaderdevs[i]->devnr) {
                        return(writerreaderdevs[i]->sector_size);
                }
                i++;
        }
 
        return DATASECTORSIZE;
}


/* convert the devnr to a device-string. return 1 if devnr not found */

gint convert_devnr2devstring(gint devnr, gchar *str) {
gint i;
gchar tmp[MAXLINE];

	i = 0;
	while(writerreaderdevs[i] != NULL) {
		if (devnr == writerreaderdevs[i]->devnr) {
			if (!writerreaderdevs[i]->devicestr) {
				g_error("empty device string?");
			}
			g_snprintf(tmp,MAXLINE,"%s %s [%s]",
				writerreaderdevs[i]->vendor, 
				writerreaderdevs[i]->model,
				writerreaderdevs[i]->devicestr);
			strcpy(str,tmp);
			return 0;
		}
		i++;
	}

	strcpy(str,"");
	return 1;
}


/* convert the devnr to a vendor-string. return 1 if devnr not found */

gint convert_devnr2vendor(gint devnr, gchar *str) {
gint i;

	i = 0;
	while(writerreaderdevs[i] != NULL) {
		if (devnr == writerreaderdevs[i]->devnr) {
			strcpy(str,writerreaderdevs[i]->vendor);
			return 0;
		}
		i++;
	}
	strcpy(str,"");
	return 1;
}


/* convert the devnr to a model-string. return 1 if devnr not found */

gint convert_devnr2model(gint devnr, gchar *str) {
gint i;

	i = 0;
	while(writerreaderdevs[i] != NULL) {
		if (devnr == writerreaderdevs[i]->devnr) {
			strcpy(str,writerreaderdevs[i]->model);
			return 0;
		}
		i++;
	}
	strcpy(str,"");
	return 1;
}


/* convert the devnr to a bus/id/lun-string. return 1 if devnr not found */

gint convert_devnr2busid(gint devnr, gchar *str) {
gint i;

	i = 0;
	while(writerreaderdevs[i] != NULL) {
		if (devnr == writerreaderdevs[i]->devnr) {
			if (!writerreaderdevs[i]->devicestr) {
				g_error("empty device string?");
			}
			strncpy(str,
			    writerreaderdevs[i]->devicestr,
			    MAXLINE);
			convert_escape(str);
			return 0;
		}
		i++;
	}
	strcpy(str,"");
	return 1;
}


/* save as convert_devnr2busid(), but return with dev= component */

gint convert_devnr2busid_dev(gint devnr, gchar *str) {
gint i;
gchar tmp[MAXLINE];

	i = 0;
	while(writerreaderdevs[i] != NULL) {
		if (devnr == writerreaderdevs[i]->devnr) {
			if (!writerreaderdevs[i]->devicestr) {
				g_error("empty device string?");
			}
			strncpy(tmp,
			    writerreaderdevs[i]->devicestr,
			    MAXLINE);
			convert_escape(tmp);
			g_snprintf(str,MAXLINE,"dev= \"%s\"",tmp);
			return 0;
		}
		i++;
	}
	strcpy(str,"");
	return 1;
}


/* convert kilobytes to MB/min string */
/* displays MB when using 2048b sectors. min like stored audiotracks on the
   hard drive - this is not correct when displaying the minutesize of DATA
   tracks. */ 

void convert_kbytes2mbminstring(gint kbytes, gchar *str) {
gint mb;
gint min;
gint sec;
gint frames;
gint frms;
gint64 tmpsize;

	mb = kbytes/1024;
	
#if 0
	/* we have a problem here, that we hit gint overflow on
	   large values - in this case round a little inexact */
	if (mb < 2000) {
		/* correct value */
		frames = (kbytes*1024)/CDDAFRAME;
	} else {
		/* rounded value */
		frames = (kbytes/CDDAFRAME)*1024;
	}	
#endif
	/* new code using 64 bit values */
	tmpsize = (gint64)kbytes * 1024;
	frames = (gint) ((gint64)tmpsize/CDDAFRAME);
	
	min = frames/(60*75);
	sec = (frames%(60*75))/75;
	frms = (frames%75);
	/* csec = (4*(frames%75)+1)/3; */

	g_snprintf(str,MAXLINE,"%dMB / %d:%02d.%02d",mb,min,sec,frms);
}


/* convert kilobytes to MB/min string */
/* displays MB when using 2048b sectors. min like the size of track after
   burned. The only correct min size display when burning data tracks */ 

void convert_kbytes2mbcorrectminstring(gint kbytes, gchar *str) {
gint mb;
gint min;
gint sec;
gint frames;
gint frms;

	mb = kbytes/1024;
	frames = kbytes/2;	
	min = frames/(60*75);
	sec = (frames%(60*75))/75;
	frms = (frames%75);
	/* csec = (4*(frames%75)+1)/3; */

	g_snprintf(str,MAXLINE,"%dMB / %d:%02d.%02d",mb,min,sec,frms);
}


/* convert frames to MB/min string */
/* should only be used for audio or full disk info */

void convert_frames2mbminstring(gint frames, gchar *str) {
gint mb;
gint min;
gint sec;
gint frms;
gint64 tmpsize;

#if 0
	mb = ((frames/1024)*CDDAFRAME)/1024; 
	/* mb = ((frames/1024)*DATASECTORSIZE)/1024; */
#endif
	/* use 64 bit values */
	tmpsize = (gint64)frames * CDDAFRAME;
	mb = (gint) ((gint64)tmpsize >> 20);

	min = frames/(60*75);
	sec = (frames%(60*75))/75;
	frms = (frames%75);
	/* csec = (4*(frames%75)+1)/3; */

	g_snprintf(str,MAXLINE,"%dMB / %d:%02d.%02d",mb,min,sec,frms);
}


/* convert frames/sectors to MB string */
/* note - this is only true for DATA-tracks */

void convert_frames2mbstring(gint frames, gchar *str) {
gint mb;

	mb = frames*(DATASECTORSIZE/1024)/1024;
	g_snprintf(str,MAXLINE,"%dMB",mb);
}


/* convert kbytes to MB string */

void convert_kbytes2mbstring(gint kbytes, gchar *str) {
gint mb;

	mb = kbytes/1024;
	g_snprintf(str,MAXLINE,"%dMB",mb);
}


/* convert frames to min string */

void convert_frames2minstring(gint frames, gchar *str) {
gint min;
gint sec;
gint frms;

	min = frames/(60*75);
	sec = (frames%(60*75))/75;
	frms = (frames%75);
	/* csec = (4*(frames%75)+1)/3; */

	g_snprintf(str,MAXLINE,"%d:%02d.%02d",min,sec,frms);
}


/* creates a label that is right justified. Useful when
   packing into a table */

GtkWidget *rightjust_gtk_label_new(gchar *txt) {
GtkWidget *align;
GtkWidget *label;

	/* create right justify alignment */
	align = gtk_alignment_new(1.0,0.5,0,0);
	label = gtk_label_new(txt);
	gtk_container_add(GTK_CONTAINER(align),label);
	gtk_widget_show(label);

	return align;
}


/* creates a label that is left justified. Useful when
   packing into a table */

GtkWidget *leftjust_gtk_label_new(gchar *txt) {
GtkWidget *align;
GtkWidget *label;

	/* create left justify alignment */
	align = gtk_alignment_new(0.0,0.5,0,0);
	label = gtk_label_new(txt);
	gtk_container_add(GTK_CONTAINER(align),label);
	gtk_widget_show(label);

	return align;
}


/* get some info about our image-file */

static void analyze_imgfile(gchar *path, gchar *file, GList **retlist) {
struct stat buf;
image_files_t *entry;
gchar tmp[MAXLINE];
gchar volid[MAXLINE];
off_t size;
gint type,readable,isosize;
gint fd;

	strncpy(tmp,path,MAXLINE-strlen(file)-2);
	strcat(tmp,"/");
	strcat(tmp,file);

	stat(tmp,&buf);

	/* check if regular file or link */
	if (S_ISLNK(buf.st_mode) != 1 && S_ISREG(buf.st_mode) != 1) {
		/* its not..so ignore */
		return;
	} 

	/* readable for us? */
	fd = open(tmp, O_RDONLY,0);
	if (fd == -1) {
		readable = 0;
	} else {
		readable = 1;
		close(fd);
	}	
	
	size = (off_t) buf.st_size;

	isosize = 0;

	/* now do some tests about file-contents */
	if (strncmp(file+strlen(file)-4,".toc",4) == 0) {
		type = 4;
	} else if (strncmp(file+strlen(file)-4,".wav",4) == 0) {
		/* wav-file */
		if (check_wav_file(tmp) == 0) {
			/* invalid wav */
			type = 2;
		} else {
			/* valid wav */
			type = 1;
		}
	} else {
		/* data-file */
		isosize = check_iso_file(-1,tmp,volid,0);
		if (isosize == 0) {
			/* unknown data */
			type = 3;
		} else {
			/* iso9660 */
			type = 0;
		}
	}

	/* allocate memory and fill structure */
	entry = g_new(image_files_t,1);
	entry->path = g_strdup(tmp);
	entry->mtime = buf.st_mtime;
	entry->size = (off_t) size;
	entry->type = type;
	entry->readable = readable;
	entry->from_track = 0;
	if (type == 0) {
		entry->volname = g_strdup(volid);
	} else {
		entry->volname = NULL;
	}
	entry->title = NULL;
	entry->artist = NULL;
	entry->cddb_ttitle = NULL;
	entry->cd_discid = NULL;
	
	entry->isosize = isosize;
	entry->last_session_start = -1;
	entry->next_session_start = -1;

	/* find if there is some information in the inf-file */
	get_inf_tracktitle(tmp, entry);

	/* add to list */
	*retlist = g_list_append(*retlist, entry);
}


/* scans a directory for files matching the known extensions */
/* return 0 if ok, 1 on problem */

gint get_img_files(gchar *path, GList **retlist) {
gchar *img_ext[] = IMG_EXTENSIONS;
struct dirent *ent;
DIR *dir;         
gint i,len,len2;

	dir = opendir(path);

	/* invalid directory */
	if (dir == NULL) 
		return 1;

	/* scan a directory */
	while ( (ent = readdir(dir)) ) {
		/* does the extension match? */
		for(i = 0; img_ext[i] != NULL; i++) {
			len = strlen(img_ext[i]);
			len2 = strlen(ent->d_name);

			/* skip to short filenames */
			if (len2 < len) continue;

			if (strncmp((ent->d_name)+len2-len,img_ext[i],len) == 0) {
				/* we found a match */
				analyze_imgfile(path,ent->d_name,retlist);			
			}
		}		
	}

	closedir(dir);
	return 0;
}


/* print imagelist-memory-structure (debug purpose) */

void print_imagelist() {
GList *loop;
image_files_t *entry;

	dodebug(2,"--------- imagelist glist ---------\n");
	loop = g_list_first(imagelist);
	while (loop) {
		entry = loop->data;
		dodebug(2,"path: %s, %"LL_FORMAT", %d, %d, %d (%d,%d)\n",entry->path,
			(gint64)entry->size, entry->type, entry->readable,
			entry->isosize, entry->last_session_start, 
			entry->next_session_start);
		if (entry->volname != NULL) {
			dodebug(2, "\tvolname: %s\n", entry->volname);
		}

		loop = loop->next;
	}	
}


/* sort the imagelist according to file names */

void sort_imagelist() {
GList *first, *last, *list1, *list2;
image_files_t *ent1, *ent2, *ent3;

       first = g_list_first(imagelist);
       last = g_list_last(imagelist);
       for (list1 = first; list1 != last; list1 = list1->next) {
               for (list2 = last; list2 != list1; list2 = list2->prev) {
                       ent1 = (image_files_t *) list1->data;
                       ent2 = (image_files_t *) list2->data;

                       if(strcmp(ent1->path,ent2->path) > 0) {
                               ent3 = ent1;
                               list1->data = list2->data;
                               list2->data = ent3;
                       }
               }
       }
}


/* search all image-directories and create a list of matching files */
/* return number of matching files */

gint scan_imagedirs() {
GList *loop;
gchar tmp[MAXLINE];
image_files_t *entry;

	/* free the old image-list first */
	loop = g_list_first(imagelist);
	while (loop) {
		entry = loop->data;
		g_free(entry->path);
		g_free(entry->volname);
		g_free(entry->title);
		g_free(entry->artist);
		g_free(entry->cddb_ttitle);
        	g_free(entry->cd_discid);
		g_free(entry);

		loop = loop->next;
	}
	g_list_free(imagelist);
	imagelist = NULL;

	loop = g_list_first(setupdata.image_dirs);
	while (loop) {
		/* image-dir extracted */
		strncpy(tmp,(gchar *)loop->data, MAXLINE);
		get_img_files(tmp,&imagelist);

		loop = loop->next;
	}

	/* sort the image-list */
	sort_imagelist();

	/* now we have a complete image-list */
	if (debug) print_imagelist(); 

	return (g_list_length(imagelist));
}


/* return a string saying which type of CD we are currently handling */
/* mode = 0: used check cd in drive, mode = 1: check trackreadset for
   writing */

gint determine_cd_type(gchar *ret, gint mode) {
gint i;
gint audio,data;
gint type;
gchar tmp[MAXLINE];
GList *loop;
track_read_param_t *trackparam;
	
	/* unknown type */
	type = -1;

	/* count tracks */
	audio = 0;
	data = 0;
	trackparam = NULL;
	
	
	if (mode == 0) {
		/* check cdinfo-structure */
		for (i = 0; i < cdinfo.nr_tracks; i++) {
			if (trackinfo[i]->type == 0) {
				data++;
			} else {
				audio++;
			}
		}
	} else {
		/* check trackreadset-structure */
		loop = g_list_first(trackreadset.trackparams);
		while(loop) {
			trackparam = loop->data;
			if (trackparam->tracktype == 0) {
				data++;
			} else {
				audio++;
			}

			loop = loop->next;
		}
		/* now point trackparam back to first track for later use */
		loop = g_list_first(trackreadset.trackparams);
		if (loop) trackparam = loop->data;
		else trackparam = NULL;
	}	

	/* pure data-cd */
	if (data == 1 && audio == 0) {
		type = 0;
	} else
	/* pure audio-cd */
	if (data == 0 && audio > 0) {
		type = 1;
	} else
	/* mixed-mode */
	if (mode == 0 && data == 1 && audio > 0 && trackinfo[0]->type == 0) {
		type = 2;
	} else
	if (mode == 1 && data == 1 && audio > 0 && trackparam->tracktype == 0) {
		type = 2;
	} else
	/* cd-extra */
	if (mode == 0 && data == 1 && audio > 0 && cdinfo.have_cdextra) {
		type = 3;
	} else
	if (mode == 1 && data == 1 && audio > 0 && trackparam->tracktype == 1) {
		/* one data, at least one audio and first track audio */
		type = 3;
	} else 
	/* multisession */
	if (data > 1 && audio == 0) {
		type = 4;
	} 

	/* enough for now */
	switch (type) {
	case 0:
		if ((mode == 0 && cdinfo.total_size < 450000) ||
		    (mode == 1 && trackreadset.cdsize < 450000)) {
			strncpy(tmp,_("Data-CD"),MAXLINE);
		} else {
			strncpy(tmp,_("Data-DVD"),MAXLINE);
		}
		break;
	case 1:
		strncpy(tmp,_("Audio-CD"),MAXLINE);
		break;
	case 2:
		strncpy(tmp,_("Mixed-Mode-CD"),MAXLINE);
		break;
	case 3:
		strncpy(tmp,_("CD-Extra"),MAXLINE);
		break;
	case 4:
		strncpy(tmp,_("Multisession-CD"),MAXLINE);
		break;
	default:
		strncpy(tmp,_("Unknown"),MAXLINE);
		break;
	}

	/* return value */
	strncpy(ret,tmp,MAXLINE);
	return (type);
}


/* calculate free space dependent of current image-dir setting */
/* return free kbytes and kbytes free in biggest imagedir */

gint determine_free_space(gint *biggestfree) {
gchar tmp[MAXLINE];
gchar path[MAXLINE];
GList *loop;
gint free, getfree;
gint maxfree;

	/* get image-path */
	if (curset.image_index == -1) {
		strncpy(path,"",MAXLINE);
	} else {
		strncpy(path,(gchar *)g_list_nth_data(setupdata.image_dirs,
			curset.image_index), MAXLINE);

		/* this dir writeable? */
		if (is_dir_writeable(path) == 1) {
			/* its not */
			*biggestfree = 0;
			return 0;
		}
	}

	free = 0;
	maxfree = 0;
	if (strcmp(path,"") != 0) {
		free = get_free_space(path,NULL);
		maxfree = free;
	} else {
		/* automatic setting - add all available space */
		loop = g_list_first(setupdata.image_dirs);
		while(loop) {
			strncpy(tmp,(gchar *)loop->data,MAXLINE);

			/* this dir writeable? */
			if (is_dir_writeable(tmp) == 1) {
				/* no? skip */
				loop = loop->next;
				continue;
			}

			getfree = get_free_space(tmp,NULL);
			free += getfree;
			/* get biggest block */
			if (getfree > maxfree) 
				maxfree = getfree;
			loop = loop->next;
		}
	}

	if (free < 0) {
		g_warning("Invalid image-path setting?\n");
		free = 0;
		maxfree = 0;
	}

	*biggestfree = maxfree;
	return free;
}


/* does look where to save the tracks before reading them. 
   Checks available diskspace and the image-directory-settings.
   return 0 if ok, 1 on error/disk full, 2 if no writeable dir found */
/* return 3 if we are about to overwrite a link */
/* return via call by reference the size (in kbytes) that will be
   free due overwriting old files. Also return the freed size on
   the directory with the most space available */

gint allocate_track_filenames(gint *overwrite, gint *overwritebiggest) {
gchar tmp[MAXLINE];
gchar biggestpath[MAXLINE];
gchar path[MAXLINE];
gchar ext[MAXLINE];
track_read_param_t *trackparam;
GList *loop, *loop2;
gint free;
gint size, tmpkbyte;
gint ret;
image_dir_free_t *freedir;
GList *freedirs;
struct stat buf;
gint overwritefree, overwritefreebiggest;
gint maxfree;

	dodebug(10,"calling allocate_track_filenames\n");

	overwritefree = 0;
	overwritefreebiggest = 0;
	ret = 0;
	freedirs = NULL;
	maxfree = 0;
	strcpy(biggestpath,"");

	/* build image-path/free structure */
	if (curset.image_index == -1) {
		/* automatic setting */
		loop = g_list_first(setupdata.image_dirs);
		while(loop) {
			strncpy(path,(gchar *)loop->data,MAXLINE);

			/* this dir writeable? */
			if (is_dir_writeable(path) == 1) {
				/* no? skip */
				loop = loop->next;
				continue;
			}
			free = get_free_space(path,NULL);
			freedir = g_new(image_dir_free_t,1);
			freedir->path = g_strdup(path);
			freedir->free = free;
			freedirs = g_list_append(freedirs,freedir);

			/* path with biggest available block? */
			if (free > maxfree) {
				maxfree = free;
				strncpy(biggestpath,path,MAXLINE);
			}	
			loop = loop->next;
		}
		/* no dirs writeable */
		if (freedirs == NULL) {
			*overwrite = 0;
			*overwritebiggest = 0;
			return 2;
		}
	} else {
		/* single path */
		strncpy(path,(gchar *)g_list_nth_data(setupdata.image_dirs,
			curset.image_index), MAXLINE);
		/* this dir writeable? */
		if (is_dir_writeable(path) == 1) {
			*overwrite = 0;
			*overwritebiggest = 0;
			return 2;
		}
		free = get_free_space(path,NULL);
		freedir = g_new(image_dir_free_t,1);
		freedir->path = g_strdup(path);
		freedir->free = free;
		freedirs = g_list_append(freedirs,freedir);
		maxfree = free;
		strncpy(biggestpath,path,MAXLINE);
	}
	/* now we have a structure with all path we are allowed to 
	   save data in and how much space is available there */

	/* loop through all available tracks */
	loop = g_list_first(trackreadset.trackparams);
	while (loop) {
		trackparam = loop->data;

		if (trackparam->tracktype == 0) 
			strcpy(ext,"iso");
		else
			strcpy(ext,"wav");
		
		/* how much space needs this track? */
		size = trackparam->kbyte;

		strcpy(path,"");

		/* where is enough space for it? */
		loop2 = g_list_first(freedirs);
		while (loop2) {
			freedir = loop2->data;
		
			/* build temporary filename */
			g_snprintf(tmp,MAXLINE, "%s/%s-%02d.%s", freedir->path, 
				curset.file_prefix,
				trackparam->starttrack, ext);

			/* already a file with this name on hd? */
			if (stat(tmp,&buf) == 0) {

				/* is a link? */
				if (check_islink(tmp, NULL)) {
					g_warning("Possibly overwriting a link at %s - not allowed.\n", tmp);
					return 3;
				}

				/* file exists */
				tmpkbyte = (gint) ((off_t)buf.st_size >> 10);
				if (tmpkbyte == 0) {
					/* file smaller than one kb? */
					/* assume 1 kb then */
					tmpkbyte = 1;
				}
				overwritefree += tmpkbyte;

				/* file in directory with most space? */
				if (strcmp(freedir->path,biggestpath) == 0) {
					overwritefreebiggest += tmpkbyte;
				} 
			} else {
				tmpkbyte = 0;
			}

			/* enough free? consider space that is freed
			   when we overwrite a file (tmpkbyte) */
			if (size < (freedir->free + tmpkbyte)) {
				/* found freespace */
				strncpy(path,freedir->path,MAXLINE);
				freedir->free-=size - tmpkbyte;
				break;
			}
 
			loop2 = loop2->next;
		}
	
		/* no free space found? */
		if (strcmp(path,"") == 0) {
			/* mark we found an error */
			ret = 1;
		}

		/* tmp does contain now our valid filename */
		g_free(trackparam->trackfile);
		trackparam->trackfile = g_strdup(tmp);

		loop = loop->next;
	}

	/* free image-path/free structure */
	loop2 = g_list_first(freedirs);
	while (loop2) {
		freedir = loop2->data;
		g_free(freedir->path);
		g_free(freedir);
		loop2 = loop2->next;
	}
	g_list_free(freedirs);

	*overwrite = overwritefree;
	*overwritebiggest = overwritefreebiggest;

	if (debug > 1) {
		print_trackreadset();
	}

	return ret;
}


/* does scan the image-structure for toc-files.
   Takes current image-dir-setting into account. Return number 
   of found toc files or 0. Newest file is on top */ 

gint scan_for_toc_files() {
GList *loop;
image_files_t *entry;
gchar basename[MAXLINE];
gchar ipath[MAXLINE];
gchar *p;
time_t fdate;

	/* clear old list */
	g_list_free(tocfiles);
	tocfiles = NULL;
	fdate = 0;

	loop = g_list_first(imagelist);
	while (loop) {
		entry = loop->data;

		/* toc-file */
		if (entry->type == 4) {
		
			/* get the basedir */
			strncpy(basename,entry->path,MAXLINE);
			p = rindex(basename,'/');
			*p = '\0';
			if (strcmp(basename,"") == 0) {
				strcpy(basename,"/");
			}
		
			/* now check if the basedir fits in the currently
			   set image-path */
			if (curset.image_index != -1) {
				strncpy(ipath, (gchar *)g_list_nth_data(
					setupdata.image_dirs,
					curset.image_index), MAXLINE);

				/* does not fit - skip */
				if (strcmp(ipath, basename) != 0) {
					loop = loop->next;
					continue;
				}
			}
			
			/* if new file newer than the old one */
			if (entry->mtime < fdate) {
				/* append at back */
				tocfiles = g_list_append(tocfiles,entry->path);
			} else {
				/* prepend at front */
				tocfiles = g_list_prepend(tocfiles,entry->path);
				fdate = entry->mtime;
			}
		}

		loop = loop->next;
	}

	return g_list_length(tocfiles);
}


/* this function is called whenever a dialog window idles on the screen
   and we want that events are processed and if there are no events
   no CPU-time is wasted */

void wait_and_process_events() {

	while (gtk_events_pending())
		gtk_main_iteration();
	usleep(100);
}


/* check if all files scheduled for writing does exist and have
   the right size. Return 0 if all ok, 1 if all files there but with
   wrong size, 2 if files missing and 3 if no permission to read/invalid,
   4 when audio files with wrong isrc or mcn found */ 

gint check_write_files(gint nosizecheck) {
GList *loop;
track_read_param_t *trackparam;
struct stat buf;
off_t size;
gint sumframes;
gint fd;
gint errsize, diff, invalidisrcmcn;

	sumframes = 0;
	errsize = 0;
	invalidisrcmcn = 0;
	loop = g_list_first(trackreadset.trackparams);
	while(loop) {
		trackparam = loop->data;

		if (stat(trackparam->trackfile, &buf) != 0) {
			/* no such file */
			return 2;
		}
		
		/* check if regular file or link */
		if (S_ISLNK(buf.st_mode) != 1 && S_ISREG(buf.st_mode) != 1) {
			/* its not */
			return 3;
		}

		/* readable for us? */
		fd = open(trackparam->trackfile, O_RDONLY,0);
		if (fd == -1) {
			return 3;
		} else {
			close(fd);
		}

		if (trackparam->tracktype == 0) {
			/* datatrack */
			size = (off_t) ((off_t)trackparam->frames * DATASECTORSIZE);
			sumframes += trackparam->frames;
		} else {
			/* audiotrack */

			/* check if ISRC/MCN info is valid */
			invalidisrcmcn += check_valid_isrc_mcn(trackparam->trackfile);

			size = (off_t) ((off_t)trackparam->frames * CDDAFRAME);
			sumframes += trackparam->frames;
		}

		/* check size of file - allow a offset of 4096 bytes */
		/* and offset of 152*2048 (leadout+runout sectors) */
		/* (and allow offset of 44 bytes (wavheader)) */
		diff = (gint) abs((off_t) size - (off_t) buf.st_size);
		if (diff != 0 && diff != 4096 && diff != 152*2048 && diff != 44) {
			/* a file with wrong size found? */
			errsize++;
		} 
		loop = loop->next;
	}	
	/* g_print("sumframes: %d\n", sumframes); */

	if (invalidisrcmcn > 0) {
		return 4;
	}

	if (errsize == 0 || nosizecheck) {
		/* all ok */
		return 0;
	} else {
		/* files with wrong sizes */
		return 1;
	}
}


/* correct any problem in an .inf file with an invalid ISRC or MCN number.
   Return 1 if there was a problem. (like permission denied) */

gint clear_isrc_mcn_from_tracks() {
GList *loop;
track_read_param_t *trackparam;
gint stat;

	stat = 0;
	loop = g_list_first(trackreadset.trackparams);
	while(loop) {
		trackparam = loop->data;

		if (check_valid_isrc_mcn(trackparam->trackfile)) {
			/* ok, thats one of the bad files */
			stat += clear_isrc_mcn_from_inffile(trackparam->trackfile);
		}

		loop = loop->next;
	}

	if (stat > 0) {
		return 1;
	} else {
		return 0;
	}
}


/* get the size of a track given by filename from imagelist (in bytes) */ 
/* or -1 when not found */

off_t get_size_from_imagelist(gchar *tname) {
GList *loop;
image_files_t *entry;

	loop = g_list_first(imagelist);
	while (loop) {
		entry = loop->data;

		if (strcmp(tname,entry->path) == 0) {
			return ((off_t) entry->size);
		}
		loop = loop->next;
	}

	return (off_t)-1;
}


/* get the type of a track given by filename from imagelist */ 
/* or -1 when not found */

gint get_type_from_imagelist(gchar *tname) {
GList *loop;
image_files_t *entry;

	loop = g_list_first(imagelist);
	while (loop) {
		entry = loop->data;

		if (strcmp(tname,entry->path) == 0) {
			return (entry->type);
		}
		loop = loop->next;
	}

	return -1;
}


/* get the number of a track given by filename from imagelist */ 
/* or -1 when not found */

gint get_tracknr_from_imagelist(gchar *tname) {
GList *loop;
image_files_t *entry;

	loop = g_list_first(imagelist);
	while (loop) {
		entry = loop->data;

		if (strcmp(tname,entry->path) == 0) {
			return (entry->from_track);
		}
		loop = loop->next;
	}

	return -1;
}


/* get the msinfo values from imagelist */

void get_msinfo_from_imagelist(gchar *tname, gint *nr1, gint *nr2) {
GList *loop;
image_files_t *entry;

	loop = g_list_first(imagelist);
	while (loop) {
		entry = loop->data;

		if (strcmp(tname,entry->path) == 0) {

			*nr1 = entry->last_session_start;
			*nr2 = entry->next_session_start;
		}
		loop = loop->next;
	}
}


image_files_t *get_entry_from_imagelist(gchar *tname) {
GList *loop;
image_files_t *entry;

	loop = g_list_first(imagelist);
	while (loop) {
		entry = loop->data;

		if (tname && strcmp(tname,entry->path) == 0) {
			return entry;
		}
		loop = loop->next;
	}
	return NULL;
}


/* get the discid of a track given by filename from imagelist */ 
/* or 1 when not found */

gint get_discid_from_imagelist(gchar *tname, gchar *ret) {
GList *loop;
image_files_t *entry;

	loop = g_list_first(imagelist);
	while (loop) {
		entry = loop->data;

		if (strcmp(tname,entry->path) == 0) {

			if (entry->cd_discid == NULL) 
				return 1;

			strcpy(ret, entry->cd_discid);
			return 0;
		}
		loop = loop->next;
	}

	return 1;
}


/* get the volname of a track given by filename from imagelist */ 
/* or 1 when not found */

gint get_volname_from_imagelist(gchar *tname, gchar *ret) {
GList *loop;
image_files_t *entry;

	loop = g_list_first(imagelist);
	while (loop) {
		entry = loop->data;

		if (strcmp(tname,entry->path) == 0) {

			if (entry->volname == NULL) 
				return 1;

			strcpy(ret, entry->volname);
			return 0;
		}
		loop = loop->next;
	}

	return 1;
}


/* is valid wav-file and in cd-quality? */
/* return 1 if, 0 if not */

gint check_wav_file(gchar *wavname) {
guchar waveHdr[44];
gint fd;

	fd = open (wavname, O_RDONLY, 0);
	if (fd == -1) {
		return 0;
	}

	read(fd, &waveHdr, sizeof(waveHdr));

	if (!is_std_wav_file(waveHdr)) {
		/* no wav at all */
		close(fd);
		return 0;
	}

	/* is it in cd-quality? */
	if (!is_in_cd_quality(waveHdr)) {
		close(fd);
		return 0;
	}

	/* passed all tests */
	close(fd);
	return 1;
}


/* small thing for iso-check */

static gint empty(gchar c) {
	return (c == 0 || c == ' ');
}


/* check if valid iso9660-image */
/* return number of sectors if, 0 if not */
/* if isoname set to NULL then query drive directly */

gint check_iso_file(gint devnr, gchar *isoname, gchar *volid, gint startsec) {
gchar buf[DATASECTORSIZE];
gchar tmp[MAXLINE];
gchar c;
gint i,j,k,count;
gint volsize;
 
	if (isoname != NULL) {
		/* read from file */
		if (read_info_sector_from_file(isoname,buf,sizeof(buf)) == 0) {
			return 0;
		}
	} else {
		/* read from device */
		if (read_info_sector_from_dev(devnr,buf,sizeof(buf), startsec) == 0) {
			return 0;
		}
	}

	/* search iso9660-signature */
	if (strncmp(buf, "\001CD001\001", 8) != 0) {
		return 0;
	}

	/* ok, we got an iso9660-image. 
	   As a bonus extract volumne-name if requested */
	if (volid != NULL) {
		count = 0;
		for(i = 40; i < 72; i++) {
			if (empty(buf[i]))
				continue;
			for (j = i+1; j < 72; j++) {
				if (!buf[j] || (j < 72-1
				&& empty(buf[j]) && empty(buf[j+1])))
					break;
			}
			for (k = i; k < j; k++) {
				c = buf[k];
				if (isprint((gint)c) || isspace((gint)c)) {
					tmp[count++] = c;			
				}
			}
			i = j;
		}
		tmp[count] = '\0';
		strcpy(volid,tmp);
	}

	/* now also extract the size of the image */
	volsize = ((buf[80] & 0xff) |
 		  ((buf[81] & 0xff) << 8) |
 		  ((buf[82] & 0xff) << 16) |
 		  ((buf[83] & 0xff) << 24)); 
		   
	return volsize;
}


/* get cd toc and do read the iso9660-volid if possible */

void get_cd_toc_and_volid(gint devnr) {
gint i, volsize;
gchar tmp[MAXLINE];
GtkWidget *tmpdialog;

	/* create dialog, just to grab the focus on it and make
	   xcdroast not longer "clickable" */
	tmpdialog = my_gtk_dialog_new();
        gtk_grab_add(tmpdialog);

	get_cd_toc(devnr);

	gtk_grab_remove(GTK_WIDGET(tmpdialog));
	gtk_widget_destroy(tmpdialog);
	
	/* no cd loaded? */
	if (cdinfo.nr_tracks <= 0) {
		return;
	}
	strcpy(tmp,"");

	/* scan every data track */
#ifdef SCANEVERYTRACK 
	for (i = 0; i < cdinfo.nr_tracks; i++) {
#else
	for (i = 0; i < 1; i++) {
#endif
	
		if (trackinfo[i]->type == 0) {
			/* get iso-header for current track */
			strcpy(tmp,"");
			volsize = check_iso_file(devnr, NULL, tmp, 
				trackinfo[i]->start_sec); 	
			if (strcmp(tmp,"") != 0) {
				g_free(trackinfo[i]->volname);
				trackinfo[i]->volname = g_strdup(tmp);
			}
			trackinfo[i]->isosize = volsize;
		}
	}

	/* now set disk-title to iso9660-volname because thats all we
	   got at the moment */

	/* last label still in buffer? */
	if (strcmp(tmp,"") != 0) {
		/* now check we have currently another title */
		if (cdinfo.cddb_dtitle == NULL) { 
			/* no? then use iso-header as title */
			cdinfo.cddb_dtitle = g_strdup(tmp);
		}
	}	
}


/* do output debug messages */

void dodebug(gint debuglevel, gchar *fmt, ...) {
va_list ap;
gchar tmp[MAXLINE*21];
gchar *p;
guint i;

	/* output message when debuglevel is high enough */
	if (debuglevel <= debug) {

		/* put together the variable argument list */
		va_start(ap,fmt);
		vsprintf(tmp, fmt, ap);
		va_end(ap);
	
                /* remove first linefeed if any */
		p = index(tmp,'\r');
		if (p != NULL) 
                        *p = ' ';

		/* remove \b if any */
		for (i = 0; i < strlen(tmp); i++) {
			if (tmp[i] == '\b') {
				tmp[i] = ' ';
			}
		}

		fprintf(stderr,"DGB%d: %s",debuglevel,tmp);
	}
}


/* do write to logfile */

void dolog(gint loglevel, gchar *fmt, ...) {
va_list ap;
gchar tmp[MAXLINE*21];	/* two buffers up to 10k plus saveguard */
gchar tmp2[MAXLINE];
char timestr[MAXLINE];
time_t acttime;
FILE *lfile;

	/* output message when loglevel is high enough */
	if (loglevel <= setupdata.loglevel && strcmp(setupdata.logfile,"")) {

		/* put together the variable argument list */
		va_start(ap,fmt);
		vsprintf(tmp, fmt, ap);
		va_end(ap);
		
		acttime = time((time_t *) 0);
		strncpy(timestr,ctime(&acttime),MAXLINE);

		/* remove last \n from timestr */
		timestr[strlen(timestr)-1] = 0;

		strncpy(tmp2, setupdata.logfile,MAXLINE);
		check_tilde(tmp2);

		lfile = fopen(tmp2,"a");

		if (lfile == NULL) {
			g_warning("Can't open logfile %s for writing\n", 
				tmp2);
			return;
		}

		if (!fprintf(lfile,"%s XCDR %s: %s", timestr,
			XCDROAST_VERSION, tmp)) {
			g_warning("Error appending to logfile\n");
		}
		fclose(lfile);
	}
}


/* notify-beep function */
/* type: 1 = completed task, 2 = warnings */

void dobeep(gint type) {
gint doit;

	doit = 0;

	switch (setupdata.notify_at) {
	case 0: 
		/* we want no beep */
		return;

	case 1:
		/* always */
		doit = 1;
		break;
	case 2:
		/* on completion */
		if (type == 1) 
			doit = 1;
		break;
	case 3:
		/* warnings only */
		if (type == 2)
			doit = 1;
		break;
	default:
		return;
	}

	/* ok..we have to play a sound */
	if (doit == 1) {
		if (setupdata.notify_via == 0) {
			/* dspdevice */
			if (strcmp(setupdata.dsp_device,"") != 0) {
				test_dspdevice_play();	
			}
		} else {
			/* internal speaker */
			gdk_beep();
		}
	}
}


/* check if the image-dirs fit to our partitions */
/* return 0 if ok, 1 when there were errors (and we edited the list) */

gint verify_loaded_config2 () {
GList *loop, *loop2;
GList *fslist;
gchar dir[MAXLINE];
gchar fs[MAXLINE];
gint free;
gint fsuse;
gint dirsok;

	/* now check if all the loaded image-dir exists and are each on
	   a own partition */

	fslist = NULL;
	dirsok = 0;
	loop = g_list_first(setupdata.image_dirs);
	while (loop) {
		strncpy(dir,(gchar *)loop->data,MAXLINE);
		/* get filesystem for this dir */
		free = get_free_space(dir,fs);
		if (free == -1) {
			/* no such directory */
			/* mark to remove this entry from the list...*/
			g_free(loop->data); 
			loop->data = NULL;
			dirsok = 1;
		} else {
			/* check if this dir is already in use */
			/* if not, add to fs-list */
			fsuse = 0;
			loop2 = g_list_first(fslist);
			while (loop2) {
				if (strcmp(fs, (gchar *)loop2->data) == 0) {
					fsuse = 1;
				}
				loop2 = loop2->next;
			}	
			if (fsuse == 0) {
				/* not already used */
				fslist = g_list_append(fslist, g_strdup(fs));
			} else {
				/* remove this entry from list */
				g_free(loop->data); 
				loop->data = NULL;
				dirsok = 1;
			}
		}

		loop = loop->next;
	}

	/* free our temporary list */
	free_glist(&fslist);

	/* now really remove the marked dirs from list */
	loop = g_list_first(setupdata.image_dirs);
	while (loop) {
		loop2 = loop->next;
		if (loop->data == NULL) {
			setupdata.image_dirs = 
				g_list_remove_link(setupdata.image_dirs, loop);
		}
		loop = loop2;
	}

	return dirsok;
}


/* check if this track match the inserted cd (verify tracks) */
/* return 0 if all ok, 1 on some error, 2 if file does not match to cd
   and 3 if we dont want verify audio (checking for readable not necessary 
   because unreadable tracks are not displayed in verify menu */

gint check_vrfy_track(gchar *fname) {
gchar tmp[MAXLINE];

        /* get the discid */
        if (get_discid_from_imagelist(fname,tmp) != 0) {
                /* no discid found in info-file? */
                return 1;
        }

        /* compare with current cd */
        if (strcmp(tmp, cdinfo.cddb_discid) != 0) {
                return 2;
        }

	/* check if its an audio track and we want to verify them */
	if (curset.noaudioverify == 1 && 
		get_type_from_imagelist(fname) == 1) {
		return 3;
	}
        /* all ok */
        return 0;
}


/* build a trackname for image-lists */

void assign_trackname(gchar *titlestr, image_files_t *entry) {

                /* see if there is cd text for this track */
                if (entry->title && entry->artist &&
                    strcmp(entry->title,"") && strcmp(entry->artist,"")) {
                        g_snprintf(titlestr,MAXLINE,"%s / %s",
                                entry->title, entry->artist);
                } else
                if (entry->title && strcmp(entry->title,"")) {
                        strcpy(titlestr, entry->title);
                } else
                if (entry->cddb_ttitle && strcmp(entry->cddb_ttitle,"")) {
                        strcpy(titlestr, entry->cddb_ttitle);
                } else
                if (entry->volname && strcmp(entry->volname,"")) {
                        g_snprintf(titlestr,MAXLINE,"%s / ISO9660",
                                entry->volname);
                }
}


/* check if a filename is on the writelist */

gint is_on_writelist(gchar *file) {
GList *loop;
gchar *track;

        loop = g_list_first(writelist);
        while (loop) {
                track = loop->data;
		if (track && strcmp(track, file) == 0) {
			return 1;
		}
		loop = loop->next;
	}
	return 0;
}


/* free trackreadset */

void clear_trackreadset() {
GList *loop;
track_read_param_t *trackparam;

        loop = g_list_first(trackreadset.trackparams);
        while (loop) {
                trackparam = loop->data;
                g_free(trackparam->trackfile);
                g_free(trackparam);
                loop = loop->next;
        }
	if (trackreadset.trackparams)
        	g_list_free(trackreadset.trackparams);
        trackreadset.trackparams = NULL;
	g_free(trackreadset.tocfile);
	trackreadset.tocfile = g_strdup("");
	g_free(trackreadset.cdtitle);
	trackreadset.cdtitle = g_strdup("");
	g_free(trackreadset.cd_discid);
	trackreadset.cd_discid = g_strdup("");
        trackreadset.nrtracks = 0;
        trackreadset.cdsize = 0;
}


/* transform coordinates when bigfonts are used */

gint tbf(gint koord) {

        if (bigfonts == 1) {
                return (koord * XCDR_TOPLEVEL_X1)/XCDR_TOPLEVEL_X0;
        } else {
                return koord;
        }
}


/* sort a glist of strings */

void sort_glist(GList *filelist) {
GList *first, *last, *list1, *list2;
gchar *str1, *str2, *str3;

        first = g_list_first(filelist);
        last = g_list_last(filelist);
        for (list1 = first; list1 != last; list1 = list1->next) {
                for (list2 = last; list2 != list1; list2 = list2->prev) {
             
Results 1 - 1
Help - FTP Sites List - Software Dir.
Searching half a billion files worldwide
© 1997-2008 IT MARUHN