ComponentDispatch.c

/*
    File:       ComponentDispatch.c
 
    Contains:   Common routines for dispatching for any sound component
 
    Written by: Mark Cookson    
 
    Copyright:  Copyright © 1996-1999 by Apple Computer, Inc., All Rights Reserved.
 
                You may incorporate this Apple sample source code into your program(s) without
                restriction. This Apple sample source code has been provided "AS IS" and the
                responsibility for its operation is yours. You are not permitted to redistribute
                this Apple sample source code as "Apple sample source code" after having made
                changes. If you're going to re-distribute the source, we require that you make
                it clear in the source that the code was descended from Apple sample source
                code, but that you've made changes.
 
    Change History (most recent first):
                8/20/1999   Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
                
 
*/
#include <Components.h>
#include <Sound.h>
#include "VU-Meter.h"
 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  Sound Component Function Prototypes
 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// component stuff
 
static pascal ComponentResult __SoundComponentOpen(void *unused1, ComponentInstance self);
static pascal ComponentResult __SoundComponentClose(SoundComponentGlobalsPtr globals, ComponentInstance self);
static pascal ComponentResult __SoundComponentRegister(SoundComponentGlobalsPtr globals);
static pascal ComponentResult __SoundComponentCanDo(void *unused1, short selector);
 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// basic stuff
 
static pascal ComponentResult __SoundComponentSetSource(SoundComponentGlobalsPtr globals, SoundSource sourceID, ComponentInstance source);
static pascal ComponentResult __SoundComponentGetSource(SoundComponentGlobalsPtr globals, SoundSource sourceID, ComponentInstance *source);
static pascal ComponentResult __SoundComponentGetSourceData(SoundComponentGlobalsPtr globals, SoundComponentDataPtr *sourceData);
static pascal ComponentResult __SoundComponentSetOutput(SoundComponentGlobalsPtr globals, SoundComponentDataPtr requested, SoundComponentDataPtr *actual);
 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// info methods
 
static pascal ComponentResult __SoundComponentGetInfo(SoundComponentGlobalsPtr globals, SoundSource sourceID, OSType selector, void *infoPtr);
 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// control methods
 
static pascal ComponentResult __SoundComponentStopSource(SoundComponentGlobalsPtr globals, short count, SoundSource *sources);
static pascal ComponentResult __SoundComponentPlaySourceBuffer(SoundComponentGlobalsPtr globals, SoundSource sourceID, SoundParamBlockPtr pb, long actions);
 
 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// types
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
#if GENERATINGCFM
 
// These structs are use in PowerMac builds to cast the
// ComponentParameters passed into our component's entry point.
 
enum {
    uppSoundComponentEntryPointProcInfo = kPascalStackBased
        | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
        | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(ComponentParameters *)))
        | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(void *)))
};
 
// These are used to create the routine descriptor to call each function.
 
enum {
        uppSoundComponentOpenProcInfo = kPascalStackBased
                | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
                | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(void *)))
                | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(ComponentInstance)))
};
 
enum {
        uppSoundComponentCloseProcInfo = kPascalStackBased
                | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
                | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(SoundComponentGlobalsPtr)))
                | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(ComponentInstance)))
};
 
enum {
        uppSoundComponentRegisterProcInfo = kPascalStackBased
                | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
                | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(SoundComponentGlobalsPtr)))
};
 
enum {
        uppSoundComponentSetSourceProcInfo = kPascalStackBased
                | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
                | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(SoundComponentGlobalsPtr)))
                | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(SoundSource)))
                | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(ComponentInstance)))
};
 
enum {
        uppSoundComponentGetSourceProcInfo = kPascalStackBased
                | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
                | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(SoundComponentGlobalsPtr)))
                | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(SoundSource)))
                | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(ComponentInstance*)))
};
 
enum {
        uppSoundComponentGetSourceDataProcInfo = kPascalStackBased
                | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
                | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(SoundComponentGlobalsPtr)))
                | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(SoundComponentDataPtr)))
};
 
enum {
        uppSoundComponentSetOutputProcInfo = kPascalStackBased
                | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
                | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(SoundComponentGlobalsPtr)))
                | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(SoundComponentDataPtr)))
                | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(SoundComponentDataPtr)))
};
 
enum {
        uppSoundComponentGetInfoProcInfo = kPascalStackBased
                | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
                | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(SoundComponentGlobalsPtr)))
                | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(SoundSource)))
                | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(OSType)))
                | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(void *)))
};
 
enum {
        uppSoundComponentStopSourceProcInfo = kPascalStackBased
                | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
                | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(SoundComponentGlobalsPtr)))
                | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(short)))
                | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(SoundSource)))
};
 
enum {
        uppSoundComponentPlaySourceBufferProcInfo = kPascalStackBased
                | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
                | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(SoundComponentGlobalsPtr)))
                | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(SoundSource)))
                | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(SoundParamBlockPtr)))
                | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(long)))
};
 
// this macro will create a global structure of type RoutineDescriptor
 
#define DeclareRoutineDescriptor(info, proc)                                    \
    RoutineDescriptor g##proc##RD = BUILD_ROUTINE_DESCRIPTOR(info, proc)
 
#define GetComponentFunction(proc)  (&g##proc##RD)
 
DeclareRoutineDescriptor(uppSoundComponentRegisterProcInfo, __SoundComponentRegister);
DeclareRoutineDescriptor(uppSoundComponentCloseProcInfo, __SoundComponentClose);
DeclareRoutineDescriptor(uppSoundComponentOpenProcInfo, __SoundComponentOpen);
DeclareRoutineDescriptor(uppSoundComponentSetSourceProcInfo, __SoundComponentSetSource);
DeclareRoutineDescriptor(uppSoundComponentGetSourceProcInfo, __SoundComponentGetSource);
DeclareRoutineDescriptor(uppSoundComponentGetSourceDataProcInfo, __SoundComponentGetSourceData);
DeclareRoutineDescriptor(uppSoundComponentSetOutputProcInfo, __SoundComponentSetOutput);
DeclareRoutineDescriptor(uppSoundComponentGetInfoProcInfo, __SoundComponentGetInfo);
DeclareRoutineDescriptor(uppSoundComponentStopSourceProcInfo, __SoundComponentStopSource);
DeclareRoutineDescriptor(uppSoundComponentPlaySourceBufferProcInfo, __SoundComponentPlaySourceBuffer);
 
 
#else //GENERATING68K
 
#define GetComponentFunction(proc)  (ComponentFunctionUPP)(proc)
 
#endif
 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  Sound Component Entry Point
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
// in 68k (non-CFM) the entry point is defined to be the SoundComponentEntryPoint
// in PowerPC the entry point is a Routine Descriptor pointing to SoundComponentEntryPoint
 
//pascal ComponentResult SoundComponentDispatcher(ComponentParameters *params, SoundComponentGlobalsPtr globals);
 
#if !GENERATINGCFM
#define SoundComponentDispatcher SoundComponentEntryPoint
#else
pascal ComponentResult SoundComponentDispatcher(ComponentParameters *params, SoundComponentGlobalsPtr globals);
RoutineDescriptor SoundComponentEntryPoint = BUILD_ROUTINE_DESCRIPTOR(uppSoundComponentEntryPointProcInfo, SoundComponentDispatcher);
#endif
 
pascal ComponentResult SoundComponentDispatcher(ComponentParameters *params, SoundComponentGlobalsPtr globals)
{
    ComponentResult             result;
    short                       selector = params->what;
 
    if (selector < 0)
        switch (selector - kComponentRegisterSelect)    // standard component selectors
        {
            case kComponentRegisterSelect - kComponentRegisterSelect:
                result = CallComponentFunctionWithStorage((Handle) globals, params, GetComponentFunction(__SoundComponentRegister));
                break;
 
            case kComponentVersionSelect - kComponentRegisterSelect:
                return (kSoundComponentVersion);
                break;
 
            case kComponentCanDoSelect - kComponentRegisterSelect:
                result = __SoundComponentCanDo(0, *((short *) &params->params[0]));
                break;
 
            case kComponentCloseSelect - kComponentRegisterSelect:
                result = CallComponentFunctionWithStorage((Handle) globals, params, GetComponentFunction(__SoundComponentClose));
                break;
 
            case kComponentOpenSelect - kComponentRegisterSelect:
                result = CallComponentFunctionWithStorage((Handle) globals, params, GetComponentFunction(__SoundComponentOpen));
                break;
 
            default:
                result = badComponentSelector;
                break;
        }
    else if (selector < kDelegatedSoundComponentSelectors)          // selectors that cannot be delegated
        switch (selector)
        {
            case kSoundComponentSetSourceSelect:
                result = CallComponentFunctionWithStorage((Handle) globals, params, GetComponentFunction(__SoundComponentSetSource));
                break;
 
            case kSoundComponentGetSourceSelect:
                result = CallComponentFunctionWithStorage((Handle) globals, params, GetComponentFunction(__SoundComponentGetSource));
                break;
 
            case kSoundComponentGetSourceDataSelect:
                result = CallComponentFunctionWithStorage((Handle) globals, params, GetComponentFunction(__SoundComponentGetSourceData));
                break;
 
            case kSoundComponentSetOutputSelect:
                result = CallComponentFunctionWithStorage((Handle) globals, params, GetComponentFunction(__SoundComponentSetOutput));
                break;
 
            default:
                result = badComponentSelector;
                break;
        }
    else                                                    // selectors that can be delegated
        switch (selector)
        {
            case kSoundComponentGetInfoSelect:
                result = CallComponentFunctionWithStorage((Handle) globals, params, GetComponentFunction(__SoundComponentGetInfo));
                break;
 
            case kSoundComponentStopSourceSelect:
                result = CallComponentFunctionWithStorage((Handle) globals, params, GetComponentFunction(__SoundComponentStopSource));
                break;
 
            case kSoundComponentPlaySourceBufferSelect:
                result = CallComponentFunctionWithStorage((Handle) globals, params, GetComponentFunction(__SoundComponentPlaySourceBuffer));
                break;
 
            default:
                result = DelegateComponentCall(params, globals->sourceComponent);
                break;
        }
 
    return (result);
}
 
 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
static pascal ComponentResult __SoundComponentCanDo(void *unused1, short selector)
{
#pragma unused (unused1)
 
    ComponentResult     result;
 
    switch (selector)
    {
        case kComponentRegisterSelect:
        case kComponentVersionSelect:
        case kComponentCanDoSelect:
        case kComponentCloseSelect:
        case kComponentOpenSelect:
        case kSoundComponentSetSourceSelect:
        case kSoundComponentGetSourceSelect:
        case kSoundComponentGetSourceDataSelect:
        case kSoundComponentSetOutputSelect:
        // selectors that can be delegated
        case kSoundComponentGetInfoSelect:
        case kSoundComponentStopSourceSelect:
        case kSoundComponentPlaySourceBufferSelect:
            result = true;
            break;
 
        default:
            result = false;
            break;
    }
 
    return (result);
}