DIRECTORY RefID USING [ID], Rope USING [ROPE], Thrush USING [Credentials, EncryptionKey, NB, none, nullID, nullKey, PartyID, SHHH] ; VoiceRopeServer: CEDAR DEFINITIONS = { VoiceRope: TYPE = REF VoiceRopeInterval; VoiceRopeInterval: TYPE = RECORD [ ropeID: Rope.ROPE, start: INT, length: INT ]; InterestClass: TYPE = Rope.ROPE; Users: TYPE = LIST OF Rope.ROPE; maxEnergy: INTEGER = (LAST[NAT])/2; EnergyRange: TYPE = [0..maxEnergy]; EnergySequence: TYPE = REF EnergySequenceRec; EnergySequenceRec: TYPE = RECORD [ s: SEQUENCE length: NAT OF EnergyRange ]; VoiceSample: TYPE = [0..256); VoiceBlock: TYPE = REF VoiceBlockRec; VoiceBlockRec: TYPE = RECORD [ s: PACKED SEQUENCE length: NAT OF VoiceSample ]; Interval: TYPE = RECORD[start, length: INT]; IntervalSpecs: TYPE = LIST OF Interval; Record: PROC[shhh: Thrush.SHHH _ Thrush.none, credentials: Thrush.Credentials, serviceID: RefID.ID, recordedParty: Thrush.PartyID _ Thrush.nullID, intID: CARD _ 0, queueIt: BOOL _ TRUE] RETURNS [nb: Thrush.NB, voiceRope: VoiceRope]; Play: PROC[shhh: Thrush.SHHH _ Thrush.none, voiceRope: VoiceRope, credentials: Thrush.Credentials, serviceID: RefID.ID, intID: CARD _ 0, queueIt: BOOL _ TRUE] RETURNS [nb: Thrush.NB]; Stop: PROC[shhh: Thrush.SHHH _ Thrush.none, credentials: Thrush.Credentials, serviceID: RefID.ID] RETURNS [nb: Thrush.NB]; Pause: PROC[shhh: Thrush.SHHH _ Thrush.none, credentials: Thrush.Credentials, serviceID: RefID.ID] RETURNS [nb: Thrush.NB]; Resume: PROC[shhh: Thrush.SHHH _ Thrush.none, credentials: Thrush.Credentials, serviceID: RefID.ID] RETURNS [nb: Thrush.NB]; Retain: PROC [shhh: Thrush.SHHH _ Thrush.none, callerRName: Rope.ROPE, vr: VoiceRope, class: InterestClass, refID: Rope.ROPE, other: Rope.ROPE _ NIL] RETURNS [nb: Thrush.NB]; Forget: PROC [shhh: Thrush.SHHH _ Thrush.none, vr: VoiceRope, class: InterestClass, refID: Rope.ROPE] RETURNS [nb: Thrush.NB]; GetByInterest: PROC [shhh: Thrush.SHHH _ Thrush.none, class: InterestClass, refID: Rope.ROPE] RETURNS [nb: Thrush.NB, voiceRope: VoiceRope]; Cat: PROC [shhh: Thrush.SHHH _ Thrush.none, callerRName: Rope.ROPE, vr1, vr2, vr3, vr4, vr5: VoiceRope _ NIL] RETURNS [nb: Thrush.NB, new: VoiceRope]; Substr: PROC [shhh: Thrush.SHHH _ Thrush.none, callerRName: Rope.ROPE, vr: VoiceRope, start: INT _ 0, len: INT _ LAST[INT]] RETURNS [nb: Thrush.NB, new: VoiceRope]; Replace: PROC [shhh: Thrush.SHHH _ Thrush.none, callerRName: Rope.ROPE, vr: VoiceRope, start: INT _ 0, len: INT _ LAST[INT], with: VoiceRope _ NIL] RETURNS [nb: Thrush.NB, new: VoiceRope]; Length: PROC [shhh: Thrush.SHHH _ Thrush.none, vr: VoiceRope] RETURNS [nb: Thrush.NB, len: INT]; DescribeRope: PROC [shhh: Thrush.SHHH _ Thrush.none, vr: VoiceRope, minSilence: INT _ -1] RETURNS [nb: Thrush.NB, length: INT, noise: IntervalSpecs]; GetEnergies: PROC [shhh: Thrush.SHHH _ Thrush.none, vr: VoiceRope, samplesPerSegment: [1..8000] _ 160] RETURNS [nb: Thrush.NB, energies: EnergySequence]; FetchBlock: PROC [shhh: Thrush.SHHH _ Thrush.none, vr: VoiceRope, start: INT, len: INT _ 8000, decrypt: BOOLEAN _ TRUE] RETURNS [nb: Thrush.NB, block: VoiceBlock]; StoreBlock: PROC [shhh: Thrush.SHHH _ Thrush.none, block: VoiceBlock, key: Thrush.EncryptionKey _ Thrush.nullKey] RETURNS [nb: Thrush.NB, voiceRope: VoiceRope]; SetPermissions: PROC [shhh: Thrush.SHHH _ Thrush.none, callerRName: Rope.ROPE, vr: VoiceRope, playAccess: Users, editAccess: Users] RETURNS [nb: Thrush.NB]; GetPermissions: PROC [shhh: Thrush.SHHH _ Thrush.none, vr: VoiceRope] RETURNS [nb: Thrush.NB, playAccess: Users, editAccess: Users]; }. ะVoiceRopeServer.mesa Copyright ำ 1986, 1988, 1990 by Xerox Corporation. All rights reserved. Last Edited by: Swinehart, February 28, 1988 11:19:58 pm PST Doug Terry, July 29, 1987 2:07:06 pm PDT Polle Zellweger, December 27, 1990 5:51 pm PST VoiceRopeServer is a voice service interface. It is exported to $recording service parties to provide access to procedures for recording and playing voice, and for VoiceRope editing activities. All of the VoiceRope operations actually deal with intervals of voice ropes. Naive clients can simply ignore the start and length fields and treat a voice rope as simply an ID; clients concerned about performance can alter the interval values associated with a voice rope as an alternative to performing Substr operations. For newly created voice ropes, the start field is always 0 and the length field contains the actual number of samples in the voice rope (or -1). The following two definitions are identical to those in Jukebox; they are reproduced here to avoid a dependency on Jukebox Creating and playing voice ropes Before calling the following operations, clients must establish a voice conversation directly with Bluejay, the voice file server. Records a voice rope, registers it, and returns its ID. The following action reports are generated if intID#0: { $recording, $started, intID } when recording begins. { $recording, $finished, intID } when the recording of this interval has finished. { $recording, $abandoned, intID } when all recording and playback actions ending with this interval has been flushed. Play a specified voice rope. If queueIt is FALSE, flush existing playback and recording requests, first. The following action reports are generated if intID#0: { $recording/$playback, $started, intID } as the interval begins playing/recording. { $recording/$playback, $scheduled, intID } as the interval is accepted for recording/playback, if there is already a list of pieces in the queue ahead of this request. { $recording/$playback, $finished, intID } when the interval has finished. { $recording/$playback, $abandoned, intID } when all recording and playback actions ending with this interval has been flushed. Stop playing or recording some or all of the scheduled intervals. Action reports are generated if intID#0 was specified in original request: { $recording, $abandoned, intID } as indicated above. Note: When the conversation is terminated before all recording/playback actions have occurred, reporting is problematical. Currently, the requesting party may well not receive any reports after idling the conversation (hanging up, for instance.) This interface, however, remains available, so that the DescribeRope function is available for finding out how much was recorded, and so on. Pause playing the scheduled intervals. No effect on recording. No reports at present. Resume playing the scheduled intervals, if paused. No effect on recording. No reports at present. Flush operation unpauses first. Interests in voice ropes Clients must explicitly express an interest in retaining a voice rope in order to prevent it from being garbage collected. Interests belong to a particular class; different applications employing voice ropes can use different interest classes to control how those voice ropes are managed. The refID and other parameters are class-specific. For instance, a class "TiogaVoice" may use refID to record the name of the Tioga file containing a voice rope. The other field can be used to store data such as a timeout. Registers a new interest in the voice rope. The voice rope will be retained until either a corresponding Forget is done or the class' garbage collection process determines that the voice rope is no longer referenced, e.g. refID no longer exists. Taken together, the vr, class, and refID must be unique. Repeated calls of Retain with the same parameters (ignoring other) will only register a single interest. The specified refID of the specified class drops its interest in the voice rope. The voice rope is not necessarily deleted, however, since other interests in the same voice rope may exist. Returns any voice rope that is of interest to the given class and refID; returns NIL if no such voice rope exists. Note: System noises, like Beeps and intolerably cute rollback tunes are indexed in the interest database as refID's like "beep", "rollback", and so on, under the class "SysNoises". Editing voice ropes Once recorded, voice ropes can be used in editing operations to produce new, immutable voice ropes. Concatenates together the non-NIL voice ropes to produce a new voice rope. Creates a new voice rope that is a substring of an existing voice rope. Creates a new voice rope in which the given interval of the voice rope "vr" is replaced by the voice rope "with". Information about voice ropes Returns the actual length of the voice rope. This operation ignores the start and length values specified in the voice rope. Thus, vr.start _ 0; vr.length _ Length[handle, vr] will restore a voice rope to its full contents. Describe the loud and silence intervals within the specified interval. nb is $success or $noSuchTune. Also indicates the total length of the tune. Returns a sequence of energy levels for the given voice rope. The voice rope is divided into segments of size samplesPerSegment, and the average energy of each segment is computed. The returned EnergySequence contains a value for each segment. For best results, samplesPerSegment should be an integral divisor of 8000. Retrieval and storage of voice samples Returns a block of stored voice samples for the requested interval of the given voice rope. Each sample is 8 bits of mu-law encoded voice. If decrypt=TRUE, then the samples are decrypted before returned (the decryption can be quite SLOW!). Creates a new voice rope whose contents are the given block. Access control Associated with each voice rope are two lists that control access to it: a playAccess list and an editAccess list. Only those users on the playAccess list are permitted to Play the voice rope; only those on the editAccess list can invoke the Cat, Substr, and Replace operations. A NIL access list implies that access is not restricted. Access control lists may contain group names that are registered with Grapevine. Note: by default, voice ropes are created with unrestricted access. Restricts access to the specified voice rope. Only the creator of a voice rope may change its access control lists, i.e. invoke this operation. Returns the access control lists for the given voice rope. Doug Terry, July 28, 1986 5:44:18 pm PDT Voice rope service interface for recording, playing, and editing stored voice. changes to: IntervalSpecs, Retain, Forget, GetByInterest, Cat, Substr, Replace, Length, DescribeRope, DIRECTORY, Record, Play, Stop, InterestClass Doug Terry, August 25, 1986 4:34:23 pm PDT changes to: DIRECTORY, Record, Play, Stop Doug Terry, July 29, 1987 2:06:33 pm PDT Added access control and block operations. changes to: DIRECTORY, VoiceRopeInterval, InterestClass, Users, VoiceBlockRec, IntervalSpecs, Cat, Replace, Length, DescribeRope, GetEnergies, StoreBlock, SetPermissions Polle Zellweger, December 27, 1990 5:44:28 pm PST Added callerRName field to operations that need to know the caller's name and don't have credentials (because there's no Etherphone conversation involved). Needed for SunRPC, because we're not currently authenticating our SunRPC calls, and even if we were, we'd get unix login names rather than our GV names. changes to: Retain, Cat, Substr, Replace, SetPermissions ส๋˜Jšœ™šœH™HJ™