/*
 * ice_streamer_asf.h
 *
 *  Created on: Jun 29, 2012
 *      Author:
 */

#ifndef ice_streamer_H_
#define ice_streamer_H_

#include "libasf/asf.h"
#include "frost/frost_basictypes.h"
#include "ice/ice_media_player_types.h"
#include "frost_basicstring.h"
#include "frost/frost_mutex.h"
#include "frost/frost_threads.h"
#include "frost/frost_condvar.h"
#include "frost/frost_message_queue.h"
#include "frost/frost_semaphore.h"
#include "frost/frost_ipc_message.h"
#include <curl/curl.h>
#include <stdarg.h>
#include "frost_common.h"
#include "frost_list.h"
#include "frost_tree.h"
#include "frost_queue.h"

#define ICE_MEDIALIB_ENTRY_PROPERTY_MIME "mime"
#define ICE_MEDIALIB_ENTRY_PROPERTY_ID "id"
#define ICE_MEDIALIB_ENTRY_PROPERTY_URL "url"
#define ICE_MEDIALIB_ENTRY_PROPERTY_ARTIST "artist"
#define ICE_MEDIALIB_ENTRY_PROPERTY_ALBUM "album"
#define ICE_MEDIALIB_ENTRY_PROPERTY_TITLE "title"
#define ICE_MEDIALIB_ENTRY_PROPERTY_YEAR "date"
#define ICE_MEDIALIB_ENTRY_PROPERTY_TRACKNR "tracknr"
#define ICE_MEDIALIB_ENTRY_PROPERTY_GENRE "genre"
#define ICE_MEDIALIB_ENTRY_PROPERTY_BITRATE "bitrate"
#define ICE_MEDIALIB_ENTRY_PROPERTY_COMMENT "comment"
#define ICE_MEDIALIB_ENTRY_PROPERTY_COMMENT_LANG "commentlang"
#define ICE_MEDIALIB_ENTRY_PROPERTY_DURATION "duration"
#define ICE_MEDIALIB_ENTRY_PROPERTY_CHANNEL "channel"
#define ICE_MEDIALIB_ENTRY_PROPERTY_CHANNELS "channels"
#define ICE_MEDIALIB_ENTRY_PROPERTY_SAMPLE_FMT "sample_format"
#define ICE_MEDIALIB_ENTRY_PROPERTY_SAMPLERATE "samplerate"
#define ICE_MEDIALIB_ENTRY_PROPERTY_LMOD "lmod"
#define ICE_MEDIALIB_ENTRY_PROPERTY_GAIN_TRACK "gain_track"
#define ICE_MEDIALIB_ENTRY_PROPERTY_GAIN_ALBUM "gain_album"
#define ICE_MEDIALIB_ENTRY_PROPERTY_PEAK_TRACK "peak_track"
#define ICE_MEDIALIB_ENTRY_PROPERTY_PEAK_ALBUM "peak_album"
/** Indicates that this album is a compilation */
#define ICE_MEDIALIB_ENTRY_PROPERTY_COMPILATION "compilation"
#define ICE_MEDIALIB_ENTRY_PROPERTY_ALBUM_ID "album_id"
#define ICE_MEDIALIB_ENTRY_PROPERTY_ARTIST_ID "artist_id"
#define ICE_MEDIALIB_ENTRY_PROPERTY_TRACK_ID "track_id"
#define ICE_MEDIALIB_ENTRY_PROPERTY_ADDED "added"
#define ICE_MEDIALIB_ENTRY_PROPERTY_BPM "bpm"
#define ICE_MEDIALIB_ENTRY_PROPERTY_LASTSTARTED "laststarted"
#define ICE_MEDIALIB_ENTRY_PROPERTY_SIZE "size"
#define ICE_MEDIALIB_ENTRY_PROPERTY_IS_VBR "isvbr"
#define ICE_MEDIALIB_ENTRY_PROPERTY_SUBTUNES "subtunes"
#define ICE_MEDIALIB_ENTRY_PROPERTY_CHAIN "chain"
#define ICE_MEDIALIB_ENTRY_PROPERTY_TIMESPLAYED "timesplayed"
#define ICE_MEDIALIB_ENTRY_PROPERTY_PARTOFSET "partofset"
#define ICE_MEDIALIB_ENTRY_PROPERTY_PICTURE_FRONT "picture_front"
#define ICE_MEDIALIB_ENTRY_PROPERTY_PICTURE_FRONT_MIME "picture_front_mime"
#define ICE_MEDIALIB_ENTRY_PROPERTY_STARTMS "startms"
#define ICE_MEDIALIB_ENTRY_PROPERTY_STOPMS "stopms"
#define ICE_MEDIALIB_ENTRY_PROPERTY_STATUS "status"
#define ICE_MEDIALIB_ENTRY_PROPERTY_DESCRIPTION "description"
#define ICE_MEDIALIB_ENTRY_PROPERTY_GROUPING "grouping"
#define ICE_MEDIALIB_ENTRY_PROPERTY_PERFORMER "performer"
#define ICE_MEDIALIB_ENTRY_PROPERTY_CONDUCTOR "conductor"
#define ICE_MEDIALIB_ENTRY_PROPERTY_ARRANGER "arranger"
#define ICE_MEDIALIB_ENTRY_PROPERTY_ORIGINAL_ARTIST "original_artist"
#define ICE_MEDIALIB_ENTRY_PROPERTY_ALBUM_ARTIST "album_artist"
#define ICE_MEDIALIB_ENTRY_PROPERTY_PUBLISHER "publisher"
#define ICE_MEDIALIB_ENTRY_PROPERTY_COMPOSER "composer"
#define ICE_MEDIALIB_ENTRY_PROPERTY_ASIN "asin"
#define ICE_MEDIALIB_ENTRY_PROPERTY_COPYRIGHT "copyright"
#define ICE_MEDIALIB_ENTRY_PROPERTY_WEBSITE_ARTIST "website_artist"
#define ICE_MEDIALIB_ENTRY_PROPERTY_WEBSITE_FILE "website_file"
#define ICE_MEDIALIB_ENTRY_PROPERTY_WEBSITE_PUBLISHER "website_publisher"
#define ICE_MEDIALIB_ENTRY_PROPERTY_WEBSITE_COPYRIGHT "website_copyright"

#define ICE_STREAMER_PATH_MAX 255
#define NO_DATA_TRANSMISSION_TIMEOUT 35L
#define NO_DATA_TRANSMISSION_SPEED_LIMIT 1024L
#define OUTPUT_BUFFERSIZE   (2*1024L*1024L)
#define ICE_STREAMER_XFORM_MAX_LINE_SIZE 1024
#define ICE_PLUGIN_SHORTNAME_MAX_LEN 32
#define READ_CHUNK CURRENT_PACKET_SIZE
#define ICE_STREAM_TYPE_BEGIN "placeholder"
#define ICE_STREAM_TYPE_PRIORITY_FALLBACK 40
#define ICE_STREAM_TYPE_PRIORITY_DEFAULT 50
#define ICE_STREAMER_VERSION "1.0"

#define ICE_STREAMER_XFORM_API_VERSION 1
#define ICE_STREAMER_OUTPUT_API_VERSION 1

//#define DUMP_CURL_DATA

struct ice_streamer_plugin_desc_St ;
typedef struct ice_streamer_plugin_desc_St ice_streamer_plugin_desc_t;

struct ice_streamer_object_St;
typedef struct ice_streamer_object_St ice_streamer_object_t ;

struct ice_val_St;
typedef struct ice_val_St ice_val_t ;

struct ice_streamer_handler_plugin_St ;
typedef struct ice_streamer_handler_plugin_St ice_streamer_handler_plugin_t;

struct ice_streamer_output_plugin_St;
typedef struct ice_streamer_output_plugin_St ice_streamer_output_plugin_t;

struct ice_streamer_ringbuf_St;
typedef struct ice_streamer_ringbuf_St ice_streamer_ringbuf_t;

struct ice_streamer_playlist_St;
typedef struct ice_streamer_playlist_St ice_streamer_playlist_t;

typedef void (*ice_streamer_object_destroy_func_t) (ice_streamer_object_t *object);

typedef enum ice_streamer_plugin_type_St
{
    ICE_PLUGIN_TYPE_ALL,
    ICE_PLUGIN_TYPE_OUTPUT,
    ICE_PLUGIN_TYPE_XFORM
} ice_streamer_plugin_type_t;

#ifdef __cplusplus
extern "C"
{
#endif


#define G_STRINGIFY(macro_or_string)    G_STRINGIFY_ARG (macro_or_string)
#define     G_STRINGIFY_ARG(contents)   #contents

#define ICE_STREAMER_XFORM_BUILTIN(shname, name, ver, desc, setupfunc) ICE_STREAMER_BUILTIN(ICE_PLUGIN_TYPE_XFORM, ICE_STREAMER_XFORM_API_VERSION, shname, name, ver, desc, (frost_bool (*)(frost_pointer))setupfunc)
#define ICE_STREAMER_OUTPUT_BUILTIN(shname, name, ver, desc, setupfunc) ICE_STREAMER_BUILTIN(ICE_PLUGIN_TYPE_OUTPUT, ICE_STREAMER_OUTPUT_API_VERSION, shname, name, ver, desc, (frost_bool (*)(frost_pointer))setupfunc)

#define ICE_STREAMER_PLUGIN(type, api_ver, shname, name, ver, desc, setupfunc)  \
    ice_streamer_plugin_desc_t ICE_STREAMER_PLUGIN_DESC = {             \
        type,                           \
        api_ver,                        \
        shname,                         \
        name,                           \
        ver,                            \
        desc,                           \
        setupfunc                       \
    };

#define ICE_STREAMER_BUILTIN(type, api_ver, shname, name, ver, desc, setupfunc) \
    const ice_streamer_plugin_desc_t ice_streamer_builtin_##shname = {          \
        type,                           \
        api_ver,                        \
        G_STRINGIFY(shname),                    \
        name,                           \
        ver,                            \
        desc,                           \
        setupfunc                       \
    };

/** @addtogroup Object
  * @{
  */
typedef struct ice_streamer_object_St
{
    frost_uint32 id;
    FROST_Mutex *mutex;

    FROST_Tree *signals;
    FROST_Tree *cmds;

    frost_int ref;
    ice_streamer_object_destroy_func_t destroy_func;
};

typedef struct ice_streamer_handler_object_t
{
    ice_streamer_object_t obj;
}ice_streamer_handler_object_t;

typedef struct ice_streamer_stream_type_t
{
    ice_streamer_object_t obj;
    frost_int priority;
    char *name;
    FROST_List *list;
}ice_streamer_stream_type_t;

typedef void (*b_asf_parser_packet_data_callback)(void * ctx, void* pData, int* dataSize);

typedef struct ice_streamer_handler_t
{
    ice_streamer_object_t obj;
    struct ice_streamer_handler_t *prev;

    const ice_streamer_handler_plugin_t *plugin;
    frost_int32 entry;

    frost_bool inited;

    void *priv;

    ice_streamer_stream_type_t *out_type;

    FROST_List *goal_hints;

    frost_bool eos;
    frost_bool error;

    char buffer[CURRENT_MAX_PACKET_SIZE];
    frost_int buffered;
    frost_int buffersize;
    frost_bool buffer_is_static;

    frost_bool metadata_collected;

    frost_bool metadata_changed;
    FROSTHashTable *metadata;

    FROSTHashTable *privdata;
    FROST_Queue *hotspots;

    FROST_List *browse_list;
    ice_val_t *browse_dict;
    frost_int browse_index;

    /** used for line reading */
    struct
    {
        char buf[ICE_STREAMER_XFORM_MAX_LINE_SIZE];
        char *bufend;
    } lr;

    /**
     * This member variables used for discretix drm
     */
    char * user_agent;
    frost_bool download_header_disabled;
    ICE_MediaPlayerStreamDetails** streams;
#ifdef DUMP_CURL_DATA
    FILE *dump_fp ;
#endif

}ice_streamer_handler_t;

typedef struct ice_streamer_handler_hotspot_t
{
    frost_uint pos;
    char *key;
    ice_val_t *obj;
} ice_streamer_handler_hotspot_t;


typedef enum ice_streamer_stream_type_key_t
{
    ICE_STREAM_TYPE_END,
    ICE_STREAM_TYPE_MIMETYPE,
    ICE_STREAM_TYPE_URL,
    ICE_STREAM_TYPE_FMT_FORMAT,
    ICE_STREAM_TYPE_FMT_CHANNELS,
    ICE_STREAM_TYPE_FMT_SAMPLERATE,
    ICE_STREAM_TYPE_PRIORITY,
    ICE_STREAM_TYPE_NAME
} ice_streamer_stream_type_key_t;

typedef enum ice_streamer_vtype_t
{
    ICE_STREAMER_V_TYPE_NONE,
    ICE_STREAMER_V_TYPE_ERROR,
    ICE_STREAMER_V_TYPE_INT32,
    ICE_STREAMER_V_TYPE_STRING,
    ICE_STREAMER_V_TYPE_COLL,
    ICE_STREAMER_V_TYPE_BIN,
    ICE_STREAMER_V_TYPE_LIST,
    ICE_STREAMER_V_TYPE_DICT,
    ICE_STREAMER_V_TYPE_BITBUFFER,
    ICE_STREAMER_V_TYPE_END
} ice_streamer_vtype_t;

typedef struct ice_streamer_bin_t
{
    unsigned char *data;
    uint32_t len;
} ice_streamer_bin_t;

typedef struct ice_streamer_list_t
{
    ice_val_t **list;
    ice_val_t *parent_value;
    int size;
    int allocated;
    frost_bool restricted;
    ice_streamer_vtype_t restricttype;
    FROST_List *iterators;
}ice_streamer_list_t;

typedef struct ice_streamer_asf_audio_t
{
    frost_int samplerate;
    frost_int channels;
    frost_int bitrate;
} ice_streamer_asf_audio_t;

typedef struct ice_streamer_asf_video_t
{
    frost_int size ;
} ice_streamer_asf_video_t;


typedef struct ice_streamer_asf_data_t
{
    asf_file_t *file;

    frost_int audio_track;
    frost_int video_track;

    ice_streamer_asf_audio_t audio_data ;
    ice_streamer_asf_audio_t video_data ;

    asf_packet_t *packet;
    frost_basic_string * outbuf;
} ice_streamer_asf_data_t;

typedef enum ice_streamer_output_filler_state_t
{
    FILLER_STOP,
    FILLER_RUN,
    FILLER_QUIT,
    FILLER_KILL,
    FILLER_TRICK_MODE,
    FILLER_TRICK_MODE_WAIT_NEXT_IFRAME,
    FILLER_TRICK_MODE_STOP,
} ice_streamer_output_filler_state_t;

typedef enum ice_streamer_playback_status_t
{
    ICE_PLAYBACK_STATUS_STOP,
    ICE_PLAYBACK_STATUS_EOS,
    ICE_PLAYBACK_STATUS_PLAY,
    ICE_PLAYBACK_STATUS_PAUSE,
    ICE_PLAYBACK_STATUS_IDLE
} ice_streamer_playback_status_t;

typedef struct ice_streamer_output_t
{
    ice_streamer_object_t object;

    ice_streamer_output_plugin_t *plugin;
    frost_pointer plugin_data;
    frost_pointer user_data;

    /* */
    FROST_Mutex *playtime_mutex;
    frost_uint played;
    frost_uint played_time;
    frost_int32 current_entry;
    frost_uint toskip;

    /* */
    FROST_Thread *filler_thread;
    FROST_Mutex *filler_mutex;

    FROST_CondVar *filler_state_cond;
    ice_streamer_output_filler_state_t filler_state;

    ice_streamer_ringbuf_t *filler_buffer;
    frost_uint32 filler_seek;
    frost_int filler_step;
    frost_int filler_skip;

    /** Internal status, tells which state the
        output really is in */
    FROST_Mutex *status_mutex;
    frost_uint status;

    ice_streamer_playlist_t *playlist;

    /** Supported formats */
    FROST_List *format_list;
    /** Active format */
    ice_streamer_stream_type_t *format;

    /**
     * Number of bytes totaly written to output driver,
     * this is only for statistics...
     */
    frost_uint64 bytes_written;

    /**
     * How many times didn't we have enough data in the buffer?
     */
    frost_int32 buffer_underruns;
    
    frost_uint8 source_id;
    frost_bool first_in_list; // please refer to comment above 'set_flush_ctrl()'

    FROST_Thread *monitor_volume_thread;
    frost_bool monitor_volume_running;
}ice_streamer_output_t;

typedef enum ice_seek_mode_t
{
    ICE_SEEK_CUR = 1, ICE_SEEK_SET = 2, ICE_SEEK_END = 3
} ice_seek_mode_t;

typedef void (*handler_func_t) (ice_streamer_handler_t * handle, char *header);

typedef enum ice_error_code_t
{
    ICE_ERROR_NONE = 0,
    ICE_ERROR_GENERIC,
    ICE_ERROR_OOM,
    ICE_ERROR_PERMISSION,
    ICE_ERROR_NOENT,
    ICE_ERROR_INVAL,
    ICE_ERROR_NO_SAUSAGE,
    ICE_ERROR_COUNT
/* must be last */
} ice_error_code_t;

typedef enum ice_streamer_buffer_state_t
{
    STATE_WANT_BUFFER,
    STATE_BUFFERING,
    STATE_WANT_SEEK,
    STATE_SEEK_DONE,
    STATE_WANT_STOP,
    STATE_IS_STOPPED
} ice_streamer_buffer_state_t;

typedef enum ice_plugin_id_t
{
    ICE_PLUGIN_MAGIC = 0,
    ICE_PLUGIN_ASF,
    ICE_PLUGIN_CURL,
    ICE_PLUGIN_RINGBUF,
    ICE_PLUGIN_EXTERNAL,    
    ICE_PLUGIN_MSTAR,
    ICE_PLUGIN_DISKWRITE,
    ICE_PLUGIN_COUNT,
/* must be last */
} ice_plugin_id_t;

typedef struct ice_streamer_asf_parsed_header_t
{
    char * header ;
    uint64_t  header_size ;
    void * asf_data_object ;
}ice_streamer_asf_parsed_header_t ;

typedef struct ice_streamer_handler_methods_t
{
    /**
     * Initialisation method.
     *
     * Called when a new xform is to be instantiated.  It should
     * prepare for the transformation and use
     * #ice_streamer_asf_outdata_type_add to inform what type of data it
     * outputs.
     *
     * @returns frost_true if initialisation was successful, frost_false otherwise.
     */
    frost_bool (*init)(ice_streamer_handler_t *);
    /**
     * Destruction method.
     *
     * Called when the xform isn't needed anymore. Should free any
     * resources used by the xform.
     */
    void (*destroy)(ice_streamer_handler_t *);
    /**
     * Read method.
     *
     * Called to read data from the xform.
     */
    frost_int (*read)(ice_streamer_handler_t *, frost_pointer, frost_int,
            ice_error_code_t *);
    /**
     * Seek method.
     *
     * Called to change the offset in the stream.  Observe that
     * the offset is measured in "natural" units; audio/pcm-data
     * is measured in samples, application/octet-stream in bytes.
     *
     */
    frost_int64 (*seek)(ice_streamer_handler_t *, frost_int64, ice_seek_mode_t, ice_error_code_t *);

    /**
     * browse method.
     *
     * Called when a users wants to do some server side browsing.
     * This is called without init() beeing called.
     */
    frost_bool (*browse)(ice_streamer_handler_t *, const char *, ice_error_code_t *);
} ice_streamer_handler_methods_t;

typedef struct ice_streamer_plugin_t
{
    ice_streamer_object_t object;

    ice_streamer_plugin_type_t type;
    const frost_uint8 *name;
    const frost_uint8 *shortname;
    const frost_uint8 *description;
    const frost_uint8 *version;
    frost_bool in_use;
    ice_streamer_handler_methods_t methods;
} ice_streamer_plugin_t;

typedef void ice_sample_t;

/**
 * A ringbuffer
 */
typedef struct ice_streamer_ringbuf_St
{
    /** The actual bufferdata */
    frost_uint8 *buffer;
    /** Number of bytes in #buffer */
    frost_uint buffer_size;
    /** Actually usable number of bytes */
    frost_uint buffer_size_usable;
    /** Read and write index */
    frost_uint rd_index, wr_index;
    frost_bool eos;

    FROST_Queue *hotspots;

    FROST_CondVar *free_cond, *used_cond, *eos_cond;
};

typedef struct ice_streamer_ringbuf_hotspot_t
{
    frost_uint pos;
    frost_bool (*callback)(void *);
    void (*destroy)(void *);
    void *arg;
} ice_streamer_ringbuf_hotspot_t;

typedef struct ice_streamer_ringbuf_priv_t
{
    FROST_Thread *thread;

    ice_streamer_ringbuf_t *buffer;
    FROST_Mutex *buffer_lock;

    ice_streamer_buffer_state_t state;
    FROST_CondVar *state_cond;
    FROST_Mutex *state_lock;
} ice_streamer_ringbuf_priv_t;

typedef struct ice_streamer_handler_plugin_St
{
    ice_streamer_plugin_t plugin;
    ice_streamer_handler_methods_t methods;
    FROST_List *in_types;
};

typedef struct ice_streamer_output_methods_t
{
    /**
     * Initiate the output decoder.
     *
     * This function should setup everything that is required to function
     * once the output device is opened for playback. This may for example
     * include probing for usable audio formats (#ice_streamer_output_format_add)
     * and setting up the mixer. Blocking calls in this function are to be
     * avoided as far as possible as this would freeze the startup of ice_streamer.
     *
     * @param output an output object
     * @return frost_true on successful init, otherwise frost_false
     */
    frost_bool (*create)(ice_streamer_output_t *output);

    /**
     * Destroy the output plugin.
     *
     * Tear down the data initialized in new.
     *
     * @param output an output object
     */
    void (*destroy)(ice_streamer_output_t *output);

    /**
     * Open the output device.
     *
     * Blocking calls in this function are to be avoided as far as
     * possible as this would freeze ice streamer. This function cannot coexist
     * with #status.
     *
     * @param output an output object
     * @return frost_true on successful opening of the output device, otherwise frost_false
     */
    frost_bool (*open)(ice_streamer_output_t *output);

    /**
     * Close the output device.
     *
     * This function cannot coexist with #status.
     *
     * @param output an output object
     */
    void (*close)(ice_streamer_output_t *output);

    /**
     * Flush the decoder buffer.
     *
     * This should tell the decoder to drop whatever it is doing and
     * empty the buffer.
     *
     * @param output an output object
     */
    void (*flush)(ice_streamer_output_t *output);

    /**
     * Update the sample format.
     *
     * This should tell the decoder what sample format that will be used
     * for the next track. This is only called when there is an actual
     * change in the sample format. This function cannot coexist with
     * #format_set_always.
     *
     * @param output an output object
     * @param type the stream type to use
     * @return frost_true if the format was successfully set.
     */
    frost_bool (*format_set)(ice_streamer_output_t *output, const ice_streamer_stream_type_t *type);

    /**
     * Update the sample format.
     *
     * This should tell the decoder what sample format that will be used
     * for the next track. This is called each time a track changes even
     * if the sample format is identical to the previous one. This function
     * cannot coexist with #format_set.
     *
     * @param output an output object
     * @param type the stream type to use
     * @return frost_true if the format was successfully set.
     */
    frost_bool (*format_set_always)(ice_streamer_output_t *output,
                                  const ice_streamer_stream_type_t *type);

    /**
     * Update the output plugin with the current playback status.
     *
     * This function is used when the output architecture is driven by an
     * external thread. When status is set to ICE_PLAYBACK_STATUS_PLAY,
     * the external thread should be activated, and will then get its data
     * from #ice_streamer_output_read, and render it to the decoder buffer.
     * This function cannot coexist with #open, #close or #write.
     *
     * @param output an output object
     * @param status the new playback status
     */
    frost_bool (*status)(ice_streamer_output_t *output, ice_streamer_playback_status_t status);

    /**
     * Write audio data to the output device.
     *
     * This function is called from a separate thread and should block until
     * the input buffer has been written to the decoder. This function cannot
     * coexist with #status.
     *
     * @param output an output object
     * @param buffer a buffer with audio data to write to the decoder
     * @param size the number of bytes in the buffer
     * @param err an error struct
     */
    void (*write)(ice_streamer_output_t *output, frost_pointer buffer,
                  frost_int size, ice_error_code_t *err);

    /**
     * Header of the current content.
     *
     * This function is called from a separate thread and should block until
     * the header has been written to the decoder. This function cannot
     * coexist with #status.
     *
     * @param output an output object
     * @param buffer a header of the content to write to the decoder
     * @param size the number of bytes in the buffer
     * @param err an error struct
     */
    void (*header)(ice_streamer_output_t *output, frost_pointer buffer, ice_error_code_t *err);

    /**
     * Get the number of bytes in the decoder buffer.
     *
     * This is needed for the visualization to perform correct synchronization
     * between audio and graphics for example.
     *
     * @param output an output object
     * @return the number of bytes in the decoder buffer or 0 on failure
     */
    frost_uint (*latency_get)(ice_streamer_output_t *);

    /**
     * Checks status of the output plugin.
     *
     * This is needed for the visualization to perform correct synchronization
     * between audio and graphics for example.
     *
     * @param output an output object
     * @return the number of bytes in the decoder buffer or 0 on failure
     */
    frost_bool (*set_status)(ice_streamer_output_t *output,ice_streamer_playback_status_t wanted_status );

} ice_streamer_output_methods_t;
/**
 * CURL
 */

/*
 * Type definitions
 */
typedef struct ice_streamer_curl_data_t
{
    CURL *curl_easy;
    CURLM *curl_multi;

    frost_uint meta_offset;

    char *url;

    struct curl_slist *http_200_aliases;
    struct curl_slist *http_req_headers;

    char *buffer;
    char *header;
    frost_bool header_enabled;
    frost_uint header_allocated;

    frost_uint bufferpos, bufferlen, headerlen;

    frost_int curl_code;

    frost_bool done;

    ice_error_code_t status;

    frost_bool broken_version;

    frost_int64 seek_start ;

    frost_int64 seek_end ;

} ice_streamer_curl_data_t;

typedef struct handler_t
{
    const char *name;
    handler_func_t func;
} handler_t;

/** Playlist structure */
typedef struct ice_streamer_playlist_St
{
    void* object;
    char *url;
    /* playlists are in the collection DAG */

    frost_bool repeat_one;
    frost_bool repeat_all;

    FROST_Mutex *mutex;

    frost_bool update_flag;
};


typedef struct ice_streamer_output_plugin_St
{
    ice_streamer_plugin_t plugin;

    ice_streamer_output_methods_t methods;

    /* make sure we only do one call at a time */
    FROST_Mutex *api_mutex;

    /* */
    ice_streamer_playback_status_t wanted_status;
    frost_bool write_running;
    FROST_Mutex *write_mutex;
    FROST_CondVar *write_cond;
    FROST_Thread *write_thread;

    FROST_CondVar *status_cond;
    FROST_Mutex *status_mutex;
    ice_streamer_playback_status_t status;

    ice_streamer_output_t *write_output;
};

typedef struct ice_streamer_main_t {
    ice_streamer_object_t object;
    FROST_List *output_list;
    ice_streamer_handler_object_t *xform_obj;
    ice_streamer_playlist_t *playlist;
    time_t starttime;
}ice_streamer_main_t;

typedef frost_int32 ice_streamer_medialib_entry_t;

typedef enum ice_streamer_stream_type_val_type_E {
    STRING,
    INTEGER,
} ice_streamer_stream_type_val_type_t;

typedef int8_t ice_samples8_t;
#define ICE_SAMPLES8_MIN -128
#define ICE_SAMPLES8_MAX 127
typedef uint8_t ice_sampleu8_t;
#define ICE_SAMPLEU8_MAX 255
typedef int16_t ice_samples16_t;
#define ICE_SAMPLES16_MIN -32768
#define ICE_SAMPLES16_MAX 32767
typedef uint16_t ice_sampleu16_t;
#define ICE_SAMPLEU16_MAX 65535
typedef int32_t ice_samples32_t;
#define ICE_SAMPLES32_MIN (-2147483647L-1)
#define ICE_SAMPLES32_MAX 2147483647L
typedef uint32_t ice_sampleu32_t;
#define ICE_SAMPLEU32_MAX 4294967295UL
typedef float ice_samplefloat_t;
typedef double ice_sampledouble_t;

typedef enum {
    ICE_SAMPLE_FORMAT_UNKNOWN,
    ICE_SAMPLE_FORMAT_S8,
    ICE_SAMPLE_FORMAT_U8,
    ICE_SAMPLE_FORMAT_S16,
    ICE_SAMPLE_FORMAT_U16,
    ICE_SAMPLE_FORMAT_S32,
    ICE_SAMPLE_FORMAT_U32,
    ICE_SAMPLE_FORMAT_FLOAT,
    ICE_SAMPLE_FORMAT_DOUBLE,
    /* DO NOT CHANGE ORDER! Just add to the end! */
} ice_streamer_sample_format_t;

typedef struct ice_streamer_stream_type_val_St {
    ice_streamer_stream_type_key_t key;
    ice_streamer_stream_type_val_type_t type;
    union {
        char *string;
        int num;
    } d;
} ice_streamer_stream_type_val_t;

typedef struct ice_streamer_config_t {
    ice_streamer_object_t obj;

    const char *filename;
    FROST_Tree *properties;

    /* Lock on globals are great! */
    FROST_Mutex *mutex;

    /* parsing */
    frost_bool is_parsing;
    FROST_Queue *states;
    FROST_Queue *sections;
    char *value_name;
    frost_uint version;
}ice_streamer_config_t;

typedef struct ice_streamer_config_property_t {
    ice_streamer_object_t obj;

    /** Name of the config directive */
    const char *name;
    /** The data */
    char *value;
}ice_streamer_config_property_t;

void b_asf_parser_register_data_cb( void* callback, void* user_data);

typedef enum ICE_IceStreamerStatus
{
    ice_streamer_started,
    ice_streamer_completed,
    ice_streamer_error
} ICE_IceStreamerStatus;

typedef void (*ICE_IceStreamerStatusCallback)(void* user_data, ICE_IceStreamerStatus status);
void ice_streamer_status_callback_set(ICE_IceStreamerStatusCallback callback_function,void* user_data);


/* Need/Write Data functionality is used for External streaming, e.g. for Opera streamed data */
typedef frost_bool (*ICE_IceStreamerWriteDataCallback)(frost_uint8 *buffer, frost_uint length, frost_bool end_of_data, void *user_data);
typedef void (*ICE_IceStreamerNeedDataCallback)(frost_uint8 *buffer, frost_uint length, void *user_data);

void ice_streamer_need_data_callback_set(ICE_IceStreamerNeedDataCallback need_data_callback,
                                         void* user_data);
void ice_streamer_write_data_callback_set(ICE_IceStreamerWriteDataCallback write_data_callback,
                                         void* user_data);

void ice_streamer_handler_need_data(frost_uint8 *buffer, frost_uint buffer_len);

frost_bool ice_streamer_handler_write_data(frost_uint8 *buffer, frost_uint length, frost_bool end_of_data);

frost_bool ice_streamer_write_data(ice_streamer_main_t *ice_streamer, frost_uint8 *buffer, frost_uint length, frost_bool end_of_data);

/* *** */
void header_handler_contentlength (ice_streamer_handler_t * handle, char *header);
void header_handler_icy_metaint (ice_streamer_handler_t * handle, char *header);
void header_handler_icy_name (ice_streamer_handler_t * handle, char *header);
void header_handler_icy_genre (ice_streamer_handler_t * handle, char *header);
handler_func_t header_handler_find (char *header);

handler_t handlers[] = {
    { "content-length", header_handler_contentlength },
    { "icy-metaint", header_handler_icy_metaint },
    { "icy-name", header_handler_icy_name },
    { "icy-genre", header_handler_icy_genre },
/*  { "\r\n", header_handler_last }, */
    { NULL, NULL }
};

/**
 * GENERIC
 */
void ice_streamer_error_set(ice_error_code_t *err, ice_error_code_t code, const char *message);
void ice_streamer_error_reset(ice_error_code_t *err);
void * ice_streamer_private_data_get( ice_streamer_handler_t * handle);
void ice_streamer_private_data_set(ice_streamer_handler_t * handle, void *data);
frost_bool ice_streamer_error_iserror (ice_error_code_t *err);

/**
 * ASF
 */
ice_streamer_asf_parsed_header_t * ice_streamer_get_header_from_asf(void);
const ice_streamer_plugin_desc_t * getAsfPluginDesc() ;
frost_bool ice_streamer_asf_setup(ice_streamer_handler_t * handle);
frost_bool ice_streamer_asf_init(ice_streamer_handler_t * handle);
void ice_streamer_asf_destroy(ice_streamer_handler_t * handle);
frost_int ice_streamer_asf_read(ice_streamer_handler_t * handle, void *buf,
        frost_int len, ice_error_code_t *err);
frost_int64 ice_streamer_asf_seek(ice_streamer_handler_t * handle,
        frost_int64 samples, ice_seek_mode_t whence, ice_error_code_t *err);
//ICE_MediaPlayerFileDetails * ice_streamer_asf_get_mediainfo( ice_streamer_handler_t * handle);
frost_bool ice_streamer_asf_get_mediainfo (ice_streamer_handler_t * handle, ICE_MediaPlayerFileDetails * media_details);


/*
 * Curl Plugin
 */
const ice_streamer_plugin_desc_t * getCurlPluginDesc() ;
void ice_streamer_curl_seek_enable(frost_bool enable);
frost_bool ice_streamer_curl_init (ice_streamer_handler_t * handle);
void ice_streamer_curl_destroy (ice_streamer_handler_t * handle);
frost_int fill_buffer (ice_streamer_handler_t * handle, ice_streamer_curl_data_t *data, ice_error_code_t *error);
frost_int ice_streamer_curl_read (ice_streamer_handler_t * handle, void *buffer, frost_int len, ice_error_code_t *error);
frost_int64 ice_streamer_curl_seek (ice_streamer_handler_t * handle, frost_int64 offset, ice_seek_mode_t whence, ice_error_code_t *error);
size_t ice_streamer_curl_callback_write (void *ptr, size_t size, size_t nmemb, void *stream);
size_t ice_streamer_curl_callback_header (void *ptr, size_t size, size_t nmemb, void *stream);
void ice_streamer_curl_free_data (ice_streamer_curl_data_t *data);
char * ice_streamer_curl_get_header(void);

char **ice_streamer_valist_to_strlist(const char *first, va_list ap);
char **ice_streamer_vargs_to_strlist(const char *first, ...);
int ice_streamer_strlist_len (char **data);
void ice_streamer_strlist_destroy (char **data);
char **ice_streamer_strlist_prepend_copy (char **data, char *newstr);
char **ice_streamer_strlist_copy (char **strlist);

/**
 * Magic
 */
const ice_streamer_plugin_desc_t * getMagicPluginDesc();

frost_bool ice_streamer_magic_add (const char *desc, const char *mime, ...);
frost_bool ice_streamer_magic_extension_add (const char *mime, const char *ext);

/**
 * Disk write
 */
const ice_streamer_plugin_desc_t * getDiskWritePluginDesc() ;


/**
 * External data plugin
 */
const ice_streamer_plugin_desc_t * getExternalDataPluginDesc() ;

/**
 * RINGBUF
 */

const ice_streamer_plugin_desc_t * getRingBufPluginDesc() ;
frost_bool ice_streamer_ringbuf_plugin_init (ice_streamer_handler_t * handle);
ice_streamer_ringbuf_t *ice_streamer_ringbuf_new (frost_uint size);
void ice_streamer_ringbuf_destroy (ice_streamer_ringbuf_t *ringbuf);
void ice_streamer_ringbuf_clear (ice_streamer_ringbuf_t *ringbuf);
frost_uint ice_streamer_ringbuf_bytes_free (const ice_streamer_ringbuf_t *ringbuf);
frost_uint ice_streamer_ringbuf_bytes_used (const ice_streamer_ringbuf_t *ringbuf);
frost_uint ice_streamer_ringbuf_size (ice_streamer_ringbuf_t *ringbuf);

frost_uint ice_streamer_ringbuf_read (ice_streamer_ringbuf_t *ringbuf, frost_pointer data, frost_uint length);
frost_uint ice_streamer_ringbuf_read_wait (ice_streamer_ringbuf_t *ringbuf, frost_pointer data, frost_uint length, FROST_Mutex *mtx);
frost_uint ice_streamer_ringbuf_peek (ice_streamer_ringbuf_t *ringbuf, frost_pointer data, frost_uint length);
frost_uint ice_streamer_ringbuf_peek_wait (ice_streamer_ringbuf_t *ringbuf, frost_pointer data, frost_uint length, FROST_Mutex *mtx);
void ice_streamer_ringbuf_hotspot_set (ice_streamer_ringbuf_t *ringbuf, frost_bool (*cb) (void *), void (*destroy) (void *), void *arg);
frost_uint ice_streamer_ringbuf_write (ice_streamer_ringbuf_t *ringbuf, frost_constpointer data, frost_uint length);
frost_uint ice_streamer_ringbuf_write_wait (ice_streamer_ringbuf_t *ringbuf, frost_constpointer data, frost_uint length, FROST_Mutex *mtx);

void ice_streamer_ringbuf_wait_free (const ice_streamer_ringbuf_t *ringbuf, frost_uint len, FROST_Mutex *mtx);
void ice_streamer_ringbuf_wait_used (const ice_streamer_ringbuf_t *ringbuf, frost_uint len, FROST_Mutex *mtx);

frost_bool ice_streamer_ringbuf_iseos (const ice_streamer_ringbuf_t *ringbuf);
void ice_streamer_ringbuf_set_eos (ice_streamer_ringbuf_t *ringbuf, frost_bool eos);
void ice_streamer_ringbuf_wait_eos (const ice_streamer_ringbuf_t *ringbuf, FROST_Mutex *mtx);

/**
 * Streamer
 */
ice_streamer_main_t * ice_streamer_init(ICE_IceStreamerStatusCallback callback_function, void* user_data,void * handle);
void ice_streamer_destroy(ice_streamer_object_t * output);
frost_bool ice_streamer_start(ice_streamer_main_t *ice_streamer,
        const char * filename);
frost_bool ice_streamer_stop(ice_streamer_main_t *ice_streamer);
frost_bool ice_streamer_trick_mode(ice_streamer_main_t *ice_streamer, frost_int step, frost_int mili_seconds, ice_streamer_output_filler_state_t state);
frost_bool ice_streamer_play(ice_streamer_main_t *ice_streamer);
frost_uint32 ice_streamer_playtime(ice_streamer_main_t *ice_streamer);
frost_bool ice_streamer_pause(ice_streamer_main_t *ice_streamer);
frost_int ice_streamer_stream_type_get_int (const ice_streamer_stream_type_t *st, ice_streamer_stream_type_key_t key);
const char * ice_streamer_stream_type_get_str (const ice_streamer_stream_type_t *st, ice_streamer_stream_type_key_t key);
ice_streamer_stream_type_t * ice_streamer_stream_type_parse (va_list ap);
void ice_streamer_register_need_data(ICE_IceStreamerNeedDataCallback need_data_callback,
                                     void *user_data);
frost_bool ice_streamer_attach_source(ice_streamer_main_t *ice_streamer, unsigned int source_id);
frost_bool ice_streamer_remove_source(ice_streamer_main_t *ice_streamer, unsigned int source_id);
/**
 * MSTAR
 */
const ice_streamer_plugin_desc_t * getMstarPluginDesc();

/**
 * Output
 */
frost_bool ice_streamer_output_format_set (ice_streamer_output_t *output, ice_streamer_stream_type_t *fmt);
ice_streamer_output_t * ice_streamer_output_new ( ice_streamer_output_plugin_t * plugin,ice_streamer_playlist_t *playlist, frost_uint8 source_id);
void ice_streamer_output_flush (ice_streamer_output_t *output);
void ice_playback_client_start (ice_streamer_output_t *output, ice_error_code_t *err);
void ice_playback_client_stop (ice_streamer_output_t *output, ice_error_code_t *err);
void ice_playback_client_pause (ice_streamer_output_t *output, ice_error_code_t *err);
void ice_playback_client_play (ice_streamer_output_t *output, ice_error_code_t *err);
void ice_playback_client_tickle (ice_streamer_output_t *output, ice_error_code_t *err);
void ice_playback_client_trick_mode (ice_streamer_output_t *output, frost_int32 step, frost_int32 mili_seconds, ice_streamer_output_filler_state_t state);
frost_int32 ice_playback_client_status (ice_streamer_output_t *output, ice_error_code_t *error);
frost_int ice_playback_client_current_id (ice_streamer_output_t *output, ice_error_code_t *error);
frost_int32 ice_playback_client_playtime (ice_streamer_output_t *output, ice_error_code_t *err);

void ice_streamer_output_filler_state (ice_streamer_output_t *output, ice_streamer_output_filler_state_t state);
void ice_streamer_output_filler_state_nolock (ice_streamer_output_t *output, ice_streamer_output_filler_state_t state);

frost_bool ice_streamer_output_status_set (ice_streamer_output_t *output, frost_int status);

void ice_streamer_output_format_list_free_elem (frost_pointer data, frost_pointer user_data);
void ice_streamer_output_format_list_clear (ice_streamer_output_t *output);
ice_streamer_medialib_entry_t ice_streamer_output_current_id (ice_streamer_output_t *output);
frost_int ice_streamer_handler_read (ice_streamer_handler_t *xform, frost_pointer buf, frost_int siz, ice_error_code_t *err);
const char * ice_streamer_handler_get_url (ice_streamer_handler_t *xform);

/**
 * Object
 */

/* Convenience wrapper to create #ice_val_t from GLib types. */
ice_val_t *ice_streamer_convert_and_kill_list (FROST_List *list);
ice_val_t *ice_streamer_convert_and_kill_dict (FROST_Tree *dict);
ice_val_t *ice_streamer_convert_and_kill_string (char *str);
ice_val_t *ice_streamer_convert_and_kill_bin (frost_basic_string *gs);

int ice_streamer_bin_to_gstring (ice_val_t *value, frost_basic_string **gs);
int dummy_identity (ice_val_t *value, ice_val_t **arg);
frost_bool check_string_list (ice_val_t *list);
ice_streamer_handler_object_t * ice_streamer_handler_object_init (void);
void ice_streamer_handler_browse_add_entry_property (ice_streamer_handler_t *xform, const char *key,
                                      ice_val_t *val);
void ice_streamer_handler_browse_add_entry (ice_streamer_handler_t *xform, const char *filename,
                             frost_uint32 flags);
frost_uint ice_streamer_sample_ms_to_samples (const ice_streamer_stream_type_t *st, frost_uint milliseconds);
frost_uint ice_streamer_sample_samples_to_ms (const ice_streamer_stream_type_t *st, frost_uint samples);
frost_uint ice_streamer_sample_bytes_to_ms (const ice_streamer_stream_type_t *st, frost_uint bytes);
frost_int ice_streamer_sample_frame_size_get (const ice_streamer_stream_type_t *st);
frost_bool ice_streamer_stream_type_match (const ice_streamer_stream_type_t *in_type, const ice_streamer_stream_type_t *out_type);

#define ICE_BROWSE_FLAG_DIR (1 << 0)

typedef void (*ice_streamer_object_handler_t) (ice_streamer_object_t *object, ice_val_t *data, frost_pointer userdata);

#define ice_streamer_OBJECT_CMD_MAX_ARGS 6
typedef struct ice_streamer_object_cmd_arg_t{
    ice_val_t *args; /* list */
    ice_val_t *retval;
    ice_error_code_t error;
} ice_streamer_object_cmd_arg_t;

typedef void (*ice_streamer_object_cmd_func_t) (ice_streamer_object_t *object, ice_streamer_object_cmd_arg_t *arg);

#define ICE_STREAMER_OBJECT_MID 0x00455574
#define ICEST_OBJECT(p) ((ice_streamer_object_t *)p)
#define ICEST_IS_OBJECT(p) (ICEST_OBJECT (p)->id == ICE_STREAMER_OBJECT_MID)

void ice_streamer_object_cleanup (ice_streamer_object_t *object);

void ice_streamer_object_connect (ice_streamer_object_t *object, frost_uint32 signalid,
        ice_streamer_object_handler_t handler, frost_pointer userdata);

void ice_streamer_object_disconnect (ice_streamer_object_t *object, frost_uint32 signalid,
        ice_streamer_object_handler_t handler, frost_pointer userdata);

void ice_streamer_object_emit (ice_streamer_object_t *object, frost_uint32 signalid, ice_val_t *data);

void ice_streamer_object_emit_f (ice_streamer_object_t *object, frost_uint32 signalid,
        ice_streamer_vtype_t type, ...);

void ice_streamer_object_cmd_arg_init (ice_streamer_object_cmd_arg_t *arg);

void ice_streamer_object_cmd_add (ice_streamer_object_t *object, frost_uint cmdid, const ice_streamer_object_cmd_func_t desc);

void ice_streamer_object_cmd_call (ice_streamer_object_t *object, frost_uint cmdid, ice_streamer_object_cmd_arg_t *arg);


void __int_ice_streamer_object_unref (ice_streamer_object_t *object);
ice_streamer_object_t *__int_ice_streamer_object_new (frost_int size, ice_streamer_object_destroy_func_t destfunc);

void frost_atomic_int_add (volatile frost_int __attribute__((may_alias)) *atomic,
          frost_int           val);
frost_int frost_atomic_int_exchange_and_add (volatile frost_int __attribute__((may_alias)) *atomic,
                   frost_int           val);

#define frost_atomic_int_inc(atomic) (frost_atomic_int_add ((atomic), 1))

#define frost_atomic_int_dec_and_test(atomic) \
  (frost_atomic_int_exchange_and_add ((atomic), -1) == 1)

#define ice_streamer_object_ref(obj) do { \
    if (obj && ICEST_IS_OBJECT (obj)) { \
        frost_atomic_int_inc (&(ICEST_OBJECT (obj)->ref)); \
    } \
} while (0)

#define ice_streamer_object_unref(obj) do { \
    if (obj && ICEST_IS_OBJECT (obj)) { \
        __int_ice_streamer_object_unref (ICEST_OBJECT (obj)); \
    } \
} while (0)

#define ice_streamer_object_new(objtype,destroyfunc) (objtype *) __int_ice_streamer_object_new (sizeof (objtype), destroyfunc)

/**
 * Output Plugin
 *
 *
 */

#define ICE_STREAMER_OUTPUT_METHODS_INIT(m) memset (&m, 0, sizeof (ice_streamer_output_methods_t))
void ice_streamer_output_plugin_methods_set (ice_streamer_output_plugin_t *output, ice_streamer_output_methods_t *methods);
frost_pointer ice_streamer_output_private_data_get (ice_streamer_output_t *output);
void ice_streamer_output_private_data_set (ice_streamer_output_t *output, frost_pointer data);
#define ice_streamer_output_format_add(output, fmt, ch, rate)           \
        ice_streamer_output_stream_type_add (output,                            \
                                     ICE_STREAM_TYPE_MIMETYPE,         \
                                     "audio/pcm",                       \
                                     ICE_STREAM_TYPE_FMT_FORMAT,       \
                                     fmt,                               \
                                     ICE_STREAM_TYPE_FMT_CHANNELS,     \
                                     ch,                                \
                                     ICE_STREAM_TYPE_FMT_SAMPLERATE,   \
                                     rate,                              \
                                     ICE_STREAM_TYPE_END)


void ice_streamer_output_stream_type_add (ice_streamer_output_t *output, ...);
frost_int ice_streamer_output_read (ice_streamer_output_t *output, char *buffer, frost_int len);
frost_int ice_streamer_output_bytes_available (ice_streamer_output_t *output);
void ice_streamer_output_set_error (ice_streamer_output_t *output, ice_error_code_t *error);
frost_bool ice_streamer_output_plugin_format_set_always (ice_streamer_output_plugin_t *plugin);
frost_int32 ice_streamer_output_current_id (ice_streamer_output_t *output);
frost_bool ice_streamer_plugin_init ();
ice_streamer_config_property_t * ice_streamer_output_plugin_config_property_register (ice_streamer_output_plugin_t *plugin,
                                             const char *name,
                                             const char *default_value,
                                             ice_streamer_object_handler_t cb,
                                             frost_pointer userdata);
