<<>> <> <> <> <> <<>> DIRECTORY IO USING [ atom, rope ], PhSmarts USING [ lock, PhoenixInfo, PhoenixInfoBody, phoenixInfo, pd, SHHH ], Process USING [ Detach, SecondsToTicks, SetTimeout ], Rope USING [ Equal, ROPE ], ThParty, ThPartySunRPControl USING [ ReportProblem, ReportState, ThrushConnect, ThrushDisconnect, ThrushReportState ], Thrush, ThSmartsSunExport USING [ ExportInterface ], UserProfile USING [ Token ], VoiceUtils USING [ CurrentRName, CurrentPasskey, OwnNetAddress, Problem, ProblemFR, Report, RopeFromSunAddr ] ; PhRegisterImpl: CEDAR MONITOR LOCKS PhSmarts.lock IMPORTS IO, PhSmarts, Process, Rope, ThParty, ThPartySunRPControl, ThSmartsSunExport, UserProfile, VoiceUtils EXPORTS PhSmarts ~ BEGIN OPEN PhSmarts; NB: TYPE = Thrush.NB; ROPE: TYPE = Rope.ROPE; uniqueSuffix: CARD ¬ 0; InitPhoenixSmarts: PUBLIC ENTRY PROC [ thrushInstance: Thrush.ROPE¬NIL ] = { ENABLE UNWIND => NULL; problem: ROPE¬NIL; nb: NB¬$serverDown; prevInfo: PhSmarts.PhoenixInfo ¬ PhSmarts.phoenixInfo; IF phoenixInfo#NIL AND phoenixInfo.connected THEN UnInitPhoenixSmartsInt[]; phoenixInfo ¬ NEW[PhSmarts.PhoenixInfoBody]; -- Dump any old one! IF prevInfo#NIL THEN NOTIFY prevInfo.pollCondition; phoenixInfo.conversations ¬ NIL; phoenixInfo.connected ¬ FALSE; thrushInstance ¬ SELECT TRUE FROM thrushInstance#NIL => thrushInstance, prevInfo#NIL AND prevInfo.prevThrushInstance#NIL => prevInfo.prevThrushInstance, ENDCASE=> UserProfile.Token["ThrushSunClientServerInstance", "Growler"]; phoenixInfo.prevThrushInstance ¬ thrushInstance; uniqueSuffix ¬ ThSmartsSunExport.ExportInterface[port: uniqueSuffix]; phoenixInfo.myName ¬ [ type: "ThSmarts.Lark", instance: VoiceUtils.RopeFromSunAddr[port: uniqueSuffix]]; phoenixInfo.myRName ¬ VoiceUtils.CurrentRName[]; phoenixInfo.myPassword ¬ VoiceUtils.CurrentPasskey[]; <> phoenixInfo.shh ¬ ThPartySunRPControl.ThrushConnect[ server: thrushInstance, rName: phoenixInfo.myRName, type: $telephone, interface: phoenixInfo.myName, properties: [role: $voiceTerminal, netAddress: VoiceUtils.OwnNetAddress[]], reportState: ReportStateFromThPartyRPC, reportProblem: ReportProblemFromThPartyRPC]; TRUSTED { Process.Detach[FORK PollWaiter[phoenixInfo]]; }; }; UnInitPhoenixSmarts: PUBLIC ENTRY PROC[disable: BOOL¬TRUE] = { ENABLE UNWIND=>NULL; UnInitPhoenixSmartsInt[disable]; }; UnInitPhoenixSmartsInt: INTERNAL PROC[disable: BOOL¬TRUE] = { shhh: PhSmarts.SHHH ¬ IF phoenixInfo#NIL THEN phoenixInfo.shh ELSE NIL; IF shhh=NIL THEN RETURN; ThPartySunRPControl.ThrushDisconnect[shhh, disable]; <<IF disable THEN ThPartySunRPControl.ReleaseConversation[shhh];>> <> }; PhoenixIsRunning: PUBLIC PROC RETURNS [phoenixIsEnabled: BOOL¬FALSE, phoenixIsRunning: BOOL¬FALSE] = { IF phoenixInfo=NIL THEN RETURN; RETURN[phoenixInfo.enabled, phoenixInfo.connected]; }; RecordSystemStateFromSmartsReport: PUBLIC INTERNAL PROC[ nb: NB, remark: Rope.ROPE, connected: BOOL, enabled: BOOL, voicePath: BOOL, remoteRemark: Rope.ROPE ] RETURNS[echoNB: NB] -- A convenience for callers -- = { IF phoenixInfo.shh#NIL THEN ThPartySunRPControl.ThrushReportState[phoenixInfo.shh, enabled, connected]; RETURN[RecSS[nb, remark, connected, enabled, voicePath, remoteRemark]]; }; nextSched: INT ¬ pd.pollDefault; PollWaiter: ENTRY PROC[myInfo: PhSmarts.PhoenixInfo] = { ENABLE UNWIND => NULL; nextSched ¬ pd.pollDefault; WHILE myInfo = phoenixInfo DO nextSched ¬ MIN[nextSched, pd.pollDefault]; TRUSTED { Process.SetTimeout[@myInfo.pollCondition, Process.SecondsToTicks[nextSched]]; }; WAIT phoenixInfo.pollCondition; IF myInfo#phoenixInfo THEN RETURN; IF phoenixInfo.nextScheduledCheck#0 THEN { nextSched ¬ phoenixInfo.nextScheduledCheck; phoenixInfo.nextScheduledCheck ¬ 0; LOOP; } ELSE nextSched ¬ nextSched + 30; <> IF ~phoenixInfo.enabled OR ~pd.doPollingTimeouts THEN LOOP; <> [] ¬ ThParty.CheckIn[shh: phoenixInfo.shh, credentials: [ partyID: phoenixInfo.partyID, smartsID: phoenixInfo.smartsID, convID: Thrush.nullConvID]]; ENDLOOP; }; ReportProblemFromThPartyRPC: --already ENTRY-- ThPartySunRPControl.ReportProblem ~ { []¬RecSS[nb: ec, remark: expl]; }; ReportStateFromThPartyRPC: --already ENTRY-- ThPartySunRPControl.ReportState ~ { IF phoenixInfo#NIL THEN { phoenixInfo.partyID ¬ myPartyID; phoenixInfo.smartsID ¬ mySmartsID; }; []¬RecSS[connected: registered, enabled: enabled]; }; Poke: PUBLIC ENTRY PROC = { ENABLE UNWIND => NULL; IF phoenixInfo#NIL THEN NOTIFY phoenixInfo.pollCondition; }; <> <> RecSS: --may be INTERNAL-- PROC[ nb: NB¬NIL, remark: Rope.ROPE¬NIL, connected: BOOL¬phoenixInfo.connected, enabled: BOOL¬phoenixInfo.enabled, voicePath: BOOL¬FALSE, remoteRemark: Rope.ROPE¬NIL ] RETURNS[echoNB: NB] -- A convenience for callers -- = { IF nb#NIL OR connected#phoenixInfo.connected OR enabled#phoenixInfo.enabled THEN { IF nb#NIL THEN NBProblem[remark, nb] ELSE IF remark#NIL THEN VoiceUtils.Report[remark, $Finch]; }; phoenixInfo.connected ¬ connected; phoenixInfo.enabled ¬ enabled; <> IF remoteRemark#NIL THEN { <> IF phoenixInfo=NIL OR ~remoteRemark.Equal[phoenixInfo.lastRemoteRemark] THEN VoiceUtils.Report[remoteRemark, $Finch]; IF phoenixInfo#NIL THEN phoenixInfo.lastRemoteRemark ¬ remoteRemark; }; RETURN[nb]; }; NBProblem: PROC[remark: ROPE¬NIL, nb: NB¬NIL] = { IF nb=NIL THEN VoiceUtils.Problem[remark, $Finch] ELSE VoiceUtils.ProblemFR["%g, reason: %g", $Finch, NIL, IO.rope[remark], IO.atom[nb]]; }; END.