home *** CD-ROM | disk | FTP | other *** search
/ ftp.mactech.com 2010 / ftp.mactech.com.tar / ftp.mactech.com / macintosh-pascal / macintoshp-1.2-demos.sit.hqx / chap21pascal_demo / SoundPascal.p < prev    next >
Text File  |  1999-04-05  |  21KB  |  813 lines

  1. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊
  2. // SoundPascal.p
  3. // ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊
  4. //
  5. // This program opens a modal dialog containing eight button controls arranged in two
  6. // groups, namely, a synchronous sound group and an asynchronous sound group.  Clicking
  7. // on the buttons causes sound to be played back or recorded as follows:
  8. //
  9. // •    Synchronous group:
  10. //
  11. //        •  Play sound resource.
  12. //
  13. //        •  Play sound file.
  14. //
  15. //        •  Record sound resource.          
  16. //
  17. //        •  Record sound file.
  18. //
  19. //        •  Speak text string.
  20. //
  21. // •    Asynchronous group:
  22. //
  23. //        •  Start and stop looped sound playback.
  24. //
  25. //        •  Play unlooped sound.
  26. //
  27. //        •  Speak text string.
  28. //
  29. // At startup, the program checks for play-from-disk, sound recording capability, speech
  30. // capability, and multi-channel capability. If these are not available, the relevant 
  31. // buttons are disabled. 
  32. //
  33. // The asynchronous sound sections of the program utilise a special library called
  34. // AsyncSoundLib, which must be included in the CodeWarrior project.
  35. //
  36. // The program utilises the following resources:
  37. //
  38. // •    A 'DLOG' resource and associated 'DITL' and 'dctb' resources (all purgeable).
  39. //
  40. // •    Three 'snd ' resources, one for synchronous playback (purgeable), one for looped 
  41. //        asynchronous playback (unpurgeable), and one for unlooped asynchronous playback
  42. //        (purgeable).
  43. //
  44. // •    Two 'cicn' resources (purgeable) used to provide an animated display which halts
  45. //        during synchronous playback and continues during asynchronous playback.
  46. //
  47. // •    Three 'STR#' resources containing error message strings and "speak text" strings
  48. //        (all purgeable). 
  49. //
  50. // •    Two 'ALRT' resources (purgeable) for displaying error messages.
  51. //
  52. // In addition, the function doPlayFile utilises the file "soundfile.aiff".
  53. //
  54. // Each time is is invoked, the function doRecordResource creates a new 'snd' resource 
  55. // with a unique ID in the application's resource fork.
  56. //
  57. // When first invoked, the function doRecordFile creates the file "test.aiff" in the
  58. // chap21cw_demo folder.  All subsequent record-to-file is to this file.  
  59. //
  60. // ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ }
  61.  
  62. program SoundPascal(input, output);
  63.  
  64. { …………………………………………………………………………………………………………………… include the following Universal Interfaces }
  65.  
  66. uses
  67.  
  68.     Windows, Fonts, Menus, TextEdit, Quickdraw, Dialogs, QuickdrawText, Processes, Types, 
  69.     Memory, Events, TextUtils, ToolUtils, OSUtils, Devices, SegLoad, Resources, 
  70.     Sound, SoundInput, Speech, GestaltEqu, Icons;
  71.  
  72. { …………………………………………………………………………………………………………………………………………………… define the following constants }
  73.  
  74. const
  75.  
  76. rDialog = 128;
  77.  iQuit = 1;
  78.  iPlayResource = 2;
  79.  iPlayFile = 3;
  80.  iRecordResource = 4;
  81.  iRecordFile = 5;
  82.  iSpeakTextSync = 6;
  83.  iLoopedSound = 7;
  84.  iUnloopedSound = 8;    
  85.  iSpeakTextAsync = 9;
  86.  iSynchSoundRect = 10;
  87.  iAsynchSoundRect = 11;
  88. rPlaySoundResource = 8192;
  89. rLoopedSound = 8193;
  90. rUnloopedSound = 8194;
  91. rSpeechStrings = 130;
  92. rErrorAlert = 129;
  93. rErrorStrings = 128;
  94.  eOpenDialogFail = 1;
  95.  eLoopedSoundSetUp = 2;
  96.  eCannotInitialise = 3;
  97.  eGetResource = 4;
  98.  eNoChannelsAvailable = 5;
  99.  ePlaySound = 6;
  100.  eMemory = 7;
  101. rErrorAlertWithCode = 130;
  102. rErrorStringsWithCode = 129;
  103.  eSndPlay = 1;        
  104.  ePlayFile = 2;
  105.  eSndRecord = 3;
  106.  eWriteResource = 4;
  107.  eRecordFile = 5;
  108.  eSpeakString = 6;
  109.  eSndDoImmediate = 7;
  110. rColourIcon1 = 128;
  111. rColourIcon2 = 129;
  112. kMaxChannels = 8;
  113. kOutOfChannels = 1;
  114.  
  115. { ………………………………………………………………………………………………………………………………………………………………………………………… global variables }
  116.  
  117. var
  118.  
  119. gDone : boolean;
  120. gDialogPtr : DialogPtr;
  121. gAppResFileRefNum : integer;
  122. gColorQuickDrawPresent : boolean;
  123. gHasSoundPlayDoubBuff : boolean;
  124. gHasSoundInputDevice : boolean;
  125. gHasSpeechmanager : boolean;
  126. gHasMultiChannel : boolean;
  127. gLoopedSoundOn : boolean;
  128. gLoopedSoundRefNum : longint;
  129. gLoopedSoundChannel : SndChannelPtr;
  130. gColourIconHdl1 : CIconHandle;
  131. gColourIconHdl2 : CIconHandle;
  132.  
  133. theErr : OSErr;
  134. response : longint;
  135.  
  136. { ………………………………………………………………………………………………………………………………………………………… AsyncSoundLib attention flag }
  137.  
  138. gCallASLcloseChannel : boolean;
  139.  
  140. { …………………………………………………………………………………………………………………………………………… procedure and function interfaces }
  141.  
  142. procedure DoInitManagers; forward;
  143. procedure DoCheckSoundEnv; forward;
  144. procedure DoInitialiseASL; forward;
  145. function  DoLoopedSoundSetUp : boolean; forward;
  146. procedure EventLoop; forward;
  147. procedure DoDialogHit(item : integer); forward;
  148. procedure DoPlayResource; forward;
  149. procedure DoPlayFile; forward;
  150. procedure DoRecordResource; forward;
  151. procedure DoRecordFile; forward;
  152. procedure DoSpeakStringSync; forward;
  153. procedure DoLoopedSoundAsync; forward;
  154. procedure DoUnloopedSoundAsync; forward;
  155. procedure DoSpeakStringAsync; forward;
  156. procedure DoSetUpDialog; forward;
  157. procedure DrawDialog(theDialogPtr : DialogPtr; theItem : integer); forward;
  158. procedure DoAdjustItems; forward;
  159. procedure DoErrorAlert(stringIndex : integer); forward;
  160. procedure DoErrorAlertWithCode(stringIndex, resultCode : integer); forward;
  161.  
  162. { ………………………………………………………………………………………………………………………………………… AsyncSoundLib procedure interfaces }
  163.  
  164. function  ASLinitialise(var attnFlag : boolean; numChannels : integer) : OSErr; C; external;
  165. function  ASLgetChannel(refNum : longint; var channel : SndChannelPtr) : OSErr; C; external;
  166. function  ASLplayID(resID: integer;  refNum : UNIV Ptr) : OSErr; C; external;
  167. function  ASLplayHandle(sound : Handle; refNum : UNIV Ptr) : OSErr; C; external;
  168. procedure ASLcloseChannel; C; external;
  169. procedure ASLcloseDown; C; external;
  170.  
  171. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoInitManagers }
  172.  
  173. procedure DoInitManagers;
  174.  
  175.     begin
  176.     MaxApplZone;
  177.     MoreMasters;
  178.  
  179.     InitGraf(@qd.thePort);
  180.     InitFonts;
  181.     InitWindows;
  182.     InitMenus;
  183.     TEInit;
  184.     InitDialogs(nil);
  185.  
  186.     InitCursor;    
  187.     FlushEvents(everyEvent, 0);
  188.     end;
  189.         {of procedure DoInitManagers}
  190.         
  191. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoCheckSoundEnv }
  192.  
  193. procedure DoCheckSoundEnv;
  194.  
  195.     var
  196.     theErr : OSErr;
  197.     response : longint;
  198.  
  199.     begin
  200.     theErr := Gestalt(gestaltSoundAttr,response);
  201.  
  202.     if (theErr = noErr) then
  203.         gHasSoundPlayDoubBuff := BitTst(@response,31 - gestaltSndPlayDoubleBuffer)
  204.     else
  205.         gHasSoundPlayDoubBuff := false;
  206.  
  207.     if (theErr = noErr) then
  208.         gHasSoundInputDevice := BitTst(@response,31 - gestaltHasSoundInputDevice)
  209.     else
  210.         gHasSoundInputDevice := false;
  211.  
  212.     if (theErr = noErr) then
  213.         gHasSpeechmanager := BitTst(@response,31 - gestaltSpeechMgrPresent)
  214.     else
  215.         gHasSpeechmanager := false;
  216.  
  217.     if (theErr = noErr) then
  218.         gHasMultiChannel := BitTst(@response,31 - gestaltMultiChannels)        
  219.     else
  220.         gHasMultiChannel := false;
  221.     end;
  222.         {of procedure DoCheckSoundEnv}
  223.  
  224. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoInitialiseASL }
  225.  
  226. procedure DoInitialiseASL;
  227.  
  228.     begin
  229.     if (ASLinitialise(gCallASLcloseChannel, kMaxChannels) <> noErr) then
  230.         begin
  231.         DoErrorAlert(eCannotInitialise);
  232.         ExitToShell;
  233.         end;
  234.     end;
  235.         {of procedure DoInitialiseASL}
  236.         
  237. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoLoopedSoundSetUp }
  238.  
  239. function DoLoopedSoundSetUp : boolean;
  240.  
  241.     var
  242.     error : integer;
  243.     theErr : OSErr;
  244.     soundHdl : Handle;
  245.  
  246.     begin
  247.     error := ASLplayHandle(nil, @gLoopedSoundRefNum);
  248.     if (error <> 0) then
  249.         begin
  250.         DoLoopedSoundSetUp := false;
  251.         Exit(DoLoopedSoundSetUp);
  252.         end
  253.     else begin
  254.         error := ASLgetChannel(gLoopedSoundRefNum, gLoopedSoundChannel);
  255.         if (error <> 0) then
  256.             begin
  257.             DoLoopedSoundSetUp := false;
  258.             Exit(DoLoopedSoundSetUp);
  259.             end;
  260.         
  261.         soundHdl := GetResource('snd ', rLoopedSound);
  262.         if (soundHdl <> nil)  then
  263.             begin
  264.             HLockHi(soundHdl);
  265.             theErr := SndPlay(gLoopedSoundChannel, SndListHandle(soundHdl), true);
  266.             if (theErr <> noErr) then
  267.                 begin
  268.                 DoLoopedSoundSetUp := false;
  269.                 Exit(DoLoopedSoundSetUp);
  270.                 end;
  271.             end
  272.         else begin
  273.             DoLoopedSoundSetUp := false;
  274.             Exit(DoLoopedSoundSetUp);
  275.             end;
  276.         end;
  277.     
  278.     DoLoopedSoundSetUp := true;
  279.     end;
  280.         {of procedure DoLoopedSoundSetUp}
  281.         
  282. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ EventLoop }
  283.  
  284. procedure EventLoop;
  285.  
  286.     var
  287.     theRect, eraseRect : Rect;
  288.     gotEvent : boolean;
  289.     eventRec : EventRecord;
  290.     theDialogPtr : DialogPtr;
  291.     itemHit : integer;
  292.     finalTicks : UInt32;
  293.  
  294.     begin
  295.     gDone := false;
  296.  
  297.     SetRect(theRect, 10, 273, 35, 299);
  298.     SetRect(eraseRect, 45, 273, 125, 299);
  299.  
  300.     while not (gDone) do
  301.         begin        
  302.         if (gCallASLcloseChannel) then
  303.             begin
  304.             ASLcloseChannel;
  305.  
  306.             TextFont(kFontIDGeneva);
  307.             TextSize(9);
  308.             MoveTo(45, 285);
  309.             DrawString('ASLcloseChannel');
  310.             MoveTo(45, 295);
  311.             DrawString('called');
  312.             end;
  313.                 
  314.         gotEvent := WaitNextEvent(everyEvent, eventRec, 10, nil);
  315.  
  316.         if (gotEvent) then
  317.             begin
  318.             if (IsDialogEvent(eventRec)) then
  319.                 if (DialogSelect(eventRec, theDialogPtr, itemHit)) then
  320.                     DoDialogHit(itemHit);
  321.             end
  322.         else begin
  323.             if (gColorQuickDrawPresent) then
  324.                 begin
  325.                 PlotCIcon(theRect, gColourIconHdl1);
  326.                 Delay(15, finalTicks);
  327.                 PlotCIcon(theRect, gColourIconHdl2);
  328.                 Delay(15, finalTicks);
  329.                 EraseRect(eraseRect);
  330.                 end;
  331.             end;
  332.         end;
  333.     
  334.     DisposeDialog(gDialogPtr);
  335.     
  336.     ASLcloseDown;
  337.     end;
  338.         {of procedure EventLoop}
  339.  
  340. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoDialogHit }
  341.  
  342. procedure DoDialogHit(item : integer);
  343.  
  344.     begin
  345.     case (item) of
  346.  
  347.         iQuit: begin
  348.             gDone := true;
  349.             end;
  350.  
  351.         iPlayResource: begin
  352.             DoPlayResource;
  353.             end;
  354.  
  355.         iPlayFile: begin
  356.             DoPlayFile;
  357.             end;
  358.  
  359.         iRecordResource: begin
  360.             DoRecordResource;
  361.             end;
  362.  
  363.         iRecordFile: begin
  364.             DoRecordFile;
  365.             end;
  366.  
  367.         iSpeakTextSync: begin
  368.             DoSpeakStringSync;
  369.             end;
  370.  
  371.         iLoopedSound: begin
  372.             DoLoopedSoundAsync;
  373.             end;
  374.  
  375.         iUnloopedSound: begin
  376.             DoUnloopedSoundAsync;
  377.             end;
  378.             
  379.         iSpeakTextAsync: begin
  380.             DoSpeakStringAsync;
  381.             end;
  382.         end;
  383.             {of case statement}            
  384.     end;
  385.         {of procedure DoDialogHit}
  386.  
  387. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoPlayResource }
  388.  
  389. procedure DoPlayResource;
  390.  
  391.     var
  392.     sndListHdl : SndListHandle;
  393.     resErr : integer;
  394.     theErr : OSErr;
  395.  
  396.     begin
  397.     sndListHdl := SndListHandle(GetResource('snd ', rPlaySoundResource));
  398.     resErr := ResError;
  399.     if (resErr <> noErr) then
  400.         DoErrorAlert(eGetResource);        
  401.     
  402.     if (sndListHdl <> nil) then
  403.         begin
  404.         HLock(Handle(sndListHdl));
  405.         theErr := SndPlay(nil, sndListHdl, false);
  406.         if (theErr <> noErr) then
  407.             DoErrorAlertWithCode(eSndPlay, theErr);            
  408.         HUnlock(Handle(sndListHdl));
  409.         ReleaseResource(Handle(sndListHdl));
  410.         end;
  411.     end;
  412.         {of procedure DoPlayResource}
  413.  
  414. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoPlayFile } 
  415.  
  416. procedure DoPlayFile;
  417.  
  418.     var
  419.     theErr : OSErr;
  420.     fileSysSpec : FSSpec;
  421.     fileRefNum : integer;
  422.     ignoredErr : OSErr;
  423.     
  424.     begin        
  425.     theErr := FSMakeFSSpec(0, 0, ':soundfile.aiff', fileSysSpec);
  426.     
  427.     if (theErr = noErr) then
  428.         theErr := FSpOpenDF(fileSysSpec, fsRdPerm, fileRefNum);
  429.         
  430.     if (theErr = noErr) then
  431.         ignoredErr := SetFPos(fileRefNum, fsFromStart, 0);
  432.         
  433.     if (theErr = noErr) then
  434.         theErr := SndStartFilePlay(nil, fileRefNum, 0, 20480, nil, nil, nil, false);
  435.         
  436.     if (theErr <> noErr) then
  437.         DoErrorAlertWithCode(ePlayFile, theErr);            
  438.  
  439.     ignoredErr := FSClose(fileRefNum);
  440.     end;
  441.         {of procedure DoPlayFile}
  442.  
  443. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoRecordResource }
  444.  
  445. procedure DoRecordResource;
  446.  
  447.     var
  448.     oldResFileRefNum : integer;
  449.     topLeft : Point;
  450.     soundHdl : Handle;
  451.     theErr, memErr : OSErr;
  452.     theResourceID, resErr : integer;
  453.             
  454.     begin
  455.     oldResFileRefNum := CurResFile;
  456.     UseResFile(gAppResFileRefNum);
  457.  
  458.     topLeft.v := 40;
  459.     topLeft.h := 250;
  460.     
  461.     soundHdl := NewHandle(25000);
  462.     memErr := MemError;
  463.     if (memErr <> noErr) then
  464.         begin
  465.         DoErrorAlert(eMemory);
  466.         Exit(DoRecordResource);
  467.         end;
  468.         
  469.     theErr := SndRecord(nil, topLeft, siBetterQuality, SndListHandle(soundHdl));
  470.     if ((theErr <> noErr) and (theErr <> userCanceledErr)) then
  471.         DoErrorAlertWithCode(eSndRecord, theErr)
  472.     else begin
  473.         repeat
  474.         theResourceID := UniqueID('snd ');
  475.         until (theResourceID >= 8191);
  476.  
  477.         AddResource(Handle(soundHdl), 'snd ', theResourceID, 'Test');
  478.         resErr := ResError;
  479.         if (resErr = noErr) then
  480.             UpdateResFile(gAppResFileRefNum);
  481.             
  482.         resErr := ResError;
  483.         if (resErr <> noErr) then
  484.             DoErrorAlertWithCode(eWriteResource, resErr);
  485.         end;
  486.  
  487.     UseResFile(oldResFileRefNum);
  488.     end;
  489.         {of procedure DoRecordResource}
  490.  
  491. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoRecordFile }
  492.  
  493. procedure DoRecordFile;
  494.  
  495.     var
  496.     topLeft : Point;
  497.     theErr : OSErr;
  498.     fileSysSpec : FSSpec;
  499.     fileRefNum : integer;
  500.     ignoredErr : OSErr;
  501.         
  502.     begin    
  503.     topLeft.v := 40;
  504.     topLeft.h := 250;
  505.     
  506.     theErr := FSMakeFSSpec(0, 0, ':test.aiff', fileSysSpec);
  507.     if (theErr = fnfErr) then
  508.         theErr := FSpCreate(fileSysSpec, '????', 'AIFF', smSystemScript);
  509.         
  510.     if (theErr = noErr) then
  511.         theErr := FSpOpenDF(fileSysSpec, fsWrPerm, fileRefNum);
  512.         
  513.     if (theErr = noErr) then
  514.         ignoredErr := SetFPos(fileRefNum, fsFromStart, 0);
  515.         
  516.     if (theErr = noErr) then
  517.         theErr := SndRecordToFile(nil, topLeft, siBetterQuality, fileRefNum);
  518.         
  519.     if ((theErr <> noErr) and (theErr <> userCanceledErr)) then
  520.         DoErrorAlertWithCode(eRecordFile, theErr);            
  521.  
  522.     ignoredErr := FSClose(fileRefNum);
  523.     end;
  524.         {of procedure DoRecordFile}
  525.  
  526. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoSpeakStringSync }
  527.  
  528. procedure DoSpeakStringSync;
  529.  
  530.     var
  531.     activeChannels : integer;
  532.     theString : Str255;
  533.     resErr, theErr : OSErr;
  534.         
  535.     begin
  536.     activeChannels := SpeechBusy;
  537.  
  538.     GetIndString(theString, rSpeechStrings, 1);
  539.     resErr := ResError;
  540.     if (resErr <> noErr) then
  541.         begin
  542.         DoErrorAlert(eGetResource);
  543.         Exit(DoSpeakStringSync);
  544.         end;
  545.     
  546.     theErr := SpeakString(theString);
  547.     if (theErr <> noErr) then
  548.         DoErrorAlertWithCode(eSpeakString, theErr);
  549.         
  550.     while (SpeechBusy <> activeChannels) do ;
  551.     end;
  552.         {of procedure DoSpeakStringSync}
  553.  
  554. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoLoopedSoundAsync }
  555.  
  556. procedure DoLoopedSoundAsync;
  557.  
  558.     var
  559.     soundCommand : SndCommand;
  560.     theErr : OSErr;
  561.             
  562.     begin
  563.     gLoopedSoundOn := not (gLoopedSoundOn);
  564.  
  565.     DoAdjustItems;
  566.  
  567.     soundCommand.param1 := 0;
  568.     
  569.     if (gLoopedSoundOn) then
  570.         begin
  571.         soundCommand.cmd := freqCmd;
  572.         soundCommand.param2 := $3C;
  573.         end 
  574.     else begin
  575.         soundCommand.cmd := quietCmd;
  576.         soundCommand.param2 := 0;
  577.         end;
  578.     
  579.     theErr := SndDoImmediate(gLoopedSoundChannel, soundCommand);
  580.     if (theErr <> noErr) then
  581.         DoErrorAlertWithCode(eSndDoImmediate, theErr);
  582.     end;
  583.         {of procedure DoLoopedSoundAsync}
  584.         
  585. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoUnloopedSoundAsync }
  586.  
  587. procedure DoUnloopedSoundAsync;
  588.  
  589.     var
  590.     error : integer;
  591.     
  592.     begin
  593.     error := ASLplayID(rUnloopedSound, nil);
  594.     if (error = kOutOfChannels) then
  595.         DoErrorAlert(eNoChannelsAvailable)
  596.     else if (error <> noErr) then
  597.         DoErrorAlert(ePlaySound);
  598.     end;
  599.         {of procedure DoUnloopedSoundAsync}
  600.  
  601. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoSpeakStringAsync }
  602.  
  603. procedure DoSpeakStringAsync;
  604.  
  605.     var
  606.     theString : Str255;
  607.     resErr, theErr : OSErr;
  608.  
  609.     begin
  610.     GetIndString(theString, rSpeechStrings, 2);
  611.     resErr := ResError;
  612.     if (resErr <> noErr) then
  613.         begin
  614.         DoErrorAlert(eGetResource);
  615.         Exit(DoSpeakStringAsync);
  616.         end;
  617.     
  618.     theErr := SpeakString(theString);
  619.     if (theErr <> noErr) then
  620.         DoErrorAlertWithCode(eSpeakString, theErr);
  621.     end;
  622.         {of procedure DoSpeakStringAsync}
  623.  
  624. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoSetUpDialog }
  625.  
  626. procedure DoSetUpDialog;
  627.  
  628.     var
  629.     itemType : integer;
  630.     itemHdl : Handle;
  631.     itemRect : Rect;
  632.             
  633.     begin
  634.     GetDialogItem(gDialogPtr, iSynchSoundRect, itemType, itemHdl, itemRect);
  635.     SetDialogItem(gDialogPtr, iSynchSoundRect, itemType, Handle(@DrawDialog), itemRect);
  636.  
  637.     if not (gHasSoundPlayDoubBuff) then
  638.         begin
  639.         GetDialogItem(gDialogPtr, iPlayFile, itemType, itemHdl, itemRect);
  640.         HiliteControl(ControlHandle(itemHdl), 255);
  641.         end;
  642.  
  643.     if not (gHasSoundInputDevice) then
  644.         begin
  645.         GetDialogItem(gDialogPtr, iRecordResource, itemType, itemHdl, itemRect);
  646.         HiliteControl(ControlHandle(itemHdl), 255);
  647.         GetDialogItem(gDialogPtr, iRecordFile, itemType, itemHdl, itemRect);
  648.         HiliteControl(ControlHandle(itemHdl), 255);
  649.         end;
  650.     
  651.     if not (gHasSpeechmanager) then
  652.         begin
  653.         GetDialogItem(gDialogPtr, iSpeakTextSync, itemType, itemHdl, itemRect);
  654.         HiliteControl(ControlHandle(itemHdl), 255);
  655.         GetDialogItem(gDialogPtr, iSpeakTextAsync, itemType, itemHdl, itemRect);
  656.         HiliteControl(ControlHandle(itemHdl), 255);
  657.         end;
  658.  
  659.     if not (gHasMultiChannel) then
  660.         begin
  661.         GetDialogItem(gDialogPtr, iLoopedSound, itemType, itemHdl, itemRect);
  662.         HiliteControl(ControlHandle(itemHdl), 255);
  663.         end;    
  664.     end;
  665.         {of procedure DoSetUpDialog}
  666.  
  667. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DrawDialog }
  668.  
  669. procedure DrawDialog(theDialogPtr : DialogPtr; theItem : integer);
  670.  
  671.     var
  672.     itemType : integer;
  673.     itemHdl : Handle;
  674.     itemRect : Rect;
  675.     buttonOval : integer;
  676.  
  677.     begin
  678.     GetDialogItem(theDialogPtr, iSynchSoundRect, itemType, itemHdl, itemRect);
  679.     FrameRect(itemRect);
  680.     GetDialogItem(theDialogPtr, iAsynchSoundRect, itemType, itemHdl, itemRect);
  681.     FrameRect(itemRect);
  682.     GetDialogItem(theDialogPtr, iQuit, itemType, itemHdl, itemRect);
  683.     InsetRect(itemRect, -4, -4);
  684.     PenSize(3, 3);
  685.     buttonOval := (itemRect.bottom - itemRect.top) div 2 + 2;
  686.     FrameRoundRect(itemRect, buttonOval, buttonOval);
  687.     end;
  688.         {of procedure DrawDialog}
  689.  
  690. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoAdjustItems }
  691.  
  692. procedure DoAdjustItems;
  693.  
  694.     var
  695.     itemType, a : integer;
  696.     itemHdl : Handle;
  697.     itemRect : Rect;
  698.  
  699.     begin
  700.     GetDialogItem(gDialogPtr, iLoopedSound, itemType, itemHdl, itemRect);
  701.     if (gLoopedSoundOn) then
  702.         SetControlTitle(ControlHandle(itemHdl), 'Switch Looped Sound Off')
  703.     else
  704.         SetControlTitle(ControlHandle(itemHdl), 'Switch Looped Sound On');
  705.  
  706.     for a := iRecordResource to iRecordFile do
  707.         begin
  708.         GetDialogItem(gDialogPtr, a, itemType, itemHdl, itemRect);
  709.         if (gLoopedSoundOn) then
  710.             HiliteControl(ControlHandle(itemHdl), 255)
  711.         else
  712.             HiliteControl(ControlHandle(itemHdl), 0);
  713.         end;        
  714.     end;
  715.         {of procedure DoAdjustItems}
  716. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoErrorAlert }
  717.  
  718. procedure DoErrorAlert(stringIndex : integer);
  719.  
  720.     var
  721.     errorString : string;
  722.     ignoredErr : OSErr;
  723.     
  724.     begin
  725.     GetIndString(errorString, rErrorStrings, stringIndex);
  726.     ParamText(errorString, '', '', '');
  727.     ignoredErr := StopAlert(rErrorAlert, nil);
  728.     end;
  729.         {of procedure DoErrorAlert}
  730.  
  731. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoErrorAlertWithCode }
  732.  
  733. procedure DoErrorAlertWithCode(stringIndex, resultCode : integer);
  734.  
  735.     var
  736.     errorString, resultCodeString : string;
  737.     ignoredErr : OSErr;
  738.     
  739.     begin
  740.     GetIndString(errorString, rErrorStringsWithCode, stringIndex);
  741.     NumToString(longint(resultCode), resultCodeString);
  742.  
  743.     ParamText(errorString, resultCodeString, '', '');
  744.     ignoredErr := StopAlert(rErrorAlertWithCode, nil);
  745.     end;
  746.         {of procedure DoErrorAlertWithCode}
  747.  
  748. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ start of main program }
  749.  
  750. begin
  751.  
  752.     gColorQuickDrawPresent := false;
  753.     gLoopedSoundOn := false;
  754.     gCallASLcloseChannel := false;
  755.     
  756.     { ……………………………………………………………………………………………………………………………………………………… check for Color QuickDraw }
  757.  
  758.     theErr := Gestalt(gestaltQuickdrawVersion, response);
  759.     if (response >= gestalt8BitQD) then
  760.         gColorQuickDrawPresent := true;
  761.  
  762.     { ……………………………………………………………………………………………………………………………………………………………………… initialise managers }
  763.  
  764.     DoInitManagers;
  765.  
  766.     { ……………………………………………………………………………… save reference number of application's resource file } 
  767.     
  768.     gAppResFileRefNum := CurResFile;
  769.  
  770.     { …………………………………………………………… check for sound recording equipment and speech capabilities }
  771.  
  772.     DoCheckSoundEnv;
  773.  
  774.     { ……………………………………………………………………………………………… open and set up modal dialog, get colour icons }
  775.  
  776.     gDialogPtr := GetNewDialog(rDialog, nil, WindowPtr(-1));
  777.     if (gDialogPtr = nil) then
  778.         begin
  779.         DoErrorAlert(eOpenDialogFail);
  780.         ExitToShell;
  781.         end;
  782.  
  783.     SetPort(gDialogPtr);
  784.  
  785.     DoSetUpDialog;
  786.  
  787.     if (gColorQuickDrawPresent) then
  788.         begin
  789.         gColourIconHdl1 := GetCIcon(rColourIcon1);
  790.         gColourIconHdl2 := GetCIcon(rColourIcon2);
  791.         end;
  792.     
  793.     { ………………………………………………………………………………………………………………………………………………………… initialize AsychSoundLib }
  794.  
  795.     DoInitialiseASL;
  796.  
  797.     { ……………………………………………………………………………………………………………………………………………………………………… set up looped sound }
  798.  
  799.     if (gHasMultiChannel) then
  800.         if not (DoLoopedSoundSetUp) then
  801.             begin
  802.             DoErrorAlert(eLoopedSoundSetUp);
  803.             ASLcloseDown;
  804.             ExitToShell;
  805.             end;
  806.  
  807.     { ……………………………………………………………………………………………………………………………………………………………………………… enter event loop }
  808.  
  809.     EventLoop;
  810.  
  811. end.
  812.     
  813. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ }