/*
 * Copyright (c) 2001-2003 Shiman Associates Inc. All Rights Reserved.
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */

#ifndef _ANX_INTERNAL_H
#define _ANX_INTERNAL_H

#include "mixer.h"
#include "buffer.h"

#define HALF_UINT32_MAX 2147483647U

/*
 * Include platform-dependent header below.  ANX_* defines are in the
 * Imakefile.  
 * 
 */

/*** PLATFORM DEPENDENT SECTION *******************/
#if defined(ANX_OSS)
# include "oss.h"
#elif defined(ANX_SOLARIS)
# include "solaris.h"
#elif defined(ANX_DIRECTSOUND)
# include "directsound.h"
#endif
/*** END PLATFORM DEPENDENT ***********************/


/* stream state definitions */
#define STOP_STATE  0
#define PAUSE_STATE 1
#define PLAY_STATE  2
#define START_STATE 3

enum res_state
{
    INACTIVE = 0,
    INACTIVE_PENDING = 1,
    ACTIVE_PENDING = 2,
    ACTIVE = 3
};

struct anx_state
{
    /*** PLATFORM DEPENDENT SECTION *******************/

    /* must define symbol pdstate */
#if defined(ANX_OSS)
    struct oss_state pdstate;
#elif defined(ANX_SOLARIS)
    struct solaris_audio_state pdstate;
#elif defined(ANX_DIRECTSOUND)
    struct directsound_state pdstate;
#endif

    /*** END PLATFORM DEPENDENT ***********************/

    int32 device_instance;

    /* resource state */
    enum res_state res_state;
    int32 res_state_ito_s;
    int res_state_usectr;
    int res_state_ito_changed;
    uint32 res_state_last_s;
    
    /* configured format */
    uint8 play_format;
    uint8 play_resolution;
    uint8 play_channels;
    u_int16 play_sample_rate; 
    u_int16 play_bpstc; /* bytes per sample times channels */
    int play_clkid;

    uint8 rec_format;
    uint8 rec_resolution;
    uint8 rec_channels;
    u_int16 rec_sample_rate; 
    u_int16 rec_bpstc; /* bytes per sample times channels */
    int rec_clkid;
    uint32 rec_period;

    /* capabilities */
    int is_full_duplex;
    int is_sample_accurate;
    int no_loop_record;
    
    /* statistics */
    u_int32 played_bytes;
    u_int32 rec_bytes;
    uint32 rec_mts;
    uint32 rec_seq;
    uint32 play_mts;

    /* buffering */
    uint32 buftime_ms;
    uint32 buftime_mt;
    int    valid_refmark;
    uint32 mcref;
    uint32 mcnow;
    uint32 mtref;
    uint32 mtnow;
    int32  dropped;
    int32  gaps; /* number of gaps in the audio - contiguous dropped
                    packets count as one */
    int    gapping; /* boolean: true if currently in a gap */
    int    rebuffer;
    
    /* playback buffer */
    struct anx_buffer* play_buffer;

    /* mixer */
    struct mixer_channel mch[ALLOCATED_MIX_CH];
    int main_mix_ch;
    int dac_ch;
    int mic_ch;
    int cd_ch;

    /* stream state information */
    int play_state;
    int rec_state;
    int sink_active;
    int source_active;

    /* capabilities */
    int cap_io_diff_fmt; /* boolean: input and output can be different
                          * formats */
    
    /* DROP **********/
    double zero_mts;
    double drop_until;
    /*****************/
    
    /* ports */
    int32 reaction;
    int32 audio_sink;
    int32 audio_source;

    /* master clock sample counter */
    struct mas_mc_clkval* scnt;
    double expected_rate;
};


/*
 * PLATFORM DEPENDENT ACTIONS
 *
 * These must be implemented on any new platform.
 *
 */

extern int32 pdanx_init_library( void );
extern int32 pdanx_init_instance( struct anx_state* state, void* predicate );
extern int32 pdanx_exit_instance( struct anx_state* state, void* predicate );
extern int32 pdanx_open_resource( struct anx_state* state );
extern int32 pdanx_close_resource( struct anx_state* state );
extern int32 pdanx_configure_resource( struct anx_state *state, int32 portnum );
extern int32 pdanx_change_res_state( struct anx_state* state, enum res_state res_state );
extern int32 pdanx_exit_library( void );
extern int32 pdanx_configure_port( struct anx_state* state, int32 portnum, struct mas_data_characteristic* dc );
extern int32 pdanx_disconnect_port( struct anx_state* state, int32 portnum );
extern int32 pdanx_playback_start( struct anx_state* state );
extern int32 pdanx_playback_stop( struct anx_state* state );
extern int32 pdanx_playback_pause( struct anx_state* state );
extern int32 pdanx_playback_poll( struct anx_state* state, struct mas_data* data );
extern int32 pdanx_record_start( struct anx_state* state );
extern int32 pdanx_record_stop( struct anx_state* state );
extern int32 pdanx_record_pause( struct anx_state* state );
extern int32 pdanx_record_poll( struct anx_state* state, struct mas_data** data_ptr );
extern int32 pdanx_show_state( struct anx_state* state );
extern int32 pdanx_get( struct anx_state* state, char* key, struct mas_package* arg, struct mas_package* r_package );
extern int32 pdanx_set( struct anx_state* state, char* key, struct mas_package* arg );
extern int32 pdanx_set_mixer_volume(struct anx_state* state, int ch_id );
extern int32 pdanx_get_mixer_volume(struct anx_state* state, int ch_id );
extern int32 pdanx_set_recording_source(struct anx_state* state, int ch_id );
extern int32 pdanx_get_recording_source(struct anx_state* state );
extern uint32 pdanx_get_sample_count(struct anx_state* state, struct mas_mc_clkval* scnt );

#endif /* _ANX_INTERNAL_H */
