Definitions
ROPE: TYPE = Thrush.ROPE;
ConvDesc: TYPE = PhSmarts.ConvDesc;
ConvEvent: TYPE = Thrush.ConvEvent;
ConversationID:
TYPE = Thrush.ConversationID;
nullConvID: ConversationID=Thrush.nullConvID;
NB : TYPE = Thrush.NB;
OpenConversations: TYPE = PhSmarts.OpenConversations;
PhoenixInfo: TYPE = PhSmarts.PhoenixInfo;
SmartsID: TYPE = Thrush.SmartsID;
StateInConv: TYPE = Thrush.StateInConv;
PartyInfo: TYPE ~ ThParty.PartyInfo;
PartyID:
TYPE = Thrush.PartyID;
nullID: RefID.ID = Thrush.nullID;
PD: TYPE = PhSmarts.PD;
serverInstance: Rope.ROPE ¬ NIL;
WhatNeedsDoing: TYPE = ATOM;
whatNeedsDoingIf:
ARRAY Thrush.StateInConv
OF
ARRAY Thrush.StateInConv
OF WhatNeedsDoing ¬ [
If we're in the state identified by the row, and someone else in the conversation reports a transition onto the state identified by the column, what should we do?
never idle failed resrv pars init notif rback ring canAc activ inact
[ $imp,
$frgt,
$frgt,
$frgt,
$frgt,
$frgt,
$frgt,
$frgt,
$frgt,
$frgt,
$frgt,
$frgt],
--neverWas
(Clip this table to view without these comments.)
This situation arises when we've forgotten about the conversation that somebody else is still reporting on.
[ $imp, $noop, $noop, $noop, $noop, $noop, $noop, $noop, $noop, $noop, $noop, $ntiy ], -- idle
[ $imp, $noop, $noop, $noop, $noop, $noop, $noop, $noop, $noop, $noop, $noop, $ntiy ], -- failed
[ $imp, $imp, $imp, $imp, $imp, $imp, $imp, $imp, $imp, $imp, $imp, $imp ],
-- reserved
The actions of other parties are not of interest to us yet, since they're not in this conv.
[ $imp, $imp, $imp, $imp, $imp, $imp, $imp, $imp, $imp, $imp, $imp, $imp ],
-- parsing
Ditto.
[ $imp,
$idle, $noop, $invl, $invl, $invl, $xrep, $xrep,
$rback,
$actvd,
$actvd,$actvd ],
-- initiating
They can either enter ringing to indicate interest, or go active without ringing
[ $imp,
$idlerg,$noop,$invl, $invl, $invl, $xrep, $noop, $noop, $ntiy, $noop, $ntiy ],
-- notified
We don't expect to hear from others while we're deciding whether to play
[ $imp,
$idle, $noop, $invl, $invl, $invl, $noop, $xrep, $noop, $ntiy,
$actv,
$actvd ],
-- ringback
They have earlier expressed interest noopringing), and are now joining the fray
[ $imp,
$idlerg,$noop,$invl, $invl, $invl, $xrep, $xrep, $noop, $ntiy,
$ckrg, $ntiy ],
-- ringing
The only thing that interests us here is everybody else quitting.
[ $imp, $idle, $noop, $invl, $invl, $invl, $xrep, $xrep, $noop, $ntiy, $ckrg, $ntiy ], -- canActivate
[ $imp, $idle, $noop, $invl, $invl, $invl, $xrep, $xrep, $noop, $ntiy, $reac, $deac ], -- active
[ $imp, $idle, $noop, $invl, $invl, $noop, $noop, $noop, $noop, $ntiy, $reac, $deac ], -- active
[ $imp, $idle, $invl, $invl, $invl, $invl, $xrep, $xrep, $noop, $ntiy, $ntiy, $ntiy ] -- inactive (current )
];
Unique ID for actions
actionID: INT ¬ 0;
Substitution: PUBLIC ENTRY PROC [shh: Thrush.SHHH, convEvent: Thrush.ConvEvent, oldPartyID: Thrush.PartyID, newPartyID: Thrush.PartyID] = {};
CheckIn:
PUBLIC
ENTRY
PROC[
shh: Thrush.SHHH, credentials: Thrush.Credentials,
voicePath: BOOL, reason: Thrush.Reason, remark: ROPE, nextScheduledCheck: INT ] = {
ENABLE UNWIND => NULL;
localRemark: ROPE¬NIL;
connected: BOOL ¬ TRUE;
enabled: BOOL ¬ phoenixInfo.enabled;
phoenixInfo.nextScheduledCheck ¬ nextScheduledCheck;
SELECT reason
FROM
$goodbye => {
enabled ¬ connected ¬ FALSE;
localRemark ¬ "Permanent disconnect requested by server";
};
$trylater => {
localRemark ¬ "Temporary disconnect requested by server";
connected ¬ FALSE;
};
$welcome, $hello => connected ¬ TRUE;
ENDCASE;
[]¬PhSmarts.RecordSystemStateFromSmartsReport[
remark: localRemark, connected: connected, enabled: enabled, voicePath: voicePath, remoteRemark: remark];
NOTIFY phoenixInfo.pollCondition;
};
Progress:
PUBLIC
ENTRY
PROC [shh: Thrush.
SHHH, convEvent: Thrush.ConvEvent] = {
Some party has changed state in a conversation we know about.
Three cases:
Another smarts initiated a state change for this party, and we're not receptive.
(For now, when we don't know about that conversation and are already in another)
Another smarts initiated a change for this party, and we're receptive.
(New conversation and we're idle or it's a conversation we're in already)
Another party changed state in a conversation we know about.
ENABLE UNWIND => NULL;
partyInfo: ThParty.PartyInfo;
whatNeedsDoing: WhatNeedsDoing;
nb: Thrush.NB;
reason: Thrush.Reason;
refAny: REF ANY;
cInfo: ThParty.ConversationInfoRec;
numParties: INT;
numActive: INT;
convID: ConversationID = convEvent.self.convID;
cDesc: ConvDesc;
info: PhoenixInfo ¬ PhSmarts.phoenixInfo;
VoiceUtils.ReportFR["Progress Called: myState=%g, otherState=%g, %g", $Smarts, info, [rope[stateRope[convEvent.self.state]]], [rope[stateRope[convEvent.other.state]]], [rope[IF convEvent.self.partyID=convEvent.other.partyID THEN "(me)" ELSE "(somebody else)"]]];
IF info=NIL THEN { Problem["No Smarts for SmartsID %g", NIL, IO.card[convEvent.self.smartsID]]; RETURN; };
[nb, cDesc] ¬ GetInfo[convEvent.self];
IF nb#$success
THEN {
IF cDesc#
NIL
THEN NoteNewState[cDesc, convEvent];
RETURN; };
Not at all sure what the implications of doing this are. Hope GetInfo doesn't fail.
cInfo ¬ cDesc.cInfo;
partyInfo ¬ cDesc.partyInfo;
numParties ¬ cInfo.numParties;
numActive ¬ cInfo.numActive;
cDesc.convMedia ¬ FetchAtom[cInfo.convAttributes, $Media];
cDesc.doingAudio ¬ cDesc.convMedia#$Video;
cDesc.doingVideo ¬ cDesc.convMedia#$Audio;
cDesc.expectedMedia ¬ FetchAtom[cInfo.convAttributes, $ExpectedMedia];
cDesc.actualMedia ¬ FetchAtom[cInfo.convAttributes, $ActualMedia];
cDesc.isConference ¬ numParties > 2;
Added temporarily *****
Here we should also check whether there is already a video conversation in progress. If it is, then we have to decide the actual media of the call or reject the call.
IF cDesc.doingVideo THEN
IF ~PhSmarts.VideoHardwareInUse[cDesc] THEN {
MacawProc.Initialize[];
MacawProc.InitializeMacaw[partyInfo: partyInfo, isConference: cDesc.isConference];
}
ELSE -- Reject the call --;
IF convEvent.self.partyID = convEvent.other.partyID
THEN {
-- own state changed
NoteNewState[cDesc, convEvent]; -- Existing conv. or notif. of new one.
RETURN;
};
Someone else's state changed in a conv. we're interested in; see if it means anything to us!
whatNeedsDoing ¬ whatNeedsDoingIf[convEvent.self.state][convEvent.other.state];
SELECT whatNeedsDoing
FROM
$noop, $ntiy => NULL;
$imp => ERROR;
$xrep => Problem["Didn't expect state change report", info];
We don't expect reports of state changes like $notified and $ringback to be reported to us unless it's us.
$frgt => PhSmarts.ForgetConv[cDesc];
$invl => {
Problem["Invalid State Transition", info];
ChangeState[cDesc: cDesc, desiredState: $failed, reason: $error, comment: "System Error: Invalid State Transition" ];
};
$idle => {
Somebody just quit. If everybody else has quit, or if the moderator of the meeting conversation has quit, then quit too. Otherwise, if the conversation is not of meeting type, then remove that participant from the list of senders maintained in VoiceProtocol.
reason ¬ IF convEvent.reason # NIL THEN convEvent.reason ELSE $terminating;
IF (cInfo.numParties - cInfo.numIdle) <= 1
OR (cInfo.convType = $meeting
AND convEvent.other.partyID = cInfo.moderator)
THEN
This means that we are the last party to leave the conversation. Quit, too.
ChangeState[cDesc: cDesc, desiredState: IF reason=$terminating THEN $idle ELSE $failed, reason: reason, reportToAll: reason=$terminating];
};
$idlerg => {
We are ringing, and someone just quit. If it was the originator, quit too.
Otherwise, ignore the event.
reason ¬ IF convEvent.reason#NIL THEN convEvent.reason ELSE $terminating;
IF cInfo.originator = convEvent.other.partyID
THEN
ChangeState[cDesc: cDesc, desiredState: IF reason=$terminating THEN $idle ELSE $failed, reason: reason, comment: "Originator left", reportToAll: reason=$terminating];
};
$rback => ChangeState[cDesc: cDesc, desiredState: $ringback];
$actv, $actvd => ChangeState[cDesc: cDesc, desiredState: $active, reportToAll:TRUE];
$ckrg =>
NULL;
We are ringing and someone just went into an active state. Check whether we should continue ringing or stop. This should be implemented - but later.
$reac =>
Someone has become active, we're already active. If not a meeting, add new party.
IF convEvent.other.partyID # partyInfo.parties[partyInfo.ixOriginator].partyID
THEN {
NoteNewState[cDesc, convEvent]; -- make sure we're up to date in compliance.
};
$deac =>
Someone has gone into an inactive (held) state, we're active. Not clear what we should do.
NoteNewState[cDesc, convEvent]; -- assure compliance.
IF cDesc.doingVideo THEN MacawProc.DeActiveProc[];
ENDCASE => ERROR;
};
CheckInitiation:
ENTRY
PROC [cDesc: ConvDesc] ~
TRUSTED {
ENABLE UNWIND => NULL;
nb: NB;
c: CONDITION;
Process.SetTimeout[@c, Process.SecondsToTicks[pd.timeoutInitiating]];
WAIT c;
IF cDesc.situation.self.state # $initiating THEN RETURN;
If no response has been received in the timeout period, then terminate the request - since something must be wrong.
ChangeState[cDesc: cDesc, desiredState: $idle, comment: "Initial Connection Timeout: Party can't be reached", reportToAll: TRUE];
};
ReportAction:
PUBLIC
ENTRY
PROC [shh: Thrush.
SHHH, report: Thrush.ActionReport] = {
ENABLE UNWIND => NULL;
nb: NB;
cDesc: ConvDesc;
myName: Rope.ROPE;
IF PhSmarts.phoenixInfo=NIL THEN { Problem["No Smarts for SmartsID %g", NIL, IO.card[report.self.smartsID]]; RETURN; };
[nb, cDesc] ¬ GetInfo[credentials: report.self];
IF nb#$success OR cDesc=NIL THEN RETURN;
SELECT report.actionClass
FROM
$conferenceParticipation => {
IF nb=$success
THEN
SELECT report.actionType
FROM
$conferenceEstablished =>
If the report is received from a participant other than the originator, ignore it.
IF report.requestingParty = cDesc.cInfo.originator
AND
report.self.state # $active
THEN
If we are not active, go idle. Otherwise, ignore report.
ChangeState[cDesc: cDesc, desiredState: $idle, comment: "Conference Established, and we're not in it", reportToAll:TRUE];
$requestToLeave => {
myName ¬ cDesc.partyInfo[cDesc.partyInfo.ixSelf].intendedName;
IF report.requestingParty = cDesc.cInfo.originator
AND Rope.Equal[myName, report.actionInfo]
THEN
We are being asked to leave the conversation. Take appropriate actions here.
ChangeState[cDesc: cDesc, desiredState: $idle, reportToAll:TRUE];
};
ENDCASE;
};
$PriorityChange =>
The participant has requested a change in priority. The changed priority is available in ActionReport.actionInfo. Set this priority value in the conversation information being maintained by Phoenix.
cDesc.myPriority ¬ report.actionInfo;
$ParticipationChange => NULL; -- Perhaps must manually ensure realworld compliance
ENDCASE;
};
}.