home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 3 / Info_Mac_1994-01.iso / Development / Source / RandomSound Source / RandomSound.cc next >
Encoding:
C/C++ Source or Header  |  1993-08-12  |  7.5 KB  |  240 lines  |  [TEXT/KAHL]

  1. /*
  2.  ***********************************************************************
  3.  *
  4.  * This is a whimsy set of functions that lets one play the sound
  5.  * picked at random from the sound folder.
  6.  * The sound folder name is supposed to be specified as a "Sound Folder"
  7.  * STR resource. Even if you bastard forgot to set this resource,
  8.  * the folder "Sounds" in the system folder would be assumed.
  9.  *
  10.  ***********************************************************************
  11.  */
  12.  
  13. /* MacHeaders Included */
  14.  
  15. #include <Folders.h>
  16. #include <Sound.h>
  17.  
  18. /*
  19.  *-----------------------------------------------------------------------------------
  20.  *                                 Some standard I/O classes
  21.  */
  22. class ParamBlockHdr
  23. {
  24.     char internal[12];                    // Managed by the File/Queue Managers exclusively
  25.     int (*completion_routine)(void * param_block);    // Completion routine
  26.     OSErr result;                        // Result code, =0 means OK, <0 means error
  27. public:
  28.     StringPtr name;                        // Pointer to some name
  29.     short VRefNum;                        // Vol ref number (if <0), drive ref number (if >0)
  30.                                         // or working dir reference number
  31.                                         
  32.     ParamBlockHdr(void);
  33.     ~ParamBlockHdr(void) {}
  34.     OSErr io_error(void) const        { return result; }
  35. };
  36.  
  37. ParamBlockHdr::ParamBlockHdr(void)
  38. {
  39.     completion_routine = nil;
  40.     result = 1;                            // Work is in progress
  41. }
  42.  
  43. class DIRInfo: public ParamBlockHdr
  44. {
  45. public:
  46.     short ioFRefNum;                    // File ref number
  47.     signed char ioFVersNum;                // Version number
  48.     signed char    filler1;                // Not used
  49.     short ioFDirIndex;                    // Index for the directory
  50.     signed char ioFlAttrib;                // File Attribute
  51.     signed char    filler2;                // Not used
  52.     DInfo ioDrUsrWds;                    // Finder Info
  53.     long ioDrDirId;                        // Directory ID
  54.     short ioDrNmFls;                    // No. files and directories inside this dir
  55.     short filler3[9];                    // Not used
  56.     long ioDrCrDat;                        // Creation date
  57.     long ioDrMdDat;                        // Modification date
  58.     long ioDrBkDat;                        // Backup date
  59.     DXInfo ioDrFndrInfo;                // Additional info for the finder
  60.     long ioDRParID;                        // Dir ID of the parent dir
  61.     
  62.     DIRInfo(const short vol_refno, const long parent_dirid, StringPtr dir_name);
  63.     ~DIRInfo(void) {}
  64.     
  65. };
  66.  
  67.                                     // Getting a directory info
  68.                                     // Dir is specified by the volume refno, 
  69.                                     // parent ID and its name
  70. DIRInfo::DIRInfo(const short vol_refno, const long parent_dirid, StringPtr dir_name)
  71. {
  72.     VRefNum = vol_refno;
  73.     name = dir_name;
  74.     ioFDirIndex = 0;                // not used here
  75.     ioDrDirId = parent_dirid;
  76.     do_well( PBGetCatInfo((CInfoPBRec *)this,FALSE) );
  77.     assert( io_error() == noErr );
  78. }
  79.  
  80. class FLInfo: public ParamBlockHdr
  81. {
  82. public:
  83.     short ioFRefNum;                    // File ref number
  84.     signed char ioFVersNum;                // Version number
  85.     signed char    filler1;                // Not used
  86.     short ioFDirIndex;                    // Index for the directory
  87.     signed char ioFlAttrib;                // File Attribute
  88.     signed char    ioFlVersNum;            // Version number
  89.     FInfo ioFlFndrInfo;                    // Finder Info
  90.     long ioDirId;                        // Directory ID
  91.     short ioFlStBlk;                    // First alloc block of data fork
  92.     long ioFlLgLen;                        // Logical end-of-file of data fork
  93.     long ioFlPyLen;                        // Physical end-of-file of data fork
  94.     short ioFlRStBlk;                    // First alloc block of resource fork
  95.     long ioFlRLgLen;                    // Logical end-of-file of resource fork
  96.     long ioFlRPyLen;                    // Physical end-of-file of resource fork
  97.     long ioFlCrDat;                        // Creation date
  98.     long ioFlMdDat;                        // Modification date
  99.     
  100.     Str63 file_name;
  101.     FLInfo(const short vol_refno, const long parent_dirid, const int index);
  102.     ~FLInfo(void) {}
  103.     
  104. };
  105.  
  106.                                     // Getting a file info 
  107.                                     // File is specified by the volume refno, 
  108.                                     // dir ID and the index
  109.                                     // Check io_error() for possible fnfErr
  110. FLInfo::FLInfo(const short vol_refno, const long parent_dirid, const int index)
  111. {
  112.     
  113.     VRefNum = vol_refno;
  114.     name = file_name;
  115.     ioFDirIndex = index;                // not used here
  116.     ioDirId = parent_dirid;
  117.     OSErr err = PBHGetFInfo((HParamBlockRec *)this,FALSE);
  118.     if( err != noErr && err != fnfErr )
  119.       _error("Failed to get a file info for a file indexed %d; error code %d",index,
  120.                err);
  121. }
  122.  
  123. /*
  124.  *-----------------------------------------------------------------------------------
  125.  *                 Sound Directory class that contains all the info about
  126.  *                        the directory with sound files
  127.  */
  128.  
  129. class SoundDirectory
  130. {
  131.     short volume_refno;
  132.     long  dir_id;                // Directory ID of the Sound directory
  133.     long  no_files;                // No. of files and folders in the directory
  134.     void locate_sound_directory(void);
  135.                                 // Locate the file with given index and tries
  136.                                 // to open it as a resource. Returns the resource
  137.                                 // refnumber if succeeded, or -1
  138.     short locate_file_open_resource(const int file_no);
  139.     
  140. public:
  141.     SoundDirectory(void)    { volume_refno = 0; dir_id = -1; }
  142.     ~SoundDirectory(void) {}
  143.     void play_at_random(void);
  144. };
  145.  
  146. /*
  147.  *-----------------------------------------------------------------------------------
  148.  *                 Selecting a folder that contains sound files
  149.  */
  150.  
  151.  
  152.                                         // The present version locates the
  153.                                         // directory named Sound inside the
  154.                                         // system folder
  155. void SoundDirectory::locate_sound_directory(void)
  156. {
  157.                                     // First locate the system directory
  158.     long system_dir_id;
  159.     do_well( ::FindFolder(kOnSystemDisk,kSystemFolderType,kDontCreateFolder,
  160.                          &volume_refno,&system_dir_id) );
  161.     
  162.                                     // Then get the directory ID of the "Sound"
  163.                                     // folder within it
  164.     DIRInfo sound_dir(volume_refno, system_dir_id, "\pSounds");
  165.     assure( sound_dir.ioFlAttrib & 0x10, "The named thing is not a directory!");
  166.     dir_id = sound_dir.ioDrDirId;
  167.     no_files = sound_dir.ioDrNmFls;
  168. //    message("Dir Id of the sound dir is %d, no. files %d",dir_id,no_files);
  169. }
  170.  
  171.  
  172. /*
  173.  *-----------------------------------------------------------------------------------
  174.  *                     Picking a file at random and playing it
  175.  */
  176.  
  177.                                     // Locating a file in the sound dir with a
  178.                                     // specified index. The program then tries
  179.                                     // to open it as a resource. Returns the resource
  180.                                     // refnumber if succeeded, or -1
  181. short SoundDirectory::locate_file_open_resource(const int file_index)
  182. {
  183.     assert( file_index > 0 && file_index <= no_files );
  184.     FLInfo file_info(volume_refno,dir_id,file_index);
  185.     if( file_info.io_error() != noErr )
  186.       return -1;
  187. //    message("File name is %#s",file_info.file_name);
  188.     short res_refno = HOpenResFile(volume_refno,dir_id,file_info.file_name,fsRdPerm);
  189.     if( res_refno == -1 )
  190.       message("Failed to open the resource fork because of error %d",ResError());
  191.     return res_refno;
  192. }
  193.  
  194.  
  195.                                             // Plays and closes the resource file
  196. void SoundDirectory::play_at_random(void)
  197. {
  198.     if( dir_id < 0 )
  199.       locate_sound_directory();
  200.     GetDateTime((unsigned long *)&randSeed);
  201.     const int max_no_tries = 5;
  202.     register int try;
  203.     for(try=1; try <= max_no_tries; try++)
  204.     {
  205.       int file_index = Random() % no_files;
  206.       file_index = (file_index < 0 ? file_index + no_files : file_index ) + 1;
  207.       short res_refno = locate_file_open_resource(file_index);
  208.       if( res_refno == -1 )
  209.         continue;
  210.         
  211.       Handle sound_handle = Get1IndResource('snd ',1);    // Get the first sound found
  212.       if( ResError() != noErr )
  213.       {
  214.         message("Failed to load a sound resource because of error %d",ResError());
  215.         CloseResFile(res_refno);
  216.         continue;
  217.       }
  218.       if( sound_handle != nil )
  219.         {
  220.           LoadResource(sound_handle);      
  221.         do_well( SndPlay(nil,sound_handle,FALSE) );        // Play sound in sync mode
  222.         DisposeHandle(sound_handle);
  223.         CloseResFile(res_refno);
  224.         break;
  225.       }
  226.      }
  227. }
  228.  
  229. /*
  230.  *-----------------------------------------------------------------------------------
  231.  *                                 Routing module
  232.  */
  233.  
  234. static SoundDirectory sound_bundle;
  235.  
  236. void play_random_sound(void)
  237. {
  238.     sound_bundle.play_at_random();
  239. }
  240.