| version 1.1, 2003/10/16 17:58:10 | version 1.11, 2006/12/16 22:23:24 | 
| Line 3 | Line 3 | 
 | #include        "dosio.h" | #include        "dosio.h" | 
 | #include        "textfile.h" | #include        "textfile.h" | 
 | #include        "midiout.h" | #include        "midiout.h" | 
 |  | #if defined(SUPPORT_ARC) | 
 |  | #include        "arc.h" | 
 |  | #endif | 
 |  |  | 
 |  |  | 
 | #define CFG_MAXAMP              400 | #define CFG_MAXAMP              400 | 
| Line 16  enum { | Line 19  enum { | 
 | CFG_DRUM | CFG_DRUM | 
 | }; | }; | 
 |  |  | 
| static const char str_dir[] = "dir"; | static const OEMCHAR str_dir[] = OEMTEXT("dir"); | 
| static const char str_source[] = "source"; | static const OEMCHAR str_source[] = OEMTEXT("source"); | 
| static const char str_default[] = "default"; | static const OEMCHAR str_default[] = OEMTEXT("default"); | 
| static const char str_bank[] = "bank"; | static const OEMCHAR str_bank[] = OEMTEXT("bank"); | 
| static const char str_drumset[] = "drumset"; | static const OEMCHAR str_drumset[] = OEMTEXT("drumset"); | 
| static const char *cfgstr[] = {str_dir, str_source, str_default, | static const OEMCHAR *cfgstr[] = {str_dir, str_source, str_default, | 
 | str_bank, str_drumset}; | str_bank, str_drumset}; | 
 |  |  | 
| static const char str_amp[] = "amp"; | static const OEMCHAR str_amp[] = OEMTEXT("amp"); | 
| static const char str_keep[] = "keep"; | static const OEMCHAR str_keep[] = OEMTEXT("keep"); | 
| static const char str_note[] = "note"; | static const OEMCHAR str_note[] = OEMTEXT("note"); | 
| static const char str_pan[] = "pan"; | static const OEMCHAR str_pan[] = OEMTEXT("pan"); | 
| static const char str_strip[] = "strip"; | static const OEMCHAR str_strip[] = OEMTEXT("strip"); | 
| static const char str_left[] = "left"; | static const OEMCHAR str_left[] = OEMTEXT("left"); | 
| static const char str_center[] = "center"; | static const OEMCHAR str_center[] = OEMTEXT("center"); | 
| static const char str_right[] = "right"; | static const OEMCHAR str_right[] = OEMTEXT("right"); | 
| static const char str_env[] = "env"; | static const OEMCHAR str_env[] = OEMTEXT("env"); | 
| static const char str_loop[] = "loop"; | static const OEMCHAR str_loop[] = OEMTEXT("loop"); | 
| static const char str_tail[] = "tail"; | static const OEMCHAR str_tail[] = OEMTEXT("tail"); | 
| static const char file_timiditycfg[] = "timidity.cfg"; | static const OEMCHAR file_timiditycfg[] = OEMTEXT("timidity.cfg"); | 
|  | static const OEMCHAR str_basedir[] = OEMTEXT("${basedir}"); | 
 |  |  | 
 |  |  | 
| static void pathadd(MIDIMOD mod, const char *path) { | static void VERMOUTHCL pathadd(MIDIMOD mod, const OEMCHAR *path) { | 
 |  |  | 
 | _PATHLIST       pl; | _PATHLIST       pl; | 
 | PATHLIST        p; | PATHLIST        p; | 
| Line 46  static void pathadd(MIDIMOD mod, const c | Line 50  static void pathadd(MIDIMOD mod, const c | 
 | ZeroMemory(&pl, sizeof(pl)); | ZeroMemory(&pl, sizeof(pl)); | 
 | if (path) { | if (path) { | 
 | pl.path[0] = '\0'; | pl.path[0] = '\0'; | 
| file_catname(pl.path, path, sizeof(pl.path));   // separator change! | // separator change! | 
|  | file_catname(pl.path, path, NELEMENTS(pl.path)); | 
 | if (path[0]) { | if (path[0]) { | 
| file_setseparator(pl.path, sizeof(pl.path)); | #if defined(SUPPORT_ARC) | 
|  | if (milstr_chr(pl.path, '#') == NULL) | 
|  | #endif | 
|  | file_setseparator(pl.path, NELEMENTS(pl.path)); | 
 | } | } | 
 | } | } | 
 |  |  | 
 | pl.next = mod->pathlist; | pl.next = mod->pathlist; | 
 | p = pl.next; | p = pl.next; | 
 | while(p) { | while(p) { | 
| if (!strcmp(p->path, pl.path)) { | if (!file_cmpname(p->path, pl.path)) { | 
 | return; | return; | 
 | } | } | 
 | p = p->next; | p = p->next; | 
| Line 66  static void pathadd(MIDIMOD mod, const c | Line 74  static void pathadd(MIDIMOD mod, const c | 
 | } | } | 
 | } | } | 
 |  |  | 
| static int cfggetarg(char *str, char *arg[], int maxarg) { | static void VERMOUTHCL pathaddex(MIDIMOD mod, const OEMCHAR *path) { | 
|  |  | 
|  | OEMCHAR _path[MAX_PATH]; | 
|  |  | 
|  | if (milstr_memcmp(path, str_basedir)) { | 
|  | pathadd(mod, path); | 
|  | } | 
|  | else { | 
|  | file_cpyname(_path, file_getcd(str_null), NELEMENTS(_path)); | 
|  | file_cutseparator(_path); | 
|  | file_catname(_path, path + 10, NELEMENTS(_path)); | 
|  | pathadd(mod, _path); | 
|  | } | 
|  | } | 
|  |  | 
|  | static int VERMOUTHCL cfggetarg(OEMCHAR *str, OEMCHAR *arg[], int maxarg) { | 
 |  |  | 
 | int             ret; | int             ret; | 
 | BOOL    quot; | BOOL    quot; | 
| char    *p; | OEMCHAR *p; | 
| BYTE    c; | OEMCHAR c; | 
 |  |  | 
 | ret = 0; | ret = 0; | 
 | while(maxarg--) { | while(maxarg--) { | 
| Line 81  static int cfggetarg(char *str, char *ar | Line 104  static int cfggetarg(char *str, char *ar | 
 | if ((c == 0) || (c == 0x23)) { | if ((c == 0) || (c == 0x23)) { | 
 | goto cga_done; | goto cga_done; | 
 | } | } | 
| if (c > 0x20) { | if ((c < 0) || (c > 0x20)) { | 
 | break; | break; | 
 | } | } | 
 | str++; | str++; | 
| Line 104  static int cfggetarg(char *str, char *ar | Line 127  static int cfggetarg(char *str, char *ar | 
 | *p = '\0'; | *p = '\0'; | 
 | goto cga_done; | goto cga_done; | 
 | } | } | 
| else if (c > 0x20) { | else if ((c < 0) || (c > 0x20)) { | 
 | *p++ = c; | *p++ = c; | 
 | } | } | 
 | else { | else { | 
| Line 118  cga_done: | Line 141  cga_done: | 
 | return(ret); | return(ret); | 
 | } | } | 
 |  |  | 
| static char *seachr(char *str, char sepa) { | static OEMCHAR *VERMOUTHCL seachr(const OEMCHAR *str, OEMCHAR sepa) { | 
 |  |  | 
| char    c; | OEMCHAR c; | 
 |  |  | 
 | while(1) { | while(1) { | 
 | c = *str; | c = *str; | 
| Line 128  static char *seachr(char *str, char sepa | Line 151  static char *seachr(char *str, char sepa | 
 | break; | break; | 
 | } | } | 
 | if (c == sepa) { | if (c == sepa) { | 
| return(str); | return((OEMCHAR *)str); | 
 | } | } | 
 | str++; | str++; | 
 | } | } | 
| Line 140  enum { | Line 163  enum { | 
 | VAL_SIGN        = 2 | VAL_SIGN        = 2 | 
 | }; | }; | 
 |  |  | 
| static BOOL cfggetval(const char *str, int *val) { | static BRESULT VERMOUTHCL cfggetval(const OEMCHAR *str, int *val) { | 
 |  |  | 
 | int             ret; | int             ret; | 
 | int             flag; | int             flag; | 
| Line 185  static BOOL cfggetval(const char *str, i | Line 208  static BOOL cfggetval(const char *str, i | 
 |  |  | 
 | // ---- | // ---- | 
 |  |  | 
| static void settone(MIDIMOD mod, int bank, int argc, char *argv[]) { | static void VERMOUTHCL settone(MIDIMOD mod, int bank, int argc, | 
|  | OEMCHAR *argv[]) { | 
 |  |  | 
 | int             val; | int             val; | 
 | TONECFG tone; | TONECFG tone; | 
| char    *name; | OEMCHAR *name; | 
 | int             i; | int             i; | 
| char    *key; | OEMCHAR *key; | 
| char    *data; | OEMCHAR *data; | 
| BYTE    flag; | UINT8   flag; | 
 |  |  | 
 | if ((bank < 0) || (bank >= (MIDI_BANKS * 2)) || (argc < 2) || | if ((bank < 0) || (bank >= (MIDI_BANKS * 2)) || (argc < 2) || | 
 | (cfggetval(argv[0], &val) != SUCCESS) || (val < 0) || (val >= 128)) { | (cfggetval(argv[0], &val) != SUCCESS) || (val < 0) || (val >= 128)) { | 
| Line 211  static void settone(MIDIMOD mod, int ban | Line 235  static void settone(MIDIMOD mod, int ban | 
 | tone += val; | tone += val; | 
 | name = tone->name; | name = tone->name; | 
 | if (name == NULL) { | if (name == NULL) { | 
| name = (char *)listarray_append(mod->namelist, NULL); | name = (OEMCHAR *)listarray_append(mod->namelist, NULL); | 
 | tone->name = name; | tone->name = name; | 
 | } | } | 
 | if (name) { | if (name) { | 
| Line 227  static void settone(MIDIMOD mod, int ban | Line 251  static void settone(MIDIMOD mod, int ban | 
 | } | } | 
 | else {                                                          // for drums | else {                                                          // for drums | 
 | flag |= TONECFG_NOLOOP | TONECFG_NOENV; | flag |= TONECFG_NOLOOP | TONECFG_NOENV; | 
| tone->note = (BYTE)val; | tone->note = (UINT8)val; | 
 | } | } | 
 |  |  | 
 | for (i=2; i<argc; i++) { | for (i=2; i<argc; i++) { | 
| Line 260  static void settone(MIDIMOD mod, int ban | Line 284  static void settone(MIDIMOD mod, int ban | 
 | else if (!milstr_cmp(key, str_note)) { | else if (!milstr_cmp(key, str_note)) { | 
 | if ((cfggetval(data, &val) == SUCCESS) && | if ((cfggetval(data, &val) == SUCCESS) && | 
 | (val >= 0) && (val < 128)) { | (val >= 0) && (val < 128)) { | 
| tone->note = (BYTE)val; | tone->note = (UINT8)val; | 
 | } | } | 
 | } | } | 
 | else if (!milstr_cmp(key, str_pan)) { | else if (!milstr_cmp(key, str_pan)) { | 
| Line 288  static void settone(MIDIMOD mod, int ban | Line 312  static void settone(MIDIMOD mod, int ban | 
 | else { | else { | 
 | continue; | continue; | 
 | } | } | 
| tone->pan = (BYTE)val; | tone->pan = (UINT8)val; | 
 | } | } | 
 | else if (!milstr_cmp(key, str_strip)) { | else if (!milstr_cmp(key, str_strip)) { | 
 | if (!milstr_cmp(data, str_env)) { | if (!milstr_cmp(data, str_env)) { | 
| Line 309  static void settone(MIDIMOD mod, int ban | Line 333  static void settone(MIDIMOD mod, int ban | 
 |  |  | 
 | // ---- | // ---- | 
 |  |  | 
| BOOL cfgfile_getfile(MIDIMOD mod, const char *filename, | BRESULT VERMOUTHCL midimod_getfile(MIDIMOD mod, const OEMCHAR *filename, | 
| char *path, int size) { | OEMCHAR *path, int size) { | 
 |  |  | 
 | PATHLIST        p; | PATHLIST        p; | 
 | short           attr; | short           attr; | 
| Line 321  BOOL cfgfile_getfile(MIDIMOD mod, const | Line 345  BOOL cfgfile_getfile(MIDIMOD mod, const | 
 | } | } | 
 | p = mod->pathlist; | p = mod->pathlist; | 
 | while(p) { | while(p) { | 
| milstr_ncpy(path, p->path, size); | file_cpyname(path, p->path, size); | 
| milstr_ncat(path, filename, size); | file_catname(path, filename, size); | 
|  | #if defined(SUPPORT_ARC) | 
|  | attr = arcex_attr(path); | 
|  | #else | 
 | attr = file_attr(path); | attr = file_attr(path); | 
 |  | #endif | 
 | if (attr != -1) { | if (attr != -1) { | 
 | return(SUCCESS); | return(SUCCESS); | 
 | } | } | 
| Line 334  fpgf_exit: | Line 362  fpgf_exit: | 
 | return(FAILURE); | return(FAILURE); | 
 | } | } | 
 |  |  | 
| BOOL cfgfile_load(MIDIMOD mod, const char *filename, int depth) { | static BRESULT VERMOUTHCL cfgfile_load(MIDIMOD mod, const OEMCHAR *filename, | 
|  | int depth) { | 
 |  |  | 
 | TEXTFILEH       tfh; | TEXTFILEH       tfh; | 
| char            buf[1024]; | OEMCHAR         buf[1024]; | 
 | int                     bank; | int                     bank; | 
 | int                     i; | int                     i; | 
 | int                     argc; | int                     argc; | 
| char            *argv[16]; | OEMCHAR         *argv[16]; | 
 | int                     val; | int                     val; | 
 | UINT            cfg; | UINT            cfg; | 
 |  |  | 
 | bank = -1; | bank = -1; | 
 |  |  | 
 | if ((depth >= 16) || | if ((depth >= 16) || | 
| (cfgfile_getfile(mod, filename, buf, sizeof(buf)) != SUCCESS)) { | (midimod_getfile(mod, filename, buf, NELEMENTS(buf)) != SUCCESS)) { | 
 | goto cfl_err; | goto cfl_err; | 
 | } | } | 
 | //      TRACEOUT(("open: %s", buf)); | //      TRACEOUT(("open: %s", buf)); | 
| Line 356  BOOL cfgfile_load(MIDIMOD mod, const cha | Line 385  BOOL cfgfile_load(MIDIMOD mod, const cha | 
 | if (tfh == NULL) { | if (tfh == NULL) { | 
 | goto cfl_err; | goto cfl_err; | 
 | } | } | 
| while(textfile_read(tfh, buf, sizeof(buf)) == SUCCESS) { | while(textfile_read(tfh, buf, NELEMENTS(buf)) == SUCCESS) { | 
| argc = cfggetarg(buf, argv, sizeof(argv)/sizeof(char *)); | argc = cfggetarg(buf, argv, NELEMENTS(argv)); | 
 | if (argc < 2) { | if (argc < 2) { | 
 | continue; | continue; | 
 | } | } | 
 | cfg = 0; | cfg = 0; | 
| while(cfg < (sizeof(cfgstr)/sizeof(char *))) { | while(cfg < NELEMENTS(cfgstr)) { | 
 | if (!milstr_cmp(argv[0], cfgstr[cfg])) { | if (!milstr_cmp(argv[0], cfgstr[cfg])) { | 
 | break; | break; | 
 | } | } | 
| Line 371  BOOL cfgfile_load(MIDIMOD mod, const cha | Line 400  BOOL cfgfile_load(MIDIMOD mod, const cha | 
 | switch(cfg) { | switch(cfg) { | 
 | case CFG_DIR: | case CFG_DIR: | 
 | for (i=1; i<argc; i++) { | for (i=1; i<argc; i++) { | 
| pathadd(mod, argv[i]); | pathaddex(mod, argv[i]); | 
 | } | } | 
 | break; | break; | 
 |  |  | 
| Line 413  cfl_err: | Line 442  cfl_err: | 
 |  |  | 
 | // ---- | // ---- | 
 |  |  | 
| MIDIMOD midimod_create(UINT samprate) { | VEXTERN MIDIMOD VEXPORT midimod_create(UINT samprate) { | 
 |  |  | 
 | UINT    size; | UINT    size; | 
 | MIDIMOD ret; | MIDIMOD ret; | 
| BOOL    r; | BRESULT r; | 
 |  |  | 
 | size = sizeof(_MIDIMOD); | size = sizeof(_MIDIMOD); | 
 | size += sizeof(INSTRUMENT) * 128 * 2; | size += sizeof(INSTRUMENT) * 128 * 2; | 
 | size += sizeof(_TONECFG) * 128 * 2; | size += sizeof(_TONECFG) * 128 * 2; | 
 | ret = (MIDIMOD)_MALLOC(size, "MIDIMOD"); | ret = (MIDIMOD)_MALLOC(size, "MIDIMOD"); | 
| if (ret) { | if (ret == NULL) { | 
| ZeroMemory(ret, size); | goto mmcre_err1; | 
| ret->samprate = samprate; | } | 
| ret->tone[0] = (INSTRUMENT *)(ret + 1); | ZeroMemory(ret, size); | 
| ret->tone[1] = ret->tone[0] + 128; | ret->samprate = samprate; | 
| ret->tonecfg[0] = (TONECFG)(ret->tone[1] + 128); | ret->tone[0] = (INSTRUMENT *)(ret + 1); | 
| ret->tonecfg[1] = ret->tonecfg[0] + 128; | ret->tone[1] = ret->tone[0] + 128; | 
| ret->pathtbl = listarray_new(sizeof(_PATHLIST), 64); | ret->tonecfg[0] = (TONECFG)(ret->tone[1] + 128); | 
| pathadd(ret, NULL); | ret->tonecfg[1] = ret->tonecfg[0] + 128; | 
| pathadd(ret, file_getcd(str_null)); | ret->pathtbl = listarray_new(sizeof(_PATHLIST), 16); | 
| ret->namelist = listarray_new(MAX_NAME, 128); | pathadd(ret, NULL); | 
| r = cfgfile_load(ret, file_timiditycfg, 0); | pathadd(ret, file_getcd(str_null)); | 
|  | ret->namelist = listarray_new(MAX_NAME, 128); | 
|  | r = cfgfile_load(ret, file_timiditycfg, 0); | 
 | #if defined(TIMIDITY_CFGFILE) | #if defined(TIMIDITY_CFGFILE) | 
| if (r != SUCCESS) { | if (r != SUCCESS) { | 
| r = cfgfile_load(ret, TIMIDITY_CFGFILE, 0); | r = cfgfile_load(ret, TIMIDITY_CFGFILE, 0); | 
| } | } | 
 | #endif | #endif | 
 |  | if (r != SUCCESS) { | 
 |  | goto mmcre_err2; | 
 | } | } | 
 |  | midimod_lock(ret); | 
 | return(ret); | return(ret); | 
 |  |  | 
 |  | mmcre_err2: | 
 |  | listarray_destroy(ret->namelist); | 
 |  | listarray_destroy(ret->pathtbl); | 
 |  | _MFREE(ret); | 
 |  |  | 
 |  | mmcre_err1: | 
 |  | return(NULL); | 
 |  | } | 
 |  |  | 
 |  | void VERMOUTHCL midimod_lock(MIDIMOD mod) { | 
 |  |  | 
 |  | mod->lockcount++; | 
 | } | } | 
 |  |  | 
| void midimod_destroy(MIDIMOD hdl) { | void VERMOUTHCL midimod_unlock(MIDIMOD mod) { | 
 |  |  | 
 | UINT    r; | UINT    r; | 
 | TONECFG bank; | TONECFG bank; | 
 |  |  | 
| if (hdl) { | if (!mod->lockcount) { | 
| r = 128; | return; | 
| do { | } | 
| r--; | mod->lockcount--; | 
| inst_bankfree(hdl, r); | if (mod->lockcount) { | 
| } while(r > 0); | return; | 
| for (r=2; r<(MIDI_BANKS*2); r++) { | } | 
| bank = hdl->tonecfg[r]; |  | 
| if (bank) { | r = 128; | 
| _MFREE(bank); | do { | 
| } | r--; | 
|  | inst_bankfree(mod, r); | 
|  | } while(r > 0); | 
|  | for (r=2; r<(MIDI_BANKS*2); r++) { | 
|  | bank = mod->tonecfg[r]; | 
|  | if (bank) { | 
|  | _MFREE(bank); | 
 | } | } | 
 | listarray_destroy(hdl->namelist); |  | 
 | listarray_destroy(hdl->pathtbl); |  | 
 | _MFREE(hdl); |  | 
 | } | } | 
 |  | listarray_destroy(mod->namelist); | 
 |  | listarray_destroy(mod->pathtbl); | 
 |  | _MFREE(mod); | 
 | } | } | 
 |  |  | 
| void midimod_loadprogram(MIDIMOD hdl, UINT num) { | VEXTERN void VEXPORT midimod_destroy(MIDIMOD mod) { | 
|  |  | 
|  | if (mod) { | 
|  | midimod_unlock(mod); | 
|  | } | 
|  | } | 
|  |  | 
|  | VEXTERN BRESULT VEXPORT midimod_cfgload(MIDIMOD mod, | 
|  | const OEMCHAR *filename) { | 
|  |  | 
|  | return(cfgfile_load(mod, filename, 0)); | 
|  | } | 
|  |  | 
|  | VEXTERN void VEXPORT midimod_loadprogram(MIDIMOD mod, UINT num) { | 
 |  |  | 
 | UINT    bank; | UINT    bank; | 
 |  |  | 
| if (hdl != NULL) { | if (mod != NULL) { | 
 | bank = (num >> 8) & 0x7f; | bank = (num >> 8) & 0x7f; | 
 | num &= 0x7f; | num &= 0x7f; | 
| if (inst_singleload(hdl, bank << 1, num) != MIDIOUT_SUCCESS) { | if (inst_singleload(mod, bank << 1, num) != MIDIOUT_SUCCESS) { | 
| inst_singleload(hdl, 0, num); | inst_singleload(mod, 0, num); | 
 | } | } | 
 | } | } | 
 | } | } | 
 |  |  | 
| void midimod_loadrhythm(MIDIMOD hdl, UINT num) { | VEXTERN void VEXPORT midimod_loadrhythm(MIDIMOD mod, UINT num) { | 
 |  |  | 
 | UINT    bank; | UINT    bank; | 
 |  |  | 
| if (hdl != NULL) { | if (mod != NULL) { | 
 | bank = (num >> 8) & 0x7f; | bank = (num >> 8) & 0x7f; | 
 | num &= 0x7f; | num &= 0x7f; | 
| if (inst_singleload(hdl, (bank << 1) + 1, num) != MIDIOUT_SUCCESS) { | if (inst_singleload(mod, (bank << 1) + 1, num) != MIDIOUT_SUCCESS) { | 
| inst_singleload(hdl, 1, num); | inst_singleload(mod, 1, num); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | VEXTERN void VEXPORT midimod_loadgm(MIDIMOD mod) { | 
|  |  | 
|  | if (mod) { | 
|  | inst_bankload(mod, 0); | 
|  | inst_bankload(mod, 1); | 
|  | } | 
|  | } | 
|  |  | 
|  | VEXTERN void VEXPORT midimod_loadall(MIDIMOD mod) { | 
|  |  | 
|  | UINT    b; | 
|  |  | 
|  | if (mod) { | 
|  | for (b=0; b<(MIDI_BANKS*2); b++) { | 
|  | inst_bankload(mod, b); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | VEXTERN void VEXPORT midimod_loadallex(MIDIMOD mod, FNMIDIOUTLAEXCB cb, | 
|  | void *userdata) { | 
|  |  | 
|  | MIDIOUTLAEXPARAM param; | 
|  | UINT    b; | 
|  |  | 
|  | if (mod) { | 
|  | ZeroMemory(¶m, sizeof(param)); | 
|  | param.userdata = userdata; | 
|  | for (b=0; b<(MIDI_BANKS*2); b++) { | 
|  | param.totaltones += inst_gettones(mod, b); | 
|  | } | 
|  | for (b=0; b<(MIDI_BANKS*2); b++) { | 
|  | param.bank = b; | 
|  | inst_bankloadex(mod, b, cb, ¶m); | 
 | } | } | 
 | } | } | 
 | } | } |