#include #include #include extern int errno; #include /* For access() */ #include #include #include "../include/Y2/Y.h" #include "../include/Y2/Ylib.h" #include "../include/disk.h" #include "../include/string.h" #include "../include/strexp.h" #include "guiutils.h" #include "cdialog.h" #include "yc.h" #include "config.h" yc_ymode_data_struct *YCYModeDataStructNew(void); void YCYModeDataStructFree(yc_ymode_data_struct *ymode_data_ptr); void YCYModeFetchFromWidgets(yc_struct *yc, yc_ymode_data_struct *buf); void YCYModeSetToWidgets(yc_struct *yc, yc_ymode_data_struct *buf); void YCConfermListRefresh(yc_struct *yc); gint YCCheckInstallation( yc_struct *yc, const gchar *configuration_file, const gchar *yiff_program, gboolean report_problems ); #define MAX(a,b) (((a) > (b)) ? (a) : (b)) #define MIN(a,b) (((a) < (b)) ? (a) : (b)) #define CLIP(a,l,h) (MIN(MAX((a),(l)),(h))) /* * Returns a newly allocated yc_ymode_data_struct structure * with all its values set to 0. */ yc_ymode_data_struct *YCYModeDataStructNew(void) { return( (yc_ymode_data_struct *)calloc( 1, sizeof(yc_ymode_data_struct) ) ); } /* * Deallocates the given yc_ymode_data_struct and all * of it's substructures. */ void YCYModeDataStructFree(yc_ymode_data_struct *ymode_data_ptr) { if(ymode_data_ptr == NULL) return; free(ymode_data_ptr->name); free(ymode_data_ptr); return; } /* * Fetches Y audio mode values from the widgets on the yc's * YModes page and sets them to the given yc_ymode_data_struct * structure. */ void YCYModeFetchFromWidgets(yc_struct *yc, yc_ymode_data_struct *buf) { GtkWidget *w; GtkEntry *entry; gchar *strptr; if((yc == NULL) || (buf == NULL)) return; /* Sample rate */ w = yc->ymode_sample_rate_combo; if(w != NULL) { entry = (GtkEntry *)GTK_COMBO(w)->entry; if(entry != NULL) { /* Get sample rate in Hz */ strptr = gtk_entry_get_text(entry); if(strptr != NULL) buf->sample_rate = MAX( atoi(strptr), YC_MIN_SAMPLE_RATE ); } } /* Fragment size in bytes */ w = yc->ymode_fragment_size_combo; if(w != NULL) { entry = (GtkEntry *)GTK_COMBO(w)->entry; if(entry != NULL) { /* Get fragment buffer size in bytes */ strptr = gtk_entry_get_text(entry); if(strptr != NULL) buf->fragment_size_bytes = MAX( atoi(strptr), YC_MIN_FRAGMENT_SIZE ); } } /* Channels */ w = yc->ymode_channels1_radio; if(w != NULL) { if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))) buf->channels = 1; } w = yc->ymode_channels2_radio; if(w != NULL) { if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))) buf->channels = 2; } /* Sample size */ w = yc->ymode_sample_size8_radio; if(w != NULL) { if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))) buf->sample_size = 8; } w = yc->ymode_sample_size16_radio; if(w != NULL) { if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))) buf->sample_size = 16; } /* Cycle */ w = yc->ymode_cycle_spin; if(w != NULL) { /* Get cycle in microseconds */ buf->cycle_us = MAX( gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w)), 100 ); } /* Calculate cycle ahead as 1.5 times the cycle */ buf->write_ahead_us = 1.5 * buf->cycle_us; /* Leave direction (play/record) alone */ /* yc->direction; */ /* Leave fragmenting alone */ /* yc->allow_fragmenting = TRUE; */ /* Set default number of fragments to 2 (one for current and * another for next. */ /* Leave number of fragments alone. yc->num_fragments = 2; */ return; } /* * Sets Y audio mode values to the widgets on the yc's YModes * page based on the given yc_ymode_data_struct structure. */ void YCYModeSetToWidgets(yc_struct *yc, yc_ymode_data_struct *buf) { GtkWidget *w; GtkEntry *entry; gchar num_str[80]; if((yc == NULL) || (buf == NULL)) return; /* Sample rate */ w = yc->ymode_sample_rate_combo; if(w != NULL) { entry = (GtkEntry *)GTK_COMBO(w)->entry; if(entry != NULL) { sprintf(num_str, "%i", buf->sample_rate); gtk_entry_set_text(entry, num_str); } } /* Fragment size in bytes */ w = yc->ymode_fragment_size_combo; if(w != NULL) { entry = (GtkEntry *)GTK_COMBO(w)->entry; if(entry != NULL) { sprintf(num_str, "%i", buf->fragment_size_bytes); gtk_entry_set_text(entry, num_str); } } /* Channels */ switch(buf->channels) { case 2: w = yc->ymode_channels1_radio; if(w != NULL) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), FALSE); w = yc->ymode_channels2_radio; if(w != NULL) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), TRUE); break; default: w = yc->ymode_channels1_radio; if(w != NULL) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), TRUE); w = yc->ymode_channels2_radio; if(w != NULL) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), FALSE); break; } /* Sample size */ switch(buf->sample_size) { case 16: w = yc->ymode_sample_size8_radio; if(w != NULL) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), FALSE); w = yc->ymode_sample_size16_radio; if(w != NULL) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), TRUE); break; default: w = yc->ymode_sample_size8_radio; if(w != NULL) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), TRUE); w = yc->ymode_sample_size16_radio; if(w != NULL) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), FALSE); break; } /* Cycle */ w = yc->ymode_cycle_spin; if(w != NULL) gtk_spin_button_set_value( GTK_SPIN_BUTTON(w), MAX((gfloat)buf->cycle_us, 100) ); return; } /* * Updates the confermation items clist on the yc with respect * to the current values on the other widgets on the yc. */ void YCConfermListRefresh(yc_struct *yc) { GtkWidget *w; GtkCList *clist; gchar *text[1]; gchar *buf; const gchar *parm, *val; gint len_parm, len_val; gboolean show_cfgfmt_parms = FALSE; if(yc == NULL) return; clist = (GtkCList *)yc->conferm_items_clist; if(clist == NULL) return; w = yc->conferm_verbose_toggle; if(w != NULL) show_cfgfmt_parms = !GTK_TOGGLE_BUTTON(w)->active; gtk_clist_freeze(clist); gtk_clist_clear(clist); /* Adds entry widget w values to clist, based on parm and val */ #define DO_ADD_ITEM_FROM_ENTRY \ if(w != NULL) \ { \ val = (const gchar *)gtk_entry_get_text(GTK_ENTRY(w)); \ len_parm = ((parm == NULL) ? 0 : strlen(parm)); \ len_val = ((val == NULL) ? 0 : strlen(val)); \ buf = (gchar *)malloc((len_parm + len_val + 10) * sizeof(gchar)); \ if(buf != NULL) \ { \ sprintf(buf, "%s = %s", parm, val); \ text[0] = buf; \ gtk_clist_append(clist, text); \ free(buf); \ } \ } /* Adds entry widget w values to clist, based on parm and val */ #define DO_ADD_ITEM_FROM_SPIN \ if(w != NULL) \ { \ gint spin_val = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w)); \ gchar *sval = (gchar *)malloc(256 * sizeof(gchar)); \ if(sval != NULL) \ sprintf(sval, "%i", spin_val); \ len_parm = ((parm == NULL) ? 0 : strlen(parm)); \ len_val = ((sval == NULL) ? 0 : strlen(sval)); \ buf = (gchar *)malloc((len_parm + len_val + 10) * sizeof(gchar)); \ if(buf != NULL) \ { \ sprintf(buf, "%s = %s", parm, sval); \ text[0] = buf; \ gtk_clist_append(clist, text); \ free(buf); \ } \ free(sval); \ sval = NULL; \ } /* Configuration file path */ w = yc->yiff_configuration_file_entry; parm = ((show_cfgfmt_parms) ? "YIFFConfigurationFile" : "YIFF configuration file" ); DO_ADD_ITEM_FROM_ENTRY /* YIFF program path */ w = yc->yiff_program_entry; parm = ((show_cfgfmt_parms) ? "YIFFProgram" : "YIFF program" ); DO_ADD_ITEM_FROM_ENTRY /* DSP device */ w = yc->dsp_device_entry; parm = ((show_cfgfmt_parms) ? "DSPDevice" : "DSP device" ); DO_ADD_ITEM_FROM_ENTRY /* Mixer device */ w = yc->mixer_device_entry; parm = ((show_cfgfmt_parms) ? "MixerDevice" : "Mixer device" ); DO_ADD_ITEM_FROM_ENTRY /* Listening port number */ w = yc->port_entry; parm = ((show_cfgfmt_parms) ? "Port" : "Listening port number" ); DO_ADD_ITEM_FROM_ENTRY /* Leave out Y Audio Modes for now */ /* Refresh interval */ w = yc->sound_refresh_spin; parm = ((show_cfgfmt_parms) ? "RefreshInterval" : "Refresh interval (us)" ); DO_ADD_ITEM_FROM_SPIN /* MIDI play command */ w = yc->midi_play_cmd_entry; parm = ((show_cfgfmt_parms) ? "MIDIPlayCommand" : "MIDI player command" ); DO_ADD_ITEM_FROM_ENTRY /* ALSA MIDI device port number */ w = yc->alsa_midi_port_entry; parm = ((show_cfgfmt_parms) ? "MIDIDevicePort" : "ALSA MIDI device port number" ); DO_ADD_ITEM_FROM_ENTRY /* Leave out Y Sound Paths for now */ #undef DO_ADD_ITEM_FROM_ENTRY #undef DO_ADD_ITEM_FROM_SPIN gtk_clist_thaw(clist); return; } /* * Procedure to check a complete YIFF installation. * * If any given check inputs are NULL then the respective value * will be fetched from the yc structure widgets (if possible). * * If report_problems is TRUE then any errors encountered will * be reported. * * Returns zero on success and non-zero if any errors were * encountered. Error codes indicate severity of error and are * as follows. * * -1 Input value error. * -2 Missing or bad compoent (minor, may still be able to run). * -3 Missing or bad compoent (critical, cannot run at all). */ gint YCCheckInstallation( yc_struct *yc, const gchar *configuration_file, const gchar *yiff_program, gboolean report_problems ) { GtkWidget *w; const gchar *mesg_title, *mesg_body, *mesg_details; gboolean path_exists; struct stat stat_buf; if(yc == NULL) return(-1); /* ********************************************************** */ /* Get values as needed */ /* YIFF Sound Server configuration file */ if(configuration_file == NULL) { w = yc->yiff_configuration_file_entry; configuration_file = gtk_entry_get_text(GTK_ENTRY(w)); } /* YIFF Sound Server program file */ if(yiff_program == NULL) { w = yc->yiff_program_entry; yiff_program = gtk_entry_get_text(GTK_ENTRY(w)); } /* ********************************************************** */ /* Got values, but note they still may be NULL */ #define DO_NOTIFY_ERROR { \ CDialogSetTransientFor(yc->toplevel); \ CDialogGetResponse( \ mesg_title, mesg_body, mesg_details, \ CDIALOG_ICON_ERROR, \ CDIALOG_BTNFLAG_OK | \ ((mesg_details != NULL) ? CDIALOG_BTNFLAG_HELP : 0), \ CDIALOG_BTNFLAG_OK \ ); \ CDialogSetTransientFor(NULL); \ } #define DO_NOTIFY_WARNING { \ CDialogSetTransientFor(yc->toplevel); \ CDialogGetResponse( \ mesg_title, mesg_body, mesg_details, \ CDIALOG_ICON_WARNING, \ CDIALOG_BTNFLAG_OK | \ ((mesg_details != NULL) ? CDIALOG_BTNFLAG_HELP : 0), \ CDIALOG_BTNFLAG_OK \ ); \ CDialogSetTransientFor(NULL); \ } /* YIFF Sound Server configuration file */ if(configuration_file != NULL) { path_exists = FALSE; if(*configuration_file == '\0') { if(report_problems) { mesg_title = "Configuration File Not Set"; mesg_body = "The location for the YIFF Sound Server configuration file\n\ has not been set.\n"; mesg_details = NULL; DO_NOTIFY_WARNING } return(-2); } if(!ISPATHABSOLUTE(configuration_file)) { if(report_problems) { mesg_title = "Invalid Configuration File"; mesg_body = "The specified path of the YIFF Sound Server configuration\n\ file is not an absolute path.\n"; mesg_details = "The path to the configruation file needs to be an\n\ absolute path to ensure that the YIFF Sound Server\n\ can find it."; DO_NOTIFY_WARNING } return(-2); } if(stat(configuration_file, &stat_buf)) { switch(errno) { case ENOENT: /* Skip this, if no configuration file is found then * user will be prompted to create a new one */ break; case EACCES: if(report_problems) { mesg_title = "Configuration File Not Accessable"; mesg_body = "The specified location of the YIFF Sound Server configuration\n\ file is not accessable, permission was denied when checking\n\ for its existance.\n"; mesg_details = "You may need to run \"chmod\" from a prompt and change\n\ the permissions on the parent directory or run this\n\ program with a higher permission level (using \"su\")."; DO_NOTIFY_WARNING } return(-3); break; default: if(report_problems) { mesg_title = "Configuration File Warning"; mesg_body = "Error encountered when checking for existance\n\ of the YIFF Sound Server configuration file.\n"; mesg_details = NULL; DO_NOTIFY_WARNING } return(-3); break; } } else { /* Successfully stat() path, mark path_exists as TRUE */ path_exists = TRUE; } /* Is it a directory? */ if(path_exists && S_ISDIR(stat_buf.st_mode)) { if(report_problems) { mesg_title = "Invalid Configuration File"; mesg_body = "The specified path to the YIFF Sound Server configuration\n\ file refers to a directory.\n"; mesg_details = NULL; DO_NOTIFY_ERROR } return(-2); } /* Is it a regular file? */ if(path_exists && !S_ISREG(stat_buf.st_mode)) { if(report_problems) { mesg_title = "Invalid Configuration File"; mesg_body = "The specified path to the YIFF Sound Server configuration\n\ file was not a file.\n"; mesg_details = NULL; DO_NOTIFY_ERROR } return(-2); } /* Is it readable? */ if(path_exists && access(configuration_file, R_OK)) { if(report_problems) { mesg_title = "Configuration File Not Readable"; mesg_body = "Current permission settings on the YIFF Sound Server\n\ configuration file prevent it from being readable to\n\ this program. You may need to run this program with a\n\ higher permission level."; mesg_details = "You may need to run \"chmod\" from a prompt and change\n\ the permissions on the parent directory or run this\n\ program with a higher permission level (using \"su\")."; DO_NOTIFY_WARNING } /* Do not return */ } /* Is it writeable? */ if(path_exists && access(configuration_file, W_OK)) { if(report_problems) { mesg_title = "Configuration File Not Writeable"; mesg_body = "The current permission settings on the YIFF Sound Server\n\ configuration file prevent it from being writeable with\n\ this program. You may need to run this program with a\n\ higher permission (exit this program and run \"su\" to\n\ gain root privileges and then run this program again).\n"; mesg_details = NULL; DO_NOTIFY_WARNING } /* Do not return */ } } /* YIFF Sound Server configuration file */ /* YIFF program */ if(yiff_program != NULL) { path_exists = FALSE; if(*yiff_program == '\0') { if(report_problems) { mesg_title = "YIFF Program Not Set"; mesg_body = "The location of the YIFF Sound Server program has not\n\ been set.\n"; mesg_details = NULL; DO_NOTIFY_WARNING } return(-2); } if(!ISPATHABSOLUTE(yiff_program)) { if(report_problems) { mesg_title = "Invalid YIFF Program"; mesg_body = "The specified path of the YIFF Sound Server program was\n\ not an absolute path.\n"; mesg_details = NULL; DO_NOTIFY_WARNING } return(-2); } if(stat(yiff_program, &stat_buf)) { if(report_problems) { switch(errno) { case ENOENT: mesg_title = "YIFF Program Not Found"; mesg_body = "YIFF Sound Server program file not found."; mesg_details = NULL; break; case EACCES: mesg_title = "YIFF Program Not Accessable"; mesg_body = "The specified location of the YIFF Sound Server program\n\ was not accessable, permission was denied when checking\n\ for its existance.\n"; mesg_details = "You may need to run \"chmod\" from a prompt and change\n\ the permissions on the parent directory or run this\n\ program with a higher permission level (using \"su\").\n"; break; default: mesg_title = "YIFF Program Warning"; mesg_body = "Error encountered when checking for existance of the\n\ YIFF Sound Server program.\n"; mesg_details = NULL; break; } DO_NOTIFY_WARNING } return(-3); } else { /* Successfully stat() path, mark path_exists as TRUE */ path_exists = TRUE; } /* Is it a directory? */ if(path_exists && S_ISDIR(stat_buf.st_mode)) { if(report_problems) { mesg_title = "Invalid YIFF Program"; mesg_body = "The specified path to the YIFF Sound Server program refers\n\ to a directory.\n"; mesg_details = NULL; DO_NOTIFY_ERROR } return(-2); } /* Is it a regular file? */ if(path_exists && !S_ISREG(stat_buf.st_mode)) { if(report_problems) { mesg_title = "Invalid YIFF Program"; mesg_body = "The specified path to the YIFF Sound Server program was\n\ not a file.\n"; mesg_details = NULL; DO_NOTIFY_ERROR } return(-2); } /* Is it set uid or set gid? (not suppose to be) */ if(path_exists && ((stat_buf.st_mode & S_ISUID) || (stat_buf.st_mode & S_ISGID) ) ) { if(report_problems) { mesg_title = "YIFF Program Permissions Warning"; mesg_body = "The YIFF Sound Server program file has setuid and/or\n\ setgid permissions set, it does not need them and may pose a\n\ security risk. You are advised to remove the setuid\n\ and/or setgid from the permissions.\n"; mesg_details = NULL; DO_NOTIFY_WARNING } /* Do not return */ } /* Is it executeable? */ if(path_exists && access(yiff_program, X_OK)) { if(report_problems) { mesg_title = "YIFF Program Permissions Warning"; mesg_body = "The YIFF Sound Server program permissions do not allow\n\ it to be executeable.\n"; mesg_details = "You may need to run \"chmod\" from a prompt and change\n\ the permissions on the YIFF Sound Server program file\n\ to \"755\"."; DO_NOTIFY_WARNING } return(-3); } } /* YIFF program */ #undef DO_NOTIFY_ERROR #undef DO_NOTIFY_WARNING return(0); }