📄 vbank.c
字号:
/*================================================================== * vbank.c - Virtual sound font bank file (*.bnk) routines * * Smurf Sound Font Editor * Copyright (C) 1999-2001 Josh Green * * Borrowed code from awesfx utilities * in files loadbank.c, bool.c, dynload.c in awelib/ * awesfx utilities are Copyright (C) 1996-1999 Takashi Iwai * * 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 <stdlib.h>#include <string.h>#include <ctype.h>#include <glib.h>#include <sys/types.h>#include <sys/stat.h>#include <dirent.h>#include <unistd.h>#include "vbank.h"#include "i18n.h"#include "sfont.h"#include "smurfcfg.h"#include "util.h"#include "uif_sfont.h" /* probably won't depend on this in future */static void vbank_sort (VBnkData *vbnk);static gint vbank_map_sort_func (gconstpointer a, gconstpointer b);static gint vbank_compare_bank_prenum (gint bank1, gint pset1, gint bank2, gint pset2);static void vbank_GHFunc_find_sfont (gpointer key, gpointer value, gpointer data);static gint vbank_hash_sffiles (gchar *dirname, gboolean recurse);static gint vbank_parse (FILE *fp, VBnkData *vbnk);static gint vbank_parse_item(gchar *arg, VBnkItem *item, gchar **strp);static void vbank_parse_preset(VBnkPtr *vptr, char *arg);static int vbank_parse_arg(char *arg);static char *strschr(char *str, char *dels);/* hash tables to index sound font file names in virtual bank search path *//* vbank_sffile_hash is an index of sound font file names but with the '.' in the extension changed to a '\0' which makes 2 strings. So the hash key is effectively the sound font file name without the extension, but the extension can still be found by retrieving the original key */static GHashTable *vbank_sffile_hash = NULL;static GHashTable *vbank_sfdir_hash = NULL; /* stores directory names */VBnkData *vbank_new (gint untitlecount){ VBnkData *vbnk; vbnk = g_malloc0 (sizeof (VBnkData)); vbnk->fname = g_strdup_printf (_("untitled%d.bnk"), untitlecount); vbnk->up2date = TRUE; vbnk->beensaved = FALSE; return (vbnk);}VBnkData *vbank_load (gchar *fname){ FILE *fp; VBnkData *vbnk; if (!(fp = fopen (fname, "r"))) { logit (LogFubar, _("Failed to open virtual bank '%s'"), fname); return (NULL); } vbnk = g_malloc0 (sizeof (VBnkData)); if (!vbank_parse (fp, vbnk)) return (NULL); vbank_sort (vbnk); vbnk->fname = g_strdup (fname); vbnk->up2date = TRUE; vbnk->beensaved = FALSE; return (vbnk);}gintvbank_save (VBnkData * vbnk, FILE *fp){ VBnkItem *item; GSList *p; gchar *s, *s2, *name; gint i; if (fprintf (fp, _("## Virtual Sound Font Bank file written by:\n")) <= 0) goto agh; if (fprintf (fp, "## Smurf Sound Font Editor v" VERSION "\n\n") <= 0) goto agh; if (vbnk->defname && fprintf (fp, _("default %s\n\n"), vbnk->defname) <= 0) goto agh; p = vbnk->items; while (p) { item = (VBnkItem *)(p->data); /* write source preset/bank[/keynote] */ if (fprintf (fp, "%d/%d", item->src.psetnum, item->src.bank) <= 0) goto agh; if (item->src.keynote >= 0 && fprintf (fp, "/%d", item->src.keynote) <= 0) goto agh; /* write destination :preset/bank[/keynote] */ if (fprintf (fp, ":%d/%d", item->map.psetnum, item->map.bank) <= 0) goto agh; if (item->map.keynote >= 0 && fprintf (fp, "/%d", item->map.keynote) <= 0) goto agh; /* get name of source sound font (no path or extension) */ s = item->sfname; if (s) /* if sound font file name, then format it */ { i = strlen (s); /* allocate space for largest possible '\' escaped sound font name */ name = g_malloc (i * 2 + 1); s2 = name; /* '\' escape all spaces and back slashes */ while (i--) { if (*s == ' ') { *(s2++) = '\\'; *(s2++) = ' '; } else if (*s == '\\') { *(s2++) = '\\'; *(s2++) = '\\'; } else *(s2++) = *s; s++; } *s2 = '\0'; i = fprintf (fp, ":%s", name); g_free (name); if (i <= 0) goto agh; } if (fputc ('\n', fp) == EOF) goto agh; p = g_slist_next (p); } return (OK); agh: return (logit (LogFubar | LogErrno, _("Failed to write to vbank")));}voidvbank_close (VBnkData *vbnk){ GSList *p; if (vbnk->fname) g_free (vbnk->fname); if (vbnk->defname) g_free (vbnk->defname); p = vbnk->items; while (p) { vbank_item_free ((VBnkItem *)(p->data)); p = g_slist_next (p); }}VBnkItem *vbank_item_alloc (void){ return ((VBnkItem *)g_malloc0 (sizeof (VBnkItem)));}voidvbank_item_free (VBnkItem *item){ if (item->sfname) g_free (item->sfname); g_free (item);}VBnkItem *vbank_add_map (gint mapbank, gint mappset, gint mapnote, gint srcbank, gint srcpset, gint srcnote, gchar *srcsfname, VBnkData *vbnk){ VBnkItem *item; g_return_val_if_fail (srcsfname != NULL, NULL); item = vbank_item_alloc (); item->map.bank = mapbank; item->map.psetnum = mappset; item->map.keynote = mapnote; item->src.bank = srcbank; item->src.psetnum = srcpset; item->src.keynote = srcnote; item->sfname = srcsfname; vbnk->items = g_slist_insert_sorted (vbnk->items, item, vbank_map_sort_func); return (item);}voidvbank_delete_map (VBnkItem *item, VBnkData *vbnk){ vbnk->items = g_slist_remove (vbnk->items, item); vbank_item_free (item);}/* finds the first available preset map greater or equal to bank:preset and stores result in bank:preset */voidvbank_find_free_map (gint *bank, gint *psetnum, VBnkData *vbnk){ VBnkItem *item; GSList *p; gint bnk, pr; p = vbnk->items; bnk = *bank; pr = *psetnum; while (p) { item = (VBnkItem *)(p->data); p = g_slist_next (p); /* if item->bank:preset < start bank:preset, then skip */ if (item->map.bank < *bank || (item->map.bank == *bank && item->map.psetnum < *psetnum)) continue; if (bnk < item->map.bank || (bnk == item->map.bank && pr < item->map.psetnum)) break; if (++pr > 127) { pr = 0; bnk++; } } *bank = bnk; *psetnum = pr;}static voidvbank_sort (VBnkData *vbnk){ vbnk->items = g_slist_sort (vbnk->items, vbank_map_sort_func);}/* a GCompareFunc for the sorting of VBnkItems */static gintvbank_map_sort_func (gconstpointer a, gconstpointer b){ VBnkItem *aitem, *bitem; aitem = (VBnkItem *)a; bitem = (VBnkItem *)b; return (((aitem->map.bank - bitem->map.bank) << 8) + (aitem->map.psetnum - bitem->map.psetnum));}/* check the extension */gintvbank_is_virtual_bank (gchar *path){ char *p; if ((p = strrchr(path, '.')) == NULL) return FALSE; if (strcmp(p + 1, "bnk") == 0) return TRUE; return FALSE;}voidvbank_set_fname (VBnkData *vbnk, gchar *fname){ if (vbnk->fname) g_free (vbnk->fname); vbnk->fname = g_strdup (fname);}voidvbank_set_defsf (VBnkData *vbnk, gchar *fname){ g_return_if_fail (fname != NULL); if (vbnk->defname) g_free (vbnk->defname); vbnk->defname = fname;}/* get virtual bank items (returns: GList of VBnkPresetMap's) ** GList and list items should be freed ** */GList *vbank_get_preset_maps (VBnkData *vbnk){ GList *psetlist = NULL; VBnkItem *item; VBnkPresetMap *psetmap; UISFont *uisf, *defuisf; SFPreset *pset; gchar *path; GSList *lvi, *lpr; gint rv; /* find default sound font if its opened already */ path = NULL; if (vbnk->defname && (path = vbank_locate_sfont_by_name (vbnk->defname)) && (defuisf = uisf_find_sfont_by_fname (path, NULL))) lpr = uisf->sf->preset; else lpr = NULL; if (path) g_free (path); lvi = vbnk->items; /* loop over virtual bank items and default sound font presets, virtual bank items override default presets */ while (lvi || lpr) { if (lvi) /* any virtual bank items left? */ { item = (VBnkItem *)(lvi->data); rv = 1; } /* allocate preset map (an SFPreset and its bank:preset # to map to) */ psetmap = g_malloc (sizeof (VBnkPresetMap)); if (lpr) /* any default presets left? */ { psetmap->preset = (SFPreset *)(lpr->data); rv = -1; } /* check ordering of current vbank item and default preset */ if (lvi && lpr) rv = vbank_compare_bank_prenum (psetmap->preset->bank, psetmap->preset->prenum, item->map.bank, item->map.psetnum); if (rv <= 0) /* advance default preset, if needed */ lpr = g_slist_next (lpr); if (rv >= 0) /* vbank item comes next or overrides def? */ { lvi = g_slist_next (lvi); /* ?: sound font loaded for this item and src preset is valid? */ if (!(pset = vbank_get_item_preset (item))) { g_free (psetmap); continue; /* ?: No, skip it */ } psetmap->preset = pset; psetmap->sf = uisf->sf; psetmap->bank = item->map.bank; psetmap->psetnum = item->map.psetnum; } else { psetmap->sf = defuisf->sf; psetmap->bank = psetmap->preset->bank; psetmap->psetnum = psetmap->preset->prenum; } psetlist = g_list_append (psetlist, psetmap); } return (psetlist);}/* find a virtual bank item's preset in opened sfonts (NULL if not found) */SFPreset *vbank_get_item_preset (VBnkItem *item){ gchar *path; UISFont *uisf; GSList *p; if (item->sfname && (path = vbank_locate_sfont_by_name (item->sfname)) && (uisf = uisf_find_sfont_by_fname (path, NULL)) && (p = sfont_find_preset (uisf->sf, NULL, item->src.bank, item->src.psetnum, NULL))) return ((SFPreset *)(p->data)); return (NULL);}/* compares two bank:preset pairs */static gintvbank_compare_bank_prenum (gint bank1, gint pset1, gint bank2, gint pset2){ if (bank1 < bank2) return (-1); if (bank1 > bank2) return (1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -