/*
* SACD Decoder plugin
* Copyright (c) 2011-2015 Maxim V.Anisiutkin <maxim.anisiutkin@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#ifndef _DSD_PATH_H_INCLUDED
#define _DSD_PATH_H_INCLUDED

#include <stdint.h>
#include <windows.h>
#include <tchar.h>
#include "dsd_method.h"

enum dsdcmd_e {
	dsdcmd_unknown,
	dsdcmd_source_init,
	dsdcmd_source_free,
	dsdcmd_decode_init,
	dsdcmd_decode_free,
	dsdcmd_playback_start,
	dsdcmd_playback_stop,
	dsdcmd_playback_seek,
	dsdcmd_playback_pause,
	dsdcmd_playback_resume,
	dsdcmd_sink_init,
	dsdcmd_sink_free,
};

class dsdcmd_t {
public:
	dsdcmd_e id;
	int      channels;
	int      samplerate;
	bool     use_dsd_path;
	dsdcmd_t(dsdcmd_e id) {
		this->id           = id;
		this->use_dsd_path = false;
	}
	dsdcmd_t(dsdcmd_e id, int channels, int samplerate, bool use_dsd_path = false) {
		this->id           = id;
		this->channels     = channels;
		this->samplerate   = samplerate;
		this->use_dsd_path = use_dsd_path;
	}
};

#define DSD_SILENCE_BYTE 0x69

#define DSD_DATA_PACE 6
#define DSD_DATA_SIZE (256 * 1024 * 1024)
#define DSD_READ_SIZE (256 * 1024)
#define DSD_WAIT_TIME 1000

struct dsd_control_t {
	dsdcmd_t     cmd;
	asio_state_e state;
};

struct dsd_dsdattr_t {
	int pipe_pace;
	volatile int pipe_size;
	volatile int pipe_end;
	volatile int pipe_read_offset;
	volatile int pipe_write_offset;
};

struct dsd_dsddata_t {
	volatile dsd_dsdattr_t attr;
	#pragma pack(16)
	uint8_t pipe_data[DSD_DATA_SIZE + DSD_READ_SIZE];
	#pragma pack()
};

class dsd_path_t {
public:
	dsd_path_t();
	void acquire();
	void release();
	dsd_control_t* get_control() const;
	dsd_dsddata_t* get_dsddata() const;
protected:
	static const LPCTSTR control_path;
	static const LPCTSTR dsddata_path;
	static const LPCTSTR access_mutex;
	HANDLE hMutex;
	HANDLE hControl;
	HANDLE hDsdData;
	dsd_control_t* p_control;
	dsd_dsddata_t* p_dsddata;
	DWORD create_control_channel();
	DWORD create_dsddata_channel();
	DWORD attach_control_channel();
	DWORD attach_dsddata_channel();
	void close_control_channel();
	void close_dsddata_channel();
	void flush_dsddata_channel();
};

#endif
