/*****************************************************************************
 * csri: common subtitle renderer interface
 *****************************************************************************
 * Copyright (C) 2007  David Lamparter
 * All rights reserved.
 * 	
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 *  - Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  - Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *  - The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
 ****************************************************************************/

/** \file csri.h - main CSRI (common subtitle renderer interface) include.
 * $Id: csri.h 45 2007-06-20 01:00:40Z equinox $ */

#ifndef _CSRI_H
/** \cond */
#define _CSRI_H 20070119
/** \endcond */

#include <stddef.h>			/* ptrdiff_t */

#ifdef __cplusplus
extern "C" {
#endif

#ifndef CSRIAPI
/** CSRI API attributes.
 * defaults to \c extern.
 */
#define CSRIAPI extern
#endif

/** \defgroup base CSRI base API. */
/*@{*/

/** pixel format specification for frames */
enum csri_pixfmt {
	CSRI_F_RGBA = 0,
	CSRI_F_ARGB,
	CSRI_F_BGRA,
	CSRI_F_ABGR,

	CSRI_F_RGB_ = 0x100,
	CSRI_F__RGB,
	CSRI_F_BGR_,			/**< Windows "RGB32" */
	CSRI_F__BGR,

	CSRI_F_RGB  = 0x200,
	CSRI_F_BGR,			/**< Windows "RGB24" */

	CSRI_F_AYUV = 0x1000,
	CSRI_F_YUVA,
	CSRI_F_YVUA,
	
	CSRI_F_YUY2 = 0x1100,

	CSRI_F_YV12A = 0x2011,		/**< planar YUV 2x2 + alpha plane */
	CSRI_F_YV12 = 0x2111		/**< planar YUV 2x2 */
};

#define csri_is_rgb(x) ((x) < 0x1000)
#define csri_is_yuv(x) ((x) >= 0x1000)
#define csri_is_yuv_planar(x) ((x) >= 0x2000)
#define csri_get_yuv_planar_xred(x) (0xf & (x))
#define csri_get_yuv_planar_yred(x) (0xf & ((x) >> 4))
#define csri_is_yuv_packed(x) ((x) >= 0x1000 && (x) < 0x2000)
#define csri_has_alpha(x) (((x) & 0xfff) < 0x100)

/** frame/image format specification pre-fed to the renderer */
struct csri_fmt {
	/** format to be used */
	enum csri_pixfmt pixfmt;
	/** image width, full frame.
	 *
	 * This should specify the full size of the frame.
	 * Specifying the video sub-size (in case of added black
	 * borders) is left to an extension.
	 */
	unsigned width;
	/** image height */
	unsigned height;
};

/** single frame to be fed to the renderer. */
struct csri_frame {
	/** frame format.
	 * It is an application bug if this differs from the one
	 * passed in struct #csri_fmt to csri_query_fmt()
	 */
	enum csri_pixfmt pixfmt;
	/** the frame's data.
	 * Packed formats only use planes[0]; planar formats
	 * have the data ordered as Y, U, V[, A].
	 *
	 * Also note that the topmost line always comes first.
	 * The Windows biHeight strange-ity is \a NOT duplicated.
	 */
	unsigned char *planes[4];
	/** strides for the individual planes.
	 * Stride means full byte offset, i.e. do \a not add 
	 * frame width
	 */
	ptrdiff_t strides[4];
};

#ifndef CSRI_OWN_HANDLES
/** opaque renderer data */
typedef void csri_rend;
/** opaque instance data */
typedef void csri_inst;
#endif

#ifdef DOXYGEN
/** disable the emission of the csri_rend and csri_inst typedefs.
 * define this if you are in a renderer and are typedef'ing
 * csri_rend and csri_inst to your own structs.
 */
#define CSRI_OWN_HANDLES
#endif

/** renderer description.
 * \ingroup loader
 */
struct csri_info {
	/** an identifier for the renderer.
	 * - MUST match the regular expression
	 *   \code ^[a-zA-Z]([a-zA-Z0-9_]*[a-zA-Z0-9])? \endcode
	 *   i.e. consists only of letters, numbers and underscores;
	 *   must start with a letter and doesnt have an underscore
	 *   as the last character.
	 */
	const char *name;
	/** an identifier to the exact version of the renderer.
	 * most likely a version number or revision identifier.
	 *
	 * The helper library does a strcmp over this field in order
	 * to order multiple instances of the same renderer. Use
	 * higher-byte-value strings for newer renderers.
	 */
	const char *specific;

	/** a nice name to be presented to the user */
	const char *longname;
	/** the renderer's author */
	const char *author;
	/** a copyright string. Copyright (c) 2042 by Mr. Nice Guy */
	const char *copyright;
};

/** data of extension-dependent type.
 * The field to be used MUST be specified in the extension where it is used.
 */
union csri_vardata {
	long lval;
	double dval;
	const char *utf8val;
	void *otherval;
};

/** extension identifier.
 * This follows reverse DNS syntax, i.e.:
 * \code root.branch.leaf \endcode
 * you can either reverse a registered domain name, e.g.
 * \code com.microsoft.csri.usegdiplus \endcode
 * or ask the CSRI maintainers to assign a namespace to you.
 *
 * currently registered namespaces are:
 *
 * \code
 * csri.* - official extensions
 * asa.*  - custom extensions of the asa renderer
 * \endcode
 */
typedef const char *csri_ext_id;

/** script loading parameters.
 * each flag MUST have an associated extension, which can be queried
 * with csri_query_ext(). If the open flag constitutes an extension on its
 * sole own, csri_query_ext() can return a meaningless non-NULL value for
 * it.
 *
 * The data field used must be specified.
 *
 * An extension can have multiple flags. In that case, the flags should have
 * the extension name as common prefix, separated with a dot.
 *
 * A renderer MUST ignore unknown open flags. It MUST NOT return an error
 * just because it does not support a particular flag.
 */
struct csri_openflag {
	/** flag name */
	csri_ext_id name;
	/** flag data argument */
	union csri_vardata data;
	/** link to next flag */
	struct csri_openflag *next;
};

/** load a script from a file.
 * \param renderer the handle to the renderer
 * \param filename the path to the file to be loaded. \n
 *   The filename should be encoded as UTF-8. Windows renderers are
 *   expected to convert it to UTF-16 and use the Unicode Windows API
 *   functions.
 * \param flags a linked list of open flags. \n
 *   The caller manages memory allocation, i.e. static allocation is OK.
 * \return the renderer instance handle, or NULL on error.
 */
CSRIAPI csri_inst *csri_open_file(csri_rend *renderer,
	const char *filename, struct csri_openflag *flags);

/** load a script from memory.
 * \param renderer the handle to the renderer
 * \param data pointer to the first data byte. \n
 *   The caller manages memory allocation and should free the data after
 *   calling csri_open_mem(). If the renderer needs to keep the data, it
 *   must copy it. \n
 *   The renderer is not allowed to write to the data.
 * \param length length, in bytes, of the data
 * \param flags see csri_open_file()
 * \return the render instance handle, or NULL on error.
 */

CSRIAPI csri_inst *csri_open_mem(csri_rend *renderer,
	const void *data, size_t length, struct csri_openflag *flags);

/** close a renderer instance.
 * \param inst the instance handle.
 */
CSRIAPI void csri_close(csri_inst *inst);


/** query / set the image format and size.
 * \param inst the renderer instance handle
 * \param fmt the format and image size to be used
 * \return 0 if the format was successfully set,
 *   any other value in case of error.
 */
CSRIAPI int csri_request_fmt(csri_inst *inst, const struct csri_fmt *fmt);

/** render a single frame
 * \param inst the renderer instance handle
 * \param frame frame data to render to
 * \param time associated timestamp of the frame
 */
CSRIAPI void csri_render(csri_inst *inst, struct csri_frame *frame,
	double time);


/** query for an extension.
 * \param rend the renderer handle
 * \param extname the extension's identifier
 * \return NULL if the extension is not supported,
 *   a pointer to extension-specific data otherwise
 *
 * The data pointed to by the return value does not neccessarily need to
 * have any meaning; An extension that does not need to return data
 * can return a pointer to whatever it wants, as long as that pointer is
 * not NULL.
 *
 * In the usual case, the pointer is supposed to point to a struct with
 * function pointers and other information as needed.
 */
CSRIAPI void *csri_query_ext(csri_rend *rend, csri_ext_id extname);

/*@}*/

/** \defgroup loader CSRI loader API.
 *
 * These functions locate renderers based on given parameters.
 *
 * <b>Renderers must implement these functions as well.</b>
 *
 * They are used by the library to grab renderer information
 * from a shared object; and also this way a single renderer
 * can be linked directly into an appliaction.
 */
/*@{*/

/** get renderer information
 * \param rend the renderer handle
 * \return information about the renderer, or NULL in case the renderer
 *   encountered an internal error.
 */
CSRIAPI struct csri_info *csri_renderer_info(csri_rend *rend);

/** try to load a given renderer
 * \param name the name of the renderer, as in csri_info.name
 * \param specific the specific version of the renderer,
 *   as in csri_info.specific;\n
 *   alternatively NULL if any version of the renderer is ok.
 * \return a handle to the renderer if it was successfully loaded,
 *   NULL otherwise.
 */
CSRIAPI csri_rend *csri_renderer_byname(const char *name,
	const char *specific);

/** try to find an implementation of the given extensions.
 * \param next number of extensions pointed to by ext
 * \param ext array of extensions to search for
 * \return a handle to a renderer supporting ALL of the
 *   extensions, NULL if none was found.
 */
CSRIAPI csri_rend *csri_renderer_byext(unsigned n_ext, csri_ext_id *ext);

/** get the default (highest priority) renderer
 * \return a handle to the default renderer, or NULL if
 *   no renderer is installed.
 * 
 * Together with csri_renderer_next(), this can be used
 * to enumerate all installed renderers.
 */
CSRIAPI csri_rend *csri_renderer_default();

/** get the next lower priority renderer
 * \param prev the current renderer
 * \return the renderer with the next lower priority than
 *   the one named in prev, or NULL if prev is the last
 *   renderer installed.
 */
CSRIAPI csri_rend *csri_renderer_next(csri_rend *prev);

/*@}*/

#ifdef __cplusplus
}
#endif

#endif /* _CSRI_H */
