owntone-server/src/input.h

248 lines
6.3 KiB
C

#ifndef __INPUT_H__
#define __INPUT_H__
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <event2/buffer.h>
#include "db.h"
#include "misc.h"
// Must be in sync with inputs[] in input.c
enum input_types
{
INPUT_TYPE_FILE,
INPUT_TYPE_HTTP,
INPUT_TYPE_PIPE,
INPUT_TYPE_TIMER,
#ifdef SPOTIFY_LIBRESPOTC
INPUT_TYPE_SPOTIFY,
#endif
#ifdef SPOTIFY_LIBSPOTIFY
INPUT_TYPE_LIBSPOTIFY,
#endif
};
enum input_flags
{
// Flags that input is closing current source
INPUT_FLAG_START_NEXT = (1 << 0),
// Flags end of file
INPUT_FLAG_EOF = (1 << 1),
// Flags error reading file
INPUT_FLAG_ERROR = (1 << 2),
// Flags possible new stream metadata
INPUT_FLAG_METADATA = (1 << 3),
// Flags new stream quality
INPUT_FLAG_QUALITY = (1 << 4),
};
struct input_source
{
// Type of input
enum input_types type;
// Item-Id of the file/item in the queue
uint32_t item_id;
// Id of the file/item in the files database
uint32_t id;
// Length of the file/item in milliseconds
uint32_t len_ms;
enum data_kind data_kind;
enum media_kind media_kind;
char *path;
// Flags that the input has been opened (i.e. needs to be closed)
bool open;
// The below is private data for the input backend. It is optional for the
// backend to use, so nothing in the input or player should depend on it!
//
// Opaque pointer to data that the input backend sets up when start() is
// called, and that is cleaned up by the backend when stop() is called
void *input_ctx;
// The input's event base that the input backend can use for own events
struct event_base *evbase;
// Private evbuf. Alloc'ed by backend at start() and free'd at stop()
struct evbuffer *evbuf;
// Private source quality storage
struct media_quality quality;
};
typedef int (*input_cb)(void);
struct input_metadata
{
// queue_item id
uint32_t item_id;
// Input can override the default player progress by setting this. For the
// other fields the receiver can check whether an update happened by checking
// if it is non-zero/null, but not for pos_ms since 0 and even negative values
// are valid.
bool pos_is_updated;
int32_t pos_ms;
// Sets new song length (input will also update queue_item)
uint32_t len_ms;
// Input can update queue_item with the below
char *artist;
char *title;
char *album;
char *genre;
char *artwork_url;
};
struct input_definition
{
// Name of the input
const char *name;
// Type of input
enum input_types type;
// Set to 1 if the input initialization failed
char disabled;
// Prepare a playback session
int (*setup)(struct input_source *source);
// One iteration of the playback loop (= a read operation from source)
int (*play)(struct input_source *source);
// Cleans up (only required when stopping source before it ends itself)
int (*stop)(struct input_source *source);
// Changes the playback position
int (*seek)(struct input_source *source, int seek_ms);
// Return metadata
int (*metadata_get)(struct input_metadata *metadata, struct input_source *source);
// Initialization function called during startup
int (*init)(void);
// Deinitialization function called at shutdown
void (*deinit)(void);
};
/* ---------------------- Interface towards input backends ------------------ */
/* Thread: input */
/*
* Transfer stream data to the player's input buffer. Data must be PCM-LE
* samples. The input evbuf will be drained on succesful write. This is to avoid
* copying memory. Thread-safe.
*
* @in evbuf Raw PCM_LE audio data to write
* @in evbuf Quality of the PCM (sample rate etc.)
* @in flags One or more INPUT_FLAG_*
* @return 0 on success, EAGAIN if buffer was full, -1 on error
*/
int
input_write(struct evbuffer *evbuf, struct media_quality *quality, short flags);
/*
* Input modules can use this to wait for the player to read, so the module's
* playback-loop doesn't spin out of control.
*/
int
input_wait(void);
/* ---------------------- Interface towards player thread ------------------- */
/* Thread: player */
/*
* Move a chunk of stream data from the player's input buffer to an output
* buffer. Should only be called by the player thread. Will not block.
*
* @in data Output buffer
* @in size How much data to move to the output buffer
* @out flag Flag INPUT_FLAG_*
* @out flagdata Data associated with the flag, e.g. quality or metadata struct
* @return Number of bytes moved, -1 on error
*/
int
input_read(void *data, size_t size, short *flag, void **flagdata);
/*
* Player can set this to get a callback from the input when the input buffer
* is full. The player may use this to resume playback after an underrun.
*
* @in cb The callback
*/
void
input_buffer_full_cb(input_cb cb);
/*
* Tells the input to start, i.e. after calling this function the input buffer
* will begin to fill up, and should be read periodically with input_read(). If
* called while another item is still open, it will be closed and the input
* buffer will be flushed. This operation blocks.
*
* @in item_id Queue item id to start playing
* @in seek_ms Position to start playing
* @return Actual seek position if seekable, 0 otherwise, -1 on error
*/
int
input_seek(uint32_t item_id, int seek_ms);
/*
* Same as input_seek(), just non-blocking and does not offer seek.
*
* @in item_id Queue item id to start playing
*/
void
input_start(uint32_t item_id);
/*
* Same as input_seek(), but non-blocking and if the item is already being read
* we don't do anything (no flush & seek)
*
* @in item_id Queue item id to start playing
* @in seek_ms Position to start playing
*/
void
input_resume(uint32_t item_id, int seek_ms);
/*
* Stops the input and clears everything. Flushes the input buffer.
*/
void
input_stop(void);
/*
* Flush input buffer. Output flags will be the same as input_read(). Call with
* null pointer is valid.
*/
void
input_flush(short *flags);
/*
* Free input_metadata
*/
void
input_metadata_free(struct input_metadata *metadata, int content_only);
/*
* Called by player_init (so will run in main thread)
*/
int
input_init(void);
/*
* Called by player_deinit (so will run in main thread)
*/
void
input_deinit(void);
#endif /* !__INPUT_H__ */