DIRECTORY Commander USING [CommandProc, Register], CommandTool USING [ArgumentVector, Failed, Parse], Convert USING [IntFromRope], IO USING [int, PutF, STREAM], Jukebox USING [CloseJukebox, ArchiveCloseTune, Error, FindJukebox, Handle, OpenJukebox, OpenTune, Tune, TuneSize, EnergyRange, RunArray, LengthRange, RunArrayRange, bytesPerChirp, MissingChirp], Rope USING [ ROPE], TuneAccess USING [ReadRunArray, InterpretRunArrayElement, ReadChirpSamples, ByteBlock, ReadTuneHeader, userHeaderLength, ReadAmbientLevel]; TuneCompareImpl: CEDAR PROGRAM IMPORTS Commander, CommandTool, Convert, IO, Jukebox, TuneAccess = BEGIN CompareTunes: Commander.CommandProc = { tune1: Jukebox.Tune _ NIL; jukebox1: Jukebox.Handle _ NIL; weOpened1: BOOLEAN _ FALSE; tune2: Jukebox.Tune _ NIL; jukebox2: Jukebox.Handle _ NIL; weOpened2: BOOLEAN _ FALSE; { ENABLE Jukebox.Error => {msg _ rope; GOTO QuitInError}; argv: CommandTool.ArgumentVector _ CommandTool.Parse[cmd ! CommandTool.Failed => {msg _ errorMsg; GOTO QuitInError}]; IF argv.argc # 5 THEN RETURN [$Failure, "Usage: CompareTunes jukebox1 tuneID1 jukebox2 tuneID2\n"]; TRUSTED { jukebox1 _ Jukebox.FindJukebox[argv[1]]; IF jukebox1 = NIL THEN { weOpened1 _ TRUE; jukebox1 _ Jukebox.OpenJukebox[argv[1]]; }; jukebox2 _ Jukebox.FindJukebox[argv[3]]; IF jukebox2 = NIL THEN { weOpened2 _ TRUE; jukebox2 _ Jukebox.OpenJukebox[argv[3]]; }; tune1 _ Jukebox.OpenTune[self: jukebox1, tuneId: Convert.IntFromRope[argv[2]], write: FALSE]; tune2 _ Jukebox.OpenTune[self: jukebox2, tuneId: Convert.IntFromRope[argv[4]], write: FALSE] }; TRUSTED { IF Jukebox.TuneSize[tune1] # Jukebox.TuneSize[tune2] THEN { cmd.out.PutF["Tunes are of different chirp lengths!\n"]; GOTO Quit } }; { header1: TuneAccess.ByteBlock _ TuneAccess.ReadTuneHeader[jukebox1, tune1, TuneAccess.userHeaderLength, NIL]; header2: TuneAccess.ByteBlock _ TuneAccess.ReadTuneHeader[jukebox2, tune2, TuneAccess.userHeaderLength, NIL]; FOR i: INT IN [0..TuneAccess.userHeaderLength) DO IF header1[i] # header2[i] THEN GOTO mismatch REPEAT mismatch => { cmd.out.PutF["User data headers differ at byte %d\n", IO.int[i]]; GOTO failure } ENDLOOP; cmd.out.PutF["User data headers match\n"] EXITS failure => NULL }; { ambientDiscrepancy: BOOLEAN _ FALSE; TRUSTED { FOR chirpNumber: INT IN [0..Jukebox.TuneSize[tune1]) DO ENABLE Jukebox.MissingChirp => LOOP; IF TuneAccess.ReadAmbientLevel[jukebox1, tune1, chirpNumber] # TuneAccess.ReadAmbientLevel[jukebox2, tune2, chirpNumber] THEN IF ambientDiscrepancy THEN cmd.out.PutF[", %d", IO.int[chirpNumber]] ELSE { ambientDiscrepancy _ TRUE; cmd.out.PutF["Ambient levels differ in chirps %d", IO.int[chirpNumber]] } ENDLOOP}; cmd.out.PutF[IF ambientDiscrepancy THEN "\n" ELSE "Ambient levels match throughout\n"] }; TRUSTED { FOR chirpNumber: INT IN [0..Jukebox.TuneSize[tune1]) DO runArray1, runArray2: REF Jukebox.RunArray; timeAccounted, samplesAccounted: Jukebox.LengthRange _ 0; currRunElement: Jukebox.RunArrayRange _ 0; thisLength: Jukebox.LengthRange; skip, silence: BOOLEAN; cmd.out.PutF["Chirp %d", IO.int[chirpNumber]]; runArray1 _ TuneAccess.ReadRunArray[jukebox1, tune1, chirpNumber, NIL ! Jukebox.MissingChirp => { runArray2 _ TuneAccess.ReadRunArray[jukebox2, tune2, chirpNumber, NIL ! Jukebox.MissingChirp => { cmd.out.PutF[" okay (missing)\n"]; LOOP }]; cmd.out.PutF[":\n chirp missing in first tune\n"]; LOOP } ]; runArray2 _ TuneAccess.ReadRunArray[jukebox1, tune1, chirpNumber, NIL ! Jukebox.MissingChirp => { cmd.out.PutF[":\n chirp missing in second tune\n"]; LOOP }]; WHILE timeAccounted cmd.out.PutF[":\n Run arrays differ at element %d\n", IO.int[currRunElement]]; > Jukebox.bytesPerChirp => cmd.out.PutF[":\n FORMAT ERROR: Run arrays do not describe exactly %d samples\n", IO.int[Jukebox.bytesPerChirp]]; = Jukebox.bytesPerChirp => { samples1: TuneAccess.ByteBlock _ TuneAccess.ReadChirpSamples[jukebox1, tune1, chirpNumber, samplesAccounted]; samples2: TuneAccess.ByteBlock _ TuneAccess.ReadChirpSamples[jukebox2, tune2, chirpNumber, samplesAccounted]; FOR i: INT IN [0..samplesAccounted) DO IF samples1[i] # samples2[i] THEN GOTO mismatch REPEAT mismatch => { cmd.out.PutF[":\n Samples differ at element %d\n", IO.int[i]]; GOTO failure } ENDLOOP; cmd.out.PutF[" okay (%d samples and %d run elements)\n", IO.int[samplesAccounted], IO.int[currRunElement]] EXITS failure => NULL } ENDCASE ENDLOOP}; TRUSTED { Jukebox.ArchiveCloseTune[jukebox1, tune1]; Jukebox.ArchiveCloseTune[jukebox2, tune2]; IF weOpened1 THEN jukebox1 _ Jukebox.CloseJukebox[jukebox1]; IF weOpened2 THEN jukebox2 _ Jukebox.CloseJukebox[jukebox2] } EXITS Quit => TRUSTED { IF tune1 # NIL THEN Jukebox.ArchiveCloseTune[jukebox1, tune1]; IF tune2 # NIL THEN Jukebox.ArchiveCloseTune[jukebox2, tune2]; IF jukebox1 # NIL AND weOpened1 THEN jukebox1 _ Jukebox.CloseJukebox[jukebox1]; IF jukebox2 # NIL AND weOpened2 THEN jukebox2 _ Jukebox.CloseJukebox[jukebox2] }; QuitInError => TRUSTED { IF tune1 # NIL THEN Jukebox.ArchiveCloseTune[jukebox1, tune1]; IF tune2 # NIL THEN Jukebox.ArchiveCloseTune[jukebox2, tune2]; IF jukebox1 # NIL AND weOpened1 THEN jukebox1 _ Jukebox.CloseJukebox[jukebox1]; IF jukebox2 # NIL AND weOpened2 THEN jukebox2 _ Jukebox.CloseJukebox[jukebox2]; RETURN [$Failure, msg] } }}; Commander.Register[key: "CompareTunes", proc: CompareTunes, doc: "CompareTunes jukebox1 tuneID1 jukebox2 tuneID2"]; END.  File: TuneCompareImpl.mesa commands to operate on tunes within a jukebox, plus one to list the tunes in a given jukebox(es) Ades, March 6, 1986 3:20:39 pm PST we use ArchiveCloseTune so that the read/write dates will not be altered by this command Κ&˜šœ™J™`Icode™"—J™šΟk ˜ Jšœ œ˜(Jšœ œ!˜2Jšœœ˜Jšœœ œ˜Jšœœ΅˜ΒJšœœœ˜Jšœ œ{˜‹J˜—Jšœœ˜Jšœ"œ˜BJš˜J˜J˜šΟb œ˜'Jšœœ˜Jšœœ˜Jšœ œœ˜Jšœœ˜Jšœœ˜Jšœ œœ˜—˜Jš˜Jšœœ˜0J˜Jšœcœ˜vJ˜šœœœG˜dJ˜—Jš˜˜*šœ œœ˜Jšœ œ˜J˜(—J˜J˜(šœ œœ˜Jšœ œ˜J˜(—J˜JšœVœ˜]JšœVœ˜\—J˜J˜J˜šœ˜ Jšœ2˜4Jšœ˜šœ:˜:Jšœ˜ —J˜—J˜J˜šœjœ˜oJšœhœ˜mšœœœ"˜1Jšœœœ ˜-—š˜šœ ˜ Jšœ6œ ˜AJšœ ˜——Jšœ˜Jšœ)˜)š˜Jšœ ˜——J˜J˜J˜šœœœ˜&Jšœ˜ šœœœ˜7š˜Jšœœ˜J˜—Jšœv˜xšœ˜Jšœ˜Jšœœ˜.Jš˜šœœ˜Jšœ3œ˜G—J˜——Jšœ˜ Jšœ œœœ%˜V—J˜J˜Jšœ˜ šœœœ˜7Jšœœ˜+J˜9J˜*J˜ Jšœœ˜J˜Jšœœ˜.J˜Jš œBœ_œ@œ;œ˜―JšœBœSœ˜ J˜J˜šœ%˜,Jšœ7œœ˜CJšœ_˜_Jšœœ˜ šœ'˜'Jšœ7œ˜B—J˜Jšœ$˜$J˜+Jšœ œ1˜A—Jšœ˜J˜Jšœ˜šœ˜Jšœ9œ˜Q—šœ˜JšœUœ˜t—Jšœ˜šœt˜tJšœq˜qšœœœ˜&Jšœœœ ˜/—š˜šœ ˜ Jšœ5œ ˜@Jšœ ˜——Jšœ˜Jšœ9œœ˜jš˜Jšœ ˜——Jšœ˜Jš˜—šœ˜ J˜—J˜Jš˜šœ-˜-Jšœ*˜*JšœX™XJšœ œ+˜Jšœ œœ+˜>Jšœ œœ œ+˜OJšœ œœ œ*˜N—J˜Jšœ˜šœœ œœ+˜AJšœ œœ+˜>Jšœ œœ œ+˜OJšœ œœ œ+˜OJšœ˜—J˜—Jšœ˜šœ˜J˜Jšœž œ ž œ ž œ&˜sJ˜—Jšœ˜—…—*P