⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smurfcfg.c

📁 A GTK sound font editor. Sound font files are used to synthesize instruments from audio samples for
💻 C
字号:
/*================================================================== * smurfcfg.c - Smurf preference config loading routines * * Based on gtkrc.c in the GTK source "GTK - The GIMP Toolkit" * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * Smurf Sound Font Editor * Copyright (C) 1999-2001 Josh Green * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA or point your web browser to http://www.gnu.org. * * To contact the author of this program: * Email: Josh Green <jgreen@users.sourceforge.net> * Smurf homepage: http://smurf.sourceforge.net *==================================================================*/#include "config.h"#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <string.h>#include <glib.h>#include "smurfcfg.h"#include "util.h"#include "i18n.h"/* global data */gboolean smurfcfg_error;static const GScannerConfig smurfcfg_scanner_config = {  " \t\n",			/* cset_skip_characters */  G_CSET_a_2_z "_" G_CSET_A_2_Z,	/* cset_identifier_first */  G_CSET_a_2_z "_-0123456789" G_CSET_A_2_Z,	/* cset_identifier_nth */  "#\n",			/* cpair_comment_single */  FALSE,			/* case_sensitive */  TRUE,				/* skip_comment_multi */  TRUE,				/* skip_comment_single */  TRUE,				/* scan_comment_multi */  TRUE,				/* scan_identifier */  FALSE,			/* scan_identifier_1char */  FALSE,			/* scan_identifier_NULL */  TRUE,				/* scan_symbols */  TRUE,				/* scan_binary */  TRUE,				/* scan_octal */  TRUE,				/* scan_float */  TRUE,				/* scan_hex */  TRUE,				/* scan_hex_dollar */  TRUE,				/* scan_string_sq */  TRUE,				/* scan_string_dq */  TRUE,				/* numbers_2_int */  FALSE,			/* int_2_float */  FALSE,			/* identifier_2_string */  TRUE,				/* char_2_token */  TRUE,				/* symbol_2_token */  FALSE,			/* scope_0_fallback */};static struct{  gchar *name;			/* the variable name */  guint type;			/* the variable type (GTokenType) */  GTokenValue def;		/* default value of variable */  GTokenValue val;		/* the current variable value */} symbols[] = {/* VERSION is saved to both config files */    {"version",		G_TOKEN_STRING,     {VERSION}, {NULL} },/* state information (saved into a seperate file on exit, smurf_state.cfg) */    {"win_xpos",	G_TOKEN_INT, {GINT_TO_POINTER (0)}, {NULL} },    {"win_ypos",	G_TOKEN_INT, {GINT_TO_POINTER (0)}, {NULL} },    {"win_width",	G_TOKEN_INT, {GINT_TO_POINTER (620)}, {NULL} },    {"win_height",	G_TOKEN_INT, {GINT_TO_POINTER (440)}, {NULL} },    {"treewin_width",	G_TOKEN_INT, {GINT_TO_POINTER (0)}, {NULL} },    {"treewin_height",	G_TOKEN_INT, {GINT_TO_POINTER (0)}, {NULL} },    {"tips_position",	G_TOKEN_INT, {GINT_TO_POINTER (0)}, {NULL} },/* dummy value for SMURFCFG_STATE_LAST separator */    {"dummy", G_TOKEN_NONE, {NULL}, {NULL} },/* Smurf preferences (requires manual saving by user, saved to smurf.cfg) *//* paths */    {"def_sfont_path",	G_TOKEN_STRING, {""}, {NULL} },    {"def_sample_path", G_TOKEN_STRING, {""}, {NULL} },    {"vbnk_search_path",G_TOKEN_STRING, {""}, {NULL} },    {"quit_confirm",	G_TOKEN_INT,     {GINT_TO_POINTER (SMURFCFG_QUIT_CONFIRM_ALWAYS)}, {NULL} },    {"disable_splash",  G_TOKEN_INT, {GINT_TO_POINTER (FALSE)}, {NULL} },/* Smurfy tips */    {"tips_enabled",	G_TOKEN_INT, {GINT_TO_POINTER (TRUE)}, {NULL} },/* window geometry preferences */    {"save_win_geom",	G_TOKEN_INT, {GINT_TO_POINTER (TRUE)}, {NULL} },    {"set_win_pos",	G_TOKEN_INT, {GINT_TO_POINTER (FALSE)}, {NULL} },    {"set_pane_size",	G_TOKEN_INT, {GINT_TO_POINTER (FALSE)}, {NULL} },/* sound font preferences */    {"temp_audible_bank", G_TOKEN_INT, {GINT_TO_POINTER (127)}, {NULL} },    {"temp_audible_preset", G_TOKEN_INT, {GINT_TO_POINTER (127)}, {NULL} },    /* defaults to "AUTO" mode */    {"wavetbl_sam_caching", G_TOKEN_INT, {GINT_TO_POINTER (2)}, {NULL} },    {"sam_sfspec",	G_TOKEN_INT, {GINT_TO_POINTER (TRUE)}, {NULL} },    {"sam_minloop",	G_TOKEN_INT, {GINT_TO_POINTER (32)}, {NULL} },    {"sam_minlooppad",	G_TOKEN_INT, {GINT_TO_POINTER (8)}, {NULL} },    {"sam_buf_waste",	G_TOKEN_INT, {GINT_TO_POINTER (4)}, {NULL} },    {"sam_ch1_postfix",	G_TOKEN_STRING, {"_L"}, {NULL} },    {"sam_ch2_postfix",	G_TOKEN_STRING, {"_R"}, {NULL} },/* drivers */    {"wavetbl_driver",	G_TOKEN_STRING, {"AUTO"}, {NULL} },    {"wavetbl_ossdev",	G_TOKEN_STRING, {"/dev/sequencer"}, {NULL} },    {"seq_driver",    G_TOKEN_STRING, {"AUTO"}, {NULL} },    {"seq_alsaclient",G_TOKEN_INT, {GINT_TO_POINTER (0)}, {NULL} },    {"seq_alsaport",  G_TOKEN_INT, {GINT_TO_POINTER (0)}, {NULL} },    {"midi_driver",	G_TOKEN_STRING, {"AUTO"}, {NULL} },    {"midi_alsa_inclient", G_TOKEN_INT, {GINT_TO_POINTER (0)}, {NULL} },    {"midi_alsa_inport",   G_TOKEN_INT, {GINT_TO_POINTER (0)}, {NULL} },    {"midi_alsa_outclient", G_TOKEN_INT, {GINT_TO_POINTER (0)}, {NULL} },    {"midi_alsa_outport",   G_TOKEN_INT, {GINT_TO_POINTER (0)}, {NULL} },    {"midi_alsacard",	G_TOKEN_INT, {GINT_TO_POINTER (0)}, {NULL} },    {"midi_alsadevice",	G_TOKEN_INT, {GINT_TO_POINTER (0)}, {NULL} },/* color preferences */    {"velbar_scolor",	G_TOKEN_STRING, {"#000040"}, {NULL} },    {"velbar_ecolor",	G_TOKEN_STRING, {"#0000FF"}, {NULL} },/* piano keyboard to note mapping */    {"piano_lowoctkeys", G_TOKEN_STRING, {""}, {NULL} },    {"piano_hioctkeys", G_TOKEN_STRING, {""}, {NULL} },};static const guint n_symbols = sizeof (symbols) / sizeof (symbols[0]);gboolean smurfcfg_up2date;/* prototypes */static gint smurfcfg_load_vars (gchar *fname, gboolean reset_vars);static void smurfcfg_parse_err (GScanner * scanner, gchar * msg);static void smurfcfg_next_line (GScanner * scanner);static gint smurfcfg_save_vars (gchar *fname, gint first, gint last);static gchar *smurfcfg_type_string (guint token);/* functions */gintsmurfcfg_load (void)		/* load smurf.cfg file */{  return (smurfcfg_load_vars ("smurf.cfg", TRUE));}gintsmurfcfg_load_state (void)	/* load smurf_state.cfg file, no reset vars */{  return (smurfcfg_load_vars ("smurf_state.cfg", FALSE));}/* load a smurf configuration file into variables */static gintsmurfcfg_load_vars (gchar *fname, gboolean reset_vars){  gint fh;  GScanner *scanner;  guint ndx, token;  guint i;  gchar *s;  if (reset_vars)    {				/* reset config variables to default values */      ndx = SMURFCFG_LAST - SMURFCFG_INVALID - 1;      for (i = 0; i < ndx; i++)	{	  if (symbols[i].type == G_TOKEN_STRING)	    symbols[i].val.v_string = g_strdup (symbols[i].def.v_string);	  else	    memcpy (&symbols[i].val, &symbols[i].def, sizeof (GTokenValue));	}    }  s = g_strconcat (g_get_home_dir (), "/.smurf/", fname, NULL);  if ((fh = open (s, O_RDONLY)) == -1)    {      g_free (s);      return (logit (LogWarn, _("Could not load ~/.smurf/%s"), fname));    }  g_free (s);  logit (LogInfo, _("Parsing ~/.smurf/%s.."), fname);  smurfcfg_error = FALSE;  scanner = g_scanner_new ((GScannerConfig *) & smurfcfg_scanner_config);  g_scanner_input_file (scanner, fh);  scanner->input_name = fname;  /* load symbols into scanner */  g_scanner_freeze_symbol_table (scanner);  for (i = 0; i < n_symbols; i++)    g_scanner_add_symbol (scanner, symbols[i].name,      GINT_TO_POINTER (i + SMURFCFG_INVALID + 1));  g_scanner_thaw_symbol_table (scanner);  /* loop over each "variable = value" */  while (g_scanner_peek_next_token (scanner) != G_TOKEN_EOF)    {      /* get variable token */      token = g_scanner_get_next_token (scanner);      if (token <= SMURFCFG_INVALID || token >= SMURFCFG_LAST)	{	  smurfcfg_parse_err (scanner, _("Invalid config variable name"));	  smurfcfg_next_line (scanner);	  continue;	}      /* index into symbol table */      ndx = token - SMURFCFG_INVALID - 1;      /* get equals token '=' */      token = g_scanner_get_next_token (scanner);      if (token == G_TOKEN_EOF)	{			/* end of file reached? */	  smurfcfg_parse_err (scanner, _("Unexpected end of file"));	  break;	}      if (token != G_TOKEN_EQUAL_SIGN)	{			/* make sure its an '=' sign */	  smurfcfg_parse_err (scanner,	    _("Unexpected token while looking for '='"));	  smurfcfg_next_line (scanner);	  continue;	}      /* get value */      token = g_scanner_get_next_token (scanner);      if (token == G_TOKEN_EOF)	{	  smurfcfg_parse_err (scanner, _("Unexpected end of file"));	  break;		/* end of file? */	}      /* value is of correct type? */      if (token != symbols[ndx].type)	{	  /* %s is the type of the value (i.e. string, integer, etc) */	  s = g_strdup_printf (_("Unexpected value while looking for a '%s'"),	    smurfcfg_type_string (symbols[ndx].type));	  smurfcfg_parse_err (scanner, s);	  g_free (s);	  smurfcfg_next_line (scanner);	  continue;	}      /* save the value */      switch (token)	{	case G_TOKEN_STRING:	  symbols[ndx].val.v_string = g_strdup (scanner->value.v_string);	  break;	default:	  memcpy (&symbols[ndx].val, &scanner->value, sizeof (GTokenValue));	  break;	}    }  if (!smurfcfg_error)    logit (LogInfo, _("Finished parsing %s"), fname);  else    logit (LogInfo, _("Finished parsing %s, some lines were discarded"),	   fname);  g_scanner_destroy (scanner);  smurfcfg_up2date = TRUE;  return (OK);}static voidsmurfcfg_parse_err (GScanner * scanner, gchar * msg){  smurfcfg_error = TRUE;  logit (LogFubar, _("Parse error on line %d: %s"), scanner->line, msg);}/* advance to next line of input file */static voidsmurfcfg_next_line (GScanner * scanner){  gint line;  line = g_scanner_cur_line (scanner);  while ( g_scanner_peek_next_token (scanner) != G_TOKEN_EOF)    {      if (scanner->next_line > line)	break;      g_scanner_get_next_token (scanner);    }}/* saves preference variables */gintsmurfcfg_save (void){  gint retval;  retval = smurfcfg_save_vars ("smurf.cfg", SMURFCFG_STATE_LAST + 1,			      SMURFCFG_LAST - 1);  if (retval) smurfcfg_up2date = TRUE;  return (retval);}/* saves state variables */gintsmurfcfg_save_state (void){  return (smurfcfg_save_vars ("smurf_state.cfg", SMURFCFG_VERSION + 1,			      SMURFCFG_STATE_LAST - 1));}static gintsmurfcfg_save_vars (gchar *fname, gint first, gint last){  FILE *fd;  gchar *s, *s2;  gint i;  struct stat st;  GTokenValue tokval;  s = g_strconcat (g_get_home_dir (), "/.smurf", NULL);  if (stat (s, &st) == -1)	/* check if ~/.smurf exists */    {      if (mkdir (s, 0755) == -1) /* nope: make the directory */	{	  g_free (s);	  return (logit (LogFubar | LogErrno,			 _("Failed to create ~/.smurf directory")));	}    }  s2 = g_strconcat (s, "/", fname, NULL);  g_free (s);  if (!(fd = fopen (s2, "w")))	/* open config file for writing */    {      g_free (s2);      return (logit (LogFubar | LogErrno,		     _("Failed to open ~/.smurf/%s for writing"), fname));    }  g_free (s2);  /* set Smurf version config var to current version */  tokval.v_string = VERSION;  smurfcfg_set_val (SMURFCFG_VERSION, &tokval);  /* This is a comment at the top of the smurf.cfg file, leave '#'s intact */  if (fputs (_("#\n# Smurf Sound Font Editor configuration file,"	" overwritten apon exit\n#\n"), fd) < 0)    {      fclose (fd);      return (logit (LogFubar | LogErrno,		     _("Failed to write to ~/.smurf/%s"), fname));    }  last -= SMURFCFG_VERSION;	/* convert to array index */  /* write specified config vars to file ("first" to "last") */  i = 0;  do    {      switch (symbols[i].type)	{	case G_TOKEN_STRING:	  s = g_strdup_printf ("\"%s\"", symbols[i].val.v_string);	  break;	case G_TOKEN_INT:	  s = g_strdup_printf ("%d", (int) symbols[i].val.v_int);	  break;	case G_TOKEN_FLOAT:	  s = g_strdup_printf ("%f", symbols[i].val.v_float);	  break;	default:	  s = g_strdup ("");	  break;	}      s2 = g_strdup_printf ("%s = %s\n", symbols[i].name, s);      g_free (s);      if (!safe_fwrite (s2, strlen (s2), fd))	{	  g_free (s2);	  fclose (fd);	  return (logit (LogFubar,	      _("Failed to write to ~/.smurf/%s"), fname));	}      g_free (s2);      if (i == 0)	i = first - SMURFCFG_VERSION;      else i++;    }  while (i <= last);  fclose (fd);  return (OK);}GTokenValue *smurfcfg_get_val (guint var){  g_return_val_if_fail (var > SMURFCFG_INVALID && var < SMURFCFG_LAST, NULL);  return (&symbols[var - SMURFCFG_INVALID - 1].val);}gintsmurfcfg_get_int (guint var){  GTokenValue *val;  val = smurfcfg_get_val (var);  if (!val) return (-1);  return (val->v_int);}gchar *smurfcfg_get_str (guint var){  GTokenValue *val;  val = smurfcfg_get_val (var);  if (!val) return (NULL);  return (val->v_string);}voidsmurfcfg_set_val (guint var, GTokenValue * value){  guint ndx;  g_return_if_fail (var > SMURFCFG_INVALID && var < SMURFCFG_LAST);  ndx = var - SMURFCFG_INVALID - 1;  if (symbols[ndx].type == G_TOKEN_STRING) /* variable type is string? */    {      /* current string value is not the same as new string? */      if (strcmp (symbols[ndx].val.v_string, value->v_string) != 0)	{	  g_free (symbols[ndx].val.v_string);	  symbols[ndx].val.v_string = g_strdup (value->v_string);	  smurfcfg_up2date = FALSE;	}    }  else if (symbols[ndx].type == G_TOKEN_INT) /* variable type is integer? */    {      if (symbols[ndx].val.v_int != value->v_int) /* value changed? */	{	  symbols[ndx].val.v_int = value->v_int;	  smurfcfg_up2date = FALSE;	}    }}/* parses a hash color "#RRGGBB" and saves RGB components into array   return: OK/FAIL */gintsmurfcfg_parse_hashcolor (gchar * clr, guchar * rgb){  gint i;  if (*clr++ != '#')    return (FAIL);  for (i = 0; i < 3; i++)    {      if (*clr >= '0' && *clr <= '9')	rgb[i] = (*clr - '0') << 4;      else if (*clr >= 'A' && *clr <= 'F')	rgb[i] = (*clr - 'A' + 0xA) << 4;      else if (*clr >= 'a' && *clr <= 'F')	rgb[i] = (*clr - 'a' + 0xA) << 4;      else	return (FAIL);      clr++;      if (*clr >= '0' && *clr <= '9')	rgb[i] |= (*clr - '0');      else if (*clr >= 'A' && *clr <= 'F')	rgb[i] |= (*clr - 'A' + 0xA);      else if (*clr >= 'a' && *clr <= 'F')	rgb[i] |= (*clr - 'a' + 0xA);      else	return (FAIL);      clr++;    }  return (OK);}static gchar *smurfcfg_type_string (guint token){  switch (token)    {    case G_TOKEN_STRING:      return (_("string"));    case G_TOKEN_INT:      return (_("integer"));    case G_TOKEN_FLOAT:      return (_("float"));    default:      /* "Unknown" as refering to an unknown data type */      return (_("unknown"));    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -