/*  input_plugin.h -  Use this to write input plugins
 *  Copyright (C) 1999-2002 Andy Lo A Foe <andy@loafoe.com>
 *
 *  This file is part of AlsaPlayer.
 *
 *  AlsaPlayer is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  AlsaPlayer 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
 *
 */

#ifndef __input_plugin_h__
#define __input_plugin_h__

#include "stream_info.h"

#include <pthread.h>

/**
 * Set this flag if your plugin is able to seek in the stream
 */
#define	P_SEEK		1

/** Set this flag if your plugin is able to do sample accurate seeking
 * in the stream. This is required for reverse speed playback.
 */
#define P_PERFECTSEEK	2

/**
 * Set this flag if your plugin is reentrant.
 */
#define	P_REENTRANT 	4

/**
 * Set this flag if the stream is file based (local disk file)
 */
#define P_FILEBASED	8

/**
 * Set this if the stream is a real stream e.g. HTTP or UDP based
 */
#define P_STREAMBASED	16

/**
 * Set minimal buffer
 */
#define P_BUFFERING	32

/*
 * Format of version number is 0x1000 + version
 * So 0x1001 is *binary* format version 1
 * THE VERSION NUMBER IS *NOT* A USER SERVICABLE PART!
 */

/**
 * The base version number of the scope plugin. Set at 0x1000.
 */
#define INPUT_PLUGIN_BASE_VERSION	0x1000

/**
 *  The version of the input plugin API. This should be incremented
 *  whenever structural changes are made to the API. This value should
 *  only be changed by the maintainers.
 */
#define INPUT_PLUGIN_VERSION	(INPUT_PLUGIN_BASE_VERSION + 16)

/**
 * This is a structure that keeps frequently used parameters of an
 * input instance. It also contains a pointer to any local_data
 * that might be allocated by the plugin itself.
 */
typedef struct _input_object
{
	/**
	 * Flag that should be set to 1 if your plugin is ready to accept
	 * play_block() callback
	 */
	int ready;
	/**
	 * Stream specific flags that should be set in the open() call.
	 * Read the description of the P_* definitions for details.
	 */
	int flags;
	/**
	 * The total number of blocks in the stream. Should be set in the
	 * open() call.
	 */
	int nr_blocks;
	/**
	 * The number of tracks, if any, in the stream. Should be set in
	 * the open() call.
	 */
	int nr_tracks;
	/**
	 * The number of PCM channels in the stream. Should always be 2
	 * at this time.
	 */
	int nr_channels;
	/**
	 * The block size in bytes. play_block() will be called with this
	 * value.
	 */
	int block_size;
	/** If your plugin needs extra space for its own variables assign the
	 * allocated data structure to this pointer
	 */
	void *local_data;
	/** Path of the currently played file
	 *
	 */
	char* path;
	/**
	 * The object mutex. Used to lock and unlock the data structures.
	 * Initialized and called from the HOST.
	 */
	pthread_mutex_t	object_mutex;
} input_object;


/**
 * input plugin binary version. Must be set to INPUT_PLUGIN_VERSION
 */
typedef int input_version_type;

/**
 * Capability flags for this plugin
 **/
typedef int input_flags_type;

/**
 * Init plugin
 */
typedef int(*input_init_type)(void);

/**
 * Prepare the plugin for removal
 */
typedef void(*input_shutdown_type)(void);

/**
 * Handle for plugin. Filled in by the host
 */
typedef void* input_plugin_handle_type;

/**
 * @param path Path to stream
 *
 * Returns a rating between 0.0 and 1.0 for how
 * well this plugin can handle the given path
 * 1.0 = Excellent
 * 0.0 = Huh?
 */
typedef float(*input_can_handle_type)(const char *path);

/**
 * @param obj input object
 * @param path path of stream to open
 *
 * Open stream */
typedef int(*input_open_type)(input_object *obj, const char *path);

/**
 * @param obj input object
 *
 * Close stream */
typedef void(*input_close_type)(input_object *obj);

/**
 * @param obj input object
 * @param buffer buffer where we should write the block to
 *
 * Play/decode a single block. This function should write exactly one block
 * to the buffer. If there is not enough PCM data to fill the block
 * it should be padded with zeros (silence).
 */
typedef int(*input_play_block_type)(input_object *obj, short *buffer);

/**
 * @param obj input object
 * @param block
 *
 * Seek to a specific block number
 */
typedef int(*input_block_seek_type)(input_object *obj, int block);

/**
 * @param obj input object
 *
 * Returns the block size in bytes
 */
typedef int(*input_block_size_type)(input_object *obj);

/**
 * @param obj input object
 *
 * Returns the total number of blocks in the stream */
typedef int(*input_nr_blocks_type)(input_object *obj);

/**
 * @param obj input object
 *
 * Returns the number of frames sample for in the stream (where a frame is
 * one singled sample for every channel). */
typedef int64_t (*input_frame_count_type)(input_object *obj);

/**
 * @param obj input object
 * @param block block number
 *
 * Returns the offset from the start time in centiseconds (100th of a second)
 * for the block given.
 */
typedef  long(*input_block_to_sec_type)(input_object *obj ,int block);

/**
 * @param obj input object
 *
 * Returns the sample rate of the stream
 */
typedef int(*input_sample_rate_type)(input_object *obj);

/**
 * @param obj input object
 *
 * Returns number of channels in the stream
 */
typedef int(*input_channels_type)(input_object *obj);

/**
 * @param obj input object
 * @param info pointer to stream_info structure
 *
 * Return stream info of the current stream. You should not allocate
 * space for the stream_info structure. The HOST will take care of that.
 */
typedef int(*input_stream_info_type)(input_object *obj,stream_info *info);

/**
 * @param obj input object
 *
 * Return number of tracks. Optional */
typedef int(*input_nr_tracks_type)(input_object *obj);

/* @param obj input object
 * @param track track to seek to
 *
 * Seek to a track. Optional
 */
typedef int(*input_track_seek_type)(input_object *obj, int track);


typedef struct _input_plugin
{
	/**
	 * Must be set to INPUT_PLUGIN_VERSION
	 */
	input_version_type version;
	/**
	 * Fixed flags for the plugin (P_*)
	 */
	input_flags_type	flags;
	/**
	 * Should point the a character array containing the name of this plugin
	 */
	const char *name;
	/**
	 * Should point to a character array containing the name of the
	 * author(s) of this plugin.
	 */
	const char *author;
	/**
	 * dlopen() handle of this plugin. Filled in by the HOST.
	 */
	void *handle;
	input_init_type init;
	input_shutdown_type shutdown;
	input_plugin_handle_type plugin_handle;
	input_can_handle_type can_handle;
	input_open_type open;
	input_close_type close;
	input_play_block_type play_block;
	input_block_seek_type block_seek;
	input_block_size_type block_size;
	input_nr_blocks_type nr_blocks;
	input_frame_count_type frame_count;
	input_block_to_sec_type block_to_sec;
	input_sample_rate_type sample_rate;
	input_channels_type channels;
	input_stream_info_type stream_info;
	input_nr_tracks_type nr_tracks;
	input_track_seek_type track_seek;
} input_plugin;

/**
 * Every input plugin should have an input_plugin_info() function that
 * returns a pointer to an input_plugin structure that is set up with
 * pointers to your implementations. If your plugin is compiled using
 * C++ make sure you 'extern "C"' the input_plugin_info() function or
 * else the HOST will not be able to load the plugin.
 */
typedef input_plugin*(*input_plugin_info_type)(void);

#ifdef __cplusplus
extern "C"
#endif
input_plugin* input_plugin_info (void);

#endif
