1 /*
2     TiMidity++ -- MIDI to WAVE converter and player
3     Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp>
4     Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 
20 	Macintosh interface for TiMidity
21 	by T.Nogami	<t-nogami@happy.email.ne.jp>
22 
23     mac_trace.c
24     Macintosh trace window
25 */
26 
27 // includs
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif /* HAVE_CONFIG_H */
31 #include "string.h"
32 #include "timidity.h"
33 #include "common.h"
34 #include "output.h"
35 #include "controls.h"
36 #include "instrum.h"
37 #include "playmidi.h"
38 #include "miditrace.h"
39 #include "bitset.h"
40 #include "mfnode.h"
41 //#include "aq.h"
42 
43 #include "mac_main.h"
44 #include "mac_util.h"
45 #include "mac_c.h"
46 
47 // macros & const
48 #define UPPER_MERGIN 40
49 #define LEFT_MERGIN  130
50 #define CHANNEL_HIGHT 12
51 #define CHANNEL_WIDTH 4
52 #define win mac_TraceWindow
53 #define COLS 80
54 const RGBColor	black={0,0,0};
55 
56 // global
57 static int selected_channel = -1;
58 static int current_voices=0;
59 static Bitset channel_program_flags[MAX_CHANNELS];
60 static int scr_modified_flag = 1; /* delay flush for trace mode */
61 static int display_velocity_flag = 0;
62 static const char note_name_char[12] =
63 {
64     'c', 'C', 'd', 'D', 'e', 'f', 'F', 'g', 'G', 'a', 'A', 'b'
65 };
66 
67 // static function
68 static int open_TraceWin();
69 static void click_TraceWin(Point local, short modifiers);
70 static void update_TraceWin();
71 static void goaway_TraceWin();
72 static void close_TraceWin();
73 static int	message_TraceWin(int message, long param);
74 // ****************************************************
init_trace_window_chan(int)75 static void init_trace_window_chan(int /*ch*/)
76 {
77 }
78 
DrawInstrumentName(int ch,char * comm)79 static void DrawInstrumentName(int ch, char *comm)
80 {
81 	char		buf[80];
82 	RGBColor	black={0,0,0};
83 	Rect		box;
84 
85 	SetPortWindowPort(win.ref);
86 	RGBForeColor(&black);
87 
88 		//channel number
89 	MoveTo(2, UPPER_MERGIN+CHANNEL_HIGHT*(ch+1)-1);
90 	snprintf(buf, 80,"%2d", ch+1);
91 	DrawText(buf, 0, strlen(buf));
92 
93 		//InstrumentName
94 	box.top=UPPER_MERGIN+CHANNEL_HIGHT*ch;
95 	box.left=20;
96 	box.bottom=box.top+12;
97 	box.right=LEFT_MERGIN-10;
98 	if( !comm || !*comm )
99 		EraseRect(&box);
100 	else
101 		TETextBox(comm, strlen(comm), &box, teFlushDefault);
102 }
103 
mac_ctl_refresh_trc()104 static void mac_ctl_refresh_trc()
105 {
106 	int		i;
107 	Rect	r;
108 	RGBColor	black={0,0,0},
109 				darkGray={0x2000,0x2000,0x2000};
110 
111 	if( !win.show ) return;
112 	SetPortWindowPort(win.ref);
113 	for( i=0; i<16; i++ ){
114 		DrawInstrumentName(i, instr_comment[i].comm);
115 	}
116 
117 #define MAX_NOTE_NUM 120
118 	r.top=		UPPER_MERGIN;
119 	r.left=		LEFT_MERGIN;
120 	r.bottom=	r.top+CHANNEL_HIGHT*16;
121 	r.right=	r.left+CHANNEL_WIDTH*MAX_NOTE_NUM;
122 	RGBForeColor(&darkGray);
123 	PaintRect(&r);
124 
125 		//draw separater line
126 	RGBForeColor(&black);
127 	for(i=1; i<16; i++){	//horizontal
128 		MoveTo(LEFT_MERGIN, UPPER_MERGIN+CHANNEL_HIGHT*i-1);
129 		Line(CHANNEL_WIDTH*MAX_NOTE_NUM-1, 0);
130 	}
131 	for(i=12; i<MAX_NOTE_NUM; i+=12){	//vertical
132 		MoveTo(LEFT_MERGIN+CHANNEL_WIDTH*i-1, UPPER_MERGIN);
133 		Line(0, CHANNEL_HIGHT*16-1);
134 	}
135 }
136 
mac_ctl_reset_trc()137 void mac_ctl_reset_trc()
138 {
139 	int i;
140 
141     for(i = 0; i < MAX_CHANNELS; i++)
142     {
143 		instr_comment[i].last_note_on = 0.0;
144 		instr_comment[i].comm =""; // channel_instrum_name(i);
145 		clear_bitset(channel_program_flags + i, 0, 128);
146     }
147 	SetPortWindowPort(win.ref);
148 	TextMode(srcCopy);
149 	TextSize(9);
150 	mac_ctl_refresh_trc();
151 	current_voices=0;
152 }
153 
mac_ctl_program(int ch,int val,void * comm)154 void mac_ctl_program(int ch, int val, void *comm)
155 {
156     int pr;
157 
158     if(ch >= 16)
159 	return;
160 
161     if(!ctl->trace_playing)
162 	return;
163 
164     if(IS_CURRENT_MOD_FILE)
165 		pr = val;
166     else
167 		pr = val + progbase;
168 
169     //if(ctl_ncurs_mode == NCURS_MODE_TRACE)
170     {
171 		if(ch == selected_channel)
172 			init_trace_window_chan(ch);
173 		else
174 		{
175 			//wmove(dftwin, NOTE_LINE+ch, COLS-21);
176 			if(ISDRUMCHANNEL(ch))
177 			{
178 				//wattron(dftwin, A_BOLD);
179 				//wprintw(dftwin, " %03d", pr);
180 				//wattroff(dftwin, A_BOLD);
181 		    }
182 		    else
183 			//wprintw(dftwin, " %03d", pr);
184 			;
185 		}
186     }
187 
188     //if(comm != NULL)
189 	indicator_set_prog(ch, val, (char *)comm);
190     //scr_modified_flag = 1;
191 
192 	instr_comment[ch].last_note_on = 0.0;
193 	instr_comment[ch].comm = channel_instrum_name(ch);
194 	DrawInstrumentName(ch, instr_comment[ch].comm);
195 }
196 // ****************************************************
197 #pragma mark -
update_channel(int)198 static void update_channel(int /*ch*/)
199 {
200 
201 }
202 
update_filename()203 static void update_filename()
204 {
205 	char	buf[256]="";
206 
207 	if( !mac_TraceWindow.show ) return;
208 	SetPortWindowPort(win.ref);
209 
210 	if( mac_n_files>0 && nPlaying<=mac_n_files && fileList[nPlaying].mfn &&
211 										fileList[nPlaying].mfn->file )
212 		snprintf(buf, 256,"File: %s", fileList[nPlaying].mfn->file);
213 	RGBForeColor(&black);
214 	MoveTo(2,12); DrawText(buf, 0, strlen(buf));
215 }
216 
update_title()217 static void update_title()
218 {
219 	char	buf[256]="";
220 
221 	if( !mac_TraceWindow.show ) return;
222 	SetPortWindowPort(win.ref);
223 	if( mac_n_files>0 && nPlaying<=mac_n_files && fileList[nPlaying].mfn &&
224 										fileList[nPlaying].mfn->title )
225 		snprintf(buf, 256, "Title: %s", fileList[nPlaying].mfn->title);
226 	RGBForeColor(&black);
227 	MoveTo(2,24); DrawText(buf, 0, strlen(buf));
228 }
229 
mac_trc_update_time(int cur_sec,int tot_sec)230 void mac_trc_update_time( int cur_sec, int tot_sec )
231 {
232 	static int	save_tot_sec=0, save_cur_sec;
233 	//int rate;
234 	char		buf[80];
235 
236 	if( cur_sec!=-1 ) save_cur_sec=tot_sec;
237 	if( tot_sec!=-1 ) save_tot_sec=tot_sec;
238 	if( cur_sec==-1 ) cur_sec=0;
239 	if( cur_sec > save_tot_sec ) cur_sec=save_tot_sec;
240 
241 	if( !win.show ) return;
242 	//rate = (int)(aq_filled_ratio() * 100 + 0.5);
243 
244 	SetPortWindowPort(win.ref);
245 	snprintf(buf, 80," %3d:%02d /%3d:%02d   " /*"buffering=%3d %% "*/ "buffer %d/256  ",
246 		cur_sec/60, cur_sec%60, save_tot_sec/60,save_tot_sec%60,
247 		/*rate,*/ mac_buf_using_num );
248 	RGBForeColor(&black);
249 	MoveTo(400,12); DrawText(buf, 0, strlen(buf));
250 }
251 
mac_trc_update_voices()252 void mac_trc_update_voices()
253 {
254 	char	buf[20];
255 	static	int	prev=-1;
256 
257 	if( !mac_TraceWindow.show ) return;
258 	SetPortWindowPort(win.ref);
259 
260 	snprintf(buf, 20, "Voice %3d/%3d   ", current_voices, voices);
261 	RGBForeColor(&black);
262 	MoveTo(450,24); DrawText(buf, 0, strlen(buf));
263 }
264 
mac_trc_update_all_info()265 void mac_trc_update_all_info()
266 {
267 	Rect r;
268 
269 	SetPortWindowPort(win.ref);
270 	SetRect(&r, 0,0, win.ref->portRect.right,UPPER_MERGIN);
271 	EraseRect(&r);
272 
273 	mac_trc_update_voices();
274 	update_filename();
275 	update_title();
276 	mac_trc_update_time(-1,-1);
277 }
278 // *****************************************************
279 #pragma mark -
280 MacWindow win={
281 	0,	//WindowRef
282 	open_TraceWin,
283 	click_TraceWin,
284 	update_TraceWin,
285 	goaway_default,
286 	close_default,
287 	message_TraceWin,
288 	0, 120,120
289 };
290 
open_TraceWin()291 static int open_TraceWin()
292 		/*success-> return 0;*/
293 {
294 	int		i;
295 
296 	open_window(&win, kTraceWinID);
297 	position_window(&win);
298 
299 	mac_ctl_reset_trc();
300 	for(i = 0; i < 16; i++)
301 	    init_bitset(channel_program_flags + i, 128);
302 
303 	return 0;
304 }
305 
click_TraceWin(Point,short)306 static void click_TraceWin(Point /*local*/, short /*modifiers*/)
307 {
308 }
309 
update_TraceWin()310 static void update_TraceWin()
311 {
312 	SetPortWindowPort(win.ref);
313 	mac_ctl_refresh_trc();
314 	mac_trc_update_all_info();
315 }
316 
message_TraceWin(int,long)317 static int	message_TraceWin(int /*message*/, long /*param*/)
318 {
319 	//Rect rect;
320 
321 	//switch(message){
322 	//}
323 
324 	return -1;  //not supported
325 }
326 
327 const RGBColor	vel_color[10]={
328 					{0x0000, 0x0000, 0xFFFF},	//0:blue
329 					{0x0000, 0xFFFF, 0x0000},	//6;green
330 					{0x0000, 0x6666, 0xFFFF},	//1;
331 					{0x0000, 0xFFFF, 0x6666},	//5;
332 					{0x6666, 0xFFFF, 0x0000},	//7;
333 					{0x0000, 0x9999, 0xFFFF},	//2;
334 					{0x0000, 0xFFFF, 0x9999},	//4;
335 					{0x9999, 0xFFFF, 0x0000},	//8;
336 					{0x0000, 0xFFFF, 0xFFFF},	//3;
337 					{0xFFFF, 0xFFFF, 0x0000},	//9;yellow
338 				};
339 
340 #define DARKEN2(c) (c.red/=2,c.green/=2,c.blue/=2)
341 #define DARKEN4(c) (c.red/=4,c.green/=4,c.blue/=4)
342 
UpdateNote(int status,int ch,int note,int vel)343 static unsigned int UpdateNote(int status, int ch, int note, int vel)
344 {
345 	//int	vel;
346 	Rect r1,r2;
347     unsigned int onoff=0 /*, check, prev_check*/;
348 	const RGBColor	dieColor=	{0x3000,0x3000,0x3000},	//dark gray
349 					freeColor=	{0x3000,0x3000,0x3000},	//dark gray
350 			onColor=	{0xffff,0xffff,0}, 	//yellow
351 					sustainedColor={0x8000,0x8000,0},	//dark yellow
352 			offColor=	{0x4000,0x4000,0},	//dark yellow
353 			noColor=	{0x2000,0x2000,0x2000};
354 	RGBColor	color;
355 
356 	vel=(10 * vel) / 128; /* 0-9 */
357 	if( vel>9 ) vel=9;
358 
359 	r1.left=r2.left=	LEFT_MERGIN+CHANNEL_WIDTH* note;
360 	r1.right=r2.right=	r1.left+CHANNEL_WIDTH-1;
361 
362 	r1.top=		UPPER_MERGIN+CHANNEL_HIGHT* ch;
363 	r1.bottom= 	r1.top+(9-vel);
364 	r2.top=		r1.bottom;
365 	r2.bottom=	r1.top+CHANNEL_HIGHT-1;
366 
367 	SetPortWindowPort(win.ref);
368 
369     color=vel_color[vel];
370     switch(status){
371 	case VOICE_DIE:	 DARKEN2(color);  onoff = 1;	break;
372 	case VOICE_FREE: color=freeColor; onoff = 0;	break;
373 	case VOICE_SUSTAINED:DARKEN2(color); onoff = 1;	break;
374 	case VOICE_OFF:	DARKEN4(color); onoff = 1;		break;
375 	case VOICE_ON:			onoff = 1;		break;
376 	default:	color= noColor; break;
377     }
378     RGBForeColor(&freeColor);
379     PaintRect(&r1);
380     RGBForeColor(&color);
381     PaintRect(&r2);
382     return onoff;
383 }
384 
385 
386 //void v_ctl_note(struct MidiTraceNote v)
v_ctl_note(int status,int ch,int note,int vel)387 void v_ctl_note(int status, int ch, int note, int vel)
388 {
389     int xl, n, c;
390     unsigned int onoff=0, prev_onoff, check;
391     Bitset *bitset;
392 
393     if( !mac_TraceWindow.show || ch >= 16)
394 	return;
395 
396     if( /*ctl_ncurs_mode != NCURS_MODE_TRACE ||*/ selected_channel == ch)
397 		return;
398 
399     scr_modified_flag = 1;
400     if(display_velocity_flag)
401 		n = '0' + (10 * vel) / 128;
402     else
403 		n = note_name_char[note % 12];
404     c = (COLS - 24) / 12 * 12;
405     if(c <= 0)
406 		c = 1;
407     xl=note % c;
408     if( note>=MAX_NOTE_NUM ) return;
409 
410 	onoff= UpdateNote( status, ch, note, vel);   //draw at first
411     bitset = channel_program_flags + ch;
412 	get_bitset(bitset, &prev_onoff, note, 1);
413     onoff <<= (8 * sizeof(onoff) - 1);
414     set_bitset(bitset, &onoff, note, 1);
415     check = has_bitset(bitset);
416 
417 	if( prev_onoff && !onoff ) current_voices--;
418 	if( !prev_onoff && onoff ){
419 		current_voices++;
420 		mac_trc_update_voices();
421 	}
422 
423 }
424 
425 #undef win
426