/*
 Copyright (C) 2002 Andreas Thiede ( a.thiede@berlin.de )

 This program is free software; you can redistribute it 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.

 This program 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 more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#import <IO/Output/Video/OutputWindow.hpp>
#import <IO/Manager/IOManager.hpp>
#import <IO/Manager/IOBuffer.hpp>
#import <IO/Manager/IOStream.hpp>
#import <IO/Manager/IOModel.hpp>
#import <IO/Manager/IOView.hpp>
#import <IO/Manager/IOLockGuard.hpp>
#import <IO/Output/Video/GLWindow.h>
#import <skins/SkinBase.hpp>

#import <lib/Tuner.h>
#import <lib/Preferences.h>

#import <util/Loader.h>

#import <unistd.h>
#import <time.h>
#import <sys/time.h>
#import <CoreServices/CoreServices.h>

static UInt64 millitime()
{
    struct timeval now;
        
    gettimeofday( &now, 0 );
    
    return (UInt64) now.tv_sec * 1000 + (UInt64) now.tv_usec / 1000;
}

@interface MyTextView : NSView
{
    char mText[1024];
}

// Overrides

- (id)initWithFrame:(NSRect) frameRect;
-(void)drawRect:(NSRect)rect;

- (BOOL) isOpaque;

@end // MyTextView

@implementation MyTextView

- (BOOL) isOpaque
{
    return NO;
}

-(void)drawRect:(NSRect)rect
{
    NSDictionary * d  = [NSDictionary dictionaryWithObject: [NSColor whiteColor] forKey:NSForegroundColorAttributeName ];
    
    NSString * text = [ NSString stringWithCString:mText ];

    NSPoint textPos  = NSMakePoint( 10, 5 );

    [ text drawAtPoint: textPos withAttributes: d ];

}

- (id)initWithFrame:(NSRect) frameRect
{
    strcpy( mText, "" );
    
    return [ super initWithFrame:frameRect ];
}

@end // implementation MyTextView

@interface MyGLWindow : GLWindow {

    UInt64               mStartTime;
    int                  mMovieWidth, mMovieHeight;
    int                  mWindowWidth, mWindowHeight;
    float                mDesiredFPS;
    int                  mFrameCount;
    int                  mDivider;
    
    OutputWindow       * mOwner;
    int                  mX, mY;
    SkinBase           * mCurrentSkin;
    bool                 mControlsVisible;
    NSTimer	       * mFrameTimer;
    BOOL		 mShowInfo;
    MyTextView         * mTextView;
    NSWindow           * mInfoWindow;

}
- (void) initWith:(OutputWindow*) owner windowPos:(NSRect) windowPos movieSize:(NSSize) movieSize;
- (void) setSkin:( const char *) skinName;
- (void) keyDown:(NSEvent *)theEvent;
- (void) windowDidResize:(NSNotification *) aNotification;
- (void) windowDidMove:(NSNotification*) aNotification;
- (void) moveWindow;
- (void) resizeWindow;
- (void) sizeChanged:(float) windowWidth height:(float) windowHeight;
- (void) posChanged:(float) x y:(float) y;
- (void) updateContent;
- (void) updateInfoWindowPos;
- (void) toggleFullScreen;
- (void) toggleControls;
- (void) updateGLView;
- (void) start;
- (void) stop;
- (void) reInit;
- (void) handleDrop:(NSString*) fileName;
- (void) showTVControls;
- (void) showPlayerControls;
- (void) toggleInfo;
- (void) showInfos;

@end // interface MyGLWindow

@implementation MyGLWindow

- (void) initWith:(OutputWindow*) owner windowPos:(NSRect) windowPos movieSize:(NSSize) movieSize
{ 
    mCurrentSkin     =  0;        
    mMovieWidth      = (short) movieSize.width;
    mMovieHeight     = (short) movieSize.height;
    mWindowWidth     = (short) windowPos.size.width;
    mWindowHeight    = (short) windowPos.size.height;
    mOwner           = owner;
    mFrameCount      = 0;
    mDivider         = 1;
    mX               = (int)windowPos.origin.x;
    mY               = (int)windowPos.origin.y;
    mControlsVisible = true;
    mShowInfo        = false;

    mInfoWindow = [ NSWindow alloc ];
    
    int flags = NSBorderlessWindowMask;
    
    NSRect frame = [ NSWindow contentRectForFrameRect: NSMakeRect(0,0,300,20) styleMask: flags ];
    
    [ mInfoWindow initWithContentRect: frame styleMask: flags backing: NSBackingStoreBuffered defer: NO ];
   // [ mInfoWindow initWithContentRect: frame styleMask: flags backing: NSBackingStoreNonretained defer: NO ]; //philipp did this
     
    [ mInfoWindow setOpaque: NO ];
    [ mInfoWindow setAlphaValue: 1.0 ];
    [ mInfoWindow setBackgroundColor: [NSColor clearColor]];

    mTextView = [ MyTextView alloc ];
    
    [ mTextView initWithFrame:NSMakeRect( 0,0, 300, 30 ) ];

    [ mInfoWindow setContentView:mTextView ];

    //[ mInfoWindow setLevel: kCGOverlayWindowLevel ];    
    
        
    //mChannelInfo = new GLWindow::String( 10, 10, mChannel.getString() );
        
    //getStringList().push_back( mChannelInfo );

    //mFrameRate =  new GLWindow::String( 50, 10, "" );

    //getStringList().push_back( mFrameRate );

    //mFileInfo =  new GLWindow::String( 90, 10, mMovieFile.getString() );

    //getStringList().push_back( mFileInfo );
        
    //mChannelInfo->setVisible( false );
        
    //mFileInfo->setVisible( false );
    
}

- (void) start
{
    //Create the update timer
    
    mFrameTimer = [[ NSTimer scheduledTimerWithTimeInterval:0.02
                        target:self				// Target is this object
                        selector:@selector(updateGLView)	// What function are we calling
                        userInfo:nil repeats:YES]		// No userinfo / repeat infinitely
                        retain ]; 				// No autorelease


    [[NSRunLoop currentRunLoop] addTimer: mFrameTimer forMode: NSEventTrackingRunLoopMode];
 
    UpdateSystemActivity( UsrActivity ); 
}

- ( void ) stop
{
    [ mFrameTimer invalidate ];
}

- (void) toggleControls
{
    if( mCurrentSkin != 0 ) {
    
        mControlsVisible = ! mControlsVisible;
        
        mCurrentSkin->showControls( mControlsVisible );
    }
}

- (void) toggleFullScreen
{
    [ super toggleFullScreen ];
    
    if( mCurrentSkin != 0 ) {
        mCurrentSkin->toggleFullScreen( [ self isFullScreen ] );
    }
}

- (void) toggleInfo
{
    mShowInfo = ! mShowInfo;

    if( mShowInfo ) {
        [ self updateInfoWindowPos ];
    }
    else {
        [ mInfoWindow orderOut:nil ];
    }
}

- (void) showTVControls
{
    if( mCurrentSkin != 0 ) {
        mCurrentSkin->showTVControls();
    }
}
- (void) showPlayerControls
{
    if( mCurrentSkin != 0 ) {
        mCurrentSkin->showPlayerControls();
    }
}

- (void) setSkin:(const char *) skinName
{
    IOObject * obj = IOManager::instance().findObject( skinName );
        
    if( obj != 0 ) {
            
        //printf( "found skin %s\n", skinName );
            
        if( mCurrentSkin != 0 ) {
            mCurrentSkin->closeSkinForWindow( self );
        }

        mCurrentSkin = (SkinBase*) obj;

        mCurrentSkin->retain();
            
        if( mCurrentSkin->createSkinForWindow( self ) ) {
        
            float w = [ self frame ].size.width;
            float h = [ self frame ].size.height;
            
            [ self  sizeChanged:w height:h  ];
        }
    }
}

- (void) handleDrop:(NSString*) fileName
{
    //puts("MyGLWindow::handleDrop");
     
    IOManager::instance().sendCommand( "WindowController",  "handleDrop", mOwner->getName(), [ fileName cString ] );
                
}

static const char * getString( NSString * characters )
{
    NSAutoreleasePool * pool =[ [ NSAutoreleasePool alloc ] init ];

    const char * result = "";
    
    if( [ characters canBeConvertedToEncoding: [ NSString defaultCStringEncoding ]] ) {
        result = [ characters cString ];
    }
    else {
        result = [ characters lossyCString ];
    }

    [ pool release ];
    
    return result;
}

- (void)scrollWheel:(NSEvent *)theEvent
{
    char dx[24];
    char dy[24];
    char dz[24];
    
    sprintf( dx, "%f", [ theEvent deltaX ] );
    sprintf( dy, "%f", [ theEvent deltaY ] );
    sprintf( dz, "%f", [ theEvent deltaZ ] );
    
    IOManager::instance().sendCommand( "WindowController",  "scrollWheel", mOwner->getName(), dx, dy, dz );

}

- (void) mouseDown:(NSEvent *)theEvent
{
    if( ! [ self isFullScreen ]  ) {
    
        float width  = [ self frame ].size.width;
        //float height = [ self frame ].size.height;
        float x      = [ theEvent locationInWindow ].x;
        float y      = [ theEvent locationInWindow ].y;

        //printf("MyGLWindow::mouseDown xywh(%d,%d,%d,%d)\n", (int)x, (int) y, (int)width, (int)height );
    
        if( x >= ( width - 40 ) && x < width && y >= 0 && y < 40 ) {
            [ self resizeWindow ];
        }
            else {
            [ self moveWindow ];
        }
        [ super mouseDown:theEvent ];
    }
    else if( mCurrentSkin != 0 && mControlsVisible == true ) {
        mCurrentSkin->toggleFullScreen( true ); // should show the control window above our glwindow
    }
    
    if( mShowInfo ) {
        [ mInfoWindow orderWindow:NSWindowAbove relativeTo:[ self windowNumber ] ];
    }
}

- (void) keyDown:(NSEvent *) event
{

    //printf("MyGLWindow::keyDown key(%s) code(%x) modifiers(%x)\n", key.c_str(), keyCode, modifiers );

    //[ super keyDown:event ];

    string key = getString( [ event characters ]);
    char  keyCode  [12];
    char  modifiers[12];
    
    sprintf( keyCode,   "%d", [ event keyCode       ] );
    sprintf( modifiers, "%d", [ event modifierFlags ] );
    
    IOManager::instance().sendCommand( "WindowController",  "keyDown", mOwner->getName(), key, keyCode, modifiers );
}
    
- (void) updateContent
{
    if( mCurrentSkin ) {
        mCurrentSkin->update();
    }
}

- (void) reInit
{
    //puts("reInit");
    
    int ww,wh;
    
    NSSize movieSize = NSMakeSize( mMovieWidth, mMovieHeight );

    [ self setupGL:[ self frame ] movieSize:movieSize ];  

    ww = (int) [ self frame ].size.width;
    wh = (int) [ self frame ].size.height;

    //[ self resize:ww-1 h:wh-1 ];
    //[ self resize:ww+0 h:wh+0 ];
            
    for( int i = 0; i < 2; i++ ) {

        IOBuffer * b = mOwner->getBuffer( 0 );
                
        if( b ) {
            b->release();
        }
    };
            
    int val = GetPrivateProfileInt( "Window", "StayOnTop" , 0 );
         
    if( val != 0 ) {

        [ self setLevel: kCGOverlayWindowLevel ];    
    }
    mFrameCount = 0;
    mStartTime  = millitime();
}            

- (void) updateGLView
{
    UInt64 start = millitime();
    
    IOBuffer * buffer = mOwner->getBuffer( 40 );

    UInt64 stop = millitime();
    
    UInt64 diff = stop - start;
    
    if( diff > 40 ) {
       printf( "updateGLView: waited %d msec\n", (int) diff );        
    }
    else if( buffer ) {
  
        if(  mFrameCount %  mDivider == 0 ) {
                                                                        
            [ self draw:(unsigned char *) buffer->getData() ];

            if( mShowInfo ) {
                [ self showInfos ];
            }            
        }
        
        mFrameCount++;
                    
        buffer->release();
    }
}

- (void) updateInfoWindowPos
{
    GLView * v     = [ self glView ];

    NSRect   glFrame = [ (NSView*)v frame ];

    NSRect   windowFrame = [ self frame ];
    
    NSRect   infoFrame = [ mInfoWindow frame ];
    
    infoFrame.origin.x = windowFrame.origin.x + glFrame.origin.x;
    infoFrame.origin.y = windowFrame.origin.y + glFrame.origin.y + glFrame.size.height - infoFrame.size.height;
    
    // printf("Moving textview to %d,%d\n", (int) infoFrame.origin.x, (int) infoFrame.origin.y );
    
    [ mInfoWindow setFrame:infoFrame display:true ];

    if( [ self isFullScreen ] || [ self level ] == kCGOverlayWindowLevel ) {
        [ mInfoWindow setLevel: kCGOverlayWindowLevel ];    
    }
    else {
        [ mInfoWindow setLevel: kCGNormalWindowLevelKey ];    
    }
    
    [ mInfoWindow orderWindow:NSWindowAbove relativeTo:[ self windowNumber ] ];
}


- (void) posChanged:(float) x y:(float) y
{
    [ super posChanged:x y:y ];

    if( ! [ self isFullScreen ] ) {
        
        WritePrivateProfileInt( mOwner->getName().c_str(), "OriginX", (int) x );
        WritePrivateProfileInt( mOwner->getName().c_str(), "OriginY", (int) y );
    }
    
    [ self updateInfoWindowPos ];    
        
}

- (void) sizeChanged:(float) windowWidth height:(float) windowHeight
{
    [ super sizeChanged:windowWidth height:windowHeight ];
    
    if( ! [ self isFullScreen ] ) {

        //[ self updateContent ];
        
        WritePrivateProfileInt( mOwner->getName().c_str(), "SizeX", (int) windowWidth  );
        WritePrivateProfileInt( mOwner->getName().c_str(), "SizeY", (int) windowHeight );
    }        

    [ self updateInfoWindowPos ];    
}

- (void)windowDidResize:(NSNotification*) aNotification
{
    puts("MyGLWindow.windowDidResize");
    
    [ super windowDidResize:aNotification ];
        
    NSRect bounds = [ self frame ];
        
    [ self sizeChanged:bounds.size.width height:bounds.size.height ];    
}

- (void) windowDidMove:(NSNotification*) aNotification
{
    if( ! [ self isFullScreen ] ) {

        NSRect bounds = [ self frame ];

        WritePrivateProfileInt( mOwner->getName().c_str(), "OriginX", (int) bounds.origin.x );
        WritePrivateProfileInt( mOwner->getName().c_str(), "OriginY", (int) bounds.origin.y );
    }

}

- (void) moveWindow
{
    int deltaX=0, deltaY=0;
    
    int keepOn = YES;

    int lastX;
    int lastY;
    int rem;
    
    NSPoint current = [ NSEvent mouseLocation];

    lastX = (int) current.x;
    lastY = (int) current.y;

    //puts("moveWindow");

    do {

        NSEvent * theEvent = [ self nextEventMatchingMask: NSAnyEventMask ];

        switch( [theEvent type] ) {

            case NSLeftMouseDragged:

                    current = [ NSEvent mouseLocation];

                    deltaX = lastX - (int) current.x;
                    deltaY = lastY - (int) current.y;

                    { 
                        NSPoint point = NSMakePoint( [ self frame].origin.x, [ self frame].origin.y );
        
                        point.x -= deltaX;
                        point.y -= deltaY;
                    
                        rem = (int)point.x % 4;
                    
                        switch( rem ) {
                        case 1:
                        case 2:
                            point.x -=  rem;
                            break;
                        case 3:
                            point.x += 1;
                            break;
                        }
                                        
                        [ [ self contentView ] lockFocus ];

                        [ self move:point.x  y:point.y ];
                    
                        [ [ self contentView ] unlockFocus ];

                        lastX = (int) current.x;
                        lastY = (int) current.y;
                    }

                    break;
            case NSLeftMouseUp:
            
                    current = [ NSEvent mouseLocation];

                    lastX = (int) current.x;
                    lastY = (int) current.y;

                    //if (isInside) [self doSomethingSignificant];
                    //[self highlight:NO];
                    keepOn = NO;
                    break;
            default:
                    /* Ignore any other kind of event. */
                    break;
        }
    } while (keepOn);    
}

