vbank.c

来自「A GTK sound font editor. Sound font file」· C语言 代码 · 共 879 行 · 第 1/2 页

C
879
字号
  if (pset1 < pset2) return (-1);  if (pset1 > pset2) return (1);  return (0);}/* searches for unloaded sound fonts required by a virtual bank and returns   a list of "found" file paths and "notfound" sound font names, both lists   (and list items) should be freed */voidvbank_find_unloaded_sfonts (VBnkData *vbnk, GList **found, GList **notfound){  GHashTable *sfnames;  GList *nlists[2] = { NULL, NULL};	/* 2 GLists for found and notfound */  VBnkItem *item;  GSList *p;  sfnames = g_hash_table_new (g_str_hash, g_str_equal);  if (vbnk->defname)    g_hash_table_insert (sfnames, vbnk->defname, GINT_TO_POINTER (TRUE));  /* loop over virtual bank items, and insert unloaded sound font names into     hash (gets rid of duplicates) */  p = vbnk->items;  while (p)    {      item = (VBnkItem *)(p->data);      if (item->sfname)	g_hash_table_insert (sfnames, item->sfname, GINT_TO_POINTER (TRUE));      p = g_slist_next (p);    }  g_hash_table_foreach (sfnames, vbank_GHFunc_find_sfont, nlists);  if (!found)    {      g_list_foreach (nlists[0], (GFunc)g_free, NULL);      g_list_free (nlists[0]);    }  else *found = nlists[0];  if (!notfound)    {      g_list_foreach (nlists[1], (GFunc)g_free, NULL);      g_list_free (nlists[1]);    }  else *notfound = nlists[1];}/* GHFunc used by vbank_find_unloaded_sfonts to fill found and not found lists   with found sfont paths and not found sfont names */static voidvbank_GHFunc_find_sfont (gpointer key, gpointer value, gpointer data){  GList **nlists = (GList **)data;  gchar *sfname = (gchar *)key;  gchar *path;  /* can we locate the sound font? (full file path) */  if (!(path = vbank_locate_sfont_by_name (sfname)))    nlists[0] = g_list_append (nlists[0], path); /* ?: YES, add path to found */  else nlists[1] = g_list_append (nlists[1], g_strdup (sfname)); /* ?: Nope */}/* looks up a sound font by name (without extension) in the sfont file hash   and returns a full path to the found file, or NULL if not found.   ** Return string should be freed ** */gchar *vbank_locate_sfont_by_name (gchar *sfname){  gchar *origkey, *dir;  gchar *filepath;  if (!vbank_sffile_hash) vbank_update_sffile_hash ();  /* lookup the sfont name and get original key string */  if (!g_hash_table_lookup_extended (vbank_sffile_hash, sfname,				     (gpointer *)(&origkey),(gpointer *)(&dir)))    return (NULL);  /* construct full path to file (original hash key contains 2 adjacent strings,     first is the sfont name (without extension) second is the 3 letter     extension) */  filepath =    g_strconcat (dir, origkey, ".", origkey + strlen (origkey) + 1, NULL);  return (filepath);}/* turns a full path into just the base file name without ".sf2" extension   ** returned string should be freed ** */gchar *vbank_base_fname (gchar *path){  gchar *s;  s = g_basename (path);  if (strlen (s) > 4 && g_strcasecmp (s + strlen (s) - 4, ".sf2") == 0)    return (g_strndup (s, strlen (s) - 4));  else return (g_strdup (s));}/* indexes all sound font files in directories of vbank search path */voidvbank_update_sffile_hash (void){  gchar *path;  gchar *s, *s2;  gboolean recurse;  /* free old hashes if any */  if (vbank_sffile_hash)    {      /* free keys only (value strings are in vbank_sfdir_hash) */      g_hash_table_foreach (vbank_sffile_hash,			    (GHFunc)g_free, NULL);      g_hash_table_destroy (vbank_sffile_hash);    }  if (vbank_sfdir_hash)    {      /* free keys only (value is just TRUE) */      g_hash_table_foreach (vbank_sfdir_hash, (GHFunc)g_free, NULL);      g_hash_table_destroy (vbank_sfdir_hash);    }  vbank_sffile_hash = g_hash_table_new (g_str_hash, g_str_equal);  vbank_sfdir_hash = g_hash_table_new (g_str_hash, g_str_equal);  path = g_strdup (smurfcfg_get_val (SMURFCFG_VBNK_SEARCH_PATH)->v_string);  /* no search path? */  if (!path || !*path) return;  s = path;  while (s && *s)		/* loop over directory names in search path */    {      if ((s2 = strchr (s, ':')))	{	  *s2 = '\0';	  s2++;	}      /* check for "slash*" (start of C comment :) at end of directory name,	 signifying recursive search */      if (strlen (s) >= 2	  && strcmp (s + strlen (s) - 2, G_DIR_SEPARATOR_S "*") == 0)	{	  s[strlen (s) - 1] = '\0'; /* truncate string at the '*' */	  recurse = TRUE;	}      else recurse = FALSE;	/* no recurse into sub directories */      vbank_hash_sffiles (s, recurse);	/* hash sfont names */      s = s2;    }  g_free (path);}/* adds all sound font file names in "dirname" to vbank_sffile_hash, called by vbank_update_sffile_hash and itself (recursively) */static gintvbank_hash_sffiles (gchar *dirname, gboolean recurse){  gchar *dname;			/* dup of dirname but with / at end if needed */  DIR *dh;  struct dirent *ent;  gchar *fname, *fullpath;  struct stat statnfo;  gboolean found = FALSE;	/* new sound font file found? */  gchar *s;  if (!dirname || !*dirname)    return (logit (LogWarn, _("Empty directory name in virtual bank"			     " search path")));  /* if directory doesn't end with a slash, then add one */  if (dirname [strlen (dirname) - 1] != G_DIR_SEPARATOR)    dname = g_strconcat (dirname, G_DIR_SEPARATOR_S, NULL);  else dname = g_strdup (dirname); /* duplicate to keep g_free consistent */  /* directory already searched? */  if (g_hash_table_lookup (vbank_sfdir_hash, dname))    {      g_free (dname);      return (OK);    }  if (!(dh = opendir (dname)))	/* attempt to open the directory */    return (logit (LogWarn | LogErrno, _("Failed to open directory '%s' in"					 " virtual bank search path"), s));  /* loop over contents of directory */  while ((ent = readdir (dh)))    {      fname = ent->d_name;      /* skip self and parent directory */      if (strcmp (fname, ".") == 0 || strcmp (fname, "..") == 0)	continue;      if (recurse)		/* recurse into sub dirs? */	{	  fullpath = g_strconcat (dname, fname, NULL); /* full path to file */	  if (stat (fullpath, &statnfo) == -1) /* stat the file */	    {	      logit (LogWarn | LogErrno, _("Failed to get stats on file '%s'"),		    fullpath);	      g_free (fullpath);	      continue;	    }	  if (S_ISDIR (statnfo.st_mode)) /* if directory, then recurse it */	    {	      vbank_hash_sffiles (fullpath, TRUE); /* call us recursively */	      g_free (fullpath);	      continue;	    }	  g_free (fullpath);	}      /* is it a sound font file? (.sf2 extension) */      if (strlen (fname) <= 4	  || g_strcasecmp (fname + strlen (fname) - 4, ".sf2") != 0)	continue;      /* make file name string dynamically allocated so we can mess with it */      fname = g_strdup (fname);      /* make file name 2 strings, first is sound font name without extension,	 second string (immediately following the first) is the extension,         therefore file name (without extension) gets used as hash key */      fname [strlen (fname) - 4] = '\0';      /* check if file by this name already found */      if ((s = g_hash_table_lookup (vbank_sffile_hash, fname)))	{	  logit (LogWarn, _("Sound font file '%s' conflicts with '%s' in"			   " virtual sound font search path"), fname, s);	  g_free (fname);	  continue;	}      /* insert into file hash table: sfont name as a key, file's directory	 as the value */      g_hash_table_insert (vbank_sffile_hash, fname, dname);      found = TRUE;    }  /* if any sfonts were found, insert directory name into directory hash     as key and value (hash used to check for duplicates), keep dname */  if (found)    g_hash_table_insert (vbank_sfdir_hash, dname, GINT_TO_POINTER (TRUE));  else g_free (dname);		/* no sfonts found, free dname */  return (OK);}/* parse a virtual bank file into a virtual bank structure */static gintvbank_parse (FILE *fp, VBnkData *vbnk){  char line[256], *p, *p2, *name;  VBnkItem *item;  int len;  gint linenum = 0;  while (fgets(line, sizeof(line) - 1, fp))    {      linenum++;      /* discard the linefeed */      len = strlen(line);      if (len > 0 && line[len-1] == '\n') line[len-1] = 0;       /* skip spaces & comments */      for (p = line; isspace(*p); p++)	;      if (!*p || *p == '#' || *p == '!' || *p == '%')	continue;      if (isalpha(*p))	{	  char *arg;	  arg = strschr(p, " \t\r\n");	  if (arg)	    {	      char *tmp = strschr(arg, " \t\r\n");	      if (tmp) *tmp = 0;	      arg++;	    }	  switch (*p)	    {	    case 'i':	    case 'I':		/* include other bank file */	      break;	    case 'd':	    case 'D':		/* set default font file */	      if (vbnk->defname) g_free(vbnk->defname);	      vbnk->defname = g_strdup(arg);	      break;	    default:	      return (logit (LogFubar, _("Illegal command on line %d"),					linenum));	      break;	    }	  continue;	}      else if (*p == '*' || *p == '-' || isdigit(*p))	{	  item = vbank_item_alloc ();	  if (! vbank_parse_item (p, item, &name))	    {	      vbank_item_free (item);	      logit (LogWarn, _("Ignoring invalid item on line %d"), linenum);	      continue;	    }	  if (item->src.bank == -1 || item->src.psetnum == -1)	    {	      vbank_item_free (item);	      logit (LogWarn, "Virtual bank wildcard maps not supported yet");	      continue;	    }	} else continue;      if (name && *name)	/* if there is a sound font name string */	{	  /* convert "\ " to spaces and "\\" to back slashes, to support	     file names with spaces (original AWE .bnk format doesn't) */	  p = p2 = name;	  while (*p2)	    {	      if (p2[0] == '\\' && p2[1] == ' ')		{		  *p = ' ';		  p2++;		}	      else if (p2[0] == '\\' && p2[1] == '\\')		{		  *p = '\\';		  p2++;		}	      else if (strchr (" \t\n", *p2))		{		  *p = '\0';		  break;		}	      else *p = *p2;	      p++;	      p2++;	    }	  *p = '\0';		/* terminate sound font name */	}      if (name == NULL || !*name) /* without font name -- its a preset link */	item->sfname = NULL;      else item->sfname = g_strdup (name);      vbnk->items = g_slist_append (vbnk->items, item);    }  return (OK);}/* parse source and mapping presets */static gintvbank_parse_item(gchar *arg, VBnkItem *item, gchar **strp){  char *next;  if ((next = strschr(arg, ":=")) != NULL)    *next++ = 0;  vbank_parse_preset(&item->src, arg);  if (next == NULL) {    item->map = item->src;    if (strp) *strp = NULL;    return TRUE;  }  arg = next;  if ((next = strschr(arg, ":=")) != NULL)    *next++ = 0;  vbank_parse_preset(&item->map, arg);  if (strp) *strp = next;  return TRUE;}/* parse preset/bank/keynote */static voidvbank_parse_preset(VBnkPtr *vptr, char *arg){  char *next;  if ((next = strschr(arg, "/: \t\n")) != NULL)    *next++ = 0;  vptr->psetnum = vbank_parse_arg(arg);  vptr->bank = 0;  vptr->keynote = -1;  arg = next;  if (arg) {    if ((next = strschr(arg, "/: \t\n")) != NULL)      *next++ = 0;    vptr->bank = vbank_parse_arg(arg);    if (next)      vptr->keynote = vbank_parse_arg(next);  }}/* ascii to digit; accept * and - characters */static intvbank_parse_arg(char *arg){  if (isdigit(*arg))    return atoi(arg);  else    return -1;}/* search delimiers */static char *strschr(char *str, char *dels){  char *p;  for (p = str; *p; p++) {    if (strchr(dels, *p))      return p;  }  return NULL;}

⌨️ 快捷键说明

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