<> <> <> <> DIRECTORY Atom USING [ DottedPair, DottedPairNode ], IO, Commander USING [ CommandProc, Register ], Lark USING [ bStar, bThorp, ConnectionSpec, ConnectionSpecRec, CommandEvent, CommandEvents, CommandEventSequence, Device, disabled, EchoParameters, EchoParameterRecord, enabled, endNum, Event, KeyTable, Milliseconds, o3i1, o2i2, o1i1, Passel, SHHH, StatusEvent, Tone, ToneSpec, ToneSpecRec, VoiceBuffer ], LarkOps USING [ LarkParameters, LarkParametersRec ], LarkPlay USING [ ToneList, ToneSpec, ToneSpecRec ], LarkRemoteControl USING [ BootLark ], LarkOpsRpcControl, LarkSmarts, MBQueue USING [ QueueClientAction ], Multicast USING [ HandleMulticast, StopHandlingMulticast ], Nice, Process USING [ Detach, EnableAborts, MsecToTicks, SetTimeout ], Pup USING [ nullSocket ], Rope USING [ Concat, Fetch, Length, ROPE ], RPC USING [ CallFailed, SetMaxTransmissions ], ThNet USING [ pd ], ThParty USING [ PartyInfo ], ThPartyPrivate USING [ SmartsData ], Thrush USING[ NetAddress, ROPE, SHHH, SmartsID ], ThSmartsPrivate USING [ ConvDesc, Deregister, FlashDone, LarkCall, LarkInfo, LarkState, LSwitches, LState, ProgressTones, SmartsInfo, SwitchState ], TU USING [ RefAddr ], VoiceUtils USING [ ProblemFR, Report, ReportFR ] ; LarkOutImpl: CEDAR MONITOR LOCKS info USING info: LarkInfo IMPORTS Commander, IO, LarkOpsRpcControl, LarkRemoteControl, MBQueue, Multicast, Nice, Process, Rope, RPC, ThNet, ThSmartsPrivate, 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; 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; TimeoutPolicy: TYPE = { never, always, unlessDebugging}; PD: TYPE = RECORD [ waitForTelco: CARDINAL _ 500, -- default values for initial pause, on time, and off time telcoMinOn: CARDINAL _ 60, -- when generating touch-tones. telcoMinOff: CARDINAL _ 60, flashWaitTime: CARDINAL _ 1200, idleWaitTime: CARDINAL _ 20000, -- time for supervisor to wait for more events. keySynchTime: CARDINAL _ 3000, -- time for keys to be distributed, else give up blinkWaitTime: CARDINAL _ 500, -- if LED is blinking, don't wait so long. backDoorOH: BOOL_FALSE, toLarkTimeoutOK: TimeoutPolicy _ unlessDebugging, <> informLarkOK: TimeoutPolicy _ unlessDebugging, <> toLarkTimeoutTransmissions: CARDINAL _ 4, -- How long to give a lark to respond fromLarkTimeoutOK: TimeoutPolicy _ unlessDebugging, <> fromLarkTimeoutTransmissions: CARDINAL _ 5, -- how long to give the server. larkEventTimer: CARDINAL _ 6000, larkTimeoutEvents: TimeoutPolicy _ unlessDebugging, tonesInvalid: BOOL_TRUE, noisyFeeps: BOOL_FALSE -- TRUE if caller is to hear automatically-generated touchtones. ]; 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]]]]; <> EnterLarkState: PUBLIC ENTRY PROC[ info: LarkInfo, newState: LarkState, data: LIST OF REF ANY_NIL ] = { ENABLE UNWIND=>NULL; EnterLarkSt[info, newState, data]; }; EnterLarkSt: PUBLIC INTERNAL PROC[ info: LarkInfo, newState: LarkState, data: LIST OF REF ANY ] = { trans: LSTrans _ lsTrans[info.larkState][newState]; oldState: LarkState = info.larkState; sw: BOOL_FALSE; otherAction: REF_NIL; connectionSpec: ThParty.PartyInfo; toneSpec: LarkPlay.ToneSpec; ropeSpec: Rope.ROPE; keyTable: Lark.KeyTable; feepSpecs: REF AFeepType_NIL; keyTablesToDate: INT; larkCall: ThSmartsPrivate.LarkCall _ NIL; -- See ThSmartsPrivate.LarkCall IF info.failed THEN { FailInt[info, "Additional requests disregarded", FALSE]; RETURN; }; IF pd.tonesInvalid THEN SetTones[]; FOR dL: LIST OF REF ANY_data, dL.rest WHILE dL#NIL DO WITH dL.first SELECT FROM cS: ThParty.PartyInfo => connectionSpec _ cS; tS: LarkPlay.ToneSpec => toneSpec _ tS; kT: Lark.KeyTable => keyTable _ kT; lC: ThSmartsPrivate.LarkCall => larkCall _ lC; -- see ThSmartsPrivate.LarkCall dP: Atom.DottedPair => SELECT dP.key FROM $audioSource => {info.audioSource _ NARROW[dP.val]; sw_TRUE; }; $transmitOnly => {info.transmitOnly _ dP.val=$true;sw_TRUE; }; $textToSpeech => info.textToSpeech _ dP.val=$true; $phoneNumber => ropeSpec _ NARROW[dP.val]; ENDCASE; -- unknown ENDCASE; -- unknown ENDLOOP; IF connectionSpec # NIL AND info.forwardedCall THEN TRUSTED { IF info.blinkProcess=NIL THEN Process.Detach[info.blinkProcess _ FORK BlinkLED[info]]; }; <> <> SELECT trans FROM nop => NULL; -- Certifiably nothing at all to do, unless there's data or some submode has changed. set => { info.larkState_newState; RETURN; }; X => {info.audioSource _ NIL; info.transmitOnly _ FALSE; FailInt[info, "Invalid LarkState Transition", TRUE]; RETURN;}; zap, zpu, zpn => { info.audioSource _ NIL; info.transmitOnly _ FALSE; }; ENDCASE; IF tClrFwd[trans] = clrFwd THEN info.forwardedCall _ FALSE; 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 THEN { <> IF ThNet.pd.debug THEN Deb[ info, "Rq disconnect" ]; QueueLarkAction[info, aDisconnect]; }; <