OSDN Git Service

Imported UnkoTim211
[timidity41/timidity41.git] / interface / portmidisyn_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     portmidisyn_c.c - PortMIDI synthesizer interface
21         Copyright (c) 2003 Keishi Suenaga <s_keishi@mutt.freemail.ne.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 Portmidi 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 PrtMIDI synthesizer interface, run timidity as folows:
36       % timidity -iP    (interactively select an Input MIDI device)
37     or
38       % timidity -iP 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 -iP       (set sampling freq. to 11025Hz)
44     or
45       % timidity -EFreverb=0 -iP    (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     (for windows)
51       I use MIDI Yoke.  It can freely be obtained MIDI-OX site
52       (http://www.midiox.com).
53     (for ALSA)
54       You can easily meke it.  See MIDI router section
55       of Alsa 0.9.0 howto
56       (http://www.suse.de/~mana/alsa090_howto.html#sect05 ).
57 */
58
59 //#define  USE_PORTMIDI 1
60 //#define USE_GTK_GUI 1
61
62 #ifdef HAVE_CONFIG_H
63 #include "config.h"
64 #endif /* HAVE_CONFIG_H */
65
66
67 #include "rtsyn.h"
68 #ifdef USE_GTK_GUI
69 #include "wsgtk_main.h"
70 #endif
71
72 #ifndef __W32__
73 #include <stdio.h>
74 #include <termios.h>
75 //#include <term.h>
76 #include <unistd.h>
77 #endif
78
79
80 #ifndef __W32__
81 static struct termios initial_settings, new_settings;
82 static int peek_character = -1;
83 #endif
84
85 extern int volatile stream_max_compute; // play_event() \82Ì compute_data() \82Å\8cv\8eZ\82ð\8b\96\82·\8dÅ\91å\8e\9e\8aÔ
86
87 ///r // define rtsyn_common.c 
88 // int seq_quit=~0;
89 extern int seq_quit;
90
91
92 static int ctl_open(int using_stdin, int using_stdout);
93 static void ctl_close(void);
94 static int ctl_read(int32 *valp);
95 static int cmsg(int type, int verbosity_level, char *fmt, ...);
96 static void ctl_event(CtlEvent *e);
97 static int ctl_pass_playing_list(int n, char *args[]);
98
99 #ifndef __W32__
100 static void init_keybord(void);
101 static void close_keybord(void);
102 static int kbhit(void);
103 static char readch(void);
104 #endif
105
106 /**********************************/
107 /* export the interface functions */
108
109 #define ctl portmidisyn_control_mode
110
111 ControlMode ctl=
112 {
113     "PortMIDI Synthesizer interface", 'P',
114     "portmidisyn",
115     1,0,0,
116     0,
117     ctl_open,
118     ctl_close,
119     ctl_pass_playing_list,
120     ctl_read,
121     NULL,
122     cmsg,
123     ctl_event
124 };
125
126 static int32 event_time_offset;
127 static FILE *outfp;
128
129 /*ARGSUSED*/
130
131 static int ctl_open(int using_stdin, int using_stdout)
132 {
133         ctl.opened = 1;
134         ctl.flags &= ~(CTLF_LIST_RANDOM|CTLF_LIST_SORT);
135         if (using_stdout)
136                 outfp = stderr;
137         else
138                 outfp = stdout;
139         return 0;
140 }
141
142 static void ctl_close(void)
143 {
144   fflush(outfp);
145   if(seq_quit==0){
146         rtsyn_synth_stop();
147         rtsyn_close();
148         seq_quit=~0;
149   }     
150   ctl.opened=0;
151 }
152
153 static int ctl_read(int32 *valp)
154 {
155     return RC_NONE;
156 }
157
158 #ifdef IA_W32G_SYN
159 extern void PutsConsoleWnd(char *str);
160 extern int ConsoleWndFlag;
161 #endif
162 static int cmsg(int type, int verbosity_level, char *fmt, ...)
163 {
164 #ifndef IA_W32G_SYN
165
166         va_list ap;
167
168   if ((type==CMSG_TEXT || type==CMSG_INFO || type==CMSG_WARNING) &&
169       ctl.verbosity<verbosity_level)
170     return 0;
171   va_start(ap, fmt);
172   if(type == CMSG_WARNING || type == CMSG_ERROR || type == CMSG_FATAL)
173       dumb_error_count++;
174   if (!ctl.opened)
175     {
176       vfprintf(stderr, fmt, ap);
177       fputs(NLS, stderr);
178     }
179   else
180     {
181       vfprintf(outfp, fmt, ap);
182       fputs(NLS, outfp);
183       fflush(outfp);
184     }
185   va_end(ap);
186
187 #else
188         if ( !ConsoleWndFlag ) return 0;
189         {
190     char buffer[1024];
191     va_list ap;
192     va_start(ap, fmt);
193     vsnprintf(buffer, sizeof(buffer), fmt, ap);
194     va_end(ap);
195
196     if((type==CMSG_TEXT || type==CMSG_INFO || type==CMSG_WARNING) &&
197        ctl.verbosity<verbosity_level) 
198         return 0;
199 //    if(type == CMSG_FATAL)
200 //      w32g_msg_box(buffer, "TiMidity Error", MB_OK);
201     PutsConsoleWnd(buffer);
202     PutsConsoleWnd("\n");
203     return 0;
204         }
205 #endif
206
207     return 0;
208 }
209
210 static void ctl_event(CtlEvent *e)
211 {
212 }
213
214 static void doit(void);
215
216 #ifdef IA_W32G_SYN
217 extern void w32g_syn_doit(void);
218 extern int w32g_syn_ctl_pass_playing_list(int n_, char *args_[]);
219
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
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         int i, j,devnum,devok;
235         unsigned int port=0 ;
236         int started;
237         char cbuf[80];
238 #if defined(__W32__) && defined(FORCE_TIME_PERIOD)
239         TIMECAPS tcaps;
240 #endif /* __W32__ && FORCE_TIME_PERIOD */
241
242 rtsyn_get_port_list();
243
244 #ifndef IA_W32G_SYN
245         if(n > MAX_PORT ){
246                 printf( "Usage: timidity -iW [Midi interface No s]\n");
247                 return 1;
248         }
249 #endif
250
251         if(n>0){
252                 port=0;
253                 while(port<n && n!=0){
254                         if( (portID[port] = atoi(args[port]))==0 ){
255                                 n=0;
256                         }else{
257                                 devok=0;
258                                 for(i=0;i<rtsyn_nportlist;i++){
259                                         sscanf( rtsyn_portlist[i],"%d:%s",&devnum,cbuf);
260                                         if(devnum==portID[port]) devok=1;
261                                 }
262                                 if(devok==0){
263                                         n=0;
264 #ifdef IA_W32G_SYN
265                                         {
266                                                 char buff[1024];
267                                                 sprintf ( buff, "MIDI IN Device ID %d is not available. So set a proper ID for the MIDI port %d and restart.", portID[port], port );
268                                                 MessageBox ( NULL, buff, "Error", MB_OK );
269                                                 return 2;
270                                         }
271 #endif
272                                 }
273                         }
274                 port++;
275                 }
276         }
277         if(n==0){
278                 rtsyn_portnumber=0;
279         }else{
280                 rtsyn_portnumber=port;
281         }
282
283 #if !defined(IA_W32G_SYN) && !defined(USE_GTK_GUI)
284         if(n==0){
285                 char cbuf[80];
286                 printf("Whow many ports do you use?(max %d)\n",MAX_PORT);
287                 do{
288                         if (0==scanf("%u",&rtsyn_portnumber)) scanf("%s",cbuf);
289                 }while(rtsyn_portnumber == 0 ||rtsyn_portnumber > MAX_PORT);
290                 printf("\n");
291                 printf("Opening Device drivers:");
292                 printf("Available Midi Input devices:\n");
293
294                 for(i=0;i<rtsyn_nportlist;i++){
295                         printf("%s\n",rtsyn_portlist[i]);
296                 }
297                 for(port=0;port<rtsyn_portnumber;port++){
298                         printf("Keyin Input Device Number of port%d\n",port+1);
299                         do{
300                                 devok=0;
301                                 if (0==scanf("%u",&portID[port])) scanf("%s",cbuf);
302                                 for(i=0;i<rtsyn_nportlist;i++){
303                                         sscanf( rtsyn_portlist[i],"%d:%s",&devnum,cbuf);
304                                         if(devnum==portID[port]) devok=1;
305                                 }
306                         }while(devok==0);
307                         printf("\n");                   
308                 }
309         }
310 #endif
311
312         for(port=0;port<rtsyn_portnumber;port++){
313                 portID[port]=portID[port]-1;
314         }
315
316
317 #if !defined(IA_W32G_SYN) && !defined(USE_GTK_GUI)
318         printf("TiMidity starting in PortMIDI Synthesizer mode\n");
319         printf("Usage: timidity -iP [Midi interface No]\n");
320         printf("\n");
321         printf("N (Normal mode) M(GM mode) S(GS mode) X(XG mode) \n");
322         printf("(Only in Normal mode, Mode can be changed by MIDI data)\n");
323         printf("m(GM reset) s(GS reset) x(XG reset)\n");
324         printf("\n");
325         printf("Press 'q' key to stop\n");
326 #endif
327
328         rtsyn_init();
329
330 #ifdef USE_GTK_GUI
331         twgtk_main();
332 #else 
333 #if defined(__W32__) && defined(FORCE_TIME_PERIOD)
334         if (timeGetDevCaps(&tcaps, sizeof(TIMECAPS)) != TIMERR_NOERROR)
335                 tcaps.wPeriodMin = 10;
336         timeBeginPeriod(tcaps.wPeriodMin);
337 #endif /* __W32__ && FORCE_TIME_PERIOD */
338 #ifdef IA_W32G_SYN
339         if(0!=rtsyn_synth_start()){
340                 seq_quit=0;
341                 while(seq_quit==0) {
342                         w32g_syn_doit();
343                 }
344                 rtsyn_synth_stop();
345         }
346 #else
347         if(0!=rtsyn_synth_start()){
348                 seq_quit=0;
349                 while(seq_quit==0) {
350                         doit();
351                 }
352                 rtsyn_synth_stop();
353         }
354 #endif /* IA_W32G_SYN */
355 #if defined(__W32__) && defined(FORCE_TIME_PERIOD)
356         timeEndPeriod(tcaps.wPeriodMin);
357 #endif /* __W32__ && FORCE_TIME_PERIOD */
358 #endif /* USE_GTK_GUI */
359         rtsyn_close();
360
361         return 0;
362 }
363
364
365 #ifndef IA_W32G_SYN
366
367
368 #ifndef __W32__
369 static void init_keybord(void){
370         tcgetattr(0,&initial_settings);
371         tcgetattr(0,&new_settings);
372         new_settings.c_lflag &= ~ICANON;
373         new_settings.c_lflag &= ~ECHO;
374         new_settings.c_lflag &= ~ISIG;
375         new_settings.c_cc[VMIN] = 1;
376         new_settings.c_cc[VTIME] = 0;
377         tcsetattr(0, TCSANOW, &new_settings);
378 }
379
380 static void close_keybord(void){
381         tcsetattr(0, TCSANOW, &initial_settings);
382 }
383
384 static int kbhit(void){
385         char ch;
386         int nread;
387         
388         if(peek_character != -1)
389                 return 1;
390         new_settings.c_cc[VMIN]=0;
391         tcsetattr(0,TCSANOW, &new_settings);
392         nread = read(0, &ch, 1);
393         new_settings.c_cc[VMIN]=1;
394         tcsetattr(0,TCSANOW, &new_settings);
395         
396         if(nread == 1) {
397                 peek_character = ch;
398                 return 1;
399         }
400         return 0;
401 }
402
403
404 static char readch(void){
405         char ch;
406         if(peek_character != -1){
407                 ch = peek_character;
408                 peek_character = -1;
409                 return ch;
410         }
411         read(0,&ch,1);
412         return ch;
413 }
414 #endif          
415
416
417 static void doit(void)
418 {
419 #ifndef __W32__
420                 init_keybord();
421 #endif
422
423         while(seq_quit==0){
424 #ifdef __W32__
425                 if(kbhit()){
426                         switch(getch()){
427 #else                   
428                 if(kbhit()){
429                         switch(readch()){
430 #endif
431                                 case 'Q':
432                                 case 'q':
433                                         seq_quit=~0;
434                                 break;
435                                 case 'm':
436                                         rtsyn_gm_reset();
437                                 break;
438                                 case 's':
439                                         rtsyn_gs_reset();
440                                 break;
441                                 case 'x':
442                                         rtsyn_xg_reset();
443                                 break;
444                                 case 'c':
445                                         rtsyn_normal_reset();
446                                 break;
447                                 case 'M':
448                                         rtsyn_gm_modeset();
449                                 break;
450                                 case 'S':
451                                         rtsyn_gs_modeset();
452                                 break;
453                                 case 'X':
454                                         rtsyn_xg_modeset();
455                                 break;
456                                 case 'N':
457                                         rtsyn_normal_modeset();
458                                 break;
459                         }
460                 }
461                 rtsyn_play_some_data();
462                 rtsyn_play_calculate();
463                 sleep(0);
464         }
465 #ifndef __W32__
466         close_keybord();
467 #endif
468 }
469
470 #endif /* !IA_W32G_SYN */
471
472
473 #ifdef IA_W32G_SYN
474 static int winplaymidi_sleep_level = 2;
475 static DWORD winplaymidi_active_start_time = 0;
476
477
478 void winplaymidi(void){
479
480         if ( winplaymidi_sleep_level < 1 ) {
481                 winplaymidi_sleep_level = 1;
482         }
483         if( 0 != rtsyn_buf_check() ){
484                         winplaymidi_sleep_level =0;
485         }
486         rtsyn_play_some_data();
487         if ( winplaymidi_sleep_level == 1 ) {
488                 DWORD ct = GetCurrentTime ();
489                 if ( winplaymidi_active_start_time == 0 || ct < winplaymidi_active_start_time ) {
490                         winplaymidi_active_start_time = ct;
491                 } else if ( ct - winplaymidi_active_start_time > 2000 ) {
492                         winplaymidi_sleep_level = 2;
493                 }
494         } else if ( winplaymidi_sleep_level == 0 ) {
495                 winplaymidi_active_start_time = 0;
496         }
497         
498         rtsyn_play_calculate();
499         
500         if ( winplaymidi_sleep_level >= 2) {
501                 Sleep ( 100 );
502         } else if ( winplaymidi_sleep_level > 0 ) {
503                 Sleep ( 1 );
504         }
505 }
506 #endif
507                 
508
509 /*
510  * interface_<id>_loader();
511  */
512 ControlMode *interface_P_loader(void)
513 {
514     return &ctl;
515 }
516
517