|
|
|
/*
|
|
|
|
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
|