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 / chap23pascal_demo / chap21pascal_demoPPC / SoundPascalPPC.p < prev    next >
Text File  |  1997-01-21  |  21KB  |  820 lines

  1. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊
  2. // SoundPascalPPC.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. drawDialogRD : UserItemUPP;                                                 { For PowerPC }
  137.  
  138. { ………………………………………………………………………………………………………………………………………………………… AsyncSoundLib attention flag }
  139.  
  140. gCallASLcloseChannel : boolean;
  141.  
  142. { …………………………………………………………………………………………………………………………………………… procedure and function interfaces }
  143.  
  144. procedure DoInitManagers; forward;
  145. procedure DoCheckSoundEnv; forward;
  146. procedure DoInitialiseASL; forward;
  147. function  DoLoopedSoundSetUp : boolean; forward;
  148. procedure EventLoop; forward;
  149. procedure DoDialogHit(item : integer); forward;
  150. procedure DoPlayResource; forward;
  151. procedure DoPlayFile; forward;
  152. procedure DoRecordResource; forward;
  153. procedure DoRecordFile; forward;
  154. procedure DoSpeakStringSync; forward;
  155. procedure DoLoopedSoundAsync; forward;
  156. procedure DoUnloopedSoundAsync; forward;
  157. procedure DoSpeakStringAsync; forward;
  158. procedure DoSetUpDialog; forward;
  159. procedure DrawDialog(theDialogPtr : DialogPtr; theItem : integer); forward;
  160. procedure DoAdjustItems; forward;
  161. procedure DoErrorAlert(stringIndex : integer); forward;
  162. procedure DoErrorAlertWithCode(stringIndex, resultCode : integer); forward;
  163.  
  164. { ………………………………………………………………………………………………………………………………………… AsyncSoundLib procedure interfaces }
  165.  
  166. function  ASLinitialise(var attnFlag : boolean; numChannels : integer) : OSErr; C; external;
  167. function  ASLgetChannel(refNum : longint; var channel : SndChannelPtr) : OSErr; C; external;
  168. function  ASLplayID(resID: integer;  refNum : UNIV Ptr) : OSErr; C; external;
  169. function  ASLplayHandle(sound : Handle; refNum : UNIV Ptr) : OSErr; C; external;
  170. procedure ASLcloseChannel; C; external;
  171. procedure ASLcloseDown; C; external;
  172.  
  173. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoInitManagers }
  174.  
  175. procedure DoInitManagers;
  176.  
  177.     begin
  178.     MaxApplZone;
  179.     MoreMasters;
  180.  
  181.     InitGraf(@qd.thePort);
  182.     InitFonts;
  183.     InitWindows;
  184.     InitMenus;
  185.     TEInit;
  186.     InitDialogs(nil);
  187.  
  188.     InitCursor;    
  189.     FlushEvents(everyEvent, 0);
  190.     end;
  191.         {of procedure DoInitManagers}
  192.         
  193. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoCheckSoundEnv }
  194.  
  195. procedure DoCheckSoundEnv;
  196.  
  197.     var
  198.     theErr : OSErr;
  199.     response : longint;
  200.  
  201.     begin
  202.     theErr := Gestalt(gestaltSoundAttr,response);
  203.  
  204.     if (theErr = noErr) then
  205.         gHasSoundPlayDoubBuff := BitTst(@response,31 - gestaltSndPlayDoubleBuffer)
  206.     else
  207.         gHasSoundPlayDoubBuff := false;
  208.  
  209.     if (theErr = noErr) then
  210.         gHasSoundInputDevice := BitTst(@response,31 - gestaltHasSoundInputDevice)
  211.     else
  212.         gHasSoundInputDevice := false;
  213.  
  214.     if (theErr = noErr) then
  215.         gHasSpeechmanager := BitTst(@response,31 - gestaltSpeechMgrPresent)
  216.     else
  217.         gHasSpeechmanager := false;
  218.  
  219.     if (theErr = noErr) then
  220.         gHasMultiChannel := BitTst(@response,31 - gestaltMultiChannels)        
  221.     else
  222.         gHasMultiChannel := false;
  223.     end;
  224.         {of procedure DoCheckSoundEnv}
  225.  
  226. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoInitialiseASL }
  227.  
  228. procedure DoInitialiseASL;
  229.  
  230.     begin
  231.     if (ASLinitialise(gCallASLcloseChannel, kMaxChannels) <> noErr) then
  232.         begin
  233.         DoErrorAlert(eCannotInitialise);
  234.         ExitToShell;
  235.         end;
  236.     end;
  237.         {of procedure DoInitialiseASL}
  238.         
  239. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoLoopedSoundSetUp }
  240.  
  241. function DoLoopedSoundSetUp : boolean;
  242.  
  243.     var
  244.     error : integer;
  245.     theErr : OSErr;
  246.     soundHdl : Handle;
  247.  
  248.     begin
  249.     error := ASLplayHandle(nil, @gLoopedSoundRefNum);
  250.     if (error <> 0) then
  251.         begin
  252.         DoLoopedSoundSetUp := false;
  253.         Exit(DoLoopedSoundSetUp);
  254.         end
  255.     else begin
  256.         error := ASLgetChannel(gLoopedSoundRefNum, gLoopedSoundChannel);
  257.         if (error <> 0) then
  258.             begin
  259.             DoLoopedSoundSetUp := false;
  260.             Exit(DoLoopedSoundSetUp);
  261.             end;
  262.         
  263.         soundHdl := GetResource('snd ', rLoopedSound);
  264.         if (soundHdl <> nil)  then
  265.             begin
  266.             HLockHi(soundHdl);
  267.             theErr := SndPlay(gLoopedSoundChannel, SndListHandle(soundHdl), true);
  268.             if (theErr <> noErr) then
  269.                 begin
  270.                 DoLoopedSoundSetUp := false;
  271.                 Exit(DoLoopedSoundSetUp);
  272.                 end;
  273.             end
  274.         else begin
  275.             DoLoopedSoundSetUp := false;
  276.             Exit(DoLoopedSoundSetUp);
  277.             end;
  278.         end;
  279.     
  280.     DoLoopedSoundSetUp := true;
  281.     end;
  282.         {of procedure DoLoopedSoundSetUp}
  283.         
  284. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ EventLoop }
  285.  
  286. procedure EventLoop;
  287.  
  288.     var
  289.     theRect, eraseRect : Rect;
  290.     gotEvent : boolean;
  291.     eventRec : EventRecord;
  292.     theDialogPtr : DialogPtr;
  293.     itemHit : integer;
  294.     finalTicks : longint;
  295.  
  296.     begin
  297.     gDone := false;
  298.  
  299.     SetRect(theRect, 10, 273, 35, 299);
  300.     SetRect(eraseRect, 45, 273, 125, 299);
  301.  
  302.     while not (gDone) do
  303.         begin        
  304.         if (gCallASLcloseChannel) then
  305.             begin
  306.             ASLcloseChannel;
  307.  
  308.             TextFont(geneva);
  309.             TextSize(9);
  310.             MoveTo(45, 285);
  311.             DrawString('ASLcloseChannel');
  312.             MoveTo(45, 295);
  313.             DrawString('called');
  314.             end;
  315.                 
  316.         gotEvent := WaitNextEvent(everyEvent, eventRec, 10, nil);
  317.  
  318.         if (gotEvent) then
  319.             begin
  320.             if (IsDialogEvent(eventRec)) then
  321.                 if (DialogSelect(eventRec, theDialogPtr, itemHit)) then
  322.                     DoDialogHit(itemHit);
  323.             end
  324.         else begin
  325.             if (gColorQuickDrawPresent) then
  326.                 begin
  327.                 PlotCIcon(theRect, gColourIconHdl1);
  328.                 Delay(15, finalTicks);
  329.                 PlotCIcon(theRect, gColourIconHdl2);
  330.                 Delay(15, finalTicks);
  331.                 EraseRect(eraseRect);
  332.                 end;
  333.             end;
  334.         end;
  335.     
  336.     DisposeDialog(gDialogPtr);
  337.     
  338.     ASLcloseDown;
  339.     end;
  340.         {of procedure EventLoop}
  341.  
  342. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoDialogHit }
  343.  
  344. procedure DoDialogHit(item : integer);
  345.  
  346.     begin
  347.     case (item) of
  348.  
  349.         iQuit: begin
  350.             gDone := true;
  351.             end;
  352.  
  353.         iPlayResource: begin
  354.             DoPlayResource;
  355.             end;
  356.  
  357.         iPlayFile: begin
  358.             DoPlayFile;
  359.             end;
  360.  
  361.         iRecordResource: begin
  362.             DoRecordResource;
  363.             end;
  364.  
  365.         iRecordFile: begin
  366.             DoRecordFile;
  367.             end;
  368.  
  369.         iSpeakTextSync: begin
  370.             DoSpeakStringSync;
  371.             end;
  372.  
  373.         iLoopedSound: begin
  374.             DoLoopedSoundAsync;
  375.             end;
  376.  
  377.         iUnloopedSound: begin
  378.             DoUnloopedSoundAsync;
  379.             end;
  380.             
  381.         iSpeakTextAsync: begin
  382.             DoSpeakStringAsync;
  383.             end;
  384.         end;
  385.             {of case statement}            
  386.     end;
  387.         {of procedure DoDialogHit}
  388.  
  389. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoPlayResource }
  390.  
  391. procedure DoPlayResource;
  392.  
  393.     var
  394.     sndListHdl : SndListHandle;
  395.     resErr : integer;
  396.     theErr : OSErr;
  397.  
  398.     begin
  399.     sndListHdl := SndListHandle(GetResource('snd ', rPlaySoundResource));
  400.     resErr := ResError;
  401.     if (resErr <> noErr) then
  402.         DoErrorAlert(eGetResource);        
  403.     
  404.     if (sndListHdl <> nil) then
  405.         begin
  406.         HLock(Handle(sndListHdl));
  407.         theErr := SndPlay(nil, sndListHdl, false);
  408.         if (theErr <> noErr) then
  409.             DoErrorAlertWithCode(eSndPlay, theErr);            
  410.         HUnlock(Handle(sndListHdl));
  411.         ReleaseResource(Handle(sndListHdl));
  412.         end;
  413.     end;
  414.         {of procedure DoPlayResource}
  415.  
  416. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoPlayFile } 
  417.  
  418. procedure DoPlayFile;
  419.  
  420.     var
  421.     theErr : OSErr;
  422.     fileSysSpec : FSSpec;
  423.     fileRefNum : integer;
  424.     ignoredErr : OSErr;
  425.     
  426.     begin        
  427.     theErr := FSMakeFSSpec(0, 0, ':soundfile.aiff', fileSysSpec);
  428.     
  429.     if (theErr = noErr) then
  430.         theErr := FSpOpenDF(fileSysSpec, fsRdPerm, fileRefNum);
  431.         
  432.     if (theErr = noErr) then
  433.         ignoredErr := SetFPos(fileRefNum, fsFromStart, 0);
  434.         
  435.     if (theErr = noErr) then
  436.         theErr := SndStartFilePlay(nil, fileRefNum, 0, 20480, nil, nil, nil, false);
  437.         
  438.     if (theErr <> noErr) then
  439.         DoErrorAlertWithCode(ePlayFile, theErr);            
  440.  
  441.     ignoredErr := FSClose(fileRefNum);
  442.     end;
  443.         {of procedure DoPlayFile}
  444.  
  445. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoRecordResource }
  446.  
  447. procedure DoRecordResource;
  448.  
  449.     var
  450.     oldResFileRefNum : integer;
  451.     topLeft : Point;
  452.     soundHdl : Handle;
  453.     theErr, memErr : OSErr;
  454.     theResourceID, resErr : integer;
  455.             
  456.     begin
  457.     oldResFileRefNum := CurResFile;
  458.     UseResFile(gAppResFileRefNum);
  459.  
  460.     topLeft.v := 40;
  461.     topLeft.h := 250;
  462.     
  463.     soundHdl := NewHandle(25000);
  464.     memErr := MemError;
  465.     if (memErr <> noErr) then
  466.         begin
  467.         DoErrorAlert(eMemory);
  468.         Exit(DoRecordResource);
  469.         end;
  470.         
  471.     theErr := SndRecord(nil, topLeft, siBetterQuality, SndListHandle(soundHdl));
  472.     if ((theErr <> noErr) and (theErr <> userCanceledErr)) then
  473.         DoErrorAlertWithCode(eSndRecord, theErr)
  474.     else begin
  475.         repeat
  476.         theResourceID := UniqueID('snd ');
  477.         until (theResourceID >= 8191);
  478.  
  479.         AddResource(Handle(soundHdl), 'snd ', theResourceID, 'Test');
  480.         resErr := ResError;
  481.         if (resErr = noErr) then
  482.             UpdateResFile(gAppResFileRefNum);
  483.             
  484.         resErr := ResError;
  485.         if (resErr <> noErr) then
  486.             DoErrorAlertWithCode(eWriteResource, resErr);
  487.         end;
  488.  
  489.     UseResFile(oldResFileRefNum);
  490.     end;
  491.         {of procedure DoRecordResource}
  492.  
  493. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoRecordFile }
  494.  
  495. procedure DoRecordFile;
  496.  
  497.     var
  498.     topLeft : Point;
  499.     theErr : OSErr;
  500.     fileSysSpec : FSSpec;
  501.     fileRefNum : integer;
  502.     ignoredErr : OSErr;
  503.         
  504.     begin    
  505.     topLeft.v := 40;
  506.     topLeft.h := 250;
  507.     
  508.     theErr := FSMakeFSSpec(0, 0, ':test.aiff', fileSysSpec);
  509.     if (theErr = fnfErr) then
  510.         theErr := FSpCreate(fileSysSpec, '????', 'AIFF', smSystemScript);
  511.         
  512.     if (theErr = noErr) then
  513.         theErr := FSpOpenDF(fileSysSpec, fsWrPerm, fileRefNum);
  514.         
  515.     if (theErr = noErr) then
  516.         ignoredErr := SetFPos(fileRefNum, fsFromStart, 0);
  517.         
  518.     if (theErr = noErr) then
  519.         theErr := SndRecordToFile(nil, topLeft, siBetterQuality, fileRefNum);
  520.         
  521.     if ((theErr <> noErr) and (theErr <> userCanceledErr)) then
  522.         DoErrorAlertWithCode(eRecordFile, theErr);            
  523.  
  524.     ignoredErr := FSClose(fileRefNum);
  525.     end;
  526.         {of procedure DoRecordFile}
  527.  
  528. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoSpeakStringSync }
  529.  
  530. procedure DoSpeakStringSync;
  531.  
  532.     var
  533.     activeChannels : integer;
  534.     theString : string;
  535.     resErr, theErr : OSErr;
  536.         
  537.     begin
  538.     activeChannels := SpeechBusy;
  539.  
  540.     GetIndString(theString, rSpeechStrings, 1);
  541.     resErr := ResError;
  542.     if (resErr <> noErr) then
  543.         begin
  544.         DoErrorAlert(eGetResource);
  545.         Exit(DoSpeakStringSync);
  546.         end;
  547.     
  548.     theErr := SpeakString(@theString);
  549.     if (theErr <> noErr) then
  550.         DoErrorAlertWithCode(eSpeakString, theErr);
  551.         
  552.     while (SpeechBusy <> activeChannels) do ;
  553.     end;
  554.         {of procedure DoSpeakStringSync}
  555.  
  556. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoLoopedSoundAsync }
  557.  
  558. procedure DoLoopedSoundAsync;
  559.  
  560.     var
  561.     soundCommand : SndCommand;
  562.     theErr : OSErr;
  563.             
  564.     begin
  565.     gLoopedSoundOn := not (gLoopedSoundOn);
  566.  
  567.     DoAdjustItems;
  568.  
  569.     soundCommand.param1 := 0;
  570.     
  571.     if (gLoopedSoundOn) then
  572.         begin
  573.         soundCommand.cmd := freqCmd;
  574.         soundCommand.param2 := $3C;
  575.         end 
  576.     else begin
  577.         soundCommand.cmd := quietCmd;
  578.         soundCommand.param2 := 0;
  579.         end;
  580.     
  581.     theErr := SndDoImmediate(gLoopedSoundChannel, soundCommand);
  582.     if (theErr <> noErr) then
  583.         DoErrorAlertWithCode(eSndDoImmediate, theErr);
  584.     end;
  585.         {of procedure DoLoopedSoundAsync}
  586.         
  587. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoUnloopedSoundAsync }
  588.  
  589. procedure DoUnloopedSoundAsync;
  590.  
  591.     var
  592.     error : integer;
  593.     
  594.     begin
  595.     error := ASLplayID(rUnloopedSound, nil);
  596.     if (error = kOutOfChannels) then
  597.         DoErrorAlert(eNoChannelsAvailable)
  598.     else if (error <> noErr) then
  599.         DoErrorAlert(ePlaySound);
  600.     end;
  601.         {of procedure DoUnloopedSoundAsync}
  602.  
  603. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoSpeakStringAsync }
  604.  
  605. procedure DoSpeakStringAsync;
  606.  
  607.     var
  608.     theString : string;
  609.     resErr, theErr : OSErr;
  610.  
  611.     begin
  612.     GetIndString(theString, rSpeechStrings, 2);
  613.     resErr := ResError;
  614.     if (resErr <> noErr) then
  615.         begin
  616.         DoErrorAlert(eGetResource);
  617.         Exit(DoSpeakStringAsync);
  618.         end;
  619.     
  620.     theErr := SpeakString(@theString);
  621.     if (theErr <> noErr) then
  622.         DoErrorAlertWithCode(eSpeakString, theErr);
  623.     end;
  624.         {of procedure DoSpeakStringAsync}
  625.  
  626. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoSetUpDialog }
  627.  
  628. procedure DoSetUpDialog;
  629.  
  630.     var
  631.     itemType : integer;
  632.     itemHdl : Handle;
  633.     itemRect : Rect;
  634.             
  635.     begin
  636.     GetDialogItem(gDialogPtr, iSynchSoundRect, itemType, itemHdl, itemRect);
  637.     SetDialogItem(gDialogPtr, iSynchSoundRect, itemType, 
  638.                 Handle(drawDialogRD), itemRect);                          { For PowerPC }
  639.  
  640.     if not (gHasSoundPlayDoubBuff) then
  641.         begin
  642.         GetDialogItem(gDialogPtr, iPlayFile, itemType, itemHdl, itemRect);
  643.         HiliteControl(ControlHandle(itemHdl), 255);
  644.         end;
  645.  
  646.     if not (gHasSoundInputDevice) then
  647.         begin
  648.         GetDialogItem(gDialogPtr, iRecordResource, itemType, itemHdl, itemRect);
  649.         HiliteControl(ControlHandle(itemHdl), 255);
  650.         GetDialogItem(gDialogPtr, iRecordFile, itemType, itemHdl, itemRect);
  651.         HiliteControl(ControlHandle(itemHdl), 255);
  652.         end;
  653.     
  654.     if not (gHasSpeechmanager) then
  655.         begin
  656.         GetDialogItem(gDialogPtr, iSpeakTextSync, itemType, itemHdl, itemRect);
  657.         HiliteControl(ControlHandle(itemHdl), 255);
  658.         GetDialogItem(gDialogPtr, iSpeakTextAsync, itemType, itemHdl, itemRect);
  659.         HiliteControl(ControlHandle(itemHdl), 255);
  660.         end;
  661.  
  662.     if not (gHasMultiChannel) then
  663.         begin
  664.         GetDialogItem(gDialogPtr, iLoopedSound, itemType, itemHdl, itemRect);
  665.         HiliteControl(ControlHandle(itemHdl), 255);
  666.         end;    
  667.     end;
  668.         {of procedure DoSetUpDialog}
  669.  
  670. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DrawDialog }
  671.  
  672. procedure DrawDialog(theDialogPtr : DialogPtr; theItem : integer);
  673.  
  674.     var
  675.     itemType : integer;
  676.     itemHdl : Handle;
  677.     itemRect : Rect;
  678.     buttonOval : integer;
  679.  
  680.     begin
  681.     GetDialogItem(theDialogPtr, iSynchSoundRect, itemType, itemHdl, itemRect);
  682.     FrameRect(itemRect);
  683.     GetDialogItem(theDialogPtr, iAsynchSoundRect, itemType, itemHdl, itemRect);
  684.     FrameRect(itemRect);
  685.     GetDialogItem(theDialogPtr, iQuit, itemType, itemHdl, itemRect);
  686.     InsetRect(itemRect, -4, -4);
  687.     PenSize(3, 3);
  688.     buttonOval := (itemRect.bottom - itemRect.top) div 2 + 2;
  689.     FrameRoundRect(itemRect, buttonOval, buttonOval);
  690.     end;
  691.         {of procedure DrawDialog}
  692.  
  693. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoAdjustItems }
  694.  
  695. procedure DoAdjustItems;
  696.  
  697.     var
  698.     itemType, a : integer;
  699.     itemHdl : Handle;
  700.     itemRect : Rect;
  701.  
  702.     begin
  703.     GetDialogItem(gDialogPtr, iLoopedSound, itemType, itemHdl, itemRect);
  704.     if (gLoopedSoundOn) then
  705.         SetControlTitle(ControlHandle(itemHdl), 'Switch Looped Sound Off')
  706.     else
  707.         SetControlTitle(ControlHandle(itemHdl), 'Switch Looped Sound On');
  708.  
  709.     for a := iRecordResource to iRecordFile do
  710.         begin
  711.         GetDialogItem(gDialogPtr, a, itemType, itemHdl, itemRect);
  712.         if (gLoopedSoundOn) then
  713.             HiliteControl(ControlHandle(itemHdl), 255)
  714.         else
  715.             HiliteControl(ControlHandle(itemHdl), 0);
  716.         end;        
  717.     end;
  718.         {of procedure DoAdjustItems}
  719. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoErrorAlert }
  720.  
  721. procedure DoErrorAlert(stringIndex : integer);
  722.  
  723.     var
  724.     errorString : string;
  725.     ignoredErr : OSErr;
  726.     
  727.     begin
  728.     GetIndString(errorString, rErrorStrings, stringIndex);
  729.     ParamText(errorString, '', '', '');
  730.     ignoredErr := StopAlert(rErrorAlert, nil);
  731.     end;
  732.         {of procedure DoErrorAlert}
  733.  
  734. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ DoErrorAlertWithCode }
  735.  
  736. procedure DoErrorAlertWithCode(stringIndex, resultCode : integer);
  737.  
  738.     var
  739.     errorString, resultCodeString : string;
  740.     ignoredErr : OSErr;
  741.     
  742.     begin
  743.     GetIndString(errorString, rErrorStringsWithCode, stringIndex);
  744.     NumToString(longint(resultCode), resultCodeString);
  745.  
  746.     ParamText(errorString, resultCodeString, '', '');
  747.     ignoredErr := StopAlert(rErrorAlertWithCode, nil);
  748.     end;
  749.         {of procedure DoErrorAlertWithCode}
  750.  
  751. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ start of main program }
  752.  
  753. begin
  754.  
  755.     gColorQuickDrawPresent := false;
  756.     gLoopedSoundOn := false;
  757.     gCallASLcloseChannel := false;
  758.     
  759.     { ……………………………………………………………………………………………………………………………………………………… check for Color QuickDraw }
  760.  
  761.     theErr := Gestalt(gestaltQuickdrawVersion, response);
  762.     if (response >= gestalt8BitQD) then
  763.         gColorQuickDrawPresent := true;
  764.  
  765.     { ……………………………………………………………………………………………………………………………………………………………………… initialise managers }
  766.  
  767.     DoInitManagers;
  768.  
  769.     { ……………………………………………………………………………………………………………………………………………………… create routine descriptor }
  770.  
  771.     drawDialogRD := NewUserItemProc(ProcPtr(@DrawDialog));                  { For PowerPC }
  772.     
  773.     { ……………………………………………………………………………… save reference number of application's resource file } 
  774.     
  775.     gAppResFileRefNum := CurResFile;
  776.  
  777.     { …………………………………………………………… check for sound recording equipment and speech capabilities }
  778.  
  779.     DoCheckSoundEnv;
  780.  
  781.     { ……………………………………………………………………………………………… open and set up modal dialog, get colour icons }
  782.  
  783.     gDialogPtr := GetNewDialog(rDialog, nil, WindowPtr(-1));
  784.     if (gDialogPtr = nil) then
  785.         begin
  786.         DoErrorAlert(eOpenDialogFail);
  787.         ExitToShell;
  788.         end;
  789.  
  790.     SetPort(gDialogPtr);
  791.  
  792.     DoSetUpDialog;
  793.  
  794.     if (gColorQuickDrawPresent) then
  795.         begin
  796.         gColourIconHdl1 := GetCIcon(rColourIcon1);
  797.         gColourIconHdl2 := GetCIcon(rColourIcon2);
  798.         end;
  799.     
  800.     { ………………………………………………………………………………………………………………………………………………………… initialize AsychSoundLib }
  801.  
  802.     DoInitialiseASL;
  803.  
  804.     { ……………………………………………………………………………………………………………………………………………………………………… set up looped sound }
  805.  
  806.     if (gHasMultiChannel) then
  807.         if not (DoLoopedSoundSetUp) then
  808.             begin
  809.             DoErrorAlert(eLoopedSoundSetUp);
  810.             ASLcloseDown;
  811.             ExitToShell;
  812.             end;
  813.  
  814.     { ……………………………………………………………………………………………………………………………………………………………………………… enter event loop }
  815.  
  816.     EventLoop;
  817.  
  818. end.
  819.     
  820. { ◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ }