CSoundboardApp.cp

// ===========================================================================
//  CSoundboardApp.cp               ©1994 Metrowerks Inc. All rights reserved.
// ===========================================================================
//
//  A "do nothing" Soundboard program that you can use as a starter for
//  you own programs.
 
#include "CSoundboardApp.h"
#include "CFilterControl.h"
#include "CQuickTimeWindow.h"
#include "CGrayBox.h"
#include "CAttachment.h"
 
#include "FilterComponent.h"
#include "FilterComponentPrivate.h"
 
#include <LApplication.h>
#include <LGrowZone.h>
#include <LWindow.h>
#include <UMemoryMgr.h>
#include <UDrawingState.h>
#include <URegistrar.h>
#include <UQuickTime.h>
 
#include <LEditField.h>
#include <LTabGroup.h>
#include <LCaption.h>
#include <LStdControl.h>
#include <LDialogBox.h>
#include <UModalDialogs.h>
#include <LModelObject.h>
#include <math.h>
 
 
const ResIDT    WIND_Soundboard     = 200;
const ResIDT    WIND_QuickTimeMovie = 1300;
const PaneIDT   FirstSliderID       = 2002;
const PaneIDT   LastSliderID        = 2011;
const PaneIDT   LabelIDOffset       = 1000;
const PaneIDT   StatusID            = 'Stat';
 
 
// Menu commands
const CommandT  cmd_EnableFilter    = 13100;
const CommandT  cmd_UseExtGains     = 13103;
const CommandT  cmd_srsFilter       = 13104;
const CommandT  cmd_srsGain         = 13105;
const CommandT  cmd_3DAudio         = 13106;
const CommandT  cmd_XTalk5b         = 13107;
const CommandT  cmd_XTalkJG         = 13110;
const CommandT  cmd_XTalkJGtest     = 13112;
const CommandT  cmd_3DAudioJG       = 13111;
const CommandT  cmd_3DAudio5b       = 13108;
const CommandT  cmd_3DAudioOnly     = 13109;
const CommandT  cmd_SoundBoardW     = 13200;
 
const short     kUninited           = 0;
 
// Declare static data members of CSoundboardApp so others can use them
ComponentInstance   CSoundboardApp::mFilterInstance = 0;
short               CSoundboardApp::mGainValue[kMaxSliders];
 
#ifdef powerc
//  #define PROFILE_604         /* Only works on 604 */
#endif
 
#ifdef PROFILE_604
    void    startData(void);
    void    stopData(void);
#endif
 
// ===========================================================================
//      ¥ Main Program
// ===========================================================================
 
 
void main(void)
{
                                    // Set Debugging options
    SetDebugThrow_(debugAction_Alert);
    SetDebugSignal_(debugAction_Alert);
 
    InitializeHeap(3);              // Initialize Memory Manager
                                    // Parameter is number of Master Pointer
                                    //   blocks to allocate
    
                                    // Initialize standard Toolbox managers
    UQDGlobals::InitializeToolbox(&qd);
    
    new LGrowZone(20000);           // Install a GrowZone function to catch
                                    //    low memory situations.
                                    //    Parameter is size of reserve memory
                                    //    block to allocated. The first time
                                    //    the GrowZone function is called,
                                    //    there will be at least this much
                                    //    memory left (so you'll have enough
                                    //    memory to alert the user or finish
                                    //    what you are doing).
    
    CSoundboardApp  soundApp;       // Create instance of your Application
    soundApp.Run();                 //   class and run it
}
 
 
// ===========================================================================
//      ¥ CSoundboardApp Class
// ===========================================================================
 
// ---------------------------------------------------------------------------
//      ¥ CSoundboardApp
// ---------------------------------------------------------------------------
//  Constructor
 
CSoundboardApp::CSoundboardApp()
{
    LPane       *statusBdrPane;
    int         i;
    ComponentDescription    filterDesc;
    
        // Register classes for objects created from 'PPob' resources
        
    URegistrar::RegisterClass(LEditField::class_ID, (ClassCreatorFunc)LEditField::CreateEditFieldStream);
//  URegistrar::RegisterClass(LTabGroup::class_ID, (ClassCreatorFunc)LTabGroup::CreateTabGroupStream);
    URegistrar::RegisterClass(LCaption::class_ID, (ClassCreatorFunc)LCaption::CreateCaptionStream);
//  URegistrar::RegisterClass(LStdButton::class_ID, (ClassCreatorFunc)LStdButton::CreateStdButtonStream);
//  URegistrar::RegisterClass(LStdCheckBox::class_ID, (ClassCreatorFunc)LStdCheckBox::CreateStdCheckBoxStream);
//  URegistrar::RegisterClass(LDialogBox::class_ID, (ClassCreatorFunc)LDialogBox::CreateDialogBoxStream);
    URegistrar::RegisterClass(LView::class_ID, (ClassCreatorFunc)LWindow::CreateViewStream);
 
    URegistrar::RegisterClass(LWindow::class_ID, (ClassCreatorFunc)LWindow::CreateWindowStream);
    URegistrar::RegisterClass(CQuickTimeWindow::class_ID, (ClassCreatorFunc)CQuickTimeWindow::CreateQuickTimeWindowStream);
    URegistrar::RegisterClass(CSoundboardWindow::class_ID, (ClassCreatorFunc)CSoundboardWindow::CreateSoundboardWindowStream);
    URegistrar::RegisterClass(CGrayBox::class_ID, (ClassCreatorFunc)CGrayBox::CreateGrayBoxStream);
    URegistrar::RegisterClass(CFilterControl::class_ID, (ClassCreatorFunc)CFilterControl::CreateFilterControlStream);
    
    CFilterControl::SetSliderJmpAddress();
    UQuickTime::Initialize();
    
        // A Soundboard program has a single main Window that is
        // displayed on start up. The "Visible on Creation" option
        // for the Window (in its PPob resource) should be OFF,
        // so that you can adjust the Window's contents before
        // displaying it.
        
    mStatusWindow = CSoundboardWindow::CreateSoundboardWindow(WIND_Soundboard, this);
    
        // +++ Add code here to configure Panes inside the Window
    statusBdrPane = mStatusWindow->FindPaneByID('Chsl');
    if (statusBdrPane)
        statusBdrPane->AddAttachment(new C3DBorderAttachment);
 
    for (i=FirstSliderID; i<=LastSliderID; ++i) {
        CFilterControl *filterControlPane = (CFilterControl *)mStatusWindow->FindPaneByID(i);
        if (filterControlPane) {
            filterControlPane->SetSuperModel(mStatusWindow);
            filterControlPane->SetMaxValue(kMaxGain);
            filterControlPane->mLabel = (LCaption *)mStatusWindow->FindPaneByID(i+LabelIDOffset);
        }
    }
 
    SetDefaultSubModel(mStatusWindow); /* Crashes PPC for some reason?! */
 
    // Get initial status string
    SetStatusText(str_IdleStr);
    
    // Init instance stuff
    mFilterComponentID = 0L;
    mFilterInstance = 0L;
        
    // Register (or find) our components
    filterDesc.componentType = filterComponentType;
    filterDesc.componentSubType = 'tim ';
    filterDesc.componentManufacturer = 'tim ';
    filterDesc.componentFlags = 0L;
    filterDesc.componentFlagsMask = 0L;
    
    // Are we debugging?
    #ifdef DEBUG_IT
    
        mFilterNameHdl = NewHandle (sizeof (Str255));
        BlockMove ((Ptr)"\pFilter_Component", (Ptr)(*mFilterNameHdl), sizeof (Str255));
 
        mInfoHdl = NewHandle (sizeof (Str255));
        BlockMove ((Ptr)"\pThis component provides simple filter services.", (Ptr)(*mInfoHdl), sizeof (Str255));
        
        // Register the Filter component
        mFilterComponentID = RegisterComponent (&filterDesc,
            NewComponentRoutineProc(FilterDispatcher), kRegisterGlobally,
            mFilterNameHdl, mInfoHdl, nil);
 
    #else   // We're running as standalone components   
    
        // Find the filter component - You should note that it is perfectly
        // acceptable to do a RegisterComponent call followed by a FindNextComponent
        // call - if you use the same component description, and the
        // RegisterComponent call was successful, then you'll get back the same
        // component ID from FindNextComponent that you got from RegisterComponent. 
        mFilterComponentID = FindNextComponent (nil, &filterDesc);
        
    #endif /*DEBUG_IT   */
    
    OpenFilterComponent();
    UpdateFilterCntls();
    
    mStatusWindow->Show();
    SetSleepTime(0);
    StartIdling();
}
 
 
// ---------------------------------------------------------------------------
//      ¥ ~CSoundboardApp
// ---------------------------------------------------------------------------
//  Destructor
 
