#ifndef __INPUT_H__ #define __INPUT_H__ #ifdef HAVE_CONFIG_H # include #endif #include #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__ */