//NetTalk
/*------------------------------------------------------------------------------*\
 =============================
   模块名称: WaveShow.cpp
 =============================
 
 [版权]
 
   2000-2002  115软件工厂  版权所有
                                              
\*------------------------------------------------------------------------------*/
#include "WndX.h"

#include "WaveShow.h"

/*------------------------------------------------------------------------------*/
CWaveShow::CWaveShow()
{
	//to fit the G729a codec,i set the audio format as below
	//infact the waveshow support not only this format
	m_crBg=0x00000000;
	m_crLine=0x00ffffff;
	m_hbBg=CreateSolidBrush(m_crBg);
	m_hpLine=CreatePen(PS_SOLID,1,m_crLine);
	m_hBmp=0;
	m_Format.wFormatTag	= WAVE_FORMAT_PCM;
	m_Format.cbSize		= 0;
	m_Format.wBitsPerSample=16;
	m_Format.nSamplesPerSec=8000;
	m_Format.nChannels=1;
	m_Format.nAvgBytesPerSec	= m_Format.nSamplesPerSec*(m_Format.wBitsPerSample/8);
	m_Format.nBlockAlign		= m_Format.nChannels     *(m_Format.wBitsPerSample/8);
}
/*------------------------------------------------------------------------------*/
CWaveShow::~CWaveShow()
{
	
}
/*------------------------------------------------------------------------------*/
BOOL CWaveShow::Create(RECT &rc,HWND hParent)
{
	return CWndX::Create(0,0,0,WS_CHILD|WS_VISIBLE,rc,hParent,0);
}
/*------------------------------------------------------------------------------*/
LRESULT CWaveShow::WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch(uMsg)
	{
	case WM_DESTROY:
		{
			if(m_hBmp)
				DeleteObject(m_hBmp);
			if(m_hbBg)
				DeleteObject(m_hbBg);
			if(m_hpLine)
				DeleteObject(m_hpLine);
			m_hBmp=0;
			m_hbBg=0;
			m_hpLine=0;
		}
		break;
	case WM_PAINT:
		OnPaint();
		return TRUE;
	case WM_TIMER:
		{
			KillTimer(m_hWnd,wParam);
			HDC hdc=GetDC(m_hWnd);
			Paint(hdc,0,0);
			ReleaseDC(m_hWnd,hdc);
		}
		break;
	}
	return CWndX::WndProc(uMsg,wParam,lParam);
}
/*------------------------------------------------------------------------------*/

BOOL CWaveShow::Paint(HDC hdc,char* buf,unsigned uSize)
{
	BOOL bRet=FALSE;
	BITMAP bmp;
	GetObject(m_hBmp,sizeof(bmp),&bmp);
	CRectX rc;
	GetClientRect(m_hWnd,&rc);
	if(m_hBmp)
	{
		
		if(bmp.bmHeight!=rc.Height()||bmp.bmWidth!=rc.Width())
		{
			DeleteObject(m_hBmp);
			m_hBmp=CreateCompatibleBitmap(hdc,rc.Width(),rc.Height());
		}
		
	}
	else
	{
		m_hBmp=CreateCompatibleBitmap(hdc,rc.Width(),rc.Height());
	}
	if(buf)
	{
				
		SetTimer(m_hWnd,1,150,0);
		switch(m_Format.wBitsPerSample)
		{
		case 8:
			{
				HDC hMemDC=CreateCompatibleDC(hdc);
				HBITMAP hob=(HBITMAP)SelectObject(hMemDC,m_hBmp);
				FillRect(hMemDC,&CRectX(0,0,rc.Width(),rc.Height()),m_hbBg);
				
				HPEN hop=(HPEN)SelectObject(hMemDC,m_hpLine);
				int iHeight=rc.Height();
				int iWidth=rc.Width();
				MoveToEx(hMemDC,-1,iHeight/2,0);
				if(m_Format.nChannels==1)
				{
					
					for(int i=0;i<iWidth;i+=2)
					{
						LineTo(hMemDC,i,((BYTE)buf[uSize*i/iWidth])*iHeight/256);
					}
				}
				else
				if(m_Format.nChannels==2)
				{
					
					for(int i=0;i<iWidth-1;i+=2)
					{
						int index=uSize*i/iWidth/2*2;
						LineTo(hMemDC,i,((BYTE)buf[index]+(BYTE)buf[index+1])*iHeight/512);
					}
				}
				LineTo(hMemDC,iWidth+1,iHeight/2);
				SelectObject(hMemDC,hop);
				BitBlt(hdc,rc.left,rc.top,iWidth,iHeight,hMemDC,0,0,SRCCOPY);
				SelectObject(hMemDC,hob);
				DeleteDC(hMemDC);
			}
			break;
		case 16:
			{
				HDC hMemDC=CreateCompatibleDC(hdc);
				HBITMAP hob=(HBITMAP)SelectObject(hMemDC,m_hBmp);
				FillRect(hMemDC,&CRectX(0,0,rc.Width(),rc.Height()),m_hbBg);
				
				HPEN hop=(HPEN)SelectObject(hMemDC,m_hpLine);
				int iHeight=rc.Height();
				int iHHeight=iHeight/2;
				int iWidth=rc.Width();
				MoveToEx(hMemDC,-1,iHeight/2,0);
				short* ps=(short*)buf;
				UINT uHSize=uSize/2;

				if(m_Format.nChannels==1)
				{
					
					for(int i=0;i<iWidth;i+=2)
					{
						LineTo(hMemDC,i,iHHeight+ps[uHSize*i/iWidth]*iHeight/65535);
					}
				}
				else
				if(m_Format.nChannels==2)
				{
					
					for(int i=0;i<iWidth-1;i+=2)
					{
						int index=uHSize*i/iWidth/2*2;
						LineTo(hMemDC,i,iHHeight+(ps[index]+ps[index+1])*iHHeight/65535);
					}
				}
				LineTo(hMemDC,iWidth+1,iHHeight);
				SelectObject(hMemDC,hop);
				BitBlt(hdc,rc.left,rc.top,iWidth,iHeight,hMemDC,0,0,SRCCOPY);
				SelectObject(hMemDC,hob);
				DeleteDC(hMemDC);
			}
			break;
		}	
	}
	else
	{
		
		HDC hMemDC=CreateCompatibleDC(hdc);
		HBITMAP hob=(HBITMAP)SelectObject(hMemDC,m_hBmp);
		HPEN hop=(HPEN)SelectObject(hMemDC,m_hpLine);
		FillRect(hMemDC,&CRectX(0,0,rc.Width(),rc.Height()),m_hbBg);
		MoveToEx(hMemDC,0,rc.Height()/2,0);
		LineTo(hMemDC,rc.Width(),rc.Height()/2);
		BitBlt(hdc,rc.left,rc.top,rc.Width(),rc.Height(),
			hMemDC,0,0,SRCCOPY);
		SelectObject(hMemDC,hop);
		SelectObject(hMemDC,hob);
		DeleteDC(hMemDC);
		bRet=TRUE;
	
	}
	return bRet;
}
/*------------------------------------------------------------------------------*/
//set the wave format,
void CWaveShow::SetFormat(WAVEFORMATEX *pfmt)
{
	if(pfmt)
		CopyMemory(&m_Format,pfmt,sizeof(m_Format));
}
/*------------------------------------------------------------------------------*/
void CWaveShow::GetFormat(WAVEFORMATEX& fmt)
{
	fmt=m_Format;
}

/*------------------------------------------------------------------------------*/

void CWaveShow::SetBgColor(COLORREF cr)
{
    m_crBg=cr;
	if(m_hbBg)
		DeleteObject(m_hbBg);
	m_hbBg=CreateSolidBrush(cr);
}
/*------------------------------------------------------------------------------*/
COLORREF CWaveShow::GetBgColor()
{
    return m_crBg;
}
/*------------------------------------------------------------------------------*/
void CWaveShow::SetLineColor(COLORREF cr)
{
	m_crLine=cr;
	if(m_hpLine)
		DeleteObject(m_hpLine);
	m_hpLine=CreatePen(PS_SOLID,1,cr);
}
/*------------------------------------------------------------------------------*/
COLORREF CWaveShow::GetLineColor()
{
	return m_crLine;
}

/*------------------------------------------------------------------------------*/

void CWaveShow::OnPaint()
{
	PAINTSTRUCT ps;
	HDC hdc=BeginPaint(m_hWnd,&ps);
	Paint(hdc,0,0);
	EndPaint(m_hWnd,&ps);
}


