Trivial Solutions Corp. Happy Programmers Make Us Happy The LoseThos 64-bit PC Operating System File:/LT/Apps/MusicOrgan/Organ.CPZ This, and all LoseThos files, are public domain. Do whatever you like. /* This uses four types of controls 1) The pull-down menu. 2) The Ctrl type for the tempo/stacatto sliders. 3) The active Ltf picture buttons with macros for left/record/play/right. 4) Hand-made controls for the kbdgraphic, notes and staff. This uses four types of output 1) The Ltf for the text and buttons and kbdgraphic, drawn by Fs->update_win(). 2) The Fs->draw_it() for the staff region, drawn every refresh. 3) The gr_persistent_base persistent layer for the note chooser, meter chooser. The persistent layer is used during drag-and-drop. 4) The Fs->next_ctrl for the tempo/stacatto sliders. See GrUpdateWins() and GrUpdateScreen(). */ #define OT_ROOT 0 #define OT_NOTE 1 #define OT_METER 2 #define Of_SELECTED 0 #define OF_SELECTED 1 class OrgNote { OrgNote *next,*last; I8 x,y; U1 *word; U1 type,flags; union { U1 note; U1 meter_top; }; union { U1 octave; U1 meter_bottom; } U1 duration,accent,width,waveform; U1 ascii[32]; }; //Tool types #define OTT_PTR_TOOL 0 #define OTT_BOX_TOOL 1 class OrgCtrl { OrgNote root; OrgNote clipboard; MenuEntry *incomplete_entry,*record_entry; I8 screen_x, tool; OrgNote *cur_note; GrBitMap *base2; BoolI1 playing; } oc; U1 *org_note_list="A\0A#\0B\0C\0C#\0D\0D#\0E\0F\0F#\0G\0G#\0"; U1 org_note_map[12]={6,6,5,4,4,3,3,2,1,1,0,0}; U1 org_note_inverse_map[7]={10,8,7,5,3,2,0}; <1>/* Graphics Not Rendered in HTML */ <2>/* Graphics Not Rendered in HTML */ <3>/* Graphics Not Rendered in HTML */ <4>/* Graphics Not Rendered in HTML */ <5>/* Graphics Not Rendered in HTML */ <6>/* Graphics Not Rendered in HTML */ <7>/* Graphics Not Rendered in HTML */ <8>/* Graphics Not Rendered in HTML */ <9>/* Graphics Not Rendered in HTML */ <10>/* Graphics Not Rendered in HTML */ <11>/* Graphics Not Rendered in HTML */ <12>/* Graphics Not Rendered in HTML */ <13>/* Graphics Not Rendered in HTML */ <14>/* Graphics Not Rendered in HTML */ <15>/* Graphics Not Rendered in HTML */ <16>/* Graphics Not Rendered in HTML */ <17>/* Graphics Not Rendered in HTML */ <18>/* Graphics Not Rendered in HTML */ #define ORG_NOTE_SPACING 9 #define ORG_NUM_DURATIONS 12 F8 org_durations[ORG_NUM_DURATIONS+1]={ 2*.25/3,.25,2*.5/3,.5,2.0/3.0,0.5*1.5,1.0,1.5,2.0,3.0,4.0,6.0,1000000.0}; U1 *org_duration_list="st\0s\0et\0e\0qt\0e.\0q\0q.\0h\0h.\0w\0w.\0"; U1 *org_duration_imgs[ORG_NUM_DURATIONS]={<1>,<1>,<2>, <2>,<3>,<2>,<3>,<3>, <4>,<4>,<5>,<5>}; BoolI1 org_triplet_durations[ORG_NUM_DURATIONS]={TRUE,FALSE,TRUE, FALSE,TRUE,FALSE,FALSE,FALSE, FALSE,FALSE,FALSE,FALSE}; BoolI8 OrgIsSharp(I8 note) { U1 *st=ListEntryPoint(note,org_note_list); if (st[1]=='#') return TRUE; else return FALSE; } BoolI8 OrgIsFlat(I8 note) { U1 *st=ListEntryPoint(note,org_note_list); if (st[1]=='b') return TRUE; else return FALSE; } BoolI8 OrgIsDotted(I8 duration) { U1 *st=ListEntryPoint(duration,org_duration_list); if (st[1]=='.') return TRUE; else return FALSE; } U0 OrgSetWidth(OrgNote *tempo) { if (tempo->type==OT_METER) tempo->width=12; else { tempo->width=ORG_NOTE_SPACING; if (OrgIsDotted(tempo->duration)) tempo->width+=ORG_NOTE_SPACING/2; if (OrgIsSharp(tempo->note) || OrgIsFlat(tempo->note)) tempo->width+=ORG_NOTE_SPACING; } } U0 OrgRecalcNoteXY() { F8 measure_len=4,measure_left=measure_len; OrgNote *tempo=oc.root.next; I8 x=8-oc.screen_x; while (TRUE) { tempo->x=x; tempo->y=50; if (tempo==&oc.root) break; else { if (tempo->type!=OT_METER && tempo->octave) //note, not rest tempo->y=(15+(org_note_map[tempo->note]-7*(tempo->octave-2)))*4; x+=tempo->width; if (tempo->type==OT_METER) { measure_len=tempo->meter_top*4.0/tempo->meter_bottom; measure_left=0; } else measure_left-=org_durations[tempo->duration]; if (measure_left<0.001) { x+=ORG_NOTE_SPACING; measure_left=measure_len; } } tempo=tempo->next; } } U0 OrgMarkSelected(I8 x1,I8 x2,BoolI1 sel) { OrgNote *tempo=oc.root.next; while (tempo!=&oc.root) { if (sel) { if (x1<=tempo->x<=x2) tempo->flags|=OF_SELECTED; } else tempo->flags&=~OF_SELECTED; tempo=tempo->next; } } OrgNote *OrgNoteCopy(OrgNote *tempo) { OrgNote *tempo1=MAllocIdentical(tempo); if (tempo->word) tempo1->word=StrNew(tempo->word); return tempo1; } U0 OrgNoteDel(OrgNote *tempo) { Free(tempo->word); Free(tempo); } U0 OrgSongDel(OrgNote *root) { OrgNote *tempo,*tempo1; tempo=root->next; while (tempo!=root) { tempo1=tempo->next; OrgNoteDel(tempo); tempo=tempo1; } root->next=root->last=root; } U0 OrgCutToClipboard() { OrgNote *tempo,*tempo1; OrgSongDel(&oc.clipboard); tempo=oc.root.next; while (tempo!=&oc.root) { tempo1=tempo->next; if (tempo->flags&OF_SELECTED) { if (oc.cur_note==tempo) oc.cur_note=tempo->next; RemQue(tempo); tempo->flags&=~OF_SELECTED; InsQue(tempo,oc.clipboard.last); } tempo=tempo1; } } U0 OrgPasteClipboard() { OrgNote *tempo,*tempo1; tempo=oc.clipboard.next; while (tempo!=&oc.clipboard) { tempo1=OrgNoteCopy(tempo); InsQue(tempo1,oc.cur_note->last); tempo=tempo->next; } } U0 OrgCopyToClipboard() { OrgNote *tempo,*tempo1; OrgSongDel(&oc.clipboard); tempo=oc.root.next; while (tempo!=&oc.root) { if (tempo->flags&OF_SELECTED) { tempo->flags&=~OF_SELECTED; tempo1=OrgNoteCopy(tempo); InsQue(tempo1,oc.clipboard.last); } tempo=tempo->next; } } OrgNote *OrgFindNote(I8 x,I8 y) { nounusedwarn y; OrgNote *tempo=oc.root.next; OrgRecalcNoteXY; x+=ORG_NOTE_SPACING/2; while (x>tempo->next->x && tempo!=&oc.root) tempo=tempo->next; return tempo; } BoolI8 OrgBlink(F8 t) { if (Blink(,t) || oc.playing) return TRUE; else return FALSE; } U0 DrawNote(GrBitMap *base,I8 x,I8 y,I8 duration) { if (0<=duration<=ORG_NUM_DURATIONS) { base->bkcolor=WHITE; GrElemsPlot(base,x,y,0,org_duration_imgs[duration]); if (org_triplet_durations[duration]) GrElemsPlot(base,x,y,0,<18>); if (OrgIsDotted(duration)) GrElemsPlot(base,x,y,0,<19>); } } U0 DrawTimeSignature(GrBitMap *base,I8 x,I8 y,I8 top,I8 bottom) { GrPrintF(base,x,y,"%d",top); GrPrintF(base,x,y+FONT_HEIGHT,"%d",bottom); } U0 DrawIt(TaskStruct *task,GrBitMap *base) { OrgNote *tempo; I8 i,x,y, w=task->win_pixel_width; F8 measure_len=4,measure_left=measure_len; BoolI1 old_preempt=Preempt(OFF); base->color=BLACK; for (i=1;i<6;i++) GrLine(base,0,i*8,w,i*8); for (i=7;i<12;i++) GrLine(base,0,i*8,w,i*8); OrgRecalcNoteXY; if (oc.cur_note->x<64) { oc.screen_x-=128; OrgRecalcNoteXY; } if (oc.cur_note->x>=GR_WIDTH-64) { oc.screen_x+=128; OrgRecalcNoteXY; } tempo=oc.root.next; while (tempo!=&oc.root) { x=tempo->x; y=tempo->y; if (measure_left<0.001) { base->color=BLACK; GrLine(base,x-ORG_NOTE_SPACING,8,x-ORG_NOTE_SPACING,11*8); measure_left=measure_len; } if (tempo->type==OT_METER) { if (tempo==oc.cur_note && OrgBlink(tP(task))) base->color=BROWN; else base->color=BLACK; DrawTimeSignature(base,x,5*8,tempo->meter_top,tempo->meter_bottom); measure_len=tempo->meter_top*4.0/tempo->meter_bottom; measure_left=0; } else { if (tempo==oc.cur_note && OrgBlink(tP(task))) { base->color=BROWN; GrPutS(base,x+8,y,tempo->word); } else if (tempo->flags&OF_SELECTED) base->color=RED; else { if (tempo->octave) //rest? base->color=BLACK; else base->color=LTGRAY; if (tempo->word) if (StrLen(tempo->word)>1 || (*tempo->word!=CH_SPACE && *tempo->word!=CH_SHIFT_SPACE)) base->color=GREEN; } if (tempo->accent==1) GrElemsPlot(base,x,y,0,<20>); else if (tempo->accent==2) GrElemsPlot(base,x,y,0,<21>); DrawNote(base,x,y,tempo->duration); if (OrgIsDotted(tempo->duration)) x+=ORG_NOTE_SPACING/2; if (OrgIsSharp(tempo->note)) GrElemsPlot(base,x,y,0,<22>); else if (OrgIsFlat(tempo->note)) GrElemsPlot(base,x,y,0,<23>); measure_left-=org_durations[tempo->duration]; } tempo=tempo->next; } if (oc.cur_note==&oc.root && OrgBlink(tP(task))) base->color=BROWN; else base->color=BLACK; GrElemsPlot(base,oc.root.x,50,0,<24>); Preempt(old_preempt); } #define ORGR_STRONG_ACCENT -9 #define ORGR_ACCENT -8 #define ORGR_NO_ACCENT -7 #define ORGR_SHARP -6 #define ORGR_REST -5 #define ORGR_INSERT_NOTE -4 #define ORGR_DELETE_NOTE -3 #define ORGR_SET_WORD -2 F8 PopUpDuration() { I8 i; Ltf *l=LtfNew; LtfPrintF(l,"$$FM,GREEN$$$$MU,\"Set Word\",%d$$\r\n",ORGR_SET_WORD); LtfPrintF(l,"$$MU,\"Toggle Sharp\",%d$$\r\n",ORGR_SHARP); LtfPrintF(l,"$$MU,\"Make Rest\",%d$$\r\n",ORGR_REST); LtfPrintF(l,"$$MU,\"Insert Note\",%d$$\r\n",ORGR_INSERT_NOTE); LtfPrintF(l,"$$MU,\"Delete Note\",%d$$\r\n",ORGR_DELETE_NOTE); LtfPrintF(l,"$$MU,\"No Accent\",%d$$\r\n",ORGR_NO_ACCENT); LtfPrintF(l,"$$MU,\"Accent\",%d$$\r\n",ORGR_ACCENT); LtfPrintF(l,"$$MU,\"Strong Accent\",%d$$\r\n\r\n",ORGR_STRONG_ACCENT); for (i=0;i<ORG_NUM_DURATIONS;i++) LtfPrintF(l,"$$MU,\"%7.5f\",%d$$\r\n",org_durations[i],i); LtfPrintF(l,"\r\n$$MU,\"CANCEL\",%d$$\r\n",-1); i=PopUpMenu(l); LtfDel(l); return i; } U0 OrgRightClick(I8 x,I8 y) { U1 *st,*st2; OrgNote *tempo,*tempo1; I8 i; U8 old_ltf_flags; if (LtfCur) old_ltf_flags=LtfCur->flags; oc.cur_note=tempo=OrgFindNote(x,y); if (tempo!=&oc.root) { LBtr(&Fs->display_flags,DISPLAYf_NO_DBL_CLICK); win_inhibit=0; i=PopUpDuration; if (i>=0 && i<ORG_NUM_DURATIONS) { if (tempo->type==OT_NOTE) tempo->duration=i; } else { switch (i) { case ORGR_REST: if (tempo->type==OT_NOTE) { tempo->octave=0; //rest tempo->note=0; tempo->accent=0; tempo->waveform=WF_SQUARE; } break; case ORGR_SHARP: if (tempo->type==OT_NOTE && tempo->octave) { if (OrgIsSharp(tempo->note)) tempo->note--; else tempo->note++; if (tempo->note<0) { tempo->note=11; tempo->octave--; } else if (tempo->note>11) { tempo->note=0; tempo->octave++; } } break; case ORGR_SET_WORD: if (tempo->type==OT_NOTE) { if (LtfCur) LtfCur->flags&=~LTFF_FORM; if (tempo->word) st2=MSPrintF("\r\nWord(\"%Q\"):",tempo->word); else st2=MSPrintF("\r\nWord(\"\"):"); LtfBottom; st=PmtStr(st2); Free(st2); Free(tempo->word); if (*st) { tempo->word=MSPrintF("%q",st); Free(st); } else tempo->word=StrNew(" "); if (LtfCur) LtfCur->flags=LtfCur->flags&~LTFF_FORM|old_ltf_flags<FF_FORM; } break; case ORGR_INSERT_NOTE: tempo1=OrgNoteCopy(tempo); InsQue(tempo1,tempo); break; case ORGR_DELETE_NOTE: oc.cur_note=tempo->next; RemQue(tempo); OrgNoteDel(tempo); break; case ORGR_NO_ACCENT: if (tempo->type==OT_NOTE && tempo->octave) tempo->accent=0; break; case ORGR_ACCENT: if (tempo->type==OT_NOTE && tempo->octave) tempo->accent=1; break; case ORGR_STRONG_ACCENT: if (tempo->type==OT_NOTE && tempo->octave) tempo->accent=2; break; } } OrgSetWidth(oc.cur_note); win_inhibit=WIF_ALL-WIF_BORDER; LBts(&Fs->display_flags,DISPLAYf_NO_DBL_CLICK); } } #define ORG_NOTE_BOX_X 220 #define ORG_NOTE_BOX_Y (13*FONT_HEIGHT+14) U0 OrgSetPickNoteBoxX(I8 duration,I8 *x) { I8 i; *x=ORG_NOTE_BOX_X; for (i=0;i<duration;i++) { if (OrgIsDotted(i)) *x+=ORG_NOTE_SPACING/2; *x+=ORG_NOTE_SPACING+4; } } I8 OrgGetPickNoteBoxDuration(I8 xx,I8 yy) { I8 i,x1,x2; if (ORG_NOTE_BOX_Y-14<=yy<ORG_NOTE_BOX_Y+6) { for (i=0;i<ORG_NUM_DURATIONS;i++) { OrgSetPickNoteBoxX(i,&x1); OrgSetPickNoteBoxX(i+1,&x2); if (x1<=xx+ORG_NOTE_SPACING/2<x2) return i; } } return -1; } U0 DrawPickNoteBox() { I8 i,x; for (i=0;i<ORG_NUM_DURATIONS;i++) { OrgSetPickNoteBoxX(i,&x); if (OrgIsDotted(i)) oc.base2->color=RED; else if (org_triplet_durations[i]) oc.base2->color=LTRED; else oc.base2->color=BLACK; DrawNote(oc.base2,x,ORG_NOTE_BOX_Y,i); } } #define ORG_TOOLS_X 450 #define ORG_TOOLS_Y 13*FONT_HEIGHT U0 DrawPickTools() { if (oc.tool==OTT_BOX_TOOL) oc.base2->color=ROPF_DITHER+WHITE<<16+ROP_EQU+RED; else oc.base2->color=ROPF_DITHER+WHITE<<16+ROP_EQU+BLACK; GrLineRect4(oc.base2,ORG_TOOLS_X,ORG_TOOLS_Y, ORG_TOOLS_X+10,ORG_TOOLS_Y+10); if (oc.tool==OTT_PTR_TOOL) oc.base2->color=ROPF_DITHER+WHITE<<16+ROP_EQU+RED; else oc.base2->color=ROPF_DITHER+WHITE<<16+ROP_EQU+BLACK; fp_draw_input_ptr(oc.base2,ORG_TOOLS_X+15,ORG_TOOLS_Y); oc.base2->color=BLACK; } BoolI8 OrgGetPickToolBox(I8 xx,I8 yy) { if (ORG_TOOLS_X<=xx<ORG_TOOLS_X+27 && ORG_TOOLS_Y<=yy<ORG_TOOLS_Y+15) { OrgMarkSelected(0,0,FALSE); if (xx<ORG_TOOLS_X+13) oc.tool=OTT_BOX_TOOL; else oc.tool=OTT_PTR_TOOL; return TRUE; } else return FALSE; } #define ORG_NUM_METERS 7 I8 meter_tops[ORG_NUM_METERS] ={2,3,4,5,6,7,9}, meter_bottoms[ORG_NUM_METERS]={4,4,4,4,8,8,8}; #define ORG_METER_X 485 #define ORG_METER_Y 13*FONT_HEIGHT #define ORG_METER_W 12 BoolI8 OrgGetPickMeterBox(I8 xx,I8 yy,I8 *top,I8 *bottom) { I8 i; if (ORG_METER_X<=xx<ORG_METER_X+ORG_METER_W*ORG_NUM_METERS && ORG_METER_Y<=yy<ORG_METER_Y+2*FONT_HEIGHT) { i=(xx-ORG_METER_X)/ORG_METER_W; *top=meter_tops[i]; *bottom=meter_bottoms[i]; return TRUE; } else return FALSE; } U0 DrawPickMeterBox() { I8 i; oc.base2->color=BLACK; for (i=0;i<ORG_NUM_METERS;i++) DrawTimeSignature(oc.base2,ORG_METER_X+i*ORG_METER_W,ORG_METER_Y,meter_tops[i],meter_bottoms[i]); } U0 DrawBase2() { GrClear; DrawPickNoteBox; DrawPickMeterBox; DrawPickTools; } U0 OrgLeftClickPickNoteBox(I8 duration) { I8 o,n,msg_code,p1,p2; OrgNote *tempo,*tempo1; do { msg_code=GetMsg(&p1,&p2,1<<MSG_IP_L_UP|1<<MSG_IP_MOVE); if (msg_code==MSG_IP_MOVE) { DrawBase2; DrawNote(oc.base2,p1,p2,duration); } } while (msg_code!=MSG_IP_L_UP); if (p2<13*FONT_HEIGHT) { if (p1>oc.root.last->x) tempo1=oc.root.last; else if (p1<oc.root.next->x) tempo1=&oc.root; else tempo1=OrgFindNote(p1-ORG_NOTE_SPACING/2,p2); tempo=CAlloc(sizeof(OrgNote)); tempo->type=OT_NOTE; p2=p2/4-15; n=-p2%7; o=2+p2/-7; n=-n; if (n<0) { n+=7; o++; } n=org_note_inverse_map[n]; tempo->note=n; tempo->octave=o; tempo->duration=duration; tempo->waveform=tempo1->waveform; OrgSetWidth(tempo); InsQue(tempo,tempo1); oc.cur_note=tempo->next; } DrawBase2; } U0 OrgLeftClickPickMeterBox(I8 top,I8 bottom) { I8 msg_code,p1,p2; OrgNote *tempo,*tempo1; do { msg_code=GetMsg(&p1,&p2,1<<MSG_IP_L_UP|1<<MSG_IP_MOVE); if (msg_code==MSG_IP_MOVE) { DrawBase2; DrawTimeSignature(oc.base2,p1,p2,top,bottom); } } while (msg_code!=MSG_IP_L_UP); if (p2<13*FONT_HEIGHT) { if (p1>=oc.root.x) tempo1=oc.root.last; else if (p1<oc.root.next->x) tempo1=&oc.root; else tempo1=OrgFindNote(p1-ORG_NOTE_SPACING/2,p2); tempo=CAlloc(sizeof(OrgNote)); tempo->type=OT_METER; tempo->meter_top=top; tempo->meter_bottom=bottom; tempo->waveform=tempo1->waveform; OrgSetWidth(tempo); InsQue(tempo,tempo1); oc.cur_note=tempo->next; } DrawBase2; } U0 OrgLeftClickStaffPtr(I8 x,I8 y) { OrgNote *tempo,*tempo1; I8 o,n,msg_code,p1,p2,n_original,o_original,a_original,wf_original; oc.cur_note=tempo=OrgFindNote(x,y); if (tempo!=&oc.root) { if (tempo->type==OT_NOTE) { n_original=tempo->note; o_original=tempo->octave; a_original=tempo->accent; wf_original=tempo->waveform; do { msg_code=GetMsg(&p1,&p2,1<<MSG_IP_L_UP|1<<MSG_IP_MOVE); if (msg_code==MSG_IP_L_UP) { tempo1=OrgFindNote(p1,p2); if (tempo1==&oc.root || tempo1==tempo) goto move_note; else { Free(tempo1->word); tempo1->word=tempo->word; tempo->word=NULL; tempo->note=n_original; tempo->octave=o_original; tempo->accent=a_original; tempo->waveform=wf_original; } } else { move_note: p2=p2/4-15; n=-p2%7; o=2+p2/-7; n=-n; if (n<0) { n+=7; o++; } n=org_note_inverse_map[n]; tempo->note=n; tempo->octave=o; } } while (msg_code!=MSG_IP_L_UP); OrgSetWidth(tempo); } } } U0 OrgLeftClickStaffBox(I8 x,I8 y) { I8 msg_code,p1,p2; do { msg_code=GetMsg(&p1,&p2,1<<MSG_IP_L_UP|1<<MSG_IP_MOVE); DrawBase2; oc.base2->color=ROPF_DITHER+WHITE<<16+ROP_EQU+BLACK; GrLineRect4(oc.base2,x,y,p1,p2); if (msg_code==MSG_IP_L_UP) { if (x>p1) SwapU8(&x,&p1); OrgMarkSelected(x,p1,TRUE); } } while (msg_code!=MSG_IP_L_UP); DrawBase2; } U0 OrgLeftClick(I8 x,I8 y) { I8 duration,top,bottom; if (y<13*FONT_HEIGHT) { if (oc.tool==OTT_PTR_TOOL) OrgLeftClickStaffPtr(x,y); else OrgLeftClickStaffBox(x,y); } else { duration=OrgGetPickNoteBoxDuration(x,y); if (0<=duration<ORG_NUM_DURATIONS) OrgLeftClickPickNoteBox(duration); else if (OrgGetPickMeterBox(x,y,&top,&bottom)) OrgLeftClickPickMeterBox(top,bottom); else if (OrgGetPickToolBox(x,y)) DrawBase2; } } #define ORGPM_NORMAL 0 #define ORGPM_REVERB1 1 #define ORGPM_NUM_PLAY_MODES 2 U8 org_play_mode=0; F8 org_play_f=0; U0 OrgPlayTask() { U8 i=0; F8 f=0,f2=0; Fs->task_end_cb=&SndTaskEndCB; while (TRUE) { i++; switch (org_play_mode) { case ORGPM_NORMAL: if (org_play_f!=f) { f=org_play_f; Snd(f,music_waveform); } break; case ORGPM_REVERB1: if (org_play_f!=f) { if (f>0) f2=f; f=org_play_f; } if (!(i&15)) { if (i&16) Snd(f,music_waveform); else Snd(f2,music_waveform); } break; } Sleep(1); } } U1 OrgCvtDuration(F8 d) { F8 d1,d2; I8 j; for (j=0;j<ORG_NUM_DURATIONS;j++) { d1=org_durations[j]; d2=org_durations[j+1]; if (d<d1*d2/(d1+d2)) return j; } return 0; } U1 *OrgMusicSetOctave(U1 *st,U8 *org_octave) { U1 ch=*st++; while (ch>='0' && ch<='9') { *org_octave=ch-'0'; ch=*st++; } return --st; } U1 *OrgMusicSetNoteLen(U1 *st,F8 *org_duration) { BoolI1 cont=TRUE; do { switch (*st++) { case 'w': *org_duration=4.0; break; case 'h': *org_duration=2.0; break; case 'q': *org_duration=1.0; break; case 'e': *org_duration=0.5; break; case 's': *org_duration=0.25; break; case 't': *org_duration=2.0* *org_duration/3.0; break; case '.': *org_duration=1.5* *org_duration; break; default: st--; cont=FALSE; } } while (cont); return st; } U0 OrgLoadSongStr(U1 *st,U8 *org_octave,F8 *org_duration) { OrgNote *tempo,*tempo1; U8 note,i=0,waveform=WF_SQUARE; while (*st) { tempo=CAlloc(sizeof(OrgNote)); tempo->waveform=WF_SQUARE; while (*st && !('A'<=*st<='G') && *st!='R') { if (*st=='M') { tempo1=CAlloc(sizeof(OrgNote)); tempo1->type=OT_METER; tempo1->waveform=tempo->waveform; st++; if ('1'<=*st<='9') tempo1->meter_top=*st++-'0'; else tempo1->meter_top=4; if (*st=='/') st++; if ('1'<=*st<='9') tempo1->meter_bottom=*st++-'0'; else tempo1->meter_bottom=4; OrgSetWidth(tempo1); InsQue(tempo1,oc.root.last); } if (*st=='W') { st++; tempo->waveform=*st++-'0'; waveform=tempo->waveform; } while (*st=='!') { tempo->accent++; st++; } st=OrgMusicSetOctave(st,org_octave); st=OrgMusicSetNoteLen(st,org_duration); } if (!*st) { OrgNoteDel(tempo); break; } note=*st++-'A'; if (note<7) { note=music_note_map[note]; if (*st=='b') { note--; st++; } else if (*st=='#') { note++; st++; } tempo->note=note; tempo->octave=*org_octave; } else { tempo->note=0; tempo->octave=0; //rest tempo->accent=0; tempo->waveform=WF_SQUARE; } if (*org_duration<=2*.25/3) i=0; else if (*org_duration<=.25) i=1; else if (*org_duration<=2*.5/3) i=2; else if (*org_duration<=.5) i=3; else if (*org_duration<=2.0/3) i=4; else if (*org_duration<=.5*1.5) i=5; else if (*org_duration<=1.0) i=6; else if (*org_duration<=1.5) i=7; else if (*org_duration<=2.0) i=8; else if (*org_duration<=3.0) i=9; else if (*org_duration<=4.0) i=10; else i=11; tempo->duration=i; tempo->type=OT_NOTE; OrgSetWidth(tempo); InsQue(tempo,oc.cur_note->last); } } U0 OrgLoadSong(U1 *filename,U8 *org_octave,F8 *org_duration) { U1 *st; OrgNote *tempo; LexStruct *lx=LexNew(TextFileRead(filename),0,StrNew(filename)); Lex(lx); if (FileOccurrences("incomplete",filename,"")) oc.incomplete_entry->checked=TRUE; else oc.incomplete_entry->checked=FALSE; while (lx->token) { if (lx->token==TK_IDENT) if (!StrCmp(lx->ident,"Play")) { if (Lex(lx)=='(') if (Lex(lx)==TK_STR) { tempo=oc.root.last; st=LexExtendStr(lx); OrgLoadSongStr(st,org_octave,org_duration); if (lx->token==',') { if (Lex(lx)==TK_STR) { st=LexExtendStr(lx); do { do tempo=tempo->next; while (tempo!=&oc.root && tempo->type==OT_METER); if (tempo!=&oc.root) tempo->word=StrNew(st); st+=StrLen(st)+1; } while (*st); } } } } else if (!StrCmp(lx->ident,"music_tempo")) { if (Lex(lx)=='=' && Lex(lx)==TK_F8) { music_tempo=lx->cur_f-0.0005; tempo_state.tempo=Round(TEMPO_RANGE*(music_tempo-0.5)/4.4); } } else if (!StrCmp(lx->ident,"music_stacatto_factor")) { if (Lex(lx)=='=' && Lex(lx)==TK_F8) { music_stacatto_factor=lx->cur_f-0.0005; tempo_state.stacatto=Round(TEMPO_RANGE*(music_stacatto_factor-0.12)/0.88); } } Lex(lx); } LexDel(lx); } U1 *OrgCvtSong() { OrgNote *tempo; U1 *st,*src,*dst; U8 i,note,octave,last_octave,last_duration,accent,waveform,last_waveform; i=0; tempo=oc.root.next; last_octave=-1; last_duration=-1; last_waveform=-1; while (tempo!=&oc.root) { dst=&tempo->ascii; if (tempo->type==OT_METER) { *dst++='M'; *dst++=tempo->meter_top+'0'; *dst++='/'; *dst++=tempo->meter_bottom+'0'; } else { octave=tempo->octave; note=tempo->note; accent=tempo->accent; waveform=tempo->waveform; if (waveform!=last_waveform && (note || octave)) { *dst++='W'; *dst++=waveform+'0'; last_waveform=waveform; } while (accent--) *dst++='!'; if (octave!=last_octave && (note || octave)) { *dst++=octave+'0'; last_octave=octave; } if (tempo->duration!=last_duration) { src=ListEntryPoint(tempo->duration,org_duration_list); *dst++=src[0]; if (src[1]) *dst++=src[1]; last_duration=tempo->duration; } if (note || octave) { src=ListEntryPoint(note,org_note_list); *dst++=src[0]; if (src[1]) *dst++=src[1]; } else *dst++='R'; } *dst++=0; i+=StrLen(tempo->ascii); tempo=tempo->next; } st=MAlloc(i+1); dst=st; tempo=oc.root.next; while (tempo!=&oc.root) { StrCpy(dst,tempo->ascii); dst+=StrLen(tempo->ascii); tempo=tempo->next; } *dst++=0; return st; } U0 OrgDelSong(U1 *full_filename) { EditFileNameStruct fn; if (full_filename) { StrCpy(fn.name,full_filename); if (LtfFormDo(&fn,"EditFileNameStruct")) Del(fn.name); } } U1 *OrgSaveSong(U1 *dirname,U1 *full_filename) { Ltf *l=LtfNew; BoolI1 has_words; OrgNote *tempo,*tempo1; F8 measure_len=4,two_measure_left=2*measure_len; U1 *ptr,ch; Free(OrgCvtSong); //set tempo->ascii; music_tempo=4.4*tempo_state.tempo/TEMPO_RANGE+0.5; music_stacatto_factor=0.88*tempo_state.stacatto/TEMPO_RANGE+0.12; has_words=FALSE; tempo=oc.root.next; while (tempo!=&oc.root) { if (tempo->word) has_words=TRUE; tempo=tempo->next; } if (oc.incomplete_entry->checked) LtfPutS(l,"//0 incomplete\r\n"); else if (has_words) LtfPutS(l,"//0 has words\r\n"); else LtfPutS(l,"//0 no nothing\r\n"); LtfPutS(l, "U0 Song()\r\n" "{\r\n" " Fs->task_end_cb=&SndTaskEndCB;\r\n" " MusicSettingsReset;\r\n"); LtfPrintF(l," music_tempo=%6.3f;\r\n",music_tempo+0.0005); LtfPrintF(l," music_stacatto_factor=%6.3f;\r\n",music_stacatto_factor+0.0005); LtfPutS(l, " try {\r\n" " while (!ScanKey) {\r\n" "\tPlay(\""); tempo=oc.root.next; tempo1=tempo; has_words=FALSE; while (tempo!=&oc.root) { LtfPutS(l,tempo->ascii); if (tempo->word) has_words=TRUE; if (tempo->type==OT_METER) { measure_len=tempo->meter_top*4.0/tempo->meter_bottom; two_measure_left=0; } else two_measure_left-=org_durations[tempo->duration]; tempo=tempo->next; if (two_measure_left<0.001 && tempo!=&oc.root) { if (has_words) { LtfPutS(l,"\",\r\n\t\t\""); while (tempo1!=tempo) { if (tempo1->type!=OT_METER) { if (ptr=tempo1->word) { while (ch=*ptr) { if (ch==CH_SPACE) *ptr=CH_SHIFT_SPACE; ptr++; } LtfPrintF(l,"%Q\\0",tempo1->word); } else LtfPrintF(l,"%c\\0",CH_SHIFT_SPACE); } tempo1=tempo1->next; } } LtfPutS(l,"\");\r\n"); LtfPutS(l,"\tPlay(\""); two_measure_left=2*measure_len; tempo1=tempo; has_words=FALSE; } } if (has_words) { LtfPutS(l,"\",\r\n\t\t\""); while (tempo1!=tempo) { if (tempo1->type!=OT_METER) { if (ptr=tempo1->word) { while (ch=*ptr) { if (ch==CH_SPACE) *ptr=CH_SHIFT_SPACE; ptr++; } LtfPrintF(l,"%Q\\0",tempo1->word); } else LtfPrintF(l,"%c\\0",CH_SHIFT_SPACE); } tempo1=tempo1->next; } } LtfPutS(l,"\");\r\n" " }\r\n" " } catch\r\n" " Fs->catch_except=TRUE;\r\n" " Snd(0);\r\n" "}\r\n" "\r\n" "Song;\r\n"); LtfRecalc(l); if (full_filename) { StrCpy(l->filename.name,full_filename); Free(full_filename); } else SPrintF(l->filename.name,"%s/Temp.CPZ",dirname); LtfWrite(l,TRUE); full_filename=StrNew(l->filename.name); LtfDel(l); return full_filename; } U0 OrgSetOctave(I8 octave) { I8 i; U1 buf[64]; MenuEntry *tempse; for (i=1;i<=5;i++) { SPrintF(buf,"Snd/Octave%d",i); if (tempse=MenuEntryFind(Fs->cur_menu,buf)) { if (i==octave) tempse->checked=TRUE; else tempse->checked=FALSE; } } if (tempse=MenuEntryFind(Fs->cur_menu,"Snd/Reverb")) tempse->checked=org_play_mode==1; } U0 OrgSetWaveform(I8 waveform) { MenuEntry *tempse; if (tempse=MenuEntryFind(Fs->cur_menu,"Snd/Square")) tempse->checked=waveform==WF_SQUARE; if (tempse=MenuEntryFind(Fs->cur_menu,"Snd/Sine")) tempse->checked=waveform==WF_SINE; if (tempse=MenuEntryFind(Fs->cur_menu,"Snd/Triangle")) tempse->checked=waveform==WF_TRIANGLE; if (tempse=MenuEntryFind(Fs->cur_menu,"Snd/Sawtooth")) tempse->checked=waveform==WF_SAWTOOTH; if (tempse=MenuEntryFind(Fs->cur_menu,"Snd/Noise")) tempse->checked=waveform==WF_NOISE; } <25>/* Graphics Not Rendered in HTML */ #define ORG_NUM_KEYS 20 class OrgKey { U1 x,w,h,ascii; }; #define ORG_W_W 16 #define ORG_W_H 36 #define ORG_B_W 8 #define ORG_B_H 20 OrgKey org_kbd[ORG_NUM_KEYS]= { { 2*ORG_W_W-4,ORG_B_W,ORG_B_H,'e' }, { 3*ORG_W_W-4,ORG_B_W,ORG_B_H,'r' }, { 4*ORG_W_W-4,ORG_B_W,ORG_B_H,'t' }, { 6*ORG_W_W-4,ORG_B_W,ORG_B_H,'u' }, { 7*ORG_W_W-4,ORG_B_W,ORG_B_H,'i' }, { 9*ORG_W_W-4,ORG_B_W,ORG_B_H,'p' }, {10*ORG_W_W-4,ORG_B_W,ORG_B_H,'[' }, {11*ORG_W_W-4,ORG_B_W,ORG_B_H,']' }, { 0*ORG_W_W,ORG_W_W,ORG_W_H,'a' }, { 1*ORG_W_W,ORG_W_W,ORG_W_H,'s' }, { 2*ORG_W_W,ORG_W_W,ORG_W_H,'d' }, { 3*ORG_W_W,ORG_W_W,ORG_W_H,'f' }, { 4*ORG_W_W,ORG_W_W,ORG_W_H,'g' }, { 5*ORG_W_W,ORG_W_W,ORG_W_H,'h' }, { 6*ORG_W_W,ORG_W_W,ORG_W_H,'j' }, { 7*ORG_W_W,ORG_W_W,ORG_W_H,'k' }, { 8*ORG_W_W,ORG_W_W,ORG_W_H,'l' }, { 9*ORG_W_W,ORG_W_W,ORG_W_H,';' }, {10*ORG_W_W,ORG_W_W,ORG_W_H,'\'' }, {11*ORG_W_W,ORG_W_W,ORG_W_H,CH_CR}, }; U0 OrgDownKey(I8 x,I8 y) { I8 i; OrgKey *o; y-=FONT_HEIGHT*13; if (0<=y<ORG_W_H) { x-=16; for (i=0;i<ORG_NUM_KEYS;i++) { o=&org_kbd[i]; if (o->x<=x<o->x+o->w && y<o->h) { kbd_evt_time=GetTimeStamp; Msg(MSG_KEY_DOWN,o->ascii,0); return; } } } } U0 OrgUpKey(I8 x,I8 y) { I8 i; OrgKey *o; y-=FONT_HEIGHT*13; if (0<=y<ORG_W_H) { x-=16; for (i=0;i<ORG_NUM_KEYS;i++) { o=&org_kbd[i]; if (o->x<=x<o->x+o->w && y<o->h) { kbd_evt_time=GetTimeStamp; Msg(MSG_KEY_UP,o->ascii,0); return; } } } } U0 OrgMenu(I8 org_octave,I8 org_waveform) { LtfBottom; LtfClear; coutln "$$BD,WHITE$$$$FD,GREEN$$$$BU,WHITE$$$$FU,GREEN$$$$FM,GREEN$$$$BM,WHITE$$$$CM,0,12$$"; PutGrElems(<25>); CrLf(5); DrawBase2; coutln "$$FG,LTGREEN$$SPACE$$FG$$\t\tRest"; coutln "$$FG,LTGREEN$$BACKSPACE$$FG$$\tDeletes Last Note"; coutln "$$FG,LTGREEN$$Left Mouse$$FG$$\tDrag note or shift word"; coutln "$$FG,LTGREEN$$Right Mouse$$FG$$\tChange duration or set word"; PutGrElems(<6>,<6>,"$$PI+LM+LA,\"\",\"Msg(MSG_KEY_DOWN,0,SCF_CTRL|SC_CURSOR_LEFT);\",%d$$"); cout " "; if (oc.playing) PutGrElems(<9>,<9>,"$$PI+LM,\"\",\"x\",%d$$"); else PutGrElems(<8>,<8>,"$$PI+LM,\"\",\"x\",%d$$"); cout " "; if (oc.record_entry->checked) { oc.record_entry->checked=TRUE; PutGrElems(<10>,<10>,"$$PI+LM,\"\",\"z\",%d$$"); } else PutGrElems(<11>,<11>,"$$PI+LM,\"\",\"z\",%d$$"); cout " "; PutGrElems(<7>,<7>,"$$PI+LM+LA,\"\",\"Msg(MSG_KEY_DOWN,0,SCF_CTRL|SC_CURSOR_RIGHT);\",%d$$"); PutS("$$CM+LX,0,6$$"); OrgSetOctave(org_octave); OrgSetWaveform(org_waveform); WinSync(TRUE); } U0 OrgPushMode(I8 org_octave,I8 org_waveform) { win_inhibit=WIF_ALL-WIF_BORDER; LBts(&Fs->display_flags,DISPLAYf_NO_DBL_CLICK); OrgMenu(org_octave,org_waveform); } U0 OrgPopMode() { LBtr(&Fs->display_flags,DISPLAYf_NO_DBL_CLICK); win_inhibit=0; GrClear; } #define ORGF_CD 1 #define ORGF_INCOMPLETE 2 U0 MusicOrgan(U1 *dirname=NULL) { BoolI1 is_note,was_playing; U8 p1,p2,ch,sc,msg_code=0,note_down_time,col; U8 note=0,octave=0,accent=0,org_waveform=WF_SQUARE,org_octave=3,timeout_val,timeout_val2; F8 f=0,last_f=0,org_duration=1.0; U1 *filename=NULL,*st,*st2; TaskStruct *play_task=Spawn(&OrgPlayTask,NULL,"Organ Play",Fs); OrgNote *tempo; U8 old_ltf_flags; F8 d; Ctrl *c=TempoNew; if (LtfCur) old_ltf_flags=LtfCur->flags; SettingsPush; //See SettingsPush WinBorder(OFF); WordStat(OFF); Preempt(OFF); MkDir("HOME/MusicOrgan"); MusicSettingsReset; tempo_state.tempo=Round(TEMPO_RANGE*(music_tempo-0.5)/4.4); tempo_state.stacatto=Round(TEMPO_RANGE*(music_stacatto_factor-0.12)/0.88); if (LtfCur) LtfCur->flags|=LTFF_FORM; MemSet(&oc,0,sizeof(OrgCtrl)); oc.screen_x=0; oc.root.next=oc.root.last=&oc.root; oc.clipboard.next=oc.clipboard.last=&oc.clipboard; oc.root.waveform=WF_SQUARE; oc.cur_note=&oc.root; oc.base2=GrAlias(gr_persistent_base,Fs); MenuPush( "File {" " New(,'.');" " ChangeDir(MSG_CMD,ORGF_CD);" " Open(,CH_CTRLO);" " SaveAs(,CH_CTRLA);" " Abort(,CH_CTRLQ);" " Exit(,CH_ESC);" "}" "Edit {" " Cut(,0,0x3D300000253);" " Copy(,0,0x4D200000452);" " Paste(,0,0x2D200000252);" " RightMenu(,CH_CR);" " BackSpace(,CH_BACKSPACE);" " DeleteNote(,,SC_DELETE);" " ClearSong(,'.');" " Left(,,SC_CURSOR_LEFT);" " Right(,,SC_CURSOR_RIGHT);" " GoBegin(,,0x4CB0000044B);" " GoEnd(,,0x4CD0000044D);" "}" "Song {" " Play(,'x');" " Record(,'z');" " Random(,',');" " MarkIncomplete(MSG_CMD,ORGF_INCOMPLETE);" "}" "Snd {" " Square(,'!');" " Sine(,'@');" " Triangle(,'#');" " Sawtooth(,'$$');" " Noise(,'%');" " Reverb(,'c');" " Octave1(,'1');" " Octave2(,'2');" " Octave3(,'3');" " Octave4(,'4');" " Octave5(,'5');" "}" "Help {" " Help(,,SC_F1);" "}" ); oc.incomplete_entry=MenuEntryFind(Fs->cur_menu,"Song/MarkIncomplete"); oc.record_entry=MenuEntryFind(Fs->cur_menu,"Song/Record"); WinMax; if (!dirname) dirname=StrNew("HOME/MusicOrgan"); else dirname=StrNew(dirname); OrgPushMode(org_octave,org_waveform); col=0; Fs->draw_it=&DrawIt; try { do { was_playing=FALSE; start: if (ipty-Fs->win_top<18) msg_code=GetMsg(&p1,&p2,1<<MSG_KEY_DOWN|1<<MSG_KEY_UP|1<<MSG_IP_L_DOWN|1<<MSG_IP_L_UP|1<<MSG_IP_R_UP| 1<<MSG_IP_MOVE|1<<MSG_CMD); else msg_code=GetMsg(&p1,&p2,1<<MSG_KEY_DOWN|1<<MSG_KEY_UP|1<<MSG_IP_MOVE|1<<MSG_CMD); got_msg: if (msg_code==MSG_KEY_DOWN && p1==CH_SPACE && !p2) { //The Window Manager sets the Ltf cur_entry to a button //and generates a SPACE when the Ltf Buttons are clicked. //This is so that kbd and mouse are the same for Ltf's. //We must now pass the SPACE onto the Ltf handler. PutKey(p1,p2); goto start; } if (msg_code!=MSG_IP_MOVE) { LtfBottom; if (was_playing || LtfCur->cur_entry->y>=Fs->win_height-2) { OrgMenu(org_octave,org_waveform); col=0; } } octave=org_octave; switch (msg_code) { case MSG_CMD: OrgPopMode; switch (p1) { case ORGF_CD: Free(filename); filename=NULL; st2=dirname; if (dirname=PopUpPickDir) Free(st2); else dirname=st2; break; case ORGF_INCOMPLETE: oc.incomplete_entry->checked=!oc.incomplete_entry->checked; break; } OrgPushMode(org_octave,org_waveform); is_note=FALSE; col=0; break; case MSG_KEY_DOWN: ch=p1; sc=p2; if (ch>='0' && ch<='9') { org_octave=ch-'0'; OrgMenu(org_octave,org_waveform); col=0; } else { is_note=TRUE; switch (ch) { case 0: switch (sc.u1[0]) { case SC_CURSOR_LEFT: if (sc&SCF_CTRL) { while (oc.cur_note->last!=&oc.root) { oc.cur_note=oc.cur_note->last; if (oc.cur_note!=&oc.root) LBEqu(&oc.cur_note->flags,Of_SELECTED,sc&SCF_SHIFT); } } else { if (oc.cur_note->last!=&oc.root) { oc.cur_note=oc.cur_note->last; if (oc.cur_note!=&oc.root) LBEqu(&oc.cur_note->flags,Of_SELECTED,sc&SCF_SHIFT); } } break; case SC_CURSOR_RIGHT: if (sc&SCF_CTRL) { while (oc.cur_note!=&oc.root) { if (oc.cur_note!=&oc.root) LBEqu(&oc.cur_note->flags,Of_SELECTED,sc&SCF_SHIFT); oc.cur_note=oc.cur_note->next; } } else { if (oc.cur_note!=&oc.root) { if (oc.cur_note!=&oc.root) LBEqu(&oc.cur_note->flags,Of_SELECTED,sc&SCF_SHIFT); oc.cur_note=oc.cur_note->next; } } break; case SC_DELETE: if (sc&SCF_SHIFT) OrgCutToClipboard; else { tempo=oc.cur_note; oc.cur_note=tempo->next; if (tempo!=&oc.root) { RemQue(tempo); OrgNoteDel(tempo); } } break; case SC_INSERT: if (sc&SCF_SHIFT) OrgPasteClipboard; else if (sc&SCF_CTRL) OrgCopyToClipboard; break; case SC_F1: OrgPopMode; PopUp("Ed(\"::/LT/Apps/MusicOrgan/Help.TXZ\");",Fs); OrgPushMode(org_octave,org_waveform); col=0; is_note=FALSE; break; } is_note=FALSE; break; case 'a': note=7; octave--; break; case 's': note=8; octave--; break; case 'e': note=9; octave--; break; case 'd': note=10; octave--; break; case 'r': note=11; octave--; break; case 'f': note=0; break; case 't': note=1; break; case 'g': note=2; break; case 'h': note=3; break; case 'u': note=4; break; case 'j': note=5; break; case 'i': note=6; break; case 'k': note=7; break; case 'l': note=8; break; case 'p': note=9; break; case ';': note=10; break; case '[': note=11; break; case '\'': note=0; octave++; break; case ']': note=1; octave++; break; case CH_SPACE: note=0; octave=0; break; case ',': Free(filename); filename=NULL; OrgPopMode; st2=CallExtStr("MakeSong"); OrgLoadSongStr(st2,&org_octave,&org_duration); Free(st2); OrgPushMode(org_octave,org_waveform); is_note=FALSE; col=0; break; case CH_CTRLO: AcctOneTimePopUp(ARf_MUSIC_ORGAN_JUKEBOX, "Select a song and preview it.\r\n" "Press $$FG,GREEN$$CTRL-Q$$FG$$ to load it into MusicOrgan.\r\n\r\n" ST_WARN_ST " Graphics and other embelishments\r\n" "will be lost because MusicOrgan cannot\r\n" "parse C/C++ programs completely.\r\n"); Free(filename); filename=NULL; JukeBox(dirname,&filename); if (filename) { oc.screen_x=0; org_duration=1.0; org_octave=3; OrgSongDel(&oc.root); oc.cur_note=&oc.root; OrgLoadSong(filename,&org_octave,&org_duration); oc.record_entry->checked=FALSE; oc.cur_note=oc.root.next; } OrgPushMode(org_octave,org_waveform); is_note=FALSE; col=0; break; case CH_CTRLA: OrgPopMode; filename=OrgSaveSong(dirname,filename); OrgPushMode(org_octave,org_waveform); is_note=FALSE; break; case '.': OrgMenu(org_octave,org_waveform); col=0; Free(filename); filename=NULL; org_duration=1.0; org_octave=3; OrgSongDel(&oc.root); oc.cur_note=&oc.root; oc.screen_x=0; is_note=FALSE; break; case CH_CR: if (oc.cur_note!=&oc.root) OrgRightClick(oc.cur_note->x,oc.cur_note->y); is_note=FALSE; break; case 'x': if (was_playing) { is_note=FALSE; break; } col=0; oc.playing=TRUE; OrgMenu(org_octave,org_waveform); tempo=oc.cur_note; while (tempo!=&oc.root) { if (tempo->type!=OT_METER) { timeout_val=GetTimeStamp; if (ipty-Fs->win_top<18) msg_code=ScanMsg(&p1,&p2,1<<MSG_KEY_DOWN|1<<MSG_IP_L_DOWN|1<<MSG_IP_R_UP|1<<MSG_CMD); else msg_code=ScanMsg(&p1,&p2,1<<MSG_KEY_DOWN|1<<MSG_IP_L_DOWN|1<<MSG_CMD); if (msg_code) { f=0; org_play_f=0; is_note=FALSE; oc.playing=FALSE; was_playing=TRUE; if (ipty-Fs->win_top>=18 && msg_code==MSG_IP_L_DOWN) goto start; else goto got_msg; } oc.cur_note=tempo; oc.screen_x+=tempo->x-0.33*GR_WIDTH; if (tempo->word) if (StrLen(tempo->word)!=1 || (*tempo->word!=CH_SPACE && *tempo->word!=CH_SHIFT_SPACE)) PutS(tempo->word); note=tempo->note; octave=tempo->octave; accent=tempo->accent; org_waveform=tempo->waveform; if (note || octave) f=Note2Freq(note,octave); else f=-1; //rest if (f>0) org_play_f=f; else org_play_f=0; music_tempo=4.4*tempo_state.tempo/TEMPO_RANGE+0.5; music_stacatto_factor=0.88*tempo_state.stacatto/TEMPO_RANGE+0.12; music_waveform=org_waveform; d=time_stamp_freq*org_durations[tempo->duration]/music_tempo; timeout_val+=d*music_stacatto_factor; timeout_val2=timeout_val+ d*(1.0-music_stacatto_factor); SleepUntil(timeout_val); org_play_f=0; SleepUntil(timeout_val2); } tempo=tempo->next; } oc.cur_note=&oc.root; oc.screen_x+=oc.cur_note->x-GR_WIDTH/2; oc.playing=FALSE; OrgMenu(org_octave,org_waveform); col=0; f=0; org_play_f=0; is_note=FALSE; break; case CH_BACKSPACE: tempo=oc.cur_note->last; if (tempo!=&oc.root) { RemQue(tempo); OrgNoteDel(tempo); } is_note=FALSE; if (col) { PutChar(CH_BACKSPACE); col--; } break; case 'c': org_play_mode++; if (org_play_mode>=ORGPM_NUM_PLAY_MODES) org_play_mode=0; is_note=FALSE; OrgMenu(org_octave,org_waveform); col=0; break; case 'z': if (oc.record_entry->checked) { oc.record_entry->checked=FALSE; st2=OrgCvtSong; coutln st2; Free(st2); } else { oc.record_entry->checked=TRUE; org_duration=1.0; org_octave=3; oc.screen_x=0; } is_note=FALSE; OrgMenu(org_octave,org_waveform); col=0; break; case CH_ESC: OrgPopMode; filename=OrgSaveSong(dirname,filename); OrgPushMode(org_octave,org_waveform); break; case '!': music_waveform=org_waveform=WF_SQUARE; OrgMenu(org_octave,org_waveform); col=0; is_note=FALSE; break; case '@': music_waveform=org_waveform=WF_SINE; OrgMenu(org_octave,org_waveform); col=0; is_note=FALSE; break; case '#': music_waveform=org_waveform=WF_TRIANGLE; OrgMenu(org_octave,org_waveform); col=0; is_note=FALSE; break; case '$$': music_waveform=org_waveform=WF_SAWTOOTH; OrgMenu(org_octave,org_waveform); col=0; is_note=FALSE; break; case '%': music_waveform=org_waveform=WF_NOISE; OrgMenu(org_octave,org_waveform); col=0; is_note=FALSE; break; default: is_note=FALSE; } if (is_note) { if (note || octave) f=Note2Freq(note,octave); else f=-1; //rest } } break; case MSG_KEY_UP: f=0; break; case MSG_IP_MOVE: if (p2>18*FONT_HEIGHT) win_inhibit=0; else win_inhibit=WIF_ALL-WIF_BORDER; break; case MSG_IP_L_DOWN: OrgDownKey(p1,p2); OrgLeftClick(p1,p2); break; case MSG_IP_L_UP: OrgUpKey(p1,p2); break; default: OrgRightClick(p1,p2); } if (f!=last_f) { if (oc.record_entry->checked) { if (last_f) { music_tempo=4.4*tempo_state.tempo/TEMPO_RANGE+0.5; music_stacatto_factor=0.88*tempo_state.stacatto/TEMPO_RANGE+0.12; tempo->duration=OrgCvtDuration(music_tempo*(kbd_evt_time-note_down_time)/time_stamp_freq); OrgSetWidth(tempo); InsQue(tempo,oc.cur_note->last); } if (f) { note_down_time=kbd_evt_time; tempo=CAlloc(sizeof(OrgNote)); tempo->type=OT_NOTE; tempo->note=note; tempo->octave=octave; tempo->accent=0; tempo->waveform=org_waveform; } } if (f>0) { st=ListEntryPoint(note,org_note_list); org_play_f=f; } else { if (f<0) st="R"; else st=""; org_play_f=0; } last_f=f; cout st; col+=StrLen(st); if (col>=Fs->win_width-1) { CrLf; col=0; } } } while (ch!=CH_ESC && ch!=CH_CTRLQ); } catch Fs->catch_except=TRUE; OrgPopMode; OrgSongDel(&oc.root); OrgSongDel(&oc.clipboard); TempoDel(c); Kill(play_task); GrClear; GrDel(oc.base2); SettingsPop; if (LtfCur) LtfCur->flags=LtfCur->flags&~LTFF_FORM|old_ltf_flags<FF_FORM; Free(dirname); coutln "$$CL$$"; MenuPop; }