static void nsRect2Carbon( NSRect rect, Rect & carbonRect )
{   
    NSSize screenSize = [[ NSScreen mainScreen ] frame ].size;
                     
    int l = int( rect.origin.x );
    int t = int( screenSize.height - ( rect.origin.y + rect.size.height ));
    int r = int( rect.origin.x+rect.size.width );
    int b = int(t + rect.size.height);
                        
    SetRect( &carbonRect, l, t, r, b );                                        
}

- (void) resizeWindow
{
    int deltaX=0, deltaY=0;
    
    int keepOn = YES;

    int lastX;
    int lastY;
    
    NSPoint current = [ NSEvent mouseLocation];

    lastX = (int) current.x;
    lastY = (int) current.y;

    NSRect rect = [ self frame];

    //puts("resizeWindow");
    
    CGrafPtr savedPort;
    
    GetPort( &savedPort );

    SetPort( 0 );
    
    PenState pnState;
    
    GetPenState(&pnState);
    
    ShowPen();
    
    PenSize( 2, 2 );
    PenMode( patXor );
    
    Pattern blackPat;

    GetQDGlobalsBlack( &blackPat );
    
    PenPat( &blackPat );

    Rect carbonRect;

    nsRect2Carbon( rect, carbonRect );

    MacFrameRect( &carbonRect );
    
    do { 

        NSEvent * theEvent = [ self nextEventMatchingMask: NSAnyEventMask ];
        
        switch( [theEvent type] ) {

            case NSLeftMouseDragged:

                    current = [ NSEvent mouseLocation];

                    deltaX = -( lastX - (int) current.x );
                    deltaY = lastY - (int) current.y;
                    
                    rect.size.width  += deltaX;
                    rect.size.height += deltaY;
                    rect.origin.y    -= deltaY;

                    MacFrameRect( &carbonRect );
                    
                    nsRect2Carbon( rect, carbonRect );

                    MacFrameRect( &carbonRect );
                    
                    lastX = (int) current.x;
                    lastY = (int) current.y;

                    break;
            case NSLeftMouseUp:
            
                    current = [ NSEvent mouseLocation];

                    lastX = (int) current.x;
                    lastY = (int) current.y;

                    keepOn = NO;
                    break;
            default:
                    /* Ignore any other kind of event. */
                    break;
        }

    } while( keepOn );

    nsRect2Carbon( rect, carbonRect );

    MacFrameRect( &carbonRect );

    ShowCursor();
    HidePen();
    SetPenState(&pnState);
    
    SetPort( savedPort );
    
    //[ self resize:rect.size.width h:rect.size.height ];

    [ self setFrame:rect display:true ];
    
    [ self sizeChanged:rect.size.width height:rect.size.height ];    
    
}

- (void) showInfos
{
    string str;
    string currentProgram = IOManager::instance().getValue( "ProgramList", "current" );

    if( currentProgram != "" && atoi( currentProgram.c_str() ) != -1 ) {
    
        str =  "program: ";
        str += currentProgram;
        str += " - ";
    }
    
    int channel = GetPrivateProfileInt( "Tuner", "CurrentChannel", 0 );
 
    char num[24];
       
    sprintf( num, "%d", channel );

    str += "channel: ";
    str += num;

    UInt64 diff = millitime() -  mStartTime;
                        
    if( diff > 30 ) {
                            
        char fps[64];
                            
        sprintf( fps, "%02.2f", (float) (  mFrameCount * 1000 ) / (float) diff );
                    
        str += " - fps: ";
        str += fps;
    }

    strcpy( mTextView->mText, str.c_str() );    
    
    [ mTextView display ];
    
}

@end // implementationMyGLWindow

OutputWindow::OutputWindow( const string & aName, IODeviceID anID )
 : IOOutput( aName, anID )
 , mTVType     ( "Hardware.TVType"     )
 , mChannel    ( "Tuner.CurrentChannel")
 , mMovieFile  ( "Player.CurrentFile"  )
 , mStayOnTop  ( "Window.StayOnTop"    )
{
    init();
}