ice_streamer_plugin_t *ice_streamer_output_plugin_new (void);
frost_bool ice_streamer_output_plugin_verify (ice_streamer_plugin_t *_plugin);
frost_bool ice_streamer_output_plugin_method_new (ice_streamer_output_plugin_t *plugin, ice_streamer_output_t *output);
void ice_streamer_output_plugin_method_destroy (ice_streamer_output_plugin_t *plugin, ice_streamer_output_t *output);
void ice_streamer_output_plugin_method_flush (ice_streamer_output_plugin_t *plugin, ice_streamer_output_t *output);
frost_bool ice_streamer_output_plugin_method_format_set (ice_streamer_output_plugin_t *plugin, ice_streamer_output_t *output, ice_streamer_stream_type_t *st);
frost_bool ice_streamer_output_plugin_method_status (ice_streamer_output_plugin_t *plugin, ice_streamer_output_t *output, int st);
frost_uint ice_streamer_output_plugin_method_latency_get (ice_streamer_output_plugin_t *plugin, ice_streamer_output_t *output);
typedef frost_bool (*ice_streamer_plugin_foreach_func_t)(ice_streamer_plugin_t *, frost_pointer);
void ice_streamer_plugin_foreach (ice_streamer_plugin_type_t type, ice_streamer_plugin_foreach_func_t func, frost_pointer user_data);
ice_streamer_plugin_t *ice_streamer_plugin_find (ice_streamer_plugin_type_t type, const char *name);
ice_streamer_plugin_t * ice_streamer_plugin_load (ice_plugin_id_t plugin_type);
FROST_List* ice_streamer_plugin_get_list();
ice_streamer_plugin_type_t ice_streamer_plugin_type_get (const ice_streamer_plugin_t *plugin);
const char *ice_streamer_plugin_name_get (const ice_streamer_plugin_t *plugin);
const char *ice_streamer_plugin_shortname_get (const ice_streamer_plugin_t *plugin);
const char *ice_streamer_plugin_version_get (const ice_streamer_plugin_t *plugin);
const char *ice_streamer_plugin_description_get (const ice_streamer_plugin_t *plugin);
void ice_streamer_plugin_destroy (ice_streamer_plugin_t *plugin);
ice_streamer_config_property_t * ice_streamer_plugin_config_property_register (ice_streamer_plugin_t *plugin,
                                      const char *name,
                                      const char *default_value,
                                      ice_streamer_object_handler_t cb,
                                      frost_pointer userdata);


/**
 * Handler
 */
const char * ice_streamer_sample_name_get (ice_streamer_sample_format_t fmt);
void ice_streamer_handler_plugin_methods_set (ice_streamer_handler_plugin_t *plugin, ice_streamer_handler_methods_t *methods);
void ice_streamer_handler_plugin_methods_set (ice_streamer_handler_plugin_t *plugin, ice_streamer_handler_methods_t *methods);
void ice_streamer_handler_outdata_type_add (ice_streamer_handler_t *xform, ...);
void ice_streamer_handler_outdata_type_copy (ice_streamer_handler_t *xform);
const char * ice_streamer_handler_indata_find_str (ice_streamer_handler_t *xform, ice_streamer_stream_type_key_t key);
void ice_streamer_handler_metadata_set_int (ice_streamer_handler_t *xform, const char *key, int val);
void ice_streamer_handler_metadata_set_str (ice_streamer_handler_t *xform, const char *key, const char *val);
frost_bool ice_streamer_handler_metadata_has_val (ice_streamer_handler_t *xform, const char *key);
frost_bool ice_streamer_handler_metadata_get_int (ice_streamer_handler_t *xform, const char *key, frost_int *val);
frost_bool ice_streamer_handler_metadata_get_str (ice_streamer_handler_t *xform, const char *key, const char **val);
void ice_streamer_handler_auxdata_barrier (ice_streamer_handler_t *xform);
void ice_streamer_handler_auxdata_set_int (ice_streamer_handler_t *xform, const char *key, frost_int32 val);
void ice_streamer_handler_auxdata_set_str (ice_streamer_handler_t *xform, const char *key, const char *val);
void ice_streamer_handler_auxdata_set_bin (ice_streamer_handler_t *xform, const char *key, frost_pointer data, frost_long len);
frost_bool ice_streamer_handler_auxdata_has_val (ice_streamer_handler_t *xform, const char *key);
frost_bool ice_streamer_handler_auxdata_get_int (ice_streamer_handler_t *xform, const char *key, frost_int32 *val);
void ice_streamer_handler_auxdata_barrier (ice_streamer_handler_t *xform);
frost_bool ice_streamer_handler_auxdata_get_str (ice_streamer_handler_t *xform, const char *key, const char **val);
frost_bool ice_streamer_handler_auxdata_get_bin (ice_streamer_handler_t *xform, const char *key, const unsigned char **data, frost_ulong *datalen);
ice_streamer_handler_t * ice_streamer_handler_chain_setup (frost_int32 entry, FROST_List *goal_formats, frost_bool rehash);
ice_streamer_config_property_t * ice_streamer_handler_config_lookup (ice_streamer_handler_t *xform, const char *path);
ice_streamer_handler_t * ice_streamer_handler_chain_setup_url (frost_int32 entry, const char *url,
                            FROST_List *goal_formats, frost_bool rehash);
const char *ice_streamer_handler_indata_get_str (ice_streamer_handler_t *xform, ice_streamer_stream_type_key_t key);
frost_int ice_streamer_handler_indata_get_int (ice_streamer_handler_t *xform, ice_streamer_stream_type_key_t key);
frost_int ice_streamer_handler_peek (ice_streamer_handler_t *xform, frost_pointer buf, frost_int siz, ice_error_code_t *err);
char *ice_streamer_handler_read_line (ice_streamer_handler_t *xform, char *buf, ice_error_code_t *err);
frost_int ice_streamer_handler_read (ice_streamer_handler_t *xform, frost_pointer buf, frost_int siz, ice_error_code_t *err);
frost_int64 ice_streamer_handler_seek (ice_streamer_handler_t *xform, frost_int64 offset, ice_seek_mode_t whence, ice_error_code_t *err);
frost_bool ice_streamer_handler_iseos (ice_streamer_handler_t *xform);
ice_streamer_handler_t * ice_streamer_handler_new (ice_streamer_handler_plugin_t *plugin, ice_streamer_handler_t *prev, frost_int32 entry, FROST_List *goal_hints);
const ice_streamer_stream_type_t *ice_streamer_handler_get_out_stream_type (ice_streamer_handler_t *xform);
void ice_streamer_handler_plugin_indata_add (ice_streamer_handler_plugin_t *plugin, ...);
frost_bool ice_streamer_handler_plugin_verify (ice_streamer_handler_plugin_t *_plugin);
void ice_streamer_handler_plugin_methods_set (ice_streamer_handler_plugin_t *plugin,
                               ice_streamer_handler_methods_t *methods);
ice_streamer_handler_plugin_t *ice_streamer_handler_plugin_new (void);
ice_streamer_handler_t *ice_streamer_handler_find (ice_streamer_handler_t *prev, frost_int32 entry, FROST_List *goal_hints);
const char *ice_streamer_handler_shortname (ice_streamer_handler_t *xform);
ice_streamer_handler_t *add_effects (ice_streamer_handler_t *last, frost_int32 entry, FROST_List *goal_formats);
ice_streamer_handler_t *ice_streamer_handler_new_effect (ice_streamer_handler_t* last, frost_int32 entry, FROST_List *goal_formats, const char *name);
void ice_streamer_handler_destroy (ice_streamer_object_t *object);
void effect_callbacks_init (void);
frost_int32 ice_streamer_handler_entry_get (ice_streamer_handler_t *xform);
FROST_List *ice_streamer_handler_client_browse (ice_streamer_handler_object_t *obj, const char *url, ice_error_code_t *error);
frost_int64 ice_streamer_handler_this_seek (ice_streamer_handler_t *xform, frost_int64 offset,
                      ice_seek_mode_t whence, ice_error_code_t *err);
frost_int ice_streamer_handler_this_read (ice_streamer_handler_t *xform, frost_pointer buf, frost_int siz,
                      ice_error_code_t *err);
ice_streamer_stream_type_t * ice_streamer_handler_outtype_get (ice_streamer_handler_t *xform);
frost_bool ice_streamer_handler_plugin_can_browse (const ice_streamer_handler_plugin_t *plugin);
frost_bool ice_streamer_handler_plugin_browse (const ice_streamer_handler_plugin_t *plugin, ice_streamer_handler_t *xform,
                          const char *url, ice_error_code_t *error);
frost_bool ice_streamer_handler_plugin_can_destroy (const ice_streamer_handler_plugin_t *plugin);
void ice_streamer_handler_plugin_destroy (const ice_streamer_handler_plugin_t *plugin, ice_streamer_handler_t *xform);
frost_bool ice_streamer_handler_plugin_init (const ice_streamer_handler_plugin_t *plugin, ice_streamer_handler_t *xform);
frost_int ice_streamer_handler_plugin_read (const ice_streamer_handler_plugin_t *plugin, ice_streamer_handler_t *xform,
                        ice_sample_t *buf, frost_int length, ice_error_code_t *error);
frost_bool ice_streamer_handler_plugin_supports (const ice_streamer_handler_plugin_t *plugin, ice_streamer_stream_type_t *st,
                            frost_int *priority);
frost_int64 ice_streamer_handler_plugin_seek (const ice_streamer_handler_plugin_t *plugin, ice_streamer_handler_t *xform,
                        frost_int64 offset, ice_seek_mode_t whence,
                        ice_error_code_t *err);
frost_bool ice_streamer_handler_plugin_can_seek (const ice_streamer_handler_plugin_t *plugin);
ice_streamer_config_property_t *ice_streamer_config_lookup (const char *path);
const char *ice_streamer_config_property_lookup_get_string (ice_streamer_config_t *conf,
                                                     const char *key,
                                                     ice_error_code_t *err);
const char *ice_streamer_config_property_get_string (const ice_streamer_config_property_t *prop);
frost_int ice_streamer_config_property_get_int (const ice_streamer_config_property_t *prop);
float ice_streamer_config_property_get_float (const ice_streamer_config_property_t *prop);
const char *ice_streamer_config_property_get_name (const ice_streamer_config_property_t *prop);
ice_streamer_config_property_t *ice_streamer_config_property_register (const char *path, const char *default_value, ice_streamer_object_handler_t cb, frost_pointer userdata);
void ice_streamer_config_property_set_data (ice_streamer_config_property_t *prop, const char *data);
void ice_streamer_config_property_callback_set (ice_streamer_config_property_t *prop, ice_streamer_object_handler_t cb, frost_pointer userdata);
void ice_streamer_config_property_callback_remove (ice_streamer_config_property_t *prop, ice_streamer_object_handler_t cb, frost_pointer userdata);
ice_streamer_config_property_t * ice_streamer_handler_plugin_config_property_register (ice_streamer_handler_plugin_t *xform_plugin,
                                            const char *name,
                                            const char *default_value,
                                            ice_streamer_object_handler_t cb,
                                            frost_pointer userdata);
void ice_streamer_config_init (void);

#define ICE_STREAMER_PLUGIN_SHORTNAME_MAX_LEN 32

ice_streamer_config_property_t *ice_streamer_plugin_config_lookup (ice_streamer_plugin_t *plugin, const char *key);

typedef struct ice_streamer_plugin_desc_St
{
    ice_streamer_plugin_type_t type;
    frost_int api_version;
    char shortname[ICE_STREAMER_PLUGIN_SHORTNAME_MAX_LEN];
    const char *name;
    const char *version;
    const char *description;
    frost_bool (*setup_func)(frost_pointer);
} ;

/****
 * VALUE
 */


typedef enum {
    ICE_VAL_TYPE_NONE,
    ICE_VAL_TYPE_ERROR,
    ICE_VAL_TYPE_INT32,
    ICE_VAL_TYPE_UINT32,
    ICE_VAL_TYPE_STRING,
    ICE_VAL_TYPE_COLL,
    ICE_VAL_TYPE_BIN,
    ICE_VAL_TYPE_LIST,
    ICE_VAL_TYPE_DICT,
    ICE_VAL_TYPE_BITBUFFER,
    ICE_VAL_TYPE_END
} ice_val_type_t;

typedef struct ice_val_coll_St ice_val_coll_t;
typedef ice_val_coll_t ice_coll_coll_t;

typedef enum {
    ICE_COLLECTION_TYPE_REFERENCE,
    ICE_COLLECTION_TYPE_UNION,
    ICE_COLLECTION_TYPE_INTERSECTION,
    ICE_COLLECTION_TYPE_COMPLEMENT,
    ICE_COLLECTION_TYPE_HAS,
    ICE_COLLECTION_TYPE_EQUALS,
    ICE_COLLECTION_TYPE_MATCH,
    ICE_COLLECTION_TYPE_SMALLER,
    ICE_COLLECTION_TYPE_GREATER,
    ICE_COLLECTION_TYPE_IDLIST,
    ICE_COLLECTION_TYPE_QUEUE,
    ICE_COLLECTION_TYPE_PARTYSHUFFLE,
    ICE_COLLECTION_TYPE_LAST = ICE_COLLECTION_TYPE_PARTYSHUFFLE
} ice_val_coll_type_t;

typedef enum {
    ICE_MEDIALIB_ENTRY_STATUS_NEW,
    ICE_MEDIALIB_ENTRY_STATUS_OK,
    ICE_MEDIALIB_ENTRY_STATUS_RESOLVING,
    ICE_MEDIALIB_ENTRY_STATUS_NOT_AVAILABLE,
    ICE_MEDIALIB_ENTRY_STATUS_REHASH
} ice_coll_medialib_entry_status_t;

typedef const char* ice_val_coll_namespace_t;
#define ICE_COLLECTION_NS_ALL          "*"
#define ICE_COLLECTION_NS_COLLECTIONS  "Collections"
#define ICE_COLLECTION_NS_PLAYLISTS    "Playlists"

typedef struct ice_val_list_St ice_val_list_t;
typedef struct ice_val_dict_St ice_val_dict_t;
typedef struct ice_val_list_iter_St ice_val_list_iter_t;
typedef struct ice_val_dict_iter_St ice_val_dict_iter_t;

typedef struct _x_list_t x_list_t;

typedef struct ice_val_bin_St {
    unsigned char *data;
    uint32_t len;
} ice_val_bin_t;

struct ice_val_list_St {
    ice_val_t **list;
    ice_val_t *parent_value;
    int size;
    int allocated;
    frost_bool restricted;
    ice_val_type_t restricttype;
    x_list_t *iterators;
};


ice_val_list_t *ice_val_list_new (void);
void ice_val_list_free (ice_val_list_t *l);
int ice_val_list_resize (ice_val_list_t *l, int newsize);
int _ice_val_list_insert (ice_val_list_t *l, int pos, ice_val_t *val);
int _ice_val_list_append (ice_val_list_t *l, ice_val_t *val);
int _ice_val_list_remove (ice_val_list_t *l, int pos);
int _ice_val_list_move (ice_val_list_t *l, int old_pos, int new_pos);
void _ice_val_list_clear (ice_val_list_t *l);

ice_val_dict_t *ice_val_dict_new (void);
void ice_val_dict_free (ice_val_dict_t *dict);


struct ice_val_list_iter_St {
    ice_val_list_t *parent;
    int position;
};

ice_val_list_iter_t *ice_val_list_iter_new (ice_val_list_t *l);
void ice_val_list_iter_free (ice_val_list_iter_t *it);


ice_val_dict_iter_t *ice_val_dict_iter_new (ice_val_dict_t *d);
void ice_val_dict_iter_free (ice_val_dict_iter_t *it);

ice_val_t *ice_val_new_none (void);
ice_val_t *ice_val_new_error (const char *errstr); /* FIXME: err id? */
ice_val_t *ice_val_new_int (int32_t i);
ice_val_t *ice_val_new_string (const char *s);
ice_val_t *ice_val_new_coll (ice_val_coll_t *coll);
ice_val_t *ice_val_new_bin (const unsigned char *data, unsigned int len);

ice_val_t *ice_val_ref (ice_val_t *val);
void ice_val_unref (ice_val_t *val);

ice_val_type_t ice_val_get_type (const ice_val_t *val);
int ice_val_is_type (const ice_val_t *val, ice_val_type_t t);

int ice_val_get_error (const ice_val_t *val, const char **r);
int ice_val_get_int (const ice_val_t *val, int32_t *r);
int ice_val_get_string (const ice_val_t *val, const char **r);
int ice_val_get_coll (const ice_val_t *val, ice_val_coll_t **coll);
int ice_val_get_bin (const ice_val_t *val, const unsigned char **r, unsigned int *rlen);

/* legacy aliases */
int ice_val_is_error (const ice_val_t *val);


typedef void (*ice_val_coll_attribute_foreach_func) (const char *key, const char *value, void *udata);

ice_val_coll_t *ice_val_coll_new (ice_val_coll_type_t type);
ice_val_coll_t *ice_val_coll_ref (ice_val_coll_t *coll);
void ice_val_coll_unref (ice_val_coll_t *coll);

void ice_val_coll_set_idlist (ice_val_coll_t *coll, int ids[]);
void ice_val_coll_add_operand (ice_val_coll_t *coll, ice_val_coll_t *op);
void ice_val_coll_remove_operand (ice_val_coll_t *coll, ice_val_coll_t *op);
struct ice_val_St *ice_val_coll_operands_get (ice_val_coll_t *coll);

int ice_val_coll_idlist_append (ice_val_coll_t *coll, int id);
int ice_val_coll_idlist_insert (ice_val_coll_t *coll, int index, int id);
int ice_val_coll_idlist_move (ice_val_coll_t *coll, int index, int newindex);
int ice_val_coll_idlist_remove (ice_val_coll_t *coll, int index);
int ice_val_coll_idlist_clear (ice_val_coll_t *coll);
int ice_val_coll_idlist_get_index (ice_val_coll_t *coll, int index, int32_t *val);
int ice_val_coll_idlist_set_index (ice_val_coll_t *coll, int index, int32_t val);
size_t ice_val_coll_idlist_get_size (ice_val_coll_t *coll);

ice_val_coll_type_t ice_val_coll_get_type (ice_val_coll_t *coll);
struct ice_val_St *ice_val_coll_idlist_get (ice_val_coll_t *coll);



void ice_val_coll_attribute_set (ice_val_coll_t *coll, const char *key, const char *value);
int ice_val_coll_attribute_remove (ice_val_coll_t *coll, const char *key);
int ice_val_coll_attribute_get (ice_val_coll_t *coll, const char *key, char **value);


struct ice_val_St *ice_val_coll_attributes_get (ice_val_coll_t *coll);

ice_val_coll_t *ice_val_coll_universe (void);



/* compability */


#define ice_coll_coll_new ice_val_coll_new
#define ice_coll_coll_ref ice_val_coll_ref
#define ice_coll_coll_unref ice_val_coll_unref

#define ice_coll_coll_set_idlist ice_val_coll_set_idlist
#define ice_coll_coll_add_operand ice_val_coll_add_operand
#define ice_coll_coll_remove_operand ice_val_coll_remove_operand

#define ice_coll_coll_idlist_append ice_val_coll_idlist_append
#define ice_coll_coll_idlist_insert ice_val_coll_idlist_insert
#define ice_coll_coll_idlist_move ice_val_coll_idlist_move
#define ice_coll_coll_idlist_remove ice_val_coll_idlist_remove
#define ice_coll_coll_idlist_clear ice_val_coll_idlist_clear
#define ice_coll_coll_idlist_get_index ice_val_coll_idlist_get_index
#define ice_coll_coll_idlist_set_index ice_val_coll_idlist_set_index
#define ice_coll_coll_idlist_get_size ice_val_coll_idlist_get_size

#define ice_coll_coll_get_type ice_val_coll_get_type
#define ice_coll_coll_get_idlist ice_val_coll_get_idlist

#define ice_coll_coll_attribute_set ice_val_coll_attribute_set
#define ice_coll_coll_attribute_remove ice_val_coll_attribute_remove
#define ice_coll_coll_attribute_get ice_val_coll_attribute_get
#define ice_coll_coll_attribute_foreach ice_val_coll_attribute_foreach

#define ice_coll_coll_universe ice_val_coll_universe

ice_val_t *ice_val_new (ice_val_type_t type);
void ice_val_free (ice_val_t *val);
int absolutify_and_validate_pos (int *pos, int size, int allow_append);

ice_val_t *ice_val_new_dict (void);
int ice_val_dict_get (ice_val_t *dictv, const char *key, ice_val_t **val);
int ice_val_dict_set (ice_val_t *dictv, const char *key, ice_val_t *val);
int ice_val_dict_remove (ice_val_t *dictv, const char *key);
int ice_val_dict_clear (ice_val_t *dictv);
int ice_val_dict_get_size (ice_val_t *dictv);
int ice_val_dict_has_key (ice_val_t *dictv, const char *key);

int ice_val_dict_entry_get_string (ice_val_t *val, const char *key, const char **r);
int ice_val_dict_entry_get_int (ice_val_t *val, const char *key, int32_t *r);
int ice_val_dict_entry_get_coll (ice_val_t *val, const char *key, ice_val_coll_t **coll);

int ice_val_dict_set_string (ice_val_t *val, const char *key, const char *el);
int ice_val_dict_set_int (ice_val_t *val, const char *key, int32_t el);
int ice_val_dict_set_coll (ice_val_t *val, const char *key, ice_val_coll_t *el);

/* Utility */
ice_val_type_t ice_val_dict_entry_get_type (ice_val_t *val, const char *key);

typedef void (*ice_val_dict_foreach_func) (const char *key, ice_val_t *value, void *user_data);
int ice_val_dict_foreach (ice_val_t *dictv, ice_val_dict_foreach_func func, void *user_data);

int ice_val_get_dict_iter (const ice_val_t *val, ice_val_dict_iter_t **it);
void ice_val_dict_iter_explicit_destroy (ice_val_dict_iter_t *it);

int  ice_val_dict_iter_pair (ice_val_dict_iter_t *it, const char **key, ice_val_t **val);
int  ice_val_dict_iter_valid (ice_val_dict_iter_t *it);
void ice_val_dict_iter_first (ice_val_dict_iter_t *it);
void ice_val_dict_iter_next (ice_val_dict_iter_t *it);
int  ice_val_dict_iter_find (ice_val_dict_iter_t *it, const char *key);

int  ice_val_dict_iter_set (ice_val_dict_iter_t *it, ice_val_t *val);
int  ice_val_dict_iter_remove (ice_val_dict_iter_t *it);

int ice_val_dict_iter_pair_string (ice_val_dict_iter_t *it, const char **key, const char **r);
int ice_val_dict_iter_pair_int (ice_val_dict_iter_t *it, const char **key, int32_t *r);
int ice_val_dict_iter_pair_coll (ice_val_dict_iter_t *it, const char **key, ice_val_coll_t **r);

int ice_val_dict_iter_set_string (ice_val_dict_iter_t *it, const char *elem);
int ice_val_dict_iter_set_int (ice_val_dict_iter_t *it, int32_t elem);
int ice_val_dict_iter_set_coll (ice_val_dict_iter_t *it, ice_val_coll_t *elem);

ice_val_t *ice_val_bitbuffer_new_ro (const unsigned char *v, int len);
ice_val_t *ice_val_bitbuffer_new (void);
int ice_val_bitbuffer_get_bits (ice_val_t *v, int bits, int *res);
int ice_val_bitbuffer_get_data (ice_val_t *v, unsigned char *b, int len);
int ice_val_bitbuffer_put_bits (ice_val_t *v, int bits, int d);
int ice_val_bitbuffer_put_bits_at (ice_val_t *v, int bits, int d, int offset);
int ice_val_bitbuffer_put_data (ice_val_t *v, const unsigned char *b, int len);
int ice_val_bitbuffer_align (ice_val_t *v);
int ice_val_bitbuffer_goto (ice_val_t *v, int pos);
int ice_val_bitbuffer_pos (ice_val_t *v);
int ice_val_bitbuffer_rewind (ice_val_t *v);
int ice_val_bitbuffer_end (ice_val_t *v);
int ice_val_bitbuffer_len (ice_val_t *v);
const unsigned char *ice_val_bitbuffer_buffer (ice_val_t *v);

int ice_val_bitbuffer_serialize_value (ice_val_t *bb, ice_val_t *v);
int ice_val_bitbuffer_deserialize_value (ice_val_t *bb, ice_val_t **val);

typedef void (*ice_val_list_foreach_func) (ice_val_t *value, void *user_data);
int ice_val_list_foreach (ice_val_t *listv, ice_val_list_foreach_func func, void* user_data);

int ice_val_get_list_iter (const ice_val_t *val, ice_val_list_iter_t **it);
void ice_val_list_iter_explicit_destroy (ice_val_list_iter_t *it);

int  ice_val_list_iter_entry (ice_val_list_iter_t *it, ice_val_t **val);
int  ice_val_list_iter_valid (ice_val_list_iter_t *it);
void ice_val_list_iter_first (ice_val_list_iter_t *it);
void ice_val_list_iter_last (ice_val_list_iter_t *it);
void ice_val_list_iter_next (ice_val_list_iter_t *it);
void ice_val_list_iter_prev (ice_val_list_iter_t *it);
int  ice_val_list_iter_seek (ice_val_list_iter_t *it, int pos);
int  ice_val_list_iter_tell (const ice_val_list_iter_t *it);
ice_val_t *ice_val_list_iter_get_parent (const ice_val_list_iter_t *it);

int  ice_val_list_iter_insert (ice_val_list_iter_t *it, ice_val_t *val);
int  ice_val_list_iter_remove (ice_val_list_iter_t *it);

int ice_val_list_iter_entry_string (ice_val_list_iter_t *it, const char **val);
int ice_val_list_iter_entry_int (ice_val_list_iter_t *it, int32_t *val);
int ice_val_list_iter_entry_coll (ice_val_list_iter_t *it, ice_val_coll_t **val);

int ice_val_list_iter_insert_string (ice_val_list_iter_t *it, const char *val);
int ice_val_list_iter_insert_int (ice_val_list_iter_t *it, int32_t val);
int ice_val_list_iter_insert_coll (ice_val_list_iter_t *it, ice_val_coll_t *val);
int ice_val_utf8_validate (const char *str);


ice_val_t *ice_val_new_list (void);

int ice_val_list_get (ice_val_t *listv, int pos, ice_val_t **val);
int ice_val_list_set (ice_val_t *listv, int pos, ice_val_t *val);
int ice_val_list_append (ice_val_t *listv, ice_val_t *val);
int ice_val_list_insert (ice_val_t *listv, int pos, ice_val_t *val);
int ice_val_list_remove (ice_val_t *listv, int pos);
int ice_val_list_move (ice_val_t *listv, int old_pos, int new_pos);
int ice_val_list_clear (ice_val_t *listv);
int ice_val_list_get_size (ice_val_t *listv);
int ice_val_list_restrict_type (ice_val_t *listv, ice_val_type_t type);

int ice_val_list_get_string (ice_val_t *v, int pos, const char **val);
int ice_val_list_get_int (ice_val_t *v, int pos, int32_t *val);
int ice_val_list_get_coll (ice_val_t *v, int pos, ice_val_coll_t **val);

int ice_val_list_set_string (ice_val_t *v, int pos, const char *val);
int ice_val_list_set_int (ice_val_t *v, int pos, int32_t val);
int ice_val_list_set_coll (ice_val_t *v, int pos, ice_val_coll_t *val);

int ice_val_list_insert_string (ice_val_t *v, int pos, const char *val);
int ice_val_list_insert_int (ice_val_t *v, int pos, int32_t val);
int ice_val_list_insert_coll (ice_val_t *v, int pos, ice_val_coll_t *val);

int ice_val_list_append_string (ice_val_t *v, const char *val);
int ice_val_list_append_int (ice_val_t *v, int32_t val);
int ice_val_list_append_coll (ice_val_t *v, ice_val_coll_t *val);

struct _x_list_t
{
  void * data;
  x_list_t *next;
  x_list_t *prev;
};
#define x_return_if_fail(expr) if (!(expr)) { fprintf (stderr, "Failed in file " __FILE__ " on  row %d\n", __LINE__); return; }
#define x_return_val_if_fail(expr, val) if (!(expr)) { fprintf (stderr, "Failed in file " __FILE__ " on  row %d\n", __LINE__); return val; }
#define x_return_null_if_fail(expr) x_return_val_if_fail (expr, NULL)
#define x_oom() do { fprintf(stderr, "Out of memory in " __FILE__ "on row %d\n", __LINE__); } while (0)
#define x_new0(type, num) calloc (1, sizeof (type) * (num))
#define x_new(type, num) malloc (sizeof (type) * (num))
#define x_malloc0(size) calloc (1, size)
#define x_malloc(size) malloc (size)

#ifdef __cplusplus
}
#endif

#endif /* ice_streamer_H_ */

