2033 lines
46 KiB
C++
2033 lines
46 KiB
C++
/*$WW,1$
|
|
This uses four types of ctrls
|
|
|
|
1) The pull-down menu.
|
|
|
|
2) The $LK,"CCtrl","MN:CCtrl"$ type for the tempo/stacatto sliders.
|
|
|
|
3) The active $LK,"CDoc","MN:CDoc"$ sprite buttons with macros for left/record/play/right.
|
|
|
|
4) Hand-made ctrls for the kbdgraphic, notes and staff.
|
|
|
|
|
|
|
|
|
|
This uses four types of output
|
|
|
|
1) The $LK,"CDoc","MN:CDoc"$ for the text and buttons and kbdgraphic.
|
|
|
|
2) The Fs->draw_it() for the staff region, drawn every refresh.
|
|
|
|
3) The gr_dc2 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 $LK,"GrUpdateWins","MN:GrUpdateWins"$() and $LK,"GrUpdateScreen","MN:GrUpdateScreen"$().
|
|
$WW,1$
|
|
|
|
$WW,0$*/
|
|
|
|
#define NOTE_REST MIN_I64
|
|
#define OCTAVE_REST MIN_I64
|
|
|
|
#define OT_ROOT 0
|
|
#define OT_NOTE 1
|
|
#define OT_METER 2
|
|
|
|
|
|
#define Of_SELECTED 0
|
|
#define Of_SHARP 1
|
|
#define Of_FLAT 2
|
|
#define Of_TIE 3
|
|
|
|
#define OF_SELECTED 1
|
|
#define OF_SHARP 2
|
|
#define OF_FLAT 4
|
|
#define OF_TIE 8
|
|
|
|
class OrgNote
|
|
{
|
|
OrgNote *next,*last;
|
|
I64 x,y;
|
|
U8 *word;
|
|
I64 type,flags;
|
|
union {
|
|
I64 note;
|
|
I64 meter_top;
|
|
};
|
|
union {
|
|
I64 octave;
|
|
I64 meter_bottom;
|
|
}
|
|
I64 duration,accent,width,waveform;
|
|
U8 ascii[32];
|
|
};
|
|
|
|
//Tool types
|
|
#define OTT_PTR_TOOL 0
|
|
#define OTT_BOX_TOOL 1
|
|
|
|
class OrgCtrl
|
|
{
|
|
OrgNote root;
|
|
OrgNote clipboard;
|
|
CMenuEntry *incomplete_entry,*record_entry;
|
|
I64 screen_x,
|
|
tool;
|
|
OrgNote *cur_note;
|
|
CDC *dc2;
|
|
Bool playing;
|
|
} oc;
|
|
|
|
U8 *org_note_list="A\0A#\0B\0C\0C#\0D\0D#\0E\0F\0F#\0G\0G#\0";
|
|
U8 org_note_map[12]={6,6,5,4,4,3,3,2,1,1,0,0};
|
|
U8 org_note_inverse_map[7]={10,8,7,5,3,2,0};
|
|
|
|
|
|
$SP,"<1>",1$
|
|
|
|
|
|
|
|
$SP,"<2>",2$
|
|
|
|
|
|
|
|
$SP,"<3>",3$
|
|
|
|
|
|
|
|
$SP,"<4>",4$
|
|
|
|
|
|
|
|
$SP,"<5>",5$
|
|
|
|
|
|
$SP,"<6>",6$
|
|
|
|
|
|
$SP,"<7>",7$
|
|
|
|
|
|
$SP,"<8>",8$
|
|
|
|
|
|
$SP,"<9>",9$
|
|
|
|
|
|
$SP,"<10>",10$
|
|
|
|
|
|
$SP,"<11>",11$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$SP,"<12>",12$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$SP,"<13>",13$
|
|
|
|
|
|
$SP,"<14>",14$
|
|
|
|
|
|
$SP,"<15>",15$
|
|
|
|
|
|
$SP,"<16>",16$
|
|
|
|
|
|
$SP,"<17>",17$
|
|
|
|
|
|
|
|
|
|
$SP,"<18>",18$
|
|
|
|
#define ORG_NOTE_SPACING 9
|
|
#define ORG_NUM_DURATIONS 12
|
|
|
|
F64 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};
|
|
U8 *org_duration_list="st\0s\0et\0e\0qt\0e.\0q\0q.\0h\0h.\0w\0w.\0";
|
|
U8 *org_duration_imgs[ORG_NUM_DURATIONS]={$IB,"<1>",1$,$IB,"<1>",1$,$IB,"<2>",2$,
|
|
$IB,"<2>",2$,$IB,"<3>",3$,$IB,"<2>",2$,$IB,"<3>",3$,$IB,"<3>",3$,
|
|
$IB,"<4>",4$,$IB,"<4>",4$,$IB,"<5>",5$,$IB,"<5>",5$};
|
|
Bool org_triplet_durations[ORG_NUM_DURATIONS]={TRUE,FALSE,TRUE,
|
|
FALSE,TRUE,FALSE,FALSE,FALSE,
|
|
FALSE,FALSE,FALSE,FALSE};
|
|
|
|
Bool OrgHasWords(U8 *st)
|
|
{
|
|
if (st && *st && (StrLen(st)>1 || *st!=CH_SPACE && *st!=CH_SHIFT_SPACE))
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
Bool OrgIsDotted(I64 duration)
|
|
{
|
|
U8 *st=ListEntryPt(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 (Bt(&tempo->flags,Of_SHARP) || Bt(&tempo->flags,Of_FLAT))
|
|
tempo->width+=ORG_NOTE_SPACING;
|
|
}
|
|
}
|
|
|
|
U0 OrgRecalcNoteXY()
|
|
{
|
|
F64 measure_len=4,measure_left=measure_len;
|
|
OrgNote *tempo=oc.root.next;
|
|
I64 x=8-oc.screen_x,note,octave;
|
|
while (TRUE) {
|
|
tempo->x=x;
|
|
tempo->y=50;
|
|
if (tempo==&oc.root)
|
|
break;
|
|
else {
|
|
if (tempo->type!=OT_METER) {
|
|
octave=tempo->octave;
|
|
if (octave!=OCTAVE_REST) {
|
|
note=tempo->note;
|
|
if (Bt(&tempo->flags,Of_SHARP))
|
|
note--;
|
|
if (Bt(&tempo->flags,Of_FLAT))
|
|
note++;
|
|
if (note<0) {
|
|
note=11;
|
|
octave--;
|
|
} else if (note>11) {
|
|
note=0;
|
|
octave++;
|
|
}
|
|
note=music_note_map[*ListEntryPt(note,org_note_list)-'A'];
|
|
tempo->y=(15+(org_note_map[note]-7*(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(I64 x1,I64 x2,Bool 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);
|
|
else
|
|
tempo1->word=NULL;
|
|
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;
|
|
QueRem(tempo);
|
|
tempo->flags&=~OF_SELECTED;
|
|
QueIns(tempo,oc.clipboard.last);
|
|
}
|
|
tempo=tempo1;
|
|
}
|
|
}
|
|
|
|
U0 OrgPasteClipboard()
|
|
{
|
|
OrgNote *tempo,*tempo1;
|
|
tempo=oc.clipboard.next;
|
|
while (tempo!=&oc.clipboard) {
|
|
tempo1=OrgNoteCopy(tempo);
|
|
QueIns(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);
|
|
QueIns(tempo1,oc.clipboard.last);
|
|
}
|
|
tempo=tempo->next;
|
|
}
|
|
}
|
|
|
|
OrgNote *OrgFindNote(I64 x,I64)
|
|
{
|
|
OrgNote *tempo=oc.root.next;
|
|
OrgRecalcNoteXY;
|
|
x+=ORG_NOTE_SPACING/2;
|
|
while (x>tempo->next->x && tempo!=&oc.root)
|
|
tempo=tempo->next;
|
|
return tempo;
|
|
}
|
|
|
|
Bool OrgBlink(F64 t)
|
|
{
|
|
if (Blink(,t) || oc.playing)
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
U0 DrawNote(CDC *dc,I64 x,I64 y,I64 duration)
|
|
{
|
|
if (0<=duration<=ORG_NUM_DURATIONS) {
|
|
CSpritePlot3(dc,x,y,0,org_duration_imgs[duration]);
|
|
if (org_triplet_durations[duration])
|
|
CSpritePlot3(dc,x,y,0,$IB,"<18>",18$);
|
|
if (OrgIsDotted(duration))
|
|
CSpritePlot3(dc,x,y,0,$IB,"<19>",19$);
|
|
}
|
|
}
|
|
|
|
U0 DrawTimeSignature(CDC *dc,I64 x,I64 y,I64 top,I64 bottom)
|
|
{
|
|
GrPrintF(dc,x,y,"%d",top);
|
|
GrPrintF(dc,x,y+FONT_HEIGHT,"%d",bottom);
|
|
}
|
|
|
|
U0 DrawIt(CTask *task,CDC *dc)
|
|
{
|
|
OrgNote *tempo;
|
|
I64 i,x,y,
|
|
w=task->win_pixel_width;
|
|
F64 measure_len=4,measure_left=measure_len;
|
|
Bool old_preempt=Preempt(OFF);
|
|
|
|
dc->color=BLACK;
|
|
for (i=1;i<6;i++)
|
|
GrLine(dc,0,i*8,w,i*8);
|
|
for (i=7;i<12;i++)
|
|
GrLine(dc,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) {
|
|
dc->color=BLACK;
|
|
GrLine(dc,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)))
|
|
dc->color=BROWN;
|
|
else
|
|
dc->color=BLACK;
|
|
DrawTimeSignature(dc,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))) {
|
|
dc->color=BROWN;
|
|
GrPutS(dc,x+8,y,tempo->word);
|
|
} else if (tempo->flags&OF_SELECTED)
|
|
dc->color=RED;
|
|
else {
|
|
if (tempo->note!=NOTE_REST)
|
|
dc->color=BLACK;
|
|
else
|
|
dc->color=LTGRAY;
|
|
if (OrgHasWords(tempo->word))
|
|
dc->color=GREEN;
|
|
}
|
|
if (tempo->accent==1)
|
|
CSpritePlot3(dc,x,y,0,$IB,"<20>",20$);
|
|
else if (tempo->accent==2)
|
|
CSpritePlot3(dc,x,y,0,$IB,"<21>",21$);
|
|
DrawNote(dc,x,y,tempo->duration);
|
|
if (OrgIsDotted(tempo->duration))
|
|
x+=ORG_NOTE_SPACING/2;
|
|
|
|
if (Bt(&tempo->flags,Of_SHARP))
|
|
CSpritePlot3(dc,x,y,0,$IB,"<22>",22$);
|
|
else if (Bt(&tempo->flags,Of_FLAT))
|
|
CSpritePlot3(dc,x,y,0,$IB,"<23>",23$);
|
|
measure_left-=org_durations[tempo->duration];
|
|
}
|
|
tempo=tempo->next;
|
|
}
|
|
|
|
if (oc.cur_note==&oc.root && OrgBlink(tP(task)))
|
|
dc->color=BROWN;
|
|
else
|
|
dc->color=BLACK;
|
|
CSpritePlot3(dc,oc.root.x,50,0,$IB,"<24>",24$);
|
|
Preempt(old_preempt);
|
|
}
|
|
|
|
#define ORGR_STRONG_ACCENT -11
|
|
#define ORGR_ACCENT -10
|
|
#define ORGR_NO_ACCENT -9
|
|
#define ORGR_FLAT -8
|
|
#define ORGR_SHARP -7
|
|
#define ORGR_TIE -6
|
|
#define ORGR_REST -5
|
|
#define ORGR_INS_NOTE -4
|
|
#define ORGR_DELETE_NOTE -3
|
|
#define ORGR_SET_WORD -2
|
|
|
|
F64 PopUpDuration()
|
|
{
|
|
I64 i;
|
|
CDoc *doc=DocNew;
|
|
DocPutS(doc,"$$FM,GREEN$$$$MU,\"Set Word\",ORGR_SET_WORD$$\n"
|
|
"$$MU,\"Toggle Sharp\",ORGR_SHARP$$\n"
|
|
"$$MU,\"Toggle Flat\",ORGR_FLAT$$\n"
|
|
"$$MU,\"Toggle Tie\",ORGR_TIE$$\n"
|
|
"$$MU,\"Make Rest\",ORGR_REST$$\n"
|
|
"$$MU,\"Insert Note\",ORGR_INS_NOTE$$\n"
|
|
"$$MU,\"Delete Note\",ORGR_DELETE_NOTE$$\n"
|
|
"$$MU,\"No Accent\",ORGR_NO_ACCENT$$\n"
|
|
"$$MU,\"Accent\",ORGR_ACCENT$$\n"
|
|
"$$MU,\"Strong Accent\",ORGR_STRONG_ACCENT$$\n\n");
|
|
for (i=0;i<ORG_NUM_DURATIONS;i++)
|
|
DocPrintF(doc,"$$MU,\"%7.5f\",%d$$\n",org_durations[i],i);
|
|
DocPutS(doc,"\n$$MU,\"CANCEL\",DOCM_CANCEL$$\n");
|
|
i=PopUpMenu(doc);
|
|
DocDel(doc);
|
|
return i;
|
|
}
|
|
|
|
U0 OrgRightClick(I64 x,I64 y)
|
|
{
|
|
U8 *st,*st2;
|
|
OrgNote *tempo,*tempo1;
|
|
I64 i;
|
|
I64 old_doc_flags;
|
|
if (DocCur) old_doc_flags=DocCur->flags;
|
|
oc.cur_note=tempo=OrgFindNote(x,y);
|
|
if (tempo!=&oc.root) {
|
|
Fs->win_inhibit=0;
|
|
i=PopUpDuration;
|
|
if (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=OCTAVE_REST;
|
|
tempo->note=NOTE_REST;
|
|
tempo->accent=0;
|
|
tempo->waveform=WF_SQUARE;
|
|
}
|
|
break;
|
|
case ORGR_SHARP:
|
|
if (tempo->type==OT_NOTE && tempo->octave!=OCTAVE_REST) {
|
|
if (Btr(&tempo->flags,Of_FLAT))
|
|
tempo->note++;
|
|
if (Btc(&tempo->flags,Of_SHARP))
|
|
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_FLAT:
|
|
if (tempo->type==OT_NOTE && tempo->octave!=OCTAVE_REST) {
|
|
if (Btr(&tempo->flags,Of_SHARP))
|
|
tempo->note--;
|
|
if (Btc(&tempo->flags,Of_FLAT))
|
|
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_TIE:
|
|
if (tempo->type==OT_NOTE)
|
|
Btc(&tempo->flags,Of_TIE);
|
|
break;
|
|
case ORGR_SET_WORD:
|
|
if (tempo->type==OT_NOTE) {
|
|
if (DocCur) DocCur->flags&=~DOCF_FORM;
|
|
if (OrgHasWords(tempo->word))
|
|
st2=MSPrintF("\nWord(\"%Q\"):",tempo->word);
|
|
else
|
|
st2=MSPrintF("\nWord(\"\"):");
|
|
DocBottom;
|
|
st=PmtStr(st2);
|
|
Free(st2);
|
|
Free(tempo->word);
|
|
if (*st) {
|
|
tempo->word=MSPrintF("%q",st);
|
|
Free(st);
|
|
} else
|
|
tempo->word=StrNew(" ");
|
|
if (DocCur) DocCur->flags=DocCur->flags&~DOCF_FORM|old_doc_flags&DOCF_FORM;
|
|
}
|
|
break;
|
|
case ORGR_INS_NOTE:
|
|
tempo1=OrgNoteCopy(tempo);
|
|
QueIns(tempo1,tempo);
|
|
break;
|
|
case ORGR_DELETE_NOTE:
|
|
oc.cur_note=tempo->next;
|
|
QueRem(tempo);
|
|
OrgNoteDel(tempo);
|
|
break;
|
|
case ORGR_NO_ACCENT:
|
|
if (tempo->type==OT_NOTE && tempo->octave!=OCTAVE_REST)
|
|
tempo->accent=0;
|
|
break;
|
|
case ORGR_ACCENT:
|
|
if (tempo->type==OT_NOTE && tempo->octave!=OCTAVE_REST)
|
|
tempo->accent=1;
|
|
break;
|
|
case ORGR_STRONG_ACCENT:
|
|
if (tempo->type==OT_NOTE && tempo->octave!=OCTAVE_REST)
|
|
tempo->accent=2;
|
|
break;
|
|
}
|
|
}
|
|
OrgSetWidth(oc.cur_note);
|
|
Fs->win_inhibit=WIF_ALL-WIF_BORDER-WIF_MENU-WIF_CTRLS;
|
|
}
|
|
}
|
|
|
|
#define ORG_NOTE_BOX_X 220
|
|
#define ORG_NOTE_BOX_Y (13*FONT_HEIGHT+14)
|
|
|
|
U0 OrgSetPickNoteBoxX(I64 duration,I64 *x)
|
|
{
|
|
I64 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;
|
|
}
|
|
}
|
|
|
|
I64 OrgGetPickNoteBoxDuration(I64 xx,I64 yy)
|
|
{
|
|
I64 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()
|
|
{
|
|
I64 i,x;
|
|
for (i=0;i<ORG_NUM_DURATIONS;i++) {
|
|
OrgSetPickNoteBoxX(i,&x);
|
|
if (OrgIsDotted(i))
|
|
oc.dc2->color=RED;
|
|
else if (org_triplet_durations[i])
|
|
oc.dc2->color=LTRED;
|
|
else
|
|
oc.dc2->color=BLACK;
|
|
DrawNote(oc.dc2,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.dc2->color=ROPF_DITHER+WHITE<<16+ROP_EQU+RED;
|
|
else
|
|
oc.dc2->color=ROPF_DITHER+WHITE<<16+ROP_EQU+BLACK;
|
|
GrLineRect4(oc.dc2,ORG_TOOLS_X,ORG_TOOLS_Y,
|
|
ORG_TOOLS_X+10,ORG_TOOLS_Y+10);
|
|
|
|
if (oc.tool==OTT_PTR_TOOL)
|
|
oc.dc2->color=ROP_EQU+RED;
|
|
else
|
|
oc.dc2->color=ROP_EQU+BLACK;
|
|
(*fp_draw_input_ptr)(oc.dc2,ORG_TOOLS_X+15,ORG_TOOLS_Y);
|
|
oc.dc2->color=BLACK;
|
|
}
|
|
|
|
|
|
Bool OrgGetPickToolBox(I64 xx,I64 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
|
|
I64 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
|
|
Bool OrgGetPickMeterBox(I64 xx,I64 yy,I64 *top,I64 *bottom)
|
|
{
|
|
I64 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()
|
|
{
|
|
I64 i;
|
|
oc.dc2->color=BLACK;
|
|
for (i=0;i<ORG_NUM_METERS;i++)
|
|
DrawTimeSignature(oc.dc2,ORG_METER_X+i*ORG_METER_W,ORG_METER_Y,meter_tops[i],meter_bottoms[i]);
|
|
}
|
|
|
|
U0 DrawDC2()
|
|
{
|
|
DCFill;
|
|
DrawPickNoteBox;
|
|
DrawPickMeterBox;
|
|
DrawPickTools;
|
|
}
|
|
|
|
U0 OrgLeftClickPickNoteBox(I64 duration)
|
|
{
|
|
I64 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) {
|
|
DrawDC2;
|
|
DrawNote(oc.dc2,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);
|
|
QueIns(tempo,tempo1);
|
|
oc.cur_note=tempo->next;
|
|
}
|
|
DrawDC2;
|
|
}
|
|
|
|
U0 OrgLeftClickPickMeterBox(I64 top,I64 bottom)
|
|
{
|
|
I64 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) {
|
|
DrawDC2;
|
|
DrawTimeSignature(oc.dc2,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);
|
|
QueIns(tempo,tempo1);
|
|
oc.cur_note=tempo->next;
|
|
}
|
|
DrawDC2;
|
|
}
|
|
|
|
U0 OrgLeftClickStaffPtr(I64 x,I64 y)
|
|
{
|
|
OrgNote *tempo,*tempo1;
|
|
I64 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(I64 x,I64 y)
|
|
{
|
|
I64 msg_code,p1,p2;
|
|
do {
|
|
msg_code=GetMsg(&p1,&p2,1<<MSG_IP_L_UP|1<<MSG_IP_MOVE);
|
|
DrawDC2;
|
|
oc.dc2->color=ROPF_DITHER+WHITE<<16+ROP_EQU+BLACK;
|
|
GrLineRect4(oc.dc2,x,y,p1,p2);
|
|
if (msg_code==MSG_IP_L_UP) {
|
|
if (x>p1) SwapU64(&x,&p1);
|
|
OrgMarkSelected(x,p1,TRUE);
|
|
}
|
|
} while (msg_code!=MSG_IP_L_UP);
|
|
DrawDC2;
|
|
}
|
|
|
|
U0 OrgLeftClick(I64 x,I64 y)
|
|
{
|
|
I64 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))
|
|
DrawDC2;
|
|
}
|
|
}
|
|
|
|
|
|
#define ORGPM_NORMAL 0
|
|
#define ORGPM_REVERB1 1
|
|
#define ORGPM_NUM_PLAY_MODES 2
|
|
|
|
I64 org_play_mode=0;
|
|
F64 org_play_f=0;
|
|
|
|
U0 OrgPlayTask(I64)
|
|
{
|
|
I64 i=0;
|
|
F64 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);
|
|
}
|
|
}
|
|
|
|
|
|
U8 OrgCvtDuration(F64 d)
|
|
{
|
|
F64 d1,d2;
|
|
I64 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;
|
|
}
|
|
|
|
|
|
U8 *OrgMusicSetOctave(U8 *st,I64 *org_octave)
|
|
{
|
|
while ('0'<=*st<='9')
|
|
*org_octave=*st++ -'0';
|
|
return st;
|
|
}
|
|
|
|
U8 *OrgMusicSetNoteLen(U8 *st,F64 *org_duration)
|
|
{
|
|
Bool 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(U8 *st,I64 *org_octave,F64 *org_duration)
|
|
{
|
|
OrgNote *tempo,*tempo1;
|
|
I64 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);
|
|
QueIns(tempo1,oc.root.last);
|
|
}
|
|
if (*st=='W') {
|
|
st++;
|
|
tempo->waveform=*st++-'0';
|
|
waveform=tempo->waveform;
|
|
}
|
|
while (*st=='!') {
|
|
tempo->accent++;
|
|
st++;
|
|
}
|
|
while (*st=='(') {
|
|
Bts(&tempo->flags,Of_TIE);
|
|
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') {
|
|
Bts(&tempo->flags,Of_FLAT);
|
|
note--;
|
|
st++;
|
|
} else if (*st=='#') {
|
|
Bts(&tempo->flags,Of_SHARP);
|
|
note++;
|
|
st++;
|
|
}
|
|
if (note<0) {
|
|
note=11;
|
|
*org_octave-=1;
|
|
} else if (note>11) {
|
|
note=0;
|
|
*org_octave+=1;
|
|
}
|
|
tempo->note=note;
|
|
tempo->octave=*org_octave;
|
|
} else {
|
|
tempo->note=NOTE_REST;
|
|
tempo->octave=OCTAVE_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);
|
|
QueIns(tempo,oc.cur_note->last);
|
|
}
|
|
}
|
|
|
|
U0 OrgLoadSong(U8 *filename,I64 *org_octave,F64 *org_duration)
|
|
{
|
|
U8 *st;
|
|
OrgNote *tempo;
|
|
CLex *lx=LexNew(TextFileRead(filename),0,StrNew(filename));
|
|
Lex(lx);
|
|
if (FileOcc("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=LexExtStr(lx);
|
|
OrgLoadSongStr(st,org_octave,org_duration);
|
|
if (lx->token==',') {
|
|
if (Lex(lx)==TK_STR) {
|
|
st=LexExtStr(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_F64) {
|
|
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_F64) {
|
|
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);
|
|
}
|
|
|
|
U8 *OrgCvtSong()
|
|
{
|
|
OrgNote *tempo;
|
|
U8 *st,*src,*dst;
|
|
I64 i,note,octave,last_octave,last_duration,accent,waveform,last_waveform;
|
|
|
|
i=0;
|
|
tempo=oc.root.next;
|
|
last_octave=OCTAVE_REST;
|
|
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;
|
|
if (note!=NOTE_REST) {
|
|
if (Bt(&tempo->flags,Of_SHARP))
|
|
note--;
|
|
if (Bt(&tempo->flags,Of_FLAT))
|
|
note++;
|
|
if (note<0) {
|
|
note=11;
|
|
octave--;
|
|
} else if (note>11) {
|
|
note=0;
|
|
octave++;
|
|
}
|
|
note=music_note_map[*ListEntryPt(note,org_note_list)-'A'];
|
|
}
|
|
accent=tempo->accent;
|
|
waveform=tempo->waveform;
|
|
if (waveform!=last_waveform && note!=NOTE_REST) {
|
|
*dst++='W';
|
|
*dst++=waveform+'0';
|
|
last_waveform=waveform;
|
|
}
|
|
if (Bt(&tempo->flags,Of_TIE))
|
|
*dst++='(';
|
|
while (accent--)
|
|
*dst++='!';
|
|
if (octave!=last_octave && note!=NOTE_REST) {
|
|
*dst++=octave+'0';
|
|
last_octave=octave;
|
|
}
|
|
if (tempo->duration!=last_duration) {
|
|
src=ListEntryPt(tempo->duration,org_duration_list);
|
|
*dst++=src[0];
|
|
if (src[1])
|
|
*dst++=src[1];
|
|
last_duration=tempo->duration;
|
|
}
|
|
if (note!=NOTE_REST) {
|
|
src=ListEntryPt(note,org_note_list);
|
|
*dst++=src[0];
|
|
if (src[1])
|
|
*dst++=src[1];
|
|
else if (Bt(&tempo->flags,Of_FLAT))
|
|
*dst++='b';
|
|
else if (Bt(&tempo->flags,Of_SHARP))
|
|
*dst++='#';
|
|
} 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;
|
|
}
|
|
|
|
U8 *OrgSaveSong(U8 *dirname,U8 *full_filename)
|
|
{
|
|
CDoc *doc=DocNew;
|
|
Bool has_words;
|
|
OrgNote *tempo,*tempo1;
|
|
F64 measure_len=4,two_measure_left=2*measure_len;
|
|
U8 *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 (OrgHasWords(tempo->word)) has_words=TRUE;
|
|
tempo=tempo->next;
|
|
}
|
|
if (oc.incomplete_entry->checked)
|
|
DocPutS(doc,"//0 incomplete\n");
|
|
else if (has_words)
|
|
DocPutS(doc,"//0 has words\n");
|
|
else
|
|
DocPutS(doc,"//0 no nothing\n");
|
|
|
|
DocPrintF(doc,
|
|
"U0 Song()\n"
|
|
"{\n"
|
|
" Fs->task_end_cb=&SndTaskEndCB;\n"
|
|
" MusicSettingsRst;\n"
|
|
" music_tempo=%6.3f;\n"
|
|
" music_stacatto_factor=%6.3f;\n"
|
|
" try {\n"
|
|
" while (!ScanKey) {\n"
|
|
"\tPlay(\"",music_tempo+0.0005,music_stacatto_factor+0.0005);
|
|
|
|
tempo=oc.root.next;
|
|
tempo1=tempo;
|
|
has_words=FALSE;
|
|
while (tempo!=&oc.root) {
|
|
DocPutS(doc,tempo->ascii);
|
|
if (OrgHasWords(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) {
|
|
DocPutS(doc,"\",\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++;
|
|
}
|
|
DocPrintF(doc,"%Q\\0",tempo1->word);
|
|
} else
|
|
DocPrintF(doc,"%c\\0",CH_SHIFT_SPACE);
|
|
}
|
|
tempo1=tempo1->next;
|
|
}
|
|
}
|
|
DocPutS(doc,"\");\n"
|
|
"\tPlay(\"");
|
|
two_measure_left=2*measure_len;
|
|
tempo1=tempo;
|
|
has_words=FALSE;
|
|
}
|
|
}
|
|
if (has_words) {
|
|
DocPutS(doc,"\",\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++;
|
|
}
|
|
DocPrintF(doc,"%Q\\0",tempo1->word);
|
|
} else
|
|
DocPrintF(doc,"%c\\0",CH_SHIFT_SPACE);
|
|
}
|
|
tempo1=tempo1->next;
|
|
}
|
|
}
|
|
DocPutS(doc,"\");\n"
|
|
" }\n"
|
|
" } catch\n"
|
|
" CatchAll;\n"
|
|
" Snd(0);\n"
|
|
"}\n"
|
|
"\n"
|
|
"Song;\n");
|
|
DocRecalc(doc);
|
|
if (full_filename) {
|
|
StrCpy(doc->filename.name,full_filename);
|
|
Free(full_filename);
|
|
} else
|
|
SPrintF(doc->filename.name,"%s/Temp.CPP.Z",dirname);
|
|
DocWrite(doc,TRUE);
|
|
full_filename=StrNew(doc->filename.name);
|
|
DocDel(doc);
|
|
return full_filename;
|
|
}
|
|
|
|
|
|
U0 OrgSetOctave(I64 octave)
|
|
{
|
|
I64 i;
|
|
U8 buf[136];
|
|
CMenuEntry *tempse;
|
|
for (i=0;i<=6;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(I64 waveform)
|
|
{
|
|
CMenuEntry *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;
|
|
}
|
|
|
|
|
|
|
|
|
|
$SP,"<25>",25$
|
|
|
|
|
|
|
|
|
|
|
|
#define ORG_NUM_KEYS 20
|
|
class OrgKey
|
|
{
|
|
U8 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_NEW_LINE},
|
|
|
|
};
|
|
|
|
|
|
U0 OrgDownKey(I64 x,I64 y)
|
|
{
|
|
I64 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) {
|
|
Msg(MSG_KEY_DOWN,o->ascii,0);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
U0 OrgUpKey(I64 x,I64 y)
|
|
{
|
|
I64 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) {
|
|
Msg(MSG_KEY_UP,o->ascii,0);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
U0 OrgMenu(I64 org_octave,I64 org_waveform)
|
|
{
|
|
DocClear;
|
|
"$$BD,WHITE$$$$FD,GREEN$$$$FU,GREEN$$$$FM,GREEN$$$$CM,0,12$$\n";
|
|
PutSprite($IB,"<25>",25$);
|
|
NewLine(5);
|
|
|
|
DrawDC2;
|
|
|
|
"$$FG,LTGREEN$$<SPACE BAR>$$FG$$\tRest\n"
|
|
"$$FG,LTGREEN$$<BACKSPACE>$$FG$$\tDeletes Last Note\n"
|
|
"$$FG,LTGREEN$$Left Mouse$$FG$$\tDrag note or shift word\n"
|
|
"$$FG,LTGREEN$$Right Mouse$$FG$$\tChange duration or set word\n";
|
|
PutSprite($IB,"<6>",6$,"$$SP+LM+LA,\"\",\"Msg(MSG_KEY_DOWN,0,SCF_CTRL|SC_CURSOR_LEFT);\",%d$$");
|
|
" ";
|
|
if (oc.playing)
|
|
PutSprite($IB,"<9>",9$,"$$SP+LM,\"\",\"x\",%d$$");
|
|
else
|
|
PutSprite($IB,"<8>",8$,"$$SP+LM,\"\",\"x\",%d$$");
|
|
" ";
|
|
if (oc.record_entry->checked) {
|
|
oc.record_entry->checked=TRUE;
|
|
PutSprite($IB,"<10>",10$,"$$SP+LM,\"\",\"z\",%d$$");
|
|
} else
|
|
PutSprite($IB,"<11>",11$,"$$SP+LM,\"\",\"z\",%d$$");
|
|
" ";
|
|
PutSprite($IB,"<7>",7$,"$$SP+LM+LA,\"\",\"Msg(MSG_KEY_DOWN,0,SCF_CTRL|SC_CURSOR_RIGHT);\",%d$$");
|
|
"$$CM+LX,0,6$$";
|
|
OrgSetOctave(org_octave);
|
|
OrgSetWaveform(org_waveform);
|
|
WinMgrSync(2);
|
|
}
|
|
|
|
|
|
U0 OrgPushMode(I64 org_octave,I64 org_waveform)
|
|
{
|
|
Fs->win_inhibit=WIF_ALL-WIF_BORDER-WIF_MENU-WIF_CTRLS;
|
|
OrgMenu(org_octave,org_waveform);
|
|
}
|
|
|
|
U0 OrgPopMode()
|
|
{
|
|
Fs->win_inhibit=0;
|
|
DCFill;
|
|
}
|
|
|
|
#define ORGF_CD 1
|
|
#define ORGF_INCOMPLETE 2
|
|
|
|
U0 MusicOrgan(U8 *dirname=NULL)
|
|
{
|
|
Bool is_note,was_playing;
|
|
I64 p1,p2,ch,sc,msg_code=0,col;
|
|
I64 note=NOTE_REST,octave=OCTAVE_REST,accent=0,org_waveform=WF_SQUARE,org_octave=3,timeout_val,timeout_val2;
|
|
F64 f=0,last_f=0,org_duration=1.0;
|
|
U8 *filename=NULL,*st,*st2;
|
|
CTask *play_task=Spawn(&OrgPlayTask,NULL,"Organ Play",Fs);
|
|
OrgNote *tempo;
|
|
I64 old_doc_flags;
|
|
F64 d,evt_time=tP,note_down_time=tP;
|
|
CCtrl *c=TempoNew;
|
|
|
|
if (DocCur) old_doc_flags=DocCur->flags;
|
|
SettingsPush; //See $LK,"SettingsPush","MN:SettingsPush"$
|
|
WinBorder;
|
|
WordStat;
|
|
Preempt(OFF);
|
|
|
|
MkDir("HOME/MusicOrgan");
|
|
MusicSettingsRst;
|
|
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 (DocCur) DocCur->flags|=DOCF_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.dc2=DCAlias;
|
|
|
|
MenuPush(
|
|
"File {"
|
|
" New(,'.');"
|
|
" ChgDir(MSG_CMD,ORGF_CD);"
|
|
" Open(,CH_CTRLO);"
|
|
" SaveAs(,CH_CTRLA);"
|
|
" Abort(,CH_SHIFT_ESC);"
|
|
" Exit(,CH_ESC);"
|
|
"}"
|
|
"Edit {"
|
|
" Cut(,CH_CTRLX);"
|
|
" Copy(,CH_CTRLC);"
|
|
" Paste(,CH_CTRLV);"
|
|
" RightMenu(,CH_NEW_LINE);"
|
|
" 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');"
|
|
" Octave0(,'0');"
|
|
" Octave1(,'1');"
|
|
" Octave2(,'2');"
|
|
" Octave3(,'3');"
|
|
" Octave4(,'4');"
|
|
" Octave5(,'5');"
|
|
" Octave6(,'6');"
|
|
"}"
|
|
"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 Mgr sets the Doc cur_entry to a button
|
|
//and generates a <SPACE BAR> when the Doc Buttons are clicked.
|
|
//This is so that kbd and mouse are the same for Doc's.
|
|
//We must now pass the <SPACE BAR> onto the Doc handler.
|
|
PutKey(p1,p2);
|
|
goto start;
|
|
}
|
|
if (msg_code!=MSG_IP_MOVE) {
|
|
DocBottom;
|
|
if (was_playing || DocCur->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:
|
|
st2=dirname;
|
|
if (dirname=PopUpPickDir) {
|
|
Free(st2);
|
|
Free(filename);
|
|
filename=NULL;
|
|
} 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:
|
|
evt_time=tP;
|
|
ch=p1;
|
|
sc=p2;
|
|
if ('0'<=ch<='9') {
|
|
org_octave=ch-'0';
|
|
OrgMenu(org_octave,org_waveform);
|
|
col=0;
|
|
} else {
|
|
is_note=TRUE;
|
|
switch (ch) {
|
|
case 0:
|
|
switch (sc.u8[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) {
|
|
QueRem(tempo);
|
|
OrgNoteDel(tempo);
|
|
}
|
|
}
|
|
break;
|
|
case SC_INS:
|
|
if (sc&SCF_SHIFT)
|
|
OrgPasteClipboard;
|
|
else if (sc&SCF_CTRL)
|
|
OrgCopyToClipboard;
|
|
break;
|
|
case SC_F1:
|
|
OrgPopMode;
|
|
PopUp("Ed(\"::/SparrowOS/Apps/MusicOrgan/Help.TXT.Z\");",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=NOTE_REST;
|
|
octave=OCTAVE_REST;
|
|
break;
|
|
case ',':
|
|
Free(filename);
|
|
filename=NULL;
|
|
OrgPopMode;
|
|
music_octave=org_octave;
|
|
if (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:
|
|
OrgPopMode;
|
|
AcctOneTimePopUp(ARf_MUSIC_ORGAN_JUKEBOX,
|
|
"Select a song and preview it.\n"
|
|
"$$FG,GREEN$$<SHIFT-ESC>$$FG$$ to load it into MusicOrgan.\n\n"
|
|
ST_WARN_ST " Graphics and other embelishments\n"
|
|
"will be lost because MusicOrgan can't\n"
|
|
"parse C/C++ programs completely.\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 CH_CTRLC:
|
|
OrgCopyToClipboard;
|
|
is_note=FALSE;
|
|
break;
|
|
case CH_CTRLV:
|
|
OrgPasteClipboard;
|
|
is_note=FALSE;
|
|
break;
|
|
case CH_CTRLX:
|
|
OrgCutToClipboard;
|
|
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_NEW_LINE:
|
|
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=sys_jiffies;
|
|
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 (OrgHasWords(tempo->word))
|
|
"" tempo->word;
|
|
note=tempo->note;
|
|
octave=tempo->octave;
|
|
accent=tempo->accent;
|
|
org_waveform=tempo->waveform;
|
|
if (note!=NOTE_REST)
|
|
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=JIFFY_FREQ*org_durations[tempo->duration]/music_tempo;
|
|
if (Bt(&tempo->flags,Of_TIE)) {
|
|
timeout_val+=d;
|
|
timeout_val2=timeout_val;
|
|
} else {
|
|
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) {
|
|
QueRem(tempo);
|
|
OrgNoteDel(tempo);
|
|
}
|
|
is_note=FALSE;
|
|
if (col) {
|
|
'' 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;
|
|
else {
|
|
oc.record_entry->checked=TRUE;
|
|
org_duration=1.0;
|
|
org_octave=3;
|
|
oc.screen_x=0;
|
|
}
|
|
OrgMenu(org_octave,org_waveform);
|
|
col=0;
|
|
is_note=FALSE;
|
|
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!=NOTE_REST)
|
|
f=Note2Freq(note,octave);
|
|
else
|
|
f=-1; //rest
|
|
}
|
|
}
|
|
break;
|
|
case MSG_KEY_UP:
|
|
evt_time=tP;
|
|
f=0;
|
|
break;
|
|
case MSG_IP_MOVE:
|
|
if (p2>18*FONT_HEIGHT)
|
|
Fs->win_inhibit=0;
|
|
else
|
|
Fs->win_inhibit=WIF_ALL-WIF_BORDER-WIF_MENU-WIF_CTRLS;
|
|
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 (f>0) {
|
|
st=ListEntryPt(note,org_note_list);
|
|
org_play_f=f;
|
|
} else {
|
|
if (f<0)
|
|
st="R";
|
|
else
|
|
st="";
|
|
org_play_f=0;
|
|
}
|
|
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*(evt_time-note_down_time));
|
|
OrgSetWidth(tempo);
|
|
QueIns(tempo,oc.cur_note->last);
|
|
}
|
|
if (f) {
|
|
note_down_time=tP;
|
|
tempo=CAlloc(sizeof(OrgNote));
|
|
tempo->type=OT_NOTE;
|
|
tempo->note=note;
|
|
tempo->octave=octave;
|
|
tempo->accent=0;
|
|
tempo->waveform=org_waveform;
|
|
if (st[1]=='#')
|
|
Bts(&tempo->flags,Of_SHARP);
|
|
}
|
|
}
|
|
last_f=f;
|
|
"" st;
|
|
col+=StrLen(st);
|
|
if (col>=Fs->win_width-1) {
|
|
NewLine;
|
|
col=0;
|
|
}
|
|
}
|
|
} while (ch!=CH_ESC && ch!=CH_SHIFT_ESC);
|
|
} catch
|
|
CatchAll;
|
|
OrgPopMode;
|
|
OrgSongDel(&oc.root);
|
|
OrgSongDel(&oc.clipboard);
|
|
TempoDel(c);
|
|
Kill(play_task);
|
|
DCFill;
|
|
DCDel(oc.dc2);
|
|
SettingsPop;
|
|
if (DocCur) DocCur->flags=DocCur->flags&~DOCF_FORM|old_doc_flags&DOCF_FORM;
|
|
Free(dirname);
|
|
"$$CL$$\n";
|
|
MenuPop;
|
|
}
|
|
|