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     Macintosh interface for TiMidity
21     by T.Nogami <t-nogami@happy.email.ne.jp>
22 
23     mac_c.c
24     Macintosh control mode
25 */
26 
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif /* HAVE_CONFIG_H */
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <stdarg.h>
34 
35 #include <Drag.h>
36 #include <Icons.h>
37 #include <Threads.h>
38 #include <TextUtils.h>
39 
40 #include "timidity.h"
41 #include "common.h"
42 #include "output.h"
43 #include "controls.h"
44 #include "instrum.h"
45 #include "playmidi.h"
46 #include "mfnode.h"
47 #include "miditrace.h"
48 #ifdef SUPPORT_SOUNDSPEC
49 #include "soundspec.h"
50 #endif /* SUPPORT_SOUNDSPEC */
51 
52 #include "mac_main.h"
53 #include "mac_util.h"
54 #include "mac_c.h"
55 #ifdef MAC_USE_OMS
56 #include "mac_oms.h"
57 #endif
58 
59 // *******************************
60 
61 static void ctl_refresh(void);
62 static void ctl_total_time(int tt);
63 static void ctl_master_volume(int mv);
64 static void ctl_file_name(char *name);
65 static void ctl_current_time(int ct, int v);
66 static void ctl_note(int status, int ch, int note, int vel);
67 static void ctl_volume(int channel, int val);
68 static void ctl_expression(int channel, int val);
69 static void ctl_panning(int channel, int val);
70 static void ctl_sustain(int channel, int val);
71 static void ctl_pitch_bend(int channel, int val);
72 static void ctl_reset(void);
73 static int ctl_open(int using_stdin, int using_stdout);
74 static int ctl_pass_playing_list(int number_of_files, char *list_of_files[]);
75 static void ctl_close(void);
76 static int ctl_read(int32 *valp);
77 static int cmsg(int type, int verbosity_level, char *fmt, ...);
78 static void ctl_event(CtlEvent *e);
79 
80 /**********************************/
81 /* export the interface functions */
82 
83 #define ctl mac_control_mode
84 
85 ControlMode ctl=
86 {
87   "mac interface", 'm',
88   "mac",
89   1,1,0,
90   0,
91   ctl_open,
92   ctl_close,
93   ctl_pass_playing_list,
94   ctl_read,
95   NULL,
96   cmsg,
97   ctl_event
98 };
99 
100 static uint32 cuepoint = 0;
101 static int cuepoint_pending = 0;
102 
103 // ***********************************************
104 Boolean	gCursorIsWatch, gHasDragMgr;
105 #define FILESTR_LEN 40
106 #define TIMESTR_LEN 10
107 char	fileStr[FILESTR_LEN]="", timeStr[TIMESTR_LEN]="";
108 Rect	rFileName={10,10, 26,140},
109 		rTime={10,150, 26,200},
110 		rLogo={38,5,94,98},
111 		rVol={28,220,92,239},
112 
113 		rPlay={40,110,62,142},
114 		rStop={40,145,62,177},
115 		rPause={40,180,62,212},
116 		rPrevious={70,110,92,142},
117 		rForward={70,145,92,177},
118 		rEject={70,180,92,212},
119 		rLoop={8,210,28,240};
120 
121 PicHandle	logo, logoDown;
122 //static RgnHandle	receiveRgn;
123 CIconHandle	button[6], iconPlay, iconPause, iconVol, iconTab, iconNotLoop,iconLoop;
124 static TEHandle	gLogTE=0,gDocTE=0;
125 
126 /****************************************/
127 static Boolean	recieveHiliting;
128 
DragTrackingProc(DragTrackingMessage theMessage,WindowPtr,void *,DragReference)129 pascal OSErr DragTrackingProc(
130 	DragTrackingMessage		theMessage,
131 	WindowPtr				/*window*/,
132 	void*					/*theRefCon*/,
133 	DragReference			/*drag*/)
134 {
135 	switch (theMessage)
136 	{
137 	case kDragTrackingEnterWindow:
138 		SetPort(mac_PlayerWindow.ref);
139 		//ShowDragHilite(drag, receiveRgn, true);
140 		DrawPicture(logoDown, &rLogo);
141 		recieveHiliting=true;
142 		break;
143 	case kDragTrackingInWindow:
144 		break;
145 	case kDragTrackingLeaveWindow:
146 		if( recieveHiliting )
147 		{
148 			SetPort(mac_PlayerWindow.ref);
149 			//HideDragHilite(drag);
150 			DrawPicture(logo, &rLogo);
151 			recieveHiliting=false;
152 		}
153 		break;
154 	}
155 	return noErr;
156 }
157 
DragReceiveFunc(WindowPtr,void *,DragReference drag)158 pascal OSErr DragReceiveFunc(
159 	WindowPtr		/*window*/,
160 	void*			/*theRefCon*/,
161 	DragReference	drag)
162 {
163 	long			i;
164 	char*			data;
165 	unsigned short	numFlavors;
166 	Size			dataSize;
167 	ItemReference	theItem;
168 	unsigned short	itemCount;
169 	FlavorType		flavor;
170 
171 	if( recieveHiliting )
172 	{
173 		int	oldListEnd=mac_n_files;
174 		CountDragItems(drag, &itemCount);
175 
176 		for( i=1; i<=itemCount; i++)
177 		{
178 			GetDragItemReferenceNumber(drag, i, &theItem);
179 
180 			if( noErr!=CountDragItemFlavors(drag, theItem, &numFlavors))
181 						continue;
182 			if( noErr!=GetFlavorType(drag, theItem, 1, &flavor))
183 						continue;
184 			if( noErr!=GetFlavorDataSize(drag, theItem, flavor, &dataSize))
185 						continue;
186 			data= (char*)malloc(dataSize);
187 			if( data==0 ) continue;
188 
189 			if( noErr!=GetFlavorData(drag, theItem, flavor,
190 						data, &dataSize, 0))
191 						continue;
192 			if(flavor== flavorTypeHFS)
193 				AddHFS2PlayList((HFSFlavor*)data);
194 			free(data);
195 		}
196 		if( gShuffle ) ShuffleList( oldListEnd, mac_n_files);
197 	}
198 
199 	return noErr;
200 }
201 
202 // *****************************************************
203 #pragma mark -
204 
open_window(MacWindow * macwin,short resID)205 int open_window(MacWindow* macwin, short resID)
206 {
207 	macwin->ref=GetNewCWindow(resID, 0, (WindowRef)-1);
208 	if( macwin->ref==0) mac_ErrorExit("\pCannot open Window!");
209 	SetWRefCon(macwin->ref, (long)macwin);
210 	return 0;
211 }
212 
position_window(MacWindow * macwin)213 void position_window(MacWindow* macwin)
214 {
215 	Point		p;
216 
217 	p.h=macwin->X; p.v=macwin->Y;
218 	if( PtInRect(p, &qd.screenBits.bounds) ){
219 		MoveWindow(macwin->ref, macwin->X, macwin->Y, true);
220 	}
221 	SizeWindow(macwin->ref, macwin->width, macwin->hight, 0);
222 
223 	if( macwin->show ) ShowWindow(macwin->ref);
224 }
225 
setsize_window(MacWindow * macwin)226 static void setsize_window(MacWindow* macwin)
227 {
228 	SizeWindow(macwin->ref, macwin->width, macwin->hight, 0);
229 }
230 
goaway_default(MacWindow * macwin)231 void goaway_default(MacWindow* macwin)
232 {
233 	HideWindow(macwin->ref); macwin->show=false;
234 }
235 
close_default(MacWindow * macwin)236 void close_default(MacWindow* macwin)
237 {
238 	Point	p;
239 	Rect	r;
240 
241 	//Get Log Window position
242 	SetPortWindowPort(macwin->ref);
243 	p.v=p.h=0;
244 	LocalToGlobal(&p);
245 	macwin->X=p.h, macwin->Y=p.v;
246 	r= GetWindowPort(macwin->ref)->portRect;
247 	macwin->width= r.right-r.left;
248 	macwin->hight= r.bottom-r.top;
249 }
250 
251 // *****************************************************
252 #pragma mark -
253 #pragma mark =================Player Window
254 
255 static int open_PlayerWin();
256 static void click_PlayerWin(Point local, short modifiers);
257 static void update_PlayerWin();
258 static void goaway_PlayerWin(MacWindow*);
259 static int	message_PlayerWin(int message, long param);
260 
261 #define win mac_PlayerWindow
262 MacWindow win={
263 	0,	//WindowRef
264 	open_PlayerWin,
265 	click_PlayerWin,
266 	update_PlayerWin,
267 	goaway_PlayerWin,
268 	close_default,
269 	message_PlayerWin,
270 	1, 10,50
271 };
272 
mac_setVolume(short amplitude)273 void mac_setVolume(short amplitude)
274 {
275 	SndCommand	theCmd;
276 
277 	if( amplitude<0 ) amplitude=0;
278 	if( amplitude>255 ) amplitude=255;
279 	theCmd.cmd=ampCmd;
280 	theCmd.param1=amplitude;
281 	SndDoImmediate(gSndCannel, &theCmd);
282 }
283 
DoVolume()284 void DoVolume()
285 {
286 	short		lastAmp=mac_amplitude;
287 	//SndCommand	theCmd;
288 	Point		p;
289 
290 	SetPortWindowPort(win.ref);
291 	GetMouse(&p);
292 	/*GlobalToLocal(&p);*/
293 	if( PtInRect(p, &rVol) && FrontWindow()==win.ref )
294 	{
295 
296 		mac_amplitude=255*((double)rVol.bottom-10-p.v)/(rVol.bottom-rVol.top-20);
297 		if( mac_amplitude<0 ) mac_amplitude=0;
298 		if( mac_amplitude>255 ) mac_amplitude=255;
299 
300 		if( lastAmp!=mac_amplitude )
301 		{
302 			//theCmd.cmd=ampCmd;
303 			//theCmd.param1=mac_amplitude;
304 			//SndDoImmediate(gSndCannel, &theCmd);
305 			mac_setVolume(mac_amplitude);
306 			InvalRect(&rVol);
307 		}
308 	}
309 }
310 
DrawButton()311 void DrawButton()
312 {
313 	SetPortWindowPort(win.ref);
314 	PlotCIcon(&rPlay, skin_state==PLAYING || skin_state==PAUSE? iconPlay:button[0] );
315 	PlotCIcon(&rStop, button[1]);
316 	PlotCIcon(&rPause, skin_state==PAUSE? iconPause:button[2] );
317 	PlotCIcon(&rPrevious, button[3]);
318 	PlotCIcon(&rForward, button[4]);
319 	PlotCIcon(&rEject, button[5]);
320 }
321 
DrawFileStr()322 static void DrawFileStr()
323 {
324 	SetPortWindowPort(win.ref);
325 	TETextBox(fileStr, strlen(fileStr), &rFileName, teCenter);
326 }
327 
DrawTimeStr()328 static void DrawTimeStr()
329 {
330 	SetPortWindowPort(win.ref);
331 	TETextBox(timeStr, strlen(timeStr), &rTime, teCenter);
332 }
333 
open_PlayerWin()334 static int open_PlayerWin()
335 		/*success-> return 0;*/
336 {
337 	int	i;
338 	OSErr	err;
339 	RGBColor	back={0,0,0},
340 				fore={65535,65535,65535};
341 
342 	open_window( &win, kPlayerWinID);
343 	position_window(&win);
344 
345 	SetPortWindowPort(win.ref);
346 	RGBForeColor(&fore);
347 	RGBBackColor(&back);
348 	logo= GetPicture(128);
349 	logoDown= GetPicture(132);
350 
351 	for(i=0; i<6; i++)
352 		button[i]= GetCIcon(i+200);
353 	iconPlay=GetCIcon(210);
354 	iconPause=GetCIcon(211);
355 	iconVol=GetCIcon(206);
356 	iconTab=GetCIcon(207);
357 	iconNotLoop=GetCIcon(208);
358 	iconLoop=GetCIcon(209);
359 
360 	if(gHasDragMgr)
361 	{
362 		//receiveRgn=NewRgn();
363 		//if( receiveRgn )
364 		{
365 			//GetWindowContentRgn(win.ref, receiveRgn);
366 			err=InstallTrackingHandler(NewDragTrackingHandlerProc(DragTrackingProc),
367 								(WindowPtr)win.ref, 0);
368 			if(err) ExitToShell();
369 
370 			err=InstallReceiveHandler(NewDragReceiveHandlerProc(DragReceiveFunc),
371 							(WindowPtr)win.ref, 0);
372 			if(err) ExitToShell();
373 		}
374 	}
375 	return 0;
376 }
377 
click_PlayerWin(Point p,short)378 static void click_PlayerWin(Point p, short /*modifiers*/)
379 {
380 		if( PtInRect(p, &rStop)){ mac_rc=RC_QUIT; ctl_current_time(0,0); }
381 	else	if( PtInRect(p, &rPlay)){ mac_rc=RC_CONTINUE; }
382 	else	if( PtInRect(p, &rPause)){ mac_rc=RC_TOGGLE_PAUSE; }
383 	else	if( PtInRect(p, &rPrevious)){ mac_rc=RC_PREVIOUS;  }
384 	else	if( PtInRect(p, &rForward)){ mac_rc=RC_NEXT; }
385 	else	if( PtInRect(p, &rEject)){
386 				if( skin_state==PLAYING ) mac_rc=RC_QUIT;
387 				skin_state=WAITING; mac_n_files=nPlaying=0; fileStr[0]=timeStr[0]=0;
388 				init_ListWin();
389 				update_PlayerWin();
390 			}
391 	else	if( PtInRect(p, &rLoop)){ skin_f_repeat=!skin_f_repeat; SetPortWindowPort(win.ref);
392 									InvalRect(&rLoop); return; } /* don't call mac_HandleControl();*/
393 	else	if( PtInRect(p, &rVol))	DoVolume();
394 	else	return; /* no button click*/
395 
396 	/* if button clicked */
397 	mac_HandleControl();
398 }
399 
update_PlayerWin()400 static void update_PlayerWin()
401 {
402 	short	y=((double)mac_amplitude/255)*(rVol.bottom-rVol.top-20);
403 	Rect	rFrame,rTab;
404 
405 	SetPortWindowPort(win.ref);
406 	DrawButton();
407 	skin_f_repeat? PlotCIcon(&rLoop, iconLoop):PlotCIcon(&rLoop, iconNotLoop);
408 	PlotCIcon(&rVol, iconVol);
409 	SetRect(&rTab, rVol.left+2, rVol.top+49-y, rVol.right-2, rVol.top+59-y);
410 	PlotCIcon(&rTab, iconTab);
411 
412 	rFrame=rFileName; InsetRect(&rFrame, -2, -2);	DrawPicture(GetPicture(129), &rFrame);
413 	rFrame=rTime; InsetRect(&rFrame, -2, -2);	DrawPicture(GetPicture(130), &rFrame);
414 
415 	DrawPicture(logo, &rLogo);
416 
417 	DrawTimeStr();
418 	DrawFileStr();
419 }
420 
goaway_PlayerWin(MacWindow * macwin)421 static void goaway_PlayerWin(MacWindow *macwin)
422 {
423 	Do_Quit();
424 }
425 
message_PlayerWin(int,long)426 static int	message_PlayerWin(int /*message*/, long /*param*/)
427 {
428 	return -1;
429 }
430 
431 #undef win
432 
433 
434 // *****************************************************
435 #pragma mark -
436 #pragma mark ==================Log Window
437 
438 static int open_LogWin();
439 static void click_LogWin(Point local, short modifiers);
440 static void update_LogWin();
441 static int	message_LogWin(int message, long param);
442 
443 #define win mac_LogWindow
444 MacWindow win={
445 	0,	//WindowRef
446 	open_LogWin,
447 	click_LogWin,
448 	update_LogWin,
449 	goaway_default,
450 	close_default,
451 	message_LogWin,
452 	1, 270,60, 300,200
453 };
454 
PrintLogStr(char str[])455 static void	PrintLogStr(char str[])
456 {
457 	int len=strlen(str);
458 
459 	if( !mac_LogWindow.show ) return;
460 
461 	if( (**gLogTE).teLength > 10000)	/* clear first half*/
462 	{
463 		TEFeatureFlag(teFAutoScroll, teBitClear, gLogTE);
464 		TESetSelect(0, 5000, gLogTE);
465 		TEDelete(gLogTE);
466 	}
467 
468 	TESetSelect((**gLogTE).teLength, (**gLogTE).teLength, gLogTE); /* move to end*/
469 	if( len>=1 && str[len-1]=='\n' ){
470 		str[len-1]=0; len--;	//convert dos return code to mac's
471 	}
472 	TEInsert(str, len, gLogTE);
473 	TESelView(gLogTE);
474 	TEFeatureFlag(teFAutoScroll, teBitSet, gLogTE);
475 }
476 
open_LogWin()477 static int open_LogWin()
478 		/*success-> return 0;*/
479 {
480 	open_window(&win, kLogWinID);
481 	position_window(&win);
482 	setsize_window(&win);
483 
484 	SetPortWindowPort(win.ref);
485 	TextSize(10);
486 	gLogTE=TENew(&win.ref->portRect, &win.ref->portRect);
487 	if( gLogTE==0 ) mac_ErrorExit("\ppCannot open LogWindow!");
488 
489 	TEFeatureFlag(teFAutoScroll, teBitSet, gLogTE);
490 	TEActivate(gLogTE);
491 	return 0;
492 }
493 
click_LogWin(Point local,short)494 static void click_LogWin(Point local, short /*modifiers*/)
495 {
496 	TEClick(local, 0, gLogTE);
497 }
498 
update_LogWin()499 static void update_LogWin()
500 {
501 	SetPortWindowPort(win.ref);
502 	TEUpdate(&win.ref->portRect, gLogTE);
503 }
504 
message_LogWin(int message,long)505 static int	message_LogWin(int message, long /*param*/)
506 {
507 	Rect rect;
508 
509 	switch(message){
510 	case MW_GROW:
511 		rect=win.ref->portRect;
512 		//rect.right-=15; rect.bottom-=15;
513 		rect = win.ref->portRect;
514 		rect.right  -= 15;
515 		//rect.bottom -= 15;
516 		(**gLogTE).viewRect= (**gLogTE).destRect= rect;
517 		(**gLogTE).destRect.right = (**gLogTE).destRect.right - 14;
518 		TECalText(gLogTE);
519 		TESetSelect((**gLogTE).teLength, (**gLogTE).teLength, gLogTE);
520 		return 0;
521 	}
522 
523 	return -1;  //not supported
524 }
525 
526 #undef win
527 // *****************************************************
528 #pragma mark -
529 #pragma mark ==================List Window
530 
531 ListHandle	gPlaylist;
532 
533 static int open_ListWin();
534 static void click_ListWin(Point local, short modifiers);
535 static void update_ListWin();
536 static int message_ListWin(int message, long param);
537 
538 enum{
539 	MW_LIST_SELECT=	0x00010001,
540 	MW_DOC_SET=		0x00020001
541 };
542 
543 #define win mac_ListWindow
544 MacWindow win={
545 	0,	//WindowRef
546 	open_ListWin,
547 	click_ListWin,
548 	update_ListWin,
549 	goaway_default,
550 	close_default,
551 	message_ListWin,
552 	1, 100,100, 300,200
553 };
554 
change_ListRow(short row,const MidiFile * file)555 void change_ListRow( short row, const MidiFile* file)
556 {
557 	Point	aCell;
558 	char	buf[256]="",*p;
559 
560 	if( file && file->mfn && file->mfn->title )
561 	{
562 		strncpy(buf, file->mfn->title, sizeof(buf) - 1);
563 		buf[sizeof(buf)-1] = '\0';
564 	}
565 
566 	p= strrchr(file->filename, PATH_SEP);
567 	if( p ){
568 		size_t len = strlen(buf);
569 		snprintf(&buf[len], sizeof(buf)-len-1, "  (%s)", p+1);
570 		buf[sizeof(buf)-1] = '\0';
571 	}
572 
573 	SetPt(&aCell, 0, row);
574 	LSetCell( buf, strlen(buf), aCell, gPlaylist);
575 }
576 
add_ListWin(MidiFile * file)577 void add_ListWin(MidiFile * file)
578 {
579 	short	rowNum=1;
580 	//Str255	fullPath;
581 
582 	//GetFullPath(&file->spec, fullPath);
583 	file->mfn=make_new_MFnode_entry(file->filename);
584 	rowNum = (**gPlaylist).dataBounds.bottom;
585 	rowNum = LAddRow(1, rowNum, gPlaylist);
586 	change_ListRow(  rowNum, file);
587 }
588 
init_ListWin()589 void init_ListWin()
590 {
591 	short	rowNum= (**gPlaylist).dataBounds.bottom;
592 
593 	SetPortWindowPort(win.ref);
594 	LDelRow(0, 0, gPlaylist);
595 }
596 
open_ListWin()597 static int open_ListWin()
598 		/*success-> return 0;*/
599 {
600 	Rect		listRect, dataBounds;
601 	Point		cSize;
602 
603 	open_window(&win, kListWinID);
604 	position_window(&win);
605 	setsize_window(&win);
606 
607 	SetPortWindowPort(win.ref);
608 	TextSize(10);
609 	listRect=win.ref->portRect;	listRect.right-=14; listRect.bottom-=14;
610 	dataBounds.top=dataBounds.left=0; dataBounds.right=1; dataBounds.bottom=0;
611 	cSize.h=1024; cSize.v=14;
612 	gPlaylist = LNew(&listRect, &dataBounds, cSize, 0, win.ref,
613 						1, 1, 0, 1);
614 	return 0;
615 }
616 
click_ListWin(Point local,short modifiers)617 static void click_ListWin(Point local, short modifiers)
618 {
619 	Boolean	doubleclick;
620 	Cell	cell;
621 
622 	SetPortWindowPort(win.ref);
623 	doubleclick=LClick(local, modifiers, gPlaylist);
624 	if(doubleclick){
625 		mac_rc=RC_LOAD_FILE;
626 		cell = LLastClick(gPlaylist);
627 		nPlaying=cell.v;
628 		mac_HandleControl();
629 	}
630 }
631 
update_ListWin()632 static void update_ListWin()
633 {
634 	SetPortWindowPort(win.ref);
635 	LUpdate( win.ref->visRgn, gPlaylist);
636 	DrawGrowIcon(win.ref);
637 }
638 
message_ListWin(int message,long param)639 static int message_ListWin(int message, long param)
640 {
641 	Cell	cell;
642 	Rect	rect;
643 
644 	switch(message){
645 	case MW_GROW:
646 		rect=win.ref->portRect;
647 		LSize(rect.right-14, rect.bottom-14, gPlaylist);
648 		return 0;
649 
650 	case MW_LIST_SELECT:
651 		LDeselectAll(gPlaylist);
652 		cell.h=0; cell.v=param;
653 		LSetSelect(true, cell, gPlaylist);
654 		LAutoScroll(gPlaylist);
655 		return 0;
656 	}
657 
658 	return -1; //not supported
659 }
660 
661 #undef win
662 // *****************************************************
663 #pragma mark -
664 #pragma mark ==================Doc Window
665 
666 static int open_DocWin();
667 static void click_DocWin(Point local, short modifiers);
668 static void update_DocWin();
669 static void close_DocWin();
670 static int	message_DocWin(int message, long param);
671 
672 #define win mac_DocWindow
673 MacWindow win={
674 	0,	//WindowRef
675 	open_DocWin,
676 	click_DocWin,
677 	update_DocWin,
678 	goaway_default,
679 	close_default,
680 	message_DocWin,
681 	0, 150,150, 300,200
682 };
683 
PrintDocStr(char str[])684 static void	PrintDocStr(char str[])
685 {
686 	if( (**gDocTE).teLength > 10000)	/* clear first half*/
687 	{
688 		TESetSelect(0, 5000, gDocTE);
689 		TEDelete(gDocTE);
690 	}
691 
692 	TESetSelect((**gDocTE).teLength, (**gDocTE).teLength, gDocTE); /* move to end*/
693 	TEInsert(str, strlen(str), gDocTE);
694 	TESelView(gDocTE);
695 }
696 
open_DocWin()697 static int open_DocWin()
698 		/*success-> return 0;*/
699 {
700 	Rect	r;
701 
702 	open_window(&win, kDocWinID);
703 	position_window(&win);
704 	setsize_window(&win);
705 
706 	SetPortWindowPort(win.ref);
707 	TextSize(10);
708 	r=win.ref->portRect; r.right-=16;
709 	gDocTE=TENew(&r, &r);
710 	if( gDocTE==0 ) mac_ErrorExit("\pCannot open DocWindow!");
711 
712 	TEFeatureFlag(teFAutoScroll, teBitSet, gDocTE);
713 	TEActivate(gDocTE);
714 	return 0;
715 }
716 
click_DocWin(Point local,short)717 static void click_DocWin(Point local, short /*modifiers*/)
718 {
719 	TEClick(local, 0, gDocTE);
720 }
721 
update_DocWin()722 static void update_DocWin()
723 {
724 	SetPortWindowPort(win.ref);
725 	DrawGrowIcon(win.ref);
726 	TEUpdate(&win.ref->portRect, gDocTE);
727 }
728 
message_DocWin(int message,long param)729 static int	message_DocWin(int message, long param)
730 {
731 	switch(message){
732 	case MW_GROW:
733 		{
734 			Rect rect;
735 			rect=win.ref->portRect;
736 			//rect.right-=15; rect.bottom-=15;
737 			rect = win.ref->portRect;
738 			rect.right  -= 16;
739 			//rect.bottom -= 15;
740 			(**gDocTE).viewRect= (**gDocTE).destRect= rect;
741 			//(**gDocTE).destRect.right = (**gDocTE).destRect.right - 14;
742 			TECalText(gDocTE);
743 			TESetSelect((**gDocTE).teLength, (**gDocTE).teLength, gDocTE);
744 			return 0;
745 		}
746 	case MW_DOC_SET:
747 		{
748 			const char	*midiname=(char*)param;
749 			char		*p, docname[256];
750 
751 			//midiname= (char*)param;
752 		    strncpy(docname, midiname, sizeof docname - 1);
753 		    docname[sizeof docname - 1] = '\0';
754 	    	if((p = strrchr(docname, '.')) == NULL){
755 				return 0;
756 		    }
757 		    else if(p - docname >= sizeof docname - 4) {
758 				return 0;	/* cannot strcpy: that cause buffer overrun */
759 		    }
760 		    if('A' <= p[1] && p[1] <= 'Z')	strcpy(p + 1, "DOC");
761 	    						else		strcpy(p + 1, "doc");
762 
763 	    	TEReadFile( docname, gDocTE );
764 			break;
765 		}
766 	}
767 
768 	return -1;  //not supported
769 }
770 
771 #undef win
772 // *****************************************************
773 #pragma mark -
774 #pragma mark ================== spec Window
775 
776 static int open_SpecWin();
777 static void click_SpecWin(Point local, short modifiers);
778 static void update_SpecWin();
779 static void goaway_SpecWin(MacWindow*);
780 static int	message_SpecWin(int message, long param);
781 
782 #define win mac_SpecWindow
783 MacWindow win={
784 	0,	//WindowRef
785 	open_SpecWin,
786 	click_SpecWin,
787 	update_SpecWin,
788 	goaway_SpecWin,
789 	close_default,
790 	message_SpecWin,
791 	0, 100,100
792 };
793 
open_SpecWin()794 static int open_SpecWin()
795 		/*success-> return 0;*/
796 {
797 #ifdef SUPPORT_SOUNDSPEC
798 	open_window(&win, kSpecWinID);
799 	position_window(&win);
800 
801 	//always
802 	//if( win.show ){ //Preference on
803 		open_soundspec();
804 	   	soundspec_update_wave(NULL, 0);
805 	//}
806 #endif /* SUPPORT_SOUNDSPEC */
807 	return 0;
808 }
809 
click_SpecWin(Point,short)810 static void click_SpecWin(Point /*local*/, short /*modifiers*/)
811 {
812 }
813 
update_SpecWin()814 static void update_SpecWin()
815 {
816 	SetPortWindowPort(win.ref);
817 }
818 
goaway_SpecWin(MacWindow * macwin)819 static void goaway_SpecWin(MacWindow *macwin)
820 {
821 	goaway_default(macwin);
822 	//close_soundspec();
823 }
824 
message_SpecWin(int message,long)825 static int	message_SpecWin(int message, long /*param*/)
826 {
827 	Rect rect;
828 
829 	switch(message){
830 	case MW_GROW:
831 		rect=win.ref->portRect;
832 		//rect.right-=15; rect.bottom-=15;
833 		rect = win.ref->portRect;
834 		rect.right  -= 15;
835 		//rect.bottom -= 15;
836 		return 0;
837 
838 	}
839 
840 	return -1;  //not supported
841 }
842 
843 #undef win
844 // *****************************************************
845 #pragma mark -
846 static MacWindow* WindowList[]={
847 	&mac_PlayerWindow,
848 	&mac_LogWindow,
849 	&mac_ListWindow,
850 	&mac_WrdWindow,
851 	&mac_DocWindow,
852 	&mac_SpecWindow,
853 	&mac_TraceWindow,
854 	&mac_SkinWindow,
855 	0
856 };
857 
DoUpdate(WindowRef win_ref)858 void DoUpdate(WindowRef win_ref)
859 {
860 	MacWindow* macwin;
861 
862 	macwin = (MacWindow*)GetWRefCon(win_ref);
863 	if( macwin ) macwin->update();
864 }
865 
mac_AdjustMenus(short modifiers)866 static void mac_AdjustMenus(short modifiers)
867 {
868 	MenuHandle	filenemu=GetMenu(mFile),
869 				synthemu=GetMenu(mSynth);
870 
871 
872 	//CheckItem(filenemu, iLogWindow  & 0xFFFF, gShowMsg);
873 	//CheckItem(filenemu, iListWindow & 0xFFFF, gShowList);
874 	//CheckItem(filenemu, iWrdWindow  & 0xFFFF, gShowWrd);
875 	if( modifiers & optionKey ){
876 		//EnableItem(filenemu, iSkinWindow);
877 		EnableItem(synthemu, iQuickTime);
878 		EnableItem(synthemu, iOMS);
879 	}
880 }
881 
HandleMouseDown(EventRecord * event)882 void HandleMouseDown(EventRecord *event)
883 {
884 	short	part;
885 	WindowRef	window;
886 	MacWindow   *macwin;
887 	Rect		growRect={100,100,32000,32000};
888 	long		size;
889 
890 	part=FindWindow(event->where, &window);
891 	macwin = (MacWindow*)GetWRefCon(window);
892 
893 	switch(part)
894 	{
895 	case inMenuBar:
896 		mac_AdjustMenus(event->modifiers);
897 		mac_HandleMenuSelect(MenuSelect(event->where), event->modifiers);
898 		HiliteMenu(0);
899 		break;
900 	case inContent:
901 		SetPortWindowPort(window);
902 		SelectWindow(window);
903 		GlobalToLocal(&event->where);
904 		if(macwin) macwin->click(event->where, event->modifiers);
905 		break;
906 	case inDrag:
907 		DragWindow(window, event->where, &qd.screenBits.bounds);
908 		break;
909 	case inGrow:
910 		SetPortWindowPort(window);
911 		size=GrowWindow(window, event->where, &growRect);
912 		if( size )
913 		{
914 			SizeWindow(window, size&0x0000FFFF, size>>16, 0);
915 			EraseRect(&GetWindowPort(window)->portRect);
916 			InvalRect(&GetWindowPort(window)->portRect);
917 			if( macwin ) macwin->message(MW_GROW, size);
918 		}
919 		break;
920 	case inGoAway:
921 		if( TrackGoAway(window, event->where) ){
922 			if( macwin ){
923 				macwin->goaway(macwin);
924 			}
925 		}
926 		break;
927 	//case inZoomIn:
928 	//case inZoomOut:
929 	//	break;
930 	}
931 }
932 
933 // *****************************************************
934 #pragma mark -
935 #pragma mark ===============control function
936 
937 
ctl_open(int,int)938 static int ctl_open(int /*using_stdin*/, int /*using_stdout*/)
939 		/*success-> return 0;*/
940 {
941 	int i, err;
942 
943 	for(i=0; WindowList[i]; i++){
944 		err=WindowList[i]->open();
945 		if(err) break;
946 	}
947 	if( !err ) ctl.opened=1;
948 	return err;
949 }
950 
ctl_close(void)951 static void ctl_close(void)
952 {
953 	int i;
954 	for( i=0; WindowList[i]; i++ ){
955 		WindowList[i]->close(WindowList[i]);
956 	}
957 
958 	ctl.opened=0;
959 	return;
960 }
961 
962 
ctl_pass_playing_list(int init_number_of_files,char * [])963 static int ctl_pass_playing_list(int init_number_of_files,
964 				  char * /*init_list_of_files*/ [])
965 {
966 	EventRecord	event;
967 
968 	if( init_number_of_files!=0 ){
969 		cmsg(CMSG_FATAL, VERB_NORMAL,
970 		  "ctl_pass_playing_list: Sorry. Fatal error.");
971 	}
972 
973 #ifdef MAC_USE_OMS
974 	mac_oms_setup();
975 #endif
976 
977 	{
978 		FSSpec	spec;
979 		OSErr	err;
980 		err=FSMakeFSSpec(0, 0, MAC_STARTUP_FOLDER_NAME, &spec);
981 		if( err==noErr ){ mac_add_fsspec( &spec ); }
982 	}
983 
984 	gQuit=false;
985 	while(!gQuit)
986 	{
987 		WaitNextEvent(everyEvent, &event, 1,0);
988 		mac_HandleEvent(&event);
989 	}
990 	Do_Quit();
991 	return 0;
992 }
993 
UserWantsControl()994 static Boolean UserWantsControl()
995 {
996 	/* Mouse down��or key down��*/
997 	KeyMap km;
998 
999 	GetKeys(km);
1000 	km[1] &= ~0x02; /* exclude caps lock */
1001 	return   Button() || km[0]|| km[1] || km[2] || km[3] || skin_state==PAUSE;
1002 }
1003 
ctl_read(int32 *)1004 static int ctl_read(int32* /*valp*/)
1005 {
1006 	int			ret;
1007 
1008 	if (cuepoint_pending) {
1009 		*valp = cuepoint;
1010 		cuepoint_pending = 0;
1011 		return RC_FORWARD;
1012 	}
1013 
1014 	//if( gCursorIsWatch ){ gCursorIsWatch=false; InitCursor(); }
1015 	if( gQuit ) Do_Quit();	/* Quit Apple event occured */
1016 	if( mac_rc ){ret=mac_rc; mac_rc=0; return ret;}
1017 	if( !gBusy || UserWantsControl()){
1018 		YieldToAnyThread();
1019 	}
1020 	return RC_NONE;
1021 }
1022 
ctl_lyric(int lyricid)1023 static void ctl_lyric(int lyricid)
1024 {
1025 	char *lyric;
1026 
1027 	lyric = event2string(lyricid);
1028 	if(lyric == NULL) return;
1029 	ctl.cmsg(CMSG_TEXT, VERB_VERBOSE, "%s", lyric + 1);
1030 }
1031 
ctl_gslcd(int lyricid)1032 static void ctl_gslcd(int lyricid)
1033 {
1034 	char *lyric;
1035 
1036 	lyric = event2string(lyricid);
1037 	if(lyric == NULL) return;
1038 
1039 	if( lyric[0] == ME_GSLCD ){
1040 		int i,j, data, mask;
1041 		char tmp[3]= "00";
1042 
1043 		lyric++;
1044 		for( j=0; j<4; j++ ){
1045 		for( i=0; i<16; i++ ){
1046 			tmp[0]= lyric[0]; tmp[1]= lyric[1]; lyric+=2;
1047 			sscanf(tmp, "%X", &data);
1048 			mask=0x10;
1049 			ctl_note((data&mask)? VOICE_ON:-1, i, 40+j*10, 127);
1050 			ctl_note((data&mask)? VOICE_ON:-1, i, 41+j*10, 127); mask>>=1;
1051 			ctl_note((data&mask)? VOICE_ON:-1, i, 42+j*10, 127);
1052 			ctl_note((data&mask)? VOICE_ON:-1, i, 43+j*10, 127); mask>>=1;
1053 			ctl_note((data&mask)? VOICE_ON:-1, i, 44+j*10, 127);
1054 			ctl_note((data&mask)? VOICE_ON:-1, i, 45+j*10, 127); mask>>=1;
1055 			ctl_note((data&mask)? VOICE_ON:-1, i, 46+j*10, 127);
1056 			ctl_note((data&mask)? VOICE_ON:-1, i, 47+j*10, 127); mask>>=1;
1057 			ctl_note((data&mask)? VOICE_ON:-1, i, 48+j*10, 127);
1058 			ctl_note((data&mask)? VOICE_ON:-1, i, 49+j*10, 127); mask>>=1;
1059 		}
1060 		}
1061 		return;
1062 	}
1063 	//else normal text
1064 	ctl.cmsg(CMSG_TEXT, VERB_VERBOSE, "%s", lyric + 1);
1065 }
1066 
cmsg(int type,int verbosity_level,char * fmt,...)1067 static int cmsg(int type, int verbosity_level, char * fmt, ...)
1068 {
1069 #define BUFSIZE 1024
1070   char	buf[BUFSIZE];
1071   va_list ap;
1072 
1073   if ((type==CMSG_TEXT || type==CMSG_INFO || type==CMSG_WARNING) &&
1074       ctl.verbosity<verbosity_level){
1075 		return 0;
1076 	}
1077   va_start(ap, fmt);
1078     {
1079     	vsnprintf(buf, BUFSIZE, fmt, ap);
1080 		if(mac_LogWindow.ref ){
1081 			PrintLogStr(buf);
1082 			PrintLogStr("\r");
1083 		}
1084 		if( !mac_LogWindow.ref || type==CMSG_FATAL){
1085       		StopAlertMessage(c2pstr(buf));  /* no Window or Fatal ERR*/
1086     	}
1087 	}
1088   	va_end(ap);
1089   	return 0;
1090 }
1091 
ctl_refresh(void)1092 static void ctl_refresh(void)
1093 {}
1094 
ctl_total_time(int tt)1095 static void ctl_total_time(int tt)
1096 {
1097 	mac_trc_update_time( -1, tt/play_mode->rate);
1098 	mac_SkinWindow.message(MW_SKIN_TOTAL_TIME, tt/play_mode->rate);
1099 }
1100 
ctl_master_volume(int)1101 static void ctl_master_volume(int /*mv*/) {}
1102 
ctl_file_name(char * name)1103 static void ctl_file_name(char *name)
1104 {
1105 	int	i;
1106 	char	*s;
1107 
1108 	for( i=strlen(name); i>=0; i--)
1109 		if( name[i]==PATH_SEP ) {
1110 			s=&name[i]+1; //remove pathname
1111 			break;
1112 		}
1113 	snprintf(fileStr, FILESTR_LEN, "%d. %s", nPlaying+1, s);
1114 
1115 	if (ctl.verbosity>=0 || ctl.trace_playing){
1116 		DrawFileStr();
1117 	}
1118 	mac_ListWindow.message(MW_LIST_SELECT, nPlaying);
1119 	mac_DocWindow.message(MW_DOC_SET, (long)name);
1120 	mac_trc_update_all_info();
1121 	mac_SkinWindow.message(MW_SKIN_FILENAME, (long)fileStr);
1122 }
1123 
ctl_current_time(int current,int)1124 static void ctl_current_time(int current, int /*v*/)
1125 {
1126 	static int	lastSec=-1, lastYieldThread=-1;
1127 	int			mins, secs, realSecs;
1128 
1129 	if( gStartTick==0 ) gStartTick=TickCount();
1130 						/*select*/
1131 	realSecs=(TickCount()-gStartTick)/60; /*real time*/
1132 	secs=current;
1133 
1134 	if( secs!=lastSec && (skin_state==PLAYING || skin_state==PAUSE))
1135 	{
1136 		lastSec=secs;
1137 		mins=secs/60;
1138 		secs-=mins*60;
1139 		snprintf(timeStr, TIMESTR_LEN, "%02d:%02d", mins, secs);
1140 		DrawTimeStr();
1141 		mac_trc_update_time(current,-1);
1142 		mac_SkinWindow.message(MW_SKIN_TIME, lastSec);
1143 	}
1144 	if( realSecs!=lastYieldThread ){
1145 		lastYieldThread= realSecs;
1146 		mac_trc_update_time(current,-1);
1147 		mac_trc_update_voices();
1148 		if( (realSecs % (evil_level*evil_level))==0 )
1149 			YieldToAnyThread();		// YieldToAnyThread every 1sec
1150 	}
1151 }
1152 
ctl_note(int status,int ch,int note,int vel)1153 static void ctl_note(int status, int ch, int note, int vel)
1154 {
1155 	if( ! mac_TraceWindow.show ) return;
1156     if(note == -1)
1157     {
1158 	//if(ctl.trace_playing && !midi_trace.flush_flag)
1159 	//    push_midi_trace0(update_indicator);
1160 	return;
1161     }
1162     //push_midi_note(v_ctl_note, note);
1163     v_ctl_note( status, ch, note, vel);
1164 }
1165 
ctl_program(int ch,int val,char * comm)1166 static void ctl_program(int ch, int val, char *comm){mac_ctl_program(ch,val,comm);}
1167 
ctl_volume(int,int)1168 static void ctl_volume(int /*channel*/, int /*val*/) {}
1169 
ctl_expression(int,int)1170 static void ctl_expression(int /*channel*/, int /*val*/) {}
1171 
ctl_panning(int,int)1172 static void ctl_panning(int /*channel*/, int /*val*/) {}
1173 
ctl_sustain(int,int)1174 static void ctl_sustain(int /*channel*/, int /*val*/) {}
1175 
ctl_pitch_bend(int,int)1176 static void ctl_pitch_bend(int /*channel*/, int /*val*/) {}
1177 
ctl_reset(void)1178 static void ctl_reset(void)
1179 {
1180 	mac_ctl_reset_trc();
1181 }
1182 
ctl_event(CtlEvent * e)1183 static void ctl_event(CtlEvent *e)
1184 {
1185     switch(e->type)
1186     {
1187       case CTLE_NOW_LOADING:
1188 	ctl_file_name((char *)e->v1);
1189 	break;
1190       case CTLE_LOADING_DONE:
1191 	break;
1192       case CTLE_PLAY_START:
1193 	ctl_total_time((int)e->v1);
1194 	break;
1195       case CTLE_PLAY_END:
1196 	break;
1197 	case CTLE_CUEPOINT:
1198 		cuepoint = e->v1;
1199 		cuepoint_pending = 1;
1200 		break;
1201       case CTLE_TEMPO:
1202 	break;
1203       case CTLE_METRONOME:
1204 	break;
1205       case CTLE_CURRENT_TIME:
1206 	ctl_current_time((int)e->v1, (int)e->v2);
1207 	break;
1208       case CTLE_NOTE:
1209 	ctl_note((int)e->v1, (int)e->v2, (int)e->v3, (int)e->v4);
1210 	break;
1211       case CTLE_MASTER_VOLUME:
1212 	ctl_master_volume((int)e->v1);
1213 	break;
1214       case CTLE_PROGRAM:
1215 	ctl_program((int)e->v1, (int)e->v2, (char *)e->v3);
1216 	break;
1217       case CTLE_VOLUME:
1218 	ctl_volume((int)e->v1, (int)e->v2);
1219 	break;
1220       case CTLE_EXPRESSION:
1221 	ctl_expression((int)e->v1, (int)e->v2);
1222 	break;
1223       case CTLE_PANNING:
1224 	ctl_panning((int)e->v1, (int)e->v2);
1225 	break;
1226       case CTLE_SUSTAIN:
1227 	ctl_sustain((int)e->v1, (int)e->v2);
1228 	break;
1229       case CTLE_PITCH_BEND:
1230 	ctl_pitch_bend((int)e->v1, (int)e->v2);
1231 	break;
1232       case CTLE_MOD_WHEEL:
1233 	ctl_pitch_bend((int)e->v1, e->v2 ? -1 : 0x2000);
1234 	break;
1235       case CTLE_CHORUS_EFFECT:
1236 	break;
1237       case CTLE_REVERB_EFFECT:
1238 	break;
1239       case CTLE_LYRIC:
1240 	ctl_lyric((int)e->v1);
1241 	break;
1242       case CTLE_GSLCD:
1243 	ctl_gslcd((int)e->v1);
1244 	break;
1245       case CTLE_REFRESH:
1246 	ctl_refresh();
1247 	break;
1248       case CTLE_RESET:
1249 	ctl_reset();
1250 	break;
1251 #ifdef SUPPORT_SOUNDSPEC
1252       case CTLE_SPEANA:
1253         ctl_speana_data((double *)e->v1, (int)e->v2);
1254       break;
1255 #endif /* SUPPORT_SOUNDSPEC */
1256     }
1257 }
1258 
1259