/****************************************************************************
 *   Copyright (C) 2004 by Arboretum Systems, Inc.                          *
 *   Technical administrator: Alain Mazy, hav@mazy.be                       *
 *   Lead program designer: Georges Jaroslaw, gjaro@arboretum.com           *
 *                                                                          *
 *   HyperEngine-AV is a video, audio and text editor that can be used to   *
 *   record, import, edit, process and arrange together video, sound and    *
 *   text. These are all achieved in the program's free-form document       *
 *   window, with no limitations to the number of tracks.                   *
 *   The purpose of this program is to provide to users at all levels of    *
 *   expertise a readily accessible tool enabling them to create movies,    *
 *   slide shows or presentations.                                          *
 *                                                                          *
 *   HyperEngine-AV itself is free software. However, plug-ins that can be  *
 *   used as add-ons to HyperEngine-AV may or may not be free software, at  *
 *   the discretion of each plug-in developer and as specified by these     *
 *   plug-ins' respective licenses.                                         *
 *   You can redistribute HyperEngine-AV itself and/or modify it under the  *
 *   terms of the GNU General Public License as published by the Free       *
 *   Software Foundation; either version 2 of the License, or (at your      *
 *   option) any later version.                                             *
 *                                                                          *
 *   HyperEngine-AV is distributed in the hope that it will be useful, but  *
 *   WITHOUT ANY WARRANTY; without even the implied warranty of             *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
 *   GNU General Public License for all applicable details.                 *
 *                                                                          *
 *   You should have received a copy of the GNU General Public License      *
 *   along with this program; if not, write to:                             *
 *   Free Software Foundation, Inc.,                                        *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.              *
 ****************************************************************************/
#import "MIMainViewController.h"
#import "MIObject.h"
#import "MIObjectRep.h"
#import "MIMontageDocument.h"
#import "MITopLevelContainerRep.h"
#import "MIApplicationController.h"
#import "MIOverviewController.h"
#import "MIMainScrollView.h"
#import "MIAllCommands.h"
#import "TArmeDoc.h"
#import "MIPreferences.h"
#import "MITimePaletteController.h"
#import "MIAudioClipInspectorController.h"
#import "MIDeleteContainerCommand.h"
#import "MIImportPanelController.h"
#import "MIAdvancedFadeInCommand.h"
#import "MIAdvancedFadeOutCommand.h"
#import "MITime.h"
#import "MIApplicationController.h"
#import "MIApplication.h"
#import "MICreateTextClipCommand.h"
#import "MontageVerbose.h"

#ifndef TArmeDoc_h
#include "TArmeDoc.h"
#endif //TArmeDoc_h

#ifndef ZzTimer_h
#include "ZzTimer.h"
#endif ZzTimer_h

#ifndef MovieHelper_h
#include "MovieHelper.h"
#endif //MovieHelper_h

#ifndef ZzHelpers_h
#include "ZzHelpers.h"
#endif //ZzHelpers_h

#undef VER_DEF_TOPIC
#define VER_DEF_TOPIC interfaceStephan

static const UInt32 gNbHZoomIndices = 83; //44;
//static const UInt32 gNbHZoomIndices = 47;
static SInt32 gHZoomPNValues[gNbHZoomIndices] = 
{ 
	1 << 22,
	(1 << 21) + (1 << 20) + ( 1 << 19 ),
	(1 << 21) + (1 << 20),
	(1 << 21) + (1 << 19),
	1 << 21,
	(1 << 20) + (1 << 19) + ( 1 << 18 ),
	(1 << 20) + (1 << 19),
	(1 << 20) + (1 << 18),
	1 << 20,
	(1 << 19) + (1 << 18) + ( 1 << 17 ),
	(1 << 19) + (1 << 18),
	(1 << 19) + (1 << 17),
	1 << 19,
	(1 << 18) + (1 << 17) + ( 1 << 16 ),
	(1 << 18) + (1 << 17),
	(1 << 18) + (1 << 16),
	1 << 18,
	(1 << 17) + (1 << 16) + ( 1 << 15 ),
	(1 << 17) + (1 << 16),
	(1 << 17) + (1 << 15),
	1 << 17,
	(1 << 16) + (1 << 15) + ( 1 << 14 ),
	(1 << 16) + (1 << 15),
	(1 << 16) + (1 << 14),
	1 << 16,
	(1 << 15) + (1 << 14) + ( 1 << 13 ),
	(1 << 15) + (1 << 14),
	(1 << 15) + (1 << 13),
	1 << 15,
	(1 << 14) + (1 << 13) + ( 1 << 12 ),
	(1 << 14) + (1 << 13),
	(1 << 14) + (1 << 12),
	1 << 14,
	(1 << 13) + (1 << 12) + ( 1 << 11 ),
	(1 << 13) + (1 << 12),
	(1 << 13) + (1 << 11),
	1 << 13,
	(1 << 12) + (1 << 11) + ( 1 << 10 ),
	(1 << 12) + (1 << 11),
	(1 << 12) + (1 << 10),
	1 << 12,
	(1 << 11) + (1 << 10) + ( 1 << 9 ),
	(1 << 11) + (1 << 10),
	(1 << 11) + (1 << 9),
	1 << 11,
	(1 << 10) + (1 << 9) + ( 1 << 8 ),
	(1 << 10) + (1 << 9),
	(1 << 10) + (1 << 8),
	1 << 10,
	(1 << 9) + (1 << 8) + ( 1 << 7 ),
	(1 << 9) + (1 << 8),
	(1 << 9) + (1 << 7),
	1 << 9,
	(1 << 8) + (1 << 7) + ( 1 << 6 ),
	(1 << 8) + (1 << 7),
	1 << 8,
	(1 << 7) + (1 << 6) + ( 1 << 5 ),
	(1 << 7) + (1 << 6),
	(1 << 7) + (1 << 5),
	1 << 7,
	(1 << 6) + (1 << 5) + ( 1 << 4 ),
	(1 << 6) + (1 << 5),
	(1 << 6) + (1 << 4),
	1 << 6,
	(1 << 5) + (1 << 4) + ( 1 << 3 ),
	(1 << 5) + (1 << 4),
	(1 << 5) + (1 << 3),
	1 << 5,
	(1 << 4) + (1 << 3) + ( 1 << 2 ),
	(1 << 4) + (1 << 3),
	(1 << 4) + (1 << 2),
	1 << 4,
	(1 << 3) + (1 << 2) + ( 1 << 1 ),
	(1 << 3) + (1 << 2),
	(1 << 3) + (1 << 1),
	1 << 3,
	(1 << 2) + (1 << 1) + ( 1 << 0 ),
	(1 << 2) + (1 << 1),
	(1 << 2) + (1 << 0),
	1 << 2,
	(1 << 1) + (1 << 0),
	1 << 1,
	1 << 0
/*
sub frame zoomlevels disabled
    ,
	-2,
	-5,
	-10
*/
};

static const UInt32 gDefaultHZoomIndex = 44; //23;

static const UInt32 gNbVZoomIndices = 5;
static SInt32 gVZoomPNValues[gNbVZoomIndices] = 
{ 
	3,
	2,
	1,
	-2,	
	-5, 		
//	-10 		
};
static const UInt32 gDefaultVZoomIndex = 2;

@implementation MIMainViewController

- (id)init
{
    if ( self = [self initWithWindowNibName:@"MainView"] )
    {
        [self setShouldCascadeWindows:YES];
        [self window];
        //[[self window] setTitle:@"New HyperEngine-AV"];
        //[[self window] registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
        fSelection = [[MIWSSelection alloc] initEmpty];
        fVZoomIndex = [MIMainViewController getDefaultVZoomIndex];
        fHZoomIndex = [MIMainViewController getDefaultHZoomIndex];
		fSnapper = [[MISnapper alloc] initWithMainViewController:self];
        fGridFlags = MIGlobalGrid|MIObjectsGrid; // global and objects grid
        [[self window] useOptimizedDrawing:YES];
    }
    return self;
}

- (void)dealloc {
    //NSLog(@"MIMainViewController - dealloc");
	[[NSNotificationCenter defaultCenter] removeObserver:self name:NSViewBoundsDidChangeNotification object:[[fTopLevelContainerView enclosingScrollView] contentView]];

#ifdef DEBUG	
	printf("about to release the selection reps : \n");
	if([fSelection count] == 0)
		printf("the selection contains no objects...\n");
	for(UInt32 i = 0; i < [fSelection count]; i++)
	{
		id rep = [fSelection objectAtIndex:i];
		printf("    %p\n",(void*)rep);
	}
#endif //#ifdef DEBUG	
	
	[fSelection release]; // i've seen it crashing here.... maybe simply remove the call. $$HACK$$ the selection is never released!
	[fSnapper release];
	[NSApp resetMainViewController];
    [super dealloc];
}

