#define PSMR_FLAT -8 #define PSMR_SHARP -7 #define PSMR_TIE -6 #define PSMR_REST -5 #define PSMR_INS_NOTE -4 #define PSMR_DELETE_NOTE -3 #define PSMR_SET_WORD -2 F64 PopUpDuration() { I64 i; CDoc *doc=DocNew; DocPrint(doc,"$$GREEN$$$$MU,\"Set Word\",LE=PSMR_SET_WORD$$\n" "$$MU,\"Toggle Sharp\",LE=PSMR_SHARP$$\n" "$$MU,\"Toggle Flat\",LE=PSMR_FLAT$$\n" "$$MU,\"Toggle Tie\",LE=PSMR_TIE$$\n" "$$MU,\"Make Rest\",LE=PSMR_REST$$\n" "$$MU,\"Insert Note\",LE=PSMR_INS_NOTE$$\n" "$$MU,\"Delete Note\",LE=PSMR_DELETE_NOTE$$\n\n"); for (i=0;iflags; psm.cur_note=tmpn=PsmFindNote(x,y); if (tmpn!=&psm.head) { Fs->win_inhibit=WIG_USER_TASK_DFT; i=PopUpDuration; if (0<=itype==PSMT_NOTE) tmpn->duration=i; } else { switch (i) { case PSMR_REST: if (tmpn->type==PSMT_NOTE) tmpn->ona=0; break; case PSMR_SHARP: if (tmpn->type==PSMT_NOTE && tmpn->ona) { if (Btr(&tmpn->flags,PSMf_FLAT)) tmpn->ona++; if (Btc(&tmpn->flags,PSMf_SHARP)) tmpn->ona--; else tmpn->ona++; } break; case PSMR_FLAT: if (tmpn->type==PSMT_NOTE && tmpn->ona) { if (Btr(&tmpn->flags,PSMf_SHARP)) tmpn->ona--; if (Btc(&tmpn->flags,PSMf_FLAT)) tmpn->ona++; else tmpn->ona--; } break; case PSMR_TIE: if (tmpn->type==PSMT_NOTE) Btc(&tmpn->flags,PSMf_TIE); break; case PSMR_SET_WORD: if (tmpn->type==PSMT_NOTE) { if (DocPut) DocPut->flags&=~DOCF_FORM; if (PsmHasWords(tmpn->word)) st2=MStrPrint("\nWord(\"%Q\"):",tmpn->word); else st2=MStrPrint("\nWord(\"\"):"); DocBottom; st=GetStr(st2); Free(st2); Free(tmpn->word); if (*st) { tmpn->word=MStrPrint("%q",st); Free(st); } else tmpn->word=StrNew(""); if (DocPut) DocPut->flags=DocPut->flags& ~DOCF_FORM|old_doc_flags&DOCF_FORM; } break; case PSMR_INS_NOTE: tmpn1=PsmNoteCopy(tmpn); QueIns(tmpn1,tmpn); break; case PSMR_DELETE_NOTE: psm.cur_note=tmpn->next; QueRem(tmpn); PsmNoteDel(tmpn); break; } } PsmSetWidth(psm.cur_note); Fs->win_inhibit=WIG_TASK_DFT-WIF_SELF_FOCUS -WIF_SELF_BORDER-WIF_FOCUS_TASK_MENU-WIF_SELF_CTRLS; } } U0 PsmLeftClickPickNoteBox(I64 duration) { I64 o,n,msg_code,arg1,arg2; PsmNote *tmpn,*tmpn1; do { msg_code=GetMsg(&arg1,&arg2,1<psm.head.last->x) tmpn1=psm.head.last; else if (arg1x) tmpn1=&psm.head; else tmpn1=PsmFindNote(arg1-PSM_NOTE_SPACING/2,arg2); tmpn=CAlloc(sizeof(PsmNote)); tmpn->type=PSMT_NOTE; arg2=arg2/4-15; n=arg2%7; o=4+arg2/-7; if (n<0) { n+=7; o++; } n=psm_note_inverse_map[n]; if (n<3) o--; tmpn->ona=Note2Ona(n,o); tmpn->duration=duration; PsmSetWidth(tmpn); QueIns(tmpn,tmpn1); psm.cur_note=tmpn->next; } DrawDC2; } U0 PsmLeftClickPickMeterBox(I64 top,I64 bottom) { I64 msg_code,arg1,arg2; PsmNote *tmpn,*tmpn1; do { msg_code=GetMsg(&arg1,&arg2,1<=psm.head.x) tmpn1=psm.head.last; else if (arg1x) tmpn1=&psm.head; else tmpn1=PsmFindNote(arg1-PSM_NOTE_SPACING/2,arg2); tmpn=CAlloc(sizeof(PsmNote)); tmpn->type=PSMT_METER; tmpn->meter_top=top; tmpn->meter_bottom=bottom; PsmSetWidth(tmpn); QueIns(tmpn,tmpn1); psm.cur_note=tmpn->next; } DrawDC2; } U0 PsmLeftClickStaffPtr(I64 x,I64 y) { PsmNote *tmpn,*tmpn1; I64 o,n,msg_code,arg1,arg2,n_original,o_original; psm.cur_note=tmpn=PsmFindNote(x,y); if (tmpn!=&psm.head) { if (tmpn->type==PSMT_NOTE) { o_original=Ona2Octave(tmpn->ona); n_original=Ona2Note (tmpn->ona); do { msg_code=GetMsg(&arg1,&arg2,1<word); tmpn1->word=tmpn->word; tmpn->word=NULL; tmpn->ona=Note2Ona(n_original,o_original); } } else { move_note: arg2=arg2/4-15; n=arg2%7; o=4+arg2/-7; if (n<0) { n+=7; o++; } n=psm_note_inverse_map[n]; if (n<3) o--; tmpn->ona=Note2Ona(n,o); } } while (msg_code!=MSG_MS_L_UP); PsmSetWidth(tmpn); } } } U0 PsmLeftClickStaffBox(I64 x,I64 y) { I64 msg_code,arg1,arg2; do { msg_code=GetMsg(&arg1,&arg2,1<color=ROPF_DITHER+WHITE<<16+BLACK; GrBorder(psm.dc2,x,y,arg1,arg2); if (msg_code==MSG_MS_L_UP) { if (x>arg1) SwapI64(&x,&arg1); PsmMarkSel(x,arg1,TRUE); } } while (msg_code!=MSG_MS_L_UP); DrawDC2; } U0 PsmLeftClick(I64 x,I64 y) { I64 duration,top,bottom; if (y<13*FONT_HEIGHT) { if (psm.tool==PSMTT_PTR_TOOL) PsmLeftClickStaffPtr(x,y); else PsmLeftClickStaffBox(x,y); } else { duration=PsmGetPickNoteBoxDuration(x,y); if (0<=durationx<=xx+o->w && yh) { Msg(MSG_KEY_DOWN,o->ascii,0); return; } } } } U0 PsmUpKey(I64 x,I64 y) { I64 i; PsmKey *o; y-=FONT_HEIGHT*13; if (0<=yx<=xx+o->w && yh) { Msg(MSG_KEY_UP,o->ascii,0); return; } } } } U0 PsmPushMode(I64 psm_octave) { Fs->win_inhibit=WIG_TASK_DFT-WIF_SELF_FOCUS -WIF_SELF_BORDER-WIF_FOCUS_TASK_MENU-WIF_SELF_CTRLS; PsmMenu(psm_octave); } U0 PsmPopMode() { Fs->win_inhibit=WIG_USER_TASK_DFT; DCFill; } #define PSMF_CD 1 #define PSMF_INCOMPLETE 2 U0 Psalmody(U8 *dirname="~/Psalmody") { Bool was_playing,is_null=TRUE,was_null=TRUE; I64 arg1,arg2,msg_code=0,col,ona=0,last_ona=0, psm_octave=4,timeout_val,timeout_val2,old_doc_flags; U8 *filename=NULL,*st,*st2; PsmNote *tmpn; F64 psm_duration=1.0,d,evt_time=tS,note_down_time=tS; CCtrl *c=TempoNew; if (DocPut) old_doc_flags=DocPut->flags; SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$ 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 (DocPut) DocPut->flags|=DOCF_FORM; MemSet(&psm,0,sizeof(PsmCtrl)); psm.scrn_x=0; psm.head.next=psm.head.last=&psm.head; psm.clip.next=psm.clip.last=&psm.clip; psm.cur_note=&psm.head; psm.dc2=DCAlias; MenuPush( "File {" " New(,'.');" " ChgDir(MSG_CMD,PSMF_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(,'\n');" " 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,PSMF_INCOMPLETE);" "}" "Snd {" " Octave1(,'1');" " Octave2(,'2');" " Octave3(,'3');" " Octave4(,'4');" " Octave5(,'5');" " Octave6(,'6');" " Octave7(,'7');" "}" "Help {" " Help(,,SC_F1);" "}" ); psm.incomplete_entry=MenuEntryFind(Fs->cur_menu,"Song/MarkIncomplete"); psm.record_entry=MenuEntryFind(Fs->cur_menu,"Song/Record"); AutoComplete; WinBorder; WinMax; dirname=StrNew(dirname); PsmPushMode(psm_octave); col=0; Fs->draw_it=&DrawIt; try { while (TRUE) { was_playing=FALSE; mo_start: if (ms.pos_text.y-Fs->win_top<18) msg_code=GetMsg(&arg1,&arg2,1< when the Doc Bttns are clicked. //This is so that kbd and mouse are the same for Doc's. //We must now pass the onto the Doc hndlr. PutKey(arg1,arg2); goto mo_start; } if (msg_code!=MSG_MS_MOVE) { DocBottom; if (was_playing || DocPut->cur_entry->y>=Fs->win_height-2) { PsmMenu(psm_octave); col=0; } } ona=Note2Ona(3,psm_octave+1); //C is_null=TRUE; switch (msg_code) { case MSG_CMD: PsmPopMode; switch (arg1) { case PSMF_CD: st2=dirname; if (dirname=PopUpPickDir) { Free(st2); Free(filename); filename=NULL; } else dirname=st2; break; case PSMF_INCOMPLETE: psm.incomplete_entry->checked=!psm.incomplete_entry->checked; break; } PsmPushMode(psm_octave); col=0; break; case MSG_KEY_DOWN: evt_time=tS; if ('0'<=arg1<='9') { psm_octave=arg1-'0'; PsmMenu(psm_octave); col=0; } else { switch (arg1) { start: case 'a': ona-=8; break; case 's': ona-=7; break; case 'e': ona-=6; break; case 'd': ona-=5; break; case 'r': ona-=4; break; case 'f': ona-=3; break; case 't': ona-=2; break; case 'g': ona--; break; case 'h': break; case 'u': ona++; break; case 'j': ona+=2; break; case 'i': ona+=3; break; case 'k': ona+=4; break; case 'l': ona+=5; break; case 'p': ona+=6; break; case ';': ona+=7; break; case '[': ona+=8; break; case '\'': ona+=9; break; case ']': ona+=10; break; case CH_SPACE: ona=0; break; end: is_null=FALSE; break; case 0: switch (arg2.u8[0]) { case SC_CURSOR_LEFT: if (arg2&SCF_CTRL) { while (psm.cur_note->last!=&psm.head) { psm.cur_note=psm.cur_note->last; if (psm.cur_note!=&psm.head) LBEqu(&psm.cur_note->flags,PSMf_SEL,arg2&SCF_SHIFT); } } else { if (psm.cur_note->last!=&psm.head) { psm.cur_note=psm.cur_note->last; if (psm.cur_note!=&psm.head) LBEqu(&psm.cur_note->flags,PSMf_SEL,arg2&SCF_SHIFT); } } break; case SC_CURSOR_RIGHT: if (arg2&SCF_CTRL) { while (psm.cur_note!=&psm.head) { if (psm.cur_note!=&psm.head) LBEqu(&psm.cur_note->flags,PSMf_SEL,arg2&SCF_SHIFT); psm.cur_note=psm.cur_note->next; } } else { if (psm.cur_note!=&psm.head) { if (psm.cur_note!=&psm.head) LBEqu(&psm.cur_note->flags,PSMf_SEL,arg2&SCF_SHIFT); psm.cur_note=psm.cur_note->next; } } break; case SC_DELETE: if (arg2&SCF_SHIFT) PsmCutToClip; else { tmpn=psm.cur_note; psm.cur_note=tmpn->next; if (tmpn!=&psm.head) { QueRem(tmpn); PsmNoteDel(tmpn); } } break; case SC_INS: if (arg2&SCF_SHIFT) PsmPasteClip; else if (arg2&SCF_CTRL) PsmCopyToClip; break; case SC_F1: PsmPopMode; PopUpEd("::/Apps/Psalmody/Help.DD.Z",Fs); PsmPushMode(psm_octave); col=0; break; } break; case ',': Free(filename); filename=NULL; PsmPopMode; music.octave=psm_octave; if (st2=GodSongStr) { PsmLoadSongStr(st2,&psm_octave,&psm_duration); Free(st2); } PsmPushMode(psm_octave); col=0; break; case CH_CTRLO: PsmPopMode; RegOneTimePopUp(ARf_PSALMODY_JUKEBOX, "Sel a song and preview it.\n" "$$GREEN$$$$FG$$ to load it into Psalmody.\n\n" ST_WARN_ST " Graphics and other embelishments\n" "will be lost because Psalmody can't\n" "parse HolyC programs completely.\n"); Free(filename); filename=NULL; JukeBox(dirname,&filename); if (filename) { psm.scrn_x=0; psm_duration=1.0; psm_octave=4; PsmSongDel(&psm.head); psm.cur_note=&psm.head; PsmLoadSong(filename,&psm_octave,&psm_duration); psm.record_entry->checked=FALSE; psm.cur_note=psm.head.next; } PsmPushMode(psm_octave); col=0; break; case CH_CTRLA: PsmPopMode; filename=PsmSaveSong(dirname,filename); PsmPushMode(psm_octave); break; case CH_CTRLC: PsmCopyToClip; break; case CH_CTRLV: PsmPasteClip; break; case CH_CTRLX: PsmCutToClip; break; case '.': PsmMenu(psm_octave); col=0; Free(filename); filename=NULL; psm_duration=1.0; psm_octave=4; PsmSongDel(&psm.head); psm.cur_note=&psm.head; psm.scrn_x=0; break; case '\n': if (psm.cur_note!=&psm.head) PsmRightClick(psm.cur_note->x,psm.cur_note->y); break; case 'x': if (was_playing) break; col=0; psm.playing=TRUE; PsmMenu(psm_octave); tmpn=psm.cur_note; while (tmpn!=&psm.head) { if (tmpn->type!=PSMT_METER) { timeout_val=cnts.jiffies; if (ms.pos_text.y-Fs->win_top<18) msg_code=ScanMsg(&arg1,&arg2,1<win_top>=18 && msg_code==MSG_MS_L_DOWN) goto mo_start; else goto mo_got_msg; } psm.cur_note=tmpn; psm.scrn_x+=tmpn->x-0.33*GR_WIDTH; if (PsmHasWords(tmpn->word)) "%s",tmpn->word; Snd(tmpn->ona); music.tempo=4.4*tempo_state.tempo/TEMPO_RANGE+0.5; music.stacatto_factor= 0.88*tempo_state.stacatto/TEMPO_RANGE+0.12; d=JIFFY_FREQ*psm_durations[tmpn->duration]/music.tempo; if (Bt(&tmpn->flags,PSMf_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); Snd; SleepUntil(timeout_val2); } tmpn=tmpn->next; } psm.cur_note=&psm.head; psm.scrn_x+=psm.cur_note->x-GR_WIDTH/2; psm.playing=FALSE; PsmMenu(psm_octave); col=0; Snd; break; case CH_BACKSPACE: tmpn=psm.cur_note->last; if (tmpn!=&psm.head) { QueRem(tmpn); PsmNoteDel(tmpn); } if (col) { '' CH_BACKSPACE; col--; } break; case 'z': if (psm.record_entry->checked) psm.record_entry->checked=FALSE; else { psm.record_entry->checked=TRUE; psm_duration=1.0; psm_octave=4; psm.scrn_x=0; } PsmMenu(psm_octave); col=0; break; case CH_ESC: PsmPopMode; filename=PsmSaveSong(dirname,filename); PsmPushMode(psm_octave); case CH_SHIFT_ESC: goto mo_done; } } break; case MSG_KEY_UP: evt_time=tS; break; case MSG_MS_MOVE: if (arg2>18*FONT_HEIGHT) Fs->win_inhibit=WIG_USER_TASK_DFT; else Fs->win_inhibit=WIG_TASK_DFT-WIF_SELF_FOCUS-WIF_SELF_BORDER -WIF_FOCUS_TASK_MENU-WIF_SELF_CTRLS; break; case MSG_MS_L_DOWN: PsmDownKey(arg1,arg2); PsmLeftClick(arg1,arg2); break; case MSG_MS_L_UP: PsmUpKey(arg1,arg2); break; default: PsmRightClick(arg1,arg2); } if (is_null) ona=0; if (ona!=last_ona || is_null!=was_null) { if (!ona) { if (is_null) st=""; else st="R"; } else st=LstSub(Ona2Note(ona),psm_note_lst); Snd(ona); if (psm.record_entry->checked) { if (!was_null) { music.tempo=4.4*tempo_state.tempo/TEMPO_RANGE+0.5; music.stacatto_factor=0.88*tempo_state.stacatto/TEMPO_RANGE+0.12; tmpn->duration=PsmCvtDuration( music.tempo*(evt_time-note_down_time)); PsmSetWidth(tmpn); QueIns(tmpn,psm.cur_note->last); } if (!is_null) { note_down_time=tS; tmpn=CAlloc(sizeof(PsmNote)); tmpn->type=PSMT_NOTE; tmpn->ona=ona; if (st[1]=='#') Bts(&tmpn->flags,PSMf_SHARP); } } last_ona=ona; was_null=is_null; "%s",st; col+=StrLen(st); if (col>=Fs->win_width-1) { '\n'; col=0; } } } mo_done: GetMsg(,,1<flags=DocPut->flags&~DOCF_FORM|old_doc_flags&DOCF_FORM; Free(dirname); MenuPop; }