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

#include "stdafx.h"
#include "BKOscScrOGL.h"

#pragma comment (lib,"opengl32.lib")
#pragma comment (lib,"glu32.lib")

BKEXTERN_C
{

	BKOSCDLL_API BKOSCSCRHANDLE WINAPI GetBKOscScr()
	{
		return new CBKOscScrOGL;
	}

//сколько вершин, столько и цветов должно быть
	GLfloat CBKOscScrOGL::colors3[] =
	{
		0.5, 0.5, 0.5,  0.5, 0.5, 0.5,    0.5, 0.5, 0.5,  0.5, 0.5, 0.5,
		1, 1, 1,  1, 1, 1,    1, 1, 1,  1, 1, 1,
		1, 1, 1,  1, 1, 1,    1, 1, 1,  1, 1, 1
	};

	GLfloat CBKOscScrOGL::vertices2[] =
	{
		-1.0,  0.0,    1.0,  0.0, //разделительна¤ лини¤ между каналами
		-1.0,  0.5,    1.0,  0.5, //линии центров каналов.
		-1.0, -0.5,    1.0, -0.5 //линии центров каналов.
	};

	GLint CBKOscScrOGL::indices1[] = {0, 1, 2, 3, 4, 5};

	CBKOscScrOGL::CBKOscScrOGL()
		: CBKOScScr_Shared()
		, m_pVerticesL(NULL)
		, m_pVerticesR(NULL)
		, m_pIndices2(NULL)
		, m_pDC(NULL)
		, m_HDC(NULL)
		, hGLRC(NULL)
	{
	}

	CBKOscScrOGL::~CBKOscScrOGL()
	{
	}


	void CBKOscScrOGL::BKOSC_OnSize(int cx, int cy)
	{
		m_cx = cx;
		m_cy = cy;
	}

	HRESULT CBKOscScrOGL::BKOSC_OnSetBuffer(int nLen)
	{
		SAFE_DELETE_ARRAY(m_pVerticesL);
		SAFE_DELETE_ARRAY(m_pVerticesR);
		SAFE_DELETE_ARRAY(m_pIndices2);
		m_pVerticesL = new GLfloat[(nLen + 1) * 2];
		m_pVerticesR = new GLfloat[(nLen + 1) * 2];
		m_pIndices2 = new GLint[(nLen + 1)];

		for (int i = 0; i < (nLen + 1); ++i)
		{
			m_pIndices2[i] = i;
		}
		//тут нет проверки на недостачу пам¤ти, т.к. непон¤тно, как быть в этом случае.
		create_context();
		return S_OK;
	}

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

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

			if (m_HDC)
			{
				if (SetWindowPixelFormat(m_HDC))
				{
					hGLRC = wglCreateContext(m_HDC);

					if (hGLRC)
					{
						wglMakeCurrent(m_HDC, hGLRC);
					}

					hr = S_OK;
				}
			}
		}

		return hr;
	}

	void CBKOscScrOGL::BKOSC_Screen_Done()
	{
		if (wglGetCurrentContext())
		{
			wglMakeCurrent(NULL, NULL);
		}

		if (hGLRC)
		{
			wglDeleteContext(hGLRC);
			hGLRC = NULL;
		}

		m_HDC = NULL;
		SAFE_DELETE(m_pDC);
		SAFE_DELETE_ARRAY(m_pVerticesL);
		SAFE_DELETE_ARRAY(m_pVerticesR);
		SAFE_DELETE_ARRAY(m_pIndices2);
	}

	int CBKOscScrOGL::SetWindowPixelFormat(HDC hDC)
	{
		static PIXELFORMATDESCRIPTOR pfd =
		{
			sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
			1, // version number
			PFD_DRAW_TO_WINDOW | // support window
			PFD_SUPPORT_OPENGL | // support OpenGL
			PFD_DOUBLEBUFFER, // double buffered
			PFD_TYPE_RGBA, // RGBA type
			32, // 32-bit color depth
			0, 0, 0, 0, 0, 0, // color bits ignored
			0, // no alpha buffer
			0, // shift bit ignored
			0, // no accumulation buffer
			0, 0, 0, 0, // accum bits ignored
			32, // 32-bit z-buffer
			0, // no stencil buffer
			0, // no auxiliary buffer
			PFD_MAIN_PLANE, // main layer
			0, // reserved
			0, 0, 0 // layer masks ignored
		};
		int m_GLPixelIndex;
		m_GLPixelIndex = ChoosePixelFormat(hDC, &pfd);

		if (m_GLPixelIndex == 0) // Let's choose a default index.
		{
			m_GLPixelIndex = 1;

			if (DescribePixelFormat(hDC, m_GLPixelIndex, sizeof(PIXELFORMATDESCRIPTOR), &pfd) == 0)
			{
				return FALSE;
			}
		}

		if (SetPixelFormat(hDC, m_GLPixelIndex, &pfd) == FALSE)
		{
			return FALSE;
		}

		return TRUE;
	}


	BOOL CBKOscScrOGL::create_context()
	{
		BOOL bRet = FALSE;

		if (hGLRC) //каждый раз пересоздаЄм контекст
		{
			wglDeleteContext(hGLRC);
			hGLRC = wglCreateContext(m_HDC);

			if (hGLRC)
			{
				bRet = wglMakeCurrent(m_HDC, hGLRC);
			}
		}

		return bRet;
	}

	void CBKOscScrOGL::BKOSC_OnDisplay(HWND hwndScreen, SAMPLE_TYPE * inBuf, int inLen)
	{
		GLfloat s = (GLfloat) inLen / 2;

		if (!wglMakeCurrent(m_HDC, hGLRC))
		{
			if (!create_context())
			{
				return;
			}
		}

		glViewport(0, 0, m_cx, m_cy);
		GLfloat xL = -1.0, yL = 0.5;
		GLfloat xR = -1.0, yR = -0.5;
		//теперь надо сформировать массивы вертексов.
		m_pVerticesL[0] = xL;
		m_pVerticesL[1] = yL;
		m_pVerticesR[0] = xR;
		m_pVerticesR[1] = yR;

		for (int i = 0, j = 0, kL = 2, kR = 2; i < inLen; ++i)
		{
			//рисуем левый канал -32768..32767 => 0..1
			xR = xL = (GLfloat)i / s - 1.001;
			yL = ((GLfloat)inBuf[j++] + FLOAT_BASE_HALF) / FLOAT_BASE;
			m_pVerticesL[kL++] = xL;
			m_pVerticesL[kL++] = yL;
			//рисуем правый канал -32768..32767 => -1..0
			yR = ((GLfloat)inBuf[j++] + FLOAT_BASE_HALF) / FLOAT_BASE - 1.0;
			m_pVerticesR[kR++] = xR;
			m_pVerticesR[kR++] = yR;
		}

		glClearColor(0.0, 0.0, 0.0, 0.0); //очистка экрана
		glClear(GL_COLOR_BUFFER_BIT);
		glEnableClientState(GL_COLOR_ARRAY);
		glEnableClientState(GL_VERTEX_ARRAY);
		glColorPointer(3, GL_FLOAT, 0, colors3);
		glVertexPointer(2, GL_FLOAT, 0, vertices2);
		glDrawElements(GL_LINES, 6, GL_UNSIGNED_INT, indices1);
		glDisableClientState(GL_COLOR_ARRAY);
		glColor3f(0.0, 1.0, 0.0);
		glVertexPointer(2, GL_FLOAT, 0, m_pVerticesL);
		glDrawElements(GL_LINE_STRIP, inLen + 1, GL_UNSIGNED_INT, m_pIndices2);
		glVertexPointer(2, GL_FLOAT, 0, m_pVerticesR);
		glDrawElements(GL_LINE_STRIP, inLen + 1, GL_UNSIGNED_INT, m_pIndices2);
		glDisableClientState(GL_VERTEX_ARRAY);
		glFlush();
		SwapBuffers(m_HDC);
	}

};