- (void)awakeFromNib
{
    NSRect frame = [[NSScreen mainScreen] visibleFrame];
    NSWindow *window = [self window];
    NSRect wFrame = [window frame];
    // done by benjamin : correction according to screen size.
	float ratio = 5.5 / 7.0;
	if(frame.size.width > 1100)
		ratio = 4.5 / 7.0;
	if(frame.size.width > 1300)
		ratio = 3.5 / 7.0;
	if(frame.size.width > 1700)
		ratio = 3.0 / 7.0;
		
    float newWidth = NSWidth( frame ) * ratio;
//    float newHeight = NSHeight( frame ) * ratio;
	float newHeight = newWidth*0.75;

   // wFrame = NSMakeRect( NSMinX( wFrame ) + NSMinX( frame ), NSMinY( wFrame ) - ( newHeight - NSHeight( wFrame ) ), newWidth, newHeight ) ;
    wFrame = NSMakeRect( NSMinX( frame ) + 4, NSMaxY( frame ) - 4 - newHeight, newWidth, newHeight ) ;
    
    [window setFrame:wFrame display:NO];    
}

/*
- (void)redraw
{
	//$$$STEPHAN_ADVISE
	[fTopLevelContainerView setNeedsDisplay:YES];
	[self updatePlayBar];
        [self updateLocators];
}
*/

- (id)panelLayoutManager
{
	return fPanelLayoutManager;
}


- (void)setTLC:(MIObject*)tlc
{
	if ( !tlc )
	{
		verntl(interfaceStephan,0,"Null TLC passed to MainViewController setTLC");
		return;
	}
	[fTLC release];
	
	fTLC = [tlc retain];
}

- (MIObject*)getTLC
{
	return fTLC;
}

- (MITopLevelContainerRep*)topLevelContainerView
{
	return fTopLevelContainerView;
}

- (void)setTopLevelContainerView:(MITopLevelContainerRep*)newTLC
{
	if ( !newTLC )
	{
		verntl(interfaceStephan,0,"NULL newTLC passed to setTopLevelContainer in MIMainViewController");
	}

        [[NSNotificationCenter defaultCenter] removeObserver:self name:NSViewBoundsDidChangeNotification object:[[fTopLevelContainerView enclosingScrollView] contentView]];

	[[newTLC representedObject] setMontageDoc:[self document]];
	[fMainScrollView setDocumentView:newTLC];
	fTopLevelContainerView = newTLC;
	fTLC = [newTLC representedObject];
	[fTopLevelContainerView setAutoresizesSubviews:NO];
	[fTopLevelContainerView setNeedsDisplay:YES];

	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(TLCScrolled:)name:NSViewBoundsDidChangeNotification object:[[fTopLevelContainerView enclosingScrollView] contentView]];
}


- (void)TLCScrolled:(NSNotification*)theNotification
{
	NSEnumerator		*childEnum;
	MIObject			*aChild;
	NSRect				minRect;
	MIObjectRep			*childRep;
	[[MIOverviewController sharedOverviewController] reflectScrolling:fTopLevelContainerView];
	
	// cacheing
	
	childEnum = [[[fTopLevelContainerView representedObject] getChildren] objectEnumerator];
	
	minRect = [fTopLevelContainerView visibleRect];
	
	minRect = NSInsetRect(minRect, -kCacheingHorizontalExtra, -kCacheingVerticalExtra);
	
	while ( aChild = [childEnum nextObject] )
	{
		childRep = [aChild findRepresentationInTLC:fTopLevelContainerView];
		[childRep cacheImagesIfSizeSmallerThan:kCacheingMinSize frameIsInRect:minRect];
		if ( [MIPreferences movingTitles] )
		{
			[aChild setTitlesNeedDisplay];
		}
	}
}


- (void)updatePlayBar
{
    TArmeDoc				*aTArmeDoc;
    ArmeTime				newArmeTimePos;

    aTArmeDoc = [[self document] armeDocument];

    aTArmeDoc->LockRead();
    newArmeTimePos = aTArmeDoc->GetPlayPos();
    aTArmeDoc->UnlockRead();

    [fTopLevelContainerView setCurrentPlayBarPosition:newArmeTimePos];
}

- (void)updateLocators
{
    TArmeDoc				*aTArmeDoc;
    ArmeTime				leftLocTime;
    ArmeTime				rightLocTime;

    aTArmeDoc = [[self document] armeDocument];

    aTArmeDoc->LockRead();
    leftLocTime = aTArmeDoc->GetLLocator();
    rightLocTime = aTArmeDoc->GetRLocator();
    aTArmeDoc->UnlockRead();

    [fTopLevelContainerView setLeftLocatorPosition:leftLocTime];
    [fTopLevelContainerView setRightLocatorPosition:rightLocTime];
}


- (NSScrollView*)mainScrollView
{
	return fMainScrollView;
}

- (MIRuler*)ruler
{
	return fRuler;
}

- (void)setRepresentedDocument:(MIMontageDocument*)document
{
    NSLog(@"MIMainViewController - setRepresentedDocument:  is deprecated. Please use setDocument: instead. (should not be used, as the NSDocument takes care of this for you.)");
    [[MIApplicationController sharedApplicationController] beep];
    //[self setDocument:document];
	/*if ( !document )
	{
		verntl(interfaceStephan,0,"Null TLC passed to MainViewController setTLC");
		return;
	}
	
	if ( fRepresentedDocument )
		[fRepresentedDocument release];

	fRepresentedDocument = document;*/
}

- (MIMontageDocument*)representedDocument
{
        NSLog(@"MIMainViewController - representedDocument  is deprecated. Please use document instead.");
    [[MIApplicationController sharedApplicationController] beep];
    return [self document];
	//return fRepresentedDocument;
}

- (void)nudgeSelection:(unichar)key withModifiers:(unsigned int)modifiers
{
	MIMoveCommand	*cmd;
	MITime			*oneSec = [MITime timeWithDocument:[self document]];
	MITime			*oneFrame = [MITime timeWithDocument:[self document]];
	MIPoint			offset = MIZeroPoint;
	
	if ( [fSelection type] != kMIWSSelectionTypeObjects )
		return;
	
	[oneSec setSeconds:1];
	[oneFrame setVideoFrames:1];

	if ( key == NSLeftArrowFunctionKey )
	{
		if ( modifiers == NSAlternateKeyMask )
		{
			offset.time = [oneFrame getArmeTime];
			GET_VALUE(offset.time) = - GET_VALUE(offset.time);
		}
		else if ( modifiers == NSAlternateKeyMask|NSShiftKeyMask )
		{
			offset.time = [oneFrame getArmeTime];
			GET_VALUE(offset.time) = - 10 * GET_VALUE(offset.time);
		}
		else if ( modifiers == NSAlternateKeyMask|NSControlKeyMask )
		{
			offset.time = [oneSec getArmeTime];
			GET_VALUE(offset.time) = - GET_VALUE(offset.time);
		}
		else
			return;
	}
	else if ( key == NSRightArrowFunctionKey )
	{
		if ( modifiers == NSAlternateKeyMask )
		{
			offset.time = [oneFrame getArmeTime];
		}
		else if ( modifiers == NSAlternateKeyMask|NSShiftKeyMask )
		{
			offset.time = [oneFrame getArmeTime];
			GET_VALUE(offset.time) = 10 * GET_VALUE(offset.time);
		}
		else if ( modifiers == NSAlternateKeyMask|NSControlKeyMask )
		{
			offset.time = [oneSec getArmeTime];
		}
		else
			return;
	}
	else
		return;

	cmd = [[[MIMoveCommand alloc] initWithSelection:fSelection] autorelease];
	[cmd setOffset:offset];
	[cmd setNewParent:nil]; // keep the same parent that each children already has.

	VUSERCMD1("Nudge (offset = %d)", (int)(offset.time.data));
	VUSERCMD_PRINT_SELECTION(fSelection);

	[[self document] doCmd:cmd];
	
	[[MITimePaletteController sharedTimePaletteController] getValuesFromMainView];

}

- (void)clearSelection
{
	//NSEnumerator*	selEnum;
	MIObjectRep*	rep;
	//selEnum = [self selectionObjectEnumerator];
	for(UInt32 i = 0; i < [fSelection count]; i++)
	//while ( rep = [selEnum nextObject] )
	{
		rep = [fSelection objectAtIndex:i];
		[rep setSelected:NO];
		[rep setNeedsDisplay];
	}
	[fSelection clear];
	[fSelection setObjectsType];
}

- (BOOL)addObjectToSelection:(MIObjectRep*)anObjectRep
{
	if ( !anObjectRep )
	{
		verntl(interfaceStephan,1,"NULL object rep passed to addObjectToSelection in MIMainViewController");
		return NO;
	}
	verntl(interfaceStephan,5,"ws object : " << [[anObjectRep representedObject] WSObject]->GetName() << " added to selection\n");
	[fSelection addObject:anObjectRep];
	
	[anObjectRep setSelected:YES];
	[anObjectRep setNeedsDisplay];

	return YES;
}

- (void)selectAll
{
	NSEnumerator	*objEnum;
	MIObject		*anObj;
	
	if ( [fSelection type] != kMIWSSelectionTypeTimeSlice )
	{
		// put all children of the TLC in the selection
		objEnum = [[[fTopLevelContainerView representedObject] getChildren] objectEnumerator];
		
		[fSelection clear];
		while ( anObj = [objEnum nextObject] )
		{
			[self addObjectToSelection:[anObj findRepresentationInTLC:fTopLevelContainerView]];
		}
		[fTopLevelContainerView setNeedsDisplay:YES];
	}
	else
	{
		anObj = [[fSelection objectAtIndex:0] representedObject];
		if ( anObj )
		{
			MIRect objFrame = [anObj absoluteModelFrame];
			[fSelection setStartTime:MIMinX(objFrame)];
			[fSelection setEndxTime:MIMaxX(objFrame)];
			[anObj setRepresentationsNeedDisplay];
		}
	}
}


- (BOOL)removeObjectFromSelection:(MIObjectRep*)anObjectRep
{
	if ( !anObjectRep )
	{
		verntl(interfaceStephan,1,"Being asked to remove a NULL object rep in MIMainViewController");
		return NO;
	}
	verntl(interfaceStephan,5,"ws object : " << [[anObjectRep representedObject] WSObject]->GetName() << " removed from selection\n");
	
	[fSelection removeObject:anObjectRep];
	[anObjectRep setSelected:NO];
	[anObjectRep setNeedsDisplay];
	
	return YES;
}

- (BOOL)isObjectInSelection:(MIObjectRep*)anObjectRep
{
	if ([fSelection indexOfObject:anObjectRep] == NSNotFound )
	{
		ZzAssert([anObjectRep isSelected] == NO);
		return NO;
	}
	ZzAssert([anObjectRep isSelected] != NO);
	return YES;
}

- (MIWSSelection*)selection
{
	return fSelection;
}

// if ZOOM_AROUND_PLAYBAR is defined, then the zoom is centered on the playbar
// otherwise, it is centered around the middle of the view rect

#define ZOOM_AROUND_PLAYBAR

- (void)setHZoom:(UInt32)hZoomIndex
{
	MIPoint p;
	
	verntl(interfaceStephan,5,"setHZoom : hZoomIndex = " << (int)hZoomIndex << " gHZoomPNValues[hZoomIndex] = " << (int)(gHZoomPNValues[hZoomIndex]));
	if(fHZoomIndex==hZoomIndex)
		return;
	
	// the point is to change
	// the zoom while keeping
	// the center position
	
	// thus, let's compute the ArmeTime 
	// of the center of the visible rect.
	NSRect	currentVisibleRect = [fTopLevelContainerView visibleRect];
	vverntl(interfaceStephan,5,currentVisibleRect);
	NSPoint	zoomCenterPixel;

	p = [fTopLevelContainerView currentCenter];
	
	zoomCenterPixel.y = NSMidY(currentVisibleRect);
#ifndef ZOOM_AROUND_PLAYBAR
	zoomCenterPixel.x = NSMidX(currentVisibleRect);
	vverntl(interfaceStephan,5,centerPixel);
#endif //#ifndef ZOOM_AROUND_PLAYBAR
	
	// now let's find the ArmeTime of this point
#ifndef ZOOM_AROUND_PLAYBAR
	ArmeTime zoomCenterArmeTime = [self pixelToArmeTime:centerPixel.x];
#else //#ifndef ZOOM_AROUND_PLAYBAR
	ArmeTime zoomCenterArmeTime = [fTLC WSObject]->GetDoc()->GetPlayPos();
#endif //#ifndef ZOOM_AROUND_PLAYBAR

	vverntl(interfaceStephan,5,zoomCenterArmeTime);

	// now we set the new zoom
	fHZoomIndex = hZoomIndex;
	
	zoomCenterPixel.x = [self armeTimeToPixel:zoomCenterArmeTime];
	verntl(interfaceStephan,5,"zoomCenterPixel after zoom change = " << zoomCenterPixel);
		
	NSPoint newVisibleOrigin;
	newVisibleOrigin = zoomCenterPixel;
	
	newVisibleOrigin.x -= (NSWidth(currentVisibleRect)/2);
	newVisibleOrigin.y -= (NSHeight(currentVisibleRect)/2);
		
	[fTopLevelContainerView recreateFrame];

    [self updateObjectRepresentations];

	[fTopLevelContainerView setNeedsDisplay:YES];
	[fRuler setNeedsDisplay:YES];
	
	[fMainScrollView updateZoomSliders];

	[fTopLevelContainerView scrollPoint:newVisibleOrigin];

	[[MIOverviewController sharedOverviewController] refreshCachedImage];
	[[self document] setDocumentSetting:[NSNumber numberWithUnsignedInt:fHZoomIndex] forKey:@"hZoomIndex"];
}

- (void)setVZoom:(UInt32)vZoomIndex
{
	if(fVZoomIndex==vZoomIndex)
		return;
	
	// the point is to change
	// the zoom while keeping
	// the center position
	
	// thus, let's compute the VPos 
	// of the center of the visible rect.
	NSRect	currentVisibleRect = [fTopLevelContainerView visibleRect];
	NSPoint	centerPixel;
	
	centerPixel.x = NSMidX(currentVisibleRect);
	centerPixel.y = NSMidY(currentVisibleRect);
	
	// now let's find the vpos of this point
	MIVPos centerVPos = [self pixelToMIVPos:centerPixel.y];
		
	// now we set the new zoom
	fVZoomIndex = vZoomIndex;
	
	centerPixel.y = [self MIVPosToPixel:centerVPos];
	
	NSPoint newVisibleOrigin;
	newVisibleOrigin = centerPixel;
	
	newVisibleOrigin.x -= (NSWidth(currentVisibleRect)/2);
	newVisibleOrigin.y -= (NSHeight(currentVisibleRect)/2);
		
	[fTopLevelContainerView recreateFrame];
	[fTopLevelContainerView scrollPoint:newVisibleOrigin];

    [self updateObjectRepresentations];
	[fTopLevelContainerView setNeedsDisplay:YES];
	[fMainScrollView updateZoomSliders];
	[[MIOverviewController sharedOverviewController] refreshCachedImage];
	[[self document] setDocumentSetting:[NSNumber numberWithUnsignedInt:fVZoomIndex] forKey:@"vZoomIndex"];
}

- (void)hZoomOut
{
	vertl(interfaceStephan,6,"hZoomOut : "); 
	vverntl(interfaceStephan,6,fHZoomIndex);
	if(fHZoomIndex==0)
	{
		verntl(interfaceStephan,0,"ERROR : hZoomIn is trying to zoom past the highest zoom value\n");
	}
	else
	{
		[self setHZoom:(fHZoomIndex-1)];
	}
}

- (void)hZoomIn
{
	vertl(interfaceStephan,6,"hZoomIn : "); 
	vverntl(interfaceStephan,6,fHZoomIndex);
	if(fHZoomIndex==gNbHZoomIndices-1)
	{
		verntl(interfaceStephan,0,"ERROR : hZoomOut is trying to zoom past the lowest zoom value\n");
	}
	else
	{
		[self setHZoom:(fHZoomIndex+1)];
	}
}

- (void)vZoomIn
{
	vertl(interfaceStephan,6,"vZoomIn : "); 
	vverntl(interfaceStephan,6,fVZoomIndex);
	if(fVZoomIndex==gNbVZoomIndices-1)
	{
		verntl(interfaceStephan,0,"ERROR : vZoomOut is trying to zoom past the lowest zoom value\n");
	}
	else
	{
		[self setVZoom:(fVZoomIndex+1)];
	}
}

- (void)vZoomOut
{
	vertl(interfaceStephan,6,"vZoomOut : "); 
	vverntl(interfaceStephan,6,fVZoomIndex);
	if(fVZoomIndex==0)
	{
		verntl(interfaceStephan,0,"ERROR : vZoomIn is trying to zoom past the lowest zoom value\n");
	}
	else
	{
		[self setVZoom:(fVZoomIndex-1)];
	}
}

- (UInt32)vZoomIndex
{
	return fVZoomIndex;
}

- (UInt32)hZoomIndex
{
	return fHZoomIndex;
}

- (unsigned int)gridFlags
{
	return fGridFlags;
}

- (void)setGridFlags:(unsigned int)gridFlags
{
	// if show grid was changed
	if ( ( fGridFlags ^ gridFlags ) & MIShowGrid )
		[fTopLevelContainerView setNeedsDisplay:YES];

	fGridFlags = gridFlags;
}

- (float)armeTimeToPixel:(ArmeTime)time
{
	SInt32 pnHZoom = gHZoomPNValues[fHZoomIndex];
	if(pnHZoom>0)
		return (float)((double)GET_VAL(time)/(double)pnHZoom);
	else
		return (float)((double)GET_VAL(time)*(double)(-pnHZoom));
}

