<> <> <> <> DIRECTORY IO, Commander USING [ CommandProc, Register ], Convert USING [ RopeFromInt ], Lark USING [ bStar, bThorp, ConnectionSpec, ConnectionSpecRec, CommandEvent, CommandEvents, CommandEventSequence, Device, disabled, EchoParameters, EchoParameterRecord, enabled, endNum, Event, KeyTable, Milliseconds, o3i1, o2i2, o1i1, Passel, reset, SHHH, StatusEvent, Tone, ToneSpec, ToneSpecRec, VoiceBuffer ], LarkPlay USING [ ToneList, ToneSpec, ToneSpecRec ], LarkRpcControl, LarkSmarts, List USING [ Nconc1 ], Multicast USING [ HandleMulticast, StopHandlingMulticast ], Nice, Process USING [ Detach, EnableAborts, MsecToTicks, SetTimeout ], Rope USING [ Cat, Concat, Fetch, FromChar, Length, ROPE, Substr, Translate, TranslatorType ], RPC USING [ CallFailed ], ThNet USING [ pd ], ThParty USING [ PartyInfo ], ThPartyPrivate USING [ SmartsData ], Thrush USING[ Machine, ProseSpec, ProseSpecs, ROPE, SHHH, SmartsID ], ThSmartsPrivate USING [ ConvDesc, flushMarker, HookState, proseFailure, indexMarkerEnd, LarkInfo, LarkProseQueue, LarkState, LSwitches, LState, maxClientMarker, maxControlMarker, ProgressTones, ProseCmd, SmartsInfo, TerminalType, TrunkBundle ], TU USING [ RefAddr ], VoiceUtils USING [ ProblemFR, Report ] ; LarkOutImpl: CEDAR MONITOR LOCKS info USING info: LarkInfo IMPORTS Commander, Convert, IO, LarkRpcControl, List, Multicast, Nice, Process, Rope, RPC, ThNet, TU, VoiceUtils EXPORTS ThSmartsPrivate= { OPEN IO; <> ConvDesc: TYPE = ThSmartsPrivate.ConvDesc; LarkInfo: TYPE = ThSmartsPrivate.LarkInfo; LarkState: TYPE = ThSmartsPrivate.LarkState; SmartsData: TYPE = ThPartyPrivate.SmartsData; SmartsInfo: TYPE = ThSmartsPrivate.SmartsInfo; SmartsID: TYPE = Thrush.SmartsID; TerminalType: TYPE = ThSmartsPrivate.TerminalType; ProseCmd: TYPE = ThSmartsPrivate.ProseCmd; ROPE: TYPE = Thrush.ROPE; firstTone: LarkState = FIRST[ThSmartsPrivate.ProgressTones]; bStar: Lark.Event = Lark.bStar; bThorp: Lark.Event = Lark.bThorp; enabled: Lark.Event = Lark.enabled; endNum: Lark.Event = Lark.endNum; disabled: Lark.Event = Lark.disabled; reset: Lark.Event = Lark.reset; larkRegistry: ROPE _ ".Lark"; PD: TYPE = RECORD [ waitForTelco: CARDINAL _ 500, telcoMinOn: CARDINAL _ 60, telcoMinOff: CARDINAL _ 60, flashWaitTime: CARDINAL _ 800, idleWaitTime: CARDINAL _ 20000, -- time for supervisor to wait for more events. backDoorOH: BOOL_FALSE, callTimeoutOK: BOOL_FALSE, -- set to keep Thrush alive when debugging a Lark. tonesInvalid: BOOL_TRUE, tonesLast: BOOL_TRUE -- sets up alternate lark setup situation in supervisor loop <<<>>> ]; pd: REF PD _ NEW[PD_[]]; dialTone: LarkPlay.ToneSpec _ NIL; busyTone: LarkPlay.ToneSpec _ NIL; errorTone: LarkPlay.ToneSpec _ NIL; ringbackTone: LarkPlay.ToneSpec _ NIL; quenchSpec: Lark.ToneSpec _ NEW[Lark.ToneSpecRec _[volume: 0, totalTime: 0, tones: LIST[[0,0,0,0]]]]; <> pReset: PUBLIC ProseCmd _ "\022"; stopAndFlush: PUBLIC ProseCmd _ "\033[S"; commenceSpeech: ProseCmd = "\033[C"; -- \033 is ESC cmdLeader: ProseCmd = "\033["; -- for constructing arbitrary commands indexMarkerLen: INT = 6; <> minControlMarker: INT = 200; -- reserved for packet control <> speechDoneMarker: INT = 255; speechDone: ProseCmd = "\033[C\033[255i"; -- commence speech & report back when done <> EnterLarkState: PUBLIC ENTRY PROC[ info: LarkInfo, newState: LarkState, data: REF_NIL ] = { ENABLE UNWIND=>NULL; EnterLarkSt[info, newState, data]; }; EnterLarkSt: PUBLIC INTERNAL PROC[ info: LarkInfo, newState: LarkState, data: REF ]={ ENABLE UNWIND=>NULL; trans: LSTrans _ lsTrans[info.larkState][newState]; oldState: LarkState = info.larkState; sw: BOOL_FALSE; otherAction: REF_NIL; connectionSpec: ThParty.PartyInfo; toneSpec: LarkPlay.ToneSpec; newProses: Thrush.ProseSpecs; ropeSpec: Rope.ROPE; keyTable: Lark.KeyTable; IF pd.tonesInvalid THEN SetTones[]; IF data#NIL THEN WITH data SELECT FROM cS: ThParty.PartyInfo => connectionSpec _ cS; tS: LarkPlay.ToneSpec => toneSpec _ tS; nP: Thrush.ProseSpecs => newProses _ nP; rS: Rope.ROPE => ropeSpec _ rS; kT: Lark.KeyTable => keyTable _ info.keyTable _ kT; tB: REF ThSmartsPrivate.TrunkBundle => { -- way to pass two args. connectionSpec _ tB.spec; ropeSpec _ tB.ropeSpec; }; ENDCASE; IF connectionSpec # NIL AND connectionSpec.numParties=2 THEN info.forwardedCall _ connectionSpec[0].socket.host # connectionSpec[1].socket.host; <> <> SELECT trans FROM nop => NULL; -- Certifiably nothing at all to do, unless there's data or some submode has changed. watch out set => { info.larkState_newState; RETURN; }; X => { LarkProblem["%g: Invalid LarkState Transition", info]; RETURN; }; rec => { info.larkState_recovering; LarkFailed[info.larkSmartsInfo]; --RETURN--}; fai => { info.larkState _ failed; LarkProblem["%g: Lark failure requested by server", info]; info.larkProcess _ NIL; NOTIFY info.stateChange; -- Be sure process notices failure and disappears. RETURN; }; ENDCASE; IF tSetFwd[trans] = setFwd THEN { <> newState _ IF info.forwardedCall THEN trunkForwarding ELSE trunkTalking; trans _ lsTrans[info.larkState][newState]; }; info.larkState_newState; <> <> IF (tDisconn[trans] = $disconnect OR connectionSpec#NIL) AND info.spec#NIL THEN { <> IF ThNet.pd.debug THEN Deb[ info, 'd ]; QueueLarkAction[info, aDisconnect]; }; <