/*
* SACD Decoder plugin
* Copyright (c) 2011-2024 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 _SACD_READER_H_INCLUDED
#define _SACD_READER_H_INCLUDED

#include "sacd_config.h"
#include "sacd_media.h"

enum track_e {
	TRACK_SELECTED = -1,
	TRACK_CUESHEET = 0
};

enum access_mode_e {
	ACCESS_MODE_NULL                = 0,
	ACCESS_MODE_TWOCH               = 1 << 0,
	ACCESS_MODE_MULCH               = 1 << 1,
	ACCESS_MODE_SINGLE_TRACK        = 1 << 2,
	ACCESS_MODE_EDITED_MASTER_TRACK = 1 << 3,
};

enum class media_type_e {
	INVALID = -1,
	ISO     = 0,
	DSDIFF  = 1,
	DSF     = 2,
	WAVPACK = 3
};

enum class frame_type_e {
	INVALID = -1,
	DSD     = 0,
	DST     = 1
};

enum class frame_span_e {
	NO_TRACK   = 0,
	PRE_TRACK  = 1,
	IN_TRACK   = 2,
	POST_TRACK = 3
};

enum area_id_e {
	AREA_NULL  = 0,
	AREA_TWOCH = 1 << 0,
	AREA_MULCH = 1 << 1,
	AREA_BOTH  = AREA_TWOCH | AREA_MULCH
};

class sacd_reader_t {
public:
	sacd_reader_t() {};
	virtual ~sacd_reader_t() {};
	virtual	uint32_t get_track_count(uint32_t mode = 0) = 0;
	virtual	uint32_t get_track_number(uint32_t track_index) = 0;
	virtual int get_channels(uint32_t track_number = TRACK_SELECTED) = 0;
	virtual int get_loudspeaker_config(uint32_t track_number = TRACK_SELECTED) = 0;
	virtual int get_samplerate(uint32_t track_number = TRACK_SELECTED) = 0;
	virtual int get_framerate(uint32_t track_number = TRACK_SELECTED) = 0;
	virtual double get_duration(uint32_t track_number = TRACK_SELECTED) = 0;
	virtual bool is_dst(uint32_t track_number = TRACK_SELECTED) { return false; };
	virtual bool is_gapless(uint32_t track_number = TRACK_SELECTED) { return true; };
	virtual void set_mode(uint32_t selector, bool is_set = true) = 0;
	virtual bool open(sacd_media_t* media) = 0;
	virtual bool close() = 0;
	virtual	bool select_track(uint32_t track_number) = 0;
	virtual bool set_track_span(uint32_t span_frames) { return false; };
	virtual std::tuple<bool, size_t, frame_type_e, frame_span_e> read_frame(uint8_t* frame_data, size_t frame_size) = 0;
	virtual bool seek(double seconds) = 0;
	virtual void get_info(uint32_t track_number, file_info& info) = 0;
	virtual void set_info(uint32_t track_number, const file_info& info) {};
	virtual void get_albumart(uint32_t albumart_id, vector<t_uint8>& albumart_data) {};
	virtual void set_albumart(uint32_t albumart_id, const vector<t_uint8>& albumart_data) {};
	virtual void commit() {};
	virtual double get_instant_bitrate() {
		return 0.0;
	};
	virtual void get_base_info(uint32_t track_number, file_info& info) {
		info.set_length(get_duration(track_number));
		info.info_set_int("channels", get_channels(track_number));
		info.info_set_bitrate((((t_int64)get_samplerate(track_number) * (t_int64)get_channels(track_number)) + 500) / 1000);
		info.info_set_int("samplerate", get_samplerate(track_number));
		info.info_set_int("bitspersample", 1);
		pfc::string_formatter(codec);
		codec << (is_dst(track_number) ? "DST" : "DSD");
		codec << get_samplerate(track_number) / 44100;
		info.info_set("codec", codec);
		info.info_set("encoding", "lossless");
	}
};

#endif
