<> <> <> <> <> DIRECTORY CursorDefs, Graphics USING [DisplayChar, DisplayContext, DisplayString, Map, MoveTo, ScreenToUser, SetFont, SetPaint, SetTexture, Vec], Heuristic USING [MakeBeams, MakeChords, MakeSyncs, SetNoteValues], Interface USING [count, DeleteGraphical, Flash, MoveNote, MoveGraphical, Object, Wait], IODefs USING [ReadChar, ReadDecimal, ReadID, Rubout], MusicDefs, Piece USING [AddSync, CleanUpNotes, Delete, Insert, Merge, NearestNote, Replace], Real USING [Fix, FixI], Score USING [Draw, FileIn, FileOut, Look, Print, Redraw, SetKey, SetMetrenome, SetTimeSignature, ShowLogical, StartListening, StartPlaying, StopListening, StopPlaying, Test], Screen USING [CommandProcs, DisplayMessage, screen], Selection, -- USING everything Sheet USING [FindLine, Initialize, LineNumber, Map, NearestTime, Reset, ScreenPoint, Scroll, SetBegin, SetStyle], StreamDefs USING [GetDefaultKey, KeyboardHandle], StringDefs USING [AppendString, UpperCase], Utility, -- USING everything Voice USING [Check, Set]; InterfaceImplA: CEDAR MONITOR RETURNS[POINTER TO Screen.CommandProcs] IMPORTS Graphics, Heuristic, Interface, IODefs, MusicDefs, Piece, Real, Score, Screen, Selection, Sheet, StreamDefs, StringDefs, Utility, Voice = BEGIN OPEN Graphics, MusicDefs; keyboard: StreamDefs.KeyboardHandle; Error: SIGNAL; test: BOOL _ FALSE; commands: Screen.CommandProcs _ [Play, Listen, HandleRed, HandleYellow, HandleBlue, HandleKeyboard, Scroll, Thumb, Score.Draw, Score.FileIn, FileOut, Hardcopy, Initialize, 0]; <<******************************************************************>> <> <<******************************************************************>> Initialize: PROC[dc: Graphics.DisplayContext] = { keyboard _ StreamDefs.GetDefaultKey[]; Utility.InitStorage[]; Sheet.Initialize[dc]; }; <<******************************************************************>> <> <<******************************************************************>> HandleKeyboard: PROC = { ClearDirty[]; Do[IODefs.ReadChar[]]; IF test AND Score.Test[] THEN Error; --you may proceed, but you cannot file out }; HandleBlue: PROC = { OPEN Interface; ClearDirty[]; count _ FALSE; SELECT TRUE FROM Control[] => {HandleMenu[]; count _ FALSE}; Shift[] => {Selection.Clear[]; WHILE BlueBug[] DO Interface.MoveNote[Piece.NearestNote[]]; ENDLOOP}; ENDCASE => Interface.MoveGraphical[defaultObject]; IF test AND Score.Test[] THEN Error; --you may proceed, but you cannot file out IF count THEN commands.count _ commands.count+1; }; HandleYellow: PROC = -- used to delete objects or unselect notes { OPEN CursorDefs, Interface; temp: Cursor _ cursor^; cursor^ _ textCursor; ClearDirty[]; count _ FALSE; SELECT TRUE FROM scale>3 => ChangeLook['O]; Shift[] AND Control[] => NULL; Control[] => NULL; ENDCASE => Interface.DeleteGraphical[]; cursor^ _ temp; WHILE YellowBug[] DO NULL; ENDLOOP; IF test AND Score.Test[] THEN Error; --you may proceed, but you cannot file out IF count THEN commands.count _ commands.count+1; }; HandleRed: PROC = -- Only used to change the selection { OPEN CursorDefs; x, y: INTEGER; i, click: CARDINAL _ 0; temp: Cursor _ cursor^; cursor^ _ textCursor; ClearDirty[]; WHILE RedBug[] DO [x, y] _ Sheet.ScreenPoint[]; SELECT TRUE FROM Control[] => { FOR i IN [0..5) DO Interface.Wait[1]; IF ~RedBug[] THEN {click _ 1; EXIT}; ENDLOOP; IF click=1 THEN FOR i IN [0..5) DO Interface.Wait[1]; IF RedBug[] THEN {click _ 2; EXIT}; ENDLOOP; SELECT click FROM 0 => ChooseLine[Sheet.NearestTime[x, y].time]; 1 => EXIT; 2 => ExtendLine[]; ENDCASE => ERROR}; Shift[] => Selection.AddNote[Piece.NearestNote[x, y]]; ENDCASE => {IF command THEN Selection.Clear[]; Selection.AddNote[Piece.NearestNote[x, y]]}; command _ FALSE; ENDLOOP; cursor^ _ temp; IF test AND Score.Test[] THEN Error; --you may proceed, but you cannot file out }; ClearDirty: PROC = INLINE {min _ 100000; max _ -1}; ExtendLine: PROC = { time: Time; grey: BOOL _ FALSE; switch: BOOL _ TRUE; beginning: BOOL _ FALSE; temp1, temp2, gTemp1, gTemp2: Time; temp1 _ select1; temp2 _ select2; gTemp1 _ greySelect1; gTemp2 _ greySelect2; WHILE RedBug[] DO <> IF Shift[] AND NOT grey THEN { grey _ TRUE; switch _ TRUE; Selection.AddLine[temp1, temp2]; }; IF NOT Shift[] AND grey THEN { grey _ FALSE; switch _ TRUE; Selection.AddGreyLine[gTemp1, gTemp2]; }; [time,] _ Sheet.NearestTime[]; <> IF switch THEN IF grey THEN beginning _ Beginning[time, greySelect1, greySelect2] ELSE beginning _ Beginning[time, select1, select2]; switch _ FALSE; <> IF grey THEN IF beginning THEN Selection.AddGreyLine[time, greySelect2] ELSE Selection.AddGreyLine[greySelect1, time] ELSE IF beginning THEN Selection.AddLine[time, select2] ELSE Selection.AddLine[select1, time] ENDLOOP; }; Beginning: PROC[time, begin, end: Time] RETURNS[BOOL] = INLINE { IF time<=begin THEN RETURN[TRUE]; IF time>=end THEN RETURN[FALSE]; RETURN[ABS[time-begin]> <> <<************************************************************************>> Do: PROC[c: CHARACTER] = { a, b: INTEGER; SELECT c FROM 'b => IF lineSelect THEN Heuristic.MakeBeams[select1, select2] ELSE Selection.MakeBeam[]; 'B => Selection.ClearBeam[]; 002C=> Selection.MakeBeamOfBeams[]; 'c => IF lineSelect THEN Heuristic.MakeChords[select1, select2] ELSE Selection.MakeChord[]; 'C => Selection.ClearChord[]; 'd => Selection.Delete[]; 'e => {Selection.AddLine[0, EndOfScore[]]; RETURN}; <<'f => {ReadFileName[".logical"]; Score.FileInOld[fileName]};>> <<'F => {ReadFileName[".logical"]; Score.FileOutOld[fileName]};>> <<'g => GuessNoteValues[select1, select2];>> 'g => Selection.SetGrace[TRUE]; 'G => Selection.SetGrace[FALSE]; 007C => Heuristic.SetNoteValues[select1, select2]; 'k => Score.SetKey[select1, select2, ReadKey[]]; 'l => {ChangeLook[IODefs.ReadChar[]]; RETURN}; 014C => {Score.ShowLogical[0, scoreLength-1]; Sheet.Reset[]}; -- debugging aid 'm => Score.SetMetrenome[select1, select2, MAX[16, ReadNumbers["metrenome: CR",].a]]; 'n => {[a, b] _ ReadNumbers["n-tuplet: CR CR", TRUE]; Selection.MakeNTuplet[b, a]}; 'N => Selection.HideNTuplets[TRUE]; 016C=> {[a, b] _ ReadNumbers["n-tuplet: CR CR", TRUE]; Selection.MakeNTupletOfBeams[b, a]}; 'p => Selection.Transpose[ReadNumbers["transpose: +/- CR",].a]; 'r => IF lineSelect THEN Piece.Replace[select1, select2, greySelect1, greySelect2] ELSE Selection.SetRest[TRUE]; 'R => IF ~lineSelect THEN Selection.SetRest[FALSE] ELSE flash _ TRUE; 's => IF lineSelect THEN Heuristic.MakeSyncs[select1, select2] ELSE Selection.MakeSync[]; 'S => Selection.ClearSync[]; 't => Selection.MakeTie[]; 'T => Selection.ClearTie[]; 'x => {Voice.Check[]; RETURN}; 'v => Voice.Set[ReadDigit[]]; ' => {insertMeasure _ TRUE; RETURN}; <> '0 => Selection.SetNoteValue[unknown, 0]; '1 => Selection.SetNoteValue[whole, 0]; '! => Selection.SetNoteValue[whole, 1]; '2 => Selection.SetNoteValue[half, 0]; '@ => Selection.SetNoteValue[half, 1]; '4 => Selection.SetNoteValue[quarter, 0]; '$ => Selection.SetNoteValue[quarter, 1]; '8 => Selection.SetNoteValue[eighth, 0]; '* => Selection.SetNoteValue[eighth, 1]; '6 => Selection.SetNoteValue[sixteenth, 0]; '~ => Selection.SetNoteValue[sixteenth, 1]; '3 => Selection.SetNoteValue[thirtysecond, 0]; '# => Selection.SetNoteValue[thirtysecond, 1]; '7 => Selection.SetNoteValue[sixtyfourth, 0]; '& => Selection.SetNoteValue[sixtyfourth, 1]; '[ => Selection.SetStaff[ReadDigit[]]; '^ => Selection.SetStem[TRUE]; '_ => Selection.SetStem[FALSE]; '/ => {[a, b] _ ReadNumbers["time signature: CR CR", TRUE]; Score.SetTimeSignature[select1, select2,[a, b]]}; 033C => {Selection.Clear[]; RETURN}; ENDCASE => RETURN; command _ TRUE; IF flash THEN {Interface.Flash[]; RETURN}; commands.count _ commands.count+1; IF lineSelect AND min>max THEN Score.Redraw[select1, select2] ELSE Score.Redraw[min, max]; }; ChangeLook: PROC[c: CHARACTER] = { count: BOOL _ FALSE; repaint: BOOL _ TRUE; SELECT c FROM 'a=> Score.Look[accidental, TRUE,]; 'A=> Score.Look[accidental, FALSE,]; 'c=> Score.Look[noCarry, FALSE,]; 'C=> Score.Look[noCarry, TRUE,]; 'g=> flash _ TRUE; 'h=> Score.Look[hardcopy, TRUE,]; 'H=> Score.Look[hardcopy, FALSE,]; 'j=> {Score.Look[justified,, ReadDigit[]]; count _ TRUE}; 'l=> {Score.Look[logical,,]; count _ TRUE}; 'n=> Score.Look[notehead, TRUE,]; 'N=> Score.Look[notehead, FALSE,]; 'o=> Score.Look[overview, TRUE,]; 'O=> Score.Look[overview, FALSE,]; 'p=> {Score.Look[physical,, ReadDigit[]]; count _ TRUE}; 's=> {Score.Look[sync, TRUE,]; repaint _ FALSE}; 'S=> Score.Look[sync, FALSE,]; 'v=> Score.Look[voice, TRUE, ReadDigit[]]; 'V=> {Score.Look[voice, FALSE,]; repaint _ FALSE}; 177C=> IODefs.Rubout; ENDCASE => {Sheet.SetStyle[Digit[c], select1, select2]; count _ TRUE}; command _ TRUE; IF flash THEN {Interface.Flash[]; RETURN}; Score.Draw[repaint]; IF count THEN commands.count _ commands.count+1; }; ReadKey: PROC RETURNS[k: INTEGER] = { key, c: CHARACTER; accidental: Accidental _ inKey; CR: CHARACTER=015C; Major: BOOL _ TRUE; negative: BOOL _ FALSE; <> Screen.DisplayMessage["Please enter key name (A, Bb, C#m...) or number."]; key _ IODefs.ReadChar[]; IF key='- THEN { key _ IODefs.ReadChar[]; Screen.DisplayMessage[NIL]; RETURN[-Digit[key]]}; IF key IN ['0..'9] THEN { Screen.DisplayMessage[NIL]; RETURN[Digit[key]]}; <> key _ StringDefs.UpperCase[key]; IF key=177C THEN IODefs.Rubout; WHILE (c _ IODefs.ReadChar[])#CR DO SELECT c FROM 'm => Major _ FALSE; 'b => accidental _ flat; '# => accidental _ sharp; 177C=> IODefs.Rubout; ENDCASE; ENDLOOP; Screen.DisplayMessage[NIL]; SELECT key FROM 'C => k _ 0; 'D => k _ 2; 'E => k _ 4; 'F => k_ -1; 'G => k _ 1; 'A => k _ 3; 'B => k _ 5; ENDCASE => {Interface.Flash[]; RETURN[-100]}; IF accidental=flat THEN k _ k- 7; IF accidental=sharp THEN k_ k+ 7; IF NOT Major THEN k _ k- 3; RETURN[k]; }; ReadFileName: PROC[s: STRING] = { IODefs.ReadID[fileName !IODefs.Rubout=> RETRY]; StringDefs.AppendString[fileName, s]; RETURN; }; fileName: STRING _ [50]; ReadNumbers: PROC[s: STRING, two: BOOL _ FALSE] RETURNS[a, b: INTEGER] = { a _ b _ 0; Screen.DisplayMessage[s]; a _ IODefs.ReadDecimal[]; Screen.DisplayMessage[NIL]; IF NOT two THEN RETURN; Screen.DisplayMessage["and the second number..."]; b _ IODefs.ReadDecimal[]; Screen.DisplayMessage[NIL]; }; ReadDigit: PROC RETURNS[d: CARDINAL] = { Screen.DisplayMessage["Please enter a digit"]; d _ Digit[IODefs.ReadChar[]]; Screen.DisplayMessage[NIL]; }; Digit: PROC[c: CHARACTER] RETURNS[CARDINAL] = { SELECT c FROM '0 => RETURN[0]; '1 => RETURN[1]; '2 => RETURN[2]; '3 => RETURN[3]; '4 => RETURN[4]; '5 => RETURN[5]; '6 => RETURN[6]; '7 => RETURN[7]; '8 => RETURN[8]; '9 => RETURN[9]; <> ') => RETURN[10]; '! => RETURN[11]; '@ => RETURN[12]; '# => RETURN[13]; '$ => RETURN[14]; '% => RETURN[15]; '~ => RETURN[16]; '& => RETURN[17]; '* => RETURN[18]; '( => RETURN[19]; 033C => RETURN[TF]; -- default for justify ENDCASE => IODefs.Rubout; RETURN[0]; }; <<******************************************************************>> <> <<******************************************************************>> defaultObject: Interface.Object _ none; HandleMenu: PROC = { OPEN CursorDefs, Interface; x, y, i, j, newI, newJ: CARDINAL _ 0; x _ CursorX^; y _ CursorY^; DisplayMenu[x+4, y+4]; CursorGetsMenu[0, 0]; WHILE BlueBug[] DO newI _ (CursorX^-x)/16; newJ _ (CursorY^-y+8)/16; IF i=newI AND j=newJ THEN LOOP; i _ newI; j _ newJ; CursorGetsMenu[i, j]; ENDLOOP; DisplayMenu[x+4, y+4]; SELECT j FROM 0 => SELECT i FROM 0 => defaultObject _ note; 1 => defaultObject _ rest; 2 => defaultObject _ staves; 3 => defaultObject _ measure; 4 => defaultObject _ doubleMeasure; 5 => defaultObject _ repeat1; 6 => defaultObject _ repeat2; 7 => defaultObject _ endMeasure; 8 => defaultObject _ treble; 9 => defaultObject _ bass; 10=> defaultObject _ octava; ENDCASE => defaultObject _ none; 1 => SELECT i FROM 0 => defaultObject _ doubleFlat; 1 => defaultObject _ flat; 2 => defaultObject _ natural; 3 => defaultObject _ inKey; 4 => defaultObject _ sharp; 5 => defaultObject _ doubleSharp; 6 => defaultObject _ trill; 7 => defaultObject _ mordent1; 8 => defaultObject _ mordent2; ENDCASE => defaultObject _ none; ENDCASE => defaultObject _ none; }; CursorGetsMenu: PROC[i, j: CARDINAL] = { OPEN CursorDefs; SELECT j FROM 0 => SELECT i FROM 0 => cursor^ _ quarter; 1 => cursor^ _ rest; 2 => cursor^ _ measure; 3 => cursor^ _ measure; 4 => cursor^ _ doubleMeasure; 5 => cursor^ _ repeat1; 6 => cursor^ _ repeat2; 7 => cursor^ _ endMeasure; 8 => cursor^ _ trebleClef; 9 => cursor^ _ bassClef; 10=> cursor^ _ octava; ENDCASE => cursor^ _ textCursor; 1 => SELECT i FROM 0 => cursor^ _ doubleFlat; 1 => cursor^ _ flat; 2 => cursor^ _ natural; 3 => cursor^ _ inKey; 4 => cursor^ _ sharp; 5 => cursor^ _ doubleSharp; 6 => cursor^ _ trill; 7 => cursor^ _ mordent1; 8 => cursor^ _ mordent2; ENDCASE => cursor^ _ textCursor; ENDCASE => cursor^ _ textCursor; }; DisplayMenu: PROC[x, y: INTEGER] = { OPEN Screen; sp, p: Graphics.Vec _ [x, y]; p_ Graphics.ScreenToUser[screen, sp]; Graphics.MoveTo[screen, p]; Graphics.SetPaint[screen, invert]; Graphics.SetTexture[screen, black]; Graphics.SetFont[screen, music, 8]; Graphics.DisplayString[screen,"tzffghopRS"]; --note, rest, measures, clefs Utility.SetFont[screen, text, 12]; Graphics.DisplayChar[screen,'8]; Utility.SetFont[screen, music, 8]; p.y _ p.y-16; Graphics.MoveTo[screen, p]; Graphics.DisplayString[screen,"EFG.MOUVW"]; --accidentals, embellishments Graphics.SetFont[screen, text, 12]; }; <<******************************************************************>> <> <<******************************************************************>> Hardcopy: PROC[s: STRING]={Score.Print[splines: ~hardcopy OR BlueBug[]]}; FileOut: PROC[s: STRING]= { IF NOT Score.FileOut[s] THEN { Screen.DisplayMessage["FileOut aborted-- see mesa.typescript"]; Interface.Flash[]}; }; Play: PROC = { start: CARDINAL; IF playing THEN {Score.StopPlaying[]; RETURN}; <> start _ scoreLength; insertMeasure _ FALSE; <> IF select1> IF show.display=physical AND ~listening THEN { IF temp=NIL THEN temp _ Utility.NewPiece[]; Score.StartListening[temp]; merge _ TRUE}; <> Score.StartPlaying[score, start, show.display=physical, DisplayCursor]; IF flash THEN Interface.Flash[]; }; temp: PiecePTR _ NIL; merge: BOOL _ FALSE; Listen: PROC = { IF listening THEN { -- TURN THE LISTENER OFF Score.StopListening[]; IF temp[0]=NIL THEN RETURN; -- nothing recorded IF merge THEN Piece.Merge[select1, EndOfScore[], temp] ELSE {Piece.Delete[select1, select2]; Piece.Insert[select1, temp]}; temp _ NIL; Piece.CleanUpNotes[score]; Score.Look[voice, FALSE,]; WHILE AnyBug[] DO NULL; ENDLOOP; Score.Draw[erase: ~merge]; commands.count _ 100; -- force a backup RETURN}; <> IF temp=NIL THEN temp _ Utility.NewPiece[]; IF TF<64 THEN TF _ 256; Score.StartListening[temp]; IF flash THEN Interface.Flash[]; merge _ FALSE; }; DisplayCursor: PROC[time: Time] = { sync: SyncPTR; sp, p: Graphics.Vec; IF show.display=physical THEN time _ time/TF; IF time < begin THEN RETURN; [p.x, p.y] _ Sheet.Map[time,, 2]; p.y _ p.y+64; sp _ Graphics.Map[context, Screen.screen, p]; CursorX^ _ Real.FixI[sp.x]; CursorY^ _ MAX[808 - Real.FixI[sp.y], 0]; IF NOT insertMeasure THEN RETURN; insertMeasure _ FALSE; sync _ Utility.NewSync[]; sync.time _ time-8; sync.type _ measure; Piece.AddSync[score, sync]; Score.Redraw[time-8, time-8]; }; insertMeasure: BOOL _ FALSE; Scroll: PROC[by: INTEGER] = { time: Time; x, y: INTEGER; [x, y] _ Sheet.ScreenPoint[]; time _ Sheet.NearestTime[x, y-40].time; IF by>0 THEN Sheet.Scroll[MAX[Lines[begin, time], 1]] ELSE Sheet.Scroll[-MAX[Lines[begin, time], 1]]; Score.Draw[]; }; Thumb: PROC = { height: INTEGER _ 680; endOfScore: Time; sp, p: Graphics.Vec; oldBegin: Time=begin; endOfScore _ EndOfScore[]; SELECT scale FROM 1 => height _ height; 2 => height _ (3*height)/2; 4 => height _ 4*height; ENDCASE => ERROR; WHILE YellowBug[] DO [p.x, p.y] _ Sheet.ScreenPoint[]; IF p.x>-10 THEN RETURN; p.y _ -(height*begin)/endOfScore; sp _ Graphics.Map[context, Screen.screen, p]; Interface.Wait[1]; CursorY^ _ MAX[808 - Real.FixI[sp.y], 0]; ENDLOOP; [p.x, p.y] _ Sheet.ScreenPoint[]; begin _ (Real.Fix[top-p.y]*endOfScore)/height; begin _ MIN[begin, endOfScore-60]; begin _ MAX[begin, 0]; Sheet.SetBegin[begin]; IF begin#oldBegin THEN Score.Draw[]; }; Lines: PROC[time1, time2: Time] RETURNS[CARDINAL] = INLINE { line, topLine: INTEGER; line _ Sheet.LineNumber[Sheet.FindLine[time2]]; topLine _ Sheet.LineNumber[Sheet.FindLine[time1]]; RETURN[line-topLine]; }; RETURN[@commands]; END. Thumb: PROC = { time: Time; x, y: INTEGER; lines: INTEGER; [x, y] _ Sheet.ScreenPoint[]; time _ Sheet.NearestTime[x, y].time; lines _ Lines[begin, time]; SELECT TRUE FROM lines=0 AND x<0 => {Sheet.SetBegin[0]}; scale=1 => {Sheet.Scale[4]; Sheet.SetBegin[0]}; scale=2 => {Sheet.Scale[4]; Sheet.SetBegin[0]}; scale=4 => {Sheet.Scale[IF hardcopy THEN 2 ELSE 1]; Sheet.SetBegin[time]}; ENDCASE; Score.Draw[]; };