📄 tk_c.c
字号:
/*k_pipe_puts("NEXT");*/ command = ctl_blocking_read(&val); /* Main Loop */ for (;;) { if (command==RC_LOAD_FILE) { /* Read a LoadFile command */ k_pipe_gets(local, sizeof(local)-1); command=play_midi_file(local); } else { if (command==RC_QUIT) { /* if really QUIT */ k_pipe_gets(local, sizeof(local)-1); if (*local == 'Z') return; /* only stop playing..*/ } if (command==RC_CHANGE_VOLUME) /* init volume */ amplification += val; switch(command) { case RC_ERROR: k_pipe_puts("ERRR"); break; case RC_NEXT: k_pipe_puts("NEXT"); break; case RC_REALLY_PREVIOUS: k_pipe_puts("PREV"); break; case RC_TUNE_END: k_pipe_puts("TEND"); break; case RC_RESTART: k_pipe_puts("RSTA"); break; } command = ctl_blocking_read(&val); } }}/* open pipe and fork child process */static void k_pipe_open(void){ int res; res = pipe(pipeAppli); if (res!=0) k_pipe_error("PIPE_APPLI CREATION"); res = pipe(pipePanel); if (res!=0) k_pipe_error("PIPE_PANEL CREATION"); if ((child_pid = fork()) == 0) { /*child*/ close(pipePanel[1]); close(pipeAppli[0]); /* redirect to stdin/out */ dup2(pipePanel[0], fileno(stdin)); close(pipePanel[0]); dup2(pipeAppli[1], fileno(stdout)); close(pipeAppli[1]); } else { close(pipePanel[0]); close(pipeAppli[1]); fpip_in= pipeAppli[0]; fpip_out= pipePanel[1]; }}#if defined(sgi)#include <sys/time.h>#endif#if defined(SOLARIS)#include <sys/filio.h>#endifstatic int k_pipe_read_ready(void){#if defined(sgi) fd_set fds; int cnt; struct timeval timeout; FD_ZERO(&fds); FD_SET(fpip_in, &fds); timeout.tv_sec = timeout.tv_usec = 0; if((cnt = select(fpip_in + 1, &fds, NULL, NULL, &timeout)) < 0) { perror("select"); return -1; } return cnt > 0 && FD_ISSET(fpip_in, &fds) != 0;#else int num; if(ioctl(fpip_in,FIONREAD,&num) < 0) /* see how many chars in buffer. */ { perror("ioctl: FIONREAD"); return -1; } return num;#endif}/***********************************************************************//* PIPE COMUNICATION *//***********************************************************************/static void k_pipe_error(char *st){ fprintf(stderr,"CONNECTION PROBLEM WITH TCL/TK PROCESS IN %s BECAUSE:%s\n", st, strerror(errno)); exit(1);}static void k_pipe_printf(char *fmt, ...){ char buf[256]; va_list ap; va_start(ap, fmt); vsnprintf(buf, sizeof(buf), fmt, ap); k_pipe_puts(buf);}static int line_strlen(char *str){ int len; len = 0; while(*str && *str != '\r' && *str != '\n') { str++; len++; } return len;}static void k_pipe_puts(char *str){ int len; char lf = '\n'; len = line_strlen(str); write(fpip_out, str, len); write(fpip_out, &lf, 1);}int k_pipe_gets(char *str, int maxlen){/* blocking reading */ char *p; int len; /* at least 5 letters (4+\n) command */ len = 0; for (p = str; len < maxlen - 1; p++) { read(fpip_in, p, 1); if (*p == '\n') break; len++; } *p = 0; return len;}/*---------------------------------------------------------------- * shared memory handling *----------------------------------------------------------------*//*ARGSUSED*/static void get_child(int sig){ child_killed = 1;}static void shm_alloc(void){ shmid = shmget(IPC_PRIVATE, sizeof(PanelInfo), IPC_CREAT|0600); if (shmid < 0) { fprintf(stderr, "can't allocate shared memory\n"); exit(1); } semid = semget(IPC_PRIVATE, 1, IPC_CREAT|0600); if (semid < 0) { perror("semget"); shmctl(shmid, IPC_RMID,NULL); exit(1); } /* bin semaphore: only call once at first */ semaphore_V(semid); Panel = (PanelInfo *)shmat(shmid, 0, 0); Panel->reset_panel = 0; Panel->multi_part = 0; Panel->wait_reset = 0;}static void shm_free(int sig){ int status;#if defined(HAVE_UNION_SEMUN) union semun dmy;#else /* Solaris 2.x, BSDI, OSF/1, HPUX */ void *dmy;#endif kill(child_pid, SIGTERM); while(wait(&status) != child_pid) ; memset(&dmy, 0, sizeof(dmy)); /* Shut compiler warning up :-) */ semctl(semid, 0, IPC_RMID, dmy); shmctl(shmid, IPC_RMID, NULL); shmdt((char *)Panel); if (sig != 100) exit(0);}/*---------------------------------------------------------------- * start Tk window panel *----------------------------------------------------------------*/static void start_panel(void){ char *argv[128]; int argc; argc = 0; argv[argc++] = "-f"; argv[argc++] = TKPROGPATH; if (ctl.trace_playing) { argv[argc++] = "-mode"; argv[argc++] = "trace"; } /* call Tk main routine */ Tk_Main(argc, argv, AppInit); exit(0);}/*---------------------------------------------------------------- * initialize Tcl application *----------------------------------------------------------------*/static Tcl_Interp *my_interp;static int AppInit(Tcl_Interp *interp){ my_interp = interp; if (Tcl_Init(interp) == TCL_ERROR) { return TCL_ERROR; } if (Tk_Init(interp) == TCL_ERROR) { return TCL_ERROR; } Tcl_CreateCommand(interp, "TraceCreate", (Tcl_CmdProc*) TraceCreate, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); Tcl_CreateCommand(interp, "TraceUpdate", (Tcl_CmdProc*) TraceUpdate, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); Tcl_CreateCommand(interp, "TraceReset", (Tcl_CmdProc*) TraceReset, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); Tcl_CreateCommand(interp, "ExitAll", (Tcl_CmdProc*) ExitAll, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); Tcl_CreateCommand(interp, "TraceUpdate", (Tcl_CmdProc*) TraceUpdate, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); return TCL_OK;}/*ARGSUSED*/static int ExitAll(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]){ /* window is killed; kill the parent process, too */ kill(getppid(), SIGTERM); for (;;) sleep(1000); return TCL_OK;}/* evaluate Tcl script */static char *v_eval(char *fmt, ...){ char buf[256]; va_list ap; va_start(ap, fmt); vsnprintf(buf, sizeof(buf), fmt, ap); Tcl_Eval(my_interp, buf); va_end(ap); return my_interp->result;}static const char *v_get2(const char *v1, const char *v2){ return Tcl_GetVar2(my_interp, v1, v2, 0);}/*---------------------------------------------------------------- * update Tcl timer / trace window *----------------------------------------------------------------*/#define FRAME_WIN ".body.trace"#define CANVAS_WIN FRAME_WIN ".c"#define BAR_WID 20#define BAR_HGT 130#define WIN_WID (BAR_WID * 16)#define WIN_HGT (BAR_HGT + 11 + 17)#define BAR_HALF_HGT (WIN_HGT / 2 - 11 - 17)/*ARGSUSED*/static int TraceCreate(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]){ int i; v_eval("frame %s -bg black", FRAME_WIN); v_eval("canvas %s -width %d -height %d -bd 0 -bg black " "-highlightthickness 0", CANVAS_WIN, WIN_WID, WIN_HGT); v_eval("pack %s -side top -fill x", CANVAS_WIN); for (i = 0; i < 32; i++) { char *color; v_eval("%s create text 0 0 -anchor n -fill white -text 00 " "-tags prog%d", CANVAS_WIN, i); v_eval("%s create poly 0 0 0 0 0 0 -fill yellow -tags pos%d", CANVAS_WIN, i); color = (ISDRUMCHANNEL(i) || i == 25) ? "red" : "green"; v_eval("%s create rect 0 0 0 0 -fill %s -tags bar%d " "-outline \"\"", CANVAS_WIN, color, i); } v_eval("set Stat(TimerId) -1"); v_eval("TraceReset"); return TCL_OK;}static void trace_bank(int ch, int val){ v_eval("%s itemconfigure bar%d -fill %s", CANVAS_WIN, ch, (val == 128 ? "red" : "green"));}static void trace_prog(int ch, int val){ v_eval("%s itemconfigure prog%d -text %02X", CANVAS_WIN, ch, val);}static void trace_sustain(int ch, int val){ v_eval("%s itemconfigure prog%d -fill %s", CANVAS_WIN, ch, (val == 127 ? "green" : "white"));}static void trace_prog_init(int ch){ int item, yofs, bar, x, y; item = ch; yofs = 0; bar = Panel->multi_part ? BAR_HALF_HGT : BAR_HGT; if (ch >= 16) { ch -= 16; yofs = WIN_HGT / 2; if (!Panel->multi_part) yofs = -500; } x = ch * BAR_WID + BAR_WID/2; y = bar + 11 + yofs; v_eval("%s coords prog%d %d %d", CANVAS_WIN, item, x, y);}static void trace_volume(int ch, int val){ int item, bar, yofs, x1, y1, x2, y2; item = ch; yofs = 0; bar = Panel->multi_part ? BAR_HALF_HGT : BAR_HGT; if (ch >= 16) { yofs = WIN_HGT / 2; ch -= 16; if (!Panel->multi_part) yofs = -500; } x1 = ch * BAR_WID; y1 = bar - 1 + yofs; x2 = x1 + BAR_WID - 1; y2 = y1 - bar * val / 127; v_eval("%s coords bar%d %d %d %d %d", CANVAS_WIN, item, x1, y1, x2, y2);}static void trace_panning(int ch, int val){ int item, bar, yofs; int x, ap, bp; if (val < 0) { v_eval("%s coords pos%d -1 0 -1 0 -1 0", CANVAS_WIN, ch); return; } item = ch; yofs = 0; bar = Panel->multi_part ? BAR_HALF_HGT : BAR_HGT; if (ch >= 16) { yofs = WIN_HGT / 2; ch -= 16; if (!Panel->multi_part) yofs = -500; } x = BAR_WID * ch; ap = BAR_WID * val / 127; bp = BAR_WID - ap - 1; v_eval("%s coords pos%d %d %d %d %d %d %d", CANVAS_WIN, item, ap + x, bar + 5 + yofs, bp + x, bar + 1 + yofs, bp + x, bar + 9 + yofs);}/*ARGSUSED*/static int TraceReset(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]){ int i; semaphore_P(semid); for (i = 0; i < 32; i++) { trace_volume(i, 0); trace_panning(i, -1); trace_prog_init(i); trace_prog(i, 0); trace_sustain(i, 0); Panel->ctotal[i] = 0; Panel->cvel[i] = 0; Panel->v_flags[i] = 0; Panel->c_flags[i] = 0; } semaphore_V(semid); Panel->wait_reset = 0; return TCL_OK;}#define DELTA_VEL 32static void update_notes(void){ int i, imax; semaphore_P(semid); imax = Panel->multi_part ? 32 : 16; for (i = 0; i < imax; i++) { if (Panel->v_flags[i]) { if (Panel->v_flags[i] == FLAG_NOTE_OFF) { Panel->ctotal[i] -= DELTA_VEL; if (Panel->ctotal[i] <= 0) { Panel->ctotal[i] = 0; Panel->v_flags[i] = 0; } } else { Panel->v_flags[i] = 0; } trace_volume(i, Panel->ctotal[i]); } if (Panel->c_flags[i]) { if (Panel->c_flags[i] & FLAG_PAN) trace_panning(i, Panel->channel[i].panning); if (Panel->c_flags[i] & FLAG_BANK) trace_bank(i, Panel->channel[i].bank); if (Panel->c_flags[i] & FLAG_PROG) trace_prog(i, Panel->channel[i].program); if (Panel->c_flags[i] & FLAG_SUST) trace_sustain(i, Panel->channel[i].sustain); Panel->c_flags[i] = 0; } } semaphore_V(semid);}/*ARGSUSED*/static int TraceUpdate(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]){ const char *playing = v_get2("Stat", "Playing"); if (playing && *playing != '0') { if (Panel->reset_panel) { v_eval("TraceReset"); Panel->reset_panel = 0; } if (Panel->last_time != Panel->cur_time) { v_eval("SetTime %d", Panel->cur_time); Panel->last_time = Panel->cur_time; } if (ctl.trace_playing) update_notes(); } v_eval("set Stat(TimerId) [after 50 TraceUpdate]"); return TCL_OK;}static void ctl_event(CtlEvent *e){ switch(e->type) { case CTLE_NOW_LOADING: ctl_file_name((char *)e->v1); break; case CTLE_LOADING_DONE: break; case CTLE_PLAY_START: ctl_total_time((int)e->v1); break; case CTLE_PLAY_END: break; case CTLE_TEMPO: break; case CTLE_METRONOME: break; case CTLE_CURRENT_TIME: ctl_current_time((int)e->v1, (int)e->v2); break; case CTLE_NOTE: ctl_note((int)e->v1, (int)e->v2, (int)e->v3, (int)e->v4); break; case CTLE_MASTER_VOLUME: ctl_master_volume((int)e->v1); break; case CTLE_PROGRAM: ctl_program((int)e->v1, (int)e->v2); break; case CTLE_VOLUME: ctl_volume((int)e->v1, (int)e->v2); break; case CTLE_EXPRESSION: ctl_expression((int)e->v1, (int)e->v2); break; case CTLE_PANNING: ctl_panning((int)e->v1, (int)e->v2); break; case CTLE_SUSTAIN: ctl_sustain((int)e->v1, (int)e->v2); break; case CTLE_PITCH_BEND: ctl_pitch_bend((int)e->v1, (int)e->v2); break; case CTLE_MOD_WHEEL: ctl_pitch_bend((int)e->v1, e->v2 ? -1 : 0x2000); break; case CTLE_CHORUS_EFFECT: break; case CTLE_REVERB_EFFECT: break; case CTLE_LYRIC: ctl_lyric((int)e->v1); break; case CTLE_REFRESH: ctl_refresh(); break; case CTLE_RESET: ctl_reset(); break; }}/* * interface_<id>_loader(); */ControlMode *interface_k_loader(void){ return &ctl;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -