/*

File: MyController.m

Author: David Stolarsky

Change History (most recent first): <1> 05/26/06 began modifying Apple's sample code to drive SZG graphics with the Quicktime FFT
                                    <2> 11/24/05 initial release

© Copyright 2006 David Stolarsky. All rights reserved.

*/

#import "MyController.h"

static UInt32 numberOfBandLevels = 8;       // increase this number for more frequency bands
static UInt32 numberOfChannels = 1;         // for StereoMix - If using DeviceMix, you need to get the channel count of the device.
static UInt8 FFTsPerSecond = 100;
static UInt8 LengthOfFFTHistory = 100;

UInt8 currentFFTIndex = 0;

extern cosmos_loop(QTAudioFrequencyLevels*);

@implementation MyController

- (void)awakeFromNib
{
        UInt32 i;

        mFreqResultsHist = malloc(sizeof(QTAudioFrequencyLevels*) * LengthOfFFTHistory);
        for(i = 0; i < LengthOfFFTHistory; i++) {
                // allocate memory for the QTAudioFrequencyLevels struct and set it up
                // depending on the number of channels and frequency bands you want    
                mFreqResultsHist[i] = malloc(offsetof(QTAudioFrequencyLevels, level[numberOfBandLevels * numberOfChannels]));
                mFreqResultsHist[i]->numChannels = numberOfChannels;
                mFreqResultsHist[i]->numFrequencyBands = numberOfBandLevels;
        }

        blank_mFreq = malloc(offsetof(QTAudioFrequencyLevels, level[numberOfBandLevels * numberOfChannels]));
        blank_mFreq->numChannels = numberOfChannels;
        blank_mFreq->numFrequencyBands = numberOfBandLevels;
        for(i = 0; i < numberOfBandLevels * numberOfChannels; i++) {
                blank_mFreq->level[i] = 0.0;
        }

        // set up a timer and add it to the run loop
        mTimer = [NSTimer timerWithTimeInterval:1.0/FFTsPerSecond target:self selector:@selector(myTimerFireMethod:) userInfo:nil repeats:YES];

        [[NSRunLoop currentRunLoop] addTimer:mTimer forMode:(NSString *)kCFRunLoopCommonModes];
}

#pragma mark ---- panel callbacks ----

// movie opening panel
- (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
    if (NSOKButton == returnCode) {
        NSString *theFilename = [[sheet filenames] objectAtIndex:0];
        [sheet close];

        [self openMovie:theFilename];
    }
}

#pragma mark ---- timer ----

// timer method to display the frequency levels in the UI
- (void)myTimerFireMethod:(NSTimer*)theTimer
{
        UInt8 i, j;

    // get the levels from the movie
        OSStatus err = GetMovieAudioFrequencyLevels([mMovie quickTimeMovie], kQTAudioMeter_MonoMix, mFreqResultsHist[currentFFTIndex]);
    if (err) {
        // something went wrong so send blank levels
                [mWindow setTitle:[NSString stringWithFormat:@"%d on GetMovieAudioFrequencyLevels", err]];
                cosmos_loop(blank_mFreq);
        return;
    }

        cosmos_loop(mFreqResultsHist[i]);
}

#pragma mark ---- open movie/set up metering ----

// select a file to open
- (IBAction)doOpen:(id)sender
{
        [[NSOpenPanel openPanel] beginSheetForDirectory:nil
                             file:nil
                             types:nil
                             modalForWindow:mWindow
                             modalDelegate:self
                             didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:)
                             contextInfo:nil];
}

// open the QTMovie and set it in the view replacing the movie that was there
- (void)openMovie:(NSString *)inFile
{
    NSAlert *alert = nil;
    NSError *error = nil;

        if (mMovie != nil) {
        [mMovieView pause:self];
                [mMovieView setMovie:nil];
        }

    mMovie = [QTMovie movieWithFile:inFile error:&error];

    if (nil == error) {

        [mWindow setTitle:[mMovie attributeForKey:QTMovieDisplayNameAttribute]];

        [mMovieView setMovie:mMovie];
        [mMovieView setNeedsDisplay:TRUE];

        if (TRUE == [[mMovie attributeForKey:QTMovieHasAudioAttribute] boolValue]) {

            // do this once per movie to establish metering
            OSStatus err = SetMovieAudioFrequencyMeteringNumBands([mMovie quickTimeMovie], kQTAudioMeter_MonoMix, &numberOfBandLevels);
            if (err) {
                // if something went wrong turn it off
                [mWindow setTitle:[NSString stringWithFormat:@"Error %d", err]];

                [self toggleFreqLevels:self];
            } else {
            }
        } else {
            alert = [NSAlert alertWithMessageText:@"No Sound Track!"
                             defaultButton:@"OK"
                             alternateButton:nil
                             otherButton:nil
                             informativeTextWithFormat:@"Open some media that contains audio if you're planing to see some frequency levels."];

            [alert runModal];
        }
    } else {

        alert = [NSAlert alertWithError:error];

                [alert runModal];
    }
}

#pragma mark ---- application delegates ----

// split when window is closed
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
{
    return YES;
}

@end