FILE: TuneArchive.mesa
routines to enable tunes to be copied in and out of jukeboxes, archived as standard FS files.
Ades, February 24, 1986 6:09:40 pm PST
DIRECTORY
BasicTime USING [GMT],
Rope USING [ROPE],
IO USING [STREAM],
Jukebox USING [EnergyRange, RunArrayRange];
TuneArchive: CEDAR DEFINITIONS =
BEGIN
the structure of an archived tune is a single TuneInformation header followed by some number (specified in the header) of ChirpContents segments.
the structure of the header is
TuneInformation: TYPE = REF TuneInformationHeader;
TuneInformationHeader: TYPE = RECORD [
jukeboxNameLength: NAT,
-- the length in characters of the name of the jukebox from which this tune was archived
tuneNumber: INT,
-- the number of the tune, when it was archived
createDate: BasicTime.GMT,
writeDate: BasicTime.GMT,
readDate: BasicTime.GMT,
-- again applicable at the time of the archive: read date does not reflect when the archive was made
archiveDate: BasicTime.GMT,
sizeInChirps: INT ];
tuneInformationBytes: NAT = SIZE[TuneInformationHeader]*2;
this fixed length record is followed by the variable length part, the name of the jukebox from which this tune was archived as a stream of characters, and then the "client header information", which is TuneArchive.userHeaderLength bytes long
each ChirpContents segment again consists of fixed followed by variable length components and has the structure
ChirpContents: TYPE = REF ChirpContentsRecord;
ChirpContentsRecord: TYPE = RECORD [
ambientLevel: Jukebox.EnergyRange,
runArrayLength: Jukebox.RunArrayRange,
sampleBytes: NAT ];
chirpContentsBytes: NAT = SIZE[ChirpContentsRecord]*2;
this fixed length section is followed by the valid parts of the runArray and then the valid samples for the chirp.
note that a missing chirp is represented by a ChirpContentsRecord[0, 1, 0] and then a Jukebox.RunElement[silence[Jukebox.bytesPerChirp]]
ArchiveTune: PROC [jukeboxName: Rope.ROPE, tuneID: INT, toFile: Rope.ROPE] RETURNS [tuneInformation: TuneInformation, internalJukeboxName: Rope.ROPE];
archives the specified tune from the specified jukebox: if the jukebox is closed then open it and close it again after the archive. Signals that may be raised by this procedure are FS.Errors (if the file specified cannot be created or written), Jukebox.Errors (if the jukebox or tune does not exist or cannot be manipulated) and BasicTime.TimeNotKnown if the time at which the archive was done cannot be determined (and thus cannot be written into the file).
If any of these errors occurs, the file, tune and jukebox will all be closed (if applicable) on UNWINDing back to the caller.
the two return parameters give most of the important facts about the tune just archived: internalJukeboxName is the name which will have been written into the archive file and is the name for the jukebox that is actually stored in the jukebox when open, as opposed to the parameter passed to this routine
ReadArchiveHeader: PROC [readableFileStream: IO.STREAM] RETURNS [tuneInformation: TuneArchive.TuneInformation, archivedJukeboxName: Rope.ROPE];
given a readable stream positioned at the start of a tune archive file, builds up the tuneInformation and archivedJukeboxName identical to that returned by ArchiveTune
May raise FS.EndOfStream if the correct number of bytes is not available and FS.Error if the stream is of the wrong type, closed etc.
(if you try it on a non-FS stream the possiblities for signals are endless. . .)
PrintArchiveInfo: PROC [out: IO.STREAM, archiveFileName: Rope.ROPE, tuneInformation: TuneArchive.TuneInformation, archivedJukeboxName: Rope.ROPE];
prints details about an archive file: requires the name of the file; a TuneInformation record; a rope giving the internalJukeboxName and an output stream down which to send the textual output. No check is made that the tuneInformation and archivedJukeboxName correspond to what would be found in archiveFileName! Printing the length of the file may cause FS.Errors if the file name is bad in some way. Signals resulting from attempting to read a valid file's length are caught internally
RestoreTune: PROC [fromFile: Rope.ROPE, jukeboxName: Rope.ROPENIL, tuneID: INT ← -1] RETURNS [tuneIDused: INT, restoredJukeboxName: Rope.ROPE];
attempts to copy an archive file back to a jukebox tune: if the jukebox is closed then open it and close it again after the archive. If jukeboxName or tuneID are defaulted
the value(s) used will be those found in the archive file itself - which specify the location from which the archive was made. If tuneID is supplied as any negative number other than -1 then a tuneID will be selected from those available (i.e. not currently in use) in the jukebox. Signals which may be raised are FS.Errors, if the specified file cannot be read, IO.EndOfStream if a premature end-of-file is found [in which case the file was probably not an archive file] and Jukebox.Errors if the jukebox does not exist or cannot be manipulated, or if the tune number is too large for the jukebox. If any of these errors occurs, the file, tune and jukebox will all be closed (if applicable) on UNWINDing back to the caller.
END.