DIRECTORY Menus USING [MenuProc, MenuEntry, InsertMenuEntry, GetLine, SetLine, ChangeNumberOfLines], MessageWindow USING [Append, Blink], MBQueue USING [CreateMenuEntry], TiogaOps USING [GetSelection, FirstChild, ViewerDoc], TiogaOpsDefs USING [Location, Ref], ViewerClasses USING [Viewer], ViewerOps USING [FetchProp], VoiceAging USING [oldest], VoiceInText USING [ChangeMenu, thrushHandle, voiceButtonQueue], VoicePlayBack USING [CancelPlayBack, PlaySlabSection], VoiceRecord USING [StopRecording, RecordInPlaceOfSelection], VoiceRope USING [Stop, VoiceRopeInterval], VoiceViewers USING [voiceViewerMenu, VoiceViewerInfo, soundRopeCharLength, GetVoiceLock, SelectionRec, IntPair], DictationOps; DictationOpsImpl: CEDAR PROGRAM IMPORTS Menus, MessageWindow, MBQueue, TiogaOps, ViewerOps, VoiceAging, VoiceInText, VoicePlayBack, VoiceRecord, VoiceRope, VoiceViewers EXPORTS DictationOps = BEGIN DictationOps: PUBLIC Menus.MenuProc = { VoiceInText.ChangeMenu[NARROW[parent], dictationMenu] }; ToggleDictationMenu: PUBLIC PROC [viewer: ViewerClasses.Viewer] = { VoiceInText.ChangeMenu[viewer, dictationMenu] }; FindEnd: PROC [viewerInfo: VoiceViewers.VoiceViewerInfo] RETURNS [sample: INT] = { IF viewerInfo.ropeInterval.start # 0 THEN ERROR; IF ~viewerInfo.color THEN RETURN [viewerInfo.ropeInterval.length] ELSE { minAge: INT _ VoiceAging.oldest+2; endOfAge: INT _ LAST[INT]; FOR l: LIST OF VoiceViewers.IntPair _ viewerInfo.ageList, l.rest WHILE l # NIL DO IF l.first.age <= minAge THEN { endOfAge _ IF l.rest=NIL THEN LAST[INT] ELSE l.rest.first.position; minAge _ l.first.age } ENDLOOP; RETURN [IF endOfAge = LAST[INT] THEN viewerInfo.ropeInterval.length ELSE endOfAge*VoiceViewers.soundRopeCharLength] } }; PlayFromSelection: Menus.MenuProc = { viewer: ViewerClasses.Viewer; start: TiogaOpsDefs.Location; viewerInfo: VoiceViewers.VoiceViewerInfo; node: TiogaOpsDefs.Ref; from, to: INT; [viewer: viewer, start: start] _ TiogaOps.GetSelection[]; viewerInfo _ NARROW[ViewerOps.FetchProp[viewer, $voiceViewerInfo], VoiceViewers.VoiceViewerInfo]; IF viewerInfo = NIL THEN { MessageWindow.Append["Make a selection in a voice viewer first", TRUE]; MessageWindow.Blink[]; RETURN }; VoiceRope.Stop[VoiceInText.thrushHandle]; VoicePlayBack.CancelPlayBack[]; VoiceRecord.StopRecording[]; node _ TiogaOps.FirstChild[TiogaOps.ViewerDoc[viewer]]; from _ start.where; to _ FindEnd[viewerInfo]/VoiceViewers.soundRopeCharLength; IF to >= from THEN VoicePlayBack.PlaySlabSection[viewer, node, from, to] ELSE { MessageWindow.Append["Make a selection before the end of the most recent edit", TRUE]; MessageWindow.Blink[] }; }; ResumeFromSelection: Menus.MenuProc = { viewer: ViewerClasses.Viewer; start: TiogaOpsDefs.Location; viewerInfo: VoiceViewers.VoiceViewerInfo; node: TiogaOpsDefs.Ref; replaceRopeInterval: VoiceRope.VoiceRopeInterval; startDelete, endDelete: INT; [viewer: viewer, start: start] _ TiogaOps.GetSelection[]; viewerInfo _ NARROW[ViewerOps.FetchProp[viewer, $voiceViewerInfo], VoiceViewers.VoiceViewerInfo]; IF viewerInfo = NIL THEN { MessageWindow.Append["Make a selection in a voice viewer first", TRUE]; MessageWindow.Blink[]; RETURN }; VoiceRope.Stop[VoiceInText.thrushHandle]; VoicePlayBack.CancelPlayBack[]; VoiceRecord.StopRecording[]; IF ~VoiceViewers.GetVoiceLock[viewerInfo] THEN RETURN; node _ TiogaOps.FirstChild[TiogaOps.ViewerDoc[viewer]]; startDelete _ start.where*VoiceViewers.soundRopeCharLength; endDelete _ FindEnd[viewerInfo]; IF startDelete>endDelete THEN { MessageWindow.Append["Make a selection before the end of the most recent edit", TRUE]; MessageWindow.Blink[]; viewerInfo.editInProgress _ FALSE; RETURN }; replaceRopeInterval _ [ropeID: viewerInfo.ropeInterval.ropeID, start: startDelete, length: endDelete - startDelete]; VoiceRecord.RecordInPlaceOfSelection[NEW[VoiceViewers.SelectionRec _ [viewer: viewer, voiceViewerInfo: viewerInfo, ropeInterval: replaceRopeInterval, displayNode: node]]] }; ResumeFromEnd: Menus.MenuProc = { viewer: ViewerClasses.Viewer _ NARROW[parent, ViewerClasses.Viewer]; viewerInfo: VoiceViewers.VoiceViewerInfo _ NARROW[ViewerOps.FetchProp[viewer, $voiceViewerInfo], VoiceViewers.VoiceViewerInfo]; node: TiogaOpsDefs.Ref; replaceRopeInterval: VoiceRope.VoiceRopeInterval; VoiceRope.Stop[VoiceInText.thrushHandle]; VoicePlayBack.CancelPlayBack[]; VoiceRecord.StopRecording[]; IF ~VoiceViewers.GetVoiceLock[viewerInfo] THEN RETURN; node _ TiogaOps.FirstChild[TiogaOps.ViewerDoc[viewer]]; replaceRopeInterval _ [ropeID: viewerInfo.ropeInterval.ropeID, start: FindEnd[viewerInfo], length: 0]; VoiceRecord.RecordInPlaceOfSelection[NEW[VoiceViewers.SelectionRec _ [viewer: viewer, voiceViewerInfo: viewerInfo, ropeInterval: replaceRopeInterval, displayNode: node]]] }; dictationMenu: Menus.MenuEntry; Menus.InsertMenuEntry[VoiceViewers.voiceViewerMenu, MBQueue.CreateMenuEntry[VoiceInText.voiceButtonQueue, "ResumeFromEnd", ResumeFromEnd], 1]; Menus.InsertMenuEntry[VoiceViewers.voiceViewerMenu, MBQueue.CreateMenuEntry[VoiceInText.voiceButtonQueue, "ResumeFromSelection", ResumeFromSelection], 1]; Menus.InsertMenuEntry[VoiceViewers.voiceViewerMenu, MBQueue.CreateMenuEntry[VoiceInText.voiceButtonQueue, "PlayFromSelection", PlayFromSelection], 1]; dictationMenu _ Menus.GetLine[VoiceViewers.voiceViewerMenu, 1]; Menus.SetLine[VoiceViewers.voiceViewerMenu, 1, NIL]; Menus.ChangeNumberOfLines[VoiceViewers.voiceViewerMenu, 1]; END. ŒDictationOpsImpl.mesa special ops provided to support the "stop, listen, [erase,] resume" model of a dictation machine Ades, May 1, 1986 9:51:59 am PDT all of the dictation operations stand apart from the normal rules for playback/recording, which are that one must be stopped manually before the other can be requested. A playback or record request in this module implicitly cancels any already in progress. the dictation machine works differently for color and monochrome viewers: the end point for playback/resume and delete to-/record from is the end of the viewer for monochrome and the end of the youngest sound for the color the button to toggle the dictation menu on and off the screen manual version of same thing procedure to interpret 'end' for monochrome/color viewers there should be a 'real rope' in this viewer!! **** need to take the voice lock before performing the following! Κ˜™code™`K™ K™—K™K™ή—J˜šΟk œ˜ JšœœO˜ZJšœœ˜$Jšœœ˜ Jšœ œ'˜5Jšœ œ˜#Jšœœ ˜Jšœ œ ˜Jšœ˜Jšœ œ.˜?Jšœœ#˜6Jšœ œ+˜