1 /*
2 TiMidity++ -- MIDI to WAVE converter and player
3 Copyright (C) 1999-2004 Masanao Izumo <iz@onicos.co.jp>
4 Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>
5
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.
10
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.
15
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
19
20 npsyn_c.c - Windows synthesizer interface
21 Copyright (c) 2007 Keishi Suenaga <s_keishi@yahoo.co.jp>
22
23 I referenced following sources.
24 alsaseq_c.c - ALSA sequencer server interface
25 Copyright (c) 2000 Takashi Iwai <tiwai@suse.de>
26 readmidi.c
27
28 DESCRIPTION
29 ===========
30
31 This interface provides a Windows MIDI device interface which receives
32 events and plays it in real-time. On this mode, TiMidity works
33 purely as software (real-time) MIDI render.
34
35 For invoking Windows synthesizer interface, run timidity as folows:
36 % timidity -iW (interactively select an Input MIDI device)
37 or
38 % timidity -iW 2 (connect to MIDI device No. 2)
39
40 TiMidity loads instruments dynamically at each time a PRM_CHANGE
41 event is received. It sometimes causes a noise.
42 If you are using a low power machine, invoke timidity as follows:
43 % timidity -s 11025 -iW (set sampling freq. to 11025Hz)
44 or
45 % timidity -EFreverb=0 -iW (disable MIDI reverb effect control)
46
47 TiMidity keeps all loaded instruments during executing.
48
49 To use TiMidity as output device, you need a MIDI loopback device.
50 I use MIDI Yoke. It can freely be obtained MIDI-OX site
51 (http://www.midiox.com).
52 */
53
54 //#define USE_PORTMIDI 1
55 //#define USE_GTK_GUI 1
56
57 #ifdef HAVE_CONFIG_H
58 #include "config.h"
59 #endif /* HAVE_CONFIG_H */
60
61 #ifdef __POCC__
62 #include <sys/types.h>
63 #endif
64
65 #include "rtsyn.h"
66 #ifdef USE_GTK_GUI
67 #include "wsgtk_main.h"
68 #endif
69
70 #ifndef __W32__
71 #include <stdio.h>
72 #include <termios.h>
73 //#include <term.h>
74 #include <unistd.h>
75 #endif
76
77
78 #ifndef __W32__
79 static struct termios initial_settings, new_settings;
80 static int peek_character = -1;
81 #endif
82
83 extern int volatile stream_max_compute; // play_event() �� compute_data() �Ōv�Z�������ő厞��
84 static int seq_quit=~0;
85
86 static int ctl_open(int using_stdin, int using_stdout);
87 static void ctl_close(void);
88 static int ctl_read(int32 *valp);
89 static int cmsg(int type, int verbosity_level, char *fmt, ...);
90 static void ctl_event(CtlEvent *e);
91 static int ctl_pass_playing_list(int n, char *args[]);
92
93 #ifndef __W32__
94 static void init_keybord(void);
95 static void close_keybord(void);
96 static int kbhit(void);
97 static char readch(void);
98 #endif
99
100 /**********************************/
101 /* export the interface functions */
102
103 #define ctl npsyn_control_mode
104
105 ControlMode ctl=
106 {
107 "Windows Named Pipe Synthesizer interface", 'N',
108 "npsyn",
109 1,0,0,
110 0,
111 ctl_open,
112 ctl_close,
113 ctl_pass_playing_list,
114 ctl_read,
115 NULL,
116 cmsg,
117 ctl_event
118 };
119
120 static int32 event_time_offset;
121 static FILE *outfp;
122
123 /*ARGSUSED*/
124
ctl_open(int using_stdin,int using_stdout)125 static int ctl_open(int using_stdin, int using_stdout)
126 {
127 ctl.opened = 1;
128 ctl.flags &= ~(CTLF_LIST_RANDOM|CTLF_LIST_SORT);
129 if (using_stdout)
130 outfp = stderr;
131 else
132 outfp = stdout;
133 return 0;
134 }
135
ctl_close(void)136 static void ctl_close(void)
137 {
138 fflush(outfp);
139 if(seq_quit==0){
140 rtsyn_np_synth_stop();
141 rtsyn_close();
142 seq_quit=~0;
143 }
144 ctl.opened=0;
145 }
146
ctl_read(int32 * valp)147 static int ctl_read(int32 *valp)
148 {
149 return RC_NONE;
150 }
151
152 #ifdef IA_W32G_SYN
153 extern void PutsConsoleWnd(char *str);
154 extern int ConsoleWndFlag;
155 #endif
cmsg(int type,int verbosity_level,char * fmt,...)156 static int cmsg(int type, int verbosity_level, char *fmt, ...)
157 {
158 #ifndef WINDRV
159 #ifndef IA_W32G_SYN
160
161 va_list ap;
162
163 if ((type==CMSG_TEXT || type==CMSG_INFO || type==CMSG_WARNING) &&
164 ctl.verbosity<verbosity_level)
165 return 0;
166 va_start(ap, fmt);
167 if(type == CMSG_WARNING || type == CMSG_ERROR || type == CMSG_FATAL)
168 dumb_error_count++;
169 if (!ctl.opened)
170 {
171 vfprintf(stderr, fmt, ap);
172 fputs(NLS, stderr);
173 }
174 else
175 {
176 vfprintf(outfp, fmt, ap);
177 fputs(NLS, outfp);
178 fflush(outfp);
179 }
180 va_end(ap);
181
182 #else
183 if ( !ConsoleWndFlag ) return 0;
184 {
185 char buffer[1024];
186 va_list ap;
187 va_start(ap, fmt);
188 vsnprintf(buffer, sizeof(buffer), fmt, ap);
189 va_end(ap);
190
191 if((type==CMSG_TEXT || type==CMSG_INFO || type==CMSG_WARNING) &&
192 ctl.verbosity<verbosity_level)
193 return 0;
194 // if(type == CMSG_FATAL)
195 // w32g_msg_box(buffer, "TiMidity Error", MB_OK);
196 PutsConsoleWnd(buffer);
197 PutsConsoleWnd("\n");
198 return 0;
199 }
200 #endif
201 #endif
202 return 0;
203 }
204
ctl_event(CtlEvent * e)205 static void ctl_event(CtlEvent *e)
206 {
207 }
208
209 static void doit(void);
210
211 #ifdef IA_W32G_SYN
212 extern void w32g_syn_doit(void);
213 extern int w32g_syn_ctl_pass_playing_list(int n_, char *args_[]);
214
215
ctl_pass_playing_list(int n,char * args[])216 static int ctl_pass_playing_list(int n, char *args[])
217 {
218 return w32g_syn_ctl_pass_playing_list ( n, args );
219 }
220 #endif
221
222 #ifndef IA_W32G_SYN
ctl_pass_playing_list(int n,char * args[])223 static int ctl_pass_playing_list(int n, char *args[])
224 #else
225 // 0: OK, 2: Require to reset.
226 int ctl_pass_playing_list2(int n, char *args[])
227 #endif
228 {
229 if( (n < 1) || (n > 2) ){
230 ctl.cmsg(CMSG_WARNING, VERB_NORMAL, "Usage: timidity -iN [Named Pipe Name] SampeTimeMode(1 or 0) \n");
231 return 1;
232 }
233
234 rtsyn_np_set_pipe_name(args[0]);
235 if( n==1 ){
236 rtsyn_sample_time_mode = 0;
237 }else{
238 rtsyn_sample_time_mode = atoi(args[1]);
239 }
240
241 #if !defined(IA_W32G_SYN) && !defined(USE_GTK_GUI)
242 ctl.cmsg(CMSG_WARNING, VERB_NORMAL,
243 "TiMidity starting in Windows Named Pipe Synthesizer mode\n");
244 ctl.cmsg(CMSG_WARNING, VERB_NORMAL,
245 "Usage: timidity -iN [Named Pipe Name] SampeTimeMode(1 or 0) \n");
246 ctl.cmsg(CMSG_WARNING, VERB_NORMAL, "\n");
247 ctl.cmsg(CMSG_WARNING, VERB_NORMAL,
248 "N (Normal mode) M(GM mode) S(GS mode) X(XG mode) \n");
249 ctl.cmsg(CMSG_WARNING, VERB_NORMAL,
250 "(Only in Normal mode, Mode can be changed by MIDI data)\n");
251 ctl.cmsg(CMSG_WARNING, VERB_NORMAL,
252 "m(GM reset) s(GS reset) x(XG reset)\n");
253 ctl.cmsg(CMSG_WARNING, VERB_NORMAL,
254 "\n");
255 ctl.cmsg(CMSG_WARNING, VERB_NORMAL,
256 "Press 'q' key to stop\n");
257
258 #endif
259
260 rtsyn_init();
261
262 #ifdef USE_GTK_GUI
263 twgtk_main();
264 #else
265 #ifdef IA_W32G_SYN
266 if(0!=rtsyn_np_synth_start()){
267 seq_quit=0;
268 while(seq_quit==0) {
269 w32g_syn_doit();
270 }
271 rtsyn_np_synth_stop();
272 }
273 #else
274 if(0!=rtsyn_np_synth_start()){
275 seq_quit=0;
276 while(seq_quit==0) {
277 doit();
278 }
279 rtsyn_np_synth_stop();
280 }
281 #endif /* IA_W32G_SYN */
282 #endif /* USE_GTK_GUI */
283 rtsyn_close();
284
285 return 0;
286 }
287
288
289 #ifndef IA_W32G_SYN
290
291
292 #ifndef __W32__
init_keybord(void)293 static void init_keybord(void){
294 tcgetattr(0,&initial_settings);
295 tcgetattr(0,&new_settings);
296 new_settings.c_lflag &= ~ICANON;
297 new_settings.c_lflag &= ~ECHO;
298 new_settings.c_lflag &= ~ISIG;
299 new_settings.c_cc[VMIN] = 1;
300 new_settings.c_cc[VTIME] = 0;
301 tcsetattr(0, TCSANOW, &new_settings);
302 }
303
close_keybord(void)304 static void close_keybord(void){
305 tcsetattr(0, TCSANOW, &initial_settings);
306 }
307
kbhit(void)308 static int kbhit(void){
309 char ch;
310 int nread;
311
312 if(peek_character != -1)
313 return 1;
314 new_settings.c_cc[VMIN]=0;
315 tcsetattr(0,TCSANOW, &new_settings);
316 nread = read(0, &ch, 1);
317 new_settings.c_cc[VMIN]=1;
318 tcsetattr(0,TCSANOW, &new_settings);
319
320 if(nread == 1) {
321 peek_character = ch;
322 return 1;
323 }
324 return 0;
325 }
326
327
readch(void)328 static char readch(void){
329 char ch;
330 if(peek_character != -1){
331 ch = peek_character;
332 peek_character = -1;
333 return ch;
334 }
335 read(0,&ch,1);
336 return ch;
337 }
338 #endif
339
340
doit(void)341 static void doit(void)
342 {
343 #ifndef __W32__
344 init_keybord();
345 #endif
346
347 while(seq_quit==0){
348 #ifdef __W32__
349 if(kbhit()){
350 switch(getch()){
351 #else
352 if(kbhit()){
353 switch(readch()){
354 #endif
355 case 'Q':
356 case 'q':
357 seq_quit=~0;
358 break;
359 case 'm':
360 rtsyn_gm_reset();
361 break;
362 case 's':
363 rtsyn_gs_reset();
364 break;
365 case 'x':
366 rtsyn_xg_reset();
367 break;
368 case 'c':
369 rtsyn_normal_reset();
370 break;
371 case 'M':
372 rtsyn_gm_modeset();
373 break;
374 case 'S':
375 rtsyn_gs_modeset();
376 break;
377 case 'X':
378 rtsyn_xg_modeset();
379 break;
380 case 'N':
381 rtsyn_normal_modeset();
382 break;
383 }
384 }
385 rtsyn_np_play_some_data();
386 if(rtsyn_sample_time_mode == 0)
387 rtsyn_play_calculate();
388 if(intr) seq_quit=~0;
389 sleep(1);
390 }
391 #ifndef __W32__
392 close_keybord();
393 #endif
394 }
395
396 #endif /* !IA_W32G_SYN */
397
398
399 #ifdef IA_W32G_SYN
400 static int winplaymidi_sleep_level = 2;
401 static DWORD winplaymidi_active_start_time = 0;
402
403
404 void winplaymidi(void){
405
406 if ( winplaymidi_sleep_level < 1 ) {
407 winplaymidi_sleep_level = 1;
408 }
409 if( 0 != rtsyn_buf_check() ){
410 winplaymidi_sleep_level =0;
411 }
412 rtsyn_np_play_some_data();
413 if ( winplaymidi_sleep_level == 1 ) {
414 DWORD ct = GetCurrentTime ();
415 if ( winplaymidi_active_start_time == 0 || ct < winplaymidi_active_start_time ) {
416 winplaymidi_active_start_time = ct;
417 } else if ( ct - winplaymidi_active_start_time > 2000 ) {
418 winplaymidi_sleep_level = 2;
419 }
420 } else if ( winplaymidi_sleep_level == 0 ) {
421 winplaymidi_active_start_time = 0;
422 }
423
424 rtsyn_play_calculate();
425
426 if ( winplaymidi_sleep_level >= 2) {
427 Sleep ( 100 );
428 } else if ( winplaymidi_sleep_level > 0 ) {
429 Sleep ( 1 );
430 }
431 }
432 #endif
433
434
435 /*
436 * interface_<id>_loader();
437 */
438 ControlMode *interface_N_loader(void)
439 {
440 return &ctl;
441 }
442
443
444