<> <> <> <<>> DIRECTORY FinchRecording USING [DescribeInterval, InitializeFinchRecording, PlaybackTune, RecordTune, StopTune], FinchSmarts USING [FinchIsRunning], Intervoice, LoganBerry USING [ Entry ], Rope USING [Cat, ROPE], Thrush USING [ ConversationID, EncryptionKey, NB, nullConvID ], UserProfile USING [ Token ], VoiceDB USING [ Create, Error, ErrorCode, Forget, Open, Query, Retain, VoiceDBHandle ], -- Need to do failure analysis throughout, here and in db impl VoiceTemp USING [ IntervalSpec, IntervalSpecs, TuneID ], VoiceUtils USING [ Problem, RnameToRspec ] ; RecordPlayImpl: CEDAR MONITOR IMPORTS FinchRecording, FinchSmarts, Rope, UserProfile, VoiceDB, VoiceUtils EXPORTS Intervoice = { <> <<>> Handle: TYPE = REF HandleRec; HandleRec: PUBLIC TYPE = RECORD [ -- Concrete implementation of Intervoice.Handle convID: Thrush.ConversationID _ Thrush.nullConvID, -- conv hint vdbHandle: VoiceDB.VoiceDBHandle, Complain: PROC[complaint: Rope.ROPE] ]; defaultHandle: Handle_NIL; <> <<>> Record: PUBLIC PROC[handle: Handle] RETURNS [voiceFileID: Rope.ROPE] = { ENABLE VoiceDB.Error => { handle.Complain[explanation]; CONTINUE; }; <> intervalSpec: VoiceTemp.IntervalSpec; intervalSpecs: VoiceTemp.IntervalSpecs; key: Thrush.EncryptionKey; nb: Thrush.NB; handle _ ValidateHandle[handle]; IF ~StartFinch[handle] THEN RETURN; Play[handle: handle, refID: "BeepTune", refIDType: "SysNoises", failOK: TRUE]; [nb, intervalSpec, key, handle.convID] _ FinchRecording.RecordTune[convID: handle.convID, queueIt: TRUE]; IF nb#$success THEN RETURN; intervalSpecs _ FinchRecording.DescribeInterval[intervalSpec].intervals; IF intervalSpecs#NIL THEN { intervalSpec _ intervalSpecs.first; FOR is: VoiceTemp.IntervalSpecs _ intervalSpecs, is.rest WHILE is#NIL DO IF is.rest=NIL THEN intervalSpec.length _ (is.first.start+is.first.length) - intervalSpec.start; ENDLOOP; }; voiceFileID _ VoiceDB.Create[ handle: handle.vdbHandle, tuneID: intervalSpec.tuneID, start: intervalSpec.start, length: intervalSpec.length, key: key].voiceFileID; }; Play: PUBLIC PROC[ handle: Handle, refID: Rope.ROPE_NIL, refIDType: Rope.ROPE_NIL, voiceFileID: Rope.ROPE_NIL, queueIt: BOOL_TRUE, failOK: BOOL_FALSE, wait: BOOL_FALSE ] = { <<In the refID case, multiple voiceID's are possible>> ENABLE VoiceDB.Error => { handle.Complain[explanation]; CONTINUE; }; intervalSpec: VoiceTemp.IntervalSpec; key: Thrush.EncryptionKey; ent: LoganBerry.Entry; handle _ ValidateHandle[handle]; IF ~StartFinch[handle] THEN RETURN; [intervalSpec, key, ent, ] _ VoiceDB.Query[handle.vdbHandle, voiceFileID, refID, refIDType]; IF ent=NIL THEN RETURN; -- Better to complain, first handle.convID_FinchRecording.PlaybackTune[ convID: handle.convID, intervalSpec: intervalSpec, key: key, queueIt: queueIt, failOK: failOK].newConvID; }; Stop: PUBLIC PROC[handle: Handle] = { <> ENABLE UNWIND => NULL; handle _ ValidateHandle[handle]; IF ~StartFinch[handle, FALSE] THEN RETURN; FinchRecording.StopTune[handle.convID]; }; <> <<>> 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]; }; <<>> <> Open: PUBLIC PROC[ tunesDBName: Rope.ROPE _ NIL, tunesDBInstance: Rope.ROPE _ NIL, localName: Rope.ROPE _ NIL, 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: BOOL_TRUE] RETURNS [on: BOOL] = { <> <> RW: PROC[c: Rope.ROPE] = { IF ~complain THEN RETURN; handle.Complain[complaint: c]; }; SELECT (on _ FinchSmarts.FinchIsRunning[]) FROM FALSE => RW["Sorry, Finch needs to be connected to telephone server.\nUse \"Finch\" command.\n"]; TRUE => FinchRecording.InitializeFinchRecording[]; ENDCASE; }; ValidateHandle: PROC[oldHandle: Handle] RETURNS [handle: Handle] = { handle _ oldHandle; IF handle=NIL THEN handle _ defaultHandle; IF handle=NIL THEN handle _ defaultHandle _ Open[]; }; }. <> <> <> <> <> <> <<>> <<>>