OutputWindow::~OutputWindow()
{    
    finit();
}


void OutputWindow::createWindow()
{
    int val = GetPrivateProfileInt( "Hardware", "TVType" , 0 );
        
    int x = 50, y = 50, w,h, ww, wh;
        
    switch( val ) {
    case FORMAT_PAL_BDGHI:
    case FORMAT_SECAM:
    case FORMAT_PAL_N:
        w = 360;
        h = 288;
        ww = 500;
        wh = 372;
        break;
    case FORMAT_NTSC:

    case FORMAT_PAL_M:
    case FORMAT_PAL60:
    case FORMAT_NTSC_J:
        w = 360;
        h = 240;
        ww = 500;
        wh = 333;
        break;
    }
    
    int wx = GetPrivateProfileInt( getName().c_str(), "OriginX", x );
    int wy = GetPrivateProfileInt( getName().c_str(), "OriginY", y );

    ww = GetPrivateProfileInt( getName().c_str(), "SizeX", ww );
    wh = GetPrivateProfileInt( getName().c_str(), "SizeY", wh );

    NSRect windowPos = NSMakeRect( wx, wy, ww, wh );

    NSSize movieSize = NSMakeSize( w, h );
    
    MyGLWindow * window = mWindow;
    
    if( window == 0 ) {
    
        //IOLockGuard lockGuard( *this );
    
        window = [ MyGLWindow alloc ];
        
        [ window initWith:this windowPos:windowPos movieSize:movieSize ];
                
    }

    if( window != 0 ) {
    
        [ window setupGL:windowPos movieSize:movieSize ];        

    }
    else  {
        puts("failed to create window");
        return;
    }
 
    [ window reInit ];

    [ window updateInfoWindowPos ];    

    // ok setup is finished
    
    mWindow = window;
}

