#pragma once
#include "common.h"
#include "types.h"
/// @file inlet.h Stream inlet functions
/** @defgroup lsl_inlet The lsl_inlet object
* @{
*/
/**
* Construct a new stream inlet from a resolved stream info.
* @param info A resolved stream info object (as coming from one of the resolver functions).
* @note The inlet makes a copy of the info object at its construction.
* @note The stream_inlet may also be constructed with a fully-specified stream_info, if the desired
* channel format and count is already known up-front, but this is strongly discouraged and should
* only ever be done if there is no time to resolve the stream up-front (e.g., due to limitations
* in the client program).
* @param max_buflen Optionally the maximum amount of data to buffer (in seconds if there is a
* nominal sampling rate, otherwise x100 in samples).
*
* Recording applications want to use a fairly large buffer size here, while real-time applications
* would only buffer as much as they need to perform their next calculation.
*
* A good default is 360, which corresponds to 6 minutes of data.
* @param max_chunklen Optionally the maximum size, in samples, at which chunks are transmitted.
* If specified as 0, the chunk sizes preferred by the sender are used.
* Recording applications can use a generous size here (leaving it to the network how to pack
* things), while real-time applications may want a finer (perhaps 1-sample) granularity.
* @param recover Try to silently recover lost streams that are recoverable (=those that that have a
* source_id set).
*
* It is generally a good idea to enable this, unless the application wants to act in a special way
* when a data provider has temporarily crashed.
*
* If recover is 0 or the stream is not recoverable, most outlet functions will return an
* #lsl_lost_error if the stream's source is lost.
* @return A newly created lsl_inlet handle or NULL in the event that an error occurred.
*/
extern LIBLSL_C_API lsl_inlet lsl_create_inlet(lsl_streaminfo info, int32_t max_buflen, int32_t max_chunklen, int32_t recover);
/**
* Destructor.
* The inlet will automatically disconnect if destroyed.
*/
extern LIBLSL_C_API void lsl_destroy_inlet(lsl_inlet in);
/**
* Retrieve the complete information of the given stream, including the extended description.
* Can be invoked at any time of the stream's lifetime.
* @param in The lsl_inlet object to act on.
* @param timeout Timeout of the operation. Use LSL_FOREVER to effectively disable it.
* @param[out] ec Error code: if nonzero, can be either lsl_timeout_error (if the timeout has
* expired) or #lsl_lost_error (if the stream source has been lost).
* @return A copy of the full streaminfo of the inlet or NULL in the event that an error happened.
* @note It is the user's responsibility to destroy it when it is no longer needed.
*/
extern LIBLSL_C_API lsl_streaminfo lsl_get_fullinfo(lsl_inlet in, double timeout, int32_t *ec);
/**
* Subscribe to the data stream.
*
* All samples pushed in at the other end from this moment onwards will be queued and
* eventually be delivered in response to pull_sample() calls.
* Pulling a sample without some preceding lsl_open_stream() is permitted (the stream will then be
* opened implicitly).
* @param in The lsl_inlet object to act on.
* @param timeout Optional timeout of the operation. Use LSL_FOREVER to effectively disable it.
* @param[out] ec Error code: if nonzero, can be either #lsl_timeout_error (if the timeout has
* expired) or lsl_lost_error (if the stream source has been lost).
*/
extern LIBLSL_C_API void lsl_open_stream(lsl_inlet in, double timeout, int32_t *ec);
/**
* Drop the current data stream.
*
* All samples that are still buffered or in flight will be dropped and transmission
* and buffering of data for this inlet will be stopped. If an application stops being
* interested in data from a source (temporarily or not) but keeps the outlet alive,
* it should call lsl_close_stream() to not waste unnecessary system and network
* resources.
*/
extern LIBLSL_C_API void lsl_close_stream(lsl_inlet in);
/**
* @brief Retrieve an estimated time correction offset for the given stream.
*
* The first call to this function takes several milliseconds until a reliable first estimate is
* obtained. Subsequent calls are instantaneous (and rely on periodic background updates).
*
* On a well-behaved network, the precision of these estimates should be below 1 ms (empirically it
* is within +/-0.2 ms).
*
* To get a measure of whether the network is well-behaved, use #lsl_time_correction_ex and check
* uncertainty (which maps to round-trip-time). 0.2 ms is typical of wired networks.
*
* 2 ms is typical of wireless networks. The number can be much higher on poor networks.
*
* @param in The lsl_inlet object to act on.
* @param timeout Timeout to acquire the first time-correction estimate.
* Use LSL_FOREVER to defuse the timeout.
* @param[out] ec Error code: if nonzero, can be either #lsl_timeout_error (if the timeout has
* expired) or lsl_lost_error (if the stream source has been lost).
* @return The time correction estimate.
* This is the number that needs to be added to a time stamp that was remotely generated via
* lsl_local_clock() to map it into the local clock domain of this machine.
*/
extern LIBLSL_C_API double lsl_time_correction(lsl_inlet in, double timeout, int32_t *ec);
/** @copydoc lsl_time_correction()
* @param remote_time The current time of the remote computer that was used to generate this
* time_correction.
* If desired, the client can fit time_correction vs remote_time to improve the real-time
* time_correction further.
* @param uncertainty The maximum uncertainty of the given time correction.
*/
extern LIBLSL_C_API double lsl_time_correction_ex(lsl_inlet in, double *remote_time, double *uncertainty, double timeout, int32_t *ec);
/**
* Set post-processing flags to use.
*
* By default, the inlet performs NO post-processing and returns the ground-truth time stamps, which
* can then be manually synchronized using time_correction(), and then smoothed/dejittered if
* desired.
*
* This function allows automating these two and possibly more operations.
* @warning When you enable this, you will no longer receive or be able to recover the original time
* stamps.
* @param in The lsl_inlet object to act on.
* @param flags An integer that is the result of bitwise OR'ing one or more options from
* #lsl_processing_options_t together (e.g., #proc_clocksync|#proc_dejitter);
* a good setting is to use #proc_ALL.
* @return The error code: if nonzero, can be #lsl_argument_error if an unknown flag was passed in.
*/
extern LIBLSL_C_API int32_t lsl_set_postprocessing(lsl_inlet in, uint32_t flags);
/* === Pulling a sample from the inlet === */
/**
* Pull a sample from the inlet and read it into a pointer to values.
* Handles type checking & conversion.
* @param in The #lsl_inlet object to act on.
* @param[out] buffer A pointer to hold the resulting values.
* @param buffer_elements The number of samples allocated in the buffer.
* @attention It is the responsibility of the user to allocate enough memory.
* @param timeout The timeout for this operation, if any.
* Use #LSL_FOREVER to effectively disable it. It is also permitted to use 0.0 here;
* in this case a sample is only returned if one is currently buffered.
* @param[out] ec Error code: can be either no error or #lsl_lost_error
* (if the stream source has been lost).
* @note If the timeout expires before a new sample was received the function returns 0.0;
* ec is *not* set to #lsl_timeout_error (because this case is not considered an error condition).
* @return The capture time of the sample on the remote machine, or 0.0 if no new sample was
* available. To remap this time stamp to the local clock, add the value returned by
* lsl_time_correction() to it.
* @{
*/
extern LIBLSL_C_API double lsl_pull_sample_f(lsl_inlet in, float *buffer, int32_t buffer_elements, double timeout, int32_t *ec);
extern LIBLSL_C_API double lsl_pull_sample_d(lsl_inlet in, double *buffer, int32_t buffer_elements, double timeout, int32_t *ec);
extern LIBLSL_C_API double lsl_pull_sample_l(lsl_inlet in, int64_t *buffer, int32_t buffer_elements, double timeout, int32_t *ec);
extern LIBLSL_C_API double lsl_pull_sample_i(lsl_inlet in, int32_t *buffer, int32_t buffer_elements, double timeout, int32_t *ec);
extern LIBLSL_C_API double lsl_pull_sample_s(lsl_inlet in, int16_t *buffer, int32_t buffer_elements, double timeout, int32_t *ec);
extern LIBLSL_C_API double lsl_pull_sample_c(lsl_inlet in, char *buffer, int32_t buffer_elements, double timeout, int32_t *ec);
extern LIBLSL_C_API double lsl_pull_sample_str(lsl_inlet in, char **buffer, int32_t buffer_elements, double timeout, int32_t *ec);
///@}
/** @copydoc lsl_pull_sample_f
* These strings may contains 0's, therefore the lengths are read into the buffer_lengths array.
* @param buffer_lengths
* A pointer to an array that holds the resulting lengths for each returned binary string.*/
extern LIBLSL_C_API double lsl_pull_sample_buf(lsl_inlet in, char **buffer, uint32_t *buffer_lengths, int32_t buffer_elements, double timeout, int32_t *ec);
/**
* Pull a sample from the inlet and read it into a custom struct or buffer.
*
* Overall size checking but no type checking or conversion are done.
* Do not use for variable-size/string-formatted streams.
* @param in The #lsl_inlet object to act on.
* @param[out] buffer A pointer to hold the resulting values.
* @param buffer_bytes Length of the array held by buffer in bytes, not items
* @param timeout The timeout for this operation, if any.
* Use #LSL_FOREVER to effectively disable it. It is also permitted to use 0.0 here;
* in this case a sample is only returned if one is currently buffered.
* @param[out] ec Error code: can be either no error or #lsl_lost_error
* (if the stream source has been lost).
* @note If the timeout expires before a new sample was received the function returns 0.0;
* ec is *not* set to #lsl_timeout_error (because this case is not considered an error condition).
* @return The capture time of the sample on the remote machine, or 0.0 if no new sample was
* available. To remap this time stamp to the local clock, add the value returned by
* lsl_time_correction() to it.
*/
extern LIBLSL_C_API double lsl_pull_sample_v(lsl_inlet in, void *buffer, int32_t buffer_bytes, double timeout, int32_t *ec);
/**
* Pull a chunk of data from the inlet and read it into a buffer.
*
* Handles type checking & conversion.
*
* @attention Note that the provided data buffer size is measured in channel values (e.g. floats)
* rather than in samples.
* @param in The lsl_inlet object to act on.
* @param[out] data_buffer A pointer to a buffer of data values where the results shall be stored.
* @param[out] timestamp_buffer A pointer to a double buffer where time stamps shall be stored.
*
* If this is NULL, no time stamps will be returned.
* @param data_buffer_elements The size of the data buffer, in channel data elements (of type T).
* Must be a multiple of the stream's channel count.
* @param timestamp_buffer_elements The size of the timestamp buffer.
*
* If a timestamp buffer is provided then this must correspond to the same number of samples as
* data_buffer_elements.
* @param timeout The timeout for this operation, if any.
*
* When the timeout expires, the function may return before the entire buffer is filled.
* The default value of 0.0 will retrieve only data available for immediate pickup.
* @param[out] ec Error code: can be either no error or #lsl_lost_error (if the stream source has
* been lost).
* @note if the timeout expires before a new sample was received the function returns 0.0;
* ec is *not* set to #lsl_timeout_error (because this case is not considered an error condition).
* @return data_elements_written Number of channel data elements written to the data buffer.
* @{
*/
extern LIBLSL_C_API unsigned long lsl_pull_chunk_f(lsl_inlet in, float *data_buffer, double *timestamp_buffer, unsigned long data_buffer_elements, unsigned long timestamp_buffer_elements, double timeout, int32_t *ec);
extern LIBLSL_C_API unsigned long lsl_pull_chunk_d(lsl_inlet in, double *data_buffer, double *timestamp_buffer, unsigned long data_buffer_elements, unsigned long timestamp_buffer_elements, double timeout, int32_t *ec);
extern LIBLSL_C_API unsigned long lsl_pull_chunk_l(lsl_inlet in, int64_t *data_buffer, double *timestamp_buffer, unsigned long data_buffer_elements, unsigned long timestamp_buffer_elements, double timeout, int32_t *ec);
extern LIBLSL_C_API unsigned long lsl_pull_chunk_i(lsl_inlet in, int32_t *data_buffer, double *timestamp_buffer, unsigned long data_buffer_elements, unsigned long timestamp_buffer_elements, double timeout, int32_t *ec);
extern LIBLSL_C_API unsigned long lsl_pull_chunk_s(lsl_inlet in, int16_t *data_buffer, double *timestamp_buffer, unsigned long data_buffer_elements, unsigned long timestamp_buffer_elements, double timeout, int32_t *ec);
extern LIBLSL_C_API unsigned long lsl_pull_chunk_c(lsl_inlet in, char *data_buffer, double *timestamp_buffer, unsigned long data_buffer_elements, unsigned long timestamp_buffer_elements, double timeout, int32_t *ec);
extern LIBLSL_C_API unsigned long lsl_pull_chunk_str(lsl_inlet in, char **data_buffer, double *timestamp_buffer, unsigned long data_buffer_elements, unsigned long timestamp_buffer_elements, double timeout, int32_t *ec);
///@}
/**
* Pull a chunk of data from the inlet and read it into an array of binary strings.
*
* These strings may contains 0's, therefore the lengths are read into the lengths_buffer array.
* Handles type checking & conversion.
* IMPORTANT: Note that the provided data buffer size is measured in channel values (e.g., floats)
* rather than in samples.
* @param in The lsl_inlet object to act on.
* @param[out] data_buffer A pointer to a buffer of data values where the results shall be stored.
* @param[out] lengths_buffer A pointer to an array that holds the resulting lengths for each
* returned binary string.
* @param timestamp_buffer A pointer to a buffer of timestamp values where time stamps shall be
* stored. If this is NULL, no time stamps will be returned.
* @param data_buffer_elements The size of the data buffer, in channel data elements (of type T).
* Must be a multiple of the stream's channel count.
* @param timestamp_buffer_elements The size of the timestamp buffer. If a timestamp buffer is
* provided then this must correspond to the same number of samples as data_buffer_elements.
* @param timeout The timeout for this operation, if any.
*
* When the timeout expires, the function may return before the entire buffer is filled.
*
* The default value of 0.0 will retrieve only data available for immediate pickup.
* @param[out] ec Error code: can be either no error or #lsl_lost_error (if the stream source has
* been lost).
* @note If the timeout expires before a new sample was received the function returns 0.0; ec is
* *not* set to #lsl_timeout_error (because this case is not considered an error condition).
* @return data_elements_written Number of channel data elements written to the data buffer.
*/
extern LIBLSL_C_API unsigned long lsl_pull_chunk_buf(lsl_inlet in, char **data_buffer, uint32_t *lengths_buffer, double *timestamp_buffer, unsigned long data_buffer_elements, unsigned long timestamp_buffer_elements, double timeout, int32_t *ec);
/**
* Query whether samples are currently available for immediate pickup.
*
* Note that it is not a good idea to use samples_available() to determine whether
* a pull_*() call would block: to be sure, set the pull timeout to 0.0 or an acceptably
* low value. If the underlying implementation supports it, the value will be the number of
* samples available (otherwise it will be 1 or 0).
*/
extern LIBLSL_C_API uint32_t lsl_samples_available(lsl_inlet in);
/// Drop all queued not-yet pulled samples, return the nr of dropped samples
extern LIBLSL_C_API uint32_t lsl_inlet_flush(lsl_inlet in);
/**
* Query whether the clock was potentially reset since the last call to lsl_was_clock_reset().
*
* This is rarely-used function is only needed for applications that combine multiple time_correction
* values to estimate precise clock drift if they should tolerate cases where the source machine was
* hot-swapped or restarted.
*/
extern LIBLSL_C_API uint32_t lsl_was_clock_reset(lsl_inlet in);
/**
* Override the half-time (forget factor) of the time-stamp smoothing.
*
* The default is 90 seconds unless a different value is set in the config file.
*
* Using a longer window will yield lower jitter in the time stamps, but longer windows will have
* trouble tracking changes in the clock rate (usually due to temperature changes); the default is
* able to track changes up to 10 degrees C per minute sufficiently well.
* @param in The lsl_inlet object to act on.
* @param value The new value, in seconds. This is the time after which a past sample
* will be weighted by 1/2 in the exponential smoothing window.
* @return The error code: if nonzero, can be #lsl_argument_error if an unknown flag was passed in.
*/
extern LIBLSL_C_API int32_t lsl_smoothing_halftime(lsl_inlet in, float value);
/// @}