1 /* 2 TiMidity++ -- MIDI to WAVE converter and player 3 Copyright (C) 1999-2002 Masanao Izumo <mo@goice.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 21 rtsyn_npipe.c 22 Copyright (c) 2007 Keishi Suenaga <s_keishi@mutt.freemail.ne.jp> 23 24 I referenced following sources. 25 alsaseq_c.c - ALSA sequencer server interface 26 Copyright (c) 2000 Takashi Iwai <tiwai@suse.de> 27 readmidi.c 28 29 */ 30 31 #ifdef HAVE_CONFIG_H 32 #include "config.h" 33 #endif /* HAVE_CONFIG_H */ 34 #include "interface.h" 35 36 #ifdef __POCC__ 37 #include <sys/types.h> 38 #endif //for off_t 39 40 #include <stdio.h> 41 42 #include <stdarg.h> 43 #ifdef HAVE_UNISTD_H 44 #include <unistd.h> 45 #endif 46 #include <sys/types.h> 47 #ifdef TIME_WITH_SYS_TIME 48 #include <sys/time.h> 49 #endif 50 #ifndef NO_STRING_H 51 #include <string.h> 52 #else 53 #include <strings.h> 54 #endif 55 #include <math.h> 56 #include <signal.h> 57 58 #include "server_defs.h" 59 60 #ifdef __W32__ 61 #include <windows.h> 62 #endif 63 64 #include "timidity.h" 65 #include "common.h" 66 #include "controls.h" 67 #include "instrum.h" 68 #include "playmidi.h" 69 #include "readmidi.h" 70 #include "recache.h" 71 #include "output.h" 72 #include "aq.h" 73 #include "timer.h" 74 75 #include "rtsyn.h" 76 77 78 #define PIPE_BUFFER_SIZE (8192) 79 static HANDLE hPipe=NULL; 80 81 82 83 84 static char pipe_name[256]; 85 86 #define EVBUFF_SIZE 512 87 typedef struct rtsyn_evbuf_t{ 88 UINT wMsg; 89 UINT port; 90 DWORD dwParam1; 91 DWORD dwParam2; 92 int exlen; 93 char *exbuffer; 94 } RtsynEvBuf; 95 static RtsynEvBuf evbuf[EVBUFF_SIZE]; 96 static UINT np_evbwpoint=0; 97 static UINT np_evbrpoint=0; 98 static UINT evbsysexpoint; 99 100 static CRITICAL_SECTION mim_np_section; 101 102 int first_ev = 1; 103 static double mim_start_time; 104 105 static char npipe_buffer[2*PIPE_BUFFER_SIZE]; 106 static int npipe_len=0; 107 108 109 110 void rtsyn_np_set_pipe_name(char* name) 111 { 112 strncpy(pipe_name, name, 256-1); 113 pipe_name[256-1]='\0'; 114 } 115 116 static int npipe_input_open(const char *pipe_name) 117 { 118 static OVERLAPPED overlapped; 119 static HANDLE hEvent; 120 char PipeName[256]; 121 DWORD ret; 122 123 124 hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 125 memset( &overlapped, 0, sizeof(OVERLAPPED)); 126 overlapped.hEvent = hEvent; 127 128 sprintf(PipeName, "\\\\.\\pipe\\%s", pipe_name); 129 hPipe = CreateNamedPipe(PipeName, PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED, 130 // PIPE_WAIT| 131 PIPE_READMODE_BYTE |PIPE_TYPE_BYTE, 2, 132 0, PIPE_BUFFER_SIZE, 0, NULL); 133 if (hPipe == INVALID_HANDLE_VALUE) { 134 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Can't create Named Pipe %s : %ld", 135 pipe_name, GetLastError()); 136 return -1; 137 } 138 ret = ConnectNamedPipe(hPipe, &overlapped); 139 if ( (ret == 0) && (ERROR_IO_PENDING!=GetLastError()) ){ 140 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "CnnectNamePipe(%ld) error %s", 141 GetLastError(), pipe_name); 142 CloseHandle(hPipe); 143 hPipe=NULL; 144 return -1; 145 } 146 // WaitForSingleObject(overlapped.hEvent, 1000); 147 CloseHandle(hEvent); 148 return 0; 149 } 150 151 int rtsyn_np_synth_start() 152 { 153 if( 0 != npipe_input_open(pipe_name)) return 0; 154 // npipe_input_open(pipe_name); 155 np_evbwpoint=0; 156 np_evbrpoint=0; 157 InitializeCriticalSection(&mim_np_section); 158 first_ev = 1; 159 npipe_len=0; 160 return ~0; 161 } 162 163 void rtsyn_np_synth_stop() 164 { 165 rtsyn_stop_playing(); 166 // play_mode->close_output(); 167 DeleteCriticalSection(&mim_np_section); 168 CloseHandle(hPipe); 169 hPipe=NULL; 170 return; 171 } 172 173 int rtsyn_np_buf_check(void) 174 { 175 int retval; 176 EnterCriticalSection(&mim_np_section); 177 retval = (np_evbrpoint != np_evbwpoint) ? 0 : -1; 178 LeaveCriticalSection(&mim_np_section); 179 return retval; 180 } 181 182 static int read_pipe_data(void); 183 184 int rtsyn_np_play_some_data(void) 185 { 186 UINT wMsg; 187 DWORD dwParam1; 188 DWORD dwParam2; 189 MidiEvent ev; 190 MidiEvent evm[260]; 191 UINT evbpoint; 192 MIDIHDR *IIMidiHdr; 193 int exlen; 194 char *sysexbuffer; 195 int ne,i,j,chk,played; 196 UINT port; 197 static DWORD pre_time; 198 static DWORD timeoffset; 199 double event_time; 200 201 // rtsyn_play_one_data (0,0x007f3c90, get_current_calender_time()); 202 if ( 0 != read_pipe_data()) return 0; 203 204 played=0; 205 if( -1 == rtsyn_np_buf_check() ){ 206 played=~0; 207 return played; 208 } 209 210 do{ 211 212 213 EnterCriticalSection(&mim_np_section); 214 evbpoint=np_evbrpoint; 215 if (++np_evbrpoint >= EVBUFF_SIZE) 216 np_evbrpoint -= EVBUFF_SIZE; 217 wMsg=evbuf[evbpoint].wMsg; 218 port=evbuf[evbpoint].port; 219 dwParam1=evbuf[evbpoint].dwParam1; 220 dwParam2=evbuf[evbpoint].dwParam2; 221 exlen = evbuf[evbpoint].exlen; 222 sysexbuffer = evbuf[evbpoint].exbuffer; 223 LeaveCriticalSection(&mim_np_section); 224 225 if(rtsyn_sample_time_mode !=1){ 226 if((first_ev == 1) || ( pre_time > dwParam2)){ 227 pre_time=dwParam2; 228 timeoffset=dwParam2; 229 mim_start_time = get_current_calender_time(); 230 first_ev=0; 231 } 232 if(dwParam2 !=0){ 233 event_time= mim_start_time+((double)(dwParam2-timeoffset))*(double)1.0/(double)1000.0; 234 }else{ 235 event_time = get_current_calender_time(); 236 } 237 } 238 239 switch (wMsg) { 240 case RTSYN_NP_DATA: 241 if(rtsyn_sample_time_mode !=1){ 242 rtsyn_play_one_data(port, dwParam1, event_time); 243 }else{ 244 rtsyn_play_one_data(port, dwParam1, dwParam2); 245 } 246 break; 247 case RTSYN_NP_LONGDATA: 248 if(rtsyn_sample_time_mode !=1){ 249 rtsyn_play_one_sysex(sysexbuffer,exlen, event_time); 250 }else{ 251 rtsyn_play_one_sysex(sysexbuffer,exlen, dwParam2); 252 } 253 free(sysexbuffer); 254 break; 255 } 256 pre_time =dwParam2; 257 258 }while( 0==rtsyn_np_buf_check()); 259 260 return played; 261 } 262 263 static void parse_ev(char* buffer, int *len){ 264 UINT wMsg; 265 UINT port; 266 DWORD dwParam1; 267 DWORD dwParam2; 268 int exlen; 269 char *exbuffer; 270 271 char *bp, *sp; 272 UINT evbpoint; 273 RtsynNpEvBuf *npevbuf; 274 275 /* 276 printf ("buhihi %d \n", *len); 277 { 278 int i,j; 279 280 for(j=0; j < 4; j++){ 281 for(i=0; i <16;i++){ 282 printf("%2X:", buffer[j*16+i]); 283 } 284 printf ("\n"); 285 } 286 } 287 */ 288 bp=buffer; 289 sp=buffer; 290 while(1){ 291 npevbuf=(RtsynNpEvBuf*)sp; 292 if(*len >= sizeof(RtsynNpEvBuf)){ 293 wMsg=npevbuf->wMsg; 294 }else{ 295 memmove(buffer, sp, *len); 296 return; 297 } 298 if( ( wMsg != RTSYN_NP_LONGDATA ) && ( wMsg != RTSYN_NP_DATA ) ){ 299 *len = 0; 300 return; 301 } 302 if( wMsg == RTSYN_NP_DATA){ 303 port=npevbuf->port; 304 dwParam1=npevbuf->dwParam1; 305 dwParam2=npevbuf->dwParam2; 306 bp = sp+sizeof(RtsynNpEvBuf); 307 } 308 309 if( wMsg == RTSYN_NP_LONGDATA ){ 310 exlen=npevbuf->exlen; 311 bp = sp+sizeof(RtsynNpEvBuf); 312 313 dwParam2=npevbuf->dwParam2; 314 if (*len >= sizeof(RtsynNpEvBuf)+exlen){ 315 exbuffer= (char *)malloc( sizeof(char) * exlen); 316 memmove(exbuffer,sp+sizeof(RtsynNpEvBuf), exlen); 317 bp += exlen; 318 }else{ 319 memmove(buffer, sp, *len); 320 return; 321 } 322 323 } 324 EnterCriticalSection(&mim_np_section); 325 evbpoint = np_evbwpoint; 326 if (++np_evbwpoint >= EVBUFF_SIZE) 327 np_evbwpoint -= EVBUFF_SIZE; 328 evbuf[evbpoint].wMsg = wMsg; 329 evbuf[evbpoint].port = port; 330 evbuf[evbpoint].dwParam1 = dwParam1; 331 evbuf[evbpoint].dwParam2 = dwParam2; 332 evbuf[evbpoint].exlen = exlen; 333 evbuf[evbpoint].exbuffer = exbuffer; 334 LeaveCriticalSection(&mim_np_section); 335 336 *len -= (bp -sp); 337 sp=bp; 338 if(*len <= 0){ 339 len = 0; 340 return; 341 } 342 }; 343 } 344 345 static int read_pipe_data() 346 { 347 DWORD last_error; 348 DWORD n; 349 DWORD length; 350 351 OVERLAPPED overlapped; 352 HANDLE hEvent; 353 354 if( hPipe == NULL ) return -1; 355 356 // if ( ( 0 == PeekNamedPipe(hPipe,NULL,0,NULL,&length,NULL)) && 357 // (GetLastError()==ERROR_BAD_PIPE) ) return -1; 358 if ( 0 == PeekNamedPipe(hPipe,NULL,0,NULL,&length,NULL)) return -1; 359 if(length == 0) return -1; 360 361 hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 362 memset( &overlapped, 0, sizeof(OVERLAPPED)); 363 overlapped.hEvent = hEvent; 364 npipe_len=0; // not good fix 365 memset(npipe_buffer+npipe_len, 0, PIPE_BUFFER_SIZE-npipe_len); 366 if(length <= PIPE_BUFFER_SIZE - npipe_len){ 367 if( length > 0 ){ 368 ReadFile(hPipe, npipe_buffer+npipe_len,length, &n, &overlapped); 369 last_error = GetLastError(); 370 if(last_error == ERROR_IO_PENDING){ 371 GetOverlappedResult(hPipe, &overlapped,&n,TRUE) ; 372 last_error = GetLastError(); 373 } 374 } 375 }else{ 376 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Named Pipe buffer overlow"); 377 return -1; 378 } 379 if(last_error == ERROR_SUCCESS){ 380 npipe_len += n; 381 parse_ev(npipe_buffer,&npipe_len); 382 } 383 CloseHandle(hEvent); 384 if ( (last_error != ERROR_SUCCESS) && 385 (last_error != ERROR_NOACCESS) ){ 386 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Named Pipe Error: %ld",last_error); 387 return -1; 388 } 389 return 0; 390 } 391 392 void rtsyn_np_pipe_close() 393 { 394 CloseHandle(hPipe); 395 } 396