TS3Menu.c

/*
 *  File:       TS3Menu.c
 *
 *  Copyright © 1996 Apple Computer, Inc.
 */
 
#include <assert.h>
 
#include <Dialogs.h>
#include <Menus.h>
#include <Resources.h>
#include <TextUtils.h>
 
#include "SoundSprocket.h"
 
#include "TS3Main.h"
#include "TS3Menu.h"
#include "TS3Resource.h"
#include "TS3Sound.h"
#include "TS3TestAPI.h"
#include "TS3TestLoLevel.h"
#include "TS3TestHiLevel.h"
#include "TS3Window.h"
 
 
typedef struct Node Node;
struct Node {
    Node*           lo;
    Node*           hi;
    Str255          name;
};
 
 
static MenuHandle   gMenuSound              = NULL;
static MenuHandle   gMenuInterpolation      = NULL;
static short        gMenuSoundItem          = kSoundItem_Silence;
static short        gMenuInterpolationItem  = kInterpolationItem_Sinusoidal;
 
 
static void Insert(
    Node**          ioRoot,
    Node*           inNode);
 
static void Traverse(
    Node*           inNode);
 
static void SelectAppleMenu(
    short           inItem);
 
static void SelectFileMenu(
    short           inItem);
 
static void SelectSoundMenu(
    short           inItem);
 
static void SelectInterpolationMenu(
    short           inItem);
 
 
/* =============================================================================
 *      Menu_Init (external)
 *
 *  Initializes our menus.
 * ========================================================================== */
void Menu_Init(
    void)
{
    Node*           root;
    Node*           node;
    short           count;
    short           index;
    Handle          resource;
    short           resID;
    ResType         resType;
    Str255          resName;
    
    SetMenuBar(GetNewMBar(kMBarID_Main));
    DrawMenuBar();
    
    AppendResMenu(GetMenuHandle(kMenuID_Apple), 'DRVR');
    
    // Get the menus that we need
    gMenuSound = GetMenuHandle(kMenuID_Sound);
    gMenuInterpolation = GetMenuHandle(kMenuID_Interpolation);
    
    // Build the sound menu
    root = NULL;
    
    SetResLoad(false);
    count = Count1Resources('snd ');
    for (index = 1; index <= count; index++)
    {
        // Grab the resource name
        resource = Get1IndResource('snd ', index);
        assert(ResError() == noErr);
        assert(resource != NULL);
        
        GetResInfo(resource, &resID, &resType, resName);
        
        ReleaseResource(resource);
        
        // Insert a new node in the tree
        node = (Node*) NewPtr(sizeof(Node));
        assert(node != NULL);
        
        node->lo = NULL;
        node->hi = NULL;
        BlockMove(resName, node->name, resName[0]+1);
        
        Insert(&root, node);
    }
    SetResLoad(true);
    
    Traverse(root);
    
    // Check the right interpolation item
    CheckItem(gMenuInterpolation, gMenuInterpolationItem, true);
}
 
 
/* =============================================================================
 *      Insert (internal)
 *
 *  Sorts the given node into the tree.
 * ========================================================================== */
void Insert(
    Node**          ioRoot,
    Node*           inNode)
{
    if (*ioRoot != NULL)
    {
        if (CompareString((*ioRoot)->name, inNode->name, NULL) > 0)
        {
            Insert(&(*ioRoot)->lo, inNode);
        }
        else
        {
            Insert(&(*ioRoot)->hi, inNode);
        }
    }
    else
    {
        *ioRoot = inNode;
    }
}
 
 
/* =============================================================================
 *      Traverse (internal)
 *
 *  Appends the tree in alpha order onto the sound menu, and kills the tree.
 * ========================================================================== */
void Traverse(
    Node*           inNode)
{
    if (inNode != NULL)
    {
        Traverse(inNode->lo);
        
        AppendMenu(gMenuSound, inNode->name);
        
        Traverse(inNode->hi);
        
        DisposePtr((Ptr) inNode);
    }
}
 
 
/* =============================================================================
 *      Menu_Exit (external)
 *
 *  Cleans up.
 * ========================================================================== */
void Menu_Exit(
    void)
{
}
 
 
/* =============================================================================
 *      Menu_Select (external)
 *
 *  Takes action on the given menu item.
 * ========================================================================== */
void Menu_Select(
    short           inMenuID,
    short           inItem)
{
    switch (inMenuID)
    {
        case kMenuID_Apple:
            SelectAppleMenu(inItem);
        break;
        
        case kMenuID_File:
            SelectFileMenu(inItem);
        break;
        
        case kMenuID_Sound:
            SelectSoundMenu(inItem);
        break;
        
        case kMenuID_Interpolation:
            SelectInterpolationMenu(inItem);
        break;
        
        case kMenuID_LoLevelPreset:
            TestLoLevel_Preset(inItem);
        break;
        
        case kMenuID_HiLevelPreset:
            TestHiLevel_Preset(inItem);
        break;
    }
 
    HiliteMenu(0);
}
 
 
/* =============================================================================
 *      SelectAppleMenu (internal)
 *
 *  Takes action on the given Apple menu item.
 * ========================================================================== */
void SelectAppleMenu(
    short           inItem)
{
    switch (inItem)
    {
        case kAppleItem_About:
            Alert(kAlrtID_About, NULL);
        break;
    }
}
 
 
/* =============================================================================
 *      SelectFileMenu (internal)
 *
 *  Takes action on the given File menu item.
 * ========================================================================== */
void SelectFileMenu(
    short           inItem)
{
    switch (inItem)
    {
        case kFileItem_RunQuiet:
            TestAPI_Execute();
        break;
        
        case kFileItem_Config3DSound:
            Sound_Configure();
        break;
        
        case kFileItem_Quit:
            Main_LastRoundup();
        break;
    }
}
 
 
/* =============================================================================
 *      SelectSoundMenu (internal)
 *
 *  Takes action on the given Sound menu item.
 * ========================================================================== */
void SelectSoundMenu(
    short           inItem)
{
    Str255          name;
    
    CheckItem(gMenuSound, gMenuSoundItem, false);
    
    switch (inItem)
    {
        case kSoundItem_Silence:
            Sound_PlaySilence();
            gMenuSoundItem = kSoundItem_Silence;
        break;
        
        default:
            GetMenuItemText(GetMenuHandle(kMenuID_Sound), inItem, name);
            
            if (Sound_PlayResource(name))
            {
                gMenuSoundItem = inItem;
            }
            else
            {
                gMenuSoundItem = kSoundItem_Silence;
            }
    }
    
    CheckItem(gMenuSound, gMenuSoundItem, true);
}
 
 
/* =============================================================================
 *      SelectInterpolationMenu (internal)
 *
 *  Takes action on the given Interpolation menu item.
 * ========================================================================== */
void SelectInterpolationMenu(
    short           inItem)
{
    switch (inItem)
    {
        case kInterpolationItem_Sinusoidal:
        case kInterpolationItem_Triangular:
        case kInterpolationItem_Sawtooth:
            if (gMenuInterpolationItem != inItem)
            {
                CheckItem(gMenuInterpolation, gMenuInterpolationItem, false);
                
                gMenuInterpolationItem = inItem;
                
                CheckItem(gMenuInterpolation, gMenuInterpolationItem, true);
            }
        break;
    }
    
}
 
 
/* =============================================================================
 *      Menu_GetInterpolation (external)
 *
 *  Returns the current interpolation mode.
 * ========================================================================== */
short Menu_GetInterpolation(
    void)
{
    return gMenuInterpolationItem;
}