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.
131 lines
5.1 KiB
131 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
|
|
|