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     w32g_syn.c: Written by Daisuke Aoki <dai@y7.net>
21 */
22 
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif /* HAVE_CONFIG_H */
26 #include "interface.h"
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <process.h>
31 #include <stddef.h>
32 #include <windows.h>
33 #undef RC_NONE
34 #include <shlobj.h>
35 
36 #if defined(__CYGWIN32__) || defined(__MINGW32__)
37 #ifndef HAVE_NEW_MMSYSTEM
38 #include <commdlg.h>
39 #ifndef TPM_TOPALIGN
40 #define TPM_TOPALIGN	0x0000L	/* for old version of cygwin */
41 #endif
42 #define TIME_ONESHOT 0
43 #define TIME_PERIODIC 1
44 int WINAPI timeSetEvent(UINT uDelay, UINT uResolution,
45 			     void *fptc, DWORD dwUser, UINT fuEvent);
46 int WINAPI timeKillEvent(UINT uTimerID);
47 #endif
48 #else
49 #include <commctrl.h>
50 #endif /* __CYGWIN32__ */
51 
52 #include <commctrl.h>
53 
54 #ifndef NO_STRING_H
55 #include <string.h>
56 #else
57 #include <strings.h>
58 #endif
59 
60 #include <shlobj.h>
61 
62 #include <windowsx.h>	/* There is no <windowsx.h> on CYGWIN.
63 			 * Edit_* and ListBox_* are defined in
64 			 * <windowsx.h>
65 			 */
66 
67 #ifdef TWSYNSRV
68 #include <winsvc.h>
69 #ifdef __DMC__
70 #define SERVICE_ACCEPT_PARAMCHANGE    8
71 #endif
72 //#include <lmcons.h>
73 #include <stdarg.h>
74 #endif
75 
76 #include "timidity.h"
77 #include "common.h"
78 #include "instrum.h"
79 #include "playmidi.h"
80 #include "readmidi.h"
81 #include "output.h"
82 #include "controls.h"
83 
84 #if defined(__CYGWIN32__) || defined(__MINGW32__)
85 #define WIN32GCC
86 WINAPI void InitCommonControls(void);
87 #endif
88 
89 #include "w32g.h"
90 #include "w32g_utl.h"
91 #include "w32g_pref.h"
92 #include "w32g_res.h"
93 
94 #ifdef IA_W32G_SYN
95 
96 typedef struct w32g_syn_t_ {
97 	UINT nid_uID;
98 #ifndef TWSYNSRV
99 	HWND nid_hWnd;
100 	HICON hIcon;
101 #endif
102 	int argc;
103 	char **argv;
104 	HANDLE gui_hThread;
105 	DWORD gui_dwThreadId;
106 	HANDLE syn_hThread;
107 	DWORD syn_dwThreadId;
108 //	int syn_ThreadPriority;
109 	HANDLE hMutex;
110 	int volatile quit_state;
111 } w32g_syn_t;
112 static w32g_syn_t w32g_syn;
113 
114 // �e��ϐ� (^^;;;
115 HINSTANCE hInst = NULL;
116 int PlayerLanguage = LANGUAGE_ENGLISH;
117 int IniFileAutoSave = 1;
118 char *IniFile;
119 char *ConfigFile;
120 char *PlaylistFile;
121 char *PlaylistHistoryFile;
122 char *MidiFileOpenDir;
123 char *ConfigFileOpenDir;
124 char *PlaylistFileOpenDir;
125 int SecondMode = 0;
126 BOOL PosSizeSave = TRUE;
127 int DocMaxSize;
128 char *DocFileExt;
129 int AutoloadPlaylist = 0;
130 int AutosavePlaylist = 0;
131 int SeachDirRecursive = 0;
132 int DocWndIndependent = 0;
133 int DocWndAutoPopup = 0;
134 int TraceGraphicFlag;
135 int PlayerThreadPriority;
136 int MidiPlayerThreadPriority;
137 int MainThreadPriority;
138 int GUIThreadPriority;
139 int TracerThreadPriority;
140 int WrdThreadPriority;
141 int SubWindowMax = 5;
142 int InitMinimizeFlag = 0;
143 int DebugWndStartFlag = 1;
144 int ConsoleWndStartFlag = 0;
145 int ListWndStartFlag = 0;
146 int TracerWndStartFlag = 0;
147 int DocWndStartFlag = 0;
148 int WrdWndStartFlag = 0;
149 int DebugWndFlag = 1;
150 int ConsoleWndFlag = 1;
151 int ListWndFlag = 1;
152 int TracerWndFlag = 0;
153 int DocWndFlag = 1;
154 int WrdWndFlag = 0;
155 int SoundSpecWndFlag = 0;
156 int WrdGraphicFlag;
157 int TraceGraphicFlag;
158 int w32g_auto_output_mode = 0;
159 char *w32g_output_dir = NULL;
160 
161 extern void CmdLineToArgv(LPSTR lpCmdLine, int *argc, CHAR ***argv);
162 
163 static int start_syn_thread ( void );
164 static void WINAPI syn_thread ( void );
165 
166 
167 #ifndef TWSYNSRV
168 
169 // Task tray version here
170 
171 static LRESULT CALLBACK SynWinProc ( HWND hwnd, UINT uMess, WPARAM wParam, LPARAM lParam );
172 static void VersionWnd(HWND hParentWnd);
173 static void TiMidityWnd(HWND hParentWnd);
174 
175 static int w32g_syn_create_win ( void );
176 
177 #define HAVE_SYN_CONSOLE
178 
179 #define MYWM_NOTIFYICON (WM_USER+501)
180 #define MYWM_QUIT (WM_USER+502)
181 #define W32G_SYNWIN_CLASSNAME "TWSYNTH GUI"
182 #define W32G_SYN_TIP "TWSYNTH GUI"
183 
184 // �|�b�v�A�b�v���j���[
185 #define IDM_NOTHING	100
186 #define IDM_QUIT	101
187 #define IDM_START	102
188 // #define IDM_STOP	103
189 #define IDM_SYSTEM_RESET	104
190 #define IDM_GM_SYSTEM_RESET	105
191 #define IDM_GS_SYSTEM_RESET	106
192 #define IDM_XG_SYSTEM_RESET	107
193 #define	IDM_CHANGE_GM_SYSTEM	108
194 #define	IDM_CHANGE_GS_SYSTEM	109
195 #define	IDM_CHANGE_XG_SYSTEM	110
196 #define	IDM_CHANGE_DEFAULT_SYSTEM	111
197 #define IDM_PREFERENCE	112
198 #define IDM_CONSOLE_WND 113
199 #define IDM_PROCESS_PRIORITY_LOWEST		131
200 #define IDM_PROCESS_PRIORITY_BELOW_NORMAL	132
201 #define IDM_PROCESS_PRIORITY_NORMAL	133
202 #define IDM_PROCESS_PRIORITY_ABOVE_NORMAL 134
203 #define IDM_PROCESS_PRIORITY_HIGHEST 135
204 #define IDM_PROCESS_PRIORITY_REALTIME 136
205 #define IDM_SYN_THREAD_PRIORITY_LOWEST		121
206 #define IDM_SYN_THREAD_PRIORITY_BELOW_NORMAL	122
207 #define IDM_SYN_THREAD_PRIORITY_NORMAL	123
208 #define IDM_SYN_THREAD_PRIORITY_ABOVE_NORMAL 124
209 #define IDM_SYN_THREAD_PRIORITY_HIGHEST 125
210 #define IDM_SYN_THREAD_PRIORITY_TIMECRITICAL 137
211 #define IDM_VERSION 126
212 #define IDM_TIMIDITY 127
213 
214 #ifdef HAVE_SYN_CONSOLE
215 HWND hConsoleWnd;
216 void InitConsoleWnd(HWND hParentWnd);
217 #endif // HAVE_SYN_CONSOLE
218 
219 #else  // !TWSYNSRV
220 
221 // Windows service version here
222 
223 #undef HAVE_SYN_CONSOLE
224 
225 static SERVICE_STATUS_HANDLE serviceStatusHandle;
226 static DWORD currentServiceStatus;
227 static const char *serviceName = "Timidity";
228 static const char *serviceDescription = "Realtime synthesize midi message";
229 static const char *regKeyTwSynSrv = "SYSTEM\\CurrentControlSet\\Services\\Timidity";
230 
231 static BOOL InstallService();
232 static BOOL UninstallService();
233 
234 #endif	// !TWSYNSRV
235 
236 
237 #define W32G_SYN_NID_UID 12301
238 #define W32G_MUTEX_NAME "TWSYNTH MUTEX"
239 
240 #define W32G_SYN_MESSAGE_MAX 100
241 #define W32G_SYN_NONE	0
242 #define W32G_SYN_QUIT	10
243 #define W32G_SYN_START	11		// ���t��Ԃֈڍs
244 #define W32G_SYN_STOP	12		// ���t��~��Ԃֈڍs
245 #define W32G_SYN_GS_SYSTEM_RESET 21
246 #define W32G_SYN_XG_SYSTEM_RESET 22
247 #define W32G_SYN_SYSTEM_RESET 23
248 #define W32G_SYN_GM_SYSTEM_RESET 24
249 #define W32G_SYN_CHANGE_GS_SYSTEM 25
250 #define W32G_SYN_CHANGE_XG_SYSTEM 26
251 #define W32G_SYN_CHANGE_GM_SYSTEM 27
252 #define W32G_SYN_CHANGE_DEFAULT_SYSTEM 28
253 
254 
255 typedef struct w32g_syn_message_t_ {
256 	int cmd;
257 } w32g_syn_message_t;
258 static volatile enum { stop, run, quit, none } w32g_syn_status, w32g_syn_status_prev;
259 #ifndef MAX_PORT
260 #define MAX_PORT 4
261 #endif
262 int w32g_syn_id_port[MAX_PORT];
263 int w32g_syn_port_num = 2;
264 
265 extern int win_main(int argc, char **argv);
266 extern int ctl_pass_playing_list2(int n, char *args[]);
267 extern void winplaymidi(void);
268 
269 w32g_syn_message_t msg_loopbuf[W32G_SYN_MESSAGE_MAX];
270 int msg_loopbuf_start = -1;
271 int msg_loopbuf_end = -1;
272 extern int rtsyn_system_mode;
273 HANDLE msg_loopbuf_hMutex = NULL; // �r�������p
274 int syn_AutoStart;	// �V���Z�����N��
275 DWORD processPriority;	// �v���Z�X�̃v���C�I���e�B
276 DWORD syn_ThreadPriority;	// �V���Z�X���b�h�̃v���C�I���e�B
277 
278 extern int volatile stream_max_compute;	// play_event() �� compute_data() �Ōv�Z�������ő厞�ԁB
279 
280 static int w32g_syn_main ( void );
281 static int start_syn_thread ( void );
282 static void WINAPI syn_thread ( void );
283 static void terminate_syn_thread ( void );
284 static int wait_for_termination_of_syn_thread ( void );
285 int w32g_message_set ( int cmd );
286 int w32g_message_get ( w32g_syn_message_t *msg );
287 int w32g_syn_ctl_pass_playing_list ( int n_, char *args_[] );
288 int w32g_syn_do_before_pref_apply ( void );
289 int w32g_syn_do_after_pref_apply ( void );
290 
291 
292 /*
293   �\��
294 	�@���C���X���b�h�FGUI�̃��b�Z�[�W���[�v
295 	�@�V���Z�T�C�U�[�X���b�h�F��������
296 */
297 int WINAPI
WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)298 WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
299 				LPSTR lpCmdLine, int nCmdShow)
300 {
301 	HANDLE hMutex;
302 	int i;
303 
304 	// ���̂Ƃ���Q�d�N���͂ł��Ȃ��悤�ɂ��Ƃ��B
305 	hMutex = OpenMutex ( 0, FALSE, W32G_MUTEX_NAME );
306 	if ( hMutex != NULL ) {
307 		CloseHandle ( hMutex );
308 		return 0;
309 	}
310 	w32g_syn.hMutex = CreateMutex ( NULL, TRUE, W32G_MUTEX_NAME );
311 	if ( w32g_syn.hMutex == NULL ) {
312 		return 0;
313 	}
314 
315 	CmdLineToArgv(lpCmdLine, &w32g_syn.argc, &w32g_syn.argv);
316 
317 #ifdef TWSYNSRV
318 	// Service install and uninstall handling
319 	for (i = 1; i < w32g_syn.argc; i++)
320 	{
321 		if (stricmp(w32g_syn.argv[i], "/INSTALL") == 0)
322 		{
323 			InstallService();
324 
325 			ReleaseMutex ( w32g_syn.hMutex );
326 			CloseHandle ( w32g_syn.hMutex );
327 
328 			return 0;
329 		}
330 		else if (stricmp(w32g_syn.argv[i], "/UNINSTALL") == 0)
331 		{
332 			UninstallService();
333 
334 			ReleaseMutex ( w32g_syn.hMutex );
335 			CloseHandle ( w32g_syn.hMutex );
336 
337 			return 0;
338 		}
339 	}
340 #endif
341 
342 //	wrdt=wrdt_list[0];
343 
344 	hInst = hInstance;
345 	w32g_syn.gui_hThread = GetCurrentThread();
346 	w32g_syn.gui_dwThreadId = GetCurrentThreadId();
347 	w32g_syn.quit_state = 0;
348 
349 	w32g_syn_main ();
350 
351 	ReleaseMutex ( w32g_syn.hMutex );
352 	CloseHandle ( w32g_syn.hMutex );
353 
354 	return 0;
355 }
356 
357 #ifndef TWSYNSRV
358 
359 // Task tray version here
360 
w32g_syn_create_win(void)361 static int w32g_syn_create_win ( void )
362 {
363 	WNDCLASSEX wndclass ;
364 	wndclass.cbSize        = sizeof(WNDCLASSEX);
365 	wndclass.style         = CS_HREDRAW | CS_VREDRAW;
366 	wndclass.lpfnWndProc   = SynWinProc ;
367 	wndclass.cbClsExtra    = 0 ;
368 	wndclass.cbWndExtra    = 0 ;
369 	wndclass.hInstance     = hInst ;
370 	wndclass.hIcon         = w32g_syn.hIcon;
371 	wndclass.hIconSm       = w32g_syn.hIcon;
372 	wndclass.hCursor       = LoadCursor(0,IDC_ARROW) ;
373 	wndclass.hbrBackground = (HBRUSH)(COLOR_SCROLLBAR + 1);
374 	wndclass.lpszMenuName  = NULL;
375 	wndclass.lpszClassName =  W32G_SYNWIN_CLASSNAME;
376 	RegisterClassEx(&wndclass);
377 	w32g_syn.nid_hWnd = CreateWindowEx ( WS_EX_TOOLWINDOW, W32G_SYNWIN_CLASSNAME, 0,
378 		WS_CLIPCHILDREN,
379 		CW_USEDEFAULT,0, 10, 10,0,0,hInst,0 );
380 	if ( w32g_syn.nid_hWnd == NULL ) {
381 		return -1;
382 	}
383 	ShowWindow ( w32g_syn.nid_hWnd, SW_HIDE );
384 	UpdateWindow ( w32g_syn.nid_hWnd );		// �K�v�Ȃ��Ǝv�������ǁB
385 	return 0;
386 }
387 
388 // return
389 // 0 : OK
390 // -1 : FATAL ERROR
w32g_syn_main(void)391 static int w32g_syn_main ( void )
392 {
393 	int i;
394 	MSG msg;
395 
396 	InitCommonControls();
397 
398 	w32g_syn.nid_uID = W32G_SYN_NID_UID;
399 	w32g_syn.nid_hWnd = NULL;
400 	w32g_syn.hIcon = LoadImage(hInst, MAKEINTRESOURCE(IDI_ICON_TIMIDITY), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
401 	processPriority = NORMAL_PRIORITY_CLASS;
402 	syn_ThreadPriority = THREAD_PRIORITY_NORMAL;
403 	for ( i = 0; i <= MAX_PORT; i ++ ) {
404 		w32g_syn_id_port[i] = i + 1;
405 	}
406 
407 	if ( w32g_syn_create_win() ) {
408 			MessageBox ( NULL, "Fatal Error", "ERROR", MB_OK );
409 			return -1;
410 	}
411 
412 	while( GetMessage(&msg,NULL,0,0) ){
413 		if ( msg.message == MYWM_QUIT ) {
414 			if ( w32g_syn.quit_state < 1 ) w32g_syn.quit_state = 1;
415 			if ( hConsoleWnd != NULL ) {
416 				DestroyWindow ( hConsoleWnd );
417 				hConsoleWnd = NULL;
418 			}
419 			DestroyWindow ( w32g_syn.nid_hWnd );
420 			w32g_syn.nid_hWnd = NULL;
421 		}
422 		TranslateMessage(&msg);
423 		DispatchMessage(&msg);
424 	}
425 
426 	while ( w32g_syn.quit_state < 2 ) {
427 		Sleep ( 300 );
428 	}
429 
430 	return 0;
431 }
432 
forced_exit(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime)433 static VOID CALLBACK forced_exit ( HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime )
434 {
435 	exit ( 0 );
436 }
437 
438 // Add the icon into the status area of the task bar.
AddTasktrayIcon(HWND hwnd)439 BOOL AddTasktrayIcon(HWND hwnd)
440 {
441 	BOOL bRes;
442 	NOTIFYICONDATA nid;
443 	nid.cbSize = sizeof ( NOTIFYICONDATA );
444 	nid.hWnd = w32g_syn.nid_hWnd = hwnd;
445 	nid.uID = w32g_syn.nid_uID;
446 	nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
447 	nid.uCallbackMessage = MYWM_NOTIFYICON;
448 	nid.hIcon = w32g_syn.hIcon;
449 	strcpy ( nid.szTip, W32G_SYN_TIP );
450 	bRes = Shell_NotifyIcon ( NIM_ADD, &nid );
451 	return bRes;
452 }
453 
454 // Delete the icon from the status area of the task bar.
DeleteTasktrayIcon(HWND hwnd)455 void DeleteTasktrayIcon(HWND hwnd)
456 {
457 	BOOL bRes;
458 	NOTIFYICONDATA nid;
459 	int i;
460 	nid.cbSize = sizeof ( NOTIFYICONDATA );
461 	nid.hWnd = w32g_syn.nid_hWnd;
462 	nid.uID = w32g_syn.nid_uID;
463 	nid.uFlags = 0;
464 	for ( i = 1; i <= 10; i ++ ) {
465 		bRes = Shell_NotifyIcon ( NIM_DELETE, &nid );
466 		if ( bRes == TRUE )
467 			break;
468 		if ( i >= 10 ) {
469 			MessageBox ( NULL, "Fatal Error", "ERROR", MB_OK );
470 		}
471 	}
472 }
473 
474 static LRESULT CALLBACK
SynWinProc(HWND hwnd,UINT uMess,WPARAM wParam,LPARAM lParam)475 SynWinProc(HWND hwnd, UINT uMess, WPARAM wParam, LPARAM lParam)
476 {
477 	static int have_popupmenu = 0;
478 	switch (uMess) {
479 	case WM_CREATE:
480 		if ( AddTasktrayIcon(hwnd) == FALSE ) {
481 			MessageBox ( NULL, "Fatal Error", "ERROR", MB_OK );
482 			DestroyWindow ( hwnd );
483 			PostQuitMessage ( 0 );
484 			return -1;
485 		}
486 		start_syn_thread ();
487 		break;
488 	case WM_DESTROY:
489 		{
490 			int i;
491 			terminate_syn_thread();
492 			for ( i = 0; i < 4; i ++ ) {
493 				if ( wait_for_termination_of_syn_thread() )
494 					break;
495 			}
496 		}
497 		DeleteTasktrayIcon(hwnd);
498 	  PostQuitMessage ( 0 );
499 	  break;
500 	case MYWM_NOTIFYICON:
501 	{
502 		if ( (UINT)wParam == w32g_syn.nid_uID ) {
503 	    if ( (UINT)lParam == WM_RBUTTONDOWN || (UINT)lParam == WM_LBUTTONDOWN) {
504 				int priority_flag[2][6];
505 				POINT point;
506 				HMENU hMenu, hMenuReset, hMenuChange, hMenuProcessPriority, hMenuSynPriority;
507 
508 				if ( have_popupmenu )
509 					break;
510 				have_popupmenu = 1;
511 
512 				// Process priority check
513 				if ( processPriority == IDLE_PRIORITY_CLASS )
514 					priority_flag[0][0] = MF_CHECKED;
515 				else
516 					priority_flag[0][0] = 0;
517 
518 				if ( processPriority == BELOW_NORMAL_PRIORITY_CLASS )
519 					priority_flag[0][1] = MF_CHECKED;
520 				else
521 					priority_flag[0][1] = 0;
522 
523 				if ( processPriority == NORMAL_PRIORITY_CLASS )
524 					priority_flag[0][2] = MF_CHECKED;
525 				else
526 					priority_flag[0][2] = 0;
527 
528 				if ( processPriority == ABOVE_NORMAL_PRIORITY_CLASS )
529 					priority_flag[0][3] = MF_CHECKED;
530 				else
531 					priority_flag[0][3] = 0;
532 
533 				if ( processPriority == HIGH_PRIORITY_CLASS )
534 					priority_flag[0][4] = MF_CHECKED;
535 				else
536 					priority_flag[0][4] = 0;
537 
538 				if ( processPriority == REALTIME_PRIORITY_CLASS )
539 					priority_flag[0][5] = MF_CHECKED;
540 				else
541 					priority_flag[0][5] = 0;
542 
543 				// Thread priority check
544 				if ( syn_ThreadPriority == THREAD_PRIORITY_LOWEST )
545 					priority_flag[1][0] = MF_CHECKED;
546 				else
547 					priority_flag[1][0] = 0;
548 
549 				if ( syn_ThreadPriority == THREAD_PRIORITY_BELOW_NORMAL )
550 					priority_flag[1][1] = MF_CHECKED;
551 				else
552 					priority_flag[1][1] = 0;
553 
554 				if ( syn_ThreadPriority == THREAD_PRIORITY_NORMAL )
555 					priority_flag[1][2] = MF_CHECKED;
556 				else
557 					priority_flag[1][2] = 0;
558 
559 				if ( syn_ThreadPriority == THREAD_PRIORITY_ABOVE_NORMAL )
560 					priority_flag[1][3] = MF_CHECKED;
561 				else
562 					priority_flag[1][3] = 0;
563 
564 				if ( syn_ThreadPriority == THREAD_PRIORITY_HIGHEST )
565 					priority_flag[1][4] = MF_CHECKED;
566 				else
567 					priority_flag[1][4] = 0;
568 
569 				if ( syn_ThreadPriority == THREAD_PRIORITY_TIME_CRITICAL )
570 					priority_flag[1][5] = MF_CHECKED;
571 				else
572 					priority_flag[1][5] = 0;
573 
574 				hMenu = CreatePopupMenu ();
575 				hMenuReset = CreateMenu ();
576 				hMenuChange = CreateMenu ();
577 				hMenuProcessPriority = CreateMenu ();
578 				hMenuSynPriority = CreateMenu ();
579 				if (PlayerLanguage == LANGUAGE_JAPANESE) {
580 					if ( w32g_syn_status == run ) {
581 						AppendMenu ( hMenu, MF_STRING, IDM_STOP, "�V���Z��~(&S)");
582 					} else if ( w32g_syn_status == stop ) {
583 						AppendMenu ( hMenu, MF_STRING, IDM_START, "�V���Z�J�n(&S)");
584 					} else if ( w32g_syn_status == quit ) {
585 						AppendMenu ( hMenu, MF_STRING | MF_GRAYED, IDM_START, "�I�����c�c");
586 					}
587 					AppendMenu ( hMenu, MF_STRING, IDM_SYSTEM_RESET, "�V�X�e�����Z�b�g(&R)");
588 					switch ( rtsyn_system_mode ) {
589 					case GM_SYSTEM_MODE:
590 						AppendMenu ( hMenuReset, MF_STRING | MF_CHECKED, IDM_GM_SYSTEM_RESET, "GM ���Z�b�g");
591 						AppendMenu ( hMenuReset, MF_STRING, IDM_GS_SYSTEM_RESET, "GS ���Z�b�g");
592 						AppendMenu ( hMenuReset, MF_STRING, IDM_XG_SYSTEM_RESET, "XG ���Z�b�g");
593 						AppendMenu ( hMenuChange, MF_STRING | MF_CHECKED, IDM_CHANGE_GM_SYSTEM, "GM �V�X�e���֕ύX");
594 						AppendMenu ( hMenuChange, MF_STRING, IDM_CHANGE_GS_SYSTEM, "GS �V�X�e���֕ύX");
595 						AppendMenu ( hMenuChange, MF_STRING, IDM_CHANGE_XG_SYSTEM, "XG �V�X�e���֕ύX");
596 						AppendMenu ( hMenuChange, MF_STRING, IDM_CHANGE_DEFAULT_SYSTEM, "�f�t�H���g�̃V�X�e���֕ύX");
597 						break;
598 					case GS_SYSTEM_MODE:
599 						AppendMenu ( hMenuReset, MF_STRING, IDM_GM_SYSTEM_RESET, "GM ���Z�b�g");
600 						AppendMenu ( hMenuReset, MF_STRING | MF_CHECKED, IDM_GS_SYSTEM_RESET, "GS ���Z�b�g");
601 						AppendMenu ( hMenuReset, MF_STRING, IDM_XG_SYSTEM_RESET, "XG ���Z�b�g");
602 						AppendMenu ( hMenuChange, MF_STRING, IDM_CHANGE_GM_SYSTEM, "GM �V�X�e���֕ύX");
603 						AppendMenu ( hMenuChange, MF_STRING | MF_CHECKED, IDM_CHANGE_GS_SYSTEM, "GS �V�X�e���֕ύX");
604 						AppendMenu ( hMenuChange, MF_STRING, IDM_CHANGE_XG_SYSTEM, "XG �V�X�e���֕ύX");
605 						AppendMenu ( hMenuChange, MF_STRING, IDM_CHANGE_DEFAULT_SYSTEM, "�f�t�H���g�̃V�X�e���֕ύX");
606 						break;
607 					case XG_SYSTEM_MODE:
608 						AppendMenu ( hMenuReset, MF_STRING, IDM_GM_SYSTEM_RESET, "GM ���Z�b�g");
609 						AppendMenu ( hMenuReset, MF_STRING, IDM_GS_SYSTEM_RESET, "GS ���Z�b�g");
610 						AppendMenu ( hMenuReset, MF_STRING | MF_CHECKED, IDM_XG_SYSTEM_RESET, "XG ���Z�b�g");
611 						AppendMenu ( hMenuChange, MF_STRING, IDM_CHANGE_GM_SYSTEM, "GM �V�X�e���֕ύX");
612 						AppendMenu ( hMenuChange, MF_STRING, IDM_CHANGE_GS_SYSTEM, "GS �V�X�e���֕ύX");
613 						AppendMenu ( hMenuChange, MF_STRING | MF_CHECKED, IDM_CHANGE_XG_SYSTEM, "XG �V�X�e���֕ύX");
614 						AppendMenu ( hMenuChange, MF_STRING, IDM_CHANGE_DEFAULT_SYSTEM, "�f�t�H���g�̃V�X�e���֕ύX");
615 						break;
616 					default:
617 					case DEFAULT_SYSTEM_MODE:
618 						AppendMenu ( hMenuReset, MF_STRING, IDM_GM_SYSTEM_RESET, "GM ���Z�b�g");
619 						AppendMenu ( hMenuReset, MF_STRING, IDM_GS_SYSTEM_RESET, "GS ���Z�b�g");
620 						AppendMenu ( hMenuReset, MF_STRING, IDM_XG_SYSTEM_RESET, "XG ���Z�b�g");
621 						AppendMenu ( hMenuChange, MF_STRING, IDM_CHANGE_GM_SYSTEM, "GM �V�X�e���֕ύX");
622 						AppendMenu ( hMenuChange, MF_STRING, IDM_CHANGE_GS_SYSTEM, "GS �V�X�e���֕ύX");
623 						AppendMenu ( hMenuChange, MF_STRING, IDM_CHANGE_XG_SYSTEM, "XG �V�X�e���֕ύX");
624 						AppendMenu ( hMenuChange, MF_STRING | MF_CHECKED, IDM_CHANGE_DEFAULT_SYSTEM, "�f�t�H���g�̃V�X�e���֕ύX");
625 						break;
626 					}
627 					AppendMenu ( hMenuProcessPriority, MF_STRING | priority_flag[0][0], IDM_PROCESS_PRIORITY_LOWEST, "�Ⴂ");
628 					AppendMenu ( hMenuProcessPriority, MF_STRING | priority_flag[0][1], IDM_PROCESS_PRIORITY_BELOW_NORMAL, "�����Ⴂ");
629 					AppendMenu ( hMenuProcessPriority, MF_STRING | priority_flag[0][2], IDM_PROCESS_PRIORITY_NORMAL, "����");
630 					AppendMenu ( hMenuProcessPriority, MF_STRING | priority_flag[0][3], IDM_PROCESS_PRIORITY_ABOVE_NORMAL, "��������");
631 					AppendMenu ( hMenuProcessPriority, MF_STRING | priority_flag[0][4], IDM_PROCESS_PRIORITY_HIGHEST, "����");
632 					AppendMenu ( hMenuProcessPriority, MF_SEPARATOR, 0, 0 );
633 					AppendMenu ( hMenuProcessPriority, MF_STRING | priority_flag[0][5], IDM_PROCESS_PRIORITY_REALTIME, "���A���^�C��");
634 					AppendMenu ( hMenuSynPriority, MF_STRING | priority_flag[1][0], IDM_SYN_THREAD_PRIORITY_LOWEST, "�Ⴂ");
635 					AppendMenu ( hMenuSynPriority, MF_STRING | priority_flag[1][1], IDM_SYN_THREAD_PRIORITY_BELOW_NORMAL, "�����Ⴂ");
636 					AppendMenu ( hMenuSynPriority, MF_STRING | priority_flag[1][2], IDM_SYN_THREAD_PRIORITY_NORMAL, "����");
637 					AppendMenu ( hMenuSynPriority, MF_STRING | priority_flag[1][3], IDM_SYN_THREAD_PRIORITY_ABOVE_NORMAL, "��������");
638 					AppendMenu ( hMenuSynPriority, MF_STRING | priority_flag[1][4], IDM_SYN_THREAD_PRIORITY_HIGHEST, "����");
639 					AppendMenu ( hMenuSynPriority, MF_SEPARATOR, 0, 0 );
640 					AppendMenu ( hMenuSynPriority, MF_STRING | priority_flag[1][5], IDM_SYN_THREAD_PRIORITY_TIMECRITICAL, "�^�C���N���e�B�J��");
641 					AppendMenu ( hMenu, MF_SEPARATOR, 0, 0 );
642 					AppendMenu ( hMenu, MF_POPUP, (UINT)hMenuReset, "�e��V�X�e�����Z�b�g" );
643 					AppendMenu ( hMenu, MF_POPUP, (UINT)hMenuChange, "����̃V�X�e���֕ύX" );
644 					AppendMenu ( hMenu, MF_SEPARATOR, 0, 0 );
645 					AppendMenu ( hMenu, MF_POPUP, (UINT)hMenuProcessPriority, "�v���Z�X�v���C�I���e�B�ݒ�" );
646 					AppendMenu ( hMenu, MF_POPUP, (UINT)hMenuSynPriority, "�V���Z�X���b�h�v���C�I���e�B�ݒ�" );
647 					AppendMenu ( hMenu, MF_SEPARATOR, 0, 0 );
648 					AppendMenu ( hMenu, MF_STRING, IDM_PREFERENCE, "�ݒ�(&P)...");
649 					AppendMenu ( hMenu, MF_STRING, IDM_CONSOLE_WND, "�R���\�[��(&C)");
650 					AppendMenu ( hMenu, MF_SEPARATOR, 0, 0 );
651 					AppendMenu ( hMenu, MF_STRING, IDM_VERSION, "�o�[�W�������");
652 					AppendMenu ( hMenu, MF_STRING, IDM_TIMIDITY, "TiMidity++ �ɂ‚���(&A)");
653 					AppendMenu ( hMenu, MF_SEPARATOR, 0, 0 );
654 					AppendMenu ( hMenu, MF_STRING, IDM_QUIT, "�I��(&X)");
655 				} else {
656 					if ( w32g_syn_status == run ) {
657 						AppendMenu ( hMenu, MF_STRING, IDM_STOP, "&Stop synthesizer");
658 					} else if ( w32g_syn_status == stop ) {
659 						AppendMenu ( hMenu, MF_STRING, IDM_START, "&Start synthesizer");
660 					} else if ( w32g_syn_status == quit ) {
661 						AppendMenu ( hMenu, MF_STRING | MF_GRAYED, IDM_START, "Quitting...");
662 					}
663 					AppendMenu ( hMenu, MF_STRING, IDM_SYSTEM_RESET, "System &Reset");
664 					switch ( rtsyn_system_mode ) {
665 					case GM_SYSTEM_MODE:
666 						AppendMenu ( hMenuReset, MF_STRING | MF_CHECKED, IDM_GM_SYSTEM_RESET, "GM Reset");
667 						AppendMenu ( hMenuReset, MF_STRING, IDM_GS_SYSTEM_RESET, "GS Reset");
668 						AppendMenu ( hMenuReset, MF_STRING, IDM_XG_SYSTEM_RESET, "XG Reset");
669 						AppendMenu ( hMenuChange, MF_STRING | MF_CHECKED, IDM_CHANGE_GM_SYSTEM, "Change GM system");
670 						AppendMenu ( hMenuChange, MF_STRING, IDM_CHANGE_GS_SYSTEM, "Change GS system");
671 						AppendMenu ( hMenuChange, MF_STRING, IDM_CHANGE_XG_SYSTEM, "Change XG system");
672 						AppendMenu ( hMenuChange, MF_STRING, IDM_CHANGE_DEFAULT_SYSTEM, "Change default system");
673 						break;
674 					case GS_SYSTEM_MODE:
675 						AppendMenu ( hMenuReset, MF_STRING, IDM_GM_SYSTEM_RESET, "GM Reset");
676 						AppendMenu ( hMenuReset, MF_STRING | MF_CHECKED, IDM_GS_SYSTEM_RESET, "GS Reset");
677 						AppendMenu ( hMenuReset, MF_STRING, IDM_XG_SYSTEM_RESET, "XG Reset");
678 						AppendMenu ( hMenuChange, MF_STRING, IDM_CHANGE_GM_SYSTEM, "Change GM system");
679 						AppendMenu ( hMenuChange, MF_STRING | MF_CHECKED, IDM_CHANGE_GS_SYSTEM, "Change GS system");
680 						AppendMenu ( hMenuChange, MF_STRING, IDM_CHANGE_XG_SYSTEM, "Change XG system");
681 						AppendMenu ( hMenuChange, MF_STRING, IDM_CHANGE_DEFAULT_SYSTEM, "Change default system");
682 						break;
683 					case XG_SYSTEM_MODE:
684 						AppendMenu ( hMenuReset, MF_STRING, IDM_GM_SYSTEM_RESET, "GM Reset");
685 						AppendMenu ( hMenuReset, MF_STRING, IDM_GS_SYSTEM_RESET, "GS Reset");
686 						AppendMenu ( hMenuReset, MF_STRING | MF_CHECKED, IDM_XG_SYSTEM_RESET, "XG Reset");
687 						AppendMenu ( hMenuChange, MF_STRING, IDM_CHANGE_GM_SYSTEM, "Change GM system");
688 						AppendMenu ( hMenuChange, MF_STRING, IDM_CHANGE_GS_SYSTEM, "Change GS system");
689 						AppendMenu ( hMenuChange, MF_STRING | MF_CHECKED, IDM_CHANGE_XG_SYSTEM, "Change XG system");
690 						AppendMenu ( hMenuChange, MF_STRING, IDM_CHANGE_DEFAULT_SYSTEM, "Change default system");
691 						break;
692 					default:
693 					case DEFAULT_SYSTEM_MODE:
694 						AppendMenu ( hMenuReset, MF_STRING, IDM_GM_SYSTEM_RESET, "GM Reset");
695 						AppendMenu ( hMenuReset, MF_STRING, IDM_GS_SYSTEM_RESET, "GS Reset");
696 						AppendMenu ( hMenuReset, MF_STRING, IDM_XG_SYSTEM_RESET, "XG Reset");
697 						AppendMenu ( hMenuChange, MF_STRING, IDM_CHANGE_GM_SYSTEM, "Change GM system");
698 						AppendMenu ( hMenuChange, MF_STRING, IDM_CHANGE_GS_SYSTEM, "Change GS system");
699 						AppendMenu ( hMenuChange, MF_STRING, IDM_CHANGE_XG_SYSTEM, "Change XG system");
700 						AppendMenu ( hMenuChange, MF_STRING | MF_CHECKED, IDM_CHANGE_DEFAULT_SYSTEM, "Change default system");
701 						break;
702 					}
703 					AppendMenu ( hMenuProcessPriority, MF_STRING | priority_flag[0][0], IDM_PROCESS_PRIORITY_LOWEST, "lowest");
704 					AppendMenu ( hMenuProcessPriority, MF_STRING | priority_flag[0][1], IDM_PROCESS_PRIORITY_BELOW_NORMAL, "below normal");
705 					AppendMenu ( hMenuProcessPriority, MF_STRING | priority_flag[0][2], IDM_PROCESS_PRIORITY_NORMAL, "normal");
706 					AppendMenu ( hMenuProcessPriority, MF_STRING | priority_flag[0][3], IDM_PROCESS_PRIORITY_ABOVE_NORMAL, "above normal");
707 					AppendMenu ( hMenuProcessPriority, MF_STRING | priority_flag[0][4], IDM_PROCESS_PRIORITY_HIGHEST, "highest");
708 					AppendMenu ( hMenuProcessPriority, MF_SEPARATOR, 0, 0 );
709 					AppendMenu ( hMenuProcessPriority, MF_STRING | priority_flag[0][5], IDM_PROCESS_PRIORITY_REALTIME, "realtime");
710 					AppendMenu ( hMenuSynPriority, MF_STRING | priority_flag[1][0], IDM_SYN_THREAD_PRIORITY_LOWEST, "lowest");
711 					AppendMenu ( hMenuSynPriority, MF_STRING | priority_flag[1][1], IDM_SYN_THREAD_PRIORITY_BELOW_NORMAL, "below normal");
712 					AppendMenu ( hMenuSynPriority, MF_STRING | priority_flag[1][2], IDM_SYN_THREAD_PRIORITY_NORMAL, "normal");
713 					AppendMenu ( hMenuSynPriority, MF_STRING | priority_flag[1][3], IDM_SYN_THREAD_PRIORITY_ABOVE_NORMAL, "above normal");
714 					AppendMenu ( hMenuSynPriority, MF_STRING | priority_flag[1][4], IDM_SYN_THREAD_PRIORITY_HIGHEST, "highest");
715 					AppendMenu ( hMenuSynPriority, MF_SEPARATOR, 0, 0 );
716 					AppendMenu ( hMenuSynPriority, MF_STRING | priority_flag[1][5], IDM_SYN_THREAD_PRIORITY_TIMECRITICAL, "time critical");
717 					AppendMenu ( hMenu, MF_SEPARATOR, 0, 0 );
718 					AppendMenu ( hMenu, MF_POPUP, (UINT)hMenuReset, "Specific system reset" );
719 					AppendMenu ( hMenu, MF_POPUP, (UINT)hMenuChange, "Change Specific system" );
720 					AppendMenu ( hMenu, MF_SEPARATOR, 0, 0 );
721 					AppendMenu ( hMenu, MF_POPUP, (UINT)hMenuProcessPriority, "Change process priority" );
722 					AppendMenu ( hMenu, MF_POPUP, (UINT)hMenuSynPriority, "Change synthesizer thread priority" );
723 					AppendMenu ( hMenu, MF_SEPARATOR, 0, 0 );
724 					AppendMenu ( hMenu, MF_STRING, IDM_PREFERENCE, "&Preferences...");
725 					AppendMenu ( hMenu, MF_STRING, IDM_CONSOLE_WND, "&Console");
726 					AppendMenu ( hMenu, MF_SEPARATOR, 0, 0 );
727 					AppendMenu ( hMenu, MF_STRING, IDM_VERSION, "Version Info");
728 					AppendMenu ( hMenu, MF_STRING, IDM_TIMIDITY, "&About TiMidity++");
729 					AppendMenu ( hMenu, MF_SEPARATOR, 0, 0 );
730 					AppendMenu ( hMenu, MF_STRING, IDM_QUIT, "E&xit");
731 				}
732 				GetCursorPos ( &point );
733 				// �|�b�v�A�b�v���j���[��������Ə����邽�߂̑���B
734 				// http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q135788& �Q��
735 #if 0		// Win 98/2000 �ȍ~�p�H
736 				{
737 					DWORD dwThreadID = GetWindowThreadProcessId ( hwnd, NULL );
738 					if ( dwThreadID != w32g_syn.gui_dwThreadId ) {
739 						AttachThreadInput ( w32g_syn.gui_dwThreadId, dwThreadID, TRUE );
740 						SetForegroundWindow ( hwnd );
741 						AttachThreadInput ( w32g_syn.gui_dwThreadId, dwThreadID, FALSE );
742 					} else {
743 						SetForegroundWindow ( hwnd );
744 					}
745 				}
746 #else	// ����ł����炵���H
747 				SetForegroundWindow ( hwnd );
748 #endif
749 				TrackPopupMenu ( hMenu, TPM_TOPALIGN | TPM_LEFTALIGN,
750 					point.x, point.y, 0, hwnd, NULL );
751 				PostMessage ( hwnd, WM_NULL, 0, 0 );	// ������|�b�v�A�b�v���j���[�̃e�N�j�b�N�炵���B
752 				DestroyMenu ( hMenu );
753 				have_popupmenu = 0;
754 				return 0;
755 			}
756     }
757 	}
758 		break;
759 	case WM_COMMAND:
760 		switch (LOWORD(wParam)) {
761 		case IDM_QUIT:
762 #if 1/* �����I�� */
763 			SetTimer ( NULL, 0, 20000, forced_exit );
764 #endif
765 			w32g_message_set (W32G_SYN_QUIT);
766 			break;
767 		case IDM_START:
768 			w32g_message_set (W32G_SYN_START);
769 			break;
770 		case IDM_STOP:
771 			w32g_message_set (W32G_SYN_STOP);
772 			break;
773 		case IDM_SYSTEM_RESET:
774 			w32g_message_set (W32G_SYN_SYSTEM_RESET);
775 			break;
776 		case IDM_GM_SYSTEM_RESET:
777 			w32g_message_set (W32G_SYN_GM_SYSTEM_RESET);
778 			break;
779 		case IDM_GS_SYSTEM_RESET:
780 			w32g_message_set (W32G_SYN_GS_SYSTEM_RESET);
781 			break;
782 		case IDM_XG_SYSTEM_RESET:
783 			w32g_message_set (W32G_SYN_XG_SYSTEM_RESET);
784 			break;
785 		case	IDM_CHANGE_GM_SYSTEM:
786 			w32g_message_set (W32G_SYN_CHANGE_GM_SYSTEM);
787 			break;
788 		case	IDM_CHANGE_GS_SYSTEM:
789 			w32g_message_set (W32G_SYN_CHANGE_GS_SYSTEM);
790 			break;
791 		case IDM_CHANGE_XG_SYSTEM:
792 			w32g_message_set (W32G_SYN_CHANGE_XG_SYSTEM);
793 			break;
794 		case IDM_CHANGE_DEFAULT_SYSTEM:
795 			w32g_message_set (W32G_SYN_CHANGE_DEFAULT_SYSTEM);
796 			break;
797 		case IDM_PREFERENCE:
798 			PrefWndCreate ( w32g_syn.nid_hWnd );
799 			break;
800 		case IDM_VERSION:
801 			VersionWnd ( w32g_syn.nid_hWnd );
802 			break;
803 		case IDM_TIMIDITY:
804 			TiMidityWnd ( w32g_syn.nid_hWnd );
805 			break;
806 		case IDM_PROCESS_PRIORITY_LOWEST:
807 			processPriority = IDLE_PRIORITY_CLASS;
808 			if ( w32g_syn_status == run ) {
809 				SetPriorityClass(GetCurrentProcess(), processPriority);
810 			}
811 			break;
812 		case IDM_PROCESS_PRIORITY_BELOW_NORMAL:
813 			processPriority = BELOW_NORMAL_PRIORITY_CLASS;
814 			if ( w32g_syn_status == run ) {
815 				SetPriorityClass(GetCurrentProcess(), processPriority);
816 			}
817 			break;
818 		case IDM_PROCESS_PRIORITY_NORMAL:
819 			processPriority = NORMAL_PRIORITY_CLASS;
820 			if ( w32g_syn_status == run ) {
821 				SetPriorityClass(GetCurrentProcess(), processPriority);
822 			}
823 			break;
824 		case IDM_PROCESS_PRIORITY_ABOVE_NORMAL:
825 			processPriority = ABOVE_NORMAL_PRIORITY_CLASS;
826 			if ( w32g_syn_status == run ) {
827 				SetPriorityClass(GetCurrentProcess(), processPriority);
828 			}
829 			break;
830 		case IDM_PROCESS_PRIORITY_HIGHEST:
831 			processPriority = HIGH_PRIORITY_CLASS;
832 			if ( w32g_syn_status == run ) {
833 				SetPriorityClass(GetCurrentProcess(), processPriority);
834 			}
835 			break;
836 		case IDM_PROCESS_PRIORITY_REALTIME:
837 			processPriority = REALTIME_PRIORITY_CLASS;
838 			if ( w32g_syn_status == run ) {
839 				SetPriorityClass(GetCurrentProcess(), processPriority);
840 			}
841 			break;
842 		case IDM_SYN_THREAD_PRIORITY_LOWEST:
843 			syn_ThreadPriority = THREAD_PRIORITY_LOWEST;
844 			if ( w32g_syn_status == run ) {
845 				SetThreadPriority ( w32g_syn.syn_hThread, syn_ThreadPriority );
846 			}
847 			break;
848 		case IDM_SYN_THREAD_PRIORITY_BELOW_NORMAL:
849 			syn_ThreadPriority = THREAD_PRIORITY_BELOW_NORMAL;
850 			if ( w32g_syn_status == run ) {
851 				SetThreadPriority ( w32g_syn.syn_hThread, syn_ThreadPriority );
852 			}
853 			break;
854 		case IDM_SYN_THREAD_PRIORITY_NORMAL:
855 			syn_ThreadPriority = THREAD_PRIORITY_NORMAL;
856 			if ( w32g_syn_status == run ) {
857 				SetThreadPriority ( w32g_syn.syn_hThread, syn_ThreadPriority );
858 			}
859 			break;
860 		case IDM_SYN_THREAD_PRIORITY_ABOVE_NORMAL:
861 			syn_ThreadPriority = THREAD_PRIORITY_ABOVE_NORMAL;
862 			if ( w32g_syn_status == run ) {
863 				SetThreadPriority ( w32g_syn.syn_hThread, syn_ThreadPriority );
864 			}
865 			break;
866 		case IDM_SYN_THREAD_PRIORITY_HIGHEST:
867 			syn_ThreadPriority = THREAD_PRIORITY_HIGHEST;
868 			if ( w32g_syn_status == run ) {
869 				SetThreadPriority ( w32g_syn.syn_hThread, syn_ThreadPriority );
870 			}
871 			break;
872 		case IDM_SYN_THREAD_PRIORITY_TIMECRITICAL:
873 			syn_ThreadPriority = THREAD_PRIORITY_TIME_CRITICAL;
874 			if ( w32g_syn_status == run ) {
875 				SetThreadPriority ( w32g_syn.syn_hThread, syn_ThreadPriority );
876 			}
877 			break;
878 #ifdef HAVE_SYN_CONSOLE
879 		case IDM_CONSOLE_WND:
880 			if ( hConsoleWnd == NULL ) {
881 				InitConsoleWnd ( w32g_syn.nid_hWnd );
882 			}
883 			if ( IsWindowVisible ( hConsoleWnd ) )
884 				ShowWindow ( hConsoleWnd, SW_HIDE );
885 			else
886 				ShowWindow ( hConsoleWnd, SW_SHOW );
887 			break;
888 #endif
889 		default:
890 			break;
891 		}
892 		break;
893 	default:
894 		if (uMess == RegisterWindowMessage("TaskbarCreated")) {
895 			AddTasktrayIcon(hwnd);
896 			return 0;
897 		}
898 	  return DefWindowProc ( hwnd, uMess, wParam, lParam );
899 	}
900 	return 0L;
901 }
902 
903 static int volatile syn_thread_started = 0;
start_syn_thread(void)904 static int start_syn_thread ( void )
905 {
906 	w32g_syn.syn_hThread = crt_beginthreadex ( NULL, 0,
907 				    (LPTHREAD_START_ROUTINE) syn_thread,
908 				    NULL, 0, & w32g_syn.syn_dwThreadId );
909 	if ( w32g_syn.syn_hThread == NULL ) {
910 		return -1;
911 	}
912 	for (;;) {
913 		if ( syn_thread_started == 1 )
914 			break;
915 		if ( syn_thread_started == 2 )
916 			return -1;
917 		Sleep ( 200 );
918 	}
919 	if ( syn_thread_started == 2 )
920 		return -1;
921 	return 0;
922 }
923 
syn_thread(void)924 static void WINAPI syn_thread ( void )
925 {
926 	syn_thread_started = 1;
927 	win_main ( w32g_syn.argc, w32g_syn.argv );
928 	syn_thread_started = 2;
929 }
930 
terminate_syn_thread(void)931 static void terminate_syn_thread ( void )
932 {
933 	w32g_message_set ( W32G_SYN_QUIT );
934 }
935 
wait_for_termination_of_syn_thread(void)936 static int wait_for_termination_of_syn_thread ( void )
937 {
938 	int i;
939 	int ok = 0;
940 	for ( i = 0; i < 10; i++ ) {
941 		if ( WaitForSingleObject ( w32g_syn.syn_hThread, 200 ) == WAIT_TIMEOUT ) {
942 			w32g_message_set ( W32G_SYN_QUIT );
943 		} else {
944 			ok = 1;
945 			break;
946 		}
947 	}
948 	return ok;
949 }
950 
951 #else // !TWSYNSRV
952 
953 // Windows service version here
954 
955 // To debug output (Require attached debugger)
OutputString(char * format,...)956 static void OutputString(char *format, ...)
957 {
958 	char temp[256];
959 	va_list va;
960 
961 	va_start(va, format);
962 	vsnprintf(temp, sizeof(temp), format, va);
963 	OutputDebugString(temp);
964 	va_end(va);
965 }
966 
PutsConsoleWnd(char * str)967 void PutsConsoleWnd(char *str)
968 {
969 	OutputString("%s", str);
970 }
971 
972 // To MessageBox Window (Require grant access windowstation)
OutputWindow(char * format,...)973 static void OutputWindow(char *format, ...)
974 {
975 	char temp[256];
976 	va_list va;
977 
978 	va_start(va, format);
979 	vsnprintf(temp, sizeof(temp), format, va);
980 	MessageBox(NULL, temp, serviceName, MB_OK | MB_ICONEXCLAMATION);
981 	va_end(va);
982 }
983 
OutputLastError(char * message)984 static void OutputLastError(char *message)
985 {
986 	LPVOID buffer;
987 
988 	FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
989 		FORMAT_MESSAGE_IGNORE_INSERTS,
990 		NULL, GetLastError(),
991 		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
992 		(LPTSTR)&buffer, 0, NULL);
993 	OutputDebugString(message);
994 	OutputDebugString(" : ");
995 	OutputDebugString(buffer);
996 	OutputDebugString("\n");
997 
998 	LocalFree(buffer);
999 }
1000 
OutputWindowLastError(char * message)1001 static void OutputWindowLastError(char *message)
1002 {
1003 	LPVOID buffer;
1004 	char *temp;
1005 
1006 	FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
1007 		FORMAT_MESSAGE_IGNORE_INSERTS,
1008 		NULL, GetLastError(),
1009 		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
1010 		(LPTSTR)&buffer, 0, NULL);
1011 
1012 	temp = (char *)malloc(strlen((const char *)buffer) + strlen(message) + 10);
1013 	sprintf(temp, "%s : %s\n", message, buffer);
1014 
1015 	MessageBox(NULL, temp, serviceName, MB_OK | MB_ICONEXCLAMATION);
1016 
1017 	free(temp);
1018 	LocalFree(buffer);
1019 }
1020 
1021 // Report service status to service control manager
ReportStatusToSCM(DWORD newServiceStatus,DWORD checkPoint,DWORD waitHint,DWORD win32ExitCode,DWORD serviceSpecificExitCode)1022 static BOOL ReportStatusToSCM(DWORD newServiceStatus, DWORD checkPoint, DWORD waitHint,
1023 	DWORD win32ExitCode, DWORD serviceSpecificExitCode)
1024 {
1025 	BOOL result;
1026 	SERVICE_STATUS serviceStatus;
1027 
1028 	serviceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
1029 	currentServiceStatus = newServiceStatus;
1030 	serviceStatus.dwCurrentState = newServiceStatus;
1031 	serviceStatus.dwCheckPoint = checkPoint;
1032 	serviceStatus.dwWaitHint = waitHint;
1033 	serviceStatus.dwWin32ExitCode = win32ExitCode;
1034 	serviceStatus.dwServiceSpecificExitCode = serviceSpecificExitCode;
1035 	if (newServiceStatus == SERVICE_START_PENDING)
1036 	{
1037 		serviceStatus.dwControlsAccepted = 0;
1038 	}
1039 	else
1040 	{
1041 		serviceStatus.dwControlsAccepted =
1042 			SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_PARAMCHANGE;
1043 	}
1044 	result = SetServiceStatus(serviceStatusHandle, &serviceStatus);
1045 	if (result == FALSE)
1046 	{
1047 		OutputLastError("ReportStatusToSCM() == FALSE");
1048 	}
1049 	return result;
1050 }
1051 
1052 // Report service status to service control manager (Alternate version)
PingStatusToSCM(DWORD checkPoint,DWORD waitHint)1053 static BOOL PingStatusToSCM(DWORD checkPoint, DWORD waitHint)
1054 {
1055 	return ReportStatusToSCM(currentServiceStatus, checkPoint, waitHint, NO_ERROR, NO_ERROR);
1056 }
1057 
1058 // Service control message from management interface (Callback from SCM)
ServiceCtrlHandler(DWORD state)1059 static void WINAPI ServiceCtrlHandler(DWORD state)
1060 {
1061  	switch (state)
1062 	{
1063 	case SERVICE_CONTROL_STOP:
1064 		ReportStatusToSCM(SERVICE_STOP_PENDING, 1, 0, NO_ERROR, NO_ERROR);
1065 		w32g_message_set(W32G_SYN_QUIT);
1066 		break;
1067 	case SERVICE_CONTROL_PAUSE:
1068 		ReportStatusToSCM(SERVICE_PAUSE_PENDING, 1, 0, NO_ERROR, NO_ERROR);
1069 		w32g_message_set(W32G_SYN_STOP);
1070 		ReportStatusToSCM(SERVICE_PAUSED, 1, 0, NO_ERROR, NO_ERROR);
1071 		break;
1072 	case SERVICE_CONTROL_CONTINUE:
1073 		ReportStatusToSCM(SERVICE_CONTINUE_PENDING, 1, 0, NO_ERROR, NO_ERROR);
1074 		w32g_message_set(W32G_SYN_START);
1075 		ReportStatusToSCM(SERVICE_RUNNING, 1, 0, NO_ERROR, NO_ERROR);
1076 		break;
1077 	case SERVICE_CONTROL_INTERROGATE:
1078 		OutputString("ServiceCtrlHandler(), SERVICE_CONTROL_INTERROGATE : oops.\n");
1079 		break;
1080 	case SERVICE_CONTROL_SHUTDOWN:
1081 		OutputString("ServiceCtrlHandler(), SERVICE_CONTROL_SHUTDOWN : oops.\n");
1082 		break;
1083 	default:
1084 		OutputString("ServiceCtrlHandler(), default handler (%d) : oops.\n", state);
1085 		break;
1086 	}
1087 	PingStatusToSCM(0, 0);
1088 }
1089 
1090 // Register service control handler
RegisterCtrlHandler()1091 static SERVICE_STATUS_HANDLE RegisterCtrlHandler()
1092 {
1093 	SERVICE_STATUS_HANDLE ssh = RegisterServiceCtrlHandler(
1094 		serviceName, ServiceCtrlHandler);
1095 	if (ssh == 0)
1096 	{
1097 		OutputLastError("RegisterServiceCtrlHandler() == 0");
1098 		return NULL;
1099 	}
1100 	return ssh;
1101 }
1102 
1103 // Service entry function (Callback from SCM)
ServiceMain(DWORD argc,LPTSTR * argv)1104 static void WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
1105 {
1106 	serviceStatusHandle = RegisterCtrlHandler();
1107 	ReportStatusToSCM(SERVICE_RUNNING, 1, 0, NO_ERROR, NO_ERROR);
1108 
1109 	w32g_syn.syn_hThread = GetCurrentThread();
1110 	win_main(w32g_syn.argc, w32g_syn.argv);
1111 
1112 	ReportStatusToSCM(SERVICE_STOPPED, 1, 0, NO_ERROR, NO_ERROR);
1113 }
1114 
1115 // return
1116 // 0 : OK
1117 // -1 : FATAL ERROR
w32g_syn_main(void)1118 static int w32g_syn_main ( void )
1119 {
1120 	int i;
1121 	BOOL result;
1122 	SERVICE_TABLE_ENTRY ServiceTable[2];
1123 
1124 	w32g_syn.nid_uID = W32G_SYN_NID_UID;
1125 	processPriority = NORMAL_PRIORITY_CLASS;
1126 	syn_ThreadPriority = THREAD_PRIORITY_NORMAL;
1127 	for ( i = 0; i <= MAX_PORT; i ++ ) {
1128 		w32g_syn_id_port[i] = i + 1;
1129 	}
1130 
1131 	ServiceTable[0].lpServiceName = (LPSTR)serviceName;
1132 	ServiceTable[0].lpServiceProc = ServiceMain;
1133 	ServiceTable[1].lpServiceName = 0;
1134 	ServiceTable[1].lpServiceProc = 0;
1135 
1136 	result = StartServiceCtrlDispatcher(ServiceTable);
1137 	if (result == FALSE)
1138 	{
1139 #if 0
1140 //		OutputLastError("StartServiceCtrlDispatcher() == FALSE");
1141 		OutputWindowLastError("StartServiceCtrlDispatcher() == FALSE");
1142 #else
1143 		ServiceMain(0, 0);
1144 #endif
1145 		return -1;
1146 	}
1147 	return 0;
1148 }
1149 
1150 // Service installer
InstallService()1151 static BOOL InstallService()
1152 {
1153 	char twSynSrvPath[_MAX_PATH], serviceLongName[40];
1154 	SC_HANDLE scm, sv;
1155 	HKEY srvKey;
1156 
1157 	GetModuleFileName(NULL, twSynSrvPath, _MAX_PATH);
1158 
1159 	scm = OpenSCManager(
1160 		NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CREATE_SERVICE);
1161 	if (scm == NULL)
1162 	{
1163 		OutputWindowLastError("OpenSCManager() == NULL");
1164 		return FALSE;
1165 	}
1166 
1167 	strcpy(serviceLongName, serviceName);
1168 	strcat(serviceLongName, (strcmp(timidity_version, "current"))
1169 			? " version " : " ");
1170 	strcat(serviceLongName, timidity_version);
1171 	sv = CreateService(scm, serviceName, serviceLongName,
1172 		0, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START,
1173 		SERVICE_ERROR_IGNORE, twSynSrvPath, NULL, NULL, NULL, NULL, NULL);
1174 	if (sv == NULL)
1175 	{
1176 		OutputWindowLastError("CreateService() == NULL");
1177 		CloseServiceHandle(scm);
1178 		return FALSE;
1179 	}
1180 
1181 	CloseServiceHandle(sv);
1182 	CloseServiceHandle(scm);
1183 
1184 	if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, regKeyTwSynSrv,
1185 		0, KEY_WRITE | KEY_READ, &srvKey) == ERROR_SUCCESS)
1186 	{
1187 		if (RegSetValueEx(srvKey, "Description", (unsigned long int)NULL, REG_SZ,
1188 			(const BYTE *)serviceDescription, strlen(serviceDescription)) != ERROR_SUCCESS)
1189 		{
1190 			OutputWindowLastError("RegSetValueEx() != ERROR_SUCCESS");
1191 			RegCloseKey(srvKey);
1192 			return FALSE;
1193 		}
1194 		RegCloseKey(srvKey);
1195 	}
1196 
1197 	OutputWindow("%s : Service install successful.", serviceLongName);
1198 
1199 	return TRUE;
1200 }
1201 
1202 // Service uninstaller
UninstallService()1203 static BOOL UninstallService()
1204 {
1205 	char serviceLongName[40];
1206 	SC_HANDLE scm, sv;
1207 
1208 	scm = OpenSCManager(
1209 		NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT);
1210 	if (scm == NULL)
1211 	{
1212 		OutputWindowLastError("OpenSCManager() == NULL");
1213 		return FALSE;
1214 	}
1215 
1216 	sv = OpenService(scm, serviceName, DELETE | SERVICE_STOP | SERVICE_QUERY_STATUS);
1217 	if (sv == NULL)
1218 	{
1219 		OutputWindowLastError("OpenService() == NULL");
1220 		CloseServiceHandle(scm);
1221 		return FALSE;
1222 	}
1223 
1224 	if (DeleteService(sv) == FALSE)
1225 	{
1226 		OutputWindowLastError("DeleteService() == FALSE");
1227 		CloseServiceHandle(sv);
1228 		CloseServiceHandle(scm);
1229 		return FALSE;
1230 	}
1231 
1232 	CloseServiceHandle(sv);
1233 	CloseServiceHandle(scm);
1234 
1235 	strcpy(serviceLongName, serviceName);
1236 	strcat(serviceLongName, (strcmp(timidity_version, "current"))
1237 			? " version " : " ");
1238 	strcat(serviceLongName, timidity_version);
1239 	OutputWindow("%s : Service uninstall successful.", serviceLongName);
1240 
1241 	return TRUE;
1242 }
1243 
1244 #endif	// !TWSYNSRV
1245 
1246 
1247 // �•ϒ������ɂ���\��c�c
1248 // 0: �����A1: �lj��ł��Ȃ�����
w32g_message_set(int cmd)1249 int w32g_message_set ( int cmd )
1250 {
1251 	int res = 0;
1252 	if ( msg_loopbuf_hMutex == NULL ) {
1253 		msg_loopbuf_hMutex = CreateMutex ( NULL, TRUE, NULL );
1254 	} else {
1255 		WaitForSingleObject ( msg_loopbuf_hMutex, INFINITE );
1256 	}
1257 	if ( cmd == W32G_SYN_QUIT || cmd == W32G_SYN_START || cmd == W32G_SYN_STOP ) {	// �D�悷�郁�b�Z�[�W�B
1258 			msg_loopbuf_start = 0;
1259 			msg_loopbuf_end = 0;
1260 			msg_loopbuf[msg_loopbuf_end].cmd = cmd;
1261 			ReleaseMutex ( msg_loopbuf_hMutex );
1262 			return res;
1263 	} else if ( cmd != W32G_SYN_NONE ) {
1264 		if ( msg_loopbuf_end < 0 ) {
1265 			msg_loopbuf_start = 0;
1266 			msg_loopbuf_end = 0;
1267 		} else if ( msg_loopbuf_start <= msg_loopbuf_end ) {
1268 			if ( msg_loopbuf_end < W32G_SYN_MESSAGE_MAX - 1)
1269 				msg_loopbuf_end ++;
1270 			else
1271 				res = 1;
1272 		} else if ( msg_loopbuf_end < msg_loopbuf_start - 1 ) {
1273 			msg_loopbuf_end ++;
1274 		} else {
1275 				res = 1;
1276 		}
1277 		if ( res == 0 ) {
1278 			msg_loopbuf[msg_loopbuf_end].cmd = cmd;
1279 		}
1280 	}
1281 	ReleaseMutex ( msg_loopbuf_hMutex );
1282 	Sleep ( 100 );
1283 	return res;
1284 }
1285 
w32g_message_get(w32g_syn_message_t * msg)1286 int w32g_message_get ( w32g_syn_message_t *msg )
1287 {
1288 	int have_msg = 0;
1289 	if ( msg_loopbuf_hMutex == NULL ) {
1290 		msg_loopbuf_hMutex = CreateMutex ( NULL, TRUE, NULL );
1291 	} else {
1292 		WaitForSingleObject ( msg_loopbuf_hMutex, INFINITE );
1293 	}
1294 	if ( msg_loopbuf_start >= 0 ) {
1295 		memcpy ( msg, &msg_loopbuf[msg_loopbuf_start], sizeof ( w32g_syn_message_t ) );
1296 		have_msg = 1;
1297 		msg_loopbuf_start ++;
1298 		if ( msg_loopbuf_end < msg_loopbuf_start ) {
1299 			msg_loopbuf_start = msg_loopbuf_end = -1;
1300 		} else if ( msg_loopbuf_start >= W32G_SYN_MESSAGE_MAX ) {
1301 			msg_loopbuf_start = 0;
1302 		}
1303 	}
1304 	ReleaseMutex ( msg_loopbuf_hMutex );
1305 	return have_msg;
1306 }
1307 
1308 extern int seq_quit;
1309 extern void rtsyn_play_event(MidiEvent *);
w32g_syn_doit(void)1310 void w32g_syn_doit(void)
1311 {
1312 	w32g_syn_message_t msg;
1313 	MidiEvent ev;
1314 	DWORD sleep_time;
1315 	while(seq_quit==0) {
1316 		int have_msg = 0;
1317 		sleep_time = 0;
1318 		have_msg = w32g_message_get ( &msg );
1319 		if ( have_msg ) {
1320 			switch ( msg.cmd ) {
1321 			case W32G_SYN_QUIT:
1322 				seq_quit=~0;
1323 				w32g_syn_status = quit;
1324 				sleep_time = 100;
1325 				break;
1326 			case W32G_SYN_START:
1327 				seq_quit=~0;
1328 				w32g_syn_status = run;
1329 				sleep_time = 100;
1330 				break;
1331 			case W32G_SYN_STOP:
1332 				seq_quit=~0;
1333 				w32g_syn_status = stop;
1334 				sleep_time = 100;
1335 				break;
1336 			case W32G_SYN_GM_SYSTEM_RESET:
1337 					rtsyn_server_reset();
1338 					ev.type=ME_RESET;
1339 					ev.a=GM_SYSTEM_MODE;
1340 					rtsyn_play_event(&ev);
1341 					sleep_time = 100;
1342 				break;
1343 			case W32G_SYN_GS_SYSTEM_RESET:
1344 				rtsyn_server_reset();
1345 				ev.type=ME_RESET;
1346 				ev.a=GS_SYSTEM_MODE;
1347 				rtsyn_play_event(&ev);
1348 				sleep_time = 100;
1349 				break;
1350 			case W32G_SYN_XG_SYSTEM_RESET:
1351 				rtsyn_server_reset();
1352 				ev.type=ME_RESET;
1353 				ev.a=XG_SYSTEM_MODE;
1354 				rtsyn_play_event(&ev);
1355 				sleep_time = 100;
1356 				break;
1357 			case W32G_SYN_SYSTEM_RESET:
1358 				rtsyn_server_reset();
1359 				ev.type=ME_RESET;
1360 				ev.a=rtsyn_system_mode;
1361 				rtsyn_play_event(&ev);
1362 				sleep_time = 100;
1363 				break;
1364 			case W32G_SYN_CHANGE_GM_SYSTEM:
1365 				rtsyn_system_mode=GM_SYSTEM_MODE;
1366 				rtsyn_server_reset();
1367 				ev.type=ME_RESET;
1368 				ev.a=GM_SYSTEM_MODE;
1369 				rtsyn_play_event(&ev);
1370 				change_system_mode(rtsyn_system_mode);
1371 				sleep_time = 100;
1372 				break;
1373 			case W32G_SYN_CHANGE_GS_SYSTEM:
1374 				rtsyn_system_mode=GS_SYSTEM_MODE;
1375 				rtsyn_server_reset();
1376 				ev.type=ME_RESET;
1377 				ev.a=GS_SYSTEM_MODE;
1378 				rtsyn_play_event(&ev);
1379 				change_system_mode(rtsyn_system_mode);
1380 				sleep_time = 100;
1381 				break;
1382 			case W32G_SYN_CHANGE_XG_SYSTEM:
1383 				rtsyn_system_mode=XG_SYSTEM_MODE;
1384 				rtsyn_server_reset();
1385 				ev.type=ME_RESET;
1386 				ev.a=XG_SYSTEM_MODE;
1387 				rtsyn_play_event(&ev);
1388 				change_system_mode(rtsyn_system_mode);
1389 				sleep_time = 100;
1390 				break;
1391 			case W32G_SYN_CHANGE_DEFAULT_SYSTEM:
1392 				rtsyn_system_mode=DEFAULT_SYSTEM_MODE;
1393 				rtsyn_server_reset();
1394 				ev.type=ME_RESET;
1395 				ev.a=GS_SYSTEM_MODE;
1396 				rtsyn_play_event(&ev);
1397 				change_system_mode(rtsyn_system_mode);
1398 				sleep_time = 100;
1399 				break;
1400 			default:
1401 				break;
1402 			}
1403 		}
1404 
1405 		winplaymidi();
1406 		Sleep ( sleep_time );
1407 	}
1408 }
1409 
w32g_syn_ctl_pass_playing_list(int n_,char * args_[])1410 int w32g_syn_ctl_pass_playing_list ( int n_, char *args_[] )
1411 {
1412 	int i;
1413 #ifndef TWSYNSRV
1414 	w32g_syn_status = syn_AutoStart ? run : stop;
1415 #else
1416 	w32g_syn_status = run;
1417 #endif
1418 	for (;;) {
1419 		int breakflag = 0;
1420 		switch ( w32g_syn_status ) {
1421 		default:
1422 		case quit:
1423 			breakflag = 1;
1424 			break;
1425 		case run:
1426 			{
1427 				int result;
1428 				char args_[MAX_PORT][10];
1429 				char *args[MAX_PORT];
1430 				if ( w32g_syn_port_num <= 0 ) {
1431 					w32g_syn_status = stop;
1432 					break;
1433 				} else if ( w32g_syn_port_num > MAX_PORT ) {
1434 					w32g_syn_port_num = MAX_PORT;
1435 				}
1436 				for ( i = 0; i < MAX_PORT; i ++ ) {
1437 					args[i] = args_[i];
1438 					sprintf ( args[i], "%d", w32g_syn_id_port[i] );
1439 				}
1440 				SetPriorityClass ( GetCurrentProcess(), processPriority );
1441 				SetThreadPriority ( w32g_syn.syn_hThread, syn_ThreadPriority );
1442 				result = ctl_pass_playing_list2 ( w32g_syn_port_num, args );
1443 				SetPriorityClass ( GetCurrentProcess(), NORMAL_PRIORITY_CLASS );
1444 				SetThreadPriority ( w32g_syn.syn_hThread, THREAD_PRIORITY_NORMAL );
1445 				if ( result == 2 ) {
1446 					w32g_syn_status = stop;
1447 				}
1448 			}
1449 			break;
1450 		case stop:
1451 			{
1452 			w32g_syn_message_t msg;
1453 			if ( w32g_message_get ( &msg ) ) {
1454 				if ( msg.cmd == W32G_SYN_START ) {
1455 					w32g_syn_status = run;
1456 					break;
1457 				} else {
1458 					if ( msg.cmd == W32G_SYN_QUIT ) {
1459 						w32g_syn_status = quit;
1460 						break;
1461 					}
1462 				}
1463 			}
1464 			Sleep ( 500 );
1465 			}
1466 			break;
1467 		}
1468 		if ( breakflag )
1469 			break;
1470 	}
1471 #ifndef TWSYNSRV
1472 	while ( w32g_syn.quit_state < 1 ) {
1473 		PostThreadMessage ( w32g_syn.gui_dwThreadId, MYWM_QUIT, 0, 0 );
1474 		Sleep ( 300 );
1475 	}
1476 #endif
1477 	if ( w32g_syn.quit_state < 2 ) w32g_syn.quit_state = 2;
1478 	return 0;
1479 }
1480 
w32g_syn_do_before_pref_apply(void)1481 int w32g_syn_do_before_pref_apply ( void )
1482 {
1483 	w32g_syn_status_prev = none;
1484 	for (;;) {
1485 		if ( w32g_syn_status == quit )
1486 			return -1;
1487 		if ( msg_loopbuf_hMutex == NULL ) {
1488 			msg_loopbuf_hMutex = CreateMutex ( NULL, TRUE, NULL );
1489 		} else {
1490 			WaitForSingleObject ( msg_loopbuf_hMutex, INFINITE );
1491 		}
1492 		if ( w32g_syn_status_prev == none )
1493 			w32g_syn_status_prev = w32g_syn_status;
1494 		if ( w32g_syn_status == stop ) {
1495 			return 0;
1496 		}
1497 		ReleaseMutex ( msg_loopbuf_hMutex );
1498 		w32g_message_set ( W32G_SYN_STOP );
1499 		Sleep ( 100 );
1500 	}
1501 }
1502 
w32g_syn_do_after_pref_apply(void)1503 int w32g_syn_do_after_pref_apply ( void )
1504 {
1505 	ReleaseMutex ( msg_loopbuf_hMutex );
1506 	if ( w32g_syn_status_prev == run ) {
1507 		w32g_message_set ( W32G_SYN_START );
1508 		Sleep ( 100 );
1509 	}
1510 	return 0;
1511 }
1512 
1513 #ifdef HAVE_SYN_CONSOLE
1514 
1515 // ****************************************************************************
1516 // Edit Ctl.
1517 
VprintfEditCtlWnd(HWND hwnd,char * fmt,va_list argList)1518 void VprintfEditCtlWnd(HWND hwnd, char *fmt, va_list argList)
1519 {
1520 	 char buffer[BUFSIZ], out[BUFSIZ];
1521 	 char *in;
1522 	 int i;
1523 
1524 	 if(!IsWindow(hwnd))
1525 		  return;
1526 
1527 	 vsnprintf(buffer, sizeof(buffer), fmt, argList);
1528 	 in = buffer;
1529 	 i = 0;
1530 	 for(;;){
1531 		  if(*in == '\0' || i>sizeof(out)-3){
1532 				out[i] = '\0';
1533 				break;
1534 		  }
1535 		  if(*in=='\n'){
1536 				out[i] = 13;
1537 				out[i+1] = 10;
1538 				in++;
1539 				i += 2;
1540 				continue;
1541 		  }
1542 		  out[i] = *in;
1543 		  in++;
1544 		  i++;
1545 	 }
1546 	 Edit_SetSel(hwnd,-1,-1);
1547 	 Edit_ReplaceSel(hwnd,out);
1548 }
1549 
PrintfEditCtlWnd(HWND hwnd,char * fmt,...)1550 void PrintfEditCtlWnd(HWND hwnd, char *fmt, ...)
1551 {
1552     va_list ap;
1553     va_start(ap, fmt);
1554     VprintfEditCtlWnd(hwnd,fmt,ap);
1555     va_end(ap);
1556 }
1557 
1558 #if 1
PutsEditCtlWnd(HWND hwnd,char * str)1559 void PutsEditCtlWnd(HWND hwnd, char *str)
1560 {
1561 	char *in = str;
1562 	int i;
1563 	char out[BUFSIZ];
1564 	i = 0;
1565 	for(;;){
1566 		if(*in == '\0' || i>sizeof(out)-3){
1567 			out[i] = '\0';
1568 			break;
1569     }
1570   	if(*in=='\n'){
1571     	out[i] = 13;
1572     	out[i+1] = 10;
1573 			in++;
1574       i += 2;
1575       continue;
1576     }
1577     out[i] = *in;
1578 		in++;
1579     i++;
1580   }
1581 	if(IsWindow(hwnd)){
1582 		Edit_SetSel(hwnd,-1,-1);
1583 		Edit_ReplaceSel(hwnd,out);
1584 	}
1585 }
1586 #else
PutsEditCtlWnd(HWND hwnd,char * str)1587 void PutsEditCtlWnd(HWND hwnd, char *str)
1588 {
1589 	if(!IsWindow(hwnd))
1590 		return;
1591 	PrintfEditCtlWnd(hwnd,"%s",str);
1592 }
1593 #endif
1594 
ClearEditCtlWnd(HWND hwnd)1595 void ClearEditCtlWnd(HWND hwnd)
1596 {
1597 	char pszVoid[]="";
1598 	if(!IsWindow(hwnd))
1599 		return;
1600 	if(IsWindow(hwnd)){
1601 //		Edit_SetSel(hwnd,0,-1);
1602 		Edit_SetSel(hwnd,-1,-1);
1603 	}
1604 	Edit_SetText(hwnd,pszVoid);
1605 }
1606 
VersionWnd(HWND hParentWnd)1607 static void VersionWnd(HWND hParentWnd)
1608 {
1609 	char VersionText[2024];
1610   sprintf(VersionText,
1611 "TiMidity++ %s%s" NLS NLS
1612 "TiMidity-0.2i by Tuukka Toivonen <tt@cgs.fi>." NLS
1613 "TiMidity Win32 version by Davide Moretti <dave@rimini.com>." NLS
1614 "TiMidity Windows 95 port by Nicolas Witczak." NLS
1615 "Twsynth by Keishi Suenaga <s_keishi@mutt.freemail.ne.jp>." NLS
1616 "Twsynth GUI by Daisuke Aoki <dai@y7.net>." NLS
1617 " Japanese menu, dialog, etc by Saito <timidity@flashmail.com>." NLS
1618 "TiMidity++ by Masanao Izumo <mo@goice.co.jp>." NLS
1619 ,(strcmp(timidity_version, "current")) ? "version " : "", timidity_version);
1620 	MessageBox(hParentWnd, VersionText, "Version", MB_OK);
1621 }
1622 
TiMidityWnd(HWND hParentWnd)1623 static void TiMidityWnd(HWND hParentWnd)
1624 {
1625 	char TiMidityText[2024];
1626   sprintf(TiMidityText,
1627 " TiMidity++ %s%s -- MIDI to WAVE converter and player" NLS
1628 " Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp>" NLS
1629 " Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>" NLS
1630 NLS
1631 " Win32 version by Davide Moretti <dmoretti@iper.net>" NLS
1632 " GUI by Daisuke Aoki <dai@y7.net>." NLS
1633 " Modified by Masanao Izumo <mo@goice.co.jp>." NLS
1634 NLS
1635 " This program is free software; you can redistribute it and/or modify" NLS
1636 " it under the terms of the GNU General Public License as published by" NLS
1637 " the Free Software Foundation; either version 2 of the License, or" NLS
1638 " (at your option) any later version." NLS
1639 NLS
1640 " This program is distributed in the hope that it will be useful," NLS
1641 " but WITHOUT ANY WARRANTY; without even the implied warranty of"NLS
1642 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the" NLS
1643 " GNU General Public License for more details." NLS
1644 NLS
1645 " You should have received a copy of the GNU General Public License" NLS
1646 " along with this program; if not, write to the Free Software" NLS
1647 " Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA" NLS
1648 ,
1649 (strcmp(timidity_version, "current")) ? "version " : "", timidity_version
1650 	);
1651 	MessageBox(hParentWnd, TiMidityText, "TiMidity", MB_OK);
1652 }
1653 
1654 
1655 // ***************************************************************************
1656 //
1657 // Console Window
1658 //
1659 // ***************************************************************************
1660 
1661 // ---------------------------------------------------------------------------
1662 // variables
1663 static int ConsoleWndMaxSize = 64 * 1024;
1664 static HFONT hFontConsoleWnd = NULL;
1665 
1666 // ---------------------------------------------------------------------------
1667 // prototypes of functions
1668 static BOOL CALLBACK ConsoleWndProc(HWND hwnd, UINT uMess, WPARAM wParam, LPARAM lParam);
1669 static void ConsoleWndAllUpdate(void);
1670 static void ConsoleWndVerbosityUpdate(void);
1671 static void ConsoleWndVerbosityApply(void);
1672 static void ConsoleWndValidUpdate(void);
1673 static void ConsoleWndValidApply(void);
1674 static void ConsoleWndVerbosityApplyIncDec(int num);
1675 static int ConsoleWndInfoReset(HWND hwnd);
1676 static int ConsoleWndInfoApply(void);
1677 
1678 void ClearConsoleWnd(void);
1679 
1680 // ---------------------------------------------------------------------------
1681 // Global Functions
1682 
1683 // Initialization
InitConsoleWnd(HWND hParentWnd)1684 void InitConsoleWnd(HWND hParentWnd)
1685 {
1686 	if (hConsoleWnd != NULL) {
1687 		DestroyWindow(hConsoleWnd);
1688 		hConsoleWnd = NULL;
1689 	}
1690 	switch(PlayerLanguage){
1691   	case LANGUAGE_ENGLISH:
1692 		hConsoleWnd = CreateDialog
1693   			(hInst,MAKEINTRESOURCE(IDD_DIALOG_CONSOLE_EN),hParentWnd,ConsoleWndProc);
1694 		break;
1695  	default:
1696 	case LANGUAGE_JAPANESE:
1697 		hConsoleWnd = CreateDialog
1698   			(hInst,MAKEINTRESOURCE(IDD_DIALOG_CONSOLE),hParentWnd,ConsoleWndProc);
1699 	break;
1700 	}
1701 	ShowWindow(hConsoleWnd,SW_HIDE);
1702 	UpdateWindow(hConsoleWnd);
1703 
1704 	ConsoleWndVerbosityApplyIncDec(0);
1705 	CheckDlgButton(hConsoleWnd, IDC_CHECKBOX_VALID, ConsoleWndFlag);
1706 	Edit_LimitText(GetDlgItem(hConsoleWnd,IDC_EDIT), ConsoleWndMaxSize);
1707 }
1708 
1709 // Window Procedure
1710 static BOOL CALLBACK
ConsoleWndProc(HWND hwnd,UINT uMess,WPARAM wParam,LPARAM lParam)1711 ConsoleWndProc(HWND hwnd, UINT uMess, WPARAM wParam, LPARAM lParam)
1712 {
1713 	switch (uMess){
1714 	case WM_INITDIALOG:
1715 		PutsConsoleWnd("Console Window\n");
1716 		ConsoleWndAllUpdate();
1717 		return FALSE;
1718 	case WM_COMMAND:
1719 		switch (LOWORD(wParam)) {
1720 		case IDCLOSE:
1721 			ShowWindow(hwnd, SW_HIDE);
1722 			break;
1723 		case IDCLEAR:
1724 			ClearConsoleWnd();
1725 			break;
1726 		case IDC_CHECKBOX_VALID:
1727 			ConsoleWndValidApply();
1728 			break;
1729 		case IDC_BUTTON_VERBOSITY:
1730 			ConsoleWndVerbosityApply();
1731 			break;
1732 		case IDC_BUTTON_INC:
1733 			ConsoleWndVerbosityApplyIncDec(1);
1734 			break;
1735 		case IDC_BUTTON_DEC:
1736 			ConsoleWndVerbosityApplyIncDec(-1);
1737 			break;
1738 		default:
1739 			break;
1740 		}
1741 		switch (HIWORD(wParam)) {
1742 		case EN_ERRSPACE:
1743 			ClearConsoleWnd();
1744 			PutsConsoleWnd("### EN_ERRSPACE -> Clear! ###\n");
1745 			break;
1746 		default:
1747 			break;
1748 		}
1749 		break;
1750 	case WM_SIZE:
1751 		ConsoleWndAllUpdate();
1752 		return FALSE;
1753 	case WM_MOVE:
1754 		break;
1755 	// See PreDispatchMessage() in w32g2_main.c
1756 	case WM_SYSKEYDOWN:
1757 	case WM_KEYDOWN:
1758 	{
1759 		int nVirtKey = (int)wParam;
1760 		switch(nVirtKey){
1761 			case VK_ESCAPE:
1762 				SendMessage(hwnd,WM_CLOSE,0,0);
1763 				break;
1764 		}
1765 	}
1766 		break;
1767 	case WM_DESTROY:
1768 		break;
1769 	case WM_CLOSE:
1770 		ShowWindow(hConsoleWnd, SW_HIDE);
1771 		break;
1772 	case WM_SETFOCUS:
1773 		HideCaret(hwnd);
1774 		break;
1775 	case WM_KILLFOCUS:
1776 		ShowCaret(hwnd);
1777 		break;
1778 	default:
1779 		return FALSE;
1780 	}
1781 	return FALSE;
1782 }
1783 
1784 // puts()
PutsConsoleWnd(char * str)1785 void PutsConsoleWnd(char *str)
1786 {
1787 	HWND hwnd;
1788 	if(!IsWindow(hConsoleWnd) || !ConsoleWndFlag)
1789 		return;
1790 	hwnd = GetDlgItem(hConsoleWnd,IDC_EDIT);
1791 	PutsEditCtlWnd(hwnd,str);
1792 }
1793 
1794 // printf()
PrintfConsoleWnd(char * fmt,...)1795 void PrintfConsoleWnd(char *fmt, ...)
1796 {
1797 	HWND hwnd;
1798 	va_list ap;
1799 	if(!IsWindow(hConsoleWnd) || !ConsoleWndFlag)
1800 		return;
1801 	hwnd = GetDlgItem(hConsoleWnd,IDC_EDIT);
1802 	va_start(ap, fmt);
1803 	VprintfEditCtlWnd(hwnd,fmt,ap);
1804 	va_end(ap);
1805 }
1806 
1807 // Clear
ClearConsoleWnd(void)1808 void ClearConsoleWnd(void)
1809 {
1810 	HWND hwnd;
1811 	if(!IsWindow(hConsoleWnd))
1812 		return;
1813 	hwnd = GetDlgItem(hConsoleWnd,IDC_EDIT);
1814 	ClearEditCtlWnd(hwnd);
1815 }
1816 
1817 // ---------------------------------------------------------------------------
1818 // Static Functions
1819 
ConsoleWndAllUpdate(void)1820 static void ConsoleWndAllUpdate(void)
1821 {
1822 	ConsoleWndVerbosityUpdate();
1823 	ConsoleWndValidUpdate();
1824 	Edit_LimitText(GetDlgItem(hConsoleWnd,IDC_EDIT_VERBOSITY),3);
1825 	Edit_LimitText(GetDlgItem(hConsoleWnd,IDC_EDIT),ConsoleWndMaxSize);
1826 }
1827 
ConsoleWndValidUpdate(void)1828 static void ConsoleWndValidUpdate(void)
1829 {
1830 	if(ConsoleWndFlag)
1831 		CheckDlgButton(hConsoleWnd, IDC_CHECKBOX_VALID, 1);
1832 	else
1833 		CheckDlgButton(hConsoleWnd, IDC_CHECKBOX_VALID, 0);
1834 }
1835 
ConsoleWndValidApply(void)1836 static void ConsoleWndValidApply(void)
1837 {
1838 	if(IsDlgButtonChecked(hConsoleWnd,IDC_CHECKBOX_VALID))
1839 		ConsoleWndFlag = 1;
1840 	else
1841 		ConsoleWndFlag = 0;
1842 }
1843 
ConsoleWndVerbosityUpdate(void)1844 static void ConsoleWndVerbosityUpdate(void)
1845 {
1846 	SetDlgItemInt(hConsoleWnd,IDC_EDIT_VERBOSITY,(UINT)ctl->verbosity, TRUE);
1847 }
1848 
ConsoleWndVerbosityApply(void)1849 static void ConsoleWndVerbosityApply(void)
1850 {
1851 	char buffer[64];
1852 	HWND hwnd;
1853 	hwnd = GetDlgItem(hConsoleWnd,IDC_EDIT_VERBOSITY);
1854 	if(!IsWindow(hConsoleWnd)) return;
1855 	if(Edit_GetText(hwnd,buffer,60)<=0) return;
1856 	ctl->verbosity = atoi(buffer);
1857 	ConsoleWndVerbosityUpdate();
1858 }
1859 
ConsoleWndVerbosityApplyIncDec(int num)1860 static void ConsoleWndVerbosityApplyIncDec(int num)
1861 {
1862 	if(!IsWindow(hConsoleWnd)) return;
1863 	ctl->verbosity += num;
1864 	RANGE(ctl->verbosity, -1, 4);
1865 	ConsoleWndVerbosityUpdate();
1866 }
1867 
1868 #endif // HAVE_SYN_CONSOLE
1869 
1870 #endif // IA_W32G_SYN
1871