// BKOscScrGDI.cpp: определяет экспортированные функции для приложения DLL.
//

#include "stdafx.h"
#include "BKOscScrGDI.h"

#include "atltypes.h"

#pragma comment (lib,"Gdiplus.lib")
BKEXTERN_C
{

	BKOSCDLL_API BKOSCSCRHANDLE APIENTRY GetBKOscScr()
	{
		return new CBKOscScrGDI;
	}

	CBKOscScrGDI::CBKOscScrGDI()
		: CBKOScScr_Shared()
		, m_pDC(NULL)
		, m_HDC(NULL)
	{
	}
	CBKOscScrGDI::~CBKOscScrGDI()
	{
	}

	void CBKOscScrGDI::BKOSC_OnSize(int cx, int cy)
	{
	}

	HRESULT CBKOscScrGDI::BKOSC_OnSetBuffer(int nLen)
	{
		return S_OK;
	}


	HRESULT CBKOscScrGDI::BKOSC_Screen_Init(HWND hwndScreen)
	{
		HRESULT hr = (HRESULT) - 1L;
		m_pDC = new CClientDC(CWnd::FromHandlePermanent(hwndScreen));

		if (m_pDC)
		{
			m_HDC = m_pDC->GetSafeHdc();
		}

		// Initialize GDI+.
		Gdiplus::Status status = GdiplusStartup(&m_ulGDIPlusToken, &gdiplusStartupInput, NULL);

		if (status == Gdiplus::Ok)
		{
			hr = S_OK;
		}
		else
		{
			m_ulGDIPlusToken = 0;
		}

		return hr;
	}

	void CBKOscScrGDI::BKOSC_Screen_Done()
	{
		if (m_ulGDIPlusToken != 0)
		{
			Gdiplus::GdiplusShutdown(m_ulGDIPlusToken);
			m_ulGDIPlusToken = 0;
		}

		SAFE_DELETE(m_pDC);
	}


	void CBKOscScrGDI::BKOSC_OnDisplay(HWND hwndScreen, SAMPLE_TYPE * inBuf, int inLen)
	{
		CRect rectClient;
		GetClientRect(hwndScreen, &rectClient);
		Graphics graphics(m_HDC);
		//очищаем экран
		Gdiplus::SolidBrush br(Gdiplus::Color(0, 0, 0));
		graphics.FillRectangle(&br, rectClient.left, rectClient.top, rectClient.Width(), rectClient.Height());
		Gdiplus::PointF rtSize = Gdiplus::PointF(Gdiplus::REAL(rectClient.Width()), Gdiplus::REAL(rectClient.Height()));
		//rtSize.X - ширина окна
		//rtSize.y - высота окна
		Gdiplus::Pen penWhite(Color(255, 255, 255));
		Gdiplus::Pen penGreen(Color(0, 255, 0));
		Gdiplus::Pen penLightSlateGray(Color(0x77, 0x88, 0x99));
		Gdiplus::REAL scalex = rtSize.X / Gdiplus::REAL(inLen);
		Gdiplus::REAL half = rtSize.Y / 2.0f;
		Gdiplus::REAL scaley = half / FLOAT_BASE;
		//рисуем разделительную линию между каналами
		graphics.DrawLine(&penLightSlateGray,
		                  Gdiplus::PointF(0.0f, half),
		                  Gdiplus::PointF(rtSize.X, half));
		Gdiplus::PointF pntbgnL = Gdiplus::PointF(0.0f, rtSize.Y / 4.0f);
		Gdiplus::PointF pntendL = Gdiplus::PointF(rtSize.X, rtSize.Y / 4.0f);
		Gdiplus::PointF pntbgnR = Gdiplus::PointF(0.0f, rtSize.Y * 0.75f);
		Gdiplus::PointF pntendR = Gdiplus::PointF(rtSize.X, rtSize.Y * 0.75f);
		//рисуем линии центров каналов.
		graphics.DrawLine(&penWhite, pntbgnL, pntendL);
		graphics.DrawLine(&penWhite, pntbgnR, pntendR);

		for (int i = 0, j = 0; i < inLen; ++i)
		{
			//рисуем левый канал -32768..32767 => 0 .. height/2
			pntendR.X = pntendL.X = (Gdiplus::REAL)i * scalex;
			pntendL.Y = half - ((Gdiplus::REAL)inBuf[j++] + FLOAT_BASE_HALF) * scaley;
			graphics.DrawLine(&penGreen, pntbgnL, pntendL);
			pntbgnL = pntendL;
			//рисуем правый канал -32768..32767 => height/2 .. height
			pntendR.Y = rtSize.Y - ((Gdiplus::REAL)inBuf[j++] + FLOAT_BASE_HALF) * scaley;
			graphics.DrawLine(&penGreen, pntbgnR, pntendR);
			pntbgnR = pntendR;
		}
	}

};