Files
TempleOS-Rijn/Apps/Psalmody/PsalmodyFile.CPP
T
2018-09-08 21:46:22 +02:00

436 lines
9.3 KiB
C++

U0 PsmNoteDel(PsmNote *tempo)
{
Free(tempo->word);
Free(tempo);
}
PsmNote *PsmNoteCopy(PsmNote *tempo)
{
PsmNote *tempo1=MAllocIdentical(tempo);
if (tempo->word)
tempo1->word=StrNew(tempo->word);
else
tempo1->word=NULL;
return tempo1;
}
U0 PsmSongDel(PsmNote *root)
{
PsmNote *tempo,*tempo1;
tempo=root->next;
while (tempo!=root) {
tempo1=tempo->next;
PsmNoteDel(tempo);
tempo=tempo1;
}
QueInit(root);
}
U0 PsmCutToClipboard()
{
PsmNote *tempo,*tempo1;
PsmSongDel(&oc.clipboard);
tempo=oc.root.next;
while (tempo!=&oc.root) {
tempo1=tempo->next;
if (tempo->flags&PSMF_SELECTED) {
if (oc.cur_note==tempo)
oc.cur_note=tempo->next;
QueRem(tempo);
tempo->flags&=~PSMF_SELECTED;
QueIns(tempo,oc.clipboard.last);
}
tempo=tempo1;
}
}
U0 PsmPasteClipboard()
{
PsmNote *tempo,*tempo1;
tempo=oc.clipboard.next;
while (tempo!=&oc.clipboard) {
tempo1=PsmNoteCopy(tempo);
QueIns(tempo1,oc.cur_note->last);
tempo=tempo->next;
}
}
U0 PsmCopyToClipboard()
{
PsmNote *tempo,*tempo1;
PsmSongDel(&oc.clipboard);
tempo=oc.root.next;
while (tempo!=&oc.root) {
if (tempo->flags&PSMF_SELECTED) {
tempo->flags&=~PSMF_SELECTED;
tempo1=PsmNoteCopy(tempo);
QueIns(tempo1,oc.clipboard.last);
}
tempo=tempo->next;
}
}
PsmNote *PsmFindNote(I64 x,I64)
{
PsmNote *tempo=oc.root.next;
PsmRecalcNoteXY;
x+=PSM_NOTE_SPACING/2;
while (x>tempo->next->x && tempo!=&oc.root)
tempo=tempo->next;
return tempo;
}
U8 *PsmMusicSetOctave(U8 *st,I64 *psm_octave)
{
while ('0'<=*st<='9')
*psm_octave=*st++ -'0';
return st;
}
U8 *PsmMusicSetNoteLen(U8 *st,F64 *psm_duration)
{
Bool cont=TRUE;
do {
switch (*st++) {
case 'w': *psm_duration=4.0; break;
case 'h': *psm_duration=2.0; break;
case 'q': *psm_duration=1.0; break;
case 'e': *psm_duration=0.5; break;
case 's': *psm_duration=0.25; break;
case 't': *psm_duration=2.0* *psm_duration/3.0; break;
case '.': *psm_duration=1.5* *psm_duration; break;
default:
st--;
cont=FALSE;
}
} while (cont);
return st;
}
U0 PsmLoadSongStr(U8 *st,I64 *psm_octave,F64 *psm_duration)
{
PsmNote *tempo,*tempo1;
I64 note,i=0;
while (*st) {
tempo=CAlloc(sizeof(PsmNote));
while (*st && !('A'<=*st<='G') && *st!='R') {
if (*st=='M') {
tempo1=CAlloc(sizeof(PsmNote));
tempo1->type=PSMT_METER;
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;
PsmSetWidth(tempo1);
QueIns(tempo1,oc.root.last);
}
while (*st=='(') {
Bts(&tempo->flags,PSMf_TIE);
st++;
}
st=PsmMusicSetOctave(st,psm_octave);
st=PsmMusicSetNoteLen(st,psm_duration);
}
if (!*st) {
PsmNoteDel(tempo);
break;
}
note=*st++-'A';
if (note<7) {
note=music.note_map[note];
if (*st=='b') {
Bts(&tempo->flags,PSMf_FLAT);
note--;
st++;
} else if (*st=='#') {
Bts(&tempo->flags,PSMf_SHARP);
note++;
st++;
}
if (note<0) {
note=11;
*psm_octave-=1;
} else if (note>11) {
note=0;
*psm_octave+=1;
}
tempo->note=note;
tempo->octave=*psm_octave;
} else {
tempo->note=NOTE_REST;
tempo->octave=OCTAVE_REST;
}
if (*psm_duration<=2*.25/3)
i=0;
else if (*psm_duration<=.25)
i=1;
else if (*psm_duration<=2*.5/3)
i=2;
else if (*psm_duration<=.5)
i=3;
else if (*psm_duration<=2.0/3)
i=4;
else if (*psm_duration<=.5*1.5)
i=5;
else if (*psm_duration<=1.0)
i=6;
else if (*psm_duration<=1.5)
i=7;
else if (*psm_duration<=2.0)
i=8;
else if (*psm_duration<=3.0)
i=9;
else if (*psm_duration<=4.0)
i=10;
else
i=11;
tempo->duration=i;
tempo->type=PSMT_NOTE;
PsmSetWidth(tempo);
QueIns(tempo,oc.cur_note->last);
}
}
U0 PsmLoadSong(U8 *filename,I64 *psm_octave,F64 *psm_duration)
{
U8 *st;
PsmNote *tempo;
CCmpCtrl *cc=CmpCtrlNew(MStrPrint("#include \"%s\"",filename));
if (FileOcc("incomplete",filename,""))
oc.incomplete_entry->checked=TRUE;
else
oc.incomplete_entry->checked=FALSE;
while (Lex(cc)) {
if (cc->token==TK_IDENT)
if (!StrCmp(cc->cur_str,"Play")) {
if (Lex(cc)=='(')
if (Lex(cc)==TK_STR) {
tempo=oc.root.last;
st=LexExtStr(cc);
PsmLoadSongStr(st,psm_octave,psm_duration);
if (cc->token==',') {
if (Lex(cc)==TK_STR) {
st=LexExtStr(cc);
do {
do tempo=tempo->next;
while (tempo!=&oc.root && tempo->type==PSMT_METER);
if (tempo!=&oc.root)
tempo->word=StrNew(st);
st+=StrLen(st)+1;
} while (*st);
}
}
}
} else if (!StrCmp(cc->cur_str,"music") &&
Lex(cc)=='.' && Lex(cc)==TK_IDENT) {
if (!StrCmp(cc->cur_str,"tempo")) {
if (Lex(cc)=='=' && Lex(cc)==TK_F64) {
music.tempo=cc->cur_f64-0.0005;
tempo_state.tempo=Round(TEMPO_RANGE*(music.tempo-0.5)/4.4);
}
} else if (!StrCmp(cc->cur_str,"stacatto_factor")) {
if (Lex(cc)=='=' && Lex(cc)==TK_F64) {
music.stacatto_factor=cc->cur_f64-0.0005;
tempo_state.stacatto=
Round(TEMPO_RANGE*(music.stacatto_factor-0.12)/0.88);
}
}
}
}
CmpCtrlDel(cc);
}
U8 *PsmCvtSong()
{
PsmNote *tempo;
U8 *st,*src,*dst;
I64 i,note,octave,last_octave,last_duration;
i=0;
tempo=oc.root.next;
last_octave=OCTAVE_REST;
last_duration=-1;
while (tempo!=&oc.root) {
dst=&tempo->ascii;
if (tempo->type==PSMT_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,PSMf_SHARP))
note--;
if (Bt(&tempo->flags,PSMf_FLAT))
note++;
if (note<0) {
note=11;
octave--;
} else if (note>11) {
note=0;
octave++;
}
note=music.note_map[*LstSub(note,psm_note_lst)-'A'];
}
if (Bt(&tempo->flags,PSMf_TIE))
*dst++='(';
if (octave!=last_octave && note!=NOTE_REST) {
*dst++=octave+'0';
last_octave=octave;
}
if (tempo->duration!=last_duration) {
src=LstSub(tempo->duration,psm_duration_lst);
*dst++=src[0];
if (src[1])
*dst++=src[1];
last_duration=tempo->duration;
}
if (note!=NOTE_REST) {
src=LstSub(note,psm_note_lst);
*dst++=src[0];
if (src[1])
*dst++=src[1];
else if (Bt(&tempo->flags,PSMf_FLAT))
*dst++='b';
else if (Bt(&tempo->flags,PSMf_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 *PsmSaveSong(U8 *dirname,U8 *full_filename)
{
CDoc *doc=DocNew(full_filename);
Bool has_words;
PsmNote *tempo,*tempo1;
F64 measure_len=4,two_measure_left=2*measure_len;
I64 ch;
U8 *ptr;
Free(PsmCvtSong); //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 (PsmHasWords(tempo->word)) has_words=TRUE;
tempo=tempo->next;
}
if (oc.incomplete_entry->checked)
DocPrint(doc,"//0 incomplete\n");
else if (has_words)
DocPrint(doc,"//0 has words\n");
else
DocPrint(doc,"//0 no nothing\n");
DocPrint(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) {
DocPrint(doc,"%s",tempo->ascii);
if (PsmHasWords(tempo->word)) has_words=TRUE;
if (tempo->type==PSMT_METER) {
measure_len=tempo->meter_top*4.0/tempo->meter_bottom;
two_measure_left=0;
} else
two_measure_left-=psm_durations[tempo->duration];
tempo=tempo->next;
if (two_measure_left<0.001 && tempo!=&oc.root) {
if (has_words) {
DocPrint(doc,"\",\n\t\t\"");
while (tempo1!=tempo) {
if (tempo1->type!=PSMT_METER) {
if (ptr=tempo1->word) {
while (ch=*ptr) {
if (ch==CH_SPACE)
*ptr=CH_SHIFT_SPACE;
ptr++;
}
DocPrint(doc,"%Q\\0",tempo1->word);
} else
DocPrint(doc,"%c\\0",CH_SHIFT_SPACE);
}
tempo1=tempo1->next;
}
}
DocPrint(doc,"\");\n"
"\tPlay(\"");
two_measure_left=2*measure_len;
tempo1=tempo;
has_words=FALSE;
}
}
if (has_words) {
DocPrint(doc,"\",\n\t\t\"");
while (tempo1!=tempo) {
if (tempo1->type!=PSMT_METER) {
if (ptr=tempo1->word) {
while (ch=*ptr) {
if (ch==CH_SPACE)
*ptr=CH_SHIFT_SPACE;
ptr++;
}
DocPrint(doc,"%Q\\0",tempo1->word);
} else
DocPrint(doc,"%c\\0",CH_SHIFT_SPACE);
}
tempo1=tempo1->next;
}
}
DocPrint(doc,"\");\n"
" }\n"
" } catch\n"
" PutExcept;\n"
" Snd(0);\n"
"}\n"
"\n"
"Song;\n");
DocRecalc(doc);
if (full_filename)
Free(full_filename);
else
StrPrint(doc->filename.name,"%s/Temp.CPP.Z",dirname);
DocWrite(doc,TRUE);
full_filename=StrNew(doc->filename.name);
DocDel(doc);
return full_filename;
}