OSDN Git Service

Import UnkoTim212
[timidity41/timidity41.git] / interface / npsyn_c.c
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 #ifdef __GNUC__
78 #include <termios.h>
79 #endif
80
81 #if defined(__W32__) && !defined(__GNUC__)
82 #define HAVE_DOS_KEYBOARD 1
83 #endif
84
85
86 #ifndef HAVE_DOS_KEYBOARD
87 static struct termios initial_settings, new_settings;
88 static int peek_character = -1;
89 #endif
90
91 extern int volatile stream_max_compute;  // play_event() \82Ì compute_data() \82Å\8cv\8eZ\82ð\8b\96\82·\8dÅ\91å\8e\9e\8aÔ
92 extern int seq_quit; // rtsyn_common.c
93
94 static int ctl_open(int using_stdin, int using_stdout);
95 static void ctl_close(void);
96 static int ctl_read(ptr_size_t *valp);
97 static int cmsg(int type, int verbosity_level, const char *fmt, ...);
98 static void ctl_event(CtlEvent *e);
99 static int ctl_pass_playing_list(int n, char *args[]);
100
101 #ifndef HAVE_DOS_KEYBOARD
102 static void init_keybord(void);
103 static void close_keybord(void);
104 static int kbhit(void);
105 static char readch(void);
106 #endif
107
108 /**********************************/
109 /* export the interface functions */
110
111 #define ctl npsyn_control_mode
112
113 ControlMode ctl =
114 {
115     "Windows Named Pipe Synthesizer interface", 'N',
116     "npsyn",
117     1, 0, 0,
118     0,
119     ctl_open,
120     ctl_close,
121     ctl_pass_playing_list,
122     ctl_read,
123     NULL,
124     cmsg,
125     ctl_event
126 };
127
128 static int32 event_time_offset;
129 static FILE *outfp;
130
131 /*ARGSUSED*/
132
133 static int ctl_open(int using_stdin, int using_stdout)
134 {
135   ctl.opened = 1;
136   ctl.flags &= ~(CTLF_LIST_RANDOM | CTLF_LIST_SORT);
137   if (using_stdout)
138     outfp = stderr;
139   else
140     outfp = stdout;
141   return 0;
142 }
143
144 static void ctl_close(void)
145 {
146   fflush(outfp);
147   if (seq_quit == 0) {
148     rtsyn_np_synth_stop();
149     rtsyn_close();
150     seq_quit = ~0;
151   }
152   ctl.opened = 0;
153 }
154
155 static int ctl_read(ptr_size_t *valp)
156 {
157     return RC_NONE;
158 }
159
160 #ifdef IA_W32G_SYN
161 extern void PutsConsoleWnd(char *str);
162 extern int ConsoleWndFlag;
163 #endif
164 static int cmsg(int type, int verbosity_level, const char *fmt, ...)
165 {
166 #ifndef WINDRV
167 #ifndef IA_W32G_SYN
168   va_list ap;
169
170   if ((type == CMSG_TEXT || type == CMSG_INFO || type == CMSG_WARNING) &&
171       ctl.verbosity < verbosity_level)
172     return 0;
173   va_start(ap, fmt);
174   if (type == CMSG_WARNING || type == CMSG_ERROR || type == CMSG_FATAL)
175       dumb_error_count++;
176   if (!ctl.opened)
177     {
178       vfprintf(stderr, fmt, ap);
179       fputs(NLS, stderr);
180     }
181   else
182     {
183       vfprintf(outfp, fmt, ap);
184       fputs(NLS, outfp);
185       fflush(outfp);
186     }
187   va_end(ap);
188 #else
189   if (!ConsoleWndFlag) return 0;
190   {
191     char buffer[1024];
192     va_list ap;
193     va_start(ap, fmt);
194     vsnprintf(buffer, sizeof(buffer), fmt, ap);
195     va_end(ap);
196
197     if ((type == CMSG_TEXT || type == CMSG_INFO || type == CMSG_WARNING) &&
198         ctl.verbosity < verbosity_level)
199       return 0;
200 //    if (type == CMSG_FATAL)
201 //      w32g_msg_box(buffer, "TiMidity Error", MB_OK);
202     PutsConsoleWnd(buffer);
203     PutsConsoleWnd("\n");
204     return 0;
205   }
206 #endif /* !IA_W32G_SYN */
207 #endif /* !WINDRV */
208     return 0;
209 }
210
211 static void ctl_event(CtlEvent *e)
212 {
213 }
214
215 static void doit(void);
216
217 #ifdef IA_W32G_SYN
218 extern void w32g_syn_doit(void);
219 extern int w32g_syn_ctl_pass_playing_list(int n_, char *args_[]);
220
221 static int ctl_pass_playing_list(int n, char *args[])
222 {
223   return w32g_syn_ctl_pass_playing_list(n, args);
224 }
225 #endif /* IA_W32G_SYN */
226
227 #ifndef IA_W32G_SYN
228 static int ctl_pass_playing_list(int n, char *args[])
229 #else
230 // 0: OK, 2: Require to reset.
231 int ctl_pass_playing_list2(int n, char *args[])
232 #endif
233 {
234   TIMECAPS tcaps;
235
236   if ((n < 1) || (n > 2)) {
237       ctl.cmsg(CMSG_WARNING, VERB_NORMAL, "Usage: timidity -iN [Named Pipe Name] SampleTimeMode(1 or 0) \n");
238     return 1;
239   }
240
241   rtsyn_np_set_pipe_name(args[0]);
242   if (n == 1) {
243     rtsyn_sample_time_mode = 0;
244   } else {
245     rtsyn_sample_time_mode = atoi(args[1]);
246   }
247
248 #if !defined(IA_W32G_SYN) && !defined(USE_GTK_GUI)
249   ctl.cmsg(CMSG_WARNING, VERB_NORMAL,
250            "TiMidity starting in Windows Named Pipe Synthesizer mode\n");
251   ctl.cmsg(CMSG_WARNING, VERB_NORMAL,
252            "Usage: timidity -iN [Named Pipe Name] SampleTimeMode(1 or 0) \n");
253   ctl.cmsg(CMSG_WARNING, VERB_NORMAL, "\n");
254   ctl.cmsg(CMSG_WARNING, VERB_NORMAL,
255            "N (Normal mode) M(GM mode) S(GS mode) X(XG mode) G(GM2 mode) D(SD mode) K(KG mode) J(CM mode)\n");
256   ctl.cmsg(CMSG_WARNING, VERB_NORMAL,
257            "(Only in Normal mode, Mode can be changed by MIDI data)\n");
258   ctl.cmsg(CMSG_WARNING, VERB_NORMAL,
259            "m(GM reset) s(GS reset) x(XG reset) g(GM2 reset) d(SD reset) k(KG reset) j(CM reset)\n");
260   ctl.cmsg(CMSG_WARNING, VERB_NORMAL,
261            "\n");
262   ctl.cmsg(CMSG_WARNING, VERB_NORMAL,
263            "Press 'q' key to stop\n");
264 #endif
265
266   rtsyn_init();
267
268 #ifdef FORCE_TIME_PERIOD
269   if (timeGetDevCaps(&tcaps, sizeof(TIMECAPS)) != TIMERR_NOERROR)
270     tcaps.wPeriodMin = 10;
271   timeBeginPeriod(tcaps.wPeriodMin);
272 #endif /* FORCE_TIME_PERIOD */
273
274 #ifdef USE_GTK_GUI
275   twgtk_main();
276 #else
277 #ifdef IA_W32G_SYN
278   if (0 != rtsyn_np_synth_start()) {
279     seq_quit = 0;
280     while (seq_quit == 0) {
281       w32g_syn_doit();
282     }
283     rtsyn_np_synth_stop();
284   }
285 #else
286   if (0 != rtsyn_np_synth_start()) {
287     seq_quit = 0;
288     while (seq_quit == 0) {
289       doit();
290     }
291     rtsyn_np_synth_stop();
292   }
293 #endif /* IA_W32G_SYN */
294 #endif /* USE_GTK_GUI */
295 #ifdef FORCE_TIME_PERIOD
296   timeEndPeriod(tcaps.wPeriodMin);
297 #endif /* FORCE_TIME_PERIOD */
298   rtsyn_close();
299
300   return 0;
301 }
302
303
304 #ifndef IA_W32G_SYN
305
306
307 #ifndef HAVE_DOS_KEYBOARD
308 static void init_keybord(void) {
309   tcgetattr(0, &initial_settings);
310   tcgetattr(0, &new_settings);
311   new_settings.c_lflag &= ~ICANON;
312   new_settings.c_lflag &= ~ECHO;
313   new_settings.c_lflag &= ~ISIG;
314   new_settings.c_cc[VMIN] = 1;
315   new_settings.c_cc[VTIME] = 0;
316   tcsetattr(0, TCSANOW, &new_settings);
317 }
318
319 static void close_keybord(void) {
320   tcsetattr(0, TCSANOW, &initial_settings);
321 }
322
323 static int kbhit(void) {
324   char ch;
325   int nread;
326
327   if (peek_character != -1)
328     return 1;
329   new_settings.c_cc[VMIN] = 0;
330   tcsetattr(0, TCSANOW, &new_settings);
331   nread = read(0, &ch, 1);
332   new_settings.c_cc[VMIN] = 1;
333   tcsetattr(0, TCSANOW, &new_settings);
334
335   if (nread == 1) {
336     peek_character = ch;
337     return 1;
338   }
339   return 0;
340 }
341
342
343 static char readch(void) {
344   char ch;
345   if (peek_character != -1) {
346     ch = peek_character;
347     peek_character = -1;
348     return ch;
349   }
350   read(0, &ch, 1);
351   return ch;
352 }
353 #endif /* !HAVE_DOS_KEYBOARD */
354
355
356 static void doit(void)
357 {
358 #ifndef HAVE_DOS_KEYBOARD
359     init_keybord();
360 #endif
361
362   while (seq_quit == 0) {
363 #ifdef HAVE_DOS_KEYBOARD
364     if (kbhit()) {
365       switch (getch()) {
366 #else
367     if (kbhit()) {
368       switch (readch()) {
369 #endif
370         case 'Q':
371         case 'q':
372           seq_quit = ~0;
373         break;
374         case 'm':
375           rtsyn_gm_reset();
376         break;
377         case 's':
378           rtsyn_gs_reset();
379         break;
380         case 'x':
381           rtsyn_xg_reset();
382         break;
383         case 'g':
384           rtsyn_gm2_reset();
385         break;
386         case 'd':
387           rtsyn_sd_reset();
388         break;
389         case 'k':
390           rtsyn_kg_reset();
391         break;
392         case 'j':
393           rtsyn_cm_reset();
394         break;
395         case 'c':
396           rtsyn_normal_reset();
397         break;
398         case 'M':
399           rtsyn_gm_modeset();
400         break;
401         case 'S':
402           rtsyn_gs_modeset();
403         break;
404         case 'X':
405           rtsyn_xg_modeset();
406         break;
407         case 'G':
408           rtsyn_gm2_modeset();
409         break;
410         case 'D':
411           rtsyn_sd_modeset();
412         break;
413         case 'K':
414           rtsyn_kg_modeset();
415         break;
416         case 'J':
417           rtsyn_cm_modeset();
418         break;
419         case 'N':
420           rtsyn_normal_modeset();
421         break;
422       }
423     }
424     rtsyn_np_play_some_data();
425     if (rtsyn_sample_time_mode == 0)
426       rtsyn_play_calculate();
427     if (intr) seq_quit = ~0;
428     sleep(1);
429   }
430 #ifndef HAVE_DOS_KEYBOARD
431   close_keybord();
432 #endif
433 }
434
435 #endif /* !IA_W32G_SYN */
436
437
438 #ifdef IA_W32G_SYN
439 static int winplaymidi_sleep_level = 2;
440 static DWORD winplaymidi_active_start_time = 0;
441
442
443 void winplaymidi(void) {
444
445   if (winplaymidi_sleep_level < 1) {
446     winplaymidi_sleep_level = 1;
447   }
448   if (0 != rtsyn_buf_check()) {
449       winplaymidi_sleep_level =0;
450   }
451   rtsyn_np_play_some_data();
452   if (winplaymidi_sleep_level == 1) {
453     DWORD ct = GetCurrentTime();
454     if (winplaymidi_active_start_time == 0 || ct < winplaymidi_active_start_time) {
455       winplaymidi_active_start_time = ct;
456     } else if (ct - winplaymidi_active_start_time > 60000) {
457       winplaymidi_sleep_level = 2;
458     }
459   } else if (winplaymidi_sleep_level == 0) {
460     winplaymidi_active_start_time = 0;
461   }
462
463   rtsyn_play_calculate();
464
465   if (winplaymidi_sleep_level >= 2) {
466     Sleep(100);
467   } else if (winplaymidi_sleep_level > 0) {
468     Sleep(1);
469   }
470 }
471 #endif /* IA_W32G_SYN */
472
473
474 /*
475  * interface_<id>_loader();
476  */
477 ControlMode *interface_N_loader(void)
478 {
479   return &ctl;
480 }
481
482