/* CSL - Common Sound Layer
 * Copyright (C) 2000-2001 Stefan Westerfeld and Tim Janik
 *
 * This library 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 of the License, or (at your option) any later version.
 *
 * This library 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 this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA.
 */
#ifndef __CSL_PCM_H__
#define __CSL_PCM_H__


#include	<csl/csldefs.h>
#include	<csl/cslmain.h>

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

/**
 * @file
 * This file defines the CSL API functions related to PCM data.
 */

/* --- CSL PCM API --- */

/**
 * An opaque type used as a handle to API functions that work with PCM streams.
 *
 * @short PCM stream type.
 */
typedef	struct _CslPcmStream	CslPcmStream;

/**
 * A type used to store status information related to PCM streams.
 *
 * @short PCM stream status type.
 */
typedef	struct _CslPcmStatus	CslPcmStatus;

/**
 * Data type for specifying PCM format.
 *
 * @see csl_pcm_open_output
 * @see csl_pcm_open_input
 * @see csl_pcm_get_format
 * @short PCM data format type.
 */
typedef enum		/* keep in sync with cslarts.idl */
{
  /** size (obligatory) */
  CSL_PCM_FORMAT_SIZE_8                         = 0x0008,
  CSL_PCM_FORMAT_SIZE_16                        = 0x0010,
  CSL_PCM_FORMAT_SIZE_32                        = 0x0020,
  CSL_PCM_FORMAT_SIZE_MASK                      = 0x00FF,
  
  /** endianess (obligatory for size > 8) */
  CSL_PCM_FORMAT_ENDIAN_LE                      = 0x0100,
  CSL_PCM_FORMAT_ENDIAN_BE                      = 0x0200,
  CSL_PCM_FORMAT_ENDIAN_MASK                    = 0x0F00,
  
  /** encoding (obligatory) */
  CSL_PCM_FORMAT_ENCODING_LINEAR_SIGNED         = 0x1000,
  CSL_PCM_FORMAT_ENCODING_LINEAR_UNSIGNED       = 0x2000,
  CSL_PCM_FORMAT_ENCODING_FLOAT                 = 0x3000,
  CSL_PCM_FORMAT_ENCODING_MASK                  = 0xF000,
  
  /** aliases */
  CSL_PCM_FORMAT_U8                             = 0x2008,
  CSL_PCM_FORMAT_S16_LE                         = 0x1110,
  CSL_PCM_FORMAT_S16_BE                         = 0x1210,
  CSL_PCM_FORMAT_FLOAT_LE                       = 0x3120,
  CSL_PCM_FORMAT_FLOAT_BE                       = 0x3220,
} CslPcmFormatType;

/* defines for host endianess */
#if CSL_BYTE_ORDER == CSL_LITTLE_ENDIAN
#define CSL_PCM_FORMAT_S16_HE		CSL_PCM_FORMAT_S16_LE
#define	CSL_PCM_FORMAT_FLOAT_HE		CSL_PCM_FORMAT_FLOAT_LE
#else /* CSL_BYTE_ORDER == CSL_LITTLE_ENDIAN */
#define CSL_PCM_FORMAT_S16_HE		CSL_PCM_FORMAT_S16_BE
#define	CSL_PCM_FORMAT_FLOAT_HE		CSL_PCM_FORMAT_FLOAT_BE
#endif

/**
 * A type used to store status information related to PCM streams.
 *
 * @warning This is still subject to change.
 * @short PCM stream status type.
 */
struct _CslPcmStatus
{
  /** sampling rate in samples/second */
  unsigned int	   rate;
  /** number of channels */
  unsigned int	   n_channels;
  /** sample size in bits. (0==float32bit) n_bytes_per_value = (n_bits + 7) / 8 */
  unsigned int	   n_bits;
  CslPcmFormatType format;
  /** buffer_size = n_buffer_packets * packet_size * (n_bits + 7) / 8 */
  unsigned int     buffer_size; /* in bytes */
  /** # of bytes left to read or write */
  unsigned int	   n_bytes_available;
  unsigned int	   packet_size;
  unsigned int	   n_buffer_packets;
  /** # of empty packets left to read or write */
  unsigned int	   n_packets_available;
  unsigned int	   padding[128];
  /* server side latency in seconds
   * (rate*server_latency==n_values_queued_on_server)
   */
  float		   server_latency;
};

CslErrorType csl_pcm_open_output		(CslDriver	 *driver,
						 const char      *role,
						 unsigned int	  rate,
						 unsigned int	  n_channels,
						 CslPcmFormatType format,
						 CslPcmStream	**stream_p);
CslErrorType csl_pcm_open_input			(CslDriver	 *driver,
						 const char	 *role,
						 unsigned int	  rate,
						 unsigned int	  n_channels,
						 CslPcmFormatType format,
						 CslPcmStream   **stream_p);
/* for coupled streams:
 * flush affects all
 * sync affects all
 * behaviour for in-streams:
 * flush: empty capture queue
 * sync: NOP? (flush?)
 */
CslPcmFormatType csl_pcm_get_format		(CslPcmStream	 *stream);
void		 csl_pcm_close			(CslPcmStream	 *stream);

/* return n_bytes processed or -1==error (FIXME: need is_broken()) */
int		 csl_pcm_read			(CslPcmStream    *stream,
						 unsigned int     n_bytes,
						 void            *bytes);
int              csl_pcm_write                  (CslPcmStream    *stream,
						 unsigned int     n_bytes,
						 void            *bytes);

CslErrorType	 csl_pcm_get_status		(CslPcmStream	 *stream,
						 CslPcmStatus	 *status);
CslErrorType	 csl_pcm_flush			(CslPcmStream	 *stream);
CslErrorType	 csl_pcm_sync			(CslPcmStream	 *stream);


/* --- advanced API --- */
/* buffer_size always in n_bytes */
CslErrorType	csl_pcm_set_title		(CslPcmStream	*stream,
						 const char	*title);
char*		csl_pcm_dup_title		(CslPcmStream	*stream); /* needs csl_free() */
CslErrorType	csl_pcm_set_stream_mode		(CslPcmStream	*stream,
						 unsigned int	 buffer_size,
						 unsigned int	 byte_watermark);
void		csl_pcm_get_stream_settings	(CslPcmStream	*stream,
						 unsigned int	*buffer_size_p,
						 unsigned int	*byte_watermark_p);
CslErrorType	csl_pcm_set_packet_mode		(CslPcmStream	*stream,
						 unsigned int	 n_packets,
						 unsigned int	 packet_size,
						 unsigned int	 packet_watermark);
void		csl_pcm_get_packet_settings	(CslPcmStream	*stream,
						 unsigned int	*n_packets_p,
						 unsigned int	*packet_size_p,
						 unsigned int	*packet_watermark_p);


/* --- proposed --- */
#define CSL_PCM_CHANNEL_FRONT_LEFT	"<front-left>"
#define CSL_PCM_CHANNEL_FRONT_RIGHT	"<front-right>"
#define CSL_PCM_CHANNEL_CENTER		"<center>"
#define CSL_PCM_CHANNEL_REAR_LEFT	"<rear-left>"
#define CSL_PCM_CHANNEL_REAR_RIGHT	"<rear-right>"
#define CSL_PCM_CHANNEL_SUB_WOOFER	"<sub-woofer>"
#if 0
/**
 * Channel names used for advanced API functions than manipulate
 * channel mappings.
 *
 * @see csl_pcm_list_channel_mappings
 * @see csl_pcm_set_channel_mapping
 * @see csl_pcm_dup_channel_mapping
 * @short Channel names.
 */

CslErrorType	csl_pcm_set_channel_mapping	(CslPcmStream	*stream,
						 unsigned int	 channel,
						 const char	*mapping);
char*		csl_pcm_dup_channel_mapping	(CslPcmStream	*stream,
						 unsigned int	 channel);
char**		csl_pcm_list_channel_mappings	(CslDriver	*driver,
						 unsigned int	*n_maps_p);
#endif

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* __CSL_PCM_H__ */ /* vim:set ts=8 sw=2 sts=2: */
