/* Copyright (c) 2004, Noah Sorscher
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 	¥ 	Redistributions of source code must retain the above copyright
 * 	notice, this list of conditions and the following disclaimer.
 * 	¥ 	Redistributions in binary form must reproduce the above copyright
 * 	notice, this list of conditions and the following disclaimer in the
 * 	documentation and/or other materials provided with the distribution.
 * 	¥ 	Neither the name of the Noah Sorscher nor the names of its
 * 	contributors may be used to endorse or promote products derived from
 * 	this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */
#import "tSync.h"
#include "Movies.h"




@implementation tSync



NSString *HandleToString(Handle h);



- (IBAction)syncAud:(id)sender
{
    double input = [audBox doubleValue];
    Track aTrack, bTrack;
    NSMovie *aMovie = [movieView movie];
    Movie qtMovie;
    long index, n, j;
    TimeValue oldTV, newTV;
    TimeScale ts, offset;
    //OSType trackType;
    BOOL neg;
    BOOL audioNow;
    
    if (input < 0) {
        neg = YES;
        input = 0 - input;
    } else if (input > 0) neg = NO;
    else if (input == 0) return;
    
    [audBox setStringValue:@""];
    if (aMovie == nil || ![aMovie isKindOfClass:[NSMovie class]]) {
        NSBeep();
        return;
    }
    qtMovie = [aMovie QTMovie];
    ts = GetMovieTimeScale(qtMovie);
    offset = (double)input * (double)ts;
    
    n = GetMovieTrackCount(qtMovie);
    for (index=1; index <= n; index++) {
        aTrack = GetMovieIndTrack(qtMovie, index);
        audioNow = NO;
        bTrack = GetMovieIndTrackType(qtMovie, 1, SoundMediaType, movieTrackMediaType);
        for ( j = 2; bTrack != nil; j++) {
            if (aTrack == bTrack) audioNow = YES;
            bTrack = GetMovieIndTrackType(qtMovie, j, SoundMediaType, movieTrackMediaType);
        }
        oldTV = GetTrackOffset(aTrack);
        newTV = oldTV + offset;
        // if the input is negative, we offset the non-audio tracks.  if the input is positive, we offset the audio tracks.
        if ((neg && !audioNow) || (!neg && audioNow))
            SetTrackOffset(aTrack, newTV);
        //aTrack = GetMovieIndTrackType(qtMovie, index, AudioMediaType, movieTrackMediaType);
    }
    
}

- (IBAction)syncVid:(id)sender
{
    double input = [vidBox doubleValue];
    Track aTrack;
    Movie qtMovie;
    NSMovie *aMovie = [movieView movie];
    long index;
    TimeScale ts;
    TimeValue oldDuration, newDuration;
    
    [vidBox setStringValue:@""];
    if (aMovie == nil || ![aMovie isKindOfClass:[NSMovie class]]) {
        NSBeep();
        return;
    }
    qtMovie = [aMovie QTMovie];
    ts = GetMovieTimeScale(qtMovie);
    
    aTrack = GetMovieIndTrackType(qtMovie, 1, VideoMediaType, movieTrackMediaType);
    for (index=2; aTrack != nil; index++) {
        oldDuration = GetTrackDuration(aTrack);
        newDuration = oldDuration + ((double)input * (double)ts);
        ScaleTrackSegment(aTrack, 0, oldDuration, newDuration);
        aTrack = GetMovieIndTrackType(qtMovie, index, VideoMediaType, movieTrackMediaType);
    }
}

//////////
//
// Tracks
//
//////////


- (IBAction)toggleTracks:(id)sender
{
    [tracksDrawer toggle:nil];
    [self reloadAudioMenu];
}

- (void)reloadAudioMenu
{
    NSMovie *theMovie = nil;
    theMovie = [movieView movie];
    if (nil == theMovie) return;
    Movie qtMovie = [theMovie QTMovie];
    [audMenu removeAllItems];
    Track aTrack;
    UserData ud;
    Handle h = NewHandle(0);
    NSString *name;
    int i = 1;
    int selected = 0;
    aTrack = GetMovieIndTrackType(qtMovie, i++, SoundMediaType, movieTrackMediaType);
    while (aTrack != nil) {
        ud = GetTrackUserData(aTrack);
        GetUserData(ud, h, kUserDataName, 1);
        name = HandleToString(h);
        if ([name length] == 0) name = [NSString stringWithFormat:@"Sound Track %d", i-1];
        [audMenu addItemWithTitle:name];
        if (GetTrackEnabled(aTrack))
            selected = i-2;
        aTrack = GetMovieIndTrackType(qtMovie, i++, SoundMediaType, movieTrackMediaType);
    }
    if (selected != 0) [audMenu selectItemAtIndex:selected];
}

- (IBAction)changeTracks:(id)sender
{
    NSMovie *theMovie = nil;
    theMovie = [movieView movie];
    if (nil == theMovie) return;
    Movie qtMovie = [theMovie QTMovie];
    int selected = [audMenu indexOfSelectedItem] + 1;
    int i = 1;
    Track aTrack = GetMovieIndTrackType(qtMovie, i++, SoundMediaType, movieTrackMediaType);
    while (aTrack != nil) {
        SetTrackEnabled(aTrack, i-1 == selected);
        aTrack = GetMovieIndTrackType(qtMovie, i++, SoundMediaType, movieTrackMediaType);
    }
}

- (IBAction)changeName:(id)sender
{
    NSMovie *theMovie = nil;
    theMovie = [movieView movie];
    if (nil == theMovie) return;
    int selected = [audMenu indexOfSelectedItem] + 1;
    NSString *name = [nameBox stringValue];
    if ([name length] == 0) return;
    const char *cString = [name cString];
    Movie qtMovie = [theMovie QTMovie];
    Track aTrack = GetMovieIndTrackType(qtMovie, selected, SoundMediaType, movieTrackMediaType);
    UserData ud = GetTrackUserData(aTrack);
    while (RemoveUserData(ud, kUserDataName, 1) == noErr);
    SetUserDataItem(ud, cString, [name length], kUserDataName, 0);
    [audMenu removeItemAtIndex:selected-1];
    [audMenu insertItemWithTitle:name atIndex:selected-1];
    [audMenu selectItemAtIndex:selected-1];
}


NSString *HandleToString(Handle h) {
    NSString *outputString;
    Size theSize;
    NSData *theData;
    char *buffer;
    
    if (h == NULL) return NULL;
    theSize = GetHandleSize( h );
    if (0 == theSize) return @"";
    
    theData = [[[NSData dataWithBytes:*h length:theSize] copy] autorelease];
    buffer = (char *)[theData bytes];
    outputString = [NSString stringWithCString:buffer];
    if (theSize < [outputString length])
        outputString = [outputString substringToIndex:theSize];
    return outputString;
}

@end