CSoundboardApp::~CSoundboardApp()
{
        // +++ Add code here to cleanup (if necessary) before quitting
    UQuickTime::Finalize();
    
    if (mFilterInstance)
        CloseComponent (mFilterInstance);
}
 
// ---------------------------------------------------------------------------
//      ¥ AttemptQuitSelf(Int32 inSaveOption)
// ---------------------------------------------------------------------------
//  Do cleanup
 
Boolean
CSoundboardApp::AttemptQuitSelf(
    Int32   inSaveOption)
{
    if (LApplication::AttemptQuitSelf(inSaveOption)) {
        // Are we debugging?
        #ifdef DEBUG_IT
            if (mFilterInstance) {
                // Check to see if others are using our component
                long    instCount = CountComponentInstances ((Component) mFilterInstance);
        
                if (instCount > 1) {
                    SetStatusText(str_ValidInstancesExist);
                    SysBeep(10);
                    return false;
                }
            }
        #endif /*DEBUG_IT*/
    
        return true;
    }
    else return false;
}
 
 
// ---------------------------------------------------------------------------
//      ¥ ObeyCommand
// ---------------------------------------------------------------------------
//  Respond to commands
 
Boolean
CSoundboardApp::ObeyCommand(
    CommandT    inCommand,
    void        *ioParam)
{
    Boolean cmdHandled = true;
    
    switch (inCommand) {
    
        // +++ Add cases here for the commands you handle
        //      Remember to add same cases to FindCommandStatus below
        //      to enable/disable the menu items for the commands
    
        case cmd_EnableFilter:
            if (mFilterInstance) {
                mEnhanceStereo = !mEnhanceStereo;
                DoSetEnhanceStereo (mFilterInstance, mEnhanceStereo);
                SetStatusText(mEnhanceStereo ? str_EnhanceStereoResultOnStr : str_EnhanceStereoResultOffStr);
            }
            break;
 
        case cmd_UseExtGains:
            if (mFilterInstance) {
                mFilterUsesGains = kExtGainControl;
                DoSetUseGain (mFilterInstance, mFilterUsesGains);
            }
            break;
 
        case cmd_srsFilter:
            if (mFilterInstance) {
                mFilterUsesGains = kSRSDiffFilter;
                DoSetUseGain (mFilterInstance, mFilterUsesGains);
            }
            break;
 
        case cmd_srsGain:
            if (mFilterInstance) {
                mFilterUsesGains = kSRSDiffGain;
                DoSetUseGain (mFilterInstance, mFilterUsesGains);
            }
            break;
 
        case cmd_3DAudio:
            if (mFilterInstance) {
                mFilterUsesGains = k3DAudio;
                DoSetUseGain (mFilterInstance, mFilterUsesGains);
            }
            break;
 
        case cmd_3DAudio5b:
            if (mFilterInstance) {
                mFilterUsesGains = k3DAudio5b;
                DoSetUseGain (mFilterInstance, mFilterUsesGains);
            }
            break;
 
        case cmd_3DAudioOnly:
            if (mFilterInstance) {
                mFilterUsesGains = k3DAudioOnly;
                DoSetUseGain (mFilterInstance, mFilterUsesGains);
            }
            break;
 
        case cmd_XTalk5b:
            if (mFilterInstance) {
                mFilterUsesGains = kXTalk5b;
                DoSetUseGain (mFilterInstance, mFilterUsesGains);
            }
            break;
            
        case cmd_XTalkJG:
            if (mFilterInstance) {
                mFilterUsesGains = kXTalkJG;
                DoSetUseGain (mFilterInstance, mFilterUsesGains);
            }
            break;
 
        case cmd_XTalkJGtest:
            if (mFilterInstance) {
                mFilterUsesGains = kXTalkJGtest;
                DoSetUseGain (mFilterInstance, mFilterUsesGains);
            }
            break;
 
        case cmd_3DAudioJG:
            if (mFilterInstance) {
                mFilterUsesGains = k3DAudioJG;
                DoSetUseGain (mFilterInstance, mFilterUsesGains);
            }
            break;
 
        case cmd_SoundBoardW:
            if (mStatusWindow->IsVisible())
                mStatusWindow->Hide();
            else mStatusWindow->Show();
 
            break;
            
        case cmd_Open:
            CQuickTimeWindow::CreateQuickTimeWindow(WIND_QuickTimeMovie, this, true);
 
            break;
            
        default:
            cmdHandled = LApplication::ObeyCommand(inCommand, ioParam);
            break;
    }
    
    return cmdHandled;
}
 
 
// ---------------------------------------------------------------------------
//      ¥ FindCommandStatus
// ---------------------------------------------------------------------------
//  Pass back status of a (menu) command
 
