DIRECTORY
Atom USING [ GetPropFromList, PutPropOnList ],
FinchSynthesizer,
FinchSmarts USING [ ConvDesc, ObtainServiceInterface, RegisterForReports, ReportConversationStateProc, ReportRequestStateProc, ReportSystemStateProc, ServiceConnect ],
PupSocket USING [ GetUniqueID ],
RefID USING [ ID ],
RPC USING [ CallFailed, ImportFailed ],
Thrush USING [ ConversationID, InterfaceSpec, NB, nullConvID, nullID, SHHH ],
Synthesizer USING [ ActionID, nullActionID, SynthSpec, SynthSpecBody, SynthSpecs ],
SynthesizerServerRpcControl USING [
ImportNewInterface, InterfaceRecord, GetSynthesizerSpecifications, StopSpeech, TextToSpeech ]
;

FinchSynthesizerImpl: CEDAR MONITOR
IMPORTS SynthesizerServerRpcControl, Atom, FinchSmarts, PupSocket, RPC
EXPORTS FinchSynthesizer = {


ConvDesc: TYPE = FinchSmarts.ConvDesc;
ConversationID: TYPE = Thrush.ConversationID;
NB: TYPE = Thrush.NB;
nullID: RefID.ID = Thrush.nullID;
SHHH: TYPE = Thrush.SHHH;
SynthSpecs: TYPE = Synthesizer.SynthSpecs; -- LIST OF Synthesizer.SynthSpec

NconcSpecs: PROC[l1, l2: SynthSpecs] RETURNS [SynthSpecs] = INLINE {
IF l1=NIL THEN RETURN[l2];
FOR specs: SynthSpecs _ l1, specs.rest WHILE specs#NIL DO
IF specs.rest=NIL THEN { specs.rest_l2; RETURN[l1]; };
ENDLOOP;
ERROR;
};

synthesizerServer: SynthesizerServerRpcControl.InterfaceRecord _ NIL;
defaultTranslateProc: FinchSynthesizer.SynthesizerTranslateProc _ NIL;
shhh: SHHH;

SysStateReport: ENTRY FinchSmarts.ReportSystemStateProc = {
};

ConvStateReport: ENTRY FinchSmarts.ReportConversationStateProc = {
ENABLE UNWIND => NULL;
sCDesc: FinchSynthesizer.SConvDesc = GetSCDesc[cDesc];
IF sCDesc=NIL THEN RETURN; -- No biggee
SELECT cDesc.situation.self.state FROM
$failed, $idle => -- If pending specs still exist, report aborted upstream (somehow)???
sCDesc.pendingSpecs _ NIL; -- For now, just zap them; problem is monitor locks.
ENDCASE;
};

ReportReport: ENTRY FinchSmarts.ReportRequestStateProc = {
ENABLE UNWIND => NULL;
SELECT actionReport.actionClass FROM
$synthesizer => {
sCDesc: FinchSynthesizer.SConvDesc = GetSCDesc[cDesc];
IF sCDesc=NIL THEN RETURN; -- presumably nothing was pending!
FOR rqs: Synthesizer.SynthSpecs _ sCDesc.pendingSpecs, rqs.rest WHILE rqs#NIL DO
IF actionReport.actionID#rqs.first.actionID THEN LOOP;
betterActionRequest _ rqs.first;
SELECT actionReport.actionType FROM
$finished, $flushed => sCDesc.pendingSpecs _ rqs.rest; ENDCASE;
EXIT;
ENDLOOP;
IF betterActionRequest=NIL THEN ERROR; -- Complain?["missing reports"]
};
ENDCASE=> cDesc _ cDesc; -- a place to stand during debugging
};

TextToSpeech: PUBLIC PROC
-- TAKES -- [
convID: Thrush.ConversationID_Thrush.nullConvID,
synthSpec: Synthesizer.SynthSpec,
queueIt: BOOL_TRUE,
synthesizerTranslateProc: FinchSynthesizer.SynthesizerTranslateProc_NIL,
synthesizerModel: ATOM_NIL, -- Not presently interpreted
synthesizerVersion: ATOM_NIL
]
RETURNS [
nb: Thrush.NB_$success,
newConvID: Thrush.ConversationID,
newActionID: Synthesizer.ActionID
] = {
cDesc: ConvDesc;
sCDesc: FinchSynthesizer.SConvDesc;
ScheduleSpeech: ENTRY PROC RETURNS[nb: NB_$success] = {
ENABLE {
UNWIND=>NULL;
RPC.CallFailed => {
IF synthesizerServer=NIL THEN { nb _ $serverDown; CONTINUE; };
synthesizerServer _ NIL;
RETRY; -- Will attempt reconnection via main Finch connectiononce
};
};
nb _ synthesizerServer.TextToSpeech[
shhh, cDesc.situation.self, sCDesc.synthesizerServiceID, synthSpec.textToSpeak, synthSpec.actionID, TRUE, queueIt];
IF nb=$success THEN
sCDesc.pendingSpecs _ NconcSpecs[sCDesc.pendingSpecs, LIST[synthSpec]];
};
[nb,cDesc,sCDesc]_SynthesizerConnect[convID];
IF nb=$success THEN {
newConvID _ cDesc.situation.self.convID;
synthSpec _ NEW[Synthesizer.SynthSpecBody _ synthSpec^];
newActionID _
IF synthSpec.actionID=Synthesizer.nullActionID THEN (synthSpec.actionID _ NewID[])
ELSE synthSpec.actionID;
IF synthesizerTranslateProc#NIL THEN
synthSpec.textToSpeak _ synthesizerTranslateProc[synthSpec.textToSpeak]
ELSE IF defaultTranslateProc#NIL THEN
synthSpec.textToSpeak _ synthesizerTranslateProc[synthSpec.textToSpeak];
nb _ ScheduleSpeech[];
};
};

StopSpeech: PUBLIC PROC[convID: Thrush.ConversationID] RETURNS [nb: Thrush.NB] ={
RETURN[DoStopSpeech[convID: convID, reset: FALSE]];
};

ResetSynthesizer: PUBLIC PROC[convID: Thrush.ConversationID] RETURNS [nb: Thrush.NB] ={
RETURN[DoStopSpeech[convID: convID, reset: TRUE]];
};

DoStopSpeech: PROC[
convID: Thrush.ConversationID, reset: BOOL] RETURNS [nb: Thrush.NB] ={
ENABLE RPC.CallFailed => {
IF synthesizerServer=NIL THEN { nb _ $serverDown; CONTINUE; };
synthesizerServer _ NIL;
RETRY; -- Will attempt reconnection via main Finch connectiononce
};
cDesc: ConvDesc;
sCDesc: FinchSynthesizer.SConvDesc;
IF ([nb,cDesc, sCDesc]_SynthesizerConnect[convID]).nb#$success OR cDesc.situation.self.state#$active THEN RETURN;
nb _ synthesizerServer.StopSpeech[
shhh, cDesc.situation.self, sCDesc.synthesizerServiceID, reset];
};

GetSynthesizerSpecifications: PUBLIC PROC[conversationID: Thrush.ConversationID]
RETURNS [nb: Thrush.NB_$success, synthesizerModel: ATOM, synthesizerVersion: ATOM] = {
ENABLE RPC.CallFailed => {
IF synthesizerServer=NIL THEN { nb _ $serverDown; CONTINUE; };
synthesizerServer _ NIL;
RETRY; -- Will attempt reconnection via main Finch connectiononce
};
cDesc: ConvDesc;
sCDesc: FinchSynthesizer.SConvDesc;
IF ([nb,cDesc, sCDesc]_SynthesizerConnect[conversationID]).nb#$success OR cDesc.situation.self.state#$active THEN RETURN;
[nb, synthesizerModel, synthesizerVersion] _ 
synthesizerServer.GetSynthesizerSpecifications[shhh, sCDesc.synthesizerServiceID];
};
RegisterTranslateProc: PUBLIC PROC [
conversationID: Thrush.ConversationID, translate: FinchSynthesizer.SynthesizerTranslateProc_NIL] = {
defaultTranslateProc _ translate;
};


SynthesizerConnect: PROC[convID: Thrush.ConversationID]
RETURNS [nb: NB, cDesc: ConvDesc, sCDesc: FinchSynthesizer.SConvDesc] = {
[nb, cDesc] _ FinchSmarts.ServiceConnect["text-to-speech", convID];
IF nb#$success THEN RETURN;
sCDesc _ GetSCDescE[cDesc];
nb _ SynthesizerInterface[cDesc, sCDesc];
};

GetSCDescE: ENTRY PROC[
cDesc: ConvDesc ] RETURNS [sCDesc: FinchSynthesizer.SConvDesc] = {
ENABLE UNWIND => NULL;
IF cDesc=NIL THEN ERROR;
RETURN[GetSCDesc[cDesc, TRUE]];
};

GetSCDesc: INTERNAL PROC[
cDesc: ConvDesc, createOK: BOOL_FALSE ] RETURNS [sCDesc: FinchSynthesizer.SConvDesc] = {
IF cDesc=NIL THEN RETURN[NIL];
sCDesc _ NARROW[Atom.GetPropFromList[cDesc.props, $SConvDesc]];
IF ~createOK OR sCDesc#NIL THEN RETURN;
sCDesc _ NEW[FinchSynthesizer.SConvDescBody _ []];
cDesc.props _ Atom.PutPropOnList[cDesc.props, $SConvDesc, sCDesc];
};

SynthesizerInterface: PROC[cDesc: ConvDesc, sCDesc: FinchSynthesizer.SConvDesc]
RETURNS [nb: NB_$success] = {
interfaceSpec: Thrush.InterfaceSpec;
IF synthesizerServer#NIL AND (sCDesc=NIL OR sCDesc.synthesizerServiceID#nullID)
THEN RETURN;
[nb, shhh, interfaceSpec] _ FinchSmarts.ObtainServiceInterface[NIL, "SynthesizerServer", cDesc];
IF nb#$success THEN RETURN;
IF synthesizerServer=NIL THEN
synthesizerServer _ SynthesizerServerRpcControl.ImportNewInterface[
interfaceName: interfaceSpec.interfaceName,
hostHint: interfaceSpec.hostHint!RPC.ImportFailed => CONTINUE
];
IF synthesizerServer=NIL THEN RETURN[$noSynthesizerServerInterface];
IF sCDesc#NIL THEN sCDesc.synthesizerServiceID _ interfaceSpec.serviceID;
};

NewID: PROC RETURNS[LONG CARDINAL] ={RETURN[LOOPHOLE[PupSocket.GetUniqueID[]]]};


InitializeFinchSynthesizer: PUBLIC PROC = {
FinchSmarts.RegisterForReports[s: NIL, c: ConvStateReport, r: ReportReport, before: TRUE];
};
}.
���n��FinchSynthesizerImpl.mesa
Copyright c 1986 by Xerox Corporation.  All rights reserved.
Last Edited by: Swinehart, July 19, 1987 9:29:57 pm PDT
Confusion about locks here and in FinchSmartsImpl; careful!
Declarations
Supervision

