#include "dsd_source.h"

dsd_source_t::dsd_source_t() : dsd_path_t () {
}

asio_state_e dsd_source_t::get_state() {
	return p_control ? p_control->state : ASIO_STATE_UNKNOWN;
}

void dsd_source_t::command(dsdcmd_t cmd) {
	switch (cmd.id) {
	case dsdcmd_source_init:
		create_control_channel();
		break;
	case dsdcmd_source_free:
		close_control_channel();
		close_dsddata_channel();
		break;
	case dsdcmd_decode_init:
		create_dsddata_channel();
		break;
	case dsdcmd_playback_seek:
	case dsdcmd_playback_stop:
		flush_dsddata_channel();
		break;
	default:
		break;
	}
	if (p_control) {
		switch (cmd.id) {
		case dsdcmd_decode_init:
		case dsdcmd_playback_start:
			p_control->cmd.id           = cmd.id;
			p_control->cmd.channels     = cmd.channels;
			p_control->cmd.samplerate   = cmd.samplerate;
			p_control->cmd.use_dsd_path = cmd.use_dsd_path;
			break;
		case dsdcmd_decode_free:
		case dsdcmd_playback_stop:
			p_control->cmd.id           = cmd.id;
			p_control->cmd.use_dsd_path = cmd.use_dsd_path;
			break;
		case dsdcmd_playback_seek:
		case dsdcmd_playback_pause:
		case dsdcmd_playback_resume:
			p_control->cmd.id = cmd.id;
			break;
		}
	}
}

void dsd_source_t::write(int channels, uint8_t* dsd_data, int dsd_size) {
	if (p_dsddata) {
		int pipe_size = p_dsddata->attr.pipe_pace * (dsd_size / channels);
		acquire();
		if (p_dsddata->attr.pipe_write_offset + pipe_size > DSD_DATA_SIZE) {
			p_dsddata->attr.pipe_end = p_dsddata->attr.pipe_write_offset;
			p_dsddata->attr.pipe_write_offset = 0;
		}
		p_dsddata->attr.pipe_write_offset += pipe_size;
		p_dsddata->attr.pipe_size += pipe_size;
		release();
		uint8_t* pipe_ptr = p_dsddata->pipe_data + p_dsddata->attr.pipe_write_offset - pipe_size;
		for (int sample = 0; sample < dsd_size / channels; sample++) {
			for (int ch = 0; ch < channels; ch++) {
				pipe_ptr[sample * p_dsddata->attr.pipe_pace + ch] = dsd_data[sample * channels + ch];
			}
			for (int ch = channels; ch < p_dsddata->attr.pipe_pace; ch++) {
				pipe_ptr[sample * p_dsddata->attr.pipe_pace + ch] = DSD_SILENCE_BYTE;
			}
		}
	}
}