void
CSoundboardApp::FindCommandStatus(
    CommandT    inCommand,
    Boolean     &outEnabled,
    Boolean     &outUsesMark,
    Char16      &outMark,
    Str255      outName)
{
    switch (inCommand) {
    
        // +++ Add cases here for the commands you handle.
        //
        //      Set outEnabled to TRUE for commands that can be executed at
        //      this time.
        //
        //      If the associated menu items can have check marks, set
        //      outUsesMark and outMark accordingly.
        //
        //      Set outName to change the name of the menu item
        
        case cmd_EnableFilter:
            outEnabled = (mFilterInstance != nil);
            outUsesMark = true;
            outMark = mEnhanceStereo ? checkMark : noMark;
            break;
            
        case cmd_UseExtGains:
            outEnabled = (mFilterInstance != nil);
            outUsesMark = true;
            outMark = (mFilterUsesGains == kExtGainControl) ? checkMark : noMark;
            break;
            
        case cmd_srsFilter:
            outEnabled = (mFilterInstance != nil);
            outUsesMark = true;
            outMark = (mFilterUsesGains == kSRSDiffFilter) ? checkMark : noMark;
            break;
            
        case cmd_srsGain:
            #ifndef kConfigGenCrossoverFilter
                outEnabled = (mFilterInstance != nil);
            #else
                outEnabled = false;
            #endif
            outUsesMark = true;
            outMark = (mFilterUsesGains == kSRSDiffGain) ? checkMark : noMark;
            break;
            
        case cmd_3DAudio:
            outEnabled = (mFilterInstance != nil);
            outUsesMark = true;
            outMark = (mFilterUsesGains == k3DAudio) ? checkMark : noMark;
            break;
            
        case cmd_3DAudio5b:
            outEnabled = (mFilterInstance != nil);
            outUsesMark = true;
            outMark = (mFilterUsesGains == k3DAudio5b) ? checkMark : noMark;
            break;
            
        case cmd_3DAudioOnly:
            outEnabled = (mFilterInstance != nil);
            outUsesMark = true;
            outMark = (mFilterUsesGains == k3DAudioOnly) ? checkMark : noMark;
            break;
            
        case cmd_XTalk5b:
            outEnabled = (mFilterInstance != nil);
            outUsesMark = true;
            outMark = (mFilterUsesGains == kXTalk5b) ? checkMark : noMark;
            break;
            
        case cmd_XTalkJG:
            outEnabled = (mFilterInstance != nil);
            outUsesMark = true;
            outMark = (mFilterUsesGains == kXTalkJG) ? checkMark : noMark;
            break;
            
        case cmd_XTalkJGtest:
            outEnabled = (mFilterInstance != nil);
            outUsesMark = true;
            outMark = (mFilterUsesGains == kXTalkJGtest) ? checkMark : noMark;
            break;
            
        case cmd_3DAudioJG:
            outEnabled = (mFilterInstance != nil);
            outUsesMark = true;
            outMark = (mFilterUsesGains == k3DAudioJG) ? checkMark : noMark;
            break;
            
        case cmd_Open:
            outEnabled = UQuickTime::QuickTimeIsPresent();
            break;
 
        case cmd_SoundBoardW:
            outEnabled = true;
            ::GetIndString(outName, STRx_ShowHideSoundBoard, mStatusWindow->IsVisible()?
                                str_HideSoundBoard:str_ShowSoundBoard);
            break;
    
        default:
            LApplication::FindCommandStatus(inCommand, outEnabled, outUsesMark,
                                outMark, outName);
            break;
    }
}
 
 
 
// ---------------------------------------------------------------------------
//      ¥ SetStatusText
// ---------------------------------------------------------------------------
//  Get status text from STR# resource and update status box
 
