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) {