VoiceViewers.mesa
interface to routines to create and delete voice viewers, data structures used in editing them and a monitor routine for locking a viewer against simultaneous attempts to manipulate it
Ades, April 29, 1986 5:10:08 pm PDT
DIRECTORY
Menus USING [Menu],
Rope USING [ROPE],
Jukebox USING [bytesPerChirp],
ViewerClasses USING [Viewer],
ViewerEvents USING [EventRegistration],
VoiceRope USING [VoiceRopeInterval],
TiogaOpsDefs USING [Ref, Location];
VoiceViewers: CEDAR DEFINITIONS = BEGIN
VoiceViewerInfo: TYPE = REF VoiceViewerInfoRec;
VoiceViewerInfoRec:
TYPE =
RECORD [
-- the data structure underpinning all voice viewers
viewer: ViewerClasses.Viewer,
viewerNumber: INT,
ropeInterval: VoiceRopeInterval, -- the rope interval represented by the viewer
soundList: SoundList, -- a list of the sound/silence intervals in that rope interval
remnant: INT, -- the display shows the rope interval using characters representing a fixed amount of time: this is samplesInRope MOD lengthOfACharacterInSamples
charMarkList: LIST OF INT ← NIL, -- an ordered list of the characters which have character marks on them
textMarkList: LIST OF TextMarkEntry ← NIL, -- see below: list is again ordered
ageList: LIST OF IntPair ← NIL, -- see below: each age lasts until the next element in the list, otherwise until the end of the viewer
color: BOOLEAN ← FALSE, -- is the viewer currently on the color display?
edited: BOOLEAN ← FALSE, -- the true indication whether the voice has been edited: at times may not agree with the viewer's 'edited' flags
editInProgress: BOOLEAN ← TRUE, -- set if an initiated edit has yet to complete: this includes all cut/paste operations; input to the viewer; alteration of markers and redrawing operations, since none of these is allowed to occur simultaneously in this implementation. It is created TRUE and only set FALSE once the viewer's contents are valid
destroyEvent: ViewerEvents.EventRegistration,
changeColumnEvent: ViewerEvents.EventRegistration,
parentViewer: ViewerClasses.Viewer ← NIL, -- trace of where the SourceMarker for the viewer is, NIL if no parent
positionInParent: TiogaOpsDefs.Location, -- ditto: invalid if parentViewer = NIL
nextInfoRec: VoiceViewerInfo ← NIL
];
textual markers are held as a list of the following elements as part of the VoiceViewerInfo; see VoiceMarkersImpl and TextInVoiceImpl for more details
TextMarkEntry: TYPE = REF TextMarkRec;
TextMarkRec:
TYPE =
RECORD [
position: INT, -- the number of the character to which the text is attached
text: Rope.ROPE, -- the text itself
displayChars: INT, -- how much of the text can be displayed [without running into the next TextMarkEntry], in characters
width: INT -- how much space this display will take, measured in voice character widths
];
aging markers in VoiceViewerInfo are held as a list the following records
IntPair:
TYPE =
RECORD [
position: INT,
age: INT
];
these constants define how a voice rope maps onto a graphical representation [in fact a rope of characters in special font, each character consisting of a series of black or white vertical stripes]
soundRopeCharsPerSecond: NAT = 4;
soundRopeCharLength: NAT = Jukebox.bytesPerChirp/soundRopeCharsPerSecond;
Jukebox.BytesPerChirp is the measure of voice samples per second
soundRopeCharDivisions: NAT = 4; -- number of stripes per character;
soundRopeResolution: NAT = soundRopeCharLength/soundRopeCharDivisions;
voiceViewerMenu: Menus.Menu;
the menu for all voice viewers
voiceViewerInfoList: VoiceViewers.VoiceViewerInfo;
the list of all currently existing voice edit windows
------------------------------------
data structures used in editing voice
VoiceRopeInterval: TYPE = VoiceRope.VoiceRopeInterval; -- RECORD [ropeID: Rope.ROPE, start: INT, length: INT]
Selection: TYPE = REF SelectionRec;
SelectionRec: TYPE = RECORD -- specification of where to insert voice into a slab: if ropeInterval.length # nil then selection is to be deleted first
[ viewer: ViewerClasses.Viewer,
voiceViewerInfo: VoiceViewers.VoiceViewerInfo,
ropeInterval: VoiceRopeInterval,
displayNode: TiogaOpsDefs.Ref
];
the purpose of the next data object is to keep track of voice which is to be moved to some part of some slab - both a VoiceRopeInterval and a cache of the SoundList, charMarkList and textMarkList which correspond to it
SoundInterval: TYPE = REF SoundIntervalRec;
SoundIntervalRec: TYPE = RECORD
[ ropeInterval: VoiceRopeInterval,
soundList: SoundList ← NIL,
charMarkList: LIST OF INT ← NIL,
textMarkList: LIST OF TextMarkEntry ← NIL
];
SoundList: TYPE = LIST OF Sound;
Sound:
TYPE =
RECORD
[ silence:
INT,
-- a Sound element simply consists of a length of silence
sound: INT -- followed by a length of sound - either may legally be zero
];
------------------------------------
routines to create and delete voice viewers
BuildVoiceViewer: PROC [voiceID: Rope.ROPE, textInVoice: Rope.ROPE, youngVoice: BOOLEAN] RETURNS [viewer: ViewerClasses.Viewer, viewerInfo: VoiceViewerInfo, viewerNumber: INT];
build a new voice viewer: if voiceID = NIL then leave it with voiceVewerInfo.editInProgress TRUE [used when opening a dictation machine viewer], otherwise then call SetViewerContents, passing on all three parameters
SetViewerContents: PROC [viewer: ViewerClasses.Viewer, viewerInfo: VoiceViewers.VoiceViewerInfo, voiceID: Rope.ROPE, textInVoice: Rope.ROPE, youngVoice: BOOLEAN];
set the contents of the viewer to the given voiceRope [voiceID] with the given textual annotations on it [textInVoice] and then make it editable. If youngVoice then set it to youngest edit and age all other voice [see VoiceAging], otherwise create it at maximum age and do not do any aging of other voice
SetParentViewer: PROC [viewerInfo: VoiceViewerInfo, parentViewer: ViewerClasses.Viewer, positionInParent: TiogaOpsDefs.Location];
RemoveParentViewer: PROC [viewerNumber: INT];
called when the referent to the voice viewer is about to be deleted
SetVoiceViewerEditStatus: PROC [viewer: ViewerClasses.Viewer];
brings the viewer into agreement with the viewerinfo about whether the viewer has been edited
GetVoiceLock: PROC [VoiceViewerInfo] RETURNS [BOOLEAN];
this routine is a monitor to prevent more than one manipulation on a voice viewer at a time: this does NOT include playback which is separately monitored: since I haven't made the VoiceViewerInfo an opaque type, dropping a lock is the right of anybody who already holds it and thus is not monitored [belch]
END.