- (double)doubleTimeToPixel:(double)time
{
	SInt32 pnHZoom = gHZoomPNValues[fHZoomIndex];
	if(pnHZoom>0)
		return (float)(time/(double)pnHZoom);
	else
		return (float)(time*(double)(-pnHZoom));	
}

- (ArmeTime)pixelToArmeTime:(float)pixels
{
	SInt32 pnHZoom = gHZoomPNValues[fHZoomIndex];
	if(pnHZoom>0)
		return _ArmeTime((SInt64)(pixels*(double)pnHZoom));
	else
		return _ArmeTime((SInt64)(pixels/(double)(-pnHZoom)));
}

- (double)pixelToDoubleTime:(float)pixels
{
	SInt32 pnHZoom = gHZoomPNValues[fHZoomIndex];
	if(pnHZoom>0)
		return (double)(pixels*(double)pnHZoom);
	else
		return (double)(pixels/(double)(-pnHZoom));
}

- (float)MIVPosToPixel:(MIVPos)vpos
{
	SInt32 pnVZoom = gVZoomPNValues[fVZoomIndex];
	if(pnVZoom>0)
		return (float)((double)GET_VALUE(vpos)/(double)pnVZoom);
	else
		return (float)((double)GET_VALUE(vpos)*(double)(-pnVZoom));
}

- (MIVPos)pixelToMIVPos:(float)pixels
{
	MIVPos vpos;
	SInt32 pnVZoom = gVZoomPNValues[fVZoomIndex];
	if(pnVZoom>0)
		GET_VALUE(vpos) = SInt32(pixels*(double)pnVZoom);
	else
		GET_VALUE(vpos) = SInt32(pixels/(double)(-pnVZoom));
	return vpos;
}

- (MIPoint)NSPointToMIPoint:(NSPoint)pt
{
	MIPoint mipt;
	mipt.time = [self pixelToArmeTime:pt.x];
	mipt.vpos = [self pixelToMIVPos:pt.y];
	return mipt;
}

- (NSPoint)MIPointToNSPoint:(MIPoint)mipt
{
	NSPoint pt;
	pt.x = [self armeTimeToPixel:mipt.time];
	pt.y = [self MIVPosToPixel:mipt.vpos];
	return pt;
}

- (MISize)NSSizeToMISize:(NSSize)size
{
	MISize misize;
	misize.duration = [self pixelToArmeTime:size.width];
	misize.height = [self pixelToMIVPos:size.height];
	return misize;
}

- (NSSize)MISizeToNSSize:(MISize)misize
{
	NSSize size;
	size.width = [self armeTimeToPixel:misize.duration];
	size.height = [self MIVPosToPixel:misize.height];
	return size;
}

- (MIRect)NSRectToMIRect:(NSRect)rc
{
	MIRect mirc;
	mirc.origin = [self NSPointToMIPoint:rc.origin];
	mirc.size = [self NSSizeToMISize:rc.size];
	return mirc;
}

- (NSRect)MIRectToNSRect:(MIRect)mirc
{
	NSRect rc;
	rc.origin = [self MIPointToNSPoint:mirc.origin];
	rc.size = [self MISizeToNSSize:mirc.size];
	return rc;
}

- (void)updateObjectRepresentations
{
	ZZTIMERS_USED_HERE;
	ZZSTART_TIMER("updateObjectRepresentations");
	NSEnumerator	*objEnum;
    MIObject		*anObject;
    
	[fTopLevelContainerView recreateFrame];
    objEnum = [[fTLC getChildren] objectEnumerator];
    
    while ( anObject = [objEnum nextObject] )
    {
		[anObject recursivelyRecreateFrame];
    }
	ZZEND_TIMER();
}

- (MIObjectRep*)findRepresentationOfObject:(MIObject*)anObject
{
	NSEnumerator	*viewEnum;
	MIObjectRep		*aRep;
	
	viewEnum = [[anObject getRepresentations] objectEnumerator];
	
	while ( aRep = [viewEnum nextObject] )
	{
		if ( [aRep getTopLevelContainerRep] == fTopLevelContainerView )
			return aRep;
	}
	
	return nil;
}

/*- (BOOL)canBecomeMainWindow
{
    return [[self window] canBecomeMainWindow];
}

- (void)windowDidBecomeKey:(NSNotification*)notification
{
    [[MIApplicationController sharedApplicationController] setCurrentMainViewController:self];
}

- (void)windowDidBecomeMain:(NSNotification*)notification
{
    [[MIApplicationController sharedApplicationController] setCurrentMainViewController:self];
}*/

+ (UInt32)getNbHZoomIndices
{
	return gNbHZoomIndices;
}

+ (UInt32)getNbVZoomIndices
{
	return gNbVZoomIndices;
}

+ (UInt32)getDefaultHZoomIndex
{
	return gDefaultHZoomIndex;
}

+ (UInt32)getDefaultVZoomIndex
{
	return gDefaultVZoomIndex;
}

+ (SInt32)getHZoomPNValueFromIndex:(UInt32)hZoomIndex
{
	assert(hZoomIndex >= 0 && hZoomIndex < gNbHZoomIndices);
	return gHZoomPNValues[hZoomIndex];
}

+ (SInt32)getVZoomPNValueFromIndex:(UInt32)vZoomIndex
{
	assert(vZoomIndex >= 0 && vZoomIndex < gNbVZoomIndices);
	return gVZoomPNValues[vZoomIndex];
}

- (SInt32)getCurrentHZoomPNValue
{
	assert(fHZoomIndex >= 0 && fHZoomIndex < gNbHZoomIndices);
	return gHZoomPNValues[fHZoomIndex];
}

- (SInt32)getCurrentVZoomPNValue;
{
	assert(fVZoomIndex >= 0 && fVZoomIndex < gNbVZoomIndices);
	return gVZoomPNValues[fVZoomIndex];
}

+ (double)getFramesPerPixelFromHZoomIndex:(UInt32)hZoomIndex
{
	SInt32 pnHZoom = gHZoomPNValues[hZoomIndex];
	if(pnHZoom>0)
		return (double)pnHZoom;
	else
		return -1.0/(double)pnHZoom;
}

+ (double)getVPosPerPixelFromVZoomIndex:(SInt32)vZoomIndex
{
	SInt32 pnVZoom = gVZoomPNValues[vZoomIndex];
	if(pnVZoom>0)
		return (double)pnVZoom;
	else
		return -1.0/(double)pnVZoom;
}

- (double)getCurrentFramesPerPixel
{
	SInt32 pnHZoom = gHZoomPNValues[fHZoomIndex];
	if(pnHZoom>0)
		return (double)pnHZoom;
	else
		return -1.0/(double)pnHZoom;
}

- (double)getCurrentVPosPerPixel
{
	SInt32 pnVZoom = gVZoomPNValues[fVZoomIndex];
	if(pnVZoom>0)
		return (double)pnVZoom;
	else
		return -1.0/(double)pnVZoom;
}

- (NSEnumerator*)selectionObjectEnumerator
{
	return [fSelection objectEnumerator];
}

- (void)setSelectionEndxTime:(ArmeTime)endxTime
{
	[fSelection setEndxTime:endxTime];
	NSEnumerator* enumerator = [self selectionObjectEnumerator];
	MIObjectRep* rep;
	while(rep = [enumerator nextObject])
	{
		[rep setNeedsDisplay];
	}
}

- (void)setSelectionStartTime:(ArmeTime)startTime
{
	[fSelection setStartTime:startTime];
	NSEnumerator* enumerator = [self selectionObjectEnumerator];
	MIObjectRep* rep;
	while(rep = [enumerator nextObject])
	{
		[rep setNeedsDisplay];
	}
}

- (void)selectionSetTimeSliceType
{
	[fSelection setTimeSliceType];
}

- (void)selectionSetObjectsType
{
	[fSelection setObjectsType];
}

/*
	This macro needs to be used when the action that
	needs to be performed is implemented thru a MICommand
	subclass
*/

