File: JukeboxCommandsImpl.mesa
This file prints information about a given Jukebox.
L. Stewart January 6, 1984 3:34 pm
DIRECTORY
Commander USING [CommandProc, Register],
CommandTool USING [ArgumentVector, Failed, Parse],
Convert USING [IntFromRope],
FileNames USING [ConvertToSlashFormat, ResolveRelativePath],
FS USING [Read, Write],
IO USING [card, int, PutChar, PutF, rope, STREAM],
Jukebox USING [bytesPerChirp, CloseJukebox, CloseTune, CreateJukebox, DeleteJukebox, Error, FindChirp, FindJukebox, Handle, Info, MissingChirp, OpenJukebox, OpenTune, pagesPerChirp, Scavenge, Tune, TuneSize, WindowOrigin],
JukeboxImpl USING [instances],
Rope USING [ROPE],
VM USING [AddressForPageNumber, Allocate, Interval, Free],
VoiceStream;
JukeboxCommandsImpl: PROGRAM
IMPORTS Commander, CommandTool, Convert, FileNames, FS, IO, Jukebox, JukeboxImpl, VM
SHARES JukeboxImpl, VoiceStream =
BEGIN
PrintIt: Commander.CommandProc = TRUSTED {
{
ENABLE Jukebox.Error => {
msg ← rope;
GOTO Quit;
};
argv: CommandTool.ArgumentVector;
weOpened: BOOLFALSE;
jukebox: Jukebox.Handle ← NIL;
argv ← CommandTool.Parse[cmd ! CommandTool.Failed => { msg ← errorMsg; GOTO Quit;}];
IF argv.argc > 2 THEN RETURN[$Failure, "Usage: PrintJukebox {jukeboxname}"];
IF argv.argc = 1 THEN {
FOR list: LIST OF Jukebox.Handle ← JukeboxImpl.instances, list.rest WHILE list # NIL DO
PrintData[list.first, cmd.out];
ENDLOOP;
RETURN[NIL, NIL];
};
jukebox ← Jukebox.FindJukebox[argv[1]];
IF jukebox = NIL THEN {
weOpened ← TRUE;
jukebox ← Jukebox.OpenJukebox[argv[1]];
};
PrintData[jukebox, cmd.out];
IF weOpened THEN jukebox ← Jukebox.CloseJukebox[jukebox];
};
EXITS
Quit => RETURN[$Faiure, msg];
};
PrintData: PROC [jukebox: Jukebox.Handle, out: IO.STREAM] = {
name: Rope.ROPE;
nPages: INT;
nTunes: INT;
totalChirpsUsed: INT ← 0;
totalTunes: INT ← 0;
tune: Jukebox.Tune;
tuneSize: INT;
[name: name, nPages: nPages, nTunes: nTunes] ← Jukebox.Info[jukebox];
out.PutF["Jukebox %g, %d pages and %d tunes\n", IO.rope[name], IO.int[nPages], IO.int[nTunes]];
FOR i: INT IN [0..nTunes) DO {
tune ← Jukebox.OpenTune[self: jukebox, tuneId: i, write: FALSE ! Jukebox.Error => {
IF reason # BadTune THEN REJECT
ELSE GOTO NextLoop;
} ];
totalTunes ← totalTunes + 1;
tuneSize ← Jukebox.TuneSize[tune];
totalChirpsUsed ← totalChirpsUsed + tuneSize;
out.PutF[" Tune %6d, %6d chirps\n", IO.int[i], IO.int[tuneSize]];
Jukebox.CloseTune[jukebox, tune];
EXITS
NextLoop => NULL;
};
ENDLOOP;
out.PutF["Total %d chirps in %6d tunes\n", IO.int[totalChirpsUsed], IO.int[totalTunes]];
};
PrivRunDataObject: PRIVATE TYPE = RECORD [
This record represents the extra space in each chirp, after the end of recorded voice.
runArray: ARRAY [0..95) OF CARDINAL,
packetSize: CARDINAL
];
PrintTune: Commander.CommandProc = TRUSTED {
chirpSpace: VM.Interval ← VM.Allocate[count: Jukebox.pagesPerChirp];
runData: LONG POINTER TO PrivRunDataObject;
runData ← VM.AddressForPageNumber[chirpSpace.page] + (Jukebox.bytesPerChirp/2);
{{
ENABLE Jukebox.Error => {
msg ← rope;
GOTO Quit;
};
argv: CommandTool.ArgumentVector;
tuneID: INT;
tuneSize: INT;
total: INT;
tune: Jukebox.Tune;
chirpWindow: Jukebox.WindowOrigin;
jukebox: Jukebox.Handle ← NIL;
weOpened: BOOLFALSE;
fixIt: BOOL ← cmd.procData.clientData = $FixTune;
fixThisChirp: BOOL;
argv ← CommandTool.Parse[cmd ! CommandTool.Failed => {msg ← errorMsg; GOTO Quit}];
IF argv.argc # 3 THEN {
msg ← "Usage: PrintTune jukeboxName tuneID";
GOTO Quit;
};
jukebox ← Jukebox.FindJukebox[argv[1]];
IF jukebox = NIL THEN {
weOpened ← TRUE;
jukebox ← Jukebox.OpenJukebox[argv[1]];
};
tuneID ← Convert.IntFromRope[argv[2]];
tune ← Jukebox.OpenTune[self: jukebox, tuneId: tuneID, write: FALSE];
tuneSize ← Jukebox.TuneSize[tune];
cmd.out.PutF["Tune %6d, %6d chirps\n", IO.int[tuneID], IO.int[tuneSize]];
FOR chirp: INT IN [0..tuneSize) DO
ENABLE {
Jukebox.MissingChirp => {
cmd.out.PutF["Chirp %6d, missing\n", IO.int[chirp]];
CONTINUE;
};
};
chirpWindow ← Jukebox.FindChirp[self: jukebox, tune: tune, chirp: chirp, signalMissingChirp: TRUE, signalEOF: TRUE];
FS.Read[file: chirpWindow.file, from: chirpWindow.base, nPages: chirpSpace.count, to: VM.AddressForPageNumber[chirpSpace.page]];
cmd.out.PutF["Chirp %6d, ps: %3d, ", IO.int[chirp], IO.int[runData.packetSize]];
total ← 0;
fixThisChirp ← FALSE;
FOR ri: NAT IN [0..95) DO
cmd.out.PutF["%d ", IO.card[runData.runArray[ri]]];
total ← total + runData.runArray[ri];
IF total = Jukebox.bytesPerChirp THEN EXIT;
REPEAT
FINISHED => {
cmd.out.PutF[" total = %d", IO.int[total]];
fixThisChirp ← TRUE;
};
ENDLOOP;
cmd.out.PutChar['\n];
IF fixIt AND fixThisChirp THEN {
cmd.out.PutF["Fixing Chirp: "];
total ← 0;
FOR ri: NAT IN [0..95) DO
cmd.out.PutF["%d ", IO.card[runData.runArray[ri]]];
IF runData.runArray[ri] > Jukebox.bytesPerChirp THEN {
runData.runArray[ri] ← Jukebox.bytesPerChirp - total;
cmd.out.PutF["( ← %d)", IO.card[runData.runArray[ri]]];
};
total ← total + runData.runArray[ri];
IF total > Jukebox.bytesPerChirp THEN {
runData.runArray[ri] ← runData.runArray[ri] - (total - Jukebox.bytesPerChirp);
cmd.out.PutF["( ← %d)", IO.card[runData.runArray[ri]]];
};
IF total = Jukebox.bytesPerChirp THEN EXIT;
REPEAT
FINISHED => {
cmd.out.PutF[" total = %d", IO.int[total]];
fixThisChirp ← TRUE;
};
ENDLOOP;
FS.Write[file: chirpWindow.file, from: VM.AddressForPageNumber[chirpSpace.page], nPages: chirpSpace.count, to: chirpWindow.base];
};
ENDLOOP;
Jukebox.CloseTune[jukebox, tune];
IF weOpened THEN jukebox ← Jukebox.CloseJukebox[jukebox];
VM.Free[chirpSpace];
};
EXITS
Quit => {
VM.Free[chirpSpace];
RETURN[$Failure, msg];
};
};
};
CreateJukebox: Commander.CommandProc = TRUSTED {
{
ENABLE Jukebox.Error => {
msg ← rope;
GOTO Quit;
};
argv: CommandTool.ArgumentVector;
name: Rope.ROPE;
nPages: INT;
nTunes: INT;
argv ← CommandTool.Parse[cmd ! CommandTool.Failed => { msg ← errorMsg; GOTO Quit;}];
IF argv.argc # 4 THEN RETURN[$Failure, "Usage: CreateJukebox jukeboxname nPages nTunes"];
name ← FileNames.ResolveRelativePath[argv[1]];
name ← FileNames.ConvertToSlashFormat[name];
nPages ← Convert.IntFromRope[argv[2]];
nTunes ← Convert.IntFromRope[argv[3]];
Jukebox.CreateJukebox[nPages: nPages, nTunes: nTunes, name: name];
};
EXITS
Quit => RETURN[$Failure, msg];
};
OpenJukebox: Commander.CommandProc = TRUSTED {
{
ENABLE Jukebox.Error => {
msg ← rope;
GOTO Quit;
};
argv: CommandTool.ArgumentVector;
name: Rope.ROPE;
weOpened: BOOLFALSE;
argv ← CommandTool.Parse[cmd ! CommandTool.Failed => { msg ← errorMsg; GOTO Quit;}];
IF argv.argc # 2 THEN RETURN[$Failure, "Usage: OpenJukebox jukeboxname"];
name ← FileNames.ResolveRelativePath[argv[1]];
name ← FileNames.ConvertToSlashFormat[name];
[] ← Jukebox.OpenJukebox[name: name];
};
EXITS
Quit => RETURN[$Failure, msg];
};
CloseJukebox: Commander.CommandProc = TRUSTED {
{
ENABLE Jukebox.Error => {
msg ← rope;
GOTO Quit;
};
argv: CommandTool.ArgumentVector;
name: Rope.ROPE;
jukebox: Jukebox.Handle ← NIL;
argv ← CommandTool.Parse[cmd ! CommandTool.Failed => { msg ← errorMsg; GOTO Quit;}];
IF argv.argc # 2 THEN RETURN[$Failure, "Usage: CloseJukebox jukeboxname"];
name ← FileNames.ResolveRelativePath[argv[1]];
name ← FileNames.ConvertToSlashFormat[name];
jukebox ← Jukebox.FindJukebox[name];
IF jukebox = NIL THEN RETURN[$Failure, "jukebox not open"];
jukebox ← Jukebox.CloseJukebox[self: jukebox];
};
EXITS
Quit => RETURN[$Failure, msg];
};
DeleteJukebox: Commander.CommandProc = TRUSTED {
{
ENABLE Jukebox.Error => {
msg ← rope;
GOTO Quit;
};
argv: CommandTool.ArgumentVector;
name: Rope.ROPE;
weOpened: BOOLFALSE;
argv ← CommandTool.Parse[cmd ! CommandTool.Failed => { msg ← errorMsg; GOTO Quit;}];
IF argv.argc # 2 THEN RETURN[$Failure, "Usage: DeleteJukebox jukeboxname"];
name ← FileNames.ResolveRelativePath[argv[1]];
name ← FileNames.ConvertToSlashFormat[name];
Jukebox.DeleteJukebox[name: name];
};
EXITS
Quit => RETURN[$Failure, msg];
};
ScavengeJukebox: Commander.CommandProc = TRUSTED {
{
ENABLE Jukebox.Error => {
msg ← rope;
GOTO Quit;
};
argv: CommandTool.ArgumentVector;
name: Rope.ROPE;
jukebox: Jukebox.Handle ← NIL;
nFree, recovered: INT;
argv ← CommandTool.Parse[cmd ! CommandTool.Failed => { msg ← errorMsg; GOTO Quit;}];
IF argv.argc # 2 THEN RETURN[$Failure, "Usage: ScavengeJukebox jukeboxname"];
name ← FileNames.ResolveRelativePath[argv[1]];
name ← FileNames.ConvertToSlashFormat[name];
jukebox ← Jukebox.FindJukebox[name: name];
IF jukebox = NIL THEN RETURN[$Failure, "jukebox not open"];
[nFree: nFree, recovered: recovered] ← Jukebox.Scavenge[self: jukebox, stream: cmd.out, makeFixes: TRUE];
cmd.out.PutF["%d chirps recovered, now %d chirps free\n", IO.int[recovered], IO.int[nFree]];
};
EXITS
Quit => RETURN[$Failure, msg];
};
Init: PROC = {
Commander.Register[key: "PrintJukebox", proc: PrintIt, doc: "PrintJukebox jukeboxname - print information about a Jukebox"];
Commander.Register[key: "PrintTune", proc: PrintTune, doc: "PrintTune jukeboxname tune - print tune information"];
Commander.Register[key: "FixTune", proc: PrintTune, doc: "FixTune jukeboxname tune - print and fix up a tune", clientData: $FixTune];
Commander.Register[key: "CreateJukebox", proc: CreateJukebox, doc: "CreateJukebox jukeboxname nPages nTunes"];
Commander.Register[key: "OpenJukebox", proc: OpenJukebox, doc: "OpenJukebox jukeboxname"];
Commander.Register[key: "CloseJukebox", proc: CloseJukebox, doc: "OpenJukebox jukeboxname"];
Commander.Register[key: "DeleteJukebox", proc: DeleteJukebox, doc: "DeleteJukebox jukeboxname"];
Commander.Register[key: "ScavengeJukebox", proc: ScavengeJukebox, doc: "ScavengeJukebox jukeboxname"];
};
initialization
Init[];
END.
L. Stewart, April 11, 1983 1:09 pm, created
L. Stewart, December 27, 1983 2:28 pm, Cedar 5
L. Stewart, January 6, 1984 3:34 pm, FixTune