/////////////////////////////////////////////////////////////////////////////
// $Id: SingleCrossbar.cpp 4579 2009-04-27 11:05:31Z adcockj $
/////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2001 Torbjörn Jansson.  All rights reserved.
/////////////////////////////////////////////////////////////////////////////
//
//  This file is subject to the terms of the GNU General Public License as
//  published by the Free Software Foundation.  A copy of this license is
//  included with this software distribution in the file COPYING.  If you
//  do not have a copy, you may obtain a copy by writing to the Free
//  Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
//
//  This software 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
/////////////////////////////////////////////////////////////////////////////

/**
 * @file SingleCrossbar.cpp implementation of the CDShowSingleCrossbar class.
 */

#include "stdafx.h"

#ifdef WANT_DSHOW_SUPPORT

#include "SingleCrossbar.h"
#include "exception.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CDShowSingleCrossbar::CDShowSingleCrossbar(CComPtr<IAMCrossbar> &pCrossbar,IGraphBuilder *pGraph)
:m_crossbar(pCrossbar),CDShowBaseCrossbar(pGraph)
{
    _ASSERTE(m_crossbar!=NULL);
}

CDShowSingleCrossbar::~CDShowSingleCrossbar()
{

}

void CDShowSingleCrossbar::GetPinCounts(long &cIn,long &cOut)
{
    HRESULT hr=m_crossbar->get_PinCounts(&cOut,&cIn);
    if(FAILED(hr))
    {
        throw CCrossbarException("get_PinCounts failed",hr);
    }
}

PhysicalConnectorType CDShowSingleCrossbar::GetInputType(long Index)
{
    long cPinRelated,type;
    HRESULT hr=m_crossbar->get_CrossbarPinInfo(TRUE,Index,&cPinRelated,&type);
    if(FAILED(hr))
    {
        throw CCrossbarException("get_CrossbarPinInfo failed",hr);
    }
    return (PhysicalConnectorType)type;
}

void CDShowSingleCrossbar::SetInputIndex(long Index,BOOL bSetRelated)
{
    long cInputPinRelated,cOutputPinRelated,type;
    long cInput,cOutput;

    HRESULT hr=m_crossbar->get_PinCounts(&cOutput,&cInput);
    if(FAILED(hr))
    {
        throw CCrossbarException("get_PinCounts failed",hr);
    }

    //set the related pin too?
    if(bSetRelated==TRUE)
    {
        hr=m_crossbar->get_CrossbarPinInfo(TRUE,Index,&cInputPinRelated,&type);
        if(FAILED(hr))
        {
            throw CCrossbarException("get_CrossbarPinInfo faile",hr);
        }
    }

    //check all outputs to see if its posibel to connect with selected input
    BOOL bInputRouted=FALSE;
    for(int i=0;i<cOutput;i++)
    {
        //CanRoute returns S_FALSE if it cant route
        if(m_crossbar->CanRoute(i,Index)==S_OK)
        {
            hr=m_crossbar->Route(i,Index);
            if(FAILED(hr))
            {
                throw CCrossbarException("failed to route",hr);
            }

            //output pin for related pin
            hr=m_crossbar->get_CrossbarPinInfo(FALSE,i,&cOutputPinRelated,&type);

            bInputRouted=TRUE;
            break;
        }
    }

    //successfull?
    if(bInputRouted==FALSE)
    {
        throw CCrossbarException("Cant find route");
    }

    if(bSetRelated==TRUE)
    {
        if(SUCCEEDED(m_crossbar->CanRoute(cOutputPinRelated,cInputPinRelated)))
        {
            if(FAILED(m_crossbar->Route(cOutputPinRelated,cInputPinRelated)))
            {
                throw CCrossbarException("failed to route related pin",hr);
            }

        }
    }
}

long CDShowSingleCrossbar::GetInputIndex(long OutIndex)
{
    long InputIndex=0;
    HRESULT hr=m_crossbar->get_IsRoutedTo(OutIndex,&InputIndex);
    if(FAILED(hr))
    {
        throw CCrossbarException("IAMCrossbar::get_IsRoutedTo failed",hr);
    }
    return InputIndex;
}

BOOL CDShowSingleCrossbar::IsInputSelected(long index)
{
    long cInput,cOutput;
    GetPinCounts(cInput,cOutput);

    for(int i=0;i<cOutput;i++)
    {
        long inputIndex=GetInputIndex(i);
        if(index==inputIndex)
        {
            return TRUE;
        }
    }
    return FALSE;
}
#endif