home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Pascal / Snippets / sndDemo / sndDemo.p < prev    next >
Encoding:
Text File  |  1995-12-30  |  7.2 KB  |  193 lines  |  [TEXT/PJMM]

  1. program sndDemo;
  2.  
  3. { I spent a hard week getting this demo of the playing of an asynchronous sound to work }
  4. { in Think Pascal 4.0.2. My main difficulty was that it won't work with the [D] Debug switch set }
  5. { on the compile options. But the manual doesn't contain all of the necessary information.  }
  6. { Some essential ideas were gleaned from Jim Reekes' pSoundApp example in the DTS folder }
  7. { of ftp.apple.com.  Since it was so touchy, I thought others might benefit from this demo. }
  8. {  }
  9. { This code is terse. I have stripped out everything but the essentials. It should be used }
  10. { in conjuntion with chapter 22 of volume VI of Inside Macintosh. I have deliberately left }
  11. { out all error checking so as to not obscure the essential code. Although in all my testing }
  12. { I never saw an error that wasn't a result of my stupidity or ignorance. I have included a }
  13. { few extra inline procedure declarations to make it easier to build this demo into a real program. }
  14. {  }
  15. { To play an asynchronous sound - that is, a sound that plays while other things are happening, }
  16. { one must define a callBack procedure. This procedure can't do much because it will be invoked }
  17. { at interrupt time and won't have access to your normal program environment. To access your }
  18. { global variables, you must restore register A5. Most of the callBack code is concerned with }
  19. { restoring A5; and all the callback procedure does is set a switch 'sndProgress := 2' so that you }
  20. { can tell (elsewhere) that the sound has finished. }
  21. {  }
  22. { Two global variables are needed: }
  23. { - The integer sndProgress is meant to have the value 0 when no sound is playing, 1 when a sound}
  24. {    is playing, and 2 when a sound has finished but the resources haven't been released yet. }
  25. { - The sndChannelPtr mySndChannel is given a value when a sound channel is allocated in the }
  26. {    routine that starts the sound playing (aSyncStartPlay), and is needed to dispose of the channel }
  27. {    when the sound has completed and must be disposed (aSyncEndPlay). }
  28. {  }
  29. { If you use these routines to play async sounds, you will want a line of code in your main}
  30. { event loop to dispose of the channel and sound handle as soon as the sound has completed:}
  31. {           if sndProgress = 2 then                }
  32. {                aSyncEndPlay(sndChannel);     }
  33. {  }
  34. { What this demo program does, is start the sound playing and then count until the sound is done. }
  35. { The count is written to the text window. It does this five times. You must open the window manually }
  36. { and place it strategically if you want to watch the counting as the sound is played. }
  37. { ------------------------------------------------------------------------------------------ }
  38. { Marv Westrom }
  39. { Mathematics and Science Education (Computing Studies Education) }
  40. { The University of British Columbia }
  41. { Vancouver, B.C.   Canada    V6T 1Z4 }
  42. { ------------------------------------------------------------------------------------------ }
  43. { March 24, 1993.}
  44. { ------------------------------------------------------------------------------------------ }
  45.  
  46. {--- Changes by Ingemar Ragnemalm june 1994. ---}
  47. {}
  48. {I've changed capitalization of some constant and procedure names to conform better to the}
  49. { standards of Mac programming: procedures and types first letter upper-case, variables and}
  50. {constants not, constants should start with "k", globals variables with "g". How "integer"}
  51. {and "longint" should look, I'm not 100% sure - everybody does it different, it seems.}
  52. {}
  53. { I also compressed the sound 3:1, making the total archive REALLY small.}
  54. {}
  55. {A little warning: This code seems quite ok, but you may want to know a few things when}
  56. {using it:}
  57. {- You don't really have to have a callback procedure, if you don't care exactly when the}
  58. {previous sound finishes playing. Even then, you can use SndChannelStatus instead. You can}
  59. {stop the previous sound by disposing the channel.}
  60. {- You will get more speed if you don't dispose the channel after every sound, BUT that}
  61. {will increase the risk of crashes when using Sound Manager older than version 3.0 (and}
  62. {there are LOTS of Macs that aren't updated yet!!!) So if you want to get speed up, beware…}
  63. {Of course, some take the easy way out and don't guarantee anything with old SM, or just}
  64. {refuse to run if SM3 isn't present.}
  65. {Moral of the story: If you have only tested your code with SM3, it PROBABLY won't work}
  66. {will older Sound Managers. Assume that that is the case! Test with older SM or demand}
  67. {SM3!}
  68. {}
  69. {Finally, including Sound.p in the project, and "uses Sound" in the beginning, is usually}
  70. {preferrable over copying in a bunch of the declarations - at least when the used file}
  71. {doesn't need a whole bunch of others too.}
  72.  
  73. {Fix in late -95: PowerMac native.}
  74.  
  75.     uses
  76. {$IFC UNDEFINED THINK_PASCAL}
  77.         Types, QuickDraw, Events, Menus, Dialogs, Fonts, Resources, Devices, 
  78. {$ELSEC}
  79. {$SETC GENERATINGPOWERPC := false}
  80. {$ENDC}
  81.         Sound;
  82.  
  83.     const
  84.         kNoSynth = 0;        { no specified synth for channel }
  85.         kInitNone = 0;            { no specified init parameters for channel }
  86.  
  87.     var { necessary globals }
  88.         gMySndChannel: SndChannelPtr;
  89.         gSndProgress: integer;
  90.  
  91. {$PUSH}
  92. {$D-}
  93.     procedure MyCallBack (Chan: sndChannelPtr; var cmd: sndCommand);
  94.         var
  95.             myA5: longint;
  96.     begin
  97.         if cmd.param1 = 99 then
  98.             begin
  99.                 myA5 := SetA5(cmd.param2);
  100.                 gSndProgress := 2;
  101.                 myA5 := SetA5(myA5);
  102.             end;
  103.     end; {MyCallBack}
  104. {$POP}
  105.  
  106.     procedure AsyncStartPlay (sndH: handle);
  107.         var
  108.             mySndCmd: sndCommand;
  109.             myErr: OSErr;
  110. {$IFC GENERATINGPOWERPC }
  111.             callbackProc: ProcPtr;
  112. {$ENDC}
  113.     begin
  114.         LoadResource(sndH);
  115.         MoveHHi(sndH);
  116.         Hlock(sndH);
  117.         gMySndChannel := nil;
  118. {$IFC GENERATINGPOWERPC}
  119.         callbackProc := NewRoutineDescriptor(@MyCallBack, uppSndCallBackProcInfo, GetCurrentISA);
  120.         myErr := SndNewChannel(gMySndChannel, kNoSynth, kInitNone, callbackProc);
  121. {$ELSEC}
  122.         myErr := SndNewChannel(gMySndChannel, kNoSynth, kInitNone, @MyCallBack);
  123. {$ENDC}
  124.  
  125. {$IFC UNDEFINED THINK_PASCAL}
  126.         myErr := SndPlay(gMySndChannel, SndListHandle(sndH), true);
  127. {$ELSEC}
  128.         myErr := SndPlay(gMySndChannel, sndH, true);
  129. {$ENDC}
  130.         gSndProgress := 1;
  131.         mySndCmd.cmd := 13;                    { callBackCmd }
  132.         mySndCmd.param1 := 99;                { arbitrary code to check MyCallback }
  133.         mySndCmd.param2 := SetCurrentA5;
  134.         myErr := SndDoCommand(gMySndChannel, mySndCmd, false);
  135.     end; {AsyncStartPlay}
  136.  
  137.     procedure AsyncEndPlay (sndH: handle);
  138.         var
  139.             mySndCmd: sndCommand;
  140.             myErr: OSErr;
  141.     begin
  142.         mySndCmd.cmd := 3;        { quietCmd }
  143.         myErr := SndDoCommand(gMySndChannel, mySndCmd, false);
  144.         myErr := SndDisposeChannel(gMySndChannel, true);
  145.         HUnlock(sndH);
  146.         gSndProgress := 0;
  147.     end; {AsyncEndPlay}
  148.  
  149.     procedure InitMacintosh;
  150.     begin
  151. {$IFC UNDEFINED THINK_PASCAL}
  152.         MaxApplZone;
  153.  
  154.         InitGraf(@qd.thePort);
  155.         InitFonts;
  156.         FlushEvents(everyEvent, 0);
  157.         InitWindows;
  158.         InitMenus;
  159.         TEInit;
  160.         InitDialogs(nil);
  161. {$ENDC}
  162.         InitCursor;
  163.     end; {InitMacintosh}
  164.  
  165. {Variables that are local to the main procedure.}
  166.     var
  167.         sndHiThere: Handle;
  168.         i, times: integer;
  169.  
  170. begin
  171.     InitMacintosh;
  172.  
  173.     gSndProgress := 0;
  174.     sndHiThere := GetNamedResource('snd ', 'Hi There');
  175. {$IFC UNDEFINED THINK_PASCAL}
  176. {$ELSEC}
  177.     ShowText;
  178. {$ENDC}
  179.     for times := 1 to 5 do
  180.         begin
  181.             writeln;
  182.             writeln('Hi there ', times : 2);
  183.             AsyncStartPlay(sndHiThere);
  184.             i := 0;
  185.             repeat
  186.                 i := i + 1;
  187.                 write(i : 3);
  188.                 if (i mod 25) = 0 then
  189.                     writeln;
  190.             until gSndProgress = 2;
  191.             AsyncEndplay(sndHiThere);
  192.         end;
  193. end.