mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
parent
d8ab51a9fc
commit
0f533c6d64
10 changed files with 171 additions and 28 deletions
|
|
@ -120,8 +120,7 @@ struct spa_io_clock {
|
|||
struct spa_fraction rate; /**< rate for position/duration/delay/xrun */
|
||||
uint64_t position; /**< current position */
|
||||
uint64_t duration; /**< duration of current cycle */
|
||||
int64_t delay; /**< delay between position and hardware,
|
||||
* positive for capture, negative for playback */
|
||||
int64_t delay; /**< delay between position and hardware */
|
||||
double rate_diff; /**< rate difference between clock and monotonic time */
|
||||
uint64_t next_nsec; /**< estimated next wakeup time in nanoseconds */
|
||||
|
||||
|
|
|
|||
|
|
@ -66,19 +66,57 @@ struct spa_loop_methods {
|
|||
#define SPA_VERSION_LOOP_METHODS 0
|
||||
uint32_t version;
|
||||
|
||||
/** add a source to the loop */
|
||||
/** Add a source to the loop. Must be called from the loop's own thread.
|
||||
*
|
||||
* \param[in] object The callbacks data.
|
||||
* \param[in] source The source.
|
||||
* \return 0 on success, negative errno-style value on failure.
|
||||
*/
|
||||
int (*add_source) (void *object,
|
||||
struct spa_source *source);
|
||||
|
||||
/** update the source io mask */
|
||||
/** Update the source io mask. Must be called from the loop's own thread.
|
||||
*
|
||||
* \param[in] object The callbacks data.
|
||||
* \param[in] source The source.
|
||||
* \return 0 on success, negative errno-style value on failure.
|
||||
*/
|
||||
int (*update_source) (void *object,
|
||||
struct spa_source *source);
|
||||
|
||||
/** remove a source from the loop */
|
||||
/** Remove a source from the loop. Must be called from the loop's own thread.
|
||||
*
|
||||
* \param[in] object The callbacks data.
|
||||
* \param[in] source The source.
|
||||
* \return 0 on success, negative errno-style value on failure.
|
||||
*/
|
||||
int (*remove_source) (void *object,
|
||||
struct spa_source *source);
|
||||
|
||||
/** invoke a function in the context of this loop */
|
||||
/** Invoke a function in the context of this loop.
|
||||
* May be called from the loop's thread, but otherwise
|
||||
* can only be called by a single thread at a time.
|
||||
* If called from the loop's thread, all callbacks previously queued with
|
||||
* invoke() will be run synchronously, which might cause unexpected
|
||||
* reentrancy problems.
|
||||
*
|
||||
* \param[in] object The callbacks data.
|
||||
* \param func The function to be invoked.
|
||||
* \param seq An opaque sequence number. This will be made
|
||||
* available to func.
|
||||
* \param[in] data Data that will be copied into the internal ring buffer and made
|
||||
* available to func. Because this data is copied, it is okay to
|
||||
* pass a pointer to a local variable, but do not pass a pointer to
|
||||
* an object that has identity.
|
||||
* \param size The size of data to copy.
|
||||
* \param block If \true, do not return until func has been called. Otherwise,
|
||||
* returns immediately. Passing \true does not risk a deadlock because
|
||||
* the data thread is never allowed to wait on any other thread.
|
||||
* \param user_data An opaque pointer passed to func.
|
||||
* \return `-EPIPE` if the internal ring buffer filled up,
|
||||
* if block is \false, 0 if seq was SPA_ID_INVALID or
|
||||
* seq with the ASYNC flag set
|
||||
* or the return value of func otherwise. */
|
||||
int (*invoke) (void *object,
|
||||
spa_invoke_func_t func,
|
||||
uint32_t seq,
|
||||
|
|
|
|||
|
|
@ -32,15 +32,17 @@ struct pw_array {
|
|||
size_t extend; /**< number of bytes to extend with */
|
||||
};
|
||||
|
||||
/** Initialize an array. The new array is empty. */
|
||||
#define PW_ARRAY_INIT(extend) ((struct pw_array) { NULL, 0, 0, (extend) })
|
||||
|
||||
/** Return the length of an array. */
|
||||
#define pw_array_get_len_s(a,s) ((a)->size / (s))
|
||||
#define pw_array_get_unchecked_s(a,idx,s,t) SPA_PTROFF((a)->data,(idx)*(s),t)
|
||||
#define pw_array_check_index_s(a,idx,s) ((idx) < pw_array_get_len_s(a,s))
|
||||
|
||||
/** Get the number of items of type \a t in array */
|
||||
#define pw_array_get_len(a,t) pw_array_get_len_s(a,sizeof(t))
|
||||
/** Get the item with index \a idx and type \a t from array */
|
||||
/** Get the item with index \a idx and type \a t from array. No bounds check is done. */
|
||||
#define pw_array_get_unchecked(a,idx,t) pw_array_get_unchecked_s(a,idx,sizeof(t),t)
|
||||
/** Check if an item with index \a idx and type \a t exist in array */
|
||||
#define pw_array_check_index(a,idx,t) pw_array_check_index_s(a,idx,sizeof(t))
|
||||
|
|
@ -110,7 +112,8 @@ static inline int pw_array_ensure_size(struct pw_array *arr, size_t size)
|
|||
}
|
||||
|
||||
/** Add \a ref size bytes to \a arr. A pointer to memory that can
|
||||
* hold at least \a size bytes is returned */
|
||||
* hold at least \a size bytes is returned or NULL when an error occured
|
||||
* and errno will be set.*/
|
||||
static inline void *pw_array_add(struct pw_array *arr, size_t size)
|
||||
{
|
||||
void *p;
|
||||
|
|
|
|||
|
|
@ -71,10 +71,17 @@ struct pw_context_events {
|
|||
void (*driver_removed) (void *data, struct pw_impl_node *node);
|
||||
};
|
||||
|
||||
/** Make a new context object for a given main_loop. Ownership of the properties is taken */
|
||||
struct pw_context * pw_context_new(struct pw_loop *main_loop, /**< a main loop to run in */
|
||||
struct pw_properties *props, /**< extra properties */
|
||||
size_t user_data_size /**< extra user data size */);
|
||||
/** Make a new context object for a given main_loop. Ownership of the properties is taken, even
|
||||
* if the function returns NULL.
|
||||
*
|
||||
* \param main_loop A main loop to run in. This must stay alive unil pw_context_destroy() is called.
|
||||
* \param props extra properties
|
||||
* \param user_data_size extra user data size
|
||||
* \return The context object on success, or NULL on failure, in which case errno is set.
|
||||
* */
|
||||
struct pw_context * pw_context_new(struct pw_loop *main_loop,
|
||||
struct pw_properties *props,
|
||||
size_t user_data_size);
|
||||
|
||||
/** destroy a context object, all resources except the main_loop will be destroyed */
|
||||
void pw_context_destroy(struct pw_context *context);
|
||||
|
|
@ -119,16 +126,17 @@ int pw_context_conf_section_match_rules(struct pw_context *context, const char *
|
|||
/** Get the context support objects */
|
||||
const struct spa_support *pw_context_get_support(struct pw_context *context, uint32_t *n_support);
|
||||
|
||||
/** get the context main loop */
|
||||
/** Get the context main loop. Returns the value passed to pw_context_new(). */
|
||||
struct pw_loop *pw_context_get_main_loop(struct pw_context *context);
|
||||
|
||||
/** get the context data loop. Since 0.3.56 */
|
||||
/** Get the context data loop. This loop runs on the realtime thread.
|
||||
* Since 0.3.56 */
|
||||
struct pw_data_loop *pw_context_get_data_loop(struct pw_context *context);
|
||||
|
||||
/** Get the work queue from the context: Since 0.3.26 */
|
||||
struct pw_work_queue *pw_context_get_work_queue(struct pw_context *context);
|
||||
|
||||
/** Get the memmory pool from the context: Since 0.3.74 */
|
||||
/** Get the memory pool from the context: Since 0.3.74 */
|
||||
struct pw_mempool *pw_context_get_mempool(struct pw_context *context);
|
||||
|
||||
/** Iterate the globals of the context. The callback should return
|
||||
|
|
@ -139,7 +147,10 @@ int pw_context_for_each_global(struct pw_context *context,
|
|||
int (*callback) (void *data, struct pw_global *global),
|
||||
void *data);
|
||||
|
||||
/** Find a context global by id */
|
||||
/** Find a context global by id.
|
||||
*
|
||||
* \return The global on success, or NULL on failure. If id is \ref PW_ID_CORE,
|
||||
* this function will always return a non-NULL value. */
|
||||
struct pw_global *pw_context_find_global(struct pw_context *context, /**< the context */
|
||||
uint32_t id /**< the global id */);
|
||||
|
||||
|
|
@ -149,6 +160,7 @@ int pw_context_add_spa_lib(struct pw_context *context, const char *factory_regex
|
|||
/** find the library name for a spa factory */
|
||||
const char * pw_context_find_spa_lib(struct pw_context *context, const char *factory_name);
|
||||
|
||||
/** Load a SPA handle from a context. On failure returns NULL and sets errno. */
|
||||
struct spa_handle *pw_context_load_spa_handle(struct pw_context *context,
|
||||
const char *factory_name,
|
||||
const struct spa_dict *info);
|
||||
|
|
@ -169,9 +181,21 @@ int pw_context_register_export_type(struct pw_context *context, struct pw_export
|
|||
/** find information about registered export type */
|
||||
const struct pw_export_type *pw_context_find_export_type(struct pw_context *context, const char *type);
|
||||
|
||||
/** add an object to the context */
|
||||
/** add an object to the context
|
||||
*
|
||||
* \param context The context.
|
||||
* \param type The type of the object, usually a `TYPE_INTERFACE_` value.
|
||||
* \param value The object value. Must last as long as the context and must
|
||||
* be of the type corresponding to the type.
|
||||
* \return A negative number on failure (out of memory).
|
||||
* */
|
||||
int pw_context_set_object(struct pw_context *context, const char *type, void *value);
|
||||
/** get an object from the context */
|
||||
/** get an object from the context
|
||||
*
|
||||
* \param context The context.
|
||||
* \param type The string corresponding to the object's interface.
|
||||
* \return The object, or NULL if the object does not exist.
|
||||
* */
|
||||
void *pw_context_get_object(struct pw_context *context, const char *type);
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -45,7 +45,8 @@ struct pw_control_events {
|
|||
/** Get the control parent port or NULL when not set */
|
||||
struct pw_impl_port *pw_control_get_port(struct pw_control *control);
|
||||
|
||||
/** Add an event listener on the control */
|
||||
/** Add an event listener on the control. May be called multiple times.
|
||||
* Each listener must be removed, but they may be removed in any order. */
|
||||
void pw_control_add_listener(struct pw_control *control,
|
||||
struct spa_hook *listener,
|
||||
const struct pw_control_events *events,
|
||||
|
|
|
|||
|
|
@ -69,11 +69,13 @@ struct pw_core_info {
|
|||
#include <pipewire/properties.h>
|
||||
#include <pipewire/proxy.h>
|
||||
|
||||
/** Update an existing \ref pw_core_info with \a update with reset */
|
||||
/** Update an existing \ref pw_core_info with \a update with reset. When info is NULL,
|
||||
* a new one will be allocated. Returns NULL on failure. */
|
||||
struct pw_core_info *
|
||||
pw_core_info_update(struct pw_core_info *info,
|
||||
const struct pw_core_info *update);
|
||||
/** Update an existing \ref pw_core_info with \a update */
|
||||
/** Update an existing \ref pw_core_info with \a update. When info is NULL, a new one
|
||||
* will be allocated. Returns NULL on failure */
|
||||
struct pw_core_info *
|
||||
pw_core_info_merge(struct pw_core_info *info,
|
||||
const struct pw_core_info *update, bool reset);
|
||||
|
|
@ -164,6 +166,9 @@ struct pw_core_events {
|
|||
* global ID. It is emitted before the global becomes visible in the
|
||||
* registry.
|
||||
*
|
||||
* The bound_props event is an enhanced version of this event that
|
||||
* also contains the extra global properties.
|
||||
*
|
||||
* \param id bound object ID
|
||||
* \param global_id the global id bound to
|
||||
*/
|
||||
|
|
@ -192,6 +197,19 @@ struct pw_core_events {
|
|||
*/
|
||||
void (*remove_mem) (void *data, uint32_t id);
|
||||
|
||||
/**
|
||||
* Notify an object binding
|
||||
*
|
||||
* This event is emitted when a local object ID is bound to a
|
||||
* global ID. It is emitted before the global becomes visible in the
|
||||
* registry.
|
||||
*
|
||||
* This is an enhanced version of the bound_id event.
|
||||
*
|
||||
* \param id bound object ID
|
||||
* \param global_id the global id bound to
|
||||
* \param props The properties of the new global object.
|
||||
*/
|
||||
void (*bound_props) (void *data, uint32_t id, uint32_t global_id, const struct spa_dict *props);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -67,13 +67,38 @@ int pw_data_loop_start(struct pw_data_loop *loop);
|
|||
/** Stop the processing thread */
|
||||
int pw_data_loop_stop(struct pw_data_loop *loop);
|
||||
|
||||
/** Check if the current thread is the processing thread */
|
||||
/** Check if the current thread is the processing thread.
|
||||
* May be called from any thread. */
|
||||
bool pw_data_loop_in_thread(struct pw_data_loop *loop);
|
||||
/** Get the thread object */
|
||||
struct spa_thread *pw_data_loop_get_thread(struct pw_data_loop *loop);
|
||||
|
||||
/** invoke func in the context of the thread or in the caller thread when
|
||||
* the loop is not running. Since 0.3.3 */
|
||||
* the loop is not running. May be called from the loop's thread, but otherwise
|
||||
* can only be called by a single thread at a time.
|
||||
* If called from the loop's thread, all callbacks previously queued with
|
||||
* pw_data_loop_invoke() will be run synchronously, which might cause
|
||||
* unexpected reentrancy problems.
|
||||
*
|
||||
* \param[in] loop The loop to invoke func on.
|
||||
* \param func The function to be invoked.
|
||||
* \param seq A sequence number, opaque to PipeWire. This will be made
|
||||
* available to func.
|
||||
* \param[in] data Data that will be copied into the internal ring buffer and made
|
||||
* available to func. Because this data is copied, it is okay to
|
||||
* pass a pointer to a local variable, but do not pass a pointer to
|
||||
* an object that has identity.
|
||||
* \param size The size of data to copy.
|
||||
* \param block If \true, do not return until func has been called. Otherwise,
|
||||
* returns immediately. Passing \true does not risk a deadlock because
|
||||
* the data thread is never allowed to wait on any other thread.
|
||||
* \param user_data An opaque pointer passed to func.
|
||||
* \return `-EPIPE` if the internal ring buffer filled up,
|
||||
* if block is \false, 0 is returned when seq is SPA_ID_INVALID or the
|
||||
* sequence number with the ASYNC bit set otherwise. When block is \true,
|
||||
* the return value of func is returned.
|
||||
*
|
||||
* Since 0.3.3 */
|
||||
int pw_data_loop_invoke(struct pw_data_loop *loop,
|
||||
spa_invoke_func_t func, uint32_t seq, const void *data, size_t size,
|
||||
bool block, void *user_data);
|
||||
|
|
|
|||
|
|
@ -45,9 +45,10 @@ struct pw_impl_module_events {
|
|||
#define PW_VERSION_IMPL_MODULE_EVENTS 0
|
||||
uint32_t version;
|
||||
|
||||
/** The module is destroyed */
|
||||
/** The module is destroyed. This is the time to unregister and
|
||||
* destroy any objects created by the module. */
|
||||
void (*destroy) (void *data);
|
||||
/** The module is freed */
|
||||
/** The module is freed. This will be called after destroy() returns. */
|
||||
void (*free) (void *data);
|
||||
/** The module is initialized */
|
||||
void (*initialized) (void *data);
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ extern "C" {
|
|||
* PipeWire loop object provides an implementation of
|
||||
* the spa loop interfaces. It can be used to implement various
|
||||
* event loops.
|
||||
*
|
||||
* The members of \ref pw_loop are read-only.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -58,11 +58,15 @@ extern "C" {
|
|||
|
||||
* \li PW_DIRECTION_INPUT for a stream that *consumes* data. This can be a
|
||||
* stream that captures from a Source or a when the stream is used to
|
||||
* implement a Sink.
|
||||
* implement a Sink. An application will use a \ref PW_DIRECTION_INPUT
|
||||
* stream to record data. A virtual sound card will use a
|
||||
* \ref PW_DIRECTION_INPUT stream to implement audio playback.
|
||||
*
|
||||
* \li PW_DIRECTION_OUTPUT for a stream that *produces* data. This can be a
|
||||
* stream that plays to a Sink or when the stream is used to implement
|
||||
* a Source.
|
||||
* a Source. An application will use a \ref PW_DIRECTION_OUTPUT
|
||||
* stream to produce data. A virtual sound card or camera will use a
|
||||
* \ref PW_DIRECTION_OUTPUT stream to implement audio or video recording.
|
||||
*
|
||||
* \subsection ssec_stream_target Stream target
|
||||
*
|
||||
|
|
@ -141,6 +145,18 @@ extern "C" {
|
|||
* The process event is emitted when PipeWire has emptied a buffer that
|
||||
* can now be refilled.
|
||||
*
|
||||
* \section sec_stream_driving Driving the graph
|
||||
*
|
||||
* Starting in 0.3.34, it is possible for a stream to drive the graph.
|
||||
* This allows interrupt-driven scheduling for drivers implemented as
|
||||
* PipeWire streams, without having to reimplement the stream as a SPA
|
||||
* plugin.
|
||||
*
|
||||
* A stream cannot drive the graph unless it is in the
|
||||
* \ref PW_STREAM_STATE_STREAMING state and \ref pw_stream_is_driving() returns
|
||||
* true. It must then use pw_stream_trigger_process() to start the graph
|
||||
* cycle.
|
||||
*
|
||||
* \section sec_stream_disconnect Disconnect
|
||||
*
|
||||
* Use \ref pw_stream_disconnect() to disconnect a stream after use.
|
||||
|
|
@ -528,7 +544,23 @@ int pw_stream_flush(struct pw_stream *stream, bool drain);
|
|||
bool pw_stream_is_driving(struct pw_stream *stream);
|
||||
|
||||
/** Trigger a push/pull on the stream. One iteration of the graph will
|
||||
* scheduled and process() will be called. Since 0.3.34 */
|
||||
* be scheduled. If it successfully finishes, process() will be called.
|
||||
* It is possible for the graph iteration to not finish, so
|
||||
* pw_stream_trigger_process() needs to be called again even if process()
|
||||
* is not called.
|
||||
*
|
||||
* If there is a deadline after which the stream will have xrun,
|
||||
* pw_stream_trigger_process() should be called then, whether or not
|
||||
* process() has been called. Sound hardware will xrun if there is
|
||||
* any delay in audio processing, so the ALSA plugin triggers the
|
||||
* graph every quantum to ensure audio keeps flowing. Drivers that
|
||||
* do not have a deadline, such as the freewheel driver, should
|
||||
* use a timeout to ensure that forward progress keeps being made.
|
||||
* A reasonable choice of deadline is three times the quantum: if
|
||||
* the graph is taking 3x longer than normal, it is likely that it
|
||||
* is hung and should be retriggered.
|
||||
*
|
||||
* Since 0.3.34 */
|
||||
int pw_stream_trigger_process(struct pw_stream *stream);
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue