DIRECTORY Atom USING [ PropList ], BasicTime USING [ GMT ], GVBasics USING [ Password ], LarkFeepRpcControl USING [ InterfaceRecord ], MBQueue USING [ Queue ], RedBlackTree USING [ EachNode, Table ], RefID USING [ ID ], Rope USING [ ROPE ], RPC USING [ EncryptionKey, InterfaceName ], ThParty USING [ Attributes, PartyInfo ], Thrush USING [ ActionReport, ConversationID, ConvEventBody, InterfaceSpec, NB, nullConvID, nullID, PartyID, Reason, ROPE, SHHH, SmartsID, StateInConv ], ThSmartsRpcControl ; FinchSmarts: CEDAR DEFINITIONS = { ConversationID: TYPE = Thrush.ConversationID; nullConvID: ConversationID = Thrush.nullConvID; NB: TYPE = Thrush.NB; nullID: RefID.ID = Thrush.nullID; PartyID: TYPE = Thrush.PartyID; Reason: TYPE = Thrush.Reason; ROPE: TYPE = Thrush.ROPE; SHHH: TYPE = Thrush.SHHH; PD: TYPE = RECORD [ -- Global values for all Finch instances doReports: BOOL_FALSE, doPollingTimeouts: BOOL_TRUE, pollDefault: INT _ 300, -- 5 minutes minimum between probes when disconnected timeoutInitiating: NAT _ 11, jayTimeout: NAT _ 1, encryptionRequested: BOOLEAN_TRUE, waitsForConnect: NAT_5, maxProseLength: INT_1000, requests: MBQueue.Queue -- requests to report; must be serialized across all instances ]; pd: REF PD; lock: MONITORLOCK; FinchInfo: TYPE = REF FinchInfoBody; FinchInfoBody: TYPE = MONITORED RECORD [ -- Per Finch instance: one, for now smartsID: Thrush.SmartsID_nullID, partyID: PartyID _ nullID, shh: SHHH_NIL, conversations: LIST OF ConvDesc -- of ConvDescs --, stateChange: CONDITION, myName: ThSmartsRpcControl.InterfaceName _ [], myRName: ROPE _ NIL, myPassword: RPC.EncryptionKey _ NULL, prevThrushInstance: ROPE _ NIL, pollCondition: CONDITION, nextScheduledCheck: INT_0, lastRemoteRemark: ROPE _ NIL, -- print each remote remark once only voicePath: BOOL _ FALSE, -- adjacent Lark is connected enabled: BOOL_FALSE, -- all levels are willing for connection to be maintained. connected: BOOL _ FALSE -- connection is established, and we're registered with Thrush ]; info: FinchInfo; -- global description of what's going on. ConvDesc: TYPE = REF ConvDescBody; ConvDescBody: TYPE = RECORD [ situation: Thrush.ConvEventBody, -- amalgam of useful info from last-reported event previousSituation: Thrush.ConvEventBody, -- helps with hold/active state transitions ultimateState: Thrush.StateInConv _ idle, -- last state reached (except for idle) startTime: BasicTime.GMT_NULL, subject: ROPE_NIL, numParties: NAT_0, numActive: NAT_0, numIdle: NAT_0, partyInfo: ThParty.PartyInfo_NIL, -- Complete description as of some recent time feepInterfaceSpec: Thrush.InterfaceSpec, feepInterface: LarkFeepRpcControl.InterfaceRecord, feepShhh: Thrush.SHHH, clientData: REF _ NIL, props: Atom.PropList _ NIL, firstReport: BOOL_TRUE, originatorRecorded: BOOL_FALSE, reportComplete: BOOL_FALSE ]; InitFinchSmarts: PROC [thrushInstance: Thrush.ROPE_NIL, key: ATOM, s: ReportSystemStateProc _ NIL, c: ReportConversationStateProc _ NIL, r: ReportRequestStateProc _ NIL]; FinchIsRunning: PROC RETURNS [finchIsEnabled: BOOL, finchIsRunning: BOOL, voicePath: BOOL]; Poke: PROC; UninitFinchSmarts: PROC[disable: BOOL_TRUE]; PlaceCall: PROC [ convID: Thrush.ConversationID _ nullConvID, rName: ROPE_NIL, number: ROPE_NIL, useNumber: BOOL_FALSE]; Join: PROC [convName: ROPE] RETURNS[nb: NB]; AnswerCall: PROC[convID: ConversationID]; DisconnectCall: PROC[ convID: ConversationID, reason: Thrush.Reason_$terminating, comment: ROPE_NIL, newState: Thrush.StateInConv _ $idle -- Can also be $failed, to terminate with fast-busy and such. ]; Feep: PROC[convID: ConversationID, feepString: ROPE]; ObtainNumbersForRName: PROC[rName: ROPE] RETURNS [fullRName: ROPE, number: ROPE, homeNumber: ROPE]; CurrentRName: PROC RETURNS [rName: ROPE]; CurrentConversations: PROC RETURNS [conversations: LIST OF ConvDesc]; FetchAttribute: PROC[attributes: ThParty.Attributes, attribute: ATOM, default: ROPE_NIL] RETURNS [value: ROPE, valueLoc: ThParty.Attributes_NIL]; ServiceConnect: PROC [ serviceName: ROPE, convID: Thrush.ConversationID _ nullConvID, createOK: BOOL_TRUE, addOK: BOOL _ FALSE ] RETURNS [ nb: NB_$success, cDesc: ConvDesc_NIL ]; ObtainServiceInterface: PROC [ serviceName: ROPE, interfaceName: ROPE, cDesc: ConvDesc_NIL ] RETURNS [ nb: NB_$success, interfaceSpec: Thrush.InterfaceSpec ]; IdentifyVisitor: PROC[visitor, password: Rope.ROPE, complain: BOOL _ TRUE] RETURNS [nb: NB_$success]; ReleaseVisitor: PROC[visitor, password: Rope.ROPE]; Problem: PROC[remark: ROPE_NIL, nb: NB_NIL]; RecordSystemStateFromSmartsReport: PROC[ nb: NB_NIL, remark: Rope.ROPE, connected: BOOL, enabled: BOOL, voicePath: BOOL, remoteRemark: Rope.ROPE ] RETURNS[echoNB: NB] -- A convenience for callers -- ; ReportProcs: TYPE = REF ReportProcsBody; ReportProcsBody: TYPE = RECORD [ key: ATOM, -- identifies the purpose of this group of procedures position: INT _ 0, -- ordinal within reporting structure; see FinchSmartsImpl reportSystemState: ReportSystemStateProc, reportConversationState: ReportConversationStateProc, reportRequestState: ReportRequestStateProc, enabled: BOOL_TRUE -- disable, don't delete ]; EnumerateIncreasing: PROC[self: RedBlackTree.Table, procToApply: RedBlackTree.EachNode]; ReportSystemStateProc: TYPE = PROC[ enabled: BOOL, connected: BOOL, voicePath: BOOL ]; ReportConversationStateProc: TYPE = PROC[ nb: NB, cDesc: ConvDesc, remark: ROPE_NIL ]; ReportRequestStateProc: TYPE = PROC[ cDesc: ConvDesc, actionReport: Thrush.ActionReport, actionRequest: REF ] RETURNS [betterActionRequest: REF]; RegisterForReports: PROC [key: ATOM, s: ReportSystemStateProc _ NIL, c: ReportConversationStateProc _ NIL, r: ReportRequestStateProc _ NIL, other: ATOM_NIL, before: BOOL _ TRUE]; UnRegisterForReports: PROC [key: ATOM]; ReportConversationState: PROC [nb: NB, cDesc: ConvDesc, remark: Rope.ROPE]; }. #ZFinchSmarts.mesa Copyright Σ 1985, 1986, 1987, 1990 by Xerox Corporation. All rights reserved. Last Edited by: Swinehart, September 22, 1990 1:51 pm PDT Doug Terry, September 5, 1986 3:44:36 pm PDT Polle Zellweger (PTZ) July 25, 1990 7:23:48 pm PDT Types These values are derived from lower-level values. Switching data Data of use to clients, maintained by FinchSmarts Maintained by SmartsImpl: For calls that were completed, this will be active For attempted outgoing calls, this is perhaps maybe For incoming calls that were not answered, this is perhaps ringing Client-maintained data ReportConversationState implementation can store client-dependent pointers here; but this field is cleared once the ConvDesc leaves the FinchInfo.conversations Queue. Client-specific values, such as information used by synthesizer code and such. Placed here as a convenience for such services. Initialization Initialize, then register the specified procedures via RegisterForReports. Solves a mutual dependency: the completion of InitFinchSmarts wants to call ReportSystemState via the registry, but the registry is maintained by a data structure that this procedure creates. finchIsEnabled means InitFinchSmarts has been called more frequently than UninitFinchSmarts; finchIsRunning means Finch and the server are in contact; if false, the next call will attempt to reestablish, but it might fail. voicePath means that the adjacent Lark is registered. If enabled but not connected, tries to get connected, best way. Call Management Uses specified conversation, creates a new one or uses one that's in a sufficiently idle state. Interpretation of rName and number -- evaluate until action can be taken: rName exists in switching system (has an Etherphone, usually) and ~use#: call that party. number#NIL: rName is simply a description; call by number rName=NIL or use#: invalid parameters rName exists in obsolete directory and ~use#: use the resulting number all tests fail: no such party. If the other party is willing to do it (trunk parties only, at present), generate touchtones corresponding to the characters in feepString. For talking to feep-controlled services. Alphabetic characters in feepString are translated to their corresponding digits, based ont he mapping found on most telephone touchpads and dials. Currently-known conversations Management of services Establishes an active conversation with the named voice service, e.g. "recording". Uses specified conversation, creates a new one, or uses one that's in a sufficiently idle state. If serviceName is NIL, this is a request to establish as innocuous a one-party conversation as possiblepreferably in the state $inactiveso that we can talk with our poachee. If supplied conversation or (if none supplied) is active and addOK, and service is not already a party, bring it in (!) Looks up the interface for the named voice service, e.g. the "VoiceRopeServer" interface for the "recording" service. Clients can then import this interface directly. If serviceName is NIL, this is a request to obtain the service from our own party, or (more likely, since that's the whole idea) that of its poachee. IF cDesc#NIL, this is a request to obtain the service from the "other party" in the present conversation; a bit flakey since there could be more than one, in which case it makes an arbitrary choice. Visiting Will complain about invalid passwords iff complain=TRUE. These are merely linkages from FinchSmartsImpl to ThPartyClientImpl. There remains some confusion about Finch-to-ThParty connection time, and about registration of a particular Finch instance; at present, only one per machine makes sense anyway, though. Records that Finch is connected or disconnected, enabled or disabled, logs the remark(s) if given, reports new system state to registered clients, returns its NB argument. See FinchSmartsImpl, ThPartyClientImpl. Reporting Used as Key and UserData in the report tree Call backs Clients of Finch can register callback procedures to receive reports concerning the state of conversations, actions taken by the recording service, etc. These will be executed serially, in the order that they are issued. enabled is made true through calls to InitFinchSmarts; connected is true only when a server connection has been established. voicePath is true only when the adjacent Lark is connected. Client-relevant changes in conversation state are reported in gory detail; FinchSmarts is allowed to invent parts of it (e.g., reason and remark fields) ThSmarts.ReportAction was called; we are willing to pass the report on to this routine. FinchSmarts implementation will locate the relevant action request (e.g., an IntervalSpec) and pass it on with the action report. N.B.!!! Each registered ReportRequestStateProc must either return actionReport, or return a better value for it. The intended use is for an upstream registered proc. to compute the request value as a function of actionReport and some local state. Downstream procedures get the augmented report. Care must be taken to register these procedures (with the help of the before hint (see RegisterForReports), so that the right thing happens. If before is true, procs go at front of other, else they go after it. If other is $all, places this set of procs at head or tail of reporting order (one only each) Key must be a unique id for an "appearance" of a proc set in the list. It is used to permit new versions to overlay old ones during system development. The "before"-ness cannot change from one version to another within the same virtual memory. Remove procs from the list of report subscribers. (Actually merely invalidates them, so that their beforeness will not be disturbed. Distributes a report to all subscribers. Swinehart, July 18, 1985 3:31:34 pm PDT Created FinchSmarts.Register and friends -- easier for WalnutVoice to deal with Finch. changes to: InitFinchSmarts, RecordTuneProc, RecordTune, StopTuneProc, StopTune, PlaybackTuneProc, PlaybackTune, PlayNoiseProc, PlayNoise, Feep, FinchState, Procs, CurrentFinchState, Procs, Register, FinchIsRunning, UninitFinchSmarts, GetProcs Polle Zellweger (PTZ) July 13, 1985 5:20:26 pm PDT adding Text-to-Speech server Changes to: DIRECTORY, FinchInfoBody, ConvDescBody Added: TextToSpeech, StopSpeech Swinehart, August 6, 1985 4:19:33 pm PDT Merge PTZ Prose changes changes to: DIRECTORY, FinchInfoBody, ConvDescBody, PlayNoise, TextToSpeech, StopSpeechProc, StopSpeech, ProcsRecord Polle Zellweger (PTZ) August 29, 1985 5:06:29 pm PDT changes to: TextToSpeechProc, ProseTranslateProc, TextToSpeech, StopSpeechProc, StopSpeech, ResetProse, ProcsRecord Polle Zellweger (PTZ) September 3, 1985 6:17:21 pm PDT Allow registration of proseTranslateProc. changes to: ProseTranslateProc, TextToSpeech, RegisterTranslateProcType, RegisterTranslateProc, ProcsRecord Polle Zellweger (PTZ) October 24, 1985 4:56:25 pm PDT Move bluejayConnection and proseConnection from FinchInfo to ConvDesc. changes to: FinchInfoBody, ConvDescBody Doug Terry, August 28, 1986 4:22:57 pm PDT Created FinchSmarts.RegisterForReports; removed all routines dealing with record or playback of tunes and removed record/play stuff from FinchInfo and ConvDesc; retired FinchSmarts.Register and friends. changes to: ReportSystemStateProc, ReportConversationStateProc, ReportRequestStateProc, RegisterForReports, DIRECTORY, FinchInfoBody, ConvDescBody, InitFinchSmarts, UnRegisterForReports Doug Terry, August 29, 1986 12:06:10 pm PDT New interface procedures for FinchSmarts clients to get at voice services: VoiceConnect and LookupServiceInterface. changes to: VoiceConnect, LookupServiceInterface Swinehart, September 25, 1986 11:12:43 am PDT Add props field to ConvDesc, in order to allow per-conversation application-specific data. changes to: ConvDescBody Polle Zellweger (PTZ) February 19, 1987 10:31:24 pm PST changes to: FinchInfoBody, VisitorInfo, VisitorInfoBody, ConvDesc, DIRECTORY, IdentifyVisitor, ReleaseVisitor Polle Zellweger (PTZ) February 23, 1987 2:15:25 pm PST changes to: FinchInfoBody Polle Zellweger (PTZ) February 27, 1987 4:23:24 pm PST changes to: IdentifyVisitor, ReleaseVisitor, FinchInfoBody Swinehart, July 14, 1987 4:19:10 pm PDT Numerous changes in support of improved error and connection management. Swinehart, July 19, 1987 4:45:25 pm PDT VoiceConnect => ServiceConnect changes to: ServiceConnect Polle Zellweger (PTZ) July 27, 1987 8:35:23 pm PDT Allow for better party reports in FinchTool (>2 parties in conversation) changes to: WhoOriginated, unknown, us Polle Zellweger (PTZ) July 31, 1987 2:13:52 pm PDT changes to: FinchSmarts, ConvDescBody, DIRECTORY Swinehart, February 16, 1988 10:20:19 pm PST Eliminate whoOriginated field; PartyInfo now contains that information directly. changes to: nullID, ConvDescBody Swinehart, September 8, 1990 6:39:47 pm PDT Clean up FinchInfo, add global info variable, since there seems to be one anyway. Add previousSituation field to ConvEventBody., RecordSystemStateFromSmartsReport Κ Π˜šœ™IcodešœN™NJšœ9™9K™,Kšœ2™2—J˜šΟk ˜ Jšœœ˜Jšœ˜Jšœ œ˜Jšœœ˜-J˜Jšœ œ˜'Jšœœœ˜Jšœœœ˜Jšœœ"˜+J˜(šœ˜ Jšœgœ ˜‹—J˜J˜J˜—šΠbl œœ˜"J˜—™J™šœœ˜-J˜/—Jšœœ œ˜Jšœœ˜!Jšœ œ˜Jšœœ˜Jšœœ œ˜Jšœœ œ˜J˜šœœœΟc(˜˜VJ˜—šœŸ)˜:J˜—Jšœ œœ˜"šœœœ˜J™Jšœ!Ÿ2˜SJšœ)Ÿ+˜TJ˜J™1šœ*Ÿ'˜QJšœ™Jšœ2™2Jšœ3™3JšœB™B—Jšœœœ˜Jšœ œœ˜Jšœ œ˜Jšœ œ˜Jšœ œ˜JšœœŸ/˜QJ˜(J˜2J˜J˜J™šœ œœ˜Jšœ¦™¦—šœœ˜Jšœ€™€—Jšœ œœ˜Jšœœœ˜Jšœœ˜J˜—J™—™J˜šΟnœœœœœœ#œœ˜ͺJ™‹—J˜š‘œ˜Jšœœœ œ˜FJšœ•™•—J˜š‘œœ˜ J™?J™—Jš‘œœ œœ˜-J˜—™J˜š‘ œœ˜Jšœ+˜+Jšœœœ˜Jšœœ˜Jšœ œœ˜J™_™IJ™YJ™9J™%J™FJ™—J˜—š ‘œœ œœœ˜,J˜—š‘ œœ˜)J˜—š‘œœ˜Jšœ˜J˜#Jšœ œ˜Jšœ%Ÿ=˜bJšœ˜J˜—™΅J™“—Jš‘œœ%œ˜5J˜š‘œœœ˜(Jšœ œ œœ˜:—J˜Jš‘ œœœ œ˜)J˜š ‘œœœœœ ˜EJ™J™—š ‘œœ,œ œœ˜XJšœ œœ˜8—J˜—™J™š‘œœ˜Jšœ œ˜Jšœ+˜+Jšœ œ˜Jšœœ˜Jšœœ˜ Jšœœ ˜Jšœ˜J˜Jšœ΄™΄Jšœœš™―J™wJ˜—š‘œœ˜Jšœ œ˜Jšœœ˜Jšœ˜Jšœœ˜ Jšœœ ˜J˜#J˜Jšœ§™§Jšœœ€™•Jšœ œΊ™Ζ—J™š ‘œœœ œœ˜JJšœœ ˜J™8—Jš‘œœœ˜3J˜š ‘œœ œœœœ˜,J˜—JšœFΟtœΈ’™€J™š‘!œœ˜(Kšœœ˜ Kšœ œ˜Kšœ œ˜Kšœ œ˜Kšœ œ˜Kšœ˜Kšœ˜Kšœ œŸœ˜5J™Τ—J˜—™ J™šœ œœ˜(J™+—šœœœ˜ J™ JšœœŸ5˜@Jšœ œŸ:˜MJšœ)˜)Jšœ5˜5Jšœ,˜,Jšœ œœŸ˜+J˜—J˜š‘œœ?˜XJ˜J˜—J™έJ˜š œœœ œ œ œ˜VJ™Έ—J˜š œœœœœœ˜VJšœ˜™˜—J˜š œœœEœœœ˜‘J™ΪJšΟbœω‘œ#™Ά—J™š‘œœœœ#œœ œœ œœ˜²Kšœ(Οoœ™EKšœ€œU™]K™υK™—š‘œœœ˜'K™…—J™š‘œœœ œ˜KJ™(——J˜J™™'K™VKšœ Οrη™σ—™2K™Kšœ ₯&™2Kšœ₯™—™(K™Kšœ ₯h™t—™4Kšœ ₯g™s—™6Kšœ₯œ™)Kšœ ₯_™k—šœ5™5KšœF™FKšœ ₯™'—™*KšœΚ™ΚKšœ ₯­™Ή—™+Kšœs™sKšœ ₯$™0—™-K™ZKšœ ₯ ™—™7Kšœ ₯a™m—™6Kšœ ₯ ™—™6Kšœ ₯.™:—™'K™H—™'K™Kšœ ₯™—™2K™HKšœ ₯™&—™2Kšœ ₯$™0—K™™,K™PKšœ ₯™ —K™™+Kšœ€₯#™£—K™K™K™K™—…—ΨE