2 TiMidity++ -- MIDI to WAVE converter and player
3 Copyright (C) 1999-2018 Masanao Izumo <iz@onicos.co.jp>
4 Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 motif_ctl.c: written by Vincent Pagel (pagel@loria.fr) 10/4/95
22 A motif interface for TIMIDITY: to prevent X redrawings from
23 interfering with the audio computation, I don't use the XtAppAddWorkProc
25 I create a pipe between the timidity process and a Motif interface
26 process forked from the 1st one
28 Copied the Motif file to create a Gtk+ interface.
29 - Glenn Trigg 29 Oct 1998
31 Modified for TiMidity++
32 - Isaku Yamahata 03 Dec 1998
37 #endif /* HAVE_CONFIG_H*/
53 static int ctl_open(int using_stdin, int using_stdout);
54 static void ctl_close(void);
55 static int ctl_pass_playing_list(int number_of_files, char *list_of_files[]);
56 static int ctl_read(ptr_size_t *valp);
57 static int cmsg(int type, int verbosity_level, const char *fmt, ...);
58 static void ctl_event(CtlEvent *e);
60 static void ctl_refresh(void);
61 static void ctl_total_time(int tt);
62 static void ctl_master_volume(int mv);
63 static void ctl_file_name(char *name);
64 static void ctl_current_time(int secs, int voices);
65 static void ctl_note(int status, int channel, int note, int velocity);
66 static void ctl_program(int ch, int val, char *vp);
67 static void ctl_volume(int channel, int val);
68 static void ctl_expression(int channel, int val);
69 static void ctl_panning(int channel, int val);
70 static void ctl_sustain(int channel, int val);
71 static void ctl_pitch_bend(int channel, int val);
72 static void ctl_reset(void);
73 static void ctl_lyric(int);
76 /**********************************************/
77 /* export the interface functions */
79 #define ctl gtk_control_mode
82 "gtk+ interface", 'g',
88 ctl_pass_playing_list,
95 static uint32 cuepoint = 0;
96 static int cuepoint_pending = 0;
99 /***********************************************************************/
100 /* Put controls on the pipe */
101 /***********************************************************************/
103 cmsg(int type, int verbosity_level, const char *fmt, ...)
108 if ((type==CMSG_TEXT || type==CMSG_INFO || type==CMSG_WARNING) &&
109 ctl.verbosity<verbosity_level)
114 vfprintf(stderr, fmt, ap);
115 fprintf(stderr, "\n");
118 vsnprintf(local, sizeof(local), fmt, ap);
119 gtk_pipe_int_write(CMSG_MESSAGE);
120 gtk_pipe_int_write(type);
121 gtk_pipe_string_write(local);
129 ctl_event is stolen from ncurses_c.c
131 static void ctl_event(CtlEvent *e)
135 case CTLE_NOW_LOADING:
136 ctl_file_name((char*) e->v1);
138 case CTLE_LOADING_DONE:
140 case CTLE_PLAY_START:
141 ctl_total_time((int) e->v1);
147 cuepoint_pending = 1;
153 case CTLE_CURRENT_TIME:
154 ctl_current_time((int) e->v1, (int) e->v2);
157 ctl_note((int) e->v1, (int) e->v2, (int) e->v3, (int) e->v4);
159 case CTLE_MASTER_VOLUME:
160 ctl_master_volume((int) e->v1);
163 ctl_program((int) e->v1, (int) e->v2, (char*) e->v3);
166 ctl_volume((int) e->v1, (int) e->v2);
168 case CTLE_EXPRESSION:
169 ctl_expression((int) e->v1, (int) e->v2);
172 ctl_panning((int) e->v1, (int) e->v2);
175 ctl_sustain((int) e->v1, (int) e->v2);
177 case CTLE_PITCH_BEND:
178 ctl_pitch_bend((int) e->v1, (int) e->v2);
181 ctl_pitch_bend((int) e->v1, e->v2);
183 case CTLE_CHORUS_EFFECT:
185 case CTLE_REVERB_EFFECT:
188 ctl_lyric((int) e->v1);
204 /* gtk_pipe_int_write(REFRESH_MESSAGE); */
208 ctl_total_time(int tt)
210 gtk_pipe_int_write(TOTALTIME_MESSAGE);
211 gtk_pipe_int_write(tt);
215 ctl_master_volume(int mv)
217 gtk_pipe_int_write(MASTERVOL_MESSAGE);
218 gtk_pipe_int_write(mv);
222 ctl_file_name(char *name)
224 gtk_pipe_int_write(FILENAME_MESSAGE);
225 gtk_pipe_string_write(name);
229 ctl_current_time(int secs, int voices)
231 gtk_pipe_int_write(CURTIME_MESSAGE);
232 gtk_pipe_int_write(secs);
233 gtk_pipe_int_write(voices);
237 ctl_note(int status, int channel, int note, int velocity)
240 if (!ctl.trace_playing)
242 xl=voice[v].note%(COLS-24);
243 wmove(dftwin, 8+voice[v].channel,xl+3);
244 switch (voice[v].status)
253 wattron(dftwin, A_BOLD);
254 waddch(dftwin, '0'+(10*voice[v].velocity)/128);
255 wattroff(dftwin, A_BOLD);
258 case VOICE_SUSTAINED:
259 waddch(dftwin, '0'+(10*voice[v].velocity)/128);
266 ctl_program(int ch, int val, char *vp)
268 /* if (!ctl.trace_playing)
270 wmove(dftwin, 8+ch, COLS-20);
271 if (ISDRUMCHANNEL(ch))
273 wattron(dftwin, A_BOLD);
274 wprintw(dftwin, "%03d", val);
275 wattroff(dftwin, A_BOLD);
278 wprintw(dftwin, "%03d", val);
283 ctl_volume(int channel, int val)
286 if (!ctl.trace_playing)
288 wmove(dftwin, 8+channel, COLS-16);
289 wprintw(dftwin, "%3d", (val*100)/127);
294 ctl_expression(int channel, int val)
296 /* if (!ctl.trace_playing)
298 wmove(dftwin, 8+channel, COLS-12);
299 wprintw(dftwin, "%3d", (val*100)/127);
304 ctl_panning(int channel, int val)
306 /* if (!ctl.trace_playing)
310 waddstr(dftwin, " ");
312 waddstr(dftwin, " L ");
314 waddstr(dftwin, " R ");
315 else if (val>60 && val<68)
316 waddstr(dftwin, " C ");
321 ctl_sustain(int channel, int val)
324 if (!ctl.trace_playing)
327 if (val) waddch(dftwin, 'S');
328 else waddch(dftwin, ' ');
333 ctl_pitch_bend(int channel, int val)
335 /* if (!ctl.trace_playing)
338 if (val>0x2000) waddch(dftwin, '+');
339 else if (val<0x2000) waddch(dftwin, '-');
340 else waddch(dftwin, ' ');
348 if (!ctl.trace_playing)
352 ctl_program(i, channel[i].program);
353 ctl_volume(i, channel[i].volume);
354 ctl_expression(i, channel[i].expression);
355 ctl_panning(i, channel[i].panning);
356 ctl_sustain(i, channel[i].sustain);
357 ctl_pitch_bend(i, channel[i].pitchbend);
364 ctl_lyric(int lyricid)
367 static char lyric_buf[300];
369 lyric = event2string(lyricid);
372 if (lyric[0] == ME_KARAOKE_LYRIC)
376 if (lyric[1] == '/' || lyric[1] == '\\')
378 snprintf(lyric_buf, sizeof(lyric_buf), "\n%s", lyric + 2);
379 gtk_pipe_int_write(LYRIC_MESSAGE);
380 gtk_pipe_string_write(lyric_buf);
382 else if (lyric[1] == '@')
385 snprintf(lyric_buf, sizeof(lyric_buf), "Language: %s\n", lyric + 3);
386 else if (lyric[2] == 'T')
387 snprintf(lyric_buf, sizeof(lyric_buf), "Title: %s\n", lyric + 3);
389 snprintf(lyric_buf, sizeof(lyric_buf), "%s\n", lyric + 1);
390 gtk_pipe_int_write(LYRIC_MESSAGE);
391 gtk_pipe_string_write(lyric_buf);
395 strncpy(lyric_buf, lyric + 1, sizeof(lyric_buf) - 1);
396 gtk_pipe_int_write(LYRIC_MESSAGE);
397 gtk_pipe_string_write(lyric_buf);
402 strncpy(lyric_buf, lyric + 1, sizeof(lyric_buf) - 1);
403 gtk_pipe_int_write(LYRIC_MESSAGE);
404 gtk_pipe_string_write(lyric_buf);
409 /***********************************************************************/
410 /* OPEN THE CONNECTION */
411 /***********************************************************************/
413 ctl_open(int using_stdin, int using_stdout)
417 /* The child process won't come back from this call */
423 /* Tells the window to disapear */
428 gtk_pipe_int_write(CLOSE_MESSAGE);
435 * Read information coming from the window in a BLOCKING way
438 ctl_blocking_read(ptr_size_t *valp)
442 int new_centiseconds;
444 gtk_pipe_int_read(&command);
446 while (1) /* Loop after pause sleeping to treat other buttons! */
450 case GTK_CHANGE_VOLUME:
451 gtk_pipe_int_read(&new_volume);
452 *valp= new_volume - output_amplification;
453 return RC_CHANGE_VOLUME;
455 case GTK_CHANGE_LOCATOR:
456 gtk_pipe_int_read(&new_centiseconds);
457 *valp= new_centiseconds*(play_mode->rate / 100);
470 return RC_REALLY_PREVIOUS;
476 *valp=play_mode->rate;
480 *valp=play_mode->rate;
501 if (command==GTK_PAUSE) {
502 gtk_pipe_int_read(&command); /* Blocking reading => Sleep ! */
503 if (command==GTK_PAUSE)
504 return RC_NONE; /* Resume where we stopped */
507 fprintf(stderr,"gtk UNKNOWN RC_MESSAGE %i" NLS,command);
514 * Read information coming from the window in a non blocking way
516 static int ctl_read(ptr_size_t *valp)
520 /* We don't wan't to lock on reading */
521 num = gtk_pipe_read_ready();
526 return(ctl_blocking_read(valp));
528 num = ctl_blocking_read(valp);
529 fprintf (stderr, "cmd=%i", num);
535 ctl_pass_playing_list(int number_of_files, char *list_of_files[])
538 char file_to_play[1000];
542 if ( number_of_files > 0 ) {
543 /* Pass the list to the interface */
544 gtk_pipe_int_write(FILE_LIST_MESSAGE);
545 gtk_pipe_int_write(number_of_files);
546 for (i=0;i<number_of_files;i++)
547 gtk_pipe_string_write(list_of_files[i]);
549 /* Ask the interface for a filename to play -> begin to play automatically */
550 gtk_pipe_int_write(NEXT_FILE_MESSAGE);
553 command = ctl_blocking_read(&val);
557 if (command==RC_LOAD_FILE) {
558 /* Read a LoadFile command */
559 gtk_pipe_string_read(file_to_play);
560 command=play_midi_file(file_to_play);
563 if (command==RC_QUIT)
565 if (command==RC_ERROR)
566 command=RC_TUNE_END; /* Launch next file */
571 gtk_pipe_int_write(NEXT_FILE_MESSAGE);
573 case RC_REALLY_PREVIOUS:
574 gtk_pipe_int_write(PREV_FILE_MESSAGE);
577 gtk_pipe_int_write(TUNE_END_MESSAGE);
580 printf("PANIC !!! OTHER COMMAND ERROR ?!?! %i" NLS,command);
583 command = ctl_blocking_read(&val);
590 * interface_<id>_loader();
592 ControlMode *interface_g_loader(void)