home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK1.toast / Development Kits (Disc 1) / AppleScript / Development Tools / Sample Code / Scripting Additions / Play Sound / PlaySnd.c < prev    next >
Encoding:
Text File  |  1993-12-15  |  6.4 KB  |  218 lines  |  [TEXT/MPS ]

  1. ////////////////////////////////////////////////////////////////////    
  2. //
  3. //    PlaySnd.c - the Play Sound OSAX 
  4. //     
  5. //    Copyright ®1993 Apple Computer Inc.
  6. //    All rights reserved
  7. //    
  8. //     Written by: Donald Olson
  9. //
  10. ////////////////////////////////////////////////////////////////////
  11.  
  12. #include <Resources.h>
  13. #include <Sound.h>
  14. #include <AppleEvents.h> 
  15.  
  16.  
  17. #define kAsync             true        // asynchronous play
  18. #define kQuietNow         true        // quiet channel now
  19.  
  20. #define kSndType        'snd '        // resource type we're looking for
  21. #define typeIntlText    'itxt'        // defined in AERegistry.r
  22. #define typeStyledText    'STXT'        // defined in AERegistry.r
  23.  
  24. //////////////////////////////////////////////////////////////////// 
  25. //
  26. //     PlaySndEntry () 
  27. //
  28. //    The direct parameter is either a name or an id of the 'snd '
  29. //    resource to play. 
  30. //
  31. ////////////////////////////////////////////////////////////////////
  32.  
  33. pascal OSErr PlaySndEntry(    AppleEvent *theAEEvent, 
  34.                             AppleEvent *theReply, 
  35.                             long *theRefCon) 
  36.  
  37. {     
  38. #pragma unused(theReply, theRefCon)
  39.  
  40.     /* Function Prototypes */
  41.      OSErr PlaySound(Handle theSoundHdl);
  42.      
  43.     /* variables */
  44.     OSErr            theErr = noErr;     
  45.     DescType         typeCode;
  46.     Size             sizeOfParam,
  47.                     actualSize;
  48.     Handle             theSndHandle = nil;    // Just clear our sound handle
  49.     SndChannelPtr     theSndChan = NULL;    // NULL pointer to a sound channel
  50.     short            ourRezID = 0;
  51.     Str255            ourRezName;
  52.     FSSpec            ourSoundFile;
  53.     short            ourFileRef, curResFile;
  54.  
  55.     /* 
  56.         Get the data type from direct object by using AESizeOfParam.
  57.         We use this call instead of AEGetParamDesc or AEGetParamPtr
  58.         since we are looking for one of several types. This way we 
  59.         can determine the type and move its data directly into a variable 
  60.         instead of an AEDesc. Makes our life easier since we don't 
  61.         have to worry about disposing the AEDesc later.
  62.     */
  63.     
  64.     theErr = AESizeOfParam(    theAEEvent,
  65.                                keyDirectObject,
  66.                                &typeCode,
  67.                                &sizeOfParam);
  68.   
  69.     if(theErr != noErr){    
  70.         /*
  71.             If we fail here just return the error. We don't need to
  72.             do any clean up since we've allocated nothing on the heap
  73.             yet.  The Apple Event Manager automatically adds the error
  74.             number to the reply as keyErrorNumber for non zero handler
  75.             returns.
  76.         */
  77.         
  78.         return theErr;
  79.     }     
  80.     else{  
  81.         if((typeCode == typeChar) || (typeCode == typeStyledText) || 
  82.             (typeCode == typeIntlText)) {        
  83.             /*
  84.                 If one of these types match, we've been passed a name of
  85.                 a resource. Use AEGetParamPtr to move it into our string
  86.                 and transform it into a Pascal type string that we can 
  87.                 pass to GetNamedResource. If we get an error in AEGetParamPtr,
  88.                 Just let it fall through to the bottom of this handler.
  89.             */
  90.         
  91.              theErr = AEGetParamPtr(theAEEvent, keyDirectObject, typeChar, 
  92.                                      &typeCode, (Ptr)&ourRezName, 
  93.                                     sizeof(ourRezName), &actualSize);
  94.                                     
  95.             if(theErr == noErr) {
  96.                 /* 'C' string has a null as last char */
  97.                 ourRezName[actualSize] = '\0';    
  98.                 /* Convert to Pascal string */
  99.                 c2pstr((char*) ourRezName);    
  100.                 /* Now grab the 'snd ' resource by name*/
  101.                 theSndHandle = GetNamedResource(kSndType, 
  102.                                                 (ConstStr255Param)ourRezName);
  103.                 /* Check the error */
  104.                 theErr = ResError();
  105.                 if(theErr == noErr)
  106.                     theErr = PlaySound(theSndHandle); // Call our sound code
  107.             }
  108.         }
  109.         else { 
  110.             if(typeCode == typeLongInteger) {    
  111.             
  112.                 /*     If we get a typeLongInteger, the user wants us to play 
  113.                     a sound by its resource id.
  114.                     
  115.                     AppleScript will send us a long here and the Resource
  116.                     Manager wants us to pass in a short so let's have the
  117.                     Apple Event Manager coerce it to a short for us.
  118.                 */
  119.                 
  120.                 theErr = AEGetParamPtr(theAEEvent, keyDirectObject, 
  121.                                         typeShortInteger, &typeCode,
  122.                                          (Ptr)&ourRezID, sizeof(ourRezID), 
  123.                                         &actualSize);
  124.                 
  125.                 if(theErr == noErr) {
  126.                     /* Now grab the 'snd ' resource by id */
  127.                     theSndHandle = GetResource (kSndType, ourRezID);
  128.                     /* Check the error */
  129.                     theErr = ResError();
  130.                     if(theErr == noErr)
  131.                         theErr = PlaySound(theSndHandle); // Call our sound code
  132.                 }
  133.             }
  134.             else  {
  135.                 if(typeCode == typeAlias) {    
  136.                     
  137.                     /*     It we receive a typeAlias, the user is asking us
  138.                         to play a sound file. We want to use a FSSpec to 
  139.                         open the Resource File so once again we ask the
  140.                         Apple Event Manager to coerce data to the type we
  141.                         need.
  142.                     */
  143.                     
  144.                     theErr = AEGetParamPtr(theAEEvent, keyDirectObject, 
  145.                                         typeFSS, &typeCode,
  146.                                          (Ptr)&ourSoundFile, sizeof(ourSoundFile), 
  147.                                         &actualSize);
  148.                     if(theErr != noErr)
  149.                         return theErr;
  150.                         /* Save off our current resource file */
  151.                     curResFile = CurResFile();
  152.                     
  153.                     /* Open our resource file  for reading */
  154.                     ourFileRef = FSpOpenResFile(&ourSoundFile, fsRdPerm);
  155.                     
  156.                     /* Check the error */
  157.                     theErr = ResError();
  158.                     if(theErr != noErr)
  159.                         return theErr;
  160.                         
  161.                     /* Make our files resource fork top in the chain */
  162.                     UseResFile(ourFileRef);
  163.                     
  164.                     /*    
  165.                         Since we don't know for sure the resource id of the
  166.                         targeted files 'snd ' resource, let's just get the first
  167.                         (and supposedly only) one.
  168.                     */
  169.                     
  170.                     theSndHandle = Get1IndResource(kSndType, 1); 
  171.                     
  172.                     /* Check the error */
  173.                     theErr = ResError();
  174.                     if(theErr == noErr) 
  175.                         theErr = PlaySound(theSndHandle);
  176.                     
  177.                     // Restore resource chain and close our file
  178.                     UseResFile(curResFile);
  179.                     CloseResFile(ourFileRef);
  180.                 }
  181.                 else // Wasn't a string, alias or number so bail
  182.                     return errAEEventNotHandled;
  183.             }
  184.         }
  185.     } 
  186.     
  187.     // Dispose 'snd ' handle if necessary
  188.     if(theSndHandle != nil) ReleaseResource(theSndHandle);
  189.     
  190.     return theErr;
  191.  }
  192.  
  193. //////////////////////////////////////////////////////////////////// 
  194. //
  195. //     PlaySound(Handle theSoundHdl) 
  196. //
  197. //    This is the code to play a 'snd '. 
  198. //
  199. ////////////////////////////////////////////////////////////////////
  200.  
  201.  OSErr PlaySound(Handle theSoundHdl) 
  202.  {
  203.      /* Our variables */
  204.     OSErr            theErr = noErr;
  205.     SndChannelPtr     theSndChan = NULL;    // NULL pointer to a sound channel
  206.     
  207.     /* Open a channel so we can do synchronous play. */
  208.     theErr = SndNewChannel (&theSndChan, sampledSynth, initMono, NULL);
  209.     
  210.     if (theErr == noErr) /* Play that sound */
  211.         theErr = SndPlay (theSndChan, theSoundHdl, !kAsync);
  212.  
  213.     /* dispose of the channel, if soundchannel was allocated */
  214.     if (theSndChan != NULL)
  215.         SndDisposeChannel(theSndChan, !kQuietNow);
  216.     
  217.     return theErr;
  218.  }