📄 wrd_read.c
字号:
/* TiMidity++ -- MIDI to WAVE converter and player Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp> Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi> 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 WRD reader - Written by Masanao Izumo <mo@goice.co.jp> Modified by Takaya Nogami <t-nogami@happy.email.ne.jp> for Sherry WRD. */#ifdef HAVE_CONFIG_H#include "config.h"#endif /* HAVE_CONFIG_H */#include <stdio.h>#include <stdlib.h>#ifndef NO_STRING_H#include <string.h>#else#include <strings.h>#endif#include <ctype.h>#include "timidity.h"#include "common.h"#include "instrum.h"#include "playmidi.h"#include "readmidi.h"#include "controls.h"#include "wrd.h"#include "strtab.h"/*#define DEBUG 1*/#if defined(JAPANESE) || defined(__MACOS__)#define IS_MULTI_BYTE(c) ( ((c)&0x80) && ((0x1 <= ((c)&0x7F) && ((c)&0x7F) <= 0x1f) ||\ (0x60 <= ((c)&0x7F) && ((c)&0x7F) <= 0x7c)))#define IS_SJIS_ZENKAKU_SPACE(p) ((p)[0] == 0x81 && (p)[1] == 0x40)#else#define IS_MULTI_BYTE(c) 0#endif /* JAPANESE */#define WRDENDCHAR 26 /* ^Z */#define MAXTOKLEN 255#define MAXTIMESIG 256/* * Define Bug emulation level. * 0: No emulatoin. * 1: Standard emulation (emulate if the bugs is well known). * 2: More emulation (including unknown bugs). * 3-9: Danger level!! (special debug level) */#ifndef MIMPI_BUG_EMULATION_LEVEL#define MIMPI_BUG_EMULATION_LEVEL 1#endifstatic int mimpi_bug_emulation_level = MIMPI_BUG_EMULATION_LEVEL;static int wrd_bugstatus;static int wrd_wmode_prev_step;#ifdef DEBUG#define WRD_BUGEMUINFO(code) ctl->cmsg(CMSG_WARNING, VERB_VERBOSE, \ "WRD: Try to emulate bug of MIMPI at line %d (code=%d)", lineno, code)#else#define WRD_BUGEMUINFO(code) ctl->cmsg(CMSG_WARNING, VERB_NOISY, \ "WRD: Try to emulate bug of MIMPI at line %d", lineno)#endif /* DEBUG *//* Current max code: 13 */#define FADE_SPEED_BASE 24 /* 24 or 48?? */StringTable wrd_read_opts;static int version;struct wrd_delayed_event{ int32 waittime; int cmd, arg; struct wrd_delayed_event* next;};struct wrd_step_tracer{ int32 at; /* total step count */ int32 last_at; /* estimated maxmum steps */ int32 step_inc; /* increment steps per newline or character */ int bar; /* total bar count */ int step; /* step in current bar */ int barstep; /* step count of current bar */ MidiEvent timesig[MAXTIMESIG]; /* list of time signature code */ int timeidx; /* index of current timesig */ int ntimesig; /* number of time signatures */ int timebase; /* divisions */ int offset; /* @OFFSET */ int wmode0, wmode1; /* @WMODE */ /* Delayed MIDI event list */ struct wrd_delayed_event *de; struct wrd_delayed_event *free_de; MBlockList pool; /* memory buffer */};static MBlockList sry_pool; /* data buffer */sry_datapacket *datapacket = NULL;#ifdef ENABLE_SHERRYstatic int datapacket_len, datapacket_cnt;#define DEFAULT_DATAPACKET_LEN 16384static int import_sherrywrd_file(const char * );#endif /* ENABLE_SHERRY */static uint8 cmdlookup(uint8 *cmd);static int wrd_nexttok(struct timidity_file *tf);static void wrd_readinit(void);static struct timidity_file *open_wrd_file(char *fn);static int wrd_hexval(char *hex);static int wrd_eint(char *hex);static int wrd_atoi(char *val, int default_value);static void wrd_add_lyric(int32 at, char *lyric, int len);static int wrd_split(char* arg, char** argv, int maxarg);static void wrdstep_inc(struct wrd_step_tracer *wrdstep, int32 inc);static void wrdstep_update_forward(struct wrd_step_tracer *wrdstep);static void wrdstep_update_backward(struct wrd_step_tracer *wrdstep);static void wrdstep_nextbar(struct wrd_step_tracer *wrdstep);static void wrdstep_prevbar(struct wrd_step_tracer *wrdstep);static void wrdstep_wait(struct wrd_step_tracer *wrdstep, int bar, int step);static void wrdstep_rest(struct wrd_step_tracer *wrdstep, int bar, int step);static struct wrd_delayed_event *wrd_delay_cmd(struct wrd_step_tracer *wrdstep, int32 waittime, int cmd, int arg);static uint8 wrd_tokval[MAXTOKLEN + 1]; /* Token value */static uint8 wrd_tok; /* Token type */static int lineno; /* linenumber */static int32 last_event_time;#define WRD_ADDEVENT(at, cmd, arg) \ { MidiEvent e; e.time = (at); e.type = ME_WRD; e.channel = (cmd); \ e.a = (uint8)((arg) & 0xFF); e.b = (uint8)(((arg) >> 8) & 0xFF); \ if(mimpi_bug_emulation_level > 0){ if(at < last_event_time){ e.time = \ last_event_time; }else{ last_event_time = e.time; }} \ readmidi_add_event(&e); }#define WRD_ADDSTREVENT(at, cmd, str) \ { MidiEvent e; readmidi_make_string_event(ME_WRD, (str), &e, 0); \ e.channel = (cmd); e.time = (at); \ if(mimpi_bug_emulation_level > 0){ if(at < last_event_time){ e.time = \ last_event_time; }else{ last_event_time = e.time; }} \ readmidi_add_event(&e); }#define SETMIDIEVENT(e, at, t, ch, pa, pb) \ { (e).time = (at); (e).type = (t); \ (e).channel = (uint8)(ch); (e).a = (uint8)(pa); (e).b = (uint8)(pb); }#define MIDIEVENT(at, t, ch, pa, pb) \ { MidiEvent event; SETMIDIEVENT(event, at, t, ch, pa, pb); \ readmidi_add_event(&event); }#ifdef DEBUGstatic char *wrd_name_string(int cmd);#endif /* DEBUG */int import_wrd_file(char *fn){ struct timidity_file *tf; char *args[WRD_MAXPARAM], *arg0; int argc; int32 i, num; struct wrd_step_tracer wrdstep;#define step_at wrdstep.at static int initflag = 0; static char *default_wrd_file1, /* Default */ *default_wrd_file2; /* Always */ char *wfn; /* opened WRD filename */ StringTableNode *stn; /* Chain list of string */ if(!initflag) /* Initialize at once */ { char *read_opts[WRD_MAXPARAM]; initflag = 1; for(stn = wrd_read_opts.head; stn; stn = stn->next) { int nopts; nopts = wrd_split(stn->string, read_opts, WRD_MAXPARAM); for(i = 0; i < nopts; i++) { char *a, *b; a = read_opts[i]; if((b = strchr(a, '=')) != NULL) *b++ = '\0'; if(strcmp(a, "d") == 0) mimpi_bug_emulation_level = (b ? atoi(b) : 0); else if(strcmp(a, "f") == 0) { if(default_wrd_file1 != NULL) free(default_wrd_file1); default_wrd_file1 = (b ? safe_strdup(b) : NULL); } else if(strcmp(a, "F") == 0) { if(default_wrd_file2 != NULL) free(default_wrd_file2); default_wrd_file2 = (b ? safe_strdup(b) : NULL); } else if(strcmp(a, "p") == 0) { if(b != NULL) wrd_add_default_path(b); } } } } if(datapacket == NULL) init_mblock(&sry_pool); else { free(datapacket); datapacket = NULL; reuse_mblock(&sry_pool); } wrd_init_path(); if(default_wrd_file2 != NULL) tf = open_file((wfn = default_wrd_file2), 0, OF_NORMAL); else tf = open_wrd_file(wfn = fn); if(tf == NULL && default_wrd_file1 != NULL) tf = open_file((wfn = default_wrd_file1), 0, OF_NORMAL); if(tf == NULL) { default_wrd_file1 = default_wrd_file2 = NULL;#ifdef ENABLE_SHERRY if(import_sherrywrd_file(fn)) return WRD_TRACE_SHERRY;#endif return WRD_TRACE_NOTHING; } wrd_readinit(); memset(&wrdstep, 0, sizeof(wrdstep)); init_mblock(&wrdstep.pool); wrdstep.de = wrdstep.free_de = NULL; wrdstep.timebase = current_file_info->divisions; wrdstep.ntimesig = dump_current_timesig(wrdstep.timesig, MAXTIMESIG - 1); if(wrdstep.ntimesig > 0) { wrdstep.timesig[wrdstep.ntimesig] = wrdstep.timesig[wrdstep.ntimesig - 1]; wrdstep.timesig[wrdstep.ntimesig].time = 0x7fffffff; /* stopper */#ifdef DEBUG printf("Time signatures:\n"); for(i = 0; i < wrdstep.ntimesig; i++) printf(" %d: %d/%d\n", wrdstep.timesig[i].time, wrdstep.timesig[i].a, wrdstep.timesig[i].b);#endif /* DEBUG */ wrdstep.barstep = wrdstep.timesig[0].a * wrdstep.timebase * 4 / wrdstep.timesig[0].b; } else wrdstep.barstep = 4 * wrdstep.timebase; wrdstep.step_inc = wrdstep.barstep; wrdstep.last_at = readmidi_set_track(0, 0); readmidi_set_track(0, 1);#ifdef DEBUG printf("Timebase: %d\n", wrdstep.timebase); printf("Step: %d\n", wrdstep.step_inc);#endif /* DEBUG */ while(!readmidi_error_flag && wrd_nexttok(tf)) { if(version == -1 && (wrd_tok != WRD_COMMAND || wrd_tokval[0] != WRD_STARTUP)) { /* WRD_STARTUP must be first */ ctl->cmsg(CMSG_WARNING, VERB_VERBOSE, "WRD: No @STARTUP"); version = 0; WRD_ADDEVENT(0, WRD_STARTUP, 0); }#ifdef DEBUG printf("%d: [%d,%d]/%d %s: ", lineno, wrdstep.bar, wrdstep.step, wrd_bugstatus, wrd_name_string(wrd_tok)); if(wrd_tok == WRD_COMMAND) printf("%s(%s)", wrd_name_string(wrd_tokval[0]), wrd_tokval + 1); else if(wrd_tok == WRD_LYRIC) printf("<%s>", wrd_tokval); printf("\n"); fflush(stdout);#endif /* DEBUG */ switch(wrd_tok) { case WRD_COMMAND: arg0 = (char *)wrd_tokval + 1; switch(wrd_tokval[0]) { case WRD_COLOR: num = atoi(arg0); WRD_ADDEVENT(step_at, WRD_COLOR, num); break; case WRD_END: while(step_at < wrdstep.last_at) wrdstep_nextbar(&wrdstep); break; case WRD_ESC: WRD_ADDSTREVENT(step_at, WRD_ESC, arg0); break; case WRD_EXEC: WRD_ADDSTREVENT(step_at, WRD_EXEC, arg0); break; case WRD_FADE: argc = wrd_split(arg0, args, 3); for(i = 0; i < 2; i++) { num = atoi(args[i]); WRD_ADDEVENT(step_at, WRD_ARG, num); } num = wrd_atoi(args[i], 1); WRD_ADDEVENT(step_at, WRD_FADE, num); if(num >= 1) { int32 delay, fade_speed; fade_speed = (num + 1) * wrdstep.timebase / FADE_SPEED_BASE; for(i = 1; i < WRD_MAXFADESTEP; i++) { delay = (int32)((double)fade_speed * i / WRD_MAXFADESTEP); wrd_delay_cmd(&wrdstep, delay, WRD_ARG, i); wrd_delay_cmd(&wrdstep, delay, WRD_FADESTEP, WRD_MAXFADESTEP); } wrd_delay_cmd(&wrdstep, fade_speed, WRD_ARG, WRD_MAXFADESTEP); wrd_delay_cmd(&wrdstep, fade_speed, WRD_FADESTEP, WRD_MAXFADESTEP); } break; case WRD_GCIRCLE: argc = wrd_split(arg0, args, 6); if(argc < 5) { /* Error : Too few argument */ break; } for(i = 0; i < 5; i++) { num = atoi(args[i]); WRD_ADDEVENT(step_at, WRD_ARG, num); } num = atoi(args[i]); WRD_ADDEVENT(step_at, WRD_GCIRCLE, num); break; case WRD_GCLS: num = atoi(arg0); WRD_ADDEVENT(step_at, WRD_GCLS, num); break; case WRD_GINIT: WRD_ADDEVENT(step_at, WRD_GINIT, 0); break; case WRD_GLINE: argc = wrd_split(arg0, args, 7); if(argc < 4) { /* Error: Too few arguments */ break; } for(i = 0; i < 4; i++) { num = atoi(args[i]); WRD_ADDEVENT(step_at, WRD_ARG, num) } WRD_ADDEVENT(step_at, WRD_ARG, atoi(args[4])); WRD_ADDEVENT(step_at, WRD_ARG, atoi(args[5])); WRD_ADDEVENT(step_at, WRD_GLINE, atoi(args[6])); break; case WRD_GMODE: num = atoi(arg0); WRD_ADDEVENT(step_at, WRD_GMODE, num) break; case WRD_GMOVE: argc = wrd_split(arg0, args, 9); if(argc < 6) { /* Error: Too few arguments */ break; } for(i = 0; i < 8; i++) { num = atoi(args[i]); WRD_ADDEVENT(step_at, WRD_ARG, num); } num = atoi(args[i]); WRD_ADDEVENT(step_at, WRD_GMOVE, num) break; case WRD_GON: num = atoi(arg0); WRD_ADDEVENT(step_at, WRD_GON, num); break; case WRD_GSCREEN: if(mimpi_bug_emulation_level >= 1) { for(i = 0; arg0[i]; i++) if(arg0[i] == '.') { WRD_BUGEMUINFO(110); arg0[i] = ','; } } argc = wrd_split(arg0, args, 2); if(argc != 2) { /* Error: Number of arguments miss match */ break; } num = atoi(args[0]); WRD_ADDEVENT(step_at, WRD_ARG, num); num = atoi(args[1]); WRD_ADDEVENT(step_at, WRD_GSCREEN, num); break; case WRD_INKEY: /* FIXME */ num = atoi(arg0); if(num < wrdstep.bar) { /* Error */ break; } WRD_ADDEVENT(step_at, WRD_INKEY, WRD_NOARG); num = (num - wrdstep.bar) * wrdstep.barstep; wrd_delay_cmd(&wrdstep, num, WRD_OUTKEY, WRD_NOARG); break; case WRD_LOCATE: if(strchr(arg0, ';') != NULL) i = 1; /* Swap argument */ else i = 0; argc = wrd_split(arg0, args, 2); if(argc != 2) { /* Error: Number of arguments miss match */ break; } if(i) { num = atoi(args[1]); WRD_ADDEVENT(step_at, WRD_ARG, num); num = atoi(args[0]); WRD_ADDEVENT(step_at, WRD_LOCATE, num); } else { num = atoi(args[0]); WRD_ADDEVENT(step_at, WRD_ARG, num); num = atoi(args[1]); WRD_ADDEVENT(step_at, WRD_LOCATE, num); } break; case WRD_LOOP: /* Not supported */ break; case WRD_MAG: argc = wrd_split(arg0, args, 5); if(!*args[0]) { /* Error: @MAG No file name */ break; } WRD_ADDSTREVENT(step_at, WRD_ARG, args[0]); for(i = 1; i < 3; i++) WRD_ADDEVENT(step_at, WRD_ARG, wrd_atoi(args[i], WRD_NOARG)); WRD_ADDEVENT(step_at, WRD_ARG, wrd_atoi(args[3], 1)); WRD_ADDEVENT(step_at, WRD_MAG, atoi(args[4])); break; case WRD_MIDI: argc = wrd_split(arg0, args, WRD_MAXPARAM); for(i = 0; i < argc; i++) WRD_ADDEVENT(step_at, WRD_ARG, wrd_hexval(args[i])); WRD_ADDEVENT(step_at, WRD_MIDI, atoi(args[i])); break; case WRD_OFFSET: wrdstep.offset = atoi(arg0); break; case WRD_PAL: argc = wrd_split(arg0, args, 17); if(argc != 16 && argc != 17) { /* Error: Number of arguments miss match */ break; } if(argc == 16) { WRD_ADDEVENT(step_at, WRD_ARG, 0); i = 0; } else { if(*args[0] == '#') num = atoi(args[0] + 1); else num = atoi(args[0]); WRD_ADDEVENT(step_at, WRD_ARG, num); i = 1; } for(; i < argc - 1; i++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -