RecordPlayImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Last Edited by: Swinehart, May 19, 1986 9:38:59 am PDT
DIRECTORY
FinchSmarts USING [CurrentFinchState, FinchState, GetProcs, Procs, RecordReason],
Intervoice,
LoganBerry USING [ Entry ],
Rope USING [Cat, ROPE],
Thrush USING [ EncryptionKey, Tune, VoiceInterval ],
UserProfile USING [ Token ],
VoiceDB USING [ Create, Error, ErrorCode, Forget, Open, Query, Retain, VoiceDBHandle ], -- Need to do failure analysis throughout, here and in db impl
VoiceUtils USING [ Problem, RnameToRspec ]
;
RecordPlayImpl: CEDAR MONITOR
IMPORTS FinchSmarts, Rope, UserProfile, VoiceDB, VoiceUtils
EXPORTS Intervoice = {
Definitions
Handle: TYPE = REF HandleRec;
HandleRec: PUBLIC TYPE = RECORD [ -- Concrete implementation of Intervoice.Handle
procs: FinchSmarts.Procs←NIL,
vdbHandle: VoiceDB.VoiceDBHandle,
Complain: PROC[complaint: Rope.ROPE]
];
defaultHandle: Handle←NIL;
Intervoice Implementations for Record and Playback
Record: PUBLIC PROC[handle: Handle] RETURNS [voiceFileID: Rope.ROPE←NIL] = {
ENABLE VoiceDB.Error => { handle.Complain[explanation]; CONTINUE; };
Nothing much can be done about it; just tell the user. Should eventually log for system administrator's benefit.
interval: Thrush.VoiceInterval;
key: Thrush.EncryptionKey;
reason: FinchSmarts.RecordReason;
tune: Thrush.Tune;
handle ← ValidateHandle[handle];
IF StartFinch[handle]#running THEN RETURN;
Play[handle: handle, refID: "BeepTune", refIDType: "SysNoises", failOK: TRUE];
[reason, tune, interval, key] ← handle.procs.recordTune[queueIt: TRUE];
IF reason#ok THEN RETURN;
voiceFileID ← VoiceDB.Create[
handle: handle.vdbHandle, tune: tune, interval: interval, key: key].voiceFileID;
};
Play: PUBLIC PROC[
handle: Handle,
refID: Rope.ROPENIL, refIDType: Rope.ROPENIL, voiceFileID: Rope.ROPENIL,
queueIt: BOOLTRUE,
failOK: BOOLFALSE,
wait: BOOLFALSE
] = {
In the refID case, multiple voiceID's are possible
ENABLE VoiceDB.Error => { handle.Complain[explanation]; CONTINUE; };
tune: Thrush.Tune;
interval: Thrush.VoiceInterval;
key: Thrush.EncryptionKey;
ent: LoganBerry.Entry;
handle ← ValidateHandle[handle];
IF StartFinch[handle]#running THEN RETURN;
[tune, interval, key, ent, ] ←
VoiceDB.Query[handle.vdbHandle, voiceFileID, refID, refIDType];
IF ent=NIL THEN RETURN; -- Better to complain, first
[]←handle.procs.playbackTune[
tune: tune, interval: interval, key: key, queueIt: queueIt, failOK: failOK, wait: wait];
};
Stop: PUBLIC PROC[handle: Handle] = {
Sender and Walnut Message viewer STOP buttons
ENABLE UNWIND => NULL;
handle ← ValidateHandle[handle];
IF StartFinch[handle, FALSE]#running THEN RETURN;
handle.procs.stopTune[];
};
Intervoice Implementations that probably belong somewhere else, but in any case just relay their calls
Retain: PUBLIC PROC [
handle: Handle,
voiceFileID: Rope.ROPE,
refID: Rope.ROPE,
refIDType: Rope.ROPE
] = {
ENABLE VoiceDB.Error => { handle.Complain[explanation]; CONTINUE; };
handle ← ValidateHandle[handle];
[]←VoiceDB.Retain[handle.vdbHandle, voiceFileID, refID, refIDType];
};
Forget: PUBLIC PROC [
handle: Handle,
refID: Rope.ROPE,
refIDType: Rope.ROPE
] = {
ENABLE VoiceDB.Error => { handle.Complain[explanation]; CONTINUE; };
handle ← ValidateHandle[handle];
VoiceDB.Forget[handle.vdbHandle, refID, refIDType];
};
Initialization (Walnut Voice and Finch)
Open: PUBLIC PROC[
tunesDBName: Rope.ROPENIL,
tunesDBInstance: Rope.ROPENIL,
localName: Rope.ROPENIL,
Complain: PROC[complaint: Rope.ROPE]←NIL] RETURNS [handle: Handle] = {
server: Rope.ROPE← UserProfile.Token["ThrushClientServerInstance", "Strowger.Lark"];
vdbHandle: VoiceDB.VoiceDBHandle;
ec: VoiceDB.ErrorCode;
expl: Rope.ROPE;
IF Complain = NIL THEN Complain ← FinchProblem;
IF tunesDBInstance = NIL THEN tunesDBInstance ← server;
IF tunesDBName = NIL THEN
tunesDBName ← Rope.Cat["///", VoiceUtils.RnameToRspec[server].simpleName, "/Tunes"];
[vdbHandle, ec, expl] ← VoiceDB.Open[tunesDBName, tunesDBInstance, "Morley.Lark"];
IF ec#NIL THEN Complain[expl]; -- Trouble opening; success of future calls in doubt
handle ← NEW[HandleRec ← [vdbHandle: vdbHandle, Complain: Complain ]];
};
FinchProblem: PROC[complaint: Rope.ROPE] = { VoiceUtils.Problem[complaint, $Finch]; };
StartFinch: PROC[handle: Handle, complain: BOOLTRUE]
RETURNS [state: FinchSmarts.FinchState] = {
Should arrange to load Finch if not loaded, start it if not started.
At present, does neither, tells caller what's what, and complains if asked to.
RW: PROC[c: Rope.ROPE] = {
IF ~complain THEN RETURN;
handle.Complain[complaint: c];
};
SELECT (state ← FinchSmarts.CurrentFinchState[]) FROM
unknown => RW["Sorry, Finch needs to be loaded and started.\n"];
stopped => RW["Sorry, Finch needs to be connected to telephone server.\nUse \"Finch\" command.\n"];
running => NULL;
ENDCASE => ERROR;
handle.procs ← IF state=unknown THEN NIL ELSE FinchSmarts.GetProcs[];
};
ValidateHandle: PROC[oldHandle: Handle] RETURNS [handle: Handle] = {
handle ← oldHandle;
IF handle=NIL THEN handle ← defaultHandle;
IF handle=NIL THEN handle ← defaultHandle ← Open[];
};
}.
Swinehart, May 19, 1986 9:19:05 am PDT
Cedar 6.1
changes to: DIRECTORY, RecordPlayImpl, Open, FinchProblem