Xash3D FWGS engine.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

132 lines
5.1 KiB

/*
reader.h - compact version of famous library mpg123
Copyright (C) 2017 Uncle Mike
This program 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.
This program 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.
*/
#ifndef READER_H
#define READER_H
#define READER_FD_OPENED 0x1
#define READER_ID3TAG 0x2
#define READER_SEEKABLE 0x4
#define READER_BUFFERED 0x8
#define READER_NONBLOCK 0x20
#define READER_HANDLEIO 0x40
typedef struct buffy_s
{
byte *data;
mpg_ssize_t size;
mpg_ssize_t realsize;
struct buffy_s *next;
} buffy_t;
typedef struct bufferchain_s
{
struct buffy_s *first; // the beginning of the chain.
struct buffy_s *last; // the end... of the chain.
mpg_ssize_t size; // aggregated size of all buffies.
// these positions are relative to buffer chain beginning.
mpg_ssize_t pos; // position in whole chain.
mpg_ssize_t firstpos; // the point of return on non-forget()
// the "real" filepos is fileoff + pos.
mpg_off_t fileoff; // beginning of chain is at this file offset.
size_t bufblock; // default (minimal) size of buffers.
size_t pool_size; // keep that many buffers in storage.
size_t pool_fill; // that many buffers are there.
// a pool of buffers to re-use, if activated. It's a linked list that is worked on from the front.
struct buffy_s *pool;
} bufferchain_t;
// call this before any buffer chain use (even bc_init()).
void bc_prepare( bufferchain_t*, size_t pool_size, size_t bufblock );
// free persistent data in the buffer chain, after bc_reset().
void bc_cleanup( bufferchain_t* );
// change pool size. This does not actually allocate/free anything on itself, just instructs later operations to free less / allocate more buffers.
void bc_poolsize( bufferchain_t*, size_t pool_size, size_t bufblock );
// return available byte count in the buffer.
size_t bc_fill( bufferchain_t *bc );
typedef struct reader_data_s
{
mpg_off_t filelen; // total file length or total buffer size
mpg_off_t filepos; // position in file or position in buffer chain
int filept;
// custom opaque I/O handle from the client.
void *iohandle;
int flags;
long timeout_sec;
mpg_ssize_t (*fdread)( mpg123_handle_t*, void*, size_t );
// user can replace the read and lseek functions. The r_* are the stored replacement functions or NULL.
mpg_ssize_t (*r_read)( int fd, void *buf, size_t count );
mpg_off_t (*r_lseek)( int fd, mpg_off_t offset, int whence );
// These are custom I/O routines for opaque user handles.
// They get picked if there's some iohandle set.
mpg_ssize_t (*r_read_handle)( void *handle, void *buf, size_t count );
mpg_off_t (*r_lseek_handle)( void *handle, mpg_off_t offset, int whence );
// an optional cleaner for the handle on closing the stream.
void (*cleanup_handle)( void *handle );
// these two pointers are the actual workers (default map to POSIX read/lseek).
mpg_ssize_t (*read)( int fd, void *buf, size_t count );
mpg_off_t (*lseek)( int fd, mpg_off_t offset, int whence );
// buffered readers want that abstracted, set internally.
mpg_ssize_t (*fullread)( mpg123_handle_t*, byte*, mpg_ssize_t );
bufferchain_t buffer; // not dynamically allocated, these few struct bytes aren't worth the trouble.
} reader_data_t;
// start to use mpg_off_t to properly do LFS in future ... used to be long
typedef struct reader_s
{
int (*init)( mpg123_handle_t* );
void (*close)( mpg123_handle_t* );
mpg_ssize_t (*fullread)( mpg123_handle_t*, byte*, mpg_ssize_t);
int (*head_read)( mpg123_handle_t*, ulong *newhead ); // succ: TRUE, else <= 0 (FALSE or READER_MORE)
int (*head_shift)( mpg123_handle_t*, ulong *head ); // succ: TRUE, else <= 0 (FALSE or READER_MORE)
mpg_off_t (*skip_bytes)( mpg123_handle_t*, mpg_off_t len ); // succ: >=0, else error or READER_MORE
int (*read_frame_body)( mpg123_handle_t*, byte*, int size );
int (*back_bytes)( mpg123_handle_t*, mpg_off_t bytes );
int (*seek_frame)( mpg123_handle_t*, mpg_off_t num );
mpg_off_t (*tell)( mpg123_handle_t* );
void (*rewind)( mpg123_handle_t* );
void (*forget)( mpg123_handle_t* );
} reader_t;
// open a file by path or use an opened file descriptor
int open_stream( mpg123_handle_t *fr, const char *path, int fd );
// open an external handle.
int open_stream_handle( mpg123_handle_t *fr, void *iohandle );
// feed based operation has some specials
int open_feed( mpg123_handle_t *fr );
// externally called function, returns 0 on success, -1 on error
int feed_more( mpg123_handle_t *fr, const byte *in, long count );
// forget the data that has been read (free some buffers)
void feed_forget( mpg123_handle_t *fr );
// set position (inside available data if possible), return wanted byte offset of next feed.
mpg_off_t feed_set_pos( mpg123_handle_t *fr, mpg_off_t pos );
// error fallback
void open_bad( mpg123_handle_t *fr );
#endif//READER_H