Previous Book Contents Book Index Next

Inside Macintosh: Sound /
Chapter 5 - Sound Components / Writing a Sound Component


Legacy Documentclose button

Important: Inside Macintosh: Sound is deprecated as of Mac OS X v10.5. For new audio development in Mac OS X, use Core Audio. See the Audio page in the ADC Reference Library.

Finding and Changing Component Capabilities

All sound components take a stream of input data and produce a (usually different) stream of output data. The Sound Manager needs to know what operations your component can perform, so that it knows what other sound components might need to be linked together to play a particular sound on the available sound output device. It calls your component's SoundComponentGetInfo and SoundComponentSetInfo functions to get and set information about the capabilities and current settings of your sound component.

To specify the kind of information it wants to get or set, the Sound Manager passes your component a sound component information selector. If your component does not support a particular selector, if should pass the selector to the specified sound source. If your component does support the selector, it should either return the desired information directly or alter its settings as requested.

The sound component information selectors can specify any of a large number of audio capabilities or component settings. For example, the selector siRateMultiplier is passed to get or set the current output sample rate multiplier value.

Note
The Sound Manager uses many of the sound input device information selectors defined by the Sound Input Manager for communicating with sound input devices. See "Sound Input Manager" in this book for a description of the sound input device information selectors. A complete list of all sound component information selectors is provided in "Sound Component Information Selectors" beginning on page 5-22.
Your component's SoundComponentGetInfo function has the following declaration:

pascal ComponentResult SoundComponentGetInfo (ComponentInstance ti, 
                                       SoundSource sourceID, OSType selector, 
                                       void *infoPtr);
The sound component information selector is passed in the selector parameter. The sound source is identified by the source ID passed in the sourceID parameter. The infoPtr parameter specifies the location in memory of the information returned by SoundComponentGetInfo. If the information to be returned occupies four bytes or fewer, you can simply return the information in the location pointed to by that parameter. Otherwise, you should pass back in the infoPtr parameter a pointer to a record of type SoundInfoList, which contains an integer and a handle to an array of data items. In the second case, you'll need to allocate memory to hold the information you need to pass back. Listing 5-5 defines a component's SoundComponentGetInfo routine. It returns information to the Sound Manager about its capabilities and current settings.

Listing 5-5 Getting sound component information

static pascal ComponentResult MySoundComponentGetInfo 
                     (SoundComponentGlobalsPtr globals, SoundSource sourceID, 
                        OSType selector, void *infoPtr)
{
   HandleListPtr        listPtr;
   short                *sp, i;
   UnsignedFixed        *lp;
   Handle               h;
   HardwareGlobalsPtr   hwGlobals = globals->hwGlobals;
   ComponentResult      result = noErr;

   /*Make sure we got our global variables.*/
   if (hwGlobals == nil)
      return (notEnoughHardwareErr);

   switch (selector)
   {
      case siSampleSize:                  /*return current sample size*/
         *((short *) infoPtr) = hwGlobals->sampleSize;
         break;

      case siSampleSizeAvailable:         /*return sample sizes available*/
         h = NewHandle(sizeof(short) * kSampleSizesCount);
         if (h == nil)
            return (MemError());

         listPtr = (HandleListPtr) infoPtr;
         listPtr->count = 0;              /*num. sample sizes in handle*/
         listPtr->handle = h;             /*handle to be returned*/

         sp = (short *) *h;               /*store sample sizes in handle*/

         for (i = 0; i < kSampleSizesCount; ++i)
            if (hwGlobals->sampleSizesActive[i])
            {
               listPtr->count++;
               *sp++ = hwGlobals->sampleSizes[i];
            }
         break;

      case siSampleRate:                  /*return current sample rate*/
         *((Fixed *) infoPtr) = hwGlobals->sampleRate;
         break;

      case siSampleRateAvailable:         /*return sample rates available*/
         h = NewHandle(sizeof(UnsignedFixed) * kSampleRatesCount);
         if (h == nil)
            return (MemError());

         listPtr = (HandleListPtr) infoPtr;
         listPtr->count = 0;              /*num. sample rates in handle*/
         listPtr->handle = h;             /*handle to be returned*/

         lp = (UnsignedFixed *) *h;

         /*If the hardware can support a range of sample rate values,
           the list count should be set to 0 and the minimum and maximum
           sample rate values should be stored in the handle.*/
         if (hwGlobals->supportsRateRange)
         {
            *lp++ = hwGlobals->sampleRateMin;
            *lp++ = hwGlobals->sampleRateMax;
         }
         
         /*If the hardware supports a limited set of sample rates, 
           the list count should be set to the number of sample rates 
           and this list of rates should be stored in the handle.*/
         else
         {
            for (i = 0; i < kSampleRatesCount; ++i)
               if (hwGlobals->sampleRatesActive[i])
               {
                  listPtr->count++;
                  *lp++ = hwGlobals->sampleRates[i];
               }
         }
         break;

      case siNumberChannels:              /*return current num. channels*/
         *((short *) infoPtr) = hwGlobals->numChannels;
         break;

      case siChannelAvailable:            /*return channels available*/
         h = NewHandle(sizeof(short) * kChannelsCount);
         if (h == nil)
            return (MemError());

         listPtr = (HandleListPtr) infoPtr;
         listPtr->count = 0;              /*num. channels in handle*/
         listPtr->handle = h;             /*handle to be returned*/

         sp = (short *) *h;               /*store channels in handle*/

         for (i = 0; i < kChannelsCount; ++i)
            if (hwGlobals->channelsActive[i])
            {
               listPtr->count++;
               *sp++ = hwGlobals->channels[i];
            }
         break;

      case siHardwareVolume:
         *((long *)infoPtr) = hwGlobals->volume;
         break;

      /*If you do not handle a selector, delegate it up the chain.*/
      default:
         result = SoundComponentGetInfo(globals->sourceComponent, sourceID, 
                                    selector, infoPtr);
         break;
   }
   return (result);
}
You can define your MySoundComponentSetInfo routine in an exactly similar fashion.


Previous Book Contents Book Index Next

© Apple Computer, Inc.
2 JUL 1996