#define EXECUTE_COMMAND_FROM_STRING(a,b)\
if([commandName isEqualToString:@#a])\
{\
	MICommand* cmd = [[b alloc] initWithSelection:[self selection]];\
	if([cmd displaySetupDialog]) [[self document] doCmd:cmd];\
	return;\
}

//right now, we have some problems with menus so we double check the command before executing it
//if needed, we might define this macro to nothing
#define CHECK_SUPPORTS_SELECTION(a)\
if (![a supportsSelection:[self selection]])\
return;


- (void)executeCommand:(NSString*)commandName
{
	//EXECUTE_COMMAND_FROM_STRING(cut,						MICutCommand);
	if([commandName isEqualToString:@"cut"])
	{
		CHECK_SUPPORTS_SELECTION(MICutCommand);
		MICommand* cmd = [[[MICutCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}
	//EXECUTE_COMMAND_FROM_STRING(copy,						MICopyCommand);
	if([commandName isEqualToString:@"copy"])
	{
		CHECK_SUPPORTS_SELECTION(MICopyCommand);
		MICommand* cmd = [[[MICopyCommand alloc] initWithSelection:[self selection] usingClipboard:nil] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}
	//EXECUTE_COMMAND_FROM_STRING(paste,						MIPasteCommand);
	if([commandName isEqualToString:@"paste"])
	{
		CHECK_SUPPORTS_SELECTION(MIPasteCommand);
		MICommand* cmd = [[[MIPasteCommand alloc] initWithSelection:[self selection] inDoc:[self document]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}
	//EXECUTE_COMMAND_FROM_STRING(del,						MIDeleteCommand);
	if([commandName isEqualToString:@"del"])
	{
		CHECK_SUPPORTS_SELECTION(MIDeleteCommand);
		MICommand* cmd = [[[MIDeleteCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}

	//EXECUTE_COMMAND_FROM_STRING(rename,						MIRenameCommand);
	if([commandName isEqualToString:@"rename"])
	{
		CHECK_SUPPORTS_SELECTION(MIRenameCommand);
		MIRenameCommand* cmd = [[[MIRenameCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD2("Rename %s in %s", [[cmd oldName] cString], [[cmd newBaseName] cString] );
			[[self document] doCmd:cmd];
		}
		return;
	}


	//EXECUTE_COMMAND_FROM_STRING(reverse,					MIReverseCommand);
	if([commandName isEqualToString:@"reverse"])
	{
		CHECK_SUPPORTS_SELECTION(MIReverseCommand);
		MICommand* cmd = [[[MIReverseCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}
	//EXECUTE_COMMAND_FROM_STRING(silence,					MISilenceCommand);
	if([commandName isEqualToString:@"silence"])
	{
		CHECK_SUPPORTS_SELECTION(MISilenceCommand);
		MICommand* cmd = [[[MISilenceCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}
	//EXECUTE_COMMAND_FROM_STRING(insertSilence,				MIInsertSilenceCommand);
	if([commandName isEqualToString:@"insertSilence"])
	{
		CHECK_SUPPORTS_SELECTION(MIInsertSilenceCommand);
		MICommand* cmd = [[[MIInsertSilenceCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}
	//EXECUTE_COMMAND_FROM_STRING(normalize,					MINormalizeCommand);
	if([commandName isEqualToString:@"normalize"])
	{
		CHECK_SUPPORTS_SELECTION(MINormalizeCommand);
		MICommand* cmd = [[[MINormalizeCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}
	//EXECUTE_COMMAND_FROM_STRING(deleteContainer,					MIDeleteContainerCommand);
	if([commandName isEqualToString:@"deleteContainer"])
	{
		CHECK_SUPPORTS_SELECTION(MIDeleteContainerCommand);
		MICommand* cmd = [[[MIDeleteContainerCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}
	//EXECUTE_COMMAND_FROM_STRING(gain,						MIGainCommand);
	if([commandName isEqualToString:@"gain"])
	{
		CHECK_SUPPORTS_SELECTION(MIGainCommand);
		MICommand* cmd = [[[MIGainCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}
	//EXECUTE_COMMAND_FROM_STRING(changeVirtualAudioOutput,	MIChangeVAOCommand);
	if([commandName isEqualToString:@"changeVirtualAudioOutput"])
	{
		CHECK_SUPPORTS_SELECTION(MIChangeVAOCommand);
		MICommand* cmd = [[[MIChangeVAOCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}
	//EXECUTE_COMMAND_FROM_STRING(shrinkToFit,				MIShrinkToFitCommand);
	if([commandName isEqualToString:@"shrinkToFit"])
	{
		CHECK_SUPPORTS_SELECTION(MIShrinkToFitCommand);
		MICommand* cmd = [[[MIShrinkToFitCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}
	//EXECUTE_COMMAND_FROM_STRING(collapse,					MICollapseCommand);
	if([commandName isEqualToString:@"collapse"])
	{
		CHECK_SUPPORTS_SELECTION(MICollapseCommand);
		MICommand* cmd = [[[MICollapseCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}
	//EXECUTE_COMMAND_FROM_STRING(expand,						MIExpandCommand);
	if([commandName isEqualToString:@"expand"])
	{
		CHECK_SUPPORTS_SELECTION(MIExpandCommand);
		MICommand* cmd = [[[MIExpandCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}
	//EXECUTE_COMMAND_FROM_STRING(dirtyResampler,				MIDirtyResamplerCommand);
	if([commandName isEqualToString:@"dirtyResampler"])
	{
		CHECK_SUPPORTS_SELECTION(MIDirtyResamplerCommand);
        vertl(commandsBenjamin,0,"WARNING: The dirtyResampler command is depreciated. Use resample or timeStretch instead.\n");
		MICommand* cmd = [[[MIDirtyResamplerCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}
    
	if([commandName isEqualToString:@"resample"])
	{
		CHECK_SUPPORTS_SELECTION(MIResampleCommand);
		MICommand* cmd = [[[MIResampleCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}
    
	if([commandName isEqualToString:@"timeStretch"])
	{
		CHECK_SUPPORTS_SELECTION(MITimeStretchCommand);
		MICommand* cmd = [[[MITimeStretchCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}

	if([commandName isEqualToString:@"trim"])
	{
		CHECK_SUPPORTS_SELECTION(MITrimCommand);
		MICommand* cmd = [[[MITrimCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}
    
	//EXECUTE_COMMAND_FROM_STRING(mute,						MIMuteCommand);
	if([commandName isEqualToString:@"mute"])
	{
		CHECK_SUPPORTS_SELECTION(MIMuteCommand);
		MICommand* cmd = [[[MIMuteCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}
	
	//EXECUTE_COMMAND_FROM_STRING(unmute,						MIUnMuteCommand);
	if([commandName isEqualToString:@"unmute"])
	{
		CHECK_SUPPORTS_SELECTION(MIUnMuteCommand);
		MICommand* cmd = [[[MIUnMuteCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}
	
	//EXECUTE_COMMAND_FROM_STRING(merge,						MIMergeCommand);
	if([commandName isEqualToString:@"merge"])
	{
		CHECK_SUPPORTS_SELECTION(MIMergeCommand);
		MICommand* cmd = [[[MIMergeCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}
    if([commandName isEqualToString:@"advancedFadeIn"])
	{
		CHECK_SUPPORTS_SELECTION(MIAdvancedFadeInCommand);
		MICommand* cmd = [[[MIAdvancedFadeInCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}

    if([commandName isEqualToString:@"advancedFadeOut"])
	{
		CHECK_SUPPORTS_SELECTION(MIAdvancedFadeOutCommand);
		MICommand* cmd = [[[MIAdvancedFadeOutCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}
    if([commandName isEqualToString:@"fadeIn"])
	{
		CHECK_SUPPORTS_SELECTION(MIFadeInCommand);
		MICommand* cmd = [[[MIFadeInCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}

    if([commandName isEqualToString:@"fadeOut"])
	{
		CHECK_SUPPORTS_SELECTION(MIFadeOutCommand);
		MICommand* cmd = [[[MIFadeOutCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}
    
///
    if([commandName isEqualToString:@"swapChannels"])
	{
		CHECK_SUPPORTS_SELECTION(MISwapChannelsCommand);
		MICommand* cmd = [[[MISwapChannelsCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}
    if([commandName isEqualToString:@"adjustDCOffset"])
	{
		CHECK_SUPPORTS_SELECTION(MIDCAdjustCommand);
		MICommand* cmd = [[[MIDCAdjustCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}
    if([commandName isEqualToString:@"invertPhase"])
	{
		CHECK_SUPPORTS_SELECTION(MIInvertPhaseCommand);
		MICommand* cmd = [[[MIInvertPhaseCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}
    
	if([commandName isEqualToString:@"all on"])
	{
		CHECK_SUPPORTS_SELECTION(MIAllOnCommand);
		MICommand* cmd = [[[MIAllOnCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}

	//EXECUTE_COMMAND_FROM_STRING(solo,						MISoloCommand);
	if([commandName isEqualToString:@"solo"])
	{
		CHECK_SUPPORTS_SELECTION(MISoloCommand);
		MICommand* cmd = [[[MISoloCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}

	//EXECUTE_COMMAND_FROM_STRING(split,						MISplitCommand);
	if([commandName isEqualToString:@"split"])
	{
		CHECK_SUPPORTS_SELECTION(MISplitCommand);
		MISplitCommand* cmd = [[[MISplitCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD1("Split at %d", (int)([cmd splitTime].data));
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}

	//EXECUTE_COMMAND_FROM_STRING(pictFromFrame,						MICreatePictFromFrameCommand);
	if([commandName isEqualToString:@"pictFromFrame"])
	{
		CHECK_SUPPORTS_SELECTION(MICreatePictFromFrameCommand);
		MICreatePictFromFrameCommand* cmd = [[[MICreatePictFromFrameCommand alloc] initWithSelection:[self selection] inDoc:[self document]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD1("Create Still Pict From Frame at %d", (int)([cmd pictTime].data));
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];

			if ( [[MIPreferences sharedPrefs] gridShowMask] & kPrefsGridShowVObjLines ||
				[[MIPreferences sharedPrefs] gridShowMask] & kPrefsGridShowHObjLines )
				[[MIApplicationController sharedApplicationController] redrawAllMainWindows];
		
		}
		return;
	}
	
	//EXECUTE_COMMAND_FROM_STRING(freezeSelection,			MIFreezeCommand);
	if([commandName isEqualToString:@"freezeSelection"])
	{
		CHECK_SUPPORTS_SELECTION(MIFreezeCommand);
		MICommand* cmd = [[[MIFreezeCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
	}

	if([commandName isEqualToString:@"djSwitch"])
	{
		CHECK_SUPPORTS_SELECTION(MIDJSwitchCommand);
		MICommand* cmd = [[[MIDJSwitchCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}
    

    if([commandName isEqualToString:@"loopsmooth"])
	{
		CHECK_SUPPORTS_SELECTION(MILoopsmoothCommand);
		MICommand* cmd = [[[MILoopsmoothCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}
	
    if([commandName isEqualToString:@"duplicateMany"])
	{
		CHECK_SUPPORTS_SELECTION(MIDuplicateManyCommand);
		MIDuplicateManyCommand* cmd = [[[MIDuplicateManyCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD2("Duplicate Many %d times (keep inside container = %d)", [cmd getNumberOfDuplications], [cmd isKeepInsideContainer]);
			VUSERCMD4("Chained = %d, horizontal inc = %d, stacked = %d, vertical inc = %d", [cmd isChainedHorizontaly], (int)([cmd getHorizontalTimeInc].data), [cmd isStackedVerticaly], [cmd getVerticalPixelsInc]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}

    if([commandName isEqualToString:@"crop"])
	{
		CHECK_SUPPORTS_SELECTION(MICropCommand);
		MICommand* cmd = [[[MICropCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}
    
    if([commandName isEqualToString:@"duplicate"])
	{
		CHECK_SUPPORTS_SELECTION(MIDuplicateCommand);
		MICommand* cmd = [[[MIDuplicateCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}

    if([commandName isEqualToString:@"createClipFromSelection"])
	{
		CHECK_SUPPORTS_SELECTION(MICreateClipFromSelectionCommand);
		MICommand* cmd = [[[MICreateClipFromSelectionCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];

			if ( [[MIPreferences sharedPrefs] gridShowMask] & kPrefsGridShowVObjLines ||
				[[MIPreferences sharedPrefs] gridShowMask] & kPrefsGridShowHObjLines )
				[[MIApplicationController sharedApplicationController] redrawAllMainWindows];
		
		}
		return;
	}

    if([commandName isEqualToString:@"lock"])
	{
		CHECK_SUPPORTS_SELECTION(MILockToTimelineCommand);
		MICommand* cmd = [[[MILockToTimelineCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}

    if([commandName isEqualToString:@"unlock"])
	{
		CHECK_SUPPORTS_SELECTION(MIUnlockToTimelineCommand);
		MICommand* cmd = [[[MIUnlockToTimelineCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}

    if([commandName isEqualToString:@"createTextClip"])
	{
		CHECK_SUPPORTS_SELECTION(MICreateTextClipCommand);
		MICommand* cmd = [[[MICreateTextClipCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}

    if([commandName isEqualToString:@"createVideoProc"])
	{
		CHECK_SUPPORTS_SELECTION(MICreateVideoProcessorCommand);
		MIWSSelection *sel = [self selection];
		MICreateVideoProcessorCommand* cmd = [[[MICreateVideoProcessorCommand alloc] initWithDocument:[self document] selection:sel] autorelease];
		if([cmd displaySetupDialog]) 
		{
			if ( [sel count] == 0 )
				[cmd setPosition:[[self topLevelContainerView] newObjectLocation]];

			[[self document] doCmd:cmd];
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);

			if ( [[MIPreferences sharedPrefs] gridShowMask] & kPrefsGridShowVObjLines ||
				[[MIPreferences sharedPrefs] gridShowMask] & kPrefsGridShowHObjLines )
				[[MIApplicationController sharedApplicationController] redrawAllMainWindows];
		
		}
		if ( [sel count] == 0 ) [[self topLevelContainerView] scrollToNewObject];
		return;
	}

	if([commandName isEqualToString:@"configureTransition"])
	{
		CHECK_SUPPORTS_SELECTION(MIConfigureTransitionCommand);
		MICommand* cmd = [[[MIConfigureTransitionCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}

	if([commandName isEqualToString:@"configureVideoEffect"])
	{
		CHECK_SUPPORTS_SELECTION(MIConfigureVideoEffectCommand);
		MICommand* cmd = [[[MIConfigureVideoEffectCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}

	if([commandName isEqualToString:@"editTextClip"])
	{
		CHECK_SUPPORTS_SELECTION(MIEditTextCommand);
		MICommand* cmd = [[[MIEditTextCommand alloc] initWithSelection:[self selection]] autorelease];
		if([cmd displaySetupDialog]) 
		{
			VUSERCMD([[cmd commandName] cString]);
			VUSERCMD_PRINT_SELECTION([self selection]);
			[[self document] doCmd:cmd];
		}
		return;
	}

	verntl(interfaceBenjamin,0,"Warning ! command " << commandName << " is not recognized");
}

/*
#define TEST_COMMAND_FROM_STRING_AGAINST_SELECTION(a,b)\
if([action isEqualToString:@#a])\
{\
	return [b supportsSelection:fSelection]; \
}
*/

- (BOOL)canMenuItemActionBePerformedOnCurrentSelection:(NSMenuItem*)menuItem
{
	NSString *action = [menuItem title] ; // what about localization (or just changing the title of the menu in IB) ?
	SEL selector = [menuItem action] ;


	if ( selector == @selector(allOn:) ) {
		return [MIAllOnCommand supportsSelection:[self selection]];
	}

	if ( selector == @selector(crop:) ) {
		return [MICropCommand supportsSelection:[self selection]];
	}
	
	if ( selector == @selector(trim:) ) {
		return [MITrimCommand supportsSelection:[self selection]];
	}


	if ( selector == @selector(createVideoEffect:) ) {	
		return ([MIConfigureVideoEffectCommand supportsSelection:[self selection]] || [MICreateVideoProcessorCommand supportsSelection:[self selection]]);
	}

	if ( [action isEqualToString:@"Video Transitions..."])
	{
		return [MIConfigureTransitionCommand supportsSelection:[self selection]];
	}


	if ( selector == @selector(cut:) ) {
		return [MICutCommand supportsSelection:[self selection]];
	}

	if ( selector == @selector(copy:) ) {
		return [MICopyCommand supportsSelection:[self selection]];
	}

	if ( selector == @selector(paste:) ) {
		return [MIPasteCommand supportsSelection:[self selection]];
	}

	if ( [action isEqualToString:@"Rename"])
	{
		return [MIRenameCommand supportsSelection:[self selection]];
	}

	if ( selector == @selector(delete:) ) {	
		return [MIDeleteCommand supportsSelection:[self selection]];
	}

	if ( selector == @selector(reverse:) ) {
		return [MIReverseCommand supportsSelection:[self selection]];
	}

	if ( [action isEqualToString:@"Delete Container"])
	{
		return [MIDeleteContainerCommand supportsSelection:[self selection]];
	}

	if ( selector == @selector(normalize:) ) {
		return [MINormalizeCommand supportsSelection:[self selection]];
	}

	if ( selector == @selector(changeGain:) ) {
		return [MIGainCommand supportsSelection:[self selection]];
	}

	if ( selector == @selector(advancedFadeIn:) ) {
		return [MIAdvancedFadeInCommand supportsSelection:[self selection]];
	}
	
	if ( selector == @selector(advancedFadeOut:) ) {
		return [MIAdvancedFadeOutCommand supportsSelection:[self selection]];
	}
	

	if ( [action isEqualToString:@"Audio Outputs"])
	{
		return [MIChangeVAOCommand supportsSelection:[self selection]];
	}

	if ( selector == @selector(shrinkToFit:) ) {
		return [MIShrinkToFitCommand supportsSelection:[self selection]];
	}

	if ( [action isEqualToString:@"Collapse"])
	{
		return [MICollapseCommand supportsSelection:[self selection]];
	}

	if ( [action isEqualToString:@"Expand"])
	{
		return [MIExpandCommand supportsSelection:[self selection]];
	}

	if ( [action isEqualToString:@"dirtyResampler"])
	{
        vertl(commandsBenjamin,0,"WARNING: The dirtyResampler command is depreciated. Use resample or timeStretch instead.\n");
		return [MIDirtyResamplerCommand supportsSelection:[self selection]];
	}

	if ( selector == @selector(resample:) ) {
		return [MIResampleCommand supportsSelection:[self selection]];
	}

	if ( [action isEqualToString:@"Time Stretch..."])
	{
		return [MITimeStretchCommand supportsSelection:[self selection]];
	}

	if ( ( [action isEqualToString:@"Mute"]) || ( [action isEqualToString:@"Un-Mute"]) )
	{
		if ( [MIMuteCommand supportsSelection:[self selection]] ) {
			[menuItem setTitle:@"Mute"];
			return YES;
		} else if ( [MIUnMuteCommand supportsSelection:[self selection]] ) {
			[menuItem setTitle:@"Un-Mute"];
			return YES;
		} else {
			[menuItem setTitle:@"Mute"];
			return NO;
		}
		return NO;
	}

	if ( [action isEqualToString:@"Merge"])
	{
		return [MIMergeCommand supportsSelection:[self selection]];
	}

	if ( selector == @selector(fadeIn:) ) {
		return [MIFadeInCommand supportsSelection:[self selection]];
	}

    if ( selector == @selector(fadeOut:) ) {
		return [MIFadeOutCommand supportsSelection:[self selection]];
	}

	if ( selector == @selector(swapChannels:) ) {
		return [MISwapChannelsCommand supportsSelection:[self selection]];
	}

	if ( selector == @selector(adjustDCOffset:) ) {
		return [MIDCAdjustCommand supportsSelection:[self selection]];
	}

	if ( selector == @selector(invertPhase:) ) {
		return [MIInvertPhaseCommand supportsSelection:[self selection]];
	}

	if ( ( [action isEqualToString:@"Solo"]) || ( [action isEqualToString:@"Un-Solo"]) )
	{
		if ( [MISoloCommand supportsSelection:[self selection]] ) {
			id objectToSolo = [[[self selection] objectAtIndex:0] representedObject];
			if ( [objectToSolo WSObject]->IsTheVideoSolo() || [objectToSolo WSObject]->IsTheAudioSolo()) {
				[menuItem setTitle:@"Un-Solo"];
				return YES;
			} else {
				[menuItem setTitle:@"Solo"];
				return YES;
			}
		} else {
			[menuItem setTitle:@"Solo"];
			return NO;
		}
	}

	if ( selector == @selector(renderClip:) ) {
		if ( [MIFreezeCommand supportsSelection:[self selection]] ) 
		{
			if ( [MIFreezeCommand isRenderCommand:[self selection]] ) 
			{
				[menuItem setTitle:@"Render Clip"];
				return YES;
			}
			else
			{
				[menuItem setTitle:@"Un-Render Clip"];
				return YES;
			}
		} else {
			[menuItem setTitle:@"Render Clip"];
			return NO;
		}
	}

	if ( [action isEqualToString:@"Split"])
	{
		return [MISplitCommand supportsSelection:[self selection]];
	}

	if ( ( selector == @selector(createVideoClip:) ) || ( selector == @selector(pictFromMovieView:) ) ) {
		if ( [MICreateClipFromSelectionCommand supportsSelection:[self selection]] ) {
			[menuItem setTitle:@"Create Clip from Selection"];
			[menuItem setAction:@selector(createVideoClip:)];
			return YES;
		} else if ( [MICreatePictFromFrameCommand supportsSelection:[self selection]] ) {
			[menuItem setTitle:@"Create Still Clip from Frame"];
			[menuItem setAction:@selector(pictFromMovieView:)];
			return YES;
		} else {
			return NO;
		}
	}

	if ( ( selector == @selector(insertSilence:) ) || ( selector == @selector(silence:) ) ) {
		if ( [MIInsertSilenceCommand supportsSelection:[self selection]] ) {
			[menuItem setTitle:@"Insert SilenceÉ"];
			[menuItem setAction:@selector(insertSilence:)];
			return YES;
		} else if ( [MISilenceCommand supportsSelection:[self selection]] ) {
			[menuItem setTitle:@"Change to Silence"];
			[menuItem setAction:@selector(silence:)];
			return YES;
		}
		return NO;
	}

	
		
	if ( [action isEqualToString:@"Freeze Selection"])
	{
		return [MIFreezeCommand supportsSelection:[self selection]];
	}

	if ( [action isEqualToString:@"djSwitch"])
	{
		return [MIDJSwitchCommand supportsSelection:[self selection]];
	}

	if ( selector == @selector(loopsmooth:) ) {
		return [MILoopsmoothCommand supportsSelection:[self selection]];
	}

    if ( [action isEqualToString:@"Duplicate Many..."])
	{
		return [MIDuplicateManyCommand supportsSelection:[self selection]];
	}

    if ( [action isEqualToString:@"Duplicate"])
	{
		return [MIDuplicateCommand supportsSelection:[self selection]];
	}

	if ( selector == @selector(lock:) ) {
		return [MILockToTimelineCommand supportsSelection:[self selection]];
	}

    if( [action isEqualToString:@"Unlock"])
	{
		return [MIUnlockToTimelineCommand supportsSelection:[self selection]];
	}

	//	NSLog( action );
	return YES;
	/*
	 TEST_COMMAND_FROM_STRING_AGAINST_SELECTION(cut,MICutCommand);
	 TEST_COMMAND_FROM_STRING_AGAINST_SELECTION(copy,MICutCommand);
	 TEST_COMMAND_FROM_STRING_AGAINST_SELECTION(paste,MICutCommand);
	 TEST_COMMAND_FROM_STRING_AGAINST_SELECTION(reverse,MICutCommand);
	 */
}

- (MIDockBar*)mainDockBar
{
	return nil;
}

- (IBAction)import:(id)sender
{
    NSOpenPanel *aPanel = [NSOpenPanel openPanel];

    [aPanel setTitle:@"Select media files to import"]; // window title
    [aPanel setPrompt:@"Import"]; // this gives the name of the default ("OK") button

    [aPanel setAllowsMultipleSelection:YES];

	NSMutableArray *types = [NSMutableArray arrayWithObject:@"montage"];
	[types addObject:@"HAV"];
	[types addObjectsFromArray:[[MIApplicationController sharedApplicationController] fileTypesAndExtensions]];
		
    [aPanel beginSheetForDirectory:nil file:nil types:types modalForWindow:[self window] modalDelegate:self didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) contextInfo:nil];
}

- (void)importFiles:(NSArray*)files contextDictionary:(NSMutableDictionary*)dict
{
	MICreateWSObjsFromFilesCommand *createClipsCommand;
	createClipsCommand = [[[MICreateWSObjsFromFilesCommand alloc] initWithFiles:files controller:self] autorelease];
	[createClipsCommand setFirstPosition:[fTopLevelContainerView newObjectLocation]];
	[createClipsCommand setParent:[fTopLevelContainerView representedObject]];
	[[self document] doCmd:createClipsCommand]; // the doIt will execute the split task

	if ( [[MIPreferences sharedPrefs] gridShowMask] & kPrefsGridShowVObjLines ||
		 [[MIPreferences sharedPrefs] gridShowMask] & kPrefsGridShowHObjLines )
		[[MIApplicationController sharedApplicationController] redrawAllMainWindows];

	[fTopLevelContainerView scrollToNewObject];
}

- (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void  *)contextInfo
{
    [sheet orderOut:nil];
    if ( returnCode == NSOKButton ) {
		
		if ( ![self unwantedFiles:[sheet filenames]] ) {
			[self importFilesUsingImportPanelIfNeeded:[sheet filenames] importSelector:@selector(importFiles:contextDictionary:) importTarget:self contextDictionary:nil];
		}
	}
}

- (void)importFilesUsingImportPanelIfNeeded:(NSArray*)files importSelector:(SEL)selector importTarget:(id)target contextDictionary:(NSMutableDictionary*)contextDict {
	   NSMutableArray *projectFiles = [NSMutableArray array];
	   NSEnumerator *enumerator = [files objectEnumerator];
	   NSMutableArray *mediaFiles = [NSMutableArray arrayWithArray:files];
	   NSMutableDictionary *dict = contextDict;
	   NSString *path;
	   
	   if ( dict == nil ) dict = [NSMutableDictionary dictionary];

	   while (( path = [enumerator nextObject] )) {
		   if (( [[path pathExtension] isEqualToString:@"montage"] ) || ( [[path pathExtension] isEqualToString:@"HAV"] )) {
			   [projectFiles addObject:path];
			   [mediaFiles removeObject:path];
		   }
	   }

	   [dict setObject:mediaFiles forKey:@"files"];
	   
	   if ( [projectFiles count] > 0 ) {
		   [dict setObject:target forKey:@"target"];
		   [dict setObject:[NSValue valueWithBytes:&selector objCType:@encode(SEL)] forKey:@"selector"];
		   
		   MIImportPanelController* importPanel = [MIImportPanelController sharedImportPanelController];

		   [importPanel setDelegate:self];
		   [importPanel setAllowsMultipleSelection:YES];

		   [importPanel beginSheetForDocuments:projectFiles modalForWindow:[self window] modalDelegate:self didEndSelector:@selector(importPanelDidEnd:returnCode:contextInfo:) contextInfo:[dict retain]];
		   
	   } else [target performSelector:selector withObject:mediaFiles withObject:dict];
   }

- (BOOL)importPanel:(id)sender shouldShowFilename:(NSString *)path {
	NSString *filename = [path lastPathComponent];
	NSLog(filename);
	if ( [filename isEqualToString:MTGArchiveName] ) return NO;
	if ( [filename isEqualToString:MTGArchiveBackupName] ) return NO;
	if ( [filename isEqualToString:MTGArchiveCorruptedName] ) return NO;
	if ( [filename isEqualToString:MTGMasterName] ) return NO;
	if ( [filename isEqualToString:MTGMasterBackupName] ) return NO;
	if ( [filename isEqualToString:MTGMasterCorruptedName] ) return NO;
	if ( [filename isEqualToString:MTGWorkingMasterName] ) return NO;
	if ( [filename isEqualToString:MTGArchiveCorruptedName] ) return NO;
	if ( [filename isEqualToString:MTGMasterCorruptedName] ) return NO;
	if ( [filename isEqualToString:MTGDocumentSettingsName] ) return NO;
	if ( [filename isEqualToString:@"background.mov"] ) return NO;
	
	if ( [[filename pathExtension] isEqualToString:@"mtga"] ) return NO;
	if ( [[filename pathExtension] isEqualToString:@"mov"] ) {
		NSFileHandle *file = [NSFileHandle fileHandleForReadingAtPath:path];
		NSData *data = [file readDataOfLength:6];
		NSString *string = [[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding] autorelease];
		if ( [string isEqualToString:@"UNUSED"] ) return NO;
	}
	return YES;
}

- (void)importPanelDidEnd:(MIImportPanelController*)importPanel returnCode:(int)returnCode contextInfo:(void  *)contextInfo {
    [importPanel orderOut:nil];
	[[NSApp mainWindow] makeKeyAndOrderFront:nil];
    if ( returnCode == NSOKButton ) {
		NSMutableDictionary* dict = (NSMutableDictionary*)contextInfo;
		SEL selector;
		[[dict objectForKey:@"files"] addObjectsFromArray:[importPanel fileNames]];
		[[dict objectForKey:@"selector"] getValue:&selector];
		[[dict objectForKey:@"target"] performSelector:selector withObject:[dict objectForKey:@"files"] withObject:[dict autorelease]];
    }
}

- (BOOL)unwantedFiles:(NSArray*)files {
	NSFileManager *fileManager = [NSFileManager defaultManager];
	NSEnumerator *enumerator = [files objectEnumerator];
	NSString *path;
	NSString *fileList = nil;
	BOOL unwanted = NO;
	BOOL moreThanOne = NO;	

	while (( path = [enumerator nextObject] )) {

		if ( [[path stringByAppendingString:@"/"] isEqualToString:[[self document] fileName]] ) {
			NSString *title = [NSString stringWithFormat:@"Unable to open file \"%@\".", [[self document] displayName]];
			NSRunAlertPanel( title, @"The document is already open.", @"OK", nil, nil);
			return YES;
		}
		
		NSString *ext = [[path lowercaseString] pathExtension];
		OSType hfsType = [[fileManager fileAttributesAtPath:path traverseLink:NO] fileHFSTypeCode];
		if ( ( [ext isEqualToString:@"mov"] ) || ( [ext isEqualToString:@"mpg"] ) || ( [ext isEqualToString:@"mpeg"] )
	   || ( hfsType == 'moov') || ( hfsType == 'mpeg') || ( hfsType == 'mpg ') ) {
			if ( 0 == CountClippableTracksInFile([path fileSystemRepresentation]) ) {
				unwanted = YES;
				if ( fileList ) {
					fileList = [fileList stringByAppendingFormat:@", \"%@\"", [path lastPathComponent]];
					moreThanOne = YES;
				}
				else fileList = [NSString stringWithFormat:@"\"%@\"", [path lastPathComponent]];
			}
		}
	}
	if ( unwanted ) {
		NSString* title;
		if ( moreThanOne ) title = [NSString stringWithFormat:@"Unable to open files %@.", fileList];
		else title = [NSString stringWithFormat:@"Unable to open file %@.", fileList];
		NSRunAlertPanel( title, @"Unsupported file format.", @"OK", nil, nil);
		//NSRunAlertPanel( title, @"MPEG files with one track for sound and video cannot be edited.", @"OK", nil, nil);
	}
	return unwanted;
}


-(MISnapper*)snapper
{
	return fSnapper;
}

- (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)proposedFrameSize
{
	NSRect fr = [sender frame];
	NSRect vRect = [fTopLevelContainerView visibleRect];
	
	NSPoint p = vRect.origin;
	
	p.y += ([sender frame].size.height - proposedFrameSize.height);
	[fTopLevelContainerView scrollPoint:p];
	
	return proposedFrameSize;
}

- (void)windowDidResize:(NSNotification *)aNotification
{
	[[MIOverviewController sharedOverviewController] setViewNeedsDisplay];
	[[self document] setDocumentSetting:NSStringFromRect( [[self window] frame] ) forKey:@"windowFrame"];
	
	if ( NSWidth([[[fTopLevelContainerView enclosingScrollView] contentView] bounds]) > NSWidth([fTopLevelContainerView frame]) ||
		 NSHeight([[[fTopLevelContainerView enclosingScrollView] contentView] bounds]) > NSHeight([fTopLevelContainerView frame]) )
	{
		[fTopLevelContainerView setFrame:NSUnionRect([[[fTopLevelContainerView enclosingScrollView] contentView] bounds], [fTopLevelContainerView frame])];
	}
}

- (void)windowDidMove:(NSNotification *)aNotification
{
	[[self document] setDocumentSetting:NSStringFromRect( [[self window] frame] ) forKey:@"windowFrame"];
}


- (void)setLocatorsFromSelection
{
		
	ArmeTime leftLoc = ARME_TIME_MAX;
	ArmeTime rightLoc = ARME_TIME_MIN;

	if([fSelection count] == 0)
	{
		TArmeWSObj* tlc = [[self document] armeDocument]->GetTopContainer();
		
		SInt32 count = tlc->GetChildrenCount();
		
		if(count == 0)
		{
			leftLoc = _ArmeTime(0);
			rightLoc = tlc->GetDuration();
		}
		else
		{		
			for(SInt32 i = 0; i < count; i++)
			{
				ArmeTime childStart = tlc->GetChild(i)->GetAbsoluteStartTime();
				ArmeTime childEndx = tlc->GetChild(i)->GetAbsoluteEndxTime();
				if(childStart < leftLoc)
					leftLoc = childStart;
				if(childEndx > rightLoc)
					rightLoc = childEndx;
			}
		}
	}
	else
	{
		if([fSelection type] == kMIWSSelectionTypeTimeSlice)
		{
		leftLoc = [fSelection startTime];
		rightLoc = [fSelection endxTime];
		}
		else if([fSelection type] == kMIWSSelectionTypeObjects)
		{
			MIObjectRep* rep;
			MIObject* obj;
			TArmeWSObj* wsobj;
			for(UInt32 i = 0; i < [fSelection count]; i++)
			{
				// WARNING maybe it's an infinite object
				rep = [fSelection objectAtIndex:i];
				obj = [rep representedObject];
				wsobj = [obj WSObject];
				if(wsobj->GetAbsoluteStartTime() < leftLoc)
					leftLoc = wsobj->GetAbsoluteStartTime();
				if(wsobj->GetAbsoluteEndxTime() > rightLoc)
					rightLoc = wsobj->GetAbsoluteEndxTime();
			}
		}
		else
		{
			ZzAssert(0);
		}
	}
	
	[fTLC WSObject]->GetDoc()->SetLLocator(leftLoc);
	[fTLC WSObject]->GetDoc()->SetRLocator(rightLoc);
	[[self document] updateDocumentChangeCount:MIChangeDone];
	
	[self updateLocators];
	[fRuler setNeedsDisplay:YES];
	[[[MIApplicationController sharedApplicationController] timePaletteController] getValuesFromMainView];
}

- (void)flagsChanged:(NSEvent *)theEvent
{
	static unsigned int lastMod = 0;
	unsigned int thisMod = [theEvent modifierFlags] & (NSHelpKeyMask| NSControlKeyMask| NSShiftKeyMask| NSCommandKeyMask| NSAlternateKeyMask);
	
	if ( lastMod != thisMod )
	{
		lastMod = thisMod;
		[[fTopLevelContainerView window] invalidateCursorRectsForView:fTopLevelContainerView];
		[[fTopLevelContainerView window] resetCursorRects];
	}
}

- (void)audioClipInspector
{
	[MIAudioClipInspectorController displayAudioClipInspector:[self selection]];
}

- (void)debugAudioRecorder
{
	ZzWarningMessageBox("This command is obsolete. Use the Record panel instead.");
}

- (BOOL)ignoreArrowKeys {
	return YES;
}


@end