bool OutputWindow::pause() 
{
    return stop();
}

bool OutputWindow::resume() 
{
    return start();
}

bool OutputWindow::start() 
{ 
    if( mInited && ! mStarted && isAttached()) {

        createWindow();

        [ mWindow start ];
                
        mStarted = true;
    }

    return mStarted;
}

bool OutputWindow::stop() 
{ 
    mStarted = false;

    [ mWindow stop ];
    
    return mStarted;
}

size_t OutputWindow::frameSize()
{
    return 8192;
}

void OutputWindow::init()
{
    mWindow = 0;
    mInited = true; 
    
    mTVType.addView( this );                
    mChannel.addView( this );                
    mMovieFile.addView( this );                
    mStayOnTop.addView( this );                

}

void OutputWindow::finit()
{
    IOManager::instance().unregisterNode ( this );
}

void OutputWindow::updateFrom( IOModel * aModel ) 
{

    //printf("%s.updateFrom: %s\n", getName().c_str(), aModel->getName().c_str() );
        
    if( aModel->getName() == "Hardware.TVType" ) {

        int val = mTVType.getInt();
        
        int w,h;
        
        switch( val ) {
        case FORMAT_PAL_BDGHI:
        case FORMAT_SECAM:
        case FORMAT_PAL_N:
            w = 360;
            h = 288;
            break;
        case FORMAT_NTSC:

        case FORMAT_PAL_M:
        case FORMAT_PAL60:
        case FORMAT_NTSC_J:
            w = 360;
            h = 240;
            break;
        }
    
        if( w != mWindow->mMovieWidth || h != mWindow->mMovieHeight ) {
            mWindow->mMovieWidth  = w;
            mWindow->mMovieHeight = h;
            
            pause();
            resume();
        }
    }
    else if( aModel->getName() == "Window.StayOnTop" ) {

        //puts("GLWindow Window.StayOnTop changed");
        
        int val = GetPrivateProfileInt( "Window", "StayOnTop" , 0 );
         
        if( val != 0 ) {

            [ mWindow setLevel: kCGOverlayWindowLevel ];    
        }
        else {
            [ mWindow setLevel: kCGNormalWindowLevelKey ];    
        }

        if( [ mWindow isVisible ] ) {
            [ mWindow orderOut:nil ];
            [ mWindow orderFront:nil ];
        }
    }
    else if( aModel->getName() == "Tuner.CurrentChannel" ) {
        
        ;//mChannelInfo->setString( aModel->getString() );
    }
    else if( aModel->getName() == "Player.CurrentFile" ) {
        
        ;//mFileInfo->setString( aModel->getString() );
    }
}
bool OutputWindow::updateFrom( IOBuffer * ioBuf )
{
    //printf("OutputWindow::updateFrom %s backlog %d\n", ioBuf->getName().c_str(), bufferCount() );
    //fflush( stdout);
    
    if( bufferCount() > 2 )  {
        //printf("OutputWindow::updateFrom %s backlog %d\n", ioBuf->getName().c_str(), bufferCount() );
        //fflush( stdout);
        return false;
    }
    return IOOutput::updateFrom( ioBuf );
}

