<> <> <> <<>> <> <> 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[]; <<**** need to take the voice lock before performing the following!>> 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.