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, reset, SHHH, StatusEvent, Tone, ToneSpec, ToneSpecRec, VoiceBuffer ], LarkOps USING [ LarkParameters, LarkParametersRec ], LarkPlay USING [ ToneList, ToneSpec, ToneSpecRec ], LarkOpsRpcControl, LarkSmarts, Multicast USING [ HandleMulticast, StopHandlingMulticast ], Nice, Process USING [ Detach, EnableAborts, MsecToTicks, SetTimeout ], Pup USING [ nullSocket ], Rope USING [ Fetch, Length, ROPE ], RPC USING [ CallFailed ], RPCTimeouts USING [ SetMaxTransmissions ], ThNet USING [ pd ], ThParty USING [ PartyInfo ], ThPartyPrivate USING [ SmartsData ], Thrush USING[ NetAddress, ROPE, SHHH, SmartsID ], ThSmartsPrivate USING [ ConvDesc, LarkCall, LarkInfo, LarkState, LSwitches, LState, ProgressTones, SmartsInfo, SwitchState ], TU USING [ RefAddr ], VoiceUtils USING [ ProblemFR, Report ] ; LarkOutImpl: CEDAR MONITOR LOCKS info USING info: LarkInfo IMPORTS Commander, IO, LarkOpsRpcControl, Multicast, Nice, Process, Rope, RPC, RPCTimeouts, ThNet, 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; reset: Lark.Event = Lark.reset; larkRegistry: ROPE _ ".Lark"; 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 _ 800, 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, 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 ] = { ENABLE UNWIND=>NULL; 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 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. watch out set => { info.larkState_newState; RETURN; }; X => {info.audioSource _ NIL; info.transmitOnly _ FALSE;LarkProblem["%g: Invalid LarkState Transition", info]; RETURN;}; fai => { info.larkState _ failed; LarkProblem["%g: Lark failure requested by server", info]; info.larkProcess _ NIL; info.audioSource _ NIL; info.transmitOnly _ FALSE; NOTIFY info.stateChange; -- Be sure process notices failure and disappears. RETURN; }; zap => { info.audioSource _ NIL; info.transmitOnly _ FALSE; }; ENDCASE; 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 OR connectionSpec#NIL) AND info.spec#NIL THEN { IF ThNet.pd.debug THEN Deb[ info, 'd ]; QueueLarkAction[info, aDisconnect]; }; toneSpec _ SELECT trans FROM dia, diu => dialTone, -- to handset receiver rbk, rbu => IF toneSpec#NIL THEN toneSpec ELSE ringbackTone, bzy, bzu => busyTone, err, eru => errorTone, rng, rgu => toneSpec, ENDCASE => NIL ; SELECT tDoTones[trans] FROM doTones => { IF ThNet.pd.debug THEN Deb[ info, 'T ]; IF toneSpec#NIL THEN QueueLarkAction[info, toneSpec]; }; stopTones => { IF ThNet.pd.debug THEN Deb[ info, 't ]; QueueLarkAction[info, aNoTones]; }; ENDCASE; SELECT tHookState[trans] FROM reset => { SELECT info.switchState FROM $monitor, $speaker => info.switchState_$onhook; -- going totally idle ENDCASE; }; spkrTrans => IF info.switchState=$onhook THEN -- dialtone, direct connect or ringback info.switchState _ $speaker; ENDCASE; -- no state change cases. IF info.switchState#info.lastSwitchState THEN sw_TRUE; SELECT tSwitch[trans] FROM switch => sw_TRUE; switchIfDiff => IF oldState { IF ThNet.pd.debug THEN Deb[info, 'F]; feepSpecs _ RopeToDTMF[ropeSpec]; pd.noisyFeeps _ feepSpecs.audible; }; ENDCASE; IF sw THEN TRUSTED { command: ROPE _ larkCommands[info.switchState][newState]; IF ThNet.pd.debug THEN Deb[info, 'M, rope[command]]; otherAction _ QueueCommandSequence[info, command, @info.lState, info.scratchEv]; IF trans=fls THEN { Process.Detach[FORK FlashWait[info]]; info.larkState _ oldState; -- never really enter fls state, stay in forwarding or trunkTalking. }; info.lastSwitchState _ info.switchState; }; IF feepSpecs#NIL THEN QueueLarkAction[info, feepSpecs]; IF keyTable#NIL THEN { IF ThNet.pd.debug THEN Deb[info, 'K]; keyTablesToDate _ (info.keyTableDistrsRequested _ info.keyTableDistrsRequested+1); QueueLarkAction[info, keyTable]; }; IF connectionSpec#NIL THEN { IF ThNet.pd.debug THEN Deb[info, 'C]; SELECT trans FROM sup, spn, tlk, frd, frn => QueueLarkAction[info, connectionSpec]; sgl, sgn => IF info.forwardedCall THEN QueueLarkAction[info, connectionSpec]; ENDCASE; }; IF larkCall#NIL THEN SELECT tLarkCall[trans] FROM call => QueueLarkAction[info, larkCall]; ENDCASE; IF otherAction#NIL THEN { IF ThNet.pd.debug THEN Deb[info, 'O]; QueueLarkAction[info, otherAction]; }; IF keyTable#NIL THEN WHILE keyTablesToDate > info.keyTablesDistributed DO WAIT info.keySynch; -- Be sure keys have really been delivered ENDLOOP; }; LarkFailed: PUBLIC ERROR [smartsInfo: SmartsInfo] = CODE; TonesDone: PUBLIC ENTRY PROC[info: LarkInfo, commandEvent: Lark.StatusEvent ] = { Deb[info, 'z]; SELECT commandEvent.event FROM 'F=> -- Feeping complete { IF info.larkState#trunkSignalling THEN RETURN; EnterLarkSt[info, trunkTalking, NIL]; }; ENDCASE => -- other tones finished. QueueLarkAction[info, NEW[ATonesDoneType _ [commandEvent.event]]]; }; FlashWait: PUBLIC ENTRY PROC[info: LarkInfo ] = TRUSTED { ENABLE UNWIND => NULL; flashWait: CONDITION; IF info=NIL THEN RETURN; Process.SetTimeout[@flashWait, Process.MsecToTicks[pd.flashWaitTime]]; -- 600 ms or so. Deb[info, 'w]; WAIT flashWait; Deb[info, 'W]; IF info.larkState=trunkTalking THEN -- nothing has gone wrong []_QueueCommandSequence[info, larkCommands[info.switchState][info.larkState], @info.lState, info.scratchEv]; }; BlinkLED: PUBLIC ENTRY PROC[info: LarkInfo] = TRUSTED { ENABLE UNWIND => NULL; blinkWait: CONDITION; IF info=NIL THEN RETURN; WHILE info.forwardedCall AND info.larkState >= trunkSignalling AND info.larkState <= trunkFlashing AND info.larkProcess#NIL DO Deb[info, 'B]; []_QueueLarkAction[info, aToggleLED]; Process.SetTimeout[@blinkWait, Process.MsecToTicks[pd.blinkWaitTime]]; -- 500 ms or so. WAIT blinkWait; ENDLOOP; info.blinkProcess _ NIL; }; QueueFeeps: PUBLIC PROC[sInfo: SmartsInfo, feeps: Rope.ROPE ] = { EnterLarkState[sInfo.larkInfo, trunkSignalling, LIST[NEW[Atom.DottedPairNode_[$phoneNumber, feeps]]]]; }; SetupTimeouts: PUBLIC ENTRY PROC[info: LarkInfo, debugging: BOOL ] = { larkParams: LarkOps.LarkParameters _ NEW[LarkOps.LarkParametersRec[4]]; RPCTimeouts.SetMaxTransmissions[ conversation: info.shh, maxTransmissions: pd.toLarkTimeoutTransmissions, timeoutEnable: SELECT pd.toLarkTimeoutOK FROM always => always, never => never, unlessDebugging => IF debugging THEN never ELSE always, ENDCASE=>dontCare]; larkParams[0] _ [prDefaultMaxTransmissions, pd.fromLarkTimeoutTransmissions]; larkParams[1] _ [prSignalTimeout, LOOPHOLE[SELECT pd.fromLarkTimeoutOK FROM always => TRUE, never => FALSE, unlessDebugging => ~debugging, ENDCASE=>ERROR]]; larkParams[2] _ [prEventTimer, pd.larkEventTimer]; larkParams[3] _ [prTimeoutEvents, LOOPHOLE[SELECT pd.larkTimeoutEvents FROM always => TRUE, never => FALSE, unlessDebugging => ~debugging, ENDCASE=>ERROR]]; larkParams.numParams _ 4; []_QueueLarkAction[info, larkParams]; }; FailE: ENTRY PROC[info: LarkInfo] = {Fail[info];}; Fail: INTERNAL PROC[info: LarkInfo] = { info.larkState_failed; info.keyTablesDistributed _ info.keyTableDistrsRequested; BROADCAST info.keySynch; }; LarkSupervisor: PROCEDURE[ info: LarkInfo ] = { ENABLE UNWIND => NULL; req: REF; WaitForAction: ENTRY PROC[info: LarkInfo] RETURNS [ref: REF_NIL] = TRUSTED { ENABLE UNWIND=>NULL; DO elt: LIST OF REF _ info.newActions; IF info.larkState=failed THEN RETURN[NIL]; IF elt # NIL THEN { ref_elt.first; info.newActions _ elt.rest; RETURN[ref]; }; Process.SetTimeout[@info.stateChange, Process.MsecToTicks[pd.idleWaitTime]]; WAIT info.stateChange; IF info.newActions = NIL THEN { IF info.nextToneList#NIL THEN Fail[info]; -- Notification is late. RETURN[NIL]; }; ENDLOOP; }; IF info.larkToneSpec=NIL THEN info.larkToneSpec _ NEW[Lark.ToneSpecRec _ [volume: 0, totalTime: 0, tones: NIL]]; IF info.cSpec=NIL THEN info.cSpec _ NEW[Lark.ConnectionSpecRec _ [ protocol: interactive, encoding: muLaw, sampleRate: 8000, packetSize: 160, buffer: in1, keyIndex: IF ThNet.pd.encryptVoice THEN 1 ELSE 0, localSocket: [[0],[0], Pup.nullSocket], remoteSocket: [[0],[0], Pup.nullSocket] ]]; TRUSTED { Process.EnableAborts[@info.stateChange]; Process.EnableAborts[@info.keySynch]; Process.SetTimeout[@info.stateChange, Process.MsecToTicks[pd.keySynchTime]]; }; StopMulticast[info]; Multicast.StopHandlingMulticast[shh: info.shh, realHost: info.netAddress.host]; WHILE (req_WaitForAction[info])#NIL DO -- Deal with communications failure. ENABLE { RPC.CallFailed => { LarkProblem["%g: Call Failed", info]; GOTO Failed; }; ABORTED => { LarkProblem["%g: LarkSupervisor aborted", info]; GOTO Failed; }; }; DoTones: PROC[newTones: BOOL] = { -- Does one tone from current list of tones IF info.nextToneList=NIL THEN RETURN; info.larkToneSpec.volume _ info.toneSpec.volume; info.expectedNotification _ IF info.expectedNotification='z THEN 'a ELSE info.expectedNotification+1; info.larkToneSpec.notification _ [tones, info.expectedNotification]; info.larkToneSpec.tones _ info.nextToneList.first; []_info.interface.SpecifyTones[shh: info.shh, queueIt: ~newTones, tones: info.larkToneSpec]; }; WITH req SELECT FROM d: REF ADisconnectType => IF info.spec#NIL THEN { buf: Lark.VoiceBuffer _ out1; info.interface.Disconnect[ shh: info.shh, buffer: in1 ]; -- always stop in1 (tx1) FOR i: NAT IN [1..info.spec.numParties) DO info.interface.Disconnect[ shh: info.shh, buffer: buf ]; -- out1 (tx1) through outn (txn) buf _ SUCC[buf]; ENDLOOP; IF info.multicasting THEN StopMulticast[info]; info.spec _ NIL; }; spec: ThParty.PartyInfo => { cSpec: Lark.ConnectionSpec = info.cSpec; conference: BOOL _ spec.numParties>=3; IF spec.numParties>=2 THEN { info.spec _ spec; IF conference THEN conference _ StartMulticast[info, spec.conferenceHost]; cSpec.buffer _ in1; cSpec.remoteSocket _ spec[1].socket; cSpec.remoteSocket.socket _ spec[0].socket.socket; IF conference THEN cSpec.remoteSocket.host _ spec.conferenceHost.host; cSpec.localSocket _ cSpec.remoteSocket; -- superstition info.interface.Connect[shh: info.shh, specs: cSpec ]; cSpec.buffer _ out1; FOR i: NAT IN [1..spec.numParties) DO cSpec.localSocket _ spec[i].socket; IF conference THEN cSpec.localSocket.host _ spec.conferenceHost.host; cSpec.remoteSocket _ cSpec.localSocket; -- superstition info.interface.Connect[shh: info.shh, specs: cSpec ]; cSpec.buffer _ SUCC[cSpec.buffer]; ENDLOOP; }; }; keyTable: Lark.KeyTable => { UKT: ENTRY PROC[info: LarkInfo] = INLINE { info.keyTable _ keyTable; info.keyTablesDistributed _ info.keyTablesDistributed + 1; BROADCAST info.keySynch; }; info.interface.SetKeyTable[shh: info.shh, table: keyTable]; UKT[info]; }; ts: LarkPlay.ToneSpec => { info.toneSpec_ts; info.nextToneList _ info.toneSpec.tones; DoTones[TRUE]; }; lC: ThSmartsPrivate.LarkCall => lC.proc[info, lC.clientData]; td: REF ATonesDoneType => IF info.toneSpec#NIL THEN { IF td.event#info.expectedNotification THEN GOTO Failed; IF info.nextToneList#NIL AND info.nextToneList.rest#NIL THEN info.nextToneList _ info.nextToneList.rest ELSE IF NOT info.toneSpec.repeatIndefinitely THEN { info.toneSpec_NIL; info.nextToneList_NIL } ELSE info.nextToneList _ info.toneSpec.tones; IF info.nextToneList#NIL THEN DoTones[FALSE]; }; a: REF ANoTonesType => { info.toneSpec_NIL; info.nextToneList_NIL; quenchSpec.tones.first.on _ 0; []_info.interface.SpecifyTones[shh: info.shh, tones: quenchSpec, queueIt: FALSE]; }; led: REF AToggleLEDType => { info.lState.lSw[led] _ IF info.lState.lSw[led] = disabled THEN enabled ELSE disabled; ledToggler[0] _ [led, info.lState.lSw[led]]; []_info.interface.Commands[info.shh, ledToggler]; }; resetAction: REF ResetActionType => { []_info.interface.Reset[shh: info.shh, rName: "Don't revert"]; IF info.multicasting THEN StopMulticast[info]; IF info.keyboardResetHandler#NIL THEN info.keyboardResetHandler[info]; }; larkParameters: LarkOps.LarkParameters => []_info.interface.SetParameters[shh: info.shh, parameters: larkParameters]; echoParameters: Lark.EchoParameters => []_info.interface.EchoSupression[shh: info.shh, echo: echoParameters]; commands: Lark.CommandEvents => IF commands#NIL THEN info.interface.Commands[ info.shh, commands ]; feepSpecs: REF AFeepType => { IF feepSpecs=NIL THEN LOOP; IF (quenchSpec.tones.first.on _ feepSpecs.initialDelay)#0 THEN []_info.interface.SpecifyTones[shh: info.shh, tones: quenchSpec, queueIt: FALSE]; []_info.interface.Feep[ shh: info.shh, on: feepSpecs.on, off: feepSpecs.off, notify: [tones, 'F], waveTable: ThNet.pd.feepVolume, queueIt: TRUE, events: feepSpecs.digits]; } ENDCASE; REPEAT Failed => FailE[info]; ENDLOOP; info.larkProcess _ NIL; }; StartMulticast: PROC[info: LarkInfo, hostAddress: Thrush.NetAddress] RETURNS[ok: BOOL_TRUE] = { IF info.multicasting THEN StopMulticast[info]; IF info.spec=NIL OR info.spec.numParties <=2 THEN RETURN[FALSE]; ok _ Multicast.HandleMulticast[shh: info.shh, net: info.netAddress.net, realHost: info.netAddress.host, listeningTo: hostAddress.host]; IF ~ok THEN { VoiceUtils.ProblemFR["Couldn't set multicasting [%g => %g]", $Lark, info, int[info.netAddress.host], int[hostAddress.host]]; RETURN; }; info.interface.SetHostNumber[shh: info.shh, host: [hostAddress.net, hostAddress.host]]; info.multicasting _ TRUE; }; StopMulticast: PROC[info: LarkInfo, force: BOOL_FALSE] = { IF ~info.multicasting THEN RETURN; info.interface.SetHostNumber[shh: info.shh, host: [info.netAddress.net, info.netAddress.host]]; Multicast.StopHandlingMulticast[shh: info.shh, realHost: info.netAddress.host]; info.multicasting _ FALSE; }; QueueLarkAction: INTERNAL PROC[info: LarkInfo, ref: REF] = { elt: LIST OF REF = LIST[ref]; lst: LIST OF REF = info.lastAction; IF info.newActions=NIL THEN info.newActions _ elt ELSE IF lst=NIL THEN ERROR ELSE lst.rest _ elt; info.lastAction _ elt; IF info.larkProcess=NIL THEN TRUSTED { Process.Detach[info.larkProcess _ FORK LarkSupervisor[ info ]]; }; NOTIFY info.stateChange; }; LarkProblem: PROC[remark: ROPE, info: LarkInfo] = { VoiceUtils.ProblemFR[remark, $Lark, info, TU.RefAddr[info.larkSmartsInfo]]; }; QueueCommandSequence: INTERNAL PROC[ info: LarkInfo, commands: ROPE, lState: LONG POINTER TO LState, scratchEv: Lark.CommandEvents] RETURNS[otherAction: REF_NIL]= TRUSTED { eventIndex: INTEGER_-1; c: CHAR; i: NAT; index: INTEGER; event: Lark.Event; events: Lark.CommandEvents _ scratchEv; nextState: LState _ []; len: NAT; IF commands=NIL THEN RETURN; -- status quo len _ commands.Length[]; FOR i IN [0..len) DO SELECT (c_commands.Fetch[i]) FROM 'J, 'j => IF ~pd.backDoorOH THEN LOOP; ENDCASE; SELECT c FROM 'Z => { lState^_ []; otherAction _ resetAction; }; -- Zap; reset hardware to full idle 'X, 'x => { -- Crossbar switch specification, possibly parameterized by next character param: CHAR _ commands.Fetch[i+1]; outputs: PACKED ARRAY [0..8) OF BOOLEAN; row: NAT; wasParam, doIt: BOOL_TRUE; SELECT param FROM IN ['0..'9] => wasParam _ FALSE; -- no parameter, just do it. 'A => IF info.audioSource#$linea THEN doIt_FALSE; 'B => IF info.audioSource#$lineb THEN doIt_FALSE; 'r => IF info.audioSource=$linea OR info.audioSource=$lineb THEN doIt_FALSE; 't => IF info.transmitOnly THEN doIt_FALSE; -- inhibit all receive switching. 'F => IF ~pd.noisyFeeps THEN doIt_FALSE; -- caller hears auto-feeping ENDCASE => doIt_FALSE; -- unrecognized parameter, don't do it; IF wasParam THEN { i_i+1; param _ commands.Fetch[i+1]; }; row _ Digit[param]; outputs _ LOOPHOLE[nextState.xbar[row]]; IF doIt THEN outputs[Digit[commands.Fetch[i+2]]] _ (c='X); nextState.xbar[row] _ LOOPHOLE[outputs]; i_i+2; LOOP; }; 'E, 'e => { nextState.echoStyle _ commands.Fetch[i_i+1]-'0; otherAction _ echosOn[nextState.echoStyle]; }; 'M, 'm => { nextState.voiceMode _ SELECT commands.Fetch[i_i+1] FROM '0 => Lark.o3i1, '1 => Lark.o2i2, '2 => Lark.o1i1, ENDCASE => ERROR; }; ENDCASE=> { IF c IN ['a..'z] THEN { event _ Lark.disabled; c_c-('a-'A); } ELSE event _ Lark.enabled; IF lStateForLetter[c]#none THEN nextState.lSw[lStateForLetter[c]] _ event; }; ENDLOOP; IF nextState=lState^ THEN RETURN; IF nextState.echoStyle#lState.echoStyle AND otherAction=NIL THEN otherAction _ echosOff[lState.echoStyle]; FOR iteration: NAT IN [0..1] DO -- 0: compute size; 1: fill in result sequence. index_-1; IF nextState.voiceMode#lState.voiceMode THEN events[index_index+1] _ [voiceMode, nextState.voiceMode]; FOR i: LSwitches DECREASING IN LSwitches DO IF nextState.lSw[i]#lState.lSw[i] THEN events[index_index+1] _ [lDevs[i], nextState.lSw[i]]; ENDLOOP; FOR i: NAT IN [0..8) DO IF nextState.xbar[i]#lState.xbar[i] THEN { outputs: PACKED ARRAY[0..8) OF BOOLEAN = LOOPHOLE[lState.xbar[i]]; nxtOutputs: PACKED ARRAY[0..8) OF BOOLEAN = LOOPHOLE[nextState.xbar[i]]; FOR j: NAT IN [0..8) DO IF outputs[j]#nxtOutputs[j] THEN events[index_index+1] _ [ Lark.Device[LOOPHOLE[IF nxtOutputs[j] THEN 23 ELSE 22]], LOOPHOLE[i*16+j] ]; ENDLOOP; }; ENDLOOP; IF index=-1 THEN { events_NIL; EXIT; }; IF iteration=0 THEN events _ NEW[Lark.CommandEventSequence[index+1]]; ENDLOOP; QueueLarkAction[info, events]; lState^ _ nextState; lState.lSw[xBarAll] _ Lark.disabled; }; Digit: PROC[c: CHAR] RETURNS [digit: NAT] = INLINE { RETURN[c-'0]; }; RopeToDTMF: PROC [r: Thrush.ROPE] RETURNS [fs: REF AFeepType] = { len: INT _ MIN[Lark.Passel.LAST, r.Length[]]; ce: Lark.CommandEvents; ceIndex: INT_0; number: INTEGER; fs _ NEW[AFeepType_[]]; FOR rIndex: INT IN [0..len) DO c: CHAR = r.Fetch[rIndex]; SELECT c FROM IN ['0..'9], IN ['a..'d], '#, '* => ceIndex _ ceIndex+1; 'P => IF ceIndex#0 THEN ceIndex _ ceIndex+1 ELSE fs.initialDelay _ number*100; 'A => fs.audible _ TRUE; 'O => fs.on _ number*10; 'F => fs.off _ number*10; IN ['\001..'\037] => number _ c-'\000; ENDCASE; -- unrecognized, so ignore it. ENDLOOP; ce _ NEW[Lark.CommandEventSequence[ceIndex]]; fs.digits _ ce; ceIndex _ 0; FOR rIndex: INT IN [0..len) DO c: CHAR = r.Fetch[rIndex]; val: CHAR _ '\000; SELECT c FROM IN ['0..'9] => val _ LOOPHOLE[128 + c - '0]; IN ['a..'d] => val _ LOOPHOLE[138 + c - 'a]; '* => val _ Lark.bStar; '# => val _ Lark.bThorp; IN ['\001..'\037] => number _ c-'\000; 'P => IF ceIndex#0 THEN val _ LOOPHOLE[number*10]; ENDCASE; IF val = '\000 THEN LOOP; ce[ceIndex] _ [touchPad, val]; ceIndex _ ceIndex+1; ENDLOOP; }; SetTones: INTERNAL PROC[] = { IF ~pd.tonesInvalid THEN RETURN; pd.tonesInvalid _ FALSE; dialTone _ NEW[LarkPlay.ToneSpecRec _ [repeatIndefinitely: TRUE, volume: ThNet.pd.tonesVolume, tones: LIST[LIST[ [f1: 350, f2: 440, on: 5000, off: 0], [f1: 350, f2: 440, on: 5000, off: 0]]]]]; busyTone _ NEW[LarkPlay.ToneSpecRec _ [repeatIndefinitely: TRUE, volume: ThNet.pd.tonesVolume, tones: LIST[LIST[ [f1: 480, f2: 620, on: 500, off: 500, repetitions: 5], [f1: 480, f2: 620, on: 500, off: 500, repetitions: 5]]]]]; errorTone _ NEW[LarkPlay.ToneSpecRec _ [repeatIndefinitely: TRUE, volume: ThNet.pd.tonesVolume, tones: LIST[LIST[ [f1: 480, f2: 620, on: 250, off: 250, repetitions: 10], [f1: 480, f2: 620, on: 250, off: 250, repetitions: 10]]]]]; ringbackTone _ NEW[LarkPlay.ToneSpecRec _ [repeatIndefinitely: TRUE, volume: ThNet.pd.tonesVolume, tones: LIST[LIST[ [f1: 440, f2: 480, on: 2000, off: 4000], [f1: 440, f2: 480, on: 2000, off: 4000]]]]]; }; Deb: PUBLIC PROC[info: LarkInfo, c: CHAR, p1, p2, p3, p4: IO.Value_[null[]]] = { s: IO.STREAM; IF ~ThNet.pd.debug THEN RETURN; s_IO.ROS[]; s.PutF["<%g", char[c]]; SELECT c FROM 'M => s.PutF["-- %g", p1]; ENDCASE; s.PutRope[">\r"]; VoiceUtils.Report[s.RopeFromROS[], $LarkDetailed, info]; }; QuickState: ARRAY LarkState OF IO.Value = [ rope["none"], rope["idle"], rope["talking"], rope["trunkSignalling"], rope["trunkTalking"], rope["trunkForwarding"], rope["trunkFlashing"], rope["failed"], rope["ringing"], rope["silence"], rope["dialTone"], rope["ringBack"], rope["busyTone"], rope["errorTone"]]; CommandsForState: TYPE = REF CommandsForStateArray; CommandsForStateArray: TYPE = ARRAY LarkState OF ROPE; telsetCommands: CommandsForState _ NEW[CommandsForStateArray _ [ NIL, -- none "Z", -- idle "SXt01Xt06Xr10XA60XB70X14", -- talking "HIX02X06X14XF01", -- trunkSignalling "HISTX02Xr10XA60XB70Xt21Xt26X14", -- trunkTalking, codec-assisted electronic mode "E3HIX02X20X24", -- trunkForwarding, trunk to remote Lark connection. "STX02Xr10XA60XB70Xt21Xt26X14", -- trunkFlashing, on-hook but otherwise trunkTalking. "Z", -- failed "RX03X06X14", -- ringing "SX14", -- silence toneStdCommand, toneStdCommand, toneStdCommand, toneStdCommand -- tones ]]; toneStdCommand: ROPE = "SX01X14X06"; monitorCommands: CommandsForState _ NEW[CommandsForStateArray _ [ NIL, -- none "Z", -- idle "LSXt01Xt06Xt03Xr10XA60XB70X14", -- talking "LHIX02X06X03X14XF01", -- trunkSignalling "LHISTX02Xr10XA60XB70Xt21Xt26Xt23X14", -- trunkTalking, codec-assisted electronic mode "LE3HIX02X20X24", -- trunkForwarding, trunk to remote Lark connection. "LSTX02Xr10XA60XB70Xt21Xt26Xt23X14", -- trunkFlashing, on-hook but otherwise trunkTalking. "Z", -- failed "RX03X06X14", -- ringing "LSX14", -- silence toneMonCommand, toneMonCommand, toneMonCommand, toneMonCommand -- tones ]]; toneMonCommand: ROPE = "LSX01X03X14X06"; speakerCommands: CommandsForState _ NEW[CommandsForStateArray _ [ NIL, -- none "Z", -- idle "E1LXt03Xt06Xr30XA60XB70X14", -- talking "LHIX02X06XF03", -- trunkSignalling "E2M1THILXr30X02Xt25Xt26X24Xt53XA60XB70", -- trunkTalking, gain-controlled digital mode "LE3HIX02X20X24", -- trunkForwarding, trunk to remote Lark connection. (need gain setting for echo?) "Z", -- trunkFlashing, on-hook for a second. "Z", -- failed "RX03X06", -- ringing "LX14", -- silence toneSpkrCommand, toneSpkrCommand, toneSpkrCommand, toneSpkrCommand -- tones ]]; toneSpkrCommand: ROPE = "LX03X14X06"; larkCommands: ARRAY ThSmartsPrivate.SwitchState OF CommandsForState _ [ telsetCommands, -- good as any for "onhook" condition telsetCommands, -- telset speakerCommands, -- speaker speakerCommands, -- sPEAKER monitorCommands, -- monitor monitorCommands -- mONITOR ]; echoStyleFD: REF _ NEW[Lark.EchoParameterRecord _[ buffer: out1, buffer2Controlled: FALSE, buffer1Controlled: TRUE, decayTime: 5, gain: [ 1024, 2048, 2048, 2048, 32767 ] ]]; echoStyleFwd: REF _ echoStyleFD; echoStyleBD: REF _ NEW[Lark.EchoParameterRecord _[ buffer: in2, buffer2Controlled: FALSE, buffer1Controlled: TRUE, decayTime: 10, gain: [ 2048, 4096, 8192, 16384, 32767 ] ]]; echoStyleNoFD: REF _ NEW[Lark.EchoParameterRecord _[ buffer: out1, -- not interesting buffer2Controlled: FALSE, buffer1Controlled: TRUE, -- FALSE, compensates for a Lark bug; restore when fixed decayTime: 5, gain: [ 32767, 32767, 32767, 32767, 32767 ] ]]; echoStyleNoFwd: REF _ echoStyleNoFD; echoStyleNoBD: REF _ NEW[Lark.EchoParameterRecord _[ buffer: in2, -- not interesting buffer2Controlled: FALSE, buffer1Controlled: TRUE, -- FALSE, compensates for a Lark bug; restore when fixed decayTime: 5, gain: [ 32767, 32767, 32767, 32767, 32767 ] ]]; echosOn: ARRAY [0..3] OF REF_[ NIL, echoStyleFD, echoStyleBD, echoStyleFwd ]; echosOff: ARRAY [0..3] OF REF_[ NIL, echoStyleNoFD, echoStyleNoBD, echoStyleNoFwd ]; LSwitches: TYPE = ThSmartsPrivate.LSwitches; LState: TYPE = ThSmartsPrivate.LState; lDevs: ARRAY LSwitches OF Lark.Device = [ crossBar, offHookRelay, aRelay, sideTone, ringEnable, revertRelay, revertHookswitch, led, spMode, crossBar--random...not used-- ]; lStateForLetter: ARRAY CHAR['A..'Z] OF LSwitches = [ none, none, none, none, none, -- A to E revert, revertHook, hook, aSwitch, hook, none, led, -- F to L none, none, none, none, none, -- M to Q ringO, sideTone, spMode, none, none, none, none, none, -- R to Y none -- Z -- ]; LSTrans: TYPE = { nop, -- nothing to do set, -- enter specified state (usu. step to recovery) without taking any other actions. zap, zpu, zpn, -- reset Lark hardware (u means unconnect first, n means silence tones first) trk, tkn, -- Set for electronic phone connection (n means silence tones first) frd, frn, -- Trunk-to-network forwarding versions of trk, tkn (frn probably doesn't exist; wrong end <>) tlk, -- like supervision, but must also adjust switching. sup, spn, -- supervision, OK to change connection, key table. (n means silence tones first) ksp, -- key supervision, OK to change key table. sgl, sgn, -- Do trunk signalling (n means silence tones first) fls, -- Flash the phone line rng, rgu, -- Set for ringing (u means unconnect first, r means repeating tone) dia, diu, -- Set for dial tone (tones should be more generic and user-programmable than this!) rbk, rbu, -- Set for ring back bzy, bzu, -- Set for busy tone err, eru, -- Set for error tone sil, -- silence tones, ksp obtains fai, -- enter failed state, by Smarts-level request. Don't complain, just do it. Make sure process goes away. X -- invalid transition; complain, then remain in present state (go idle?) }; lsTrans: ARRAY LarkState OF ARRAY LarkState OF LSTrans = [[ nop, zap, X, X, X, X, X, X, X, X, X, X, X, err ],[--non (none) X, nop, spn, sgl, trk, frd, X, fai, rng, nop, dia, rbk, bzy, err ],[--idl (idle) X, zpu, sup, X, X, X, X, fai, rgu, nop, diu, rbu, bzu, eru ],[--tlk (talking) X, zpn, X, ksp, trk, frd, X, fai, X, nop, X, X, X, X ],[--sig (trkSglng) X, zap, X, sgl, ksp, X, fls,fai, X, nop, X, X, X, X ],[--trk (trkTlkng) X, zpu, X, sgl, X, sup, X, fai, X, nop, diu, rbu, bzu, eru ],[--fwd (trkFwdng) X, zap, X, X, trk, X, sup,fai, X, nop, X, X, X, X ],[--fls (trkFlash) set, X, X, X, X, X, X, X, X, X, X, X, X, X ],[--fai (failed) X, zpn, spn, sgn, tkn, frn, X, fai, ksp, sil, dia, rbk, bzy, err ],[--rng (ringing) X, zap, tlk, sgl, trk, frd, X, fai, rng, ksp, dia, rbk, bzy, err ],[--shh (silence) X, zpn, spn, sgn, tkn, frn, X, fai, rng, sil, ksp, rbk, bzy, err ],[--dia (dialTone) X, zpn, spn, sgn, tkn, frn, X, fai, rng, sil, dia, ksp, bzy, err ],[--rbk (ringBack) X, zpn, spn, sgn, tkn, frn, X, fai, rng, sil, dia, rbk, ksp, err ],[--bzy (busyTone) X, zpn, spn, sgn, tkn, frn, X, fai, rng, sil, dia, rbk, bzy, ksp ] --err (errTone) ]; TDisconn: TYPE = { X, disconnect }; tDisconn: ARRAY LSTrans OF TDisconn = [ -- zpu, rgu, diu, rbu, bzu, eru X, X, X, disconnect, X, X, X, X, X, X, X, X, X, X, X, X, X, disconnect, X, disconnect, X, disconnect, X, disconnect, X, disconnect, X, X, X, X ]; TDoTones: TYPE = { X, doTones, stopTones }; tDoTones: ARRAY LSTrans OF TDoTones = [ -- rng, rgu, dia, diu, rbk, rbu, bzy, bzu, err, eru; zpn, tkn, spn, sgn, sil X, X, X, X, stopTones, X, stopTones, X, X, X, X, stopTones, X, X, stopTones, X, doTones, doTones, doTones, doTones, doTones, doTones, doTones, doTones, doTones, doTones, stopTones, X, X, X ]; THookState: TYPE = { X, reset, spkrTrans }; tHookState: ARRAY LSTrans OF THookState = [ -- zap, zpu, zpn; trk, tkn, tlk, spn, fls, dia, diu, rbk, rbu, bzy, bzu, err, eru, sil X, X, reset, reset, reset, spkrTrans, spkrTrans, X, X, spkrTrans, X, spkrTrans, X, X, X, spkrTrans, X, X, spkrTrans, spkrTrans, spkrTrans, spkrTrans, spkrTrans, spkrTrans, spkrTrans, spkrTrans, spkrTrans, X, X, X ]; TSwitch: TYPE = { X, switch, switchIfDiff }; tSwitch: ARRAY LSTrans OF TSwitch = [ X, X, switch, switch, switch, switch, switch, switch, switch, switch, X, switch, X, switch, switch, switch, switchIfDiff, switchIfDiff, switchIfDiff, switchIfDiff, switchIfDiff, switchIfDiff, switchIfDiff, switchIfDiff, switchIfDiff, switchIfDiff, switch, X, X, X ]; TSetFwd: TYPE = { X, setFwd }; tSetFwd: ARRAY LSTrans OF TSetFwd = [ X, X, X, X, X, setFwd, setFwd, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X ]; TLarkCall: TYPE = { X, call }; tLarkCall: ARRAY LSTrans OF TLarkCall = [ call, X, X, X, X, call, call, call, call, call, call, call, call, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X ]; ADisconnectType: TYPE = { aDisconnect }; aDisconnect: REF ADisconnectType _ NEW[ADisconnectType_aDisconnect]; ResetActionType: TYPE = { resetAction }; resetAction: REF ResetActionType _ NEW[ResetActionType_resetAction]; AFeepType: TYPE = RECORD [ initialDelay: CARDINAL _ pd.waitForTelco, on: CARDINAL _ pd.telcoMinOn, off: CARDINAL _ pd.telcoMinOff, audible: BOOL_FALSE, digits: Lark.CommandEvents_NIL ]; ANoTonesType: TYPE = { aNoTones }; aNoTones: REF ANoTonesType _ NEW[ANoTonesType_aNoTones]; ATonesDoneType: TYPE = RECORD [ event: Lark.Event ]; AToggleLEDType: TYPE = { aToggleLED }; aToggleLED: REF AToggleLEDType _ NEW[AToggleLEDType_aToggleLED]; ledToggler: Lark.CommandEvents _ NEW[Lark.CommandEventSequence[1]]; ViewCmd: Commander.CommandProc = TRUSTED { Nice.View[pd, "Lark Out PD"]; }; Commander.Register["VuLarkOut", ViewCmd, "Program Management variables for Lark Output"]; }. $ÔLarkOutImpl.mesa Copyright c 1985, 1986 by Xerox Corporation. All rights reserved. Polle Zellweger (PTZ) November 4, 1985 8:42:01 pm PST Last modified by D. Swinehart, November 25, 1986 4:06:51 pm PST Declarations Whether to let RPC calls from server to Lark time out. The default is to do so iff the database indicates the Lark is not in operational mode. Determines what to tell the Lark to do about server timeouts. External Procedures Relevant only for trunk calls. The hosts are different, so the local trunk is communicating to a remote Etherphone. See LarkSmartsSupImpl for more discussion of these connections. We don't handle conferences involving trunks, thus the numParties=2 test. Higher level code assures this. In this state, the LED flashes to let the user know why the switch hook and attempts to place calls don't work. Each select statement combines cases to execute a subset of the required actions efficiently. If trunkTalking was requested, we must enter either trunkTalking or trunkForwarding, depending on whether the other end of the connection is on the same machine. When leaving talking state but not going idle, must explicitly take down Ethernet connection. Does this ever happen? Queue up request to eliminate connections. Select tone/tune specifications. Go offhook and enter speakerphone mode if noises need to be heard and phone isn't offhook Go back onhook when idling from spkr (not sPkr) or monitor mode. Must follow switching, but calculations must precede it. Otherwise we'd be transmitting stuff for no reason. <> Server to Lark Lark to Server Internal Procedures In a loop, keep the state of the Lark up to date. Awakens itself whenever any pending tone is otherwise likely to time out. Awakened by EnterLarkState whenever the state of tones, switches, and the like might have to change. When initializing the supervisor process, multicasting should already be off for this host. But be as careful as possible here: stop any that's detectably going on, and in any case, turn off multicast forwarding for this host. If conferencing, set up multicasting for this host, first. Transmit buffer Receive buffers See ThsmartsPrivate.LarkCall < revert. Remember to change 2d parameter next time Lark.mesa changes.>> Queue is a FIFO list of REFs, with a lastAction pointer to aid in rapid enqueuing. See Hardware Switching Tables below for interpretations of these command sequences. Parameters determine whether this crossbar specification should be obeyed depending on outside influences, like "line(A/B) mode" or global indications of whether automatically-generated touch-tones should be heard by the caller. Hardware Switching Tables Interpretation of the command string characters: En-- echo mode; n IN [0..3); selects echoStyleStd (default), ...FD, ...BD, or ...Fwd F -- T/R lead reversion G -- A/A1 hookswitch control reversion H -- Assert Telewall hookswitch I -- Assert A/A1 to Telewall J -- Assert Telewall hookswitch, maybe (depends on boolean variable) L -- Lights led l -- Flashes led if trunk is forwarding a call. R -- overrides volume control for ringing through speaker S -- enables telset sidetone T -- spMode; configures codecs for electronic trunk action Xij -- connects crossbar input i to output j Xmij -- connects crossbar input i to output j, conditionally Conditions: A -- only in lineA mode (input comes from line 1 in instead of telset or microphone) B -- only in lineB mode (input comes from line 2 in instead of telset or microphone) r -- only in non-radio (standard, non-lineA/B) mode t -- inhibit in transmit-only mode (server stuff) F -- only if feeping (touch-tone signalling) is to be audible. Mn -- voiceMode; n IN [0..2); selects program O3I1 (default), O2I2, or O1I1 Z -- Resets hardware and crossbar Radio mode: input comes from line 1 in instead of telset or microphone Crossbar Connections: Port Input Output 0 dec1 co1 1 Xmtr Rcvr 2 from Telewall to Telewall 3 mike speaker 4 silence DTMF receiver 5 dec2 co2 6 line 1 in line 1 out 7 line 2 in line 2 out larkCommands: ARRAY ThSmartsPrivate.SwitchState OF CommandsForState _ [ telsetCommands, -- good as any for "onhook" condition telsetCommands, -- telset speakerCommands, -- speaker speakerCommands, -- sPEAKER monitorCommands, -- monitor monitorCommands -- mONITOR ]; Telset "Z", -- trunkFlashing, on-hook for a second. Monitoring Telset "Z", -- trunkFlashing, on-hook for a second. Speakerphone "STX02X10X21X26X14", -- trunkFlashing, on-hook but otherwise unchanged. Front Door call using Speakerphone Back Door call using Speakerphone Standard FD or BD handset mode, no forwarding Standard FD or BD handset mode, no forwarding State tables non idl tlk sig trk fwd fls fai rng shh dia rbk bzy err _new old \/ Subtransition codes and tables zap, zpu, zpn, trk, tkn, frd, frn, tlk, spn, sgl, sgn, fls; rng, rgu, dia, diu, rbk, rbu, bzy, bzu, err, eru trk, tkn nop, trk, tkn, frd, frn, tlk, sup, spn, ksp Queued specifications for Supervisor ASpeechDoneType: TYPE = RECORD [ indexMarker: INT ]; Swinehart, June 14, 1985 5:22:47 pm PDT Repair Echo stuff changes to: resetAction (local of LarkSupervisor) explicitly request resets on Z, LarkSupervisor ditto, QueueCommandSequence larkCommands, echosOn, echosOff, ZapEchosType, zapEchos, ANoTonesType, echoStyleNoFD, echoStyleNoBD Swinehart, July 16, 1985 2:15:11 pm PDT Fixes to trunkSignalling, trunkForwarding changes to: EnterLarkSt Swinehart, August 6, 1985 2:12:11 pm PDT Merge with PTZ Prose additions changes to: EnterProseQueue, ASpeechDoneType, ViewCmd Polle Zellweger (PTZ) July 3, 1985 7:11:31 pm PDT changes to: DIRECTORY, EnterLarkSt, IntIDQueue, IntIDTranslate, IntIDTranslateBody, EnterIntIDQueue (local of LarkSupervisor), RemoveIntIDQueue (local of LarkSupervisor), LarkSupervisor, HandleProseOutput Polle Zellweger (PTZ) July 11, 1985 6:20:12 pm PDT changes to: indexMarkerEnd(public), maxClientMarker(public), LarkSupervisor, ps (local of LarkSupervisor), pd (local of LarkSupervisor), ProseControlDone, EnterProseQueue(replaced EnterIntIDQueue) removed: RemoveIntIDQueue (function now in LarkInImpl), minClientMarker, minControlMarker, maxControlMarker, speechDoneMarker, DIRECTORY, pResetConfirmOK, cmdLeader, indexMarkerLen, SpeakText (local of LarkSupervisor) Polle Zellweger (PTZ) July 16, 1985 6:40:42 pm PDT Fix multiple packets bug. changes to: LarkSupervisor -- add proseActive & handle incoming speechDoneMarkers correctly=> SpeakText (local of LarkSupervisor), ps (local of LarkSupervisor), pd (local of LarkSupervisor) Polle Zellweger (PTZ) July 18, 1985 5:18:49 pm PDT new version of SpeakText preloads Prose and then sends only 1 packet at a time. changes to: DIRECTORY, LarkOutImpl, LarkSupervisor, SpeakText (local of LarkSupervisor), pd (local of LarkSupervisor), SpeakText, ps (local of LarkSupervisor) Polle Zellweger (PTZ) July 19, 1985 6:34:34 pm PDT Make sure not to break in the middle of a client marker!! changes to: SpeakText (local of LarkSupervisor) Polle Zellweger (PTZ) July 30, 1985 4:41:39 pm PDT Lark now has its own copy of newProses; must prune out started and finished reports. changes to: EnterLarkSt Polle Zellweger (PTZ) August 19, 1985 5:03:15 pm PDT Handle Prose flushing. changes to: maxTextPktLen, maxPkts, numPkts, LarkSupervisor, SpeakText (local of LarkSupervisor), ps (local of LarkSupervisor), pd (local of LarkSupervisor), FilterText, ProseControlDone Polle Zellweger (PTZ) August 27, 1985 8:58:36 pm PDT Move local variables from LarkOutImpl.LarkSupervisor into LarkInfo record. These variables are locked by the serial nature of the Lark Supervisor rather than by explicit ENTRY procedures. Reset Prose at Lark startup & idle. changes to: DIRECTORY, ProseCmd, ProseControlDone, minControlMarker, LarkSupervisor, SpeakText (local of LarkSupervisor), ps (local of LarkSupervisor), pd (local of LarkSupervisor), resetAction (local of LarkSupervisor), FilterText, ProseFlush Swinehart, October 28, 1985 11:56:38 am PST Log => VoiceUtils, Handle => ID changes to: DIRECTORY, LarkOutImpl, ConvDesc, SmartsID, EnterLarkSt, EnterProseQueue, QueueLarkAction Zellweger (PTZ), November 4, 1985 8:39:52 pm PST Remove timeout waiting for text-to-speech to report; leave the one for tones in. changes to: WaitForAction (local of LarkSupervisor) Swinehart, April 10, 1986 10:05:07 am PST Revise telset/speakerswitch behavior to integrate $monitor mode, improve things. changes to: DIRECTORY, SmartsID, PD, EnterLarkSt, FlashWait, QueueCommandSequence, CommandsForState, CommandsForStateArray, larkCommands, telsetCommands, monitorCommands, speakerCommands Swinehart, May 17, 1986 5:58:28 pm PDT Cedar 6.1 changes to: LarkSupervisor, StopMulticast Swinehart, May 25, 1986 10:10:43 pm PDT Lark => LarkOps changes to: DIRECTORY, LarkOutImpl Swinehart, October 21, 1986 5:48:38 pm PDT Total eradication of remnants of Prose code. Introduction of LarkCall case, to allow things like synthesizers to participate. See LarkSynthesizer(impl) Swinehart, November 25, 1986 4:06:02 pm PST Remote $recovering state. It was never used. Added separate failed bit to LarkInfo. Use to determine when no action is needed. On failure, issue an input Failure event. changes to: EnterLarkSt, Fail, WaitForAction (local of LarkSupervisor), QuickState, telsetCommands, monitorCommands, speakerCommands, LSTrans, lsTrans Ê$˜šœ™Icodešœ Ïmœ7™BK™5Jšœ?™?J˜—šÏk ˜ Jšœžœ ˜*Jšžœ˜Jšœ žœ˜*Jšœžœðžœ:˜¸J˜4Jšœ žœ%˜3J˜J˜ J˜;J˜Jšœžœ3˜@J˜Jšœžœžœ˜#Jšžœžœ˜Jšœ žœ˜*Jšœžœ˜Jšœžœ˜Jšœžœ˜$Jšœžœžœžœ ˜1šœžœ˜Jšœe˜e—Jšžœžœ ˜Jšœ žœ˜&J˜J˜—šœ ž œžœžœ˜:šž˜Jšœ žœ5žœžœ ˜i—Jšžœ˜Jšžœžœ˜J˜—™ J˜Jšœ žœ˜*Jšœ žœ˜*Jšœ žœ˜,Jšœ žœ˜-Jšœ žœ˜.Jšœ žœ˜!Jšžœžœ žœ˜Jšœžœ ˜J˜2Jšœžœ ˜*Jšžœ ˜—Jšžœ ˜—Jšžœ˜—š žœžœžœžœžœ˜=Jšžœžœžœ$žœ˜VJ˜—J™’J˜J™]šžœž˜JšœžœŸa˜nJšœ"žœ˜,Jšžœžœžœ8žœ˜xšœ˜JšœU˜UJšœžœ˜Jšœžœ˜Jšœžœ˜JšžœŸ2˜KJšžœ˜Jšœ˜—Jšœžœžœ˜>Jšžœ˜—šžœž˜!J™¡Jšœ žœžœžœ˜HJ˜*J˜—J˜J™]J™š žœ žœžœžœ žœžœ˜Q™*Jšžœžœ˜'Jšœ#˜#J˜——J™ šœ žœž˜JšœŸ˜,Jš œ žœ žœžœ žœ˜Jšžœ˜—Jšœ˜—J˜Jš  œž œžœ˜9J˜š  œžœžœžœ5˜QJ˜šžœž˜šœŸ˜Jšœ˜Jšžœ žœžœ˜.Jšœ žœ˜%J˜—šžœŸ˜#Jšœžœ)˜B——J˜J˜—š   œžœžœžœžœ˜9Jšžœžœžœ˜Jšœ ž œ˜Jšžœžœžœžœ˜JšœGŸ˜WJ˜Jšžœ ˜J˜šžœžŸ˜=J™1šœ˜JšœN˜N——J˜—J˜š  œžœžœžœžœ˜7Jšžœžœžœ˜Jšœ ž œ˜Jšžœžœžœžœ˜š žœžœ#žœ!žœžœž˜~J˜Jšœ%˜%JšœGŸ˜WJšžœ ˜Jšžœ˜—Jšœžœ˜J˜J˜—š  œžœžœ žœ˜Ašœ/˜/Jšžœžœ.˜6—J˜J˜—š   œžœžœžœžœ˜FJšœ%žœ˜G™˜ J˜J˜0šœžœž˜-šœ4˜4Jšžœ žœžœ žœ ˜8————™JšœM˜Mšœ"žœž˜KJš œ žœ žœ!žœžœ˜P—Jšœ2˜2šœ"žœž˜KJš œ žœ žœ!žœžœ˜P—J˜Jšœ%˜%—J˜—J™—šœ™J˜Jš œžœžœ!˜2š œžœžœ˜'Jšœ˜Jšœ9˜9Jšž œ˜Jšœ˜J˜—š œž œ˜/JšœV™VJšœT™TJšœ6™6Jšžœžœžœ˜Jšœžœ˜ J˜š  œžœžœžœžœžœžœ˜LJšžœžœžœ˜šž˜Jšœžœžœžœ˜#Jšžœžœžœžœ˜*šžœžœžœ˜Jšœ˜J˜Jšžœ˜ J˜—JšœL˜LJšžœ˜šžœžœžœ˜Jšžœžœžœ Ÿ˜BJšžœžœ˜ J˜—Jšžœ˜—J˜—J˜šžœžœž˜Jšœžœ5žœ˜R—šžœ žœž˜šœ žœ˜+J˜J˜J˜J˜J˜ Jšœ žœžœžœ˜1J˜'J˜'Jšœ˜——šžœ˜ Jšœ(˜(Jšœ%˜%JšœL˜LJšœ˜—™ãJ˜J˜O—šžœžœž˜'JšŸ$˜$šžœ˜šžœ˜Jšœ&žœ ˜5—šžœ˜ Jšœ1žœ ˜@—Jšœ˜—J˜š œžœ žœŸ+˜MJšžœžœžœžœ˜%Jšœ0˜0šœ˜Jšžœžœžœ˜I—JšœD˜DJšœ2˜2Jšœ\˜\J˜J˜—šžœžœž˜šœžœ˜šžœ žœžœ˜J˜Jšœ:Ÿ˜Ršžœžœžœž˜*Jšœ:Ÿ ˜ZJšœžœ˜Jšžœ˜—Jšžœžœ˜.Jšœ žœ˜J˜——˜J˜(Jšœ žœ˜&šžœžœ˜J™:J˜Jšžœ žœ8˜JJ™J˜J˜$J˜2Jšžœ žœ4˜FJšœ(Ÿ˜7J˜6J™J˜šžœžœžœž˜%J˜#Jšžœ žœ3˜EJšœ(Ÿ˜7J˜5Jšœžœ˜"Jšžœ˜—J˜—J˜—šœ˜šžœžœžœžœ˜*J˜J˜:Jšž œ˜J˜—Jšœ;˜;Jšžœ˜ J˜—šœ˜Jšœ˜Jšœ(˜(Jšœžœ˜Jšœ˜—šœ=˜=Jšœ™—š œžœžœžœžœ˜5Jšžœ$žœžœ˜7š žœžœžœžœž˜˜>J™P—Jšžœžœ˜.Jšžœžœžœ!˜FJ˜—šœ)˜)JšœK˜K—šœ&˜&JšœF˜F—˜Jšžœ žœžœ/˜C—šœ žœ˜Jšžœ žœžœžœ˜šžœ8ž˜>JšœJžœ˜Q—šœ˜JšœI˜IJšœ)žœ˜I—J˜—Jšžœ˜—Jšžœ˜Jšžœ˜—Jšœžœ˜J˜J˜—š œžœ0˜DJšžœžœžœ˜Jšžœžœ˜.Jš žœ žœžœžœžœžœ˜@˜GJšœ?˜?—šžœžœ˜ šœI˜IJšœ2˜2—Jšžœ˜J˜—JšœW˜WJšœžœ˜J˜J˜—š  œžœžœžœ˜:Jšžœžœžœ˜"Jšœ_˜_J˜OJšœžœ˜J˜J™—Jšœ žœD™Sš œžœžœžœ˜Jšžœžœžœžœ˜(Jšœ žœ˜Jšœžœ˜Jšœžœ˜Jšœžœ˜J˜J˜'J˜Jšœžœ˜ Jš žœ žœžœžœŸ ˜*J˜J™Sšžœžœ ž˜Jš žœžœ žœžœžœžœ˜Qšžœž˜ Jšœ4Ÿ#˜Wšœ ŸJ˜VJ˜"Jš œ žœžœžœžœ˜(Jšœžœ˜ Jšœžœžœ˜šžœž˜JšžœžœŸ˜=J™äJšœžœžœžœ˜1Jšœžœžœžœ˜1Jš œžœžœžœžœ˜LJšœžœžœžœŸ!˜MJšœžœžœžœŸ˜EJšžœ žœŸ'˜>—Jšžœ žœ)˜9Jšœ˜Jšœ žœ˜(Jšžœžœ.˜:Jšœžœ ˜(J˜Jšžœ˜Jšœ˜—˜ Jšœ/˜/J˜+Jšœ˜—˜ šœžœž˜7J˜J˜J˜Jšžœžœ˜—Jšœ˜—šžœ˜ šžœžœ žœ(˜=Jšžœ˜—Jšžœžœ+˜JJ˜——Jšžœ˜—Jšžœžœžœ˜!šžœ&žœ žœž˜@Jšœ)˜)—š žœ žœžœžœŸ/˜OJ˜ šžœ&ž˜,Jšœ9˜9—š žœž œ žœžœ ž˜RJšœ6žœ˜>—š žœžœžœžœžœ"žœ˜BJš œ žœžœžœžœžœ˜BJš œ žœžœžœžœžœ˜Hš žœžœžœžœžœž˜8˜Jš œ žœžœžœžœ˜8Jšžœ ˜—Jšžœ˜—Jšœžœ˜ —Jšžœ žœ žœžœ˜'Jšžœ žœ žœ&žœ˜N—J˜J˜J˜$J˜J˜—Jš œžœžœžœ žœžœžœ ˜EJ˜š   œžœ žœžœžœ˜AJšœžœžœ žœ˜-Jšœ˜Jšœ žœ˜Jšœžœ˜Jšœžœ˜šžœ žœžœ ž˜Jšœžœ˜šžœž˜ Jšžœ žœ)˜8Jšœžœ žœžœ˜NJšœžœ˜J˜J˜Jšžœ$˜&JšžœŸ˜'—Jšžœ˜—Jšœžœ%˜-Jšœ˜J˜ šžœ žœžœ ž˜Jšœžœ˜Jšœžœ ˜šžœž˜ Jšžœžœ˜,Jšžœžœ˜,Jšœ˜Jšœ˜Jšžœ$˜&Jšœžœ žœžœ ˜2Jšžœ˜—Jšžœ žœžœ˜J˜J˜Jšžœ˜—J˜J˜—š œž œ˜Jšžœžœžœ˜ Jšœžœ˜šœ žœ-žœ˜@šœ%ž œ˜/Jšœ%˜%Jšœ*˜*——šœ žœ-žœ˜@šœ%ž œ˜/Jšœ6˜6Jšœ;˜;——šœ žœ-žœ˜Ašœ%ž œ˜/Jšœ7˜7Jšœ<˜<——šœžœ-žœ˜Dšœžœž œ˜/Jšœ(˜(Jšœ-˜-——J˜J˜—š  œžœžœžœžœ˜PJšœžœžœ˜ Jšžœžœžœ˜Jšœžœžœ˜ J˜šžœž˜ Jšœ˜Jšžœ˜—J˜J˜8J˜—šœ žœ žœžœ ˜+J˜EJ˜wJ˜IJ˜——™J˜™0JšžœŸR™TJ™J™&J™J™J™DJ™J™/J™9J™J™:J™,™<™ J™TJ™TJ™3J™1J™>——J™K™!J™FJ™——™Itable2šÏi™Lš¢ ™ Lš¢ ™ Lš¢™Lš¢™Lš¢™Lš¢ ™ Lš¢™Lš¢™—J˜Jšœžœžœž˜3Jš œžœžœ žœžœ˜6J˜šœžœžœ™GJšœŸ%™5JšœŸ ™JšœŸ ™JšœŸ ™JšœŸ ™JšœŸ ™Jšœ™J™—šœ#žœ˜>Jšœ™šœžœŸ˜JšœŸ˜ JšœŸ ˜&JšœŸ˜%Jšœ"Ÿ/˜QJšœŸ4˜Ešœ Ÿ5˜UJšœŸ'™,—JšœŸ ˜JšœŸ ˜JšœŸ ˜Jšœ?Ÿ˜GJ˜Jšœžœ˜$—J˜—šœ$žœ˜?Jšœ™šœžœŸ˜JšœŸ˜ Jšœ!Ÿ ˜+JšœŸ˜)Jšœ'Ÿ/˜VJšœŸ4˜Fšœ%Ÿ5˜ZJšœŸ'™,—JšœŸ ˜JšœŸ ˜Jšœ Ÿ ˜Jšœ?Ÿ˜GJ˜Jšœžœ˜(—J˜—šœ$žœ˜?Jšœ ™ šœžœŸ˜JšœŸ˜ JšœŸ ˜(JšœŸ˜#Jšœ*Ÿ-˜WJšœŸR˜dšœŸ'˜,JšœŸ2™G—JšœŸ ˜Jšœ Ÿ ˜JšœŸ ˜JšœCŸ˜KJšœ˜Jšœžœ˜%—J˜—šœžœžœ˜GJšœŸ%˜5JšœŸ ˜JšœŸ ˜JšœŸ ˜JšœŸ ˜JšœŸ ˜Jšœ˜J™—šœ žœžœ˜2J™"J˜ Jšœžœ˜Jšœžœ˜J˜ J˜'Jšœ˜—Jšœžœ˜ J˜šœ žœžœ˜2J™!J˜ Jšœžœ˜Jšœžœ˜J˜J˜(J˜—J˜šœžœžœ˜4J™-J˜ Jšœžœ˜JšœžœŸ:˜SJ˜ J˜+J˜—Jšœžœ˜$J˜šœžœžœ˜4J™-J˜Jšœžœ˜JšœžœŸ9œ˜SJ˜ J˜+J˜J˜—Jš œ žœžœžœžœ+˜MJš œ žœžœžœžœ1˜TJ˜—™ J˜Jšœ žœ˜,Jšœžœ˜&šœžœ žœ˜)JšœjŸœ˜‚—šœžœžœ žœ˜4JšœŸ ˜'Jšœ4Ÿ ˜=JšœŸ ˜'Jšœ7Ÿ ˜@JšœŸ˜ J˜J˜—šœ žœ˜JšœŸ˜JšœŸR˜WJšœŸM˜\Jšœ ŸD˜NJšœ ŸbÐckŸ£Ÿ˜tJšœŸ4˜9Jšœ ŸQ˜[JšœŸ+˜0Jšœ Ÿ4˜>JšœŸ˜Jšœ ŸD˜NJšœ ŸT˜^Jšœ Ÿ˜Jšœ Ÿ˜Jšœ Ÿ˜ JšœŸ˜"JšœŸj˜oJšœŸH˜JJ˜J˜—š ¡ Ðfk¡ ¤¡¤¡ ¤¡ ˜;Jš¡O™OJš¡GÐcf ˜SJš¡G¥ ˜SJš¡G¥˜VJš¡G¥˜WJš¡G¥˜WJš¡G¥˜WJš¡G¥˜WJš¡G¥˜UJš¡G¥˜VJš¡G¥˜VJš¡G¥˜WJš¡G¥˜WJš¡G¥˜WJš¡F¥˜VJ˜—J˜J™J˜#šœG˜GJ˜•—J˜J˜+šœ˜J˜ÃJ˜—J˜+šœ„˜„J˜Û—J˜J˜,šœ%˜%Jšœm™mJ˜ŽJ˜—J˜J˜šœ%˜%Jšœ™J˜iJ˜—J˜šœ žœ žœ˜)Jšœ+™+J˜zJ˜——™$J˜J˜(Jšœ žœžœ˜DJ˜J˜(Jšœ žœžœ˜DJ˜šœ žœžœ˜Jšœž œ˜)Jšœžœ˜Jšœžœ˜Jšœ žœžœ˜Jšœž˜J˜J˜—J˜"Jšœ žœžœ˜8J˜šœžœžœ˜J˜J˜—J˜šœžœžœ™ Jšœ ž™J™J™—J˜&Jšœ žœžœ˜@Jšœ!žœ˜CJ˜šœ!žœ˜*J˜Jšœ˜—JšœY˜YJ˜—™'K™KšœPÏrœ¦z™à—K™™'K™)Kšœ ¦ ™—™(K™Kšœ ¦)™5—™1Kšœ ¦Wœ¦œ¦#™Ì—™2Kš œ ¦œ¦œ¦œ¦œ¦#œ™ÄKšœ ¦œ¦‰œ™Ù—™2K™Kš œ ¦œC¦ œ¦œ¦œ™½—™2K™OKšœ ¦1œ¦œ¦œ™ž—™2K™9Kšœ ¦ œ™/—™2K™TKšœ ¦ ™—™4K™Kš œ ¦:œ¦œ¦œ¦ œ¦™º—™4K™áKš œ ¦Rœ¦œ¦œ¦ œ¦™ó—™+K™Kšœ ¦Y™e—™0K™PKšœ ¦ œ™3—™)K™PKšœ ¦®™º—™&K™ Kšœ ¦™)—™'K™Kšœ ¦™"—™*K™™—™+K™¬Kšœ ¦ œ¦P™–—K™—…—}Æ