/*
 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
*/

#include <IO/Output/IOAudioOutput.hpp>
#include <IO/Manager/IOManager.hpp>
#include <IO/Manager/IOBuffer.hpp>
#include <IO/osx/AudioHardware.hpp>

IOAudioOutput::IOAudioOutput( const string & aName, IODeviceID anID )
 : IOOutput( aName, anID )
{
    init();
}

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

bool IOAudioOutput::updateFrom( IOBuffer * ioBuf )
{
    //printf("IOAudioOutput::updateFrom backlog %d\n", bufferCount() );
    //fflush( stdout);
    
    if( bufferCount() > 8 ) {

        //printf("IOAudioOutput::updateFrom backlog %d discard buffer\n", bufferCount() );
        //fflush( stdout);
        return false;
    }
    return IOOutput::updateFrom( ioBuf );
}

bool IOAudioOutput::start() 
{ 
    if( mInited && ! mStarted && isAttached() && AudioHardware::start( IODescription::ioOut, getDeviceID(), this ) ) {

        printf("IOAudioInput::start started(%s)\n", getName().c_str() );

        mStarted = true;
    }
    
    return mStarted;
}

bool IOAudioOutput::stop() 
{ 
    if( mStarted && AudioHardware::stop( IODescription::ioOut, getDeviceID(), this ) ) {

        printf("IOAudioOutput::stop stopped(%s)\n", getName().c_str() );

        mStarted = false;
    }
    
    while( bufferCount() > 0 ) {
    
        IOBuffer * buffer = getBuffer( true );
    
        if( buffer ) {

            buffer->release();
        }
    }
    
    return mStarted;
}

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

bool IOAudioOutput::setVolume( int   l, int r   )
{
    return AudioHardware::setVolume( getDeviceID(), l, r, false );
}

bool IOAudioOutput::getVolume( int & l, int &r  )
{
    return AudioHardware::getVolume( getDeviceID(), l, r, false );
}

bool IOAudioOutput::pop( IOBuffer * ioBuf )
{
    return false;
}

void IOAudioOutput::init()
{
    if( AudioHardware::init( IODescription::ioOut, getDeviceID(), 8192, 2, this ) != true ) { 	
        printf( "IOAudioOutput::init failed to initialize %s\n", getName().c_str());
    }
    else {
        mInited = true;
    }
}

void IOAudioOutput::finit()
{
    if( AudioHardware::finit( IODescription::ioOut, getDeviceID()) != true ) { 	
        printf( "IOAudioOutput::finit failed to finitialize %s\n", getName().c_str());
    }
}

bool IOAudioOutput::command( const string & command, 
                             const string & param1, const string & param2, const string & param3, const string & param4 )
{
    puts("IOAudioOutput::command");
    
    if( command == "incVolume" ) {

        int l,r;
        
        getVolume( l, r );

        l += atoi( param1.c_str() );
        r += atoi( param1.c_str() );

        return setVolume( l, r );

    }
    else if( command == "decVolume" ) {

        int l,r;

        getVolume( l, r );
        
        l -= atoi( param1.c_str() );
        r -= atoi( param1.c_str() );
        
        return setVolume( l, r );
    }
   else if( command == "leftVolume" ) {

        int l,r;
        
        getVolume( l, r );

        l = atoi( param1.c_str() );
        
        return setVolume( l, r );
        
    }
   else if( command == "rightVolume" ) {

        int l,r;
        
        getVolume( l, r );

        r = atoi( param1.c_str() );
        
        return setVolume( l, r );
    }
    
    return false;
}

