<> <> <> <> DIRECTORY IO, Commander USING [ CommandProc, Register ], Convert USING [ RopeFromInt ], Lark USING [ bStar, bThorp, ConnectionSpec, CommandEvent, CommandEvents, CommandEventSequence, Device, disabled, EchoParameters, EchoParameterRecord, enabled, endNum, Event, KeyTable, Milliseconds, o3i1, o2i2, o1i1, Passel, reset, SHHH, StatusEvent, Tone, ToneSpec, ToneSpecRec ], LarkPlay USING [ ToneList, ToneSpec, ToneSpecRec ], LarkRpcControl, LarkSmarts, List USING [ Nconc1 ], Log USING [ ProblemFR, Report ], Nice, Process USING [ Detach, EnableAborts, MsecToTicks, SetTimeout ], Rope USING [ Cat, Concat, Fetch, FromChar, Length, ROPE, Substr, Translate, TranslatorType ], RPC USING [ CallFailed ], ThNet USING [ pd ], ThPartyPrivate USING [ SmartsData ], Thrush USING[ H, pERROR, ProseSpec, ProseSpecs, ROPE, SHHH, SmartsHandle, ThHandle ], ThSmartsPrivate USING [ ConvDesc, flushMarker, GetConvDesc, HookState, proseFailure, indexMarkerEnd, LarkInfo, LarkProseQueue, LarkState, LarkStateSpec, LSwitches, LState, maxClientMarker, maxControlMarker, ProgressTones, ProseCmd, SmartsInfo, TerminalType ], TU USING [ RefAddr ] ; LarkOutImpl: CEDAR MONITOR LOCKS info USING info: LarkInfo IMPORTS Commander, Convert, IO, LarkRpcControl, List, Log, Nice, Process, Rope, RPC, ThNet, Thrush, ThSmartsPrivate, TU EXPORTS ThSmartsPrivate= { OPEN IO; <> ConvDesc: TYPE = ThSmartsPrivate.ConvDesc; H: PROC[r: REF] RETURNS[Thrush.ThHandle] = INLINE {RETURN[Thrush.H[r]]; }; LarkInfo: TYPE = ThSmartsPrivate.LarkInfo; LarkState: TYPE = ThSmartsPrivate.LarkState; SmartsData: TYPE = ThPartyPrivate.SmartsData; SmartsInfo: TYPE = ThSmartsPrivate.SmartsInfo; SmartsHandle: TYPE = Thrush.SmartsHandle; 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, sInfo: SmartsInfo, data: REF_NIL ] = { ENABLE UNWIND=>NULL; EnterLarkSt[info, newState, sInfo, data]; }; EnterLarkSt: PUBLIC INTERNAL PROC[ info: LarkInfo, newState: LarkState, sInfo: SmartsInfo, data: REF ]={ ENABLE UNWIND=>NULL; newSpec: LIST OF ThSmartsPrivate.LarkStateSpec = LIST[[newState, sInfo]]; trans: LSTrans _ lsTrans[info.larkState][newState]; oldState: LarkState = info.larkState; cDesc: ConvDesc_NIL; keyTable: Lark.KeyTable; sw: BOOL_FALSE; otherAction: REF_NIL; toneSpec: LarkPlay.ToneSpec _ NIL; newProses: Thrush.ProseSpecs _ NIL; IF pd.tonesInvalid THEN SetTones[]; <> SELECT trans FROM nop => RETURN; -- Certifiably nothing at all to do, or inappropriate time to do it. set => { info.larkState_newState; RETURN; }; X => { LarkProblem["%g: Invalid LarkState Transition", sInfo]; RETURN; }; rec => { info.larkState_recovering; LarkFailed[sInfo]; --RETURN--}; fai => { info.larkState _ failed; LarkProblem["%g: Lark failure requested by server", sInfo]; info.larkProcess _ NIL; NOTIFY info.stateChange; -- Be sure process notices failure and disappears. RETURN; }; ENDCASE; IF sInfo#NIL THEN cDesc _ ThSmartsPrivate.GetConvDesc[sInfo]; IF cDesc#NIL THEN { IF cDesc.newKeys THEN keyTable _ cDesc.cState.keyTable; IF cDesc.newSpec THEN { spec: Lark.ConnectionSpec _ info.spec _ cDesc.cState.spec; cDesc.newSpec_FALSE; info.forwardedCall _ spec#NIL AND (spec.localSocket.net # spec.remoteSocket.net OR spec.localSocket.host # spec.remoteSocket.host); }; newProses _ cDesc.newProses; }; IF tSetFwd[trans] = setFwd THEN { <> newState _ IF info.forwardedCall THEN trunkForwarding ELSE trunkTalking; trans _ lsTrans[info.larkState][newState]; }; info.larkState_newState; <> <> SELECT tDisconn[trans] FROM disconnect => { <> IF ThNet.pd.debug THEN Deb[ info, 'd ]; QueueLarkAction[info, aDisconnect, sInfo]; }; ENDCASE; <