At present, all that's necessary is to be sure no SCDescs remain in next iteration.  Any actions will have been abandoned.  We count on FinchSmarts to do that for us.
[nb: NB, cDesc: ConvDesc, remark: ROPE]
BROADCAST sCDesc.stateChange; -- This will be enough to alert interested parties
[cDesc: ConvDesc, actionReport: Thrush.ActionReport, actionRequest: REF]
RETURNS[betterActionRequest: REF]
This one should get the reports first.  Then the client that requested action reports can get them too.
BROADCAST sCDesc.stateChange;
Throw away pending intervals that are complete.  This includes intervals preceding the one being reported on.
Endcase events are now expected, since there is no event-filtering in FinchSmarts; these will be events for other applications.
Client Functions

Describe the assigned synthesizer.


Utilities
sCDesc=NIL if we're only interested in importing the interface.
Initialization
Ask Finch to inform us of changes in conversation state, and action reports.

Swinehart, October 3, 1986 4:40:54 pm PDT
Based on a prototype FinchRecordingImpl, and on code extracted from old FinchSmartsImpls., DIRECTORY, }, PlaybackTune



�Ê	%��˜�Jšœ™šœ
Ïmœ1™<Jšœ7™7—J˜�šÏk	˜	Jšœžœ$˜.J˜J˜§Jšœ
žœ˜ J˜Jšžœžœ˜'J˜MJšœS˜Sšœžœ˜#Jšœ]˜]—J˜J˜�—šÏnœžœž˜#JšÏt=™=Jšžœ<ž˜FJšžœ˜J˜�—™J˜�Jšœ
žœ˜&Jšœžœ˜-Jšžœžœ
žœ˜J˜!Jšžœžœ
žœ˜JšœžœÏcÐck¡˜KJ˜�šŸ
œžœžœžœ˜DIcodešžœžœžœžœ˜šžœ$žœžœž˜9Kšžœžœžœžœ˜6Kšžœ˜—Kšžœ˜Jšœ˜J˜�—JšœAžœ˜EJšœBžœ˜Fšœžœ˜J˜�——šœ™J™�šŸœžœ&˜;J™¦J˜J˜�—šÐbnœžœ,˜BJšœžœžœ™'Jšžœžœžœ˜J˜6Jš	žœžœžœžœ¡˜'šžœž˜&šœ¡Ðct¡B¤˜YJšœžœ¡¤¡1¤˜Q—Jšžœ˜—Jšž	œ¡2™PJ˜J˜�—šŸœžœ'˜:JšœDžœ™HJšžœžœ™!Jšœg™gJšžœžœžœ˜šžœž˜$šœ˜Jšœ6˜6Jš	žœžœžœžœ¡"˜=Jšž	œ™šžœ=žœžœž˜PKšžœ*žœžœ˜6K˜ šžœž˜#K™mKšœ7žœ˜?—Kšžœ˜Kšžœ˜—Kšžœžœžœžœ¡¤¡¤˜HK˜—šžœ¡$˜=K™——Jšœ˜—J˜�—™J™�šŸœž˜š¡Ñcjk¡œ˜
Jšœ0˜0Kšœ!˜!Kšœ	žœžœ˜KšœDž˜HKšœžœžœ¡˜8Kšœžœž˜Kšœ˜—šžœ˜	Kšœžœ
˜Kšœ!˜!Kšœ!˜!Kšœ˜—J˜J˜#š
Ÿœžœžœžœžœ˜7šÐksÏs¦˜Jš¦§¦§˜
š§˜Jš¦§¦§¦§¦§˜>Jš§˜Jš¦§Ðcs;˜BJš§˜—Jš§˜—šœ œ ˜$Jšœdžœ˜s—šžœ
ž˜Jšœ6žœ
˜G—Jšœ˜—Jšœ-˜-šžœ
žœ˜J˜(Jšœžœ)˜8šœ
˜
Jšžœ-žœ˜RJšžœ˜—šžœžœž˜$Jšœ
 œ œ
 ˜G—šžœžœžœž˜%Jšœ
 œ œ
 œ˜H—Jšœ˜J˜—J˜J˜�—šŸ
œžœžœ
žœ˜QJšžœ%žœ˜3Jšœ˜J˜�—šŸœžœžœ
žœ˜WJšžœ%žœ˜2Jšœ˜J˜�—šŸœžœ˜Jšœ&žœžœ
žœ˜Fš¦§˜Jš§>˜>Jš§˜Jš¦§¨;˜BJš§˜—J˜J˜#Jšžœ=žœ$žœžœ˜qšœ"˜"Jšœ@˜@—Jšœ˜J˜�—šŸœžœžœ'˜PKšžœ
žœžœžœ˜VK™"š¦§˜Jš¦§¦§¦§¦§˜>Jš§˜Jš¦§¨;˜BJš§˜—J˜J˜#JšžœEžœ$žœžœ˜yšœ-˜-JšœR˜R—J˜K™�—šŸœžœ˜$Kšœ\žœ˜dJ˜!J˜J™�——™	J˜�J˜�šŸœžœ˜7Jšžœžœ:˜IJ˜CJšžœ
žœžœ˜Jšœ˜J˜)J˜J˜�—šŸ
œžœžœ˜Jšœžœ)˜BJšžœžœžœ˜Jšžœžœžœžœ˜Jšžœžœ˜J˜J˜�—šŸ	œžœžœ˜Jšœžœžœžœ)˜XJš
žœžœžœžœžœ˜Jšœ	žœ0˜?Jš
žœžœžœžœžœ˜'Jšœ	žœ&˜2J˜BJ˜J˜�—šŸœžœ5˜OJšžœžœ˜Jšœ?™?J˜$š
žœžœžœ	žœžœ$˜OJšžœžœ˜—Jšœ?žœ˜`Jšžœ
žœžœ˜šžœžœž˜šœC˜CJ˜+Jšœ!žœž˜=J˜——Jšžœžœžœžœ ˜DJšžœžœžœ7˜IJ˜J˜�—JšŸœžœžœžœžœžœžœ˜PJ˜�—J™˜�šŸœžœžœ˜+Jšœ"žœ/žœ˜ZJ™LJ˜——J˜K™�™)KšœYÏr™u—K™�K™�K™�—�…—����^��+ñ��