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