📄 ncurs_c.c
字号:
/* TiMidity++ -- MIDI to WAVE converter and player Copyright (C) 1999-2004 Masanao Izumo <iz@onicos.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 ncurs_c.c: written by Masanao Izumo <iz@onicos.co.jp> and Aoki Daisuke <dai@y7.net>. This version is merged with title list mode from Aoki Daisuke.*/#ifdef HAVE_CONFIG_H#include "config.h"#endif /* HAVE_CONFIG_H */#include <stdio.h>#if defined(__MINGW32__) && defined(USE_PDCURSES)#define _NO_OLDNAMES 1 /* avoid type mismatch of beep() */#ifndef sleepextern void sleep(unsigned long);#endif /* sleep */#include <stdlib.h>#undef _NO_OLDNAMES#else /* USE_PDCURSES */#include <stdlib.h>#endif#include <stdarg.h>#include <ctype.h>#ifndef NO_STRING_H#include <string.h>#else#include <strings.h>#endif#include <math.h>#ifdef HAVE_UNISTD_H#include <unistd.h>#endif /* HAVE_UNISTD_H */#ifdef __W32__#include <windows.h>#endif /* __W32__ */#ifdef HAVE_NCURSES_H#include <ncurses.h>#elif defined(HAVE_NCURSES_CURSES_H)#include <ncurses/curses.h>#else#include <curses.h>#endif#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 "timer.h"#include "bitset.h"#include "arc.h"#include "aq.h"#ifdef USE_PDCURSESint PDC_set_ctrl_break(bool setting);#endif /* USE_PDCURSES */#define SCREEN_BUGFIX 1 /* FIX the old ncurses bug *//* Define WREFRESH_CACHED if wrefresh isn't clear the internal cache */#define WREFRESH_CACHED 1#ifdef JAPANESE#define MULTIBUTE_CHAR_BUGFIX 1 /* Define to fix multibute overwrite bug */#endif /* JAPANESE */#define MIDI_TITLE#define DISPLAY_MID_MODE#define COMMAND_BUFFER_SIZE 4096#define MINI_BUFF_MORE_C '$'#define LYRIC_OUT_THRESHOLD 10.0#define CHECK_NOTE_SLEEP_TIME 5.0#define NCURS_MIN_LINES 8#define CTL_STATUS_UPDATE -98#define CTL_STATUS_INIT -99#ifndef MIDI_TITLE#undef DISPLAY_MID_MODE#endif /* MIDI_TITLE */#ifdef DISPLAY_MID_MODE#if defined(JAPANESE) && !defined(__WATCOMC__)#include "mid-j.defs"#else#include "mid.defs"#endif /* JAPANESE */#endif /* DISPLAY_MID_MODE */#define MAX_U_PREFIX 256/* GS LCD */#define GS_LCD_MARK_ON -1#define GS_LCD_MARK_OFF -2#define GS_LCD_MARK_CLEAR -3#define GS_LCD_MARK_CHAR '$'static double gslcd_last_display_time;static int gslcd_displayed_flag = 0;#define GS_LCD_CLEAR_TIME 10.0#define GS_LCD_WIDTH 40extern int set_extension_modes(char *flag);static struct{ int mute, bank, bank_lsb, bank_msb, prog; int tt, vol, exp, pan, sus, pitch, wheel; int is_drum; int bend_mark; double last_note_on; char *comm;} ChannelStatus[MAX_CHANNELS];enum indicator_mode_t{ INDICATOR_DEFAULT, INDICATOR_LYRIC, INDICATOR_CMSG};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 double indicator_last_update;static int indicator_mode = INDICATOR_DEFAULT;static int display_velocity_flag = 0;static int display_channels = 16;static Bitset channel_program_flags[MAX_CHANNELS];static Bitset gs_lcd_bits[MAX_CHANNELS];static int is_display_lcd = 1;static int scr_modified_flag = 1; /* delay flush for trace mode */static void update_indicator(void);static void reset_indicator(void);static void indicator_chan_update(int ch);static void display_lyric(char *lyric, int sep);static void display_play_system(int mode);static void display_intonation(int mode);static void display_aq_ratio(void);#define LYRIC_WORD_NOSEP 0#define LYRIC_WORD_SEP ' 'static int ctl_open(int using_stdin, int using_stdout);static void ctl_close(void);static void ctl_pass_playing_list(int number_of_files, char *list_of_files[]);static int ctl_read(int32 *valp);static int cmsg(int type, int verbosity_level, char *fmt, ...);static void ctl_event(CtlEvent *e);static void ctl_refresh(void);static void ctl_help_mode(void);static void ctl_list_mode(int type);static void ctl_total_time(int tt);static void ctl_master_volume(int mv);static void ctl_metronome(int meas, int beat);static void ctl_keysig(int8 k, int ko);static void ctl_tempo(int t, int tr);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_temper_keysig(int8 tk, int ko);static void ctl_temper_type(int ch, int8 tt);static void ctl_mute(int ch, int mute);static void ctl_drumpart(int ch, int is_drum);static void ctl_program(int ch, int prog, char *vp, unsigned int banks);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 update_bend_mark(int ch);static void ctl_pitch_bend(int channel, int val);static void ctl_mod_wheel(int channel, int wheel);static void ctl_lyric(int lyricid);static void ctl_gslcd(int id);static void ctl_reset(void);/**********************************************//* define (LINE,ROW) */#ifdef MIDI_TITLE#define VERSION_LINE 0#define HELP_LINE 1#define FILE_LINE 2#define FILE_TITLE_LINE 3#define TIME_LINE 4#define VOICE_LINE 4#define SEPARATE1_LINE 5#define TITLE_LINE 6#define NOTE_LINE 7#else#define VERSION_LINE 0#define HELP_LINE 1#define FILE_LINE 2#define TIME_LINE 3#define VOICE_LINE 3#define SEPARATE1_LINE 4#define TITLE_LINE 5#define SEPARATE2_LINE 6#define NOTE_LINE 7#endif#define LIST_TITLE_LINES (LINES - TITLE_LINE - 1)/**********************************************//* export the interface functions */#define ctl ncurses_control_modeControlMode ctl={ "ncurses interface", 'n', 1,0,0, 0, ctl_open, ctl_close, ctl_pass_playing_list, ctl_read, cmsg, ctl_event};/***********************************************************************//* foreground/background checks disabled since switching to curses *//* static int in_foreground=1; */enum ctl_ncurs_mode_t{ /* Major modes */ NCURS_MODE_NONE, /* None */ NCURS_MODE_MAIN, /* Normal mode */ NCURS_MODE_TRACE, /* Trace mode */ NCURS_MODE_HELP, /* Help mode */ NCURS_MODE_LIST, /* MIDI list mode */ NCURS_MODE_DIR, /* Directory list mode */ /* Minor modes */ /* Command input mode */ NCURS_MODE_CMD_J, /* Jump */ NCURS_MODE_CMD_L, /* Load file */ NCURS_MODE_CMD_E, /* Extensional mode */ NCURS_MODE_CMD_FSEARCH, /* forward search MIDI file */ NCURS_MODE_CMD_D, /* Change drum channel */ NCURS_MODE_CMD_S, /* Save as */ NCURS_MODE_CMD_R /* Change sample rate */};static int ctl_ncurs_mode = NCURS_MODE_MAIN; /* current mode */static int ctl_ncurs_back = NCURS_MODE_MAIN; /* prev mode to back from help */static int ctl_cmdmode = 0;static int ctl_mode_L_dispstart = 0;static char ctl_mode_L_lastenter[COMMAND_BUFFER_SIZE];static char ctl_mode_SEARCH_lastenter[COMMAND_BUFFER_SIZE];struct double_list_string{ char *string; struct double_list_string *next, *prev;};static struct double_list_string *ctl_mode_L_histh = NULL; /* head */static struct double_list_string *ctl_mode_L_histc = NULL; /* current */static void ctl_ncurs_mode_init(void);static void init_trace_window_chan(int ch);static void init_chan_status(void);static void ctl_cmd_J_move(int diff);static int ctl_cmd_J_enter(void);static void ctl_cmd_L_dir(int move);static int ctl_cmd_L_enter(void);static int selected_channel = -1;/* list_mode */typedef struct _MFnode{ char *file;#ifdef MIDI_TITLE char *title;#endif /* MIDI_TITLE */ struct midi_file_info *infop; struct _MFnode *next;} MFnode;static struct _file_list { int number; MFnode *MFnode_head; MFnode *MFnode_tail;} file_list;static MFnode *MFnode_nth_cdr(MFnode *p, int n);static MFnode *current_MFnode = NULL;#define NC_LIST_MAX 512static int ctl_listmode=1;static int ctl_listmode_max=1; /* > 1 */static int ctl_listmode_play=1; /* > 1 */static int ctl_list_select[NC_LIST_MAX];static int ctl_list_from[NC_LIST_MAX];static int ctl_list_to[NC_LIST_MAX];static void ctl_list_table_init(void);static MFnode *make_new_MFnode_entry(char *file);static void insert_MFnode_entrys(MFnode *mfp, int pos);#define NC_LIST_NEW 1#define NC_LIST_NOW 2#define NC_LIST_PLAY 3#define NC_LIST_SELECT 4#define NC_LIST_NEXT 5#define NC_LIST_PREV 6#define NC_LIST_UP 7#define NC_LIST_DOWN 8#define NC_LIST_UPPAGE 9#define NC_LIST_DOWNPAGE 10/* playing files */static int nc_playfile=0;typedef struct MiniBuffer{ char *buffer; /* base buffer */ int size; /* size of base buffer */ char *text; /* pointer to buffer + (prompt length) */ int maxlen; /* max text len */ int len; /* [0..maxlen] */ int cur; /* cursor pos [0..len] */ int uflag; /* update flag */ int cflag; /* for file completion flag */ MFnode *files; /* completed files */ char *lastcmpl; /* last completed pathname */ MBlockList pool; /* memory pool */ WINDOW *bufwin; /* buffer window */ int x, y; /* window position */ int w, h; /* window size */} MiniBuffer;static MiniBuffer *command_buffer = NULL; /* command buffer */static MiniBuffer *mini_buff_new(int size);static void mini_buff_set(MiniBuffer *b, WINDOW *bufwin, int line, char *prompt);static void mini_buff_clear(MiniBuffer *b);static void mini_buff_refresh(MiniBuffer *b);static int mini_buff_forward(MiniBuffer *b);static int mini_buff_backward(MiniBuffer *b);static int mini_buff_insertc(MiniBuffer *b, int c);static int mini_buff_inserts(MiniBuffer *b, char *s);static int mini_buff_delc(MiniBuffer *b);static char *mini_buff_gets(MiniBuffer *b);static void mini_buff_sets(MiniBuffer *b, char *s);static int mini_buff_len(MiniBuffer *b);static int mini_buff_completion(MiniBuffer *b);static WINDOW *dftwin=0, *msgwin=0, *listwin=0;static void N_ctl_refresh(void){ if(!ctl.opened) return; if(ctl_cmdmode) wmove(dftwin, command_buffer->y, command_buffer->x); else wmove(dftwin, 0,0); wrefresh(dftwin); scr_modified_flag = 0;}static void N_ctl_clrtoeol(int row){ int i; wmove(dftwin, row, 0); for(i = 0; i < COLS; i++) waddch(dftwin, ' '); wmove(dftwin, row, 0); wrefresh(dftwin);}/* werase() is not collectly work if multibyte font is displayed. */static void N_ctl_werase(WINDOW *w){#ifdef WREFRESH_CACHED int x, y, xsize, ysize; getmaxyx(w, ysize, xsize); for(y = 0; y < ysize; y++) { wmove(w, y, 0); for(x = 0; x < xsize; x++) waddch(w, ' '); }#else werase(w);#endif /* WREFRESH_CACHED */ wmove(w, 0, 0); wrefresh(w);}static void N_ctl_scrinit(void){ int i; N_ctl_werase(dftwin); wmove(dftwin, VERSION_LINE,0); waddstr(dftwin, "TiMidity++ "); if (strcmp(timidity_version, "current")) waddch(dftwin, 'v'); waddstr(dftwin, timidity_version); wmove(dftwin, VERSION_LINE,COLS-51); waddstr(dftwin, "(C) 1995,1999-2004 Tuukka Toivonen, Masanao Izumo"); wmove(dftwin, FILE_LINE,0); waddstr(dftwin, "File:");#ifdef MIDI_TITLE wmove(dftwin, FILE_TITLE_LINE,0); waddstr(dftwin, "Title:"); for(i = 0; i < COLS - 6; i++) waddch(dftwin, ' ');#endif wmove(dftwin, TIME_LINE,0); waddstr(dftwin, "Time:"); wmove(dftwin, TIME_LINE,6 + 6); waddch(dftwin, '/'); wmove(dftwin, VOICE_LINE,40); wprintw(dftwin, "Voices: / %3d", voices); wmove(dftwin, VOICE_LINE, COLS-20); waddstr(dftwin, "Master volume:"); wmove(dftwin, SEPARATE1_LINE, 0); for(i = 0; i < COLS; i++)#ifdef MIDI_TITLE waddch(dftwin, '-');#else waddch(dftwin, '_');#endif wmove(dftwin, SEPARATE1_LINE, 0); waddstr(dftwin, "Meas: "); wmove(dftwin, SEPARATE1_LINE, 37); waddstr(dftwin, " Key: "); wmove(dftwin, SEPARATE1_LINE, 58); waddstr(dftwin, " Tempo: "); indicator_width = COLS - 2; if(indicator_width < 40) indicator_width = 40; if(comment_indicator_buffer != NULL) free(comment_indicator_buffer); if(current_indicator_message != NULL) free(current_indicator_message); memset(comment_indicator_buffer = (char *)safe_malloc(indicator_width), 0, indicator_width); memset(current_indicator_message = (char *)safe_malloc(indicator_width), 0, indicator_width); if(ctl.trace_playing) { int o; wmove(dftwin, TITLE_LINE, 0); waddstr(dftwin, "Ch "); o = (COLS - 28) / 12; for(i = 0; i < o; i++) { int j; for(j = 0; j < 12; j++) { int c; c = note_name_char[j]; if(islower(c)) waddch(dftwin, c); else waddch(dftwin, ' '); } } wmove(dftwin, TITLE_LINE, COLS - 20); waddstr(dftwin, "Prg Vol Exp Pan S B");#ifndef MIDI_TITLE wmove(dftwin, SEPARATE2_LINE, 0); for(i = 0; i < COLS; i++) waddch(dftwin, '-');#endif for(i = 0; i < MAX_CHANNELS; i++) { init_bitset(channel_program_flags + i, 128); init_bitset(gs_lcd_bits + i, 128); } } N_ctl_refresh();}static void ctl_refresh(void){ if (scr_modified_flag) N_ctl_refresh();}static void init_trace_window_chan(int ch){ int i, c; if(ch >= display_channels) return; N_ctl_clrtoeol(NOTE_LINE + ch); ctl_mute(ch, CTL_STATUS_UPDATE); waddch(dftwin, ' '); if(ch != selected_channel) { c = (COLS - 28) / 12 * 12; if(c <= 0) c = 1; for(i = 0; i < c; i++) waddch(dftwin, '.'); ctl_temper_type(ch, CTL_STATUS_UPDATE); ctl_program(ch, CTL_STATUS_UPDATE, NULL, 0); ctl_volume(ch, CTL_STATUS_UPDATE); ctl_expression(ch, CTL_STATUS_UPDATE); ctl_panning(ch, CTL_STATUS_UPDATE); ctl_sustain(ch, CTL_STATUS_UPDATE); update_bend_mark(ch); clear_bitset(channel_program_flags + ch, 0, 128); } else { ToneBankElement *prog; ToneBank *bank; int b, type, pr; b = ChannelStatus[ch].bank; pr = ChannelStatus[ch].prog; bank = tonebank[b]; if(bank == NULL || bank->tone[pr].instrument == NULL) { b = 0; bank = tonebank[0]; } if(ChannelStatus[ch].is_drum) { wprintw(dftwin, "Drumset Bank %d=>%d", ChannelStatus[ch].bank + progbase, b + progbase); } else { if(IS_CURRENT_MOD_FILE) { wprintw(dftwin, "MOD %d (%s)", ChannelStatus[ch].prog, ChannelStatus[ch].comm ? ChannelStatus[ch].comm : "Not installed"); } else { prog = &bank->tone[pr]; if(prog->instrument != NULL && !IS_MAGIC_INSTRUMENT(prog->instrument)) { type = prog->instrument->type; /* check instrument alias */ if(b != 0 &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -