📄 vt100_c.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 vt_100_c.c - written by Masanao Izumo <mo@goice.co.jp> */#ifdef HAVE_CONFIG_H#include "config.h"#endif /* HAVE_CONFIG_H */#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <ctype.h>#include <sys/types.h>#ifndef NO_STRING_H#include <string.h>#else#include <strings.h>#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif /* HAVE_UNISTD_H */#ifdef HAVE_SYS_TIME_H#include <sys/time.h>#endif /* HAVE_SYS_TIME_H */#include "timidity.h"#include "common.h"#include "instrum.h"#include "playmidi.h"#include "readmidi.h"#include "output.h"#include "controls.h"#include "miditrace.h"#include "vt100.h"#include "timer.h"#include "bitset.h"#include "aq.h"#define SCRMODE_OUT_THRESHOLD 10.0#define CHECK_NOTE_SLEEP_TIME 5.0#define INDICATOR_UPDATE_TIME 0.2static struct{ int prog; int disp_cnt; double last_note_on; char *comm;} instr_comment[MAX_CHANNELS];enum indicator_mode_t{ INDICATOR_DEFAULT, INDICATOR_LYRIC};static int indicator_width = 78;static char *comment_indicator_buffer = NULL;static char *current_indicator_message = NULL;static char *indicator_msgptr = NULL;static int current_indicator_chan = 0;static int next_indicator_chan = -1;static double indicator_last_update;static int indicator_mode = INDICATOR_DEFAULT;static Bitset channel_program_flags[MAX_CHANNELS];static void update_indicator(void);static void reset_indicator(void);static void indicator_chan_update(int ch);static void indicator_set_prog(int ch, int val, char *comm);static void display_lyric(char *lyric, int sep);static void display_title(char *title);static void init_lyric(char *lang);static char *vt100_getline(void);#define LYRIC_WORD_NOSEP 0#define LYRIC_WORD_SEP ' 'static void ctl_refresh(void);static void ctl_total_time(int tt);static void ctl_master_volume(int mv);static void ctl_file_name(char *name);static void ctl_current_time(int ct, int nv);static const char note_name_char[12] ={ 'c', 'C', 'd', 'D', 'e', 'f', 'F', 'g', 'G', 'a', 'A', 'b'};static void ctl_note(int status, int ch, int note, int vel);static void ctl_program(int ch, int val, void *vp);static void ctl_volume(int channel, int val);static void ctl_expression(int channel, int val);static void ctl_panning(int channel, int val);static void ctl_sustain(int channel, int val);static void ctl_pitch_bend(int channel, int val);static void ctl_lyric(uint16 lyricid);static void ctl_reset(void);static int ctl_open(int using_stdin, int using_stdout);static void ctl_close(void);static int ctl_read(int32 *valp);static int cmsg(int type, int verbosity_level, char *fmt, ...);static void ctl_event(CtlEvent *e);/**********************************************//* export the interface functions */#define ctl vt100_control_modeControlMode ctl={ "vt100 interface", 'T', 1,0,0, 0, ctl_open, ctl_close, dumb_pass_playing_list, ctl_read, cmsg, ctl_event};static int selected_channel = -1;static int lyric_row = 6;static int title_row = 6;static int msg_row = 6;static void ctl_refresh(void){ if(ctl.opened) vt100_refresh();}static void ctl_total_time(int tt){ int mins, secs=tt/play_mode->rate; mins=secs/60; secs-=mins*60; vt100_move(4, 6+6+3); vt100_set_attr(VT100_ATTR_BOLD); printf("%3d:%02d ", mins, secs); vt100_reset_attr(); ctl_current_time(0, 0);}static void ctl_master_volume(int mv){ vt100_move(4, VT100_COLS-5); vt100_set_attr(VT100_ATTR_BOLD); printf("%03d %%", mv); vt100_reset_attr(); ctl_refresh();}static void ctl_file_name(char *name){ int i; vt100_move(3, 6); vt100_clrtoeol(); vt100_set_attr(VT100_ATTR_BOLD); fputs(name, stdout); vt100_reset_attr(); if(ctl.trace_playing) { memset(instr_comment, 0, sizeof(instr_comment)); for(i = 0; i < MAX_CHANNELS; i++) instr_comment[i].disp_cnt = 1; indicator_msgptr = NULL; for(i = 0; i < indicator_width; i++) comment_indicator_buffer[i] = ' '; } ctl_refresh();}static void ctl_current_time(int secs, int v){ int mins, bold_flag = 0; static int last_voices = -1, last_secs = -1; if(last_secs != secs) { last_secs=secs; mins=secs/60; secs-=mins*60; vt100_move(4, 6); vt100_set_attr(VT100_ATTR_BOLD); printf("%3d:%02d", mins, secs); bold_flag = 1; } if(!ctl.trace_playing || midi_trace.flush_flag) { if(bold_flag) vt100_reset_attr(); return; } vt100_move(4, 47); if(!bold_flag) vt100_set_attr(VT100_ATTR_BOLD); printf("%3d", v); vt100_reset_attr(); if(last_voices != voices) { last_voices = voices; vt100_move(4, 52); printf("%3d", voices); }}static void ctl_note(int status, int ch, int note, int vel){ int xl, n, c; unsigned int onoff, check, prev_check; Bitset *bitset; if(ch >= 16) return; if (!ctl.trace_playing || midi_trace.flush_flag) return; n = note_name_char[note % 12]; c = (VT100_COLS - 24) / 12 * 12; if(c <= 0) c = 1; xl=note % c; vt100_move(8 + ch, xl + 3); switch(status) { case VOICE_DIE: putc(',', stdout); onoff = 0; break; case VOICE_FREE: putc('.', stdout); onoff = 0; break; case VOICE_ON: vt100_set_attr(VT100_ATTR_REVERSE); putc(n, stdout); vt100_reset_attr(); indicator_chan_update(ch); onoff = 1; break; case VOICE_SUSTAINED: vt100_set_attr(VT100_ATTR_BOLD); putc(n, stdout); vt100_reset_attr(); onoff = 0; break; case VOICE_OFF: putc(n, stdout); onoff = 0; break; } bitset = channel_program_flags + ch; prev_check = has_bitset(bitset); if(prev_check == onoff) { /* Not change program mark */ onoff <<= (8 * sizeof(onoff) - 1); set_bitset(bitset, &onoff, note, 1); return; } onoff <<= (8 * sizeof(onoff) - 1); set_bitset(bitset, &onoff, note, 1); check = has_bitset(bitset); if(prev_check ^ check) { vt100_move(8 + ch, VT100_COLS - 21); if(check) { vt100_set_attr(VT100_ATTR_BOLD); putc('*', stdout); vt100_reset_attr(); } else { putc(' ', stdout); } }}static void ctl_program(int ch, int val, void *comm){ int pr; if(ch >= 16) return; if (!ctl.trace_playing || midi_trace.flush_flag) return; if(channel[ch].special_sample) pr = val = channel[ch].special_sample; else pr = val + progbase; vt100_move(8+ch, VT100_COLS-21); if (ISDRUMCHANNEL(ch)) { vt100_set_attr(VT100_ATTR_BOLD); printf(" %03d", pr); vt100_reset_attr(); } else printf(" %03d", pr); if(comm != NULL) indicator_set_prog(ch, val, (char *)comm);}static void ctl_volume(int ch, int val){ if(ch >= 16) return; if (!ctl.trace_playing || midi_trace.flush_flag) return; vt100_move(8 + ch, VT100_COLS - 16); printf("%3d", (val * 100) / 127);}static void ctl_expression(int ch, int val){ if(ch >= 16) return; if (!ctl.trace_playing || midi_trace.flush_flag) return; vt100_move(8 + ch, VT100_COLS - 12); printf("%3d", (val * 100) / 127);}static void ctl_panning(int ch, int val){ if(ch >= 16) return; if (!ctl.trace_playing || midi_trace.flush_flag) return; vt100_move(8 + ch, VT100_COLS - 8); if (val==NO_PANNING) fputs(" ", stdout); else if (val<5) fputs(" L ", stdout); else if (val>123) fputs(" R ", stdout); else if (val>60 && val<68) fputs(" C ", stdout); else { val = (100*(val-64))/64; /* piss on curses */ if (val<0) { putc('-', stdout); val=-val; } else putc('+', stdout); printf("%02d", val); }}static void ctl_sustain(int ch, int val){ if(ch >= 16) return; if (!ctl.trace_playing || midi_trace.flush_flag) return; vt100_move(8 + ch, VT100_COLS - 4); if (val) putc('S', stdout); else putc(' ', stdout);}static void ctl_pitch_bend(int ch, int val){ if(ch >= 16) return; if (!ctl.trace_playing || midi_trace.flush_flag) return; vt100_move(8+ch, VT100_COLS-2); if (val==-1) putc('=', stdout); else if (val>0x2000) putc('+', stdout); else if (val<0x2000) putc('-', stdout); else putc(' ', stdout);}/*ARGSUSED*/static void ctl_lyric(uint16 lyricid){ char *lyric; lyric = event2string(lyricid); if(lyric != NULL) { /* EAW -- if not a true KAR lyric, ignore \r, treat \n as \r */ if (*lyric != ME_KARAOKE_LYRIC) { while (strchr(lyric, '\r')) { *(strchr(lyric, '\r')) = ' '; } while (strchr(lyric, '\n')) { *(strchr(lyric, '\n')) = '\r'; } } if(*lyric == ME_KARAOKE_LYRIC) { if(lyric[1] == '/') { display_lyric("\n", LYRIC_WORD_NOSEP); display_lyric(lyric + 2, LYRIC_WORD_NOSEP); } else if(lyric[1] == '\\') { display_lyric("\r", LYRIC_WORD_NOSEP); display_lyric(lyric + 2, LYRIC_WORD_NOSEP); } else if(lyric[1] == '@' && lyric[2] == 'T') { if(ctl.trace_playing) { display_lyric("\n", LYRIC_WORD_NOSEP); display_lyric(lyric + 3, LYRIC_WORD_SEP); } else display_title(lyric + 3); } else if(lyric[1] == '@' && lyric[2] == 'L') { init_lyric(lyric + 3); } else display_lyric(lyric + 1, LYRIC_WORD_NOSEP); } else { if(*lyric == ME_CHORUS_TEXT || *lyric == ME_INSERT_TEXT) display_lyric("\r", LYRIC_WORD_SEP); display_lyric(lyric + 1, LYRIC_WORD_SEP); } }}static void ctl_reset(void){ int i,j,c; char *title; if (!ctl.trace_playing) return; c = (VT100_COLS - 24) / 12 * 12; if(c <= 0) c = 1; for (i=0; i<16; i++) { vt100_move(8+i, 3); for (j=0; j<c; j++) putc('.', stdout); if(ISDRUMCHANNEL(i)) ctl_program(i, channel[i].bank, channel_instrum_name(i)); else ctl_program(i, channel[i].program, channel_instrum_name(i)); ctl_volume(i, channel[i].volume); ctl_expression(i, channel[i].expression); ctl_panning(i, channel[i].panning); ctl_sustain(i, channel[i].sustain); if(channel[i].pitchbend == 0x2000 && channel[i].mod.val > 0) ctl_pitch_bend(i, -1); else ctl_pitch_bend(i, channel[i].pitchbend); clear_bitset(channel_program_flags + i, 0, 128); } reset_indicator(); display_lyric(NULL, LYRIC_WORD_NOSEP); if((title = get_midi_title(NULL)) != NULL) display_lyric(title, LYRIC_WORD_NOSEP); ctl_refresh();}/***********************************************************************//*ARGSUSED*/static int ctl_open(int using_stdin, int using_stdout){ int i; vt100_init_screen(); ctl.opened=1; vt100_move(0, 0); fprintf(stdout, "TiMidity++ v%s" NLS, timidity_version); vt100_move(0, VT100_COLS-45); fputs("(C) 1995 Tuukka Toivonen <tt@cgs.fi>", stdout); vt100_move(1,0); fputs("vt100 Interface mode - Written by Masanao Izumo <mo@goice.co.jp>", stdout); vt100_move(3,0); fputs("File:", stdout); vt100_move(4,0); if (ctl.trace_playing) { fputs("Time:", stdout); vt100_move(4,6+6+1); putc('/', stdout); vt100_move(4,40); printf("Voices: /%3d", voices); } else { fputs("Time:", stdout); vt100_move(4,6+6+1); putc('/', stdout); } vt100_move(4,VT100_COLS-20); fputs("Master volume:", stdout); vt100_move(5,0); for (i=0; i<VT100_COLS; i++) putc('_', stdout); if (ctl.trace_playing) { int o; vt100_move(6,0); fputs("Ch ", stdout); o = (VT100_COLS - 24) / 12; for(i = 0; i < o; i++) { int j, c; for(j = 0; j < 12; j++) { c = note_name_char[j]; if(islower(c)) putc(c, stdout); else putc(' ', stdout); } } vt100_move(6,VT100_COLS-20); fputs("Prg Vol Exp Pan S B", stdout); vt100_move(7,0); for (i=0; i<VT100_COLS; i++) putc('-', stdout); for (i=0; i<16; i++) { vt100_move(8+i, 0); printf("%02d ", i+1); init_bitset(channel_program_flags + i, 128); } set_trace_loop_hook(update_indicator); indicator_width = VT100_COLS - 2; if(indicator_width < 40) indicator_width = 40; lyric_row = 2; msg_row = 2; } memset(comment_indicator_buffer = (char *)safe_malloc(indicator_width), 0, indicator_width); memset(current_indicator_message = (char *)safe_malloc(indicator_width), 0, indicator_width); ctl_refresh(); return 0;}static void ctl_close(void){ if (ctl.opened) { ctl.opened = 0; vt100_move(24, 0); vt100_refresh(); }}static int char_count(const char *s, int c){ int n; n = 0; while(*s == c) { n++; s++; } if('0' <= *s && *s <= '9') n = (n - 1) + atoi(s); return n;}static void move_select_channel(int diff){ if(selected_channel != -1) { /* erase the mark */ vt100_move(8 + selected_channel, 0); printf("%02d", selected_channel + 1); } selected_channel += diff; while(selected_channel < 0) selected_channel += 17; while(selected_channel >= 16) selected_channel -= 17; if(selected_channel != -1) { vt100_move(8 + selected_channel, 0); vt100_set_attr(VT100_ATTR_BOLD); printf("%02d", selected_channel + 1); vt100_reset_attr();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -