<> <> <> <<>> <> <<>> <> DIRECTORY Atom USING [ DottedPairNode, GetPropFromList, PutPropOnList ], Commander USING [ CommandProc, Register ], IO, Lark -- USING [ -- CommandEvents, ConnectionSpec, Event, LarkModel, Passel, StatusEvents ]--, LarkFeep, LarkFeepRpcControl USING [ ExportInterface, InterfaceRecord, InterfaceRecordObject ], LarkSmartsMonitorImpl, MBQueue USING [ Create, QueueClientAction ], Nice, Process USING [ Detach, SecondsToTicks, SetTimeout ], RefID USING [ ID, nullID, Reseal, Seal, Unseal ], Rope USING [ ROPE ], RPC USING [ EncryptionKey, ExportFailed ], ThParty USING [ Alert, ConversationInfo, CreateConversation, DescribeParty, GetConversationInfo, GetKeyTable, GetParty, PartyInfo, RegisterServiceInterface, ReportAction, SmartsInterfaceRecord ], ThPartyPrivate USING [ NewId, RegisterLocal ], Thrush USING [ ActionID, ActionReport, ConversationID, ConvEvent, Credentials, InterfaceSpec, NetAddress, PartyID, NB, noAddress, nullConvID, nullID, Reason, ROPE, SHHH, SmartsID, StateInConv ], ThSmartsPrivate USING [ ChangeState, ComputeConnection, ConvDesc, EnterLarkState, Fail, ForgetConv, GetConv, GetConvDesc, GetSIC, GetSmartsInfo, HardwareInUse, HardwareRequired, InputEventSpec, LarkInfo, LarkReportAction, LarkState, OpenConversations, QueueFeeps, SmartsInfo, SmartsInfoBody ], ThSmartsRpcControl, Triples USING [Make ], TU, VoiceUtils USING [ CmdOrToken, CurrentPasskey, MakeRName, Problem, ProblemFR, ReportFR ] ; LarkTrunkSmartsImpl: CEDAR MONITOR LOCKS root IMPORTS Atom, Commander, root: LarkSmartsMonitorImpl, IO, LarkFeepRpcControl, MBQueue, Nice, Process, RefID, RPC, ThParty, ThPartyPrivate, ThSmartsPrivate, ThSmartsRpcControl, Triples, VoiceUtils EXPORTS ThSmartsPrivate, LarkFeep --, ThSmarts via Interface record -- SHARES LarkSmartsMonitorImpl = { OPEN IO; <> ConvDesc: TYPE = ThSmartsPrivate.ConvDesc; Reseal: PROC[r: REF] RETURNS[RefID.ID] = INLINE {RETURN[RefID.Reseal[r]]; }; ROPE: TYPE = Thrush.ROPE; SHHH: TYPE = Lark.SHHH; -- Encrypts conv. if first arg to RPC PROC PartyID: TYPE = Thrush.PartyID; nullID: RefID.ID = Thrush.nullID; nullConvID: Thrush.ConversationID = Thrush.nullConvID; SmartsInfo: TYPE = ThSmartsPrivate.SmartsInfo; StateInConv: TYPE = Thrush.StateInConv; PD: TYPE = RECORD [ timeoutNoAction: INT_30, timeoutUnstableState: INT _ 5, checkConflictAtConvCreate: BOOL_FALSE, -- safer, but not as useful. doReports: BOOL_FALSE, doNice: BOOL_FALSE, reportToAll: BOOL _ TRUE ]; pd: REF PD _ NEW[PD_[]]; larkFeepSpec: Thrush.InterfaceSpec _ [interfaceName: [type: "LarkFeep"], serviceID: RefID.nullID]; larkFeepUser: ROPE; larkFeepPassword: RPC.EncryptionKey; Problem: PROC[what: ROPE, info: SmartsInfo_NIL, v1: IO.Value _ [null[]], v2: IO.Value _ [null[]]] = { VoiceUtils.ProblemFR[what, $Lark, IF info#NIL THEN info.larkInfo ELSE NIL, v1, v2]; }; <> RegisterTrunk: PUBLIC INTERNAL PROC[ hostSmartsID: Thrush.SmartsID, hostInfo: SmartsInfo, partyRname: ROPE ] RETURNS [ nb: Thrush.NB_$success, smartsID: Thrush.SmartsID_nullID ] = { ENABLE UNWIND => NULL; <> localSmarts: ThParty.SmartsInterfaceRecord; info: SmartsInfo; smarts: REF; credentials: Thrush.Credentials; exportRequired: BOOL _ larkFeepSpec.interfaceName.instance = NIL; netAddress: Thrush.NetAddress _ hostInfo.larkInfo.netAddress; feepInterface: LarkFeepRpcControl.InterfaceRecord; netAddress.socket _ ThPartyPrivate.NewId[]; localSmarts _ ThSmartsRpcControl.NewInterfaceRecord[]; localSmarts.clientStubProgress _ LarkTrunkProgress; localSmarts.clientStubSubstitution _ LarkTrunkSubstitution; localSmarts.clientStubReportAction _ ThSmartsPrivate.LarkReportAction; localSmarts.clientStubCheckIn _ LarkTrunkCheckIn; [nb, credentials] _ ThPartyPrivate.RegisterLocal [ rName: partyRname, type: $trunk, interfaceRecord: localSmarts, properties: [role: $voiceTerminal, netAddress: hostInfo.larkInfo.netAddress] ]; IF nb # $success THEN { VoiceUtils.ProblemFR[ "Can't register Lark trunk: %g -- %g",$System,NIL, rope[partyRname], atom[nb]]; RETURN; }; smarts _ RefID.Unseal[smartsID_credentials.smartsID]; IF smarts = NIL THEN ERROR; info _ NEW[ThSmartsPrivate.SmartsInfoBody _ [ smartsID: smartsID, otherSmartsID: hostSmartsID, partyType: $trunk, ParseEvent: LarkTrunkParseEvent, NoteNewStateP: NoteNewTkState, requests: MBQueue.Create[], larkInfo: hostInfo.larkInfo ]]; info.larkInfo.larkTrunkSmartsInfo _ info; Triples.Make[$SmartsData, smarts, info]; larkFeepSpec.serviceID _ smartsID; -- identify self. feepInterface _ NEW[LarkFeepRpcControl.InterfaceRecordObject]; feepInterface.clientStubFeep _ FeepOp; feepInterface.clientStubFlash _ FlashOp; larkFeepSpec.interfaceID _ RefID.Seal[feepInterface]; IF ([, larkFeepSpec] _ ThParty.RegisterServiceInterface[credentials: credentials, interfaceSpecPattern: larkFeepSpec]).nb # $success THEN GOTO CantExportFeep; IF exportRequired THEN LarkFeepRpcControl.ExportInterface[ larkFeepSpec.interfaceName, larkFeepUser, larkFeepPassword! RPC.ExportFailed => GOTO CantExportFeep] EXITS CantExportFeep => { VoiceUtils.Problem[ "Couldn't export LarkFeep from TrunkSmarts, continuing"]; RETURN;}; }; <> <> <> <> <> <> <station call) and "tones F" (station->trunk call being "answered")>> <> LarkTrunkParseEvent: ENTRY PROC[r: REF] = { -- r is the EventSpec ENABLE UNWIND=>NULL; eventSpec: ThSmartsPrivate.InputEventSpec = NARROW[r]; smartsInfo: SmartsInfo = eventSpec.smartsInfo; sEvent: Lark.StatusEvent _ eventSpec.sEvent; IF smartsInfo.failed THEN RETURN; SELECT sEvent.device FROM ringDetect => SELECT sEvent.event FROM Lark.enabled => CmdRinging[smartsInfo]; Lark.disabled => CmdStopRinging[smartsInfo]; ENDCASE => ERROR; ENDCASE; }; ringProblem: ROPE = "Problem responding to phone line ringing"; ringProblemFR: ROPE = "Problem responding to phone line ringing %g"; CmdRinging: INTERNAL PROC[info: SmartsInfo] = { partyID: PartyID; -- self calledPartyRname: ROPE; calledPartyID: PartyID; cDesc: ConvDesc; convEvent: Thrush.ConvEvent; nb: Thrush.NB; { IF ThSmartsPrivate.GetSIC[info] # $idle THEN RETURN; <> cDesc _ ThSmartsPrivate.GetConv[info, [], TRUE]; partyID _ cDesc.situation.self.partyID; -- self [nb, calledPartyRname] _ ThParty.DescribeParty[partyID: partyID, nameReq: $owner]; IF nb # $success OR calledPartyRname=NIL THEN GOTO LarkFailed; [nb, calledPartyID] _ ThParty.GetParty[partyID: partyID, rName: calledPartyRname]; SELECT nb FROM $success => NULL; $noSuchParty2 => GOTO LarkFailed; -- Trunk with no Lark is a fatal error $voiceTerminalBusy, $convStillActive => GOTO Failed; -- Can't ring in right now. ENDCASE => GOTO LarkFailed; -- None of the remaining errors are healthy [nb, convEvent] _ ThParty.CreateConversation[ credentials: cDesc.situation.self, state: $initiating, checkConflict: pd.checkConflictAtConvCreate ]; SELECT nb FROM $success => NULL; $voiceTerminalBusy => GOTO Failed; -- Temporary problem ENDCASE => GOTO LarkFailed; -- All others are fatal NoteNewTkState[cDesc, convEvent]; nb_ThParty.Alert[credentials: cDesc.situation.self, calledPartyID: calledPartyID]; <> SELECT nb FROM $success => NULL; $noSuchParty2, $voiceTerminalBusy => GOTO ZapAndFail; -- Bitch a bit and give up $noSuchSmarts, $noSuchParty, $noSuchConv => GOTO LarkFailed; ENDCASE => ERROR; -- Fatally confused. EXITS LarkFailed => { ThSmartsPrivate.ForgetConv[cDesc]; ThSmartsPrivate.Fail[info.larkInfo, ringProblem, TRUE]; }; Failed => { VoiceUtils.ReportFR[ringProblemFR, $System, NIL, atom[nb]]; ThSmartsPrivate.ForgetConv[cDesc]; }; ZapAndFail => { VoiceUtils.ProblemFR[ringProblemFR, $System, NIL, atom[nb]]; CmdStopRinging[info]; }; }}; CmdStopRinging: INTERNAL PROC[info: SmartsInfo] = { cDesc: ConvDesc=ThSmartsPrivate.GetConvDesc[info]; IF cDesc=NIL THEN RETURN; SELECT cDesc.situation.self.state FROM $initiating, $ringback => NULL; -- ringing stopped before called party answered. ENDCASE => RETURN; -- already active or something; ignore end of ringing [] _ ThSmartsPrivate.ChangeState[cDesc, $idle, $terminating]; <> }; LarkTrunkProgress: ENTRY PROC[ interface: ThSmartsRpcControl.InterfaceRecord, shh: Thrush.SHHH, convEvent: Thrush.ConvEvent ] = { ENABLE UNWIND => NULL; -- RestoreInvariant; <> convID: Thrush.ConversationID = convEvent.self.convID; info: SmartsInfo = ThSmartsPrivate.GetSmartsInfo[smartsID: convEvent.self.smartsID]; cDesc: ConvDesc; whatNeedsDoing: WhatNeedsDoing; IF info=NIL THEN { Problem["No Smarts at TrunkProgress for SmartsID %g", NIL, card[convEvent.self.smartsID]]; RETURN; }; cDesc _ ThSmartsPrivate.GetConv[ info, convEvent.self, TRUE ]; IF convEvent.self.partyID = convEvent.other.partyID THEN { -- own state changed NoteNewTkState[cDesc, convEvent]; IF ThSmartsPrivate.HardwareInUse[cDesc] THEN DoRejectCall[cDesc, convEvent]; <> RETURN; }; <> whatNeedsDoing _ whatNeedsDoingIf[cDesc.situation.self.state][convEvent.other.state]; SELECT whatNeedsDoing FROM $noop, $ntiy => NULL; -- No action is needed, or we don't know what one to take. $imp => ERROR; -- This is supposed to be impossible! $xrep => Problem["Didn't expect state change report", info]; $frgt => ThSmartsPrivate.ForgetConv[cDesc]; $invl => { Problem["Invalid state transition", info]; []_ThSmartsPrivate.ChangeState[cDesc: cDesc, state: $idle, reason: $error, comment: "System Error: Invalid state transition"]; }; $idle => { nb2: Thrush.NB; cInfo: ThParty.ConversationInfo; [nb2, cInfo] _ ThParty.GetConversationInfo[convID: convEvent.self.convID]; SELECT nb2 FROM $success => NULL; $noSuchConv => { Problem["Conversation disappeared, forget the whole thing", info]; ThSmartsPrivate.ForgetConv[cDesc]; }; ENDCASE => ERROR; IF (cInfo.numParties-cInfo.numIdle) <= 1 THEN []_ThSmartsPrivate.ChangeState[cDesc, $idle, $terminating]; }; $actv => [] _ ThSmartsPrivate.ChangeState[cDesc: cDesc, state: $active, bilateral: TRUE]; $rbak => [] _ ThSmartsPrivate.ChangeState[cDesc: cDesc, state: $ringback]; $reac => { -- we're active and the other party goes active larkInfo: ThSmartsPrivate.LarkInfo _ cDesc.info.larkInfo; SetLarkTrunkState[cDesc, larkInfo.larkState, LIST[SetupConnection[cDesc, larkInfo]]]; }; $deac => NULL; ENDCASE => ERROR; }; LarkTrunkSubstitution: ENTRY PROC[ interface: ThSmartsRpcControl.InterfaceRecord, shh: Thrush.SHHH, convEvent: Thrush.ConvEvent, oldPartyID: Thrush.PartyID, newPartyID: Thrush.PartyID ] = { ENABLE UNWIND => NULL; -- RestoreInvariant; <> info: SmartsInfo = ThSmartsPrivate.GetSmartsInfo[smartsID: convEvent.self.smartsID]; cDesc: ConvDesc; IF info=NIL THEN { Problem["No Smarts at TrunkSubstitution for SmartsID %g", NIL, card[convEvent.self.smartsID]]; RETURN; }; cDesc _ ThSmartsPrivate.GetConv[ info, convEvent.self ]; IF cDesc=NIL THEN RETURN; NoteNewTkState[cDesc, convEvent]; }; LarkTrunkCheckIn: ENTRY PROC[ interface: ThSmartsRpcControl.InterfaceRecord, shh: Thrush.SHHH, credentials: Thrush.Credentials, reason: Thrush.Reason, nextScheduledCheck: INT _ LAST[INT] ] = { ENABLE UNWIND => NULL; <> }; QdNotification: ENTRY PROC [r: REF] ~ { ENABLE UNWIND => NULL; -- RestoreInvariant; cDesc: ConvDesc = NARROW[r]; IF cDesc=NIL OR cDesc.situation.self.state # $notified THEN RETURN; [] _ ThSmartsPrivate.ChangeState[cDesc: cDesc, state: $active, bilateral: TRUE]; }; QdIdle: ENTRY PROC [r: REF] ~ { <> ENABLE UNWIND => NULL; -- RestoreInvariant; cDesc: ConvDesc = NARROW[r]; IF cDesc=NIL OR cDesc.situation.self.state = $idle THEN RETURN; [] _ ThSmartsPrivate.ChangeState[cDesc: cDesc, state: $idle, reason: $noAnswer]; }; DoRejectCall: INTERNAL PROC[cDesc: ConvDesc, convEvent: Thrush.ConvEvent] = { []_ThSmartsPrivate.ChangeState[cDesc, $idle, $busy]; }; LimitSignalling: ENTRY PROC [cDesc: ConvDesc, unstableState: StateInConv] ~ TRUSTED { <> c: CONDITION; Process.SetTimeout[@c, Process.SecondsToTicks[pd.timeoutUnstableState]]; WAIT c; SELECT cDesc.situation.self.state FROM # unstableState => RETURN; -- we made it. $initiating => NULL; -- inherently unstable $active => { nb: Thrush.NB; cInfo: ThParty.ConversationInfo; [nb, cInfo] _ ThParty.GetConversationInfo[convID: cDesc.situation.self.convID]; IF nb#$success --we got problems!-- OR cInfo.numActive>1 THEN RETURN; }; ENDCASE => RETURN; cDesc.info.requests.QueueClientAction[QdIdle, cDesc]; }; NoteNewTkState: INTERNAL PROC[cDesc: ConvDesc, convEvent: Thrush.ConvEvent] ~ { OPEN now: cDesc.situation.self; nb: Thrush.NB; larkStateData: LIST OF REF ANY_NIL; state: StateInConv _ convEvent.self.state; previousState: StateInConv = cDesc.situation.self.state; info: ThSmartsPrivate.SmartsInfo = cDesc.info; larkInfo: ThSmartsPrivate.LarkInfo = info.larkInfo; larkState: ThSmartsPrivate.LarkState _ $none; cDesc.situation _ convEvent^; IF state = previousState THEN RETURN; -- No conceivable value in acting. SELECT state FROM $notified => info.requests.QueueClientAction[QdNotification, cDesc]; $initiating => TRUSTED {Process.Detach[FORK LimitSignalling[cDesc, state]]; }; $idle => { IF larkInfo.forwardedCall THEN larkState _ $idle; ThSmartsPrivate.ForgetConv[cDesc]; }; $neverWas => ThSmartsPrivate.ForgetConv[cDesc]; $active => { phoneNumber: ROPE; connectionSpec: ThParty.PartyInfo _ SetupConnection[cDesc, larkInfo]; [nb, phoneNumber] _ ThParty.DescribeParty[partyID: now.partyID, nameReq: $address]; larkState _ IF nb # $success OR phoneNumber=NIL OR connectionSpec.conversationInfo.originator=now.partyID THEN trunkTalking ELSE trunkSignalling; larkStateData _ LIST[ connectionSpec, NEW[Atom.DottedPairNode _ [$phoneNumber, phoneNumber]]]; TRUSTED {Process.Detach[FORK LimitSignalling[cDesc, state]];}; }; ENDCASE; IF state > $idle AND cDesc.keyTable=NIL THEN { [nb, cDesc.keyTable] _ ThParty.GetKeyTable[credentials: now]; IF nb # $success THEN cDesc.keyTable_NIL; }; SetLarkTrunkState[cDesc, larkState, larkStateData]; }; SetLarkTrunkState: INTERNAL PROC[ cDesc: ConvDesc, larkState: ThSmartsPrivate.LarkState, larkStateData: LIST OF REF ANY ] = { state: StateInConv _ cDesc.situation.self.state; larkInfo: ThSmartsPrivate.LarkInfo _ cDesc.info.larkInfo; IF ThSmartsPrivate.HardwareInUse[cDesc] THEN { IF ThSmartsPrivate.HardwareRequired[cDesc] THEN Problem["Conflicting use of Lark at SetLarkTrunkState: ", cDesc.info]; RETURN; }; IF ThSmartsPrivate.HardwareRequired[cDesc] AND cDesc.keyTable#cDesc.info.larkInfo.keyTable AND cDesc.keyTable#NIL THEN larkStateData _ CONS[cDesc.keyTable, larkStateData]; IF larkState = $none THEN larkState _ cDesc.info.larkInfo.larkState; ThSmartsPrivate.EnterLarkState[cDesc.info.larkInfo, larkState, larkStateData]; }; SetupConnection: INTERNAL PROC[cDesc: ConvDesc, larkInfo: ThSmartsPrivate.LarkInfo] RETURNS[connectionSpec: ThParty.PartyInfo] = { forwardedCall: BOOL_FALSE; connectionSpec _ ThSmartsPrivate.ComputeConnection[cDesc]; IF connectionSpec=NIL THEN ERROR; forwardedCall _ connectionSpec.conversationInfo.numParties>1 AND connectionSpec[0].socket.host # connectionSpec[1].socket.host; larkInfo.forwardedCall _ forwardedCall; }; Feep: PUBLIC ENTRY PROCEDURE [ -- for local instance shhh: Thrush.SHHH, serviceID: Thrush.SmartsID, convID: Thrush.ConversationID, requestingParty: Thrush.PartyID, number: Rope.ROPE, noisy: BOOLEAN _ FALSE, on, off: CARDINAL_ 177777B] RETURNS [nb: Thrush.NB_$success] = { RETURN[FeepOp[NIL, shhh, serviceID, convID, requestingParty, number, noisy, on, off]]; }; FeepOp: INTERNAL PROCEDURE [ -- Exports to voice service interface LarkFeep interface: LarkFeepRpcControl.InterfaceRecord, shhh: Thrush.SHHH, serviceID: Thrush.SmartsID, convID: Thrush.ConversationID, requestingParty: Thrush.PartyID, number: Rope.ROPE, noisy: BOOLEAN _ FALSE, on, off: CARDINAL_ 177777B] RETURNS [nb: Thrush.NB_$success] = { info: SmartsInfo = ThSmartsPrivate.GetSmartsInfo[smartsID: serviceID]; cDesc: ConvDesc; IF info = NIL THEN RETURN[$noSuchSmarts]; cDesc _ ThSmartsPrivate.GetConv[info, [convID: convID]]; IF cDesc = NIL THEN RETURN[$notInConv]; IF cDesc.situation.self.state # $active THEN RETURN[$convNotActive]; IF noisy THEN number _ IO.PutFR["A%g", rope[number]]; IF on#177777B THEN number _ IO.PutFR["%gO%g", char[LOOPHOLE[on/10]], rope[number]]; IF off#177777B THEN number _ IO.PutFR["%gF%g", char[LOOPHOLE[off/10]], rope[number]]; ThSmartsPrivate.QueueFeeps[info, number]; }; <> <> <> <> FlashInfo: TYPE = REF FlashInfoBody; FlashInfoBody: TYPE = RECORD [ requestingPartyID: Thrush.PartyID, actionID: Thrush.ActionID ]; Flash: PUBLIC ENTRY PROCEDURE [ -- Exports to voice service interface LarkFeep shhh: Thrush.SHHH, serviceID: Thrush.SmartsID, convID: Thrush.ConversationID, requestingParty: Thrush.PartyID, actionID: Thrush.ActionID, extraTime: CARDINAL_ 177777B] RETURNS [nb: Thrush.NB_$success] = { RETURN[FlashOp[NIL, shhh, serviceID, convID, requestingParty, extraTime]]; }; FlashOp: INTERNAL PROCEDURE [ -- Exports to voice service interface LarkFeep interface: LarkFeepRpcControl.InterfaceRecord, shhh: Thrush.SHHH, serviceID: Thrush.SmartsID, convID: Thrush.ConversationID, requestingParty: Thrush.PartyID, actionID: Thrush.ActionID, extraTime: CARDINAL_ 177777B] RETURNS [nb: Thrush.NB_$success] = { info: SmartsInfo = ThSmartsPrivate.GetSmartsInfo[smartsID: serviceID]; cDesc: ConvDesc; IF info = NIL THEN RETURN[$noSuchSmarts]; cDesc _ ThSmartsPrivate.GetConv[info, [convID: convID]]; IF cDesc = NIL THEN RETURN[$notInConv]; IF cDesc.situation.self.state # $active THEN RETURN[$convNotActive]; info.larkInfo.props _ Atom.PutPropOnList[info.larkInfo.props, $FlashInfo, NEW[FlashInfoBody _ [requestingParty, actionID]]]; SetLarkTrunkState[cDesc, $trunkFlashing, NIL]; }; <> <> <> <> FlashDone: PUBLIC ENTRY PROC[r: REF] = { -- r is a LarkInfo; flashing has finished nb: Thrush.NB; info: ThSmartsPrivate.LarkInfo = NARROW[r]; smartsInfo: SmartsInfo = IF info=NIL THEN NIL ELSE info.larkTrunkSmartsInfo; cDesc: ConvDesc = ThSmartsPrivate.GetConvDesc[smartsInfo]; flashInfo: FlashInfo _ IF info=NIL THEN NIL ELSE NARROW[Atom.GetPropFromList[info.props, $FlashInfo]]; IF flashInfo=NIL OR flashInfo.actionID=0 THEN RETURN; nb _ ThParty.ReportAction[ report: [ self: cDesc.situation.self, -- placeholder other: cDesc.situation.self, requestingParty: flashInfo.requestingPartyID, actionID: flashInfo.actionID, actionClass: $switchhookFlash, actionType: $flashed ], reportToAll: FALSE ].nb; IF nb#$success THEN IF info#NIL AND ~info.failed THEN ThSmartsPrivate.Fail[info, IO.PutFR["Couldn't report switchhook flash completion -- %g", atom[nb]], TRUE] ELSE VoiceUtils.ProblemFR["Couldn't report switchhook flash completion, probably due to earlier failure -- %g", $System, NIL, atom[nb]]; }; LarkTrunkSmartsInit: Commander.CommandProc = { larkFeepSpec.interfaceName.instance _ NIL; larkFeepSpec.hostHint _ Thrush.noAddress; larkFeepUser _ VoiceUtils.MakeRName[style: rName, name: VoiceUtils.CmdOrToken[cmd: cmd, key: "ThrushServerInstance", default: "Strowger.Lark"]]; larkFeepPassword _ VoiceUtils.CurrentPasskey[VoiceUtils.CmdOrToken[ cmd: cmd, key: "ThrushServerPassword", default: "MFLFLX"]]; VoiceUtils.ReportFR["Initialize[LarkTrunkSmarts.Lark, %s]", $System, NIL, rope[larkFeepUser]]; }; WhatNeedsDoing: TYPE = ATOM; -- { <> <<$noop, $idle, $actv, $frgt, $reac, $deac, -- cases explained in code>> <<$rbak, -- enter "ringback"; stable initiating state.>> <<$invl, -- considered an invalid request>> <<$xrep, -- we got a report we feel we shouldn't have got>> <<$ntiy, -- not implemented yet>> <<$imp -- this situation should not arise even in the face of invalid requests>> <<};>> whatNeedsDoingIf: ARRAY StateInConv OF ARRAY StateInConv OF WhatNeedsDoing _ [ <> <<>> << never idle failed resrv pars init notif rback ring canAc activ inact -- _ (other)>> [ $imp, $frgt, $frgt, $frgt, $frgt, $frgt, $frgt, $frgt, $frgt, $frgt, $frgt, $frgt], --neverWas <<(Clip this table to view without these comments.)>> <> [ $imp, $noop, $frgt, $noop, $noop, $noop, $noop, $noop, $noop, $noop, $noop, $ntiy ], -- idle [ $imp, $imp, $frgt, $imp, $imp, $imp, $imp, $imp, $imp, $imp, $imp, $imp ], -- failed [ $imp, $imp, $frgt, $imp, $imp, $imp, $imp, $imp, $imp, $imp, $imp, $imp ], -- reserved <> [ $imp, $imp, $frgt, $imp, $imp, $imp, $imp, $imp, $imp, $imp, $imp, $imp ], -- parsing <> [ $imp, $idle,$frgt, $invl, $invl, $invl, $xrep, $xrep, $rbak,$actv, $actv, $actv ], -- initiating <> <> [ $imp, $idle,$frgt, $invl, $invl, $invl, $xrep, $noop, $noop, $ntiy, $noop, $ntiy ], -- notified <> [ $imp, $idle,$frgt, $invl, $invl, $invl, $xrep, $xrep, $noop,$actv, $actv, $actv ], -- ringback <> [ $imp, $idle,$frgt, $invl, $invl, $invl, $invl, $invl, $invl, $invl, $invl, $invl ], -- ringing <> [ $imp, $idle,$frgt, $invl, $invl, $invl, $xrep, $xrep, $noop, $ntiy, $noop, $ntiy ], -- canActivate [ $imp, $idle,$frgt, $invl, $invl, $invl, $xrep, $xrep, $noop, $ntiy, $reac, $deac ], -- active [ $imp, $idle,$frgt, $invl, $invl, $invl, $xrep, $xrep, $noop, $ntiy, $ntiy, $ntiy ] -- inactive (current ^) ]; <> ViewCmd: Commander.CommandProc = TRUSTED { Nice.View[pd, "Lark Trunk PD"]; }; Commander.Register["LarkTrunkSmarts", LarkTrunkSmartsInit, "LarkTrunkSmarts \nInitialize and Export LarkTrunkSmarts"]; Commander.Register["VuLarkTrunkSmarts", ViewCmd, "Program Management variables for Lark Trunk Smarts"]; }. <<>> <> < VoiceUtils, Handle => ID>> <> <> <> <> <> <> <> <> <> <> <<>> <> <> <> <<>> <> <> <> <> <> <> <<>> <<>> <<>> <> <> <> <<>>