bool OutputWindow::command( const string & command, 
                            const string & param1,  const string & param2, const string & param3, const string & param4 )
{
    if( mWindow == 0 ) {
        createWindow();
    }

    //printf("%s.command: %s %s %s\n", getName().c_str(), command.c_str(), param1.c_str(), param2.c_str() );

    if( command == "setWindowSize" ) {

        mWindow->mWindowWidth  = atoi( param1.c_str() );
        mWindow->mWindowHeight = atoi( param2.c_str() );

        if( mStarted ) {
            pause();
            resume();
        }
    }
    else if( command == "setMovieSize" ) {

        mWindow->mMovieWidth  = atoi( param1.c_str() );
        mWindow->mMovieHeight = atoi( param2.c_str() );

        if( mStarted ) {
            pause();
            resume();
        }
    }
    else if( command == "setFrameRateDivider" ) {

        int div  = atoi( param1.c_str() );

        if( div > 0 )  {
            //printf("setFrameRateDivider(%d)\n", div );
            
            mWindow->mDivider = div;
        }
    }
    else if( command == "toggleFullScreen" ) {
        [ mWindow toggleFullScreen ];
    }
    else if( command == "setSkin" ) {

       [ mWindow setSkin: param1.c_str() ];
    }
    else if( command == "lbdrag" ) {

        [ mWindow resizeWindow ];
    }
    else if( command == "toggleControls" ) {

        [ mWindow toggleControls ];
    }
    else if( command == "showPlayerControls" ) {
        [ mWindow showPlayerControls ];
    }
    else if( command == "showTVControls" ) {
        [ mWindow showTVControls ];
    }
    else if( command == "show" ) {
        [ mWindow     makeKeyAndOrderFront:nil ];
        [ mWindow->mInfoWindow orderWindow:NSWindowAbove relativeTo:[mWindow windowNumber ] ];
    }
    else if( command == "hide" ) {
        [ mWindow->mInfoWindow orderOut:nil ];
        [ mWindow     orderOut:nil ];
    }
    else if( command == "toggleInfo" ) {
       [ mWindow  toggleInfo ];
    }
#if 0
    else if( command == "showChannelInfo" ) {
        mWindow->mChannelInfo->setVisible( atoi( param1.c_str()  ) );
    }
    else if( command == "showFileInfo" ) {

        mWindow->mFileInfo->setVisible( atoi( param1.c_str()  ) );
    }
#endif
    
    return true;
}

string OutputWindow::getValue( const string & valueName )
{
    char buffer[256];

    strcpy( buffer, "" );
    
    if( valueName == "isFullScreen" ) {
        sprintf( buffer, "%d", [ mWindow isFullScreen ] );
    }
    else if( valueName == "windowNumber" ) {
        sprintf( buffer, "%d", [ mWindow windowNumber ] );
    }

    return buffer;
    
};

extern "C" int initGLWindowPlugin( int argc, const char ** argv )
{
    OutputWindow * ow = new OutputWindow( "MovieWindow", 0 );
    
    IOManager::instance().registerNode (ow );
    
    return true;
}
    
