1 /* OpenCP Module Player
2 * copyright (c) '94-'10 Niklas Beisert <nbeisert@physik.tu-muenchen.de>
3 * copyright (c) '04-'20 Stian Skjelstad <stian.skjelstad@gmail.com>
4 *
5 * ITPlayer interface routines
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 * revision history: (please note changes here)
22 * -nb980510 Niklas Beisert <nbeisert@physik.tu-muenchen.de>
23 * -first release
24 * -kb980717 Tammo Hinrichs <kb@nwn.de>
25 * -added many many things to provide channel display and stuff
26 * -removed some bugs which caused crashing in some situations
27 * -ss040709 Stian Skjelstad <stian@nixia.no>
28 * -use compatible timing instead of cputime/clock()
29 */
30
31 #include "config.h"
32 #include <time.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <stdio.h>
36 #include "types.h"
37 #include "boot/plinkman.h"
38 #include "boot/psetting.h"
39 #include "cpiface/cpiface.h"
40 #include "dev/deviwave.h"
41 #include "dev/mcp.h"
42 #include "filesel/filesystem.h"
43 #include "filesel/mdb.h"
44 #include "filesel/pfilesel.h"
45 #include "itplay.h"
46 #include "stuff/compat.h"
47 #include "stuff/err.h"
48 #include "stuff/poutput.h"
49
50 #define _MAX_FNAME 8
51 #define _MAX_EXT 4
52
53 __attribute__ ((visibility ("internal"))) struct itplayer itplayer = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
54 static struct it_module mod = {{0},0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,{0},{0},0,0,0,0,0};
55
56 static struct it_instrument *insts;
57 static struct it_sample *samps;
58
59
60 static const char *modname;
61 static const char *composer;
62
63 static char currentmodname[_MAX_FNAME+1];
64 static char currentmodext[_MAX_EXT+1];
65 static time_t starttime;
66 static time_t pausetime;
67
68
69 void itpInstClear();
70
itpProcessKey(uint16_t key)71 static int itpProcessKey(uint16_t key)
72 {
73 int row;
74 int pat, p;
75
76 switch (key)
77 {
78 case KEY_ALT_K:
79 cpiKeyHelp('p', "Start/stop pause with fade");
80 cpiKeyHelp('P', "Start/stop pause with fade");
81 cpiKeyHelp(KEY_CTRL_P, "Start/stop pause");
82 cpiKeyHelp('<', "Jump back (big)");
83 cpiKeyHelp(KEY_CTRL_LEFT, "Jump back (big)");
84 cpiKeyHelp('>', "Jump forward (big)");
85 cpiKeyHelp(KEY_CTRL_RIGHT, "Jump forward (big)");
86 cpiKeyHelp(KEY_CTRL_UP, "Jump back (small)");
87 cpiKeyHelp(KEY_CTRL_DOWN, "Jump forward (small)");
88 mcpSetProcessKey(key);
89 if (mcpProcessKey)
90 mcpProcessKey(key);
91 return 0;
92 case 'p': case 'P': case KEY_CTRL_P:
93 if (plPause)
94 starttime=starttime+dos_clock()-pausetime;
95 else
96 pausetime=dos_clock();
97 mcpSet(-1, mcpMasterPause, plPause^=1);
98 plChanChanged=1;
99 break;
100 /*
101 case 0x7700: //ctrl-home TODO keys
102 itpInstClear();
103 itplayer.setpos(0, 0);
104 if (plPause)
105 starttime=pausetime;
106 else
107 starttime=dos_clock();
108 break;
109 */
110 case '<':
111 case KEY_CTRL_LEFT:
112 /* case 0x7300: //ctrl-left */
113 p=getpos(&itplayer);
114 pat=p>>16;
115 setpos(&itplayer, pat-1, 0);
116 break;
117 case '>':
118 case KEY_CTRL_RIGHT:
119 /* case 0x7400: //ctrl-right */
120 p=getpos(&itplayer);
121 pat=p>>16;
122 setpos(&itplayer, pat+1, 0);
123 break;
124 case KEY_CTRL_UP:
125 /* case 0x8D00: //ctrl-up */
126 p=getpos(&itplayer);
127 pat=p>>16;
128 row=(p>>8)&0xFF;
129 setpos(&itplayer, pat, row-8);
130 break;
131 case KEY_CTRL_DOWN:
132 /* case 0x9100: //ctrl-down */
133 p=getpos(&itplayer);
134 pat=p>>16;
135 row=(p>>8)&0xFF;
136 setpos(&itplayer, pat, row+8);
137 break;
138 default:
139 if (mcpSetProcessKey(key))
140 return 1;
141 if (mcpProcessKey)
142 {
143 int ret=mcpProcessKey(key);
144 if (ret==2)
145 cpiResetScreen();
146 if (ret)
147 return 1;
148 }
149 }
150 return 1;
151 }
152
itpLooped(void)153 static int itpLooped(void)
154 {
155 return !fsLoopMods&&getloop(&itplayer);
156 }
157
itpIdle(void)158 static void itpIdle(void)
159 {
160 setloop(&itplayer, fsLoopMods);
161 if (mcpIdle)
162 mcpIdle();
163 }
164
itpDrawGStrings(uint16_t (* buf)[CONSOLE_MAX_X])165 static void itpDrawGStrings(uint16_t (*buf)[CONSOLE_MAX_X])
166 {
167 int pos=getrealpos(&itplayer)>>8;
168 int gvol, bpm, tmp, gs;
169 long tim;
170
171 mcpDrawGStrings(buf);
172
173 getglobinfo(&itplayer, &tmp, &bpm, &gvol, &gs);
174
175 if (plPause)
176 tim=(pausetime-starttime)/DOS_CLK_TCK;
177 else
178 tim=(dos_clock()-starttime)/DOS_CLK_TCK;
179
180 if (plScrWidth<128)
181 {
182 memset(buf[0]+80, 0, (plScrWidth-80)*sizeof(uint16_t));
183 memset(buf[1]+80, 0, (plScrWidth-80)*sizeof(uint16_t));
184 memset(buf[2]+80, 0, (plScrWidth-80)*sizeof(uint16_t));
185
186 writestring(buf[1], 0, 0x09, " row: ../.. ord: .../... speed: .. bpm: ... gvol: ..\xfa ", 58);
187 writenum(buf[1], 6, 0x0F, pos&0xFF, 16, 2, 0);
188 writenum(buf[1], 9, 0x0F, mod.patlens[mod.orders[pos>>8]]-1, 16, 2, 0);
189 writenum(buf[1], 18, 0x0F, pos>>8, 16, 3, 0);
190 writenum(buf[1], 22, 0x0F, mod.nord-1, 16, 3, 0);
191 writenum(buf[1], 34, 0x0F, tmp, 16, 2, 1);
192 writenum(buf[1], 43, 0x0F, bpm, 10, 3, 1);
193 writenum(buf[1], 54, 0x0F, gvol, 16, 2, 0);
194 writestring(buf[1], 56, 0x0F, (gs==ifxGVSUp)?"\x18":(gs==ifxGVSDown)?"\x19":" ", 1);
195 writestring(buf[2], 0, 0x09, " module \xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa.\xfa\xfa\xfa: ............................... time: ..:.. ", 80);
196 writestring(buf[2], 8, 0x0F, currentmodname, _MAX_FNAME);
197 writestring(buf[2], 16, 0x0F, currentmodext, _MAX_EXT);
198 writestring(buf[2], 22, 0x0F, modname, 31);
199 if (plPause)
200 writestring(buf[2], 58, 0x0C, "paused", 6);
201 writenum(buf[2], 74, 0x0F, (tim/60)%60, 10, 2, 1);
202 writestring(buf[2], 76, 0x0F, ":", 1);
203 writenum(buf[2], 77, 0x0F, tim%60, 10, 2, 0);
204 } else {
205 int i;
206 int nch=0;
207
208 memset(buf[0]+128, 0, (plScrWidth-128)*sizeof(uint16_t));
209 memset(buf[1]+128, 0, (plScrWidth-128)*sizeof(uint16_t));
210 memset(buf[2]+128, 0, (plScrWidth-128)*sizeof(uint16_t));
211
212 writestring(buf[1], 0, 0x09, " row: ../.. order: .../... speed: .. tempo: ... gvol: ..\xfa chan: ../..", 81);
213 writenum(buf[1], 9, 0x0F, pos&0xFF, 16, 2, 0);
214 writenum(buf[1], 12, 0x0F, mod.patlens[mod.orders[pos>>8]]-1, 16, 2, 0);
215 writenum(buf[1], 23, 0x0F, pos>>8, 16, 3, 0);
216 writenum(buf[1], 27, 0x0F, mod.nord-1, 16, 3, 0);
217 writenum(buf[1], 40, 0x0F, tmp, 16, 2, 1);
218 writenum(buf[1], 51, 0x0F, bpm, 10, 3, 1);
219 writenum(buf[1], 63, 0x0F, gvol, 16, 2, 0);
220 writestring(buf[1], 65, 0x0F, (gs==ifxGVSUp)?"\x18":(gs==ifxGVSDown)?"\x19":" ", 1);
221 for (i=0; i<plNPChan; i++)
222 if (mcpGet(i, mcpCStatus))
223 nch++;
224 writenum(buf[1], 74, 0x0F, nch, 16, 2, 0);
225 writenum(buf[1], 77, 0x0F, plNPChan, 16, 2, 0);
226 writestring(buf[2], 0, 0x09, " module \xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa.\xfa\xfa\xfa: ............................... composer: ............................... time: ..:.. ", 132);
227 writestring(buf[2], 11, 0x0F, currentmodname, _MAX_FNAME);
228 writestring(buf[2], 19, 0x0F, currentmodext, 4);
229 writestring(buf[2], 25, 0x0F, modname, 31);
230 writestring(buf[2], 68, 0x0F, composer, 31);
231 if (plPause)
232 writestring(buf[2], 100, 0x0C, "playback paused", 15);
233 writenum(buf[2], 123, 0x0F, (tim/60)%60, 10, 2, 1);
234 writestring(buf[2], 125, 0x0F, ":", 1);
235 writenum(buf[2], 126, 0x0F, tim%60, 10, 2, 0);
236 }
237 }
238
itpCloseFile(void)239 static void itpCloseFile(void)
240 {
241 stop(&itplayer);
242 mcpSet(-1, mcpGRestrict, 0);
243 it_free(&mod);
244 }
245
246 /**********************************************************************/
247
itpMarkInsSamp(uint8_t * ins,uint8_t * smp)248 static void itpMarkInsSamp(uint8_t *ins, uint8_t *smp)
249 {
250 int i;
251 for (i=0; i<plNLChan; i++)
252 {
253 int j;
254 if (plMuteCh[i])
255 continue;
256 for (j=0; j<plNLChan; j++)
257 {
258 int lc, in, sm;
259 if (!chanactive(&itplayer, j, &lc))
260 continue;
261 if (lc!=i) /* unrolled if() since left<->right order varies - stian */
262 continue;
263 in=getchanins(&itplayer, j);
264 sm=getchansamp(&itplayer, j);
265 ins[in-1]=((plSelCh==i)||(ins[in-1]==3))?3:2;
266 smp[sm]=((plSelCh==i)||(smp[sm]==3))?3:2;
267 }
268 }
269 }
270
271 /************************************************************************/
272
logvolbar(int * l,int * r)273 static void logvolbar(int *l, int *r)
274 {
275 (*l)*=2;
276 (*r)*=2;
277 if ((*l)>32)
278 (*l)=32+(((*l)-32)>>1);
279 if ((*l)>48)
280 (*l)=48+(((*l)-48)>>1);
281 if ((*l)>56)
282 (*l)=56+(((*l)-56)>>1);
283 if ((*l)>64)
284 (*l)=64;
285 if ((*r)>32)
286 (*r)=32+(((*r)-32)>>1);
287 if ((*r)>48)
288 (*r)=48+(((*r)-48)>>1);
289 if ((*r)>56)
290 (*r)=56+(((*r)-56)>>1);
291 if ((*r)>64)
292 (*r)=64;
293 }
294
drawvolbar(uint16_t * buf,int i,uint8_t st)295 static void drawvolbar(uint16_t *buf, int i, uint8_t st)
296 {
297 int l,r;
298 itplayer_getrealvol(&itplayer, i, &l, &r);
299 logvolbar(&l, &r);
300
301 l=(l+4)>>3;
302 r=(r+4)>>3;
303 if (plPause)
304 l=r=0;
305 if (st)
306 {
307 writestring(buf, 8-l, 0x08, "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe", l);
308 writestring(buf, 9, 0x08, "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe", r);
309 } else {
310 uint16_t left[] = {0x0ffe, 0x0bfe, 0x0bfe, 0x09fe, 0x09fe, 0x01fe, 0x01fe, 0x01fe};
311 uint16_t right[] = {0x01fe, 0x01fe, 0x01fe, 0x09fe, 0x09fe, 0x0bfe, 0x0bfe, 0x0ffe};
312 writestringattr(buf, 8-l, left+8-l, l);
313 writestringattr(buf, 9, right, r);
314 }
315 }
316
drawlongvolbar(uint16_t * buf,int i,uint8_t st)317 static void drawlongvolbar(uint16_t *buf, int i, uint8_t st)
318 {
319 int l,r;
320 itplayer_getrealvol(&itplayer, i, &l, &r);
321 logvolbar(&l, &r);
322 l=(l+2)>>2;
323 r=(r+2)>>2;
324 if (plPause)
325 l=r=0;
326 if (st)
327 {
328 writestring(buf, 16-l, 0x08, "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe", l);
329 writestring(buf, 17, 0x08, "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe", r);
330 } else {
331 uint16_t left[] = {0x0ffe, 0x0ffe, 0x0bfe, 0x0bfe, 0x0bfe, 0x0bfe, 0x09fe, 0x09fe, 0x09fe, 0x09fe, 0x01fe, 0x01fe, 0x01fe, 0x01fe, 0x01fe, 0x01fe};
332 uint16_t right[] = {0x01fe, 0x01fe, 0x01fe, 0x01fe, 0x01fe, 0x01fe, 0x09fe, 0x09fe, 0x09fe, 0x09fe, 0x0bfe, 0x0bfe, 0x0bfe, 0x0bfe, 0x0ffe, 0x0ffe};
333 writestringattr(buf, 16-l, left+16-l, l);
334 writestringattr(buf, 17, right, r);
335 }
336 }
337
338 static char *fxstr3[]={0,"vl\x18","vl\x19","fv\x18","fv\x19","pt\x18",
339 "pt\x19","pt\x0d","fp\x18","fp\x19","pn\x1a","pn\x1b",
340 "tre", "trr","vib","arp","cut","ret","ofs","eps",
341 "del", "cv\x18", "cv\x19", "fc\x18", "fc\x19","p-c",
342 "p-o", "p-f", "ve0", "ve1", "pe0", "pe1", "fe0",
343 "fe1", "pbr"
344 };
345
346 static char *fxstr6[]={0, "volsl\x18","volsl\x19","fvols\x18","fvols\x19",
347 "porta\x18","porta\x19","porta\x0d","fport\x18",
348 "fport\x19","pansl\x1a","pansl\x1b","tremol","tremor",
349 "vibrat","arpegg"," \x0e""cut ","retrig","offset",
350 "envpos","delay\x0d", "chvol\x18", "chvol\x19",
351 "fchvl\x18", "fchvl\x19", "past-C", "past-O",
352 "past-F", "venv:0", "venv:1", "penv:0", "penv:1",
353 "fenv:0", "fenv:1", "panbrl"
354 };
355
356 static char *fxstr12[]={0, "volumeslide\x18","volumeslide\x19",
357 "finevolslid\x18","finevolslid\x19","portamento \x18",
358 "portamento \x19","porta to \x0d ","fine porta \x18",
359 "fine porta \x19","pan slide \x1a ","pan slide \x1b ",
360 "tremolo ","tremor ","vibrato ",
361 "arpeggio ","note cut ","note retrig ",
362 "sampleoffset","set env pos ","note delay ",
363 "chanvolslid\x18","chanvolslid\x19",
364 "finechvolsl\x18","finechvolsl\x19", "past cut",
365 "past off","past fade","vol env off","vol env on",
366 "pan env off", "pan env on", "pitchenv off",
367 "pitchenv on", "panbrello"
368 };
369
370
drawchannel(uint16_t * buf,int len,int i)371 static void drawchannel(uint16_t *buf, int len, int i)
372 {
373 uint8_t st=plMuteCh[i];
374
375 uint8_t tcol=st?0x08:0x0F;
376 uint8_t tcold=st?0x08:0x07;
377 uint8_t tcolr=st?0x08:0x0B;
378
379 int av;
380
381 struct it_chaninfo ci;
382
383 char *fxstr;
384
385 switch (len)
386 {
387 case 36:
388 writestring(buf, 0, tcold, " \xfa\xfa -- --- -- --- \xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa \xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa ", 36);
389 break;
390 case 62:
391 writestring(buf, 0, tcold, " \xfa\xfa ---\xfa --\xfa -\xfa ------ \xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa \xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa ", 62);
392 break;
393 case 128:
394 writestring(buf, 0, tcold, " \xfa\xfa \xb3 \xb3 \xb3 \xb3 \xb3 \xb3 \xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa \xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa", 128);
395 break;
396 case 76:
397 writestring(buf, 0, tcold, " \xfa\xfa \xb3 \xb3 \xb3 \xb3 \xb3 \xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa \xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa", 76);
398 break;
399 case 44:
400 writestring(buf, 0, tcold, " \xfa\xfa -- ---\xfa --\xfa -\xfa ------ \xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa \xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa ", 44);
401 break;
402 }
403
404 av=getchanalloc(&itplayer, i);
405 if (av)
406 writenum(buf, 1, tcold, av, 16, 2, 0);
407
408 if (!lchanactive(&itplayer, i))
409 return;
410
411 getchaninfo(&itplayer, i, &ci);
412
413 switch (len)
414 {
415 case 36:
416 writenum(buf, 4, tcol, ci.ins, 16, 2, 0);
417 writestring(buf, 7, ci.notehit?tcolr:tcol, plNoteStr[ci.note], 3);
418 writenum(buf, 11, tcol, ci.vol, 16, 2, 0);
419 fxstr=fxstr3[ci.fx];
420 if (fxstr)
421 writestring(buf, 14, tcol, fxstr, 3);
422 drawvolbar(buf+18, i, st);
423 break;
424 case 62:
425 if (ci.ins)
426 {
427 if (*insts[ci.ins-1].name)
428 writestring(buf, 4, tcol, insts[ci.ins-1].name, 19);
429 else
430 {
431 writestring(buf, 4, 0x08, "( )", 4);
432 writenum(buf, 5, 0x08, ci.ins, 16, 2, 0);
433 }
434 }
435 writestring(buf, 25, ci.notehit?tcolr:tcol, plNoteStr[ci.note], 3);
436 writestring(buf, 28, tcol, ci.pitchslide ? &" \x18\x19\x0D\x18\x19\x0D"[ci.pitchslide] : &" ~\xf0"[ci.pitchfx], 1);
437 writenum(buf, 30, tcol, ci.vol, 16, 2, 0);
438 writestring(buf, 32, tcol, ci.volslide ? &" \x18\x19\x18\x19"[ci.volslide] : &" ~"[ci.volfx], 1);
439 writestring(buf, 34, tcol, &"L123456MM9ABCDERS"[ci.pan], 1);
440 writestring(buf, 35, tcol, &" \x1A\x1B"[ci.panslide], 1);
441 fxstr=fxstr6[ci.fx];
442 if (fxstr)
443 writestring(buf, 37, tcol, fxstr, 6);
444 drawvolbar(buf+44, i, st);
445 break;
446 case 76:
447 if (ci.ins)
448 {
449 if (*insts[ci.ins-1].name)
450 writestring(buf, 4, tcol, insts[ci.ins-1].name, 28);
451 else
452 {
453 writestring(buf, 4, 0x08, "( )", 4);
454 writenum(buf, 5, 0x08, ci.ins, 16, 2, 0);
455 }
456 }
457 writestring(buf, 33, ci.notehit?tcolr:tcol, plNoteStr[ci.note], 3);
458 writestring(buf, 36, tcol, ci.pitchslide ? &" \x18\x19\x0D\x18\x19\x0D"[ci.pitchslide] : &" ~\xf0"[ci.pitchfx], 1);
459 writenum(buf, 38, tcol, ci.vol, 16, 2, 0);
460 writestring(buf, 40, tcol, ci.volslide ? &" \x18\x19\x18\x19"[ci.volslide] : &" ~"[ci.volfx], 1);
461 writestring(buf, 42, tcol, &"L123456MM9ABCDERS"[ci.pan], 1);
462 writestring(buf, 43, tcol, &" \x1A\x1B"[ci.panslide], 1);
463
464 fxstr=fxstr12[ci.fx];
465 if (fxstr)
466 writestring(buf, 45, tcol, fxstr, 12);
467
468 drawvolbar(buf+59, i, st);
469 break;
470 case 128:
471 if (ci.ins)
472 {
473 if (*insts[ci.ins-1].name)
474 writestring(buf, 4, tcol, insts[ci.ins-1].name, 28);
475 else
476 {
477 writestring(buf, 4, 0x08, "( )", 4);
478 writenum(buf, 5, 0x08, ci.ins, 16, 2, 0);
479 }
480 }
481 if (ci.smp!=0xFFFF)
482 {
483 if (*samps[ci.smp].name)
484 writestring(buf, 34, tcol, samps[ci.smp].name, 17);
485 else
486 {
487 writestring(buf, 34, 0x08, "( )", 6);
488 writenum(buf, 35, 0x08, ci.smp, 16, 4, 0);
489 }
490 }
491 writestring(buf, 53, ci.notehit?tcolr:tcol, plNoteStr[ci.note], 3);
492 writestring(buf, 56, tcol, ci.pitchslide ? &" \x18\x19\x0D\x18\x19\x0D"[ci.pitchslide] : &" ~\xf0"[ci.pitchfx], 1);
493 writenum(buf, 58, tcol, ci.vol, 16, 2, 0);
494 writestring(buf, 60, tcol, ci.volslide ? &" \x18\x19\x18\x19"[ci.volslide] : &" ~"[ci.volfx], 1);
495 writestring(buf, 62, tcol, &"L123456MM9ABCDERS"[ci.pan], 1);
496 writestring(buf, 63, tcol, &" \x1A\x1B"[ci.panslide], 1);
497
498 fxstr=fxstr12[ci.fx];
499 if (fxstr)
500 writestring(buf, 65, tcol, fxstr, 12);
501 drawlongvolbar(buf+80, i, st);
502 break;
503 case 44:
504 writenum(buf, 4, tcol, ci.ins, 16, 2, 0);
505 writestring(buf, 7, ci.notehit?tcolr:tcol, plNoteStr[ci.note], 3);
506 writestring(buf, 10, tcol, ci.pitchslide ? &" \x18\x19\x0D\x18\x19\x0D"[ci.pitchslide] : &" ~\xf0"[ci.pitchfx], 1);
507 writenum(buf, 12, tcol, ci.vol, 16, 2, 0);
508 writestring(buf, 14, tcol, ci.volslide ? &" \x18\x19\x18\x19"[ci.volslide] : &" ~"[ci.volfx], 1);
509 writestring(buf, 16, tcol, &"L123456MM9ABCDERS"[ci.pan], 1);
510 writestring(buf, 17, tcol, &" \x1A\x1B"[ci.panslide], 1);
511
512 fxstr=fxstr6[ci.fx];
513 if (fxstr)
514 writestring(buf, 19, tcol, fxstr, 6);
515 drawvolbar(buf+26, i, st);
516 break;
517 }
518 }
519
520 /************************************************************************/
521
itpGetDots(struct notedotsdata * d,int max)522 static int itpGetDots(struct notedotsdata *d, int max)
523 {
524 int i,j;
525 int pos=0;
526 for (i=0; i<plNLChan; i++)
527 {
528 if (pos>=max)
529 break;
530 j=0;
531 while (pos<max)
532 {
533 int smp, voll, volr, note, sus;
534 j=getdotsdata(&itplayer, i, j, &smp, ¬e, &voll, &volr, &sus);
535 if (j==-1)
536 break;
537 d[pos].voll=voll;
538 d[pos].volr=volr;
539 d[pos].chan=i;
540 d[pos].note=note;
541 d[pos].col=(smp&15)+(sus?32:16);
542 pos++;
543 }
544 }
545 return pos;
546 }
547
itpMute(int i,int m)548 static void itpMute(int i, int m)
549 {
550 mutechan(&itplayer, i, m);
551 }
552
itpGetLChanSample(unsigned int ch,int16_t * buf,unsigned int len,uint32_t rate,int opt)553 static int itpGetLChanSample(unsigned int ch, int16_t *buf, unsigned int len, uint32_t rate, int opt)
554 {
555 return getchansample(&itplayer, ch, buf, len, rate, opt);
556 }
557
itpOpenFile(struct moduleinfostruct * info,struct ocpfilehandle_t * file)558 static int itpOpenFile(struct moduleinfostruct *info, struct ocpfilehandle_t *file)
559 {
560 int retval;
561
562 int nch;
563
564 if (!mcpOpenPlayer)
565 return errGen;
566
567 if (!file)
568 return errFileOpen;
569
570 strncpy(currentmodname, info->name, _MAX_FNAME);
571 strncpy(currentmodext, info->name + _MAX_FNAME, _MAX_EXT);
572
573 fprintf(stderr, "loading %s%s (%uk)...\n", currentmodname, currentmodext, (unsigned int)(file->filesize(file)>>10));
574
575 if (!(retval=it_load(&mod, file)))
576 if (!loadsamples(&mod))
577 retval=-1;
578
579 if (retval)
580 {
581 it_free(&mod);
582 return -1;
583 }
584
585 it_optimizepatlens(&mod);
586
587 mcpNormalize(1);
588 nch=cfGetProfileInt2(cfSoundSec, "sound", "itchan", 64, 10);
589 mcpSet(-1, mcpGRestrict, 0); /* oops... */
590 if (!play(&itplayer, &mod, nch, file))
591 retval=errPlay;
592
593 if (retval)
594 {
595 it_free(&mod);
596 return retval;
597 }
598
599 insts=mod.instruments;
600 samps=mod.samples;
601 plNLChan=mod.nchan;
602 plIsEnd=itpLooped;
603 plIdle=itpIdle;
604 plProcessKey=itpProcessKey;
605 plDrawGStrings=itpDrawGStrings;
606 plSetMute=itpMute;
607 plGetLChanSample=itpGetLChanSample;
608 plUseDots(itpGetDots);
609 plUseChannels(drawchannel);
610 itpInstSetup(mod.instruments, mod.ninst, mod.samples, mod.nsamp, mod.sampleinfos, /*mod.nsampi,*/ 0, itpMarkInsSamp);
611 itTrkSetup(&mod);
612 if (mod.message)
613 plUseMessage(mod.message);
614 plNPChan=mcpNChan;
615
616 modname=mod.name;
617 composer="";
618 if (!plCompoMode)
619 {
620 if (!*modname)
621 modname=info->modname;
622 composer=info->composer;
623 } else
624 modname=info->comment;
625
626 plGetRealMasterVolume=mcpGetRealMasterVolume;
627 plGetMasterSample=mcpGetMasterSample;
628 plGetPChanSample=mcpGetChanSample;
629
630 starttime=dos_clock();
631 plPause=0;
632 mcpSet(-1, mcpMasterPause, 0);
633
634 return errOk;
635 }
636
637 struct cpifaceplayerstruct itpPlayer = {itpOpenFile, itpCloseFile};
638 struct linkinfostruct dllextinfo = {.name = "playit", .desc = "OpenCP IT Player (c) 1997-10 Tammo Hinrichs, Niklas Beisert, Stian Skjelstad", .ver = DLLVERSION, .size = 0};
639