Logo Search packages:      
Sourcecode: yiff version File versions  Download package

ycutils.c

#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
extern int errno;
#include <unistd.h>           /* For access(). */
#include <sys/types.h>
#include <sys/stat.h>

#include <gtk/gtk.h>

#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);

int YCCheckInstallation(
      yc_struct *yc,
      const gchar *configuration_file,
      const gchar *yiff_program,
      gbool 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;
      gbool 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).
 */
int YCCheckInstallation(
      yc_struct *yc,
      const gchar *configuration_file,
      const gchar *yiff_program,
      gbool report_problems
)
{
      GtkWidget *w;
      const char  *mesg_title,
                  *mesg_body,
                  *mesg_details;
      gbool 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. */

/* Maps cdialog with the messages from mesg_title, mesg_body, and
 * mesg_details.
 */
#define DO_NOTIFY_ERROR \
{ \
 CDialogGetResponse( \
  mesg_title, mesg_body, mesg_details, \
  CDIALOG_ICON_ERROR, \
  CDIALOG_BTNFLAG_OK | ((mesg_details == NULL) ? 0 : CDIALOG_BTNFLAG_HELP), \
  CDIALOG_BTNFLAG_OK \
 ); \
}
#define DO_NOTIFY_WARNING     \
{ \
 CDialogGetResponse( \
  mesg_title, mesg_body, mesg_details, \
  CDIALOG_ICON_WARNING, \
  CDIALOG_BTNFLAG_OK | ((mesg_details == NULL) ? 0 : CDIALOG_BTNFLAG_HELP), \
  CDIALOG_BTNFLAG_OK \
 ); \
}

      /* YIFF Sound Server configuration file. */
      if(configuration_file != NULL)
      {
          path_exists = FALSE;
          if((*configuration_file) == '\0')
          {
            if(report_problems)
            {
                mesg_title =
"Configuration file value empty!";
                mesg_body =
"Specified location of the YIFF Sound Server configuration\n\
file is an empty string.";
                mesg_details = NULL;
                DO_NOTIFY_ERROR
            }
            return(-2);
          }
          if(!ISPATHABSOLUTE(configuration_file))
          {
            if(report_problems)
            {
                mesg_title =
"Configuration file not absolute path!";
                mesg_body =
"Specified path of the YIFF Sound Server configuration\n\
file is not an absolute path.";
                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_ERROR
            }
            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 =
"Specified location of the YIFF Sound Server configuration\n\
file is not accessable, permission was denied when checking\n\
for its existance.";
                  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_ERROR
                }
                return(-3);
                break;

              default:
                if(report_problems)
                {
                    mesg_title =
"Configuration file check error!";
                  mesg_body =
"Error encountered when checking for existance\n\
of the YIFF Sound Server configuration file.";
                  mesg_details = NULL;
                  DO_NOTIFY_ERROR
                }
                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 =
"Configuration file cannot be a directory!";
                mesg_body =
"Specified path to the YIFF Sound Server configuration\n\
file reffers to a directory.";
                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 =
"Configuration file is not a file!";
                mesg_body =
"Specified path to the YIFF Sound Server configuration\n\
file is not a regular file.";
                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 is 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_ERROR
            }
            /* Do not return. */
          }
          /* Is it writeable? */
          if(path_exists && access(configuration_file, W_OK))
          {
            if(report_problems)
            {
                mesg_title =
"Configuration file is not writeable!";
                mesg_body =
"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 level (exit this program and use 'su'\n\
to gain root privlages and then run this program).";
                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_ERROR
            }
            /* 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 file value empty!";
                mesg_body =
"Specified location of the YIFF Sound Server program\n\
file is an empty string.";
                mesg_details = NULL;
                DO_NOTIFY_ERROR
            }
            return(-2);
          }
          if(!ISPATHABSOLUTE(yiff_program))
          {
            if(report_problems)
            {
                mesg_title =
"Program file not absolute path!";
                mesg_body =
"Specified path of the YIFF Sound Server program\n\
file is not an absolute path.";
                mesg_details = NULL;
                DO_NOTIFY_ERROR
            }
            return(-2);
          }
          if(stat(yiff_program, &stat_buf))
          {
            if(report_problems)
            {
                switch(errno)
                {
                  case ENOENT:
                  mesg_title =
"Program file not found!";
                  mesg_body =
"YIFF Sound Server program file not found.";
                  mesg_details = NULL;
                  break;

                  case EACCES:
                  mesg_title =
"Program file not accessable!";
                  mesg_body =
"Specified location of the YIFF Sound Server program\n\
file is not accessable, permission was denied when checking\n\
for its existance.";
                  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\").";
                  break;

                  default:
                  mesg_title =
"Program file check error!";
                  mesg_body =
"Error encountered when checking for existance\n\
of the YIFF Sound Server program file.";
                  mesg_details = NULL;
                  break;
                }
                DO_NOTIFY_ERROR
            }
            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 =
"Program file cannot be a directory!";
                mesg_body =
"Specified path to the YIFF Sound Server program\n\
file reffers to a directory.";
                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 =
"Program file is not a file!";
                mesg_body =
"Specified path to the YIFF Sound Server program\n\
file is not a regular file.";
                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 =
"Program file is set setuid!";
                mesg_body =
"YIFF Sound Server program file has the setuid and/or\n\
setgid bit set, it does not need it and may pose a\n\
security risk. You are advised to remove the setuid\n\
and/or setgid bits from the program file's permissions.";
                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 =
"Program file not executeable!";
                mesg_body =
"YIFF Sound Server program file permissions do not\n\
allow it to be executeable.";
                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_ERROR
            }
            return(-3);
          }
      }     /* YIFF program. */




#undef DO_NOTIFY_ERROR
#undef DO_NOTIFY_WARNING

      return(0);
}

Generated by  Doxygen 1.6.0   Back to index