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
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 = {
the button to toggle the dictation menu on and off the screen
VoiceInText.ChangeMenu[NARROW[parent], dictationMenu] };
ToggleDictationMenu: PUBLIC PROC [viewer: ViewerClasses.Viewer] = {
manual version of same thing
VoiceInText.ChangeMenu[viewer, dictationMenu] };
FindEnd: PROC [viewerInfo: VoiceViewers.VoiceViewerInfo] RETURNS [sample: INT] = {
procedure to interpret 'end' for monochrome/color viewers
IF viewerInfo.ropeInterval.start # 0 THEN ERROR;
there should be a 'real rope' in this viewer!!
IF ~viewerInfo.color THEN RETURN [viewerInfo.ropeInterval.length]
ELSE
{ minAge: INT ← VoiceAging.oldest+2;
endOfAge: INTLAST[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.