home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-06-15 | 6.5 KB | 173 lines | [TEXT/MWPS] |
- program sndDemo;
-
- { I spent a hard week getting this demo of the playing of an asynchronous sound to work }
- { in Think Pascal 4.0.2. My main difficulty was that it won't work with the [D] Debug switch set }
- { on the compile options. But the manual doesn't contain all of the necessary information. }
- { Some essential ideas were gleaned from Jim Reekes' pSoundApp example in the DTS folder }
- { of ftp.apple.com. Since it was so touchy, I thought others might benefit from this demo. }
- { }
- { This code is terse. I have stripped out everything but the essentials. It should be used }
- { in conjuntion with chapter 22 of volume VI of Inside Macintosh. I have deliberately left }
- { out all error checking so as to not obscure the essential code. Although in all my testing }
- { I never saw an error that wasn't a result of my stupidity or ignorance. I have included a }
- { few extra inline procedure declarations to make it easier to build this demo into a real program. }
- { }
- { To play an asynchronous sound - that is, a sound that plays while other things are happening, }
- { one must define a callBack procedure. This procedure can't do much because it will be invoked }
- { at interrupt time and won't have access to your normal program environment. To access your }
- { global variables, you must restore register A5. Most of the callBack code is concerned with }
- { restoring A5; and all the callback procedure does is set a switch 'sndProgress := 2' so that you }
- { can tell (elsewhere) that the sound has finished. }
- { }
- { Two global variables are needed: }
- { - The integer sndProgress is meant to have the value 0 when no sound is playing, 1 when a sound}
- { is playing, and 2 when a sound has finished but the resources haven't been released yet. }
- { - The sndChannelPtr mySndChannel is given a value when a sound channel is allocated in the }
- { routine that starts the sound playing (aSyncStartPlay), and is needed to dispose of the channel }
- { when the sound has completed and must be disposed (aSyncEndPlay). }
- { }
- { If you use these routines to play async sounds, you will want a line of code in your main}
- { event loop to dispose of the channel and sound handle as soon as the sound has completed:}
- { if sndProgress = 2 then }
- { aSyncEndPlay(sndChannel); }
- { }
- { What this demo program does, is start the sound playing and then count until the sound is done. }
- { The count is written to the text window. It does this five times. You must open the window manually }
- { and place it strategically if you want to watch the counting as the sound is played. }
- { ------------------------------------------------------------------------------------------ }
- { Marv Westrom }
- { Mathematics and Science Education (Computing Studies Education) }
- { The University of British Columbia }
- { Vancouver, B.C. Canada V6T 1Z4 }
- { ------------------------------------------------------------------------------------------ }
- { March 24, 1993.}
- { ------------------------------------------------------------------------------------------ }
-
- {--- Changes by Ingemar Ragnemalm june 1994. ---}
- {}
- {All I've done is to change capitalization of some constant and procedure names to conform better to the}
- { standards of Mac programming: procedures and types first letter upper-case, variables and constants}
- { not, constants should start with "k", globals variables with "g". How "integer" and "longint" should look,}
- { I'm not 100% sure - everybody does it different, it seems.}
- {}
- { I also compressed the sound 3:1, making the total archive REALLY small.}
- {}
- {A little warning: This code seems quite ok, but you may want to know a few things when using it:}
- {- You don't really have to have a callback procedure, if you don't care exactly when the previous sound}
- {finishes playing. Even then, you can use SndChannelStatus instead. You can stop the previous sound by}
- {disposing the channel.}
- {- You will get more speed if you don't dispose the channel after every sound, BUT that will increase}
- {the risk of crashes when using Sound Manager older than version 3.0 (and there are LOTS of Macs}
- {that aren't updated yet!!!) So if you want to get speed up, beware… Of course, some take the easy way}
- {out and don't guarantee anything with old SM.}
- {}
- {Finally, including Sound.p in the project, and "uses Sound" in the beginning, is usually preferrable over}
- {copying in a bunch of the declarations.}
-
- uses
- {$IFC UNDEFINED THINK_PASCAL}
- Types, QuickDraw, Events, Menus, Dialogs, Fonts, Resources, Devices,
- {$ENDC}
- Sound;
-
- const
- kNoSynth = 0; { no specified synth for channel }
- kInitNone = 0; { no specified init parameters for channel }
-
- var { necessary globals }
- gMySndChannel: SndChannelPtr;
- gSndProgress: integer;
-
- {$PUSH}
- {$D-}
- procedure MyCallBack (Chan: sndChannelPtr; cmd: sndCommand);
- var
- myA5: longint;
- begin
- if cmd.param1 = 99 then
- begin
- myA5 := SetA5(cmd.param2);
- gSndProgress := 2;
- myA5 := SetA5(myA5);
- end;
- end;
- {$POP}
-
- procedure AsyncStartPlay (sndH: handle);
- var
- mySndCmd: sndCommand;
- myErr: OSErr;
- begin
- LoadResource(sndH);
- MoveHHi(sndH);
- Hlock(sndH);
- gMySndChannel := nil;
- myErr := SndNewChannel(gMySndChannel, kNoSynth, kInitNone, @MyCallBack);
- {$IFC UNDEFINED THINK_PASCAL}
- myErr := SndPlay(gMySndChannel, SndListHandle(sndH), true);
- {$ELSEC}
- myErr := SndPlay(gMySndChannel, sndH, true);
- {$ENDC}
- gSndProgress := 1;
- mySndCmd.cmd := 13; { callBackCmd }
- mySndCmd.param1 := 99; { arbitrary code to check MyCallback }
- mySndCmd.param2 := SetCurrentA5;
- myErr := SndDoCommand(gMySndChannel, mySndCmd, false);
- end;
-
- procedure AsyncEndPlay (sndH: handle);
- var
- mySndCmd: sndCommand;
- myErr: OSErr;
- begin
- mySndCmd.cmd := 3; { quietCmd }
- myErr := SndDoCommand(gMySndChannel, mySndCmd, false);
- myErr := SndDisposeChannel(gMySndChannel, true);
- HUnlock(sndH);
- gSndProgress := 0;
- end;
-
- procedure InitMacintosh;
- begin
- {$IFC UNDEFINED THINK_PASCAL}
- MaxApplZone;
-
- InitGraf(@qd.thePort);
- InitFonts;
- FlushEvents(everyEvent, 0);
- InitWindows;
- InitMenus;
- TEInit;
- InitDialogs(nil);
- {$ENDC}
- InitCursor;
- end; {InitMacintosh}
-
- {Variables that are local to the main procedure.}
- var
- sndHiThere: Handle;
- i, times: integer;
-
- begin
- InitMacintosh;
-
- gSndProgress := 0;
- sndHiThere := GetNamedResource('snd ', 'Hi There');
- {$IFC DEFINED THINK_PASCAL}
- ShowText;
- {$ENDC}
- for times := 1 to 5 do
- begin
- writeln;
- writeln('Hi there ', times : 2);
- AsyncStartPlay(sndHiThere);
- i := 0;
- repeat
- i := i + 1;
- write(i : 3);
- if (i mod 25) = 0 then
- writeln;
- until gSndProgress = 2;
- AsyncEndplay(sndHiThere);
- end;
- end.