void
CSoundboardApp::SetStatusText(short index)
{
    // Get error string
    LEditField  *statusPane = (LEditField   *)mStatusWindow->FindPaneByID('Stat');
    
    if (statusPane) {
        Str255      str;
        
        GetIndString (str, STRx_StatusStrsID, index);
        statusPane->SetDescriptor(str);
        mClipped = 0;
    }
 
}
 
// ---------------------------------------------------------------------------
//      ¥ OpenFilterComponent
// ---------------------------------------------------------------------------
//  Open up an instance of our filter component
 
void
CSoundboardApp::OpenFilterComponent ()
{
    if (!mFilterInstance && mFilterComponentID) {
 
        // Open the component
        mFilterInstance = (FilterComponent) OpenComponent (mFilterComponentID);
        if (!mFilterInstance)
            SetStatusText(str_DidNotGetInstStr);
        else {
            int i;
            
            mFilterUsesGains = mEnhanceStereo = mChangeCount = kUninited;
            mClipped = 0;
            for (i=0; i<kMaxSliders; ++i)
                mGainValue[i] = kUninited;
        }
        
    }
    else    // We were not asked to find some kind of Filter component
        SetStatusText(str_DidNotFindCompIDStr);
        
}
 
 
// ---------------------------------------------------------------------------
//      ¥ UpdateFilterCntls
// ---------------------------------------------------------------------------
//  Update the filter controls
 
void
CSoundboardApp::UpdateFilterCntls(void)
{
    if (mFilterInstance)
    {
        short changeCount;
        unsigned short clipped;
        
        DoGetChangeCount(mFilterInstance, &changeCount);
        if (changeCount != mChangeCount)
        {
            short i, enhancedStereo;
            
            changeCount = mChangeCount;
                
            // Check to see if state of enhanced stereo has changed
            DoGetEnhanceStereo (mFilterInstance, &enhancedStereo);
            if (enhancedStereo != mEnhanceStereo)
            {
                mEnhanceStereo = enhancedStereo;
                SetStatusText(mEnhanceStereo ? str_EnhanceStereoResultOnStr : str_EnhanceStereoResultOffStr);
            }
            
            // Check to see if filter is using its built in gain algorithms
            DoGetUseGain(mFilterInstance, &mFilterUsesGains);
            
            // Check to see slider values or labels have changed
            for (i=FirstSliderID; i<=LastSliderID; ++i) {
                CFilterControl *filterControlPane = (CFilterControl *)mStatusWindow->FindPaneByID(i);
 
                if (filterControlPane)
                {
                    unsigned short labelChanges;
                    Str255 labelStr;
                    double filterGain;
                    
                    DoGetGain (mFilterInstance, i-FirstSliderID, &filterGain);
                    if (filterGain != ((double)kMaxGain - mGainValue[i-FirstSliderID])/kMaxGain)
                    {
                        short sliderGain = ceil(kMaxGain - kMaxGain*filterGain - 0.5);
 
                        filterControlPane->SendAESetValue(sliderGain, true);
                        mGainValue[i-FirstSliderID] = sliderGain;
                    }
                    
                    DoGetGainLabel (mFilterInstance, i-FirstSliderID, &labelChanges, labelStr);
                    if (labelChanges != filterControlPane->mLabelChanges)
                    {
                        LCaption *label = filterControlPane->mLabel;
                        
                        if (label)
                        {
                            label->SetDescriptor(labelStr);
                            label->Refresh();
                            
                            if (*labelStr)
                            {
                                filterControlPane->Show();
                                label->Show();
                            }
                            else
                            {
                                filterControlPane->Hide();
                                label->Hide();
                            }
                        }
                        filterControlPane->mLabelChanges = labelChanges;
                    }
                }
            }
        }
        DoGetClipped (mFilterInstance, &clipped);
        if ((clipped && !mClipped) || (!clipped && mClipped))
        {
            SetStatusText(clipped ? str_ClippingStr : str_NotClippingStr);
            mClipped = clipped;
        }
    }
}
 
// ---------------------------------------------------------------------------
//      ¥ SpendTime
// ---------------------------------------------------------------------------
//  Idle time: Update the filter controls
 
void
CSoundboardApp::SpendTime(
    const EventRecord&  /* inMacEvent */)
{
    UpdateFilterCntls();
}