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