#ifndef LSL_C_H #define LSL_C_H #if defined(LIBLSL_FFI) // Skip any typedefs that might confuse a FFI header parser, e.g. cffi #elif defined(_MSC_VER) && _MSC_VER < 1600 typedef signed char int8_t; typedef signed short int16_t; typedef signed int int32_t; typedef signed long long int64_t; typedef unsigned int uint32_t; #else #include #endif #if defined(_MSC_VER) && _MSC_VER < 1900 #define __func__ __FUNCTION__ #endif /** @file lsl_c.h LSL C API for the lab streaming layer * * The lab streaming layer provides a set of functions to make instrument data accessible * in real time within a lab network. From there, streams can be picked up by recording programs, * viewing programs or custom experiment applications that access data streams in real time. * * The API covers two areas: * - The "push API" allows to create stream outlets and to push data (regular or irregular measurement * time series, event data, coded audio/video frames, etc.) into them. * - The "pull API" allows to create stream inlets and read time-synched experiment data from them * (for recording, viewing or experiment control). * * To use this library you need to link to either the liblsl32 or liblsl64 shared library that comes with * this header. Under Visual Studio the library is linked in automatically. * */ /// LIBLSL_C_API expands function attributes needed for the linker #if defined(LIBLSL_STATIC) || defined(LIBLSL_FFI) #define LIBLSL_C_API #elif defined _WIN32 || defined __CYGWIN__ #if defined LIBLSL_EXPORTS #define LIBLSL_C_API __declspec(dllexport) #else #define LIBLSL_C_API __declspec(dllimport) #ifdef _WIN64 #define LSLBITS "64" #else #define LSLBITS "32" #endif #if defined _DEBUG && defined LSL_DEBUG_BINDINGS #define LSLLIBPOSTFIX "-debug" #else #define LSLLIBPOSTFIX "" #endif #ifndef LSLNOAUTOLINK #pragma comment (lib, "liblsl" LSLBITS LSLLIBPOSTFIX ".lib") #endif #endif #pragma warning (disable:4275) #else // Linux / OS X #define LIBLSL_C_API __attribute__((visibility("default"))) #endif #ifdef __cplusplus extern "C" { #endif // Defined constants #include "lsl/constants.h" /* ===================================================== */ /* ==== Objects provided by the lab streaming layer ==== */ /* ===================================================== */ /** * Handle to a stream info object. Stores the declaration of a data stream. * Represents the following information: * * - stream data format (number of channels, channel format) * - core information (stream name, content type, sampling rate) * - optional meta-data about the stream content (channel labels, measurement units, etc.) * * Whenever a program wants to provide a new stream on the lab network it will typically first * create an lsl_streaminfo to describe its properties and then construct an #lsl_outlet with it to * create the stream on the network. Other parties who discover/resolve the outlet on the network * can query the stream info; it is also written to disk when recording the stream (playing a * similar role as a file header). */ typedef struct lsl_streaminfo_struct_ *lsl_streaminfo; /** * A stream outlet handle. * Outlets are used to make streaming data (and the meta-data) available on the lab network. */ typedef struct lsl_outlet_struct_ *lsl_outlet; /** * A stream inlet handle. * Inlets are used to receive streaming data (and meta-data) from the lab network. */ typedef struct lsl_inlet_struct_ *lsl_inlet; /** * A lightweight XML element tree handle; models the description of a streaminfo object. * XML elements behave like advanced pointers into memory that is owned by some respective * streaminfo. * Has a name and can have multiple named children or have text content as value; * attributes are omitted. * @note The interface is modeled after a subset of pugixml's node type and is compatible with it. * Type-casts between pugi::xml_node_struct* and #lsl_xml_ptr are permitted (in both directions) * since the types are binary compatible. * @sa [pugixml documentation](https://pugixml.org/docs/manual.html#access). */ typedef struct lsl_xml_ptr_struct_* lsl_xml_ptr; /** * Handle to a convenience object that resolves streams continuously in the background throughout * its lifetime and which can be queried at any time for the set of streams that are currently * visible on the network. */ typedef struct lsl_continuous_resolver_* lsl_continuous_resolver; // Free functions provided by the lab streaming layer /** LSL version the binary was compiled against * Used either to check if the same version is used * (`if(lsl_protocol_version()!=LIBLSL_COMPILE_HEADER_VERSION`) … * or to require a certain set of features: * ``` * #if LIBLSL_COMPILE_HEADER_VERSION > 113 * do_stuff(); * #endif * ``` * */ #define LIBLSL_COMPILE_HEADER_VERSION 113 /** * Protocol version. * * The major version is `protocol_version() / 100;` * The minor version `is protocol_version() % 100;` * * Clients with different minor versions are protocol-compatible with each other while clients with * different major versions will refuse to work together. */ extern LIBLSL_C_API int32_t lsl_protocol_version(); /** * Version of the liblsl library. * * The major version is `library_version() / 100;` * The minor version is `library_version() % 100;` */ extern LIBLSL_C_API int32_t lsl_library_version(); /** * Get a string containing library information. * * The format of the string shouldn't be used for anything important except giving a debugging * person a good idea which exact library version is used. */ extern LIBLSL_C_API const char *lsl_library_info(); /** * Obtain a local system time stamp in seconds. * * The resolution is better than a millisecond. * This reading can be used to assign time stamps to samples as they are being acquired. * If the "age" of a sample is known at a particular time (e.g., from USB transmission * delays), it can be used as an offset to lsl_local_clock() to obtain a better estimate of * when a sample was actually captured. See lsl_push_sample() for a use case. */ extern LIBLSL_C_API double lsl_local_clock(); /** @defgroup resolve Resolving streams on the network * @{*/ /** * Resolve all streams on the network. * * This function returns all currently available streams from any outlet on the network. * The network is usually the subnet specified at the local router, but may also include a multicast * group of machines (given that the network supports it), or a list of hostnames.
* These details may optionally be customized by the experimenter in a configuration file * (see page Network Connectivity in the LSL wiki). * This is the default mechanism used by the browsing programs and the recording program. * @param[out] buffer A user-allocated buffer to hold the resolve results. * @attention It is the user's responsibility to either destroy the resulting streaminfo objects or * to pass them back to the LSL during during creation of an inlet. * * @attention The stream_info's returned by the resolver are only short versions that do not include * the lsl_get_desc() field (which can be arbitrarily big). * To obtain the full stream information you need to call lsl_get_info() on the inlet after you have * created one. * @param buffer_elements The user-provided buffer length. * @param wait_time The waiting time for the operation, in seconds, to search for streams. * The recommended wait time is 1 second (or 2 for a busy and large recording operation). * @warning If this is too short (<0.5s) only a subset (or none) of the outlets that are present on * the network may be returned. * @return The number of results written into the buffer (never more than the provided # of slots) * or a negative number if an error has occurred (values corresponding to lsl_error_code_t). */ extern LIBLSL_C_API int32_t lsl_resolve_all(lsl_streaminfo *buffer, uint32_t buffer_elements, double wait_time); /** * Resolve all streams with a given value for a property. * * If the goal is to resolve a specific stream, this method is preferred over resolving all streams * and then selecting the desired one. * @param[out] buffer A user-allocated buffer to hold the resolve results. * @attention It is the user's responsibility to either destroy the resulting streaminfo objects or * to pass them back to the LSL during during creation of an inlet. * * @attention The stream_info's returned by the resolver are only short versions that do not include * the lsl_get_desc() field (which can be arbitrarily big). To obtain the full stream information * you need to call lsl_get_info() on the inlet after you have created one. * @param buffer_elements The user-provided buffer length. * @param prop The streaminfo property that should have a specific value (`"name"`, `"type"`, * `"source_id"`, or, e.g., `"desc/manufaturer"` if present). * @param value The string value that the property should have (e.g., "EEG" as the type). * @param minimum Return at least this number of streams. * @param timeout Optionally a timeout of the operation, in seconds (default: no timeout). * If the timeout expires, less than the desired number of streams (possibly none) will be returned. * @return The number of results written into the buffer (never more than the provided # of slots) * or a negative number if an error has occurred (values corresponding to #lsl_error_code_t). */ extern LIBLSL_C_API int32_t lsl_resolve_byprop(lsl_streaminfo *buffer, uint32_t buffer_elements, const char *prop, const char *value, int32_t minimum, double timeout); /** * Resolve all streams that match a given predicate. * * Advanced query that allows to impose more conditions on the retrieved streams; * the given string is an [XPath 1.0 predicate](http://en.wikipedia.org/w/index.php?title=XPath_1.0) * for the `` node (omitting the surrounding []'s) * @param[out] buffer A user-allocated buffer to hold the resolve results. * @attention It is the user's responsibility to either destroy the resulting streaminfo objects or * to pass them back to the LSL during during creation of an inlet. * * @attention The stream_info's returned by the resolver are only short versions that do not include * the lsl_get_desc() field (which can be arbitrarily big). To obtain the full stream information * you need to call lsl_get_info() on the inlet after you have created one. * @param buffer_elements The user-provided buffer length. * @param pred The predicate string, e.g. * `name='BioSemi'` or `type='EEG' and starts-with(name,'BioSemi') and count(info/desc/channel)=32` * @param minimum Return at least this number of streams. * @param timeout Optionally a timeout of the operation, in seconds (default: no timeout). * If the timeout expires, less than the desired number of streams (possibly none) * will be returned. * @return The number of results written into the buffer (never more than the provided # of slots) * or a negative number if an error has occurred (values corresponding to lsl_error_code_t). */ extern LIBLSL_C_API int32_t lsl_resolve_bypred(lsl_streaminfo *buffer, uint32_t buffer_elements, const char *pred, int32_t minimum, double timeout); /// @} /** * Deallocate a string that has been transferred to the application. * * Rarely used: the only use case is to deallocate the contents of * string-valued samples received from LSL in an application where * no free() method is available (e.g., in some scripting languages). */ extern LIBLSL_C_API void lsl_destroy_string(char *s); /** @defgroup streaminfo The lsl_streaminfo object * * The #lsl_streaminfo object keeps a stream's meta data and connection settings. * @{ */ /** * Construct a new streaminfo object. * * Core stream information is specified here. Any remaining meta-data can be added later. * @param name Name of the stream.
* Describes the device (or product series) that this stream makes available * (for use by programs, experimenters or data analysts). Cannot be empty. * @param type Content type of the stream. Please see https://github.com/sccn/xdf/wiki/Meta-Data (or * web search for: XDF meta-data) for pre-defined content-type names, but you can also make up your * own. The content type is the preferred way to find streams (as opposed to searching by name). * @param channel_count Number of channels per sample. * This stays constant for the lifetime of the stream. * @param nominal_srate The sampling rate (in Hz) as advertised by the * datasource, if regular (otherwise set to #LSL_IRREGULAR_RATE). * @param channel_format Format/type of each channel.
* If your channels have different formats, consider supplying multiple streams * or use the largest type that can hold them all (such as #cft_double64). * * A good default is #cft_float32. * @param source_id Unique identifier of the source or device, if available (e.g. a serial number). * Allows recipients to recover from failure even after the serving app or device crashes. * May in some cases also be constructed from device settings. * @return A newly created streaminfo handle or NULL in the event that an error occurred. */ extern LIBLSL_C_API lsl_streaminfo lsl_create_streaminfo(const char *name, const char *type, int32_t channel_count, double nominal_srate, lsl_channel_format_t channel_format, const char *source_id); /// Destroy a previously created streaminfo object. extern LIBLSL_C_API void lsl_destroy_streaminfo(lsl_streaminfo info); /// Copy an existing streaminfo object (rarely used). extern LIBLSL_C_API lsl_streaminfo lsl_copy_streaminfo(lsl_streaminfo info); /** * Name of the stream. * * This is a human-readable name. * For streams offered by device modules, it refers to the type of device or product series that is * generating the data of the stream. If the source is an application, the name may be a more * generic or specific identifier. Multiple streams with the same name can coexist, though * potentially at the cost of ambiguity (for the recording app or experimenter). * @return An immutable library-owned pointer to the string value. @sa lsl_destroy_string() */ extern LIBLSL_C_API const char *lsl_get_name(lsl_streaminfo info); /** * Content type of the stream. * * The content type is a short string such as "EEG", "Gaze" which describes the content carried by * the channel (if known). If a stream contains mixed content this value need not be assigned but * may instead be stored in the description of channel types. To be useful to applications and * automated processing systems using the recommended content types is preferred. Content types * usually follow those pre-defined in the [wiki](https://github.com/sccn/xdf/wiki/Meta-Data) (or * web search for: XDF meta-data). * @return An immutable library-owned pointer to the string value. @sa lsl_destroy_string() */ extern LIBLSL_C_API const char *lsl_get_type(lsl_streaminfo info); /** * Number of channels of the stream. * A stream has at least one channels; the channel count stays constant for all samples. */ extern LIBLSL_C_API int32_t lsl_get_channel_count(lsl_streaminfo info); /** * Sampling rate of the stream, according to the source (in Hz). * * If a stream is irregularly sampled, this should be set to #LSL_IRREGULAR_RATE. * * Note that no data will be lost even if this sampling rate is incorrect or if a device has * temporary hiccups, since all samples will be recorded anyway (except for those dropped by the * device itself). However, when the recording is imported into an application, a good importer may * correct such errors more accurately if the advertised sampling rate was close to the specs of the * device. */ extern LIBLSL_C_API double lsl_get_nominal_srate(lsl_streaminfo info); /** * Channel format of the stream. * All channels in a stream have the same format. * However, a device might offer multiple time-synched streams each with its own format. */ extern LIBLSL_C_API lsl_channel_format_t lsl_get_channel_format(lsl_streaminfo info); /** * Unique identifier of the stream's source, if available. * * The unique source (or device) identifier is an optional piece of information that, if available, * allows that endpoints (such as the recording program) can re-acquire a stream automatically once * it is back online. * @return An immutable library-owned pointer to the string value. @sa lsl_destroy_string() */ extern LIBLSL_C_API const char *lsl_get_source_id(lsl_streaminfo info); /** * Protocol version used to deliver the stream. */ extern LIBLSL_C_API int32_t lsl_get_version(lsl_streaminfo info); /** * Creation time stamp of the stream. * * This is the time stamp when the stream was first created * (as determined via local_clock() on the providing machine). */ extern LIBLSL_C_API double lsl_get_created_at(lsl_streaminfo info); /** * Unique ID of the stream outlet (once assigned). * * This is a unique identifier of the stream outlet, and is guaranteed to be different * across multiple instantiations of the same outlet (e.g., after a re-start). * @return An immutable library-owned pointer to the string value. @sa lsl_destroy_string() */ extern LIBLSL_C_API const char *lsl_get_uid(lsl_streaminfo info); /** * Session ID for the given stream. * * The session id is an optional human-assigned identifier of the recording session. * While it is rarely used, it can be used to prevent concurrent recording activitites * on the same sub-network (e.g., in multiple experiment areas) from seeing each other's streams * (assigned via a configuration file by the experimenter, see Network Connectivity on the LSL * wiki). * @return An immutable library-owned pointer to the string value. @sa lsl_destroy_string() */ extern LIBLSL_C_API const char *lsl_get_session_id(lsl_streaminfo info); /// Hostname of the providing machine (once bound to an outlet). Modification is not permitted. extern LIBLSL_C_API const char *lsl_get_hostname(lsl_streaminfo info); /** * Extended description of the stream. * * It is highly recommended that at least the channel labels are described here. * See code examples on the LSL wiki. Other information, such as amplifier settings, * measurement units if deviating from defaults, setup information, subject information, etc., * can be specified here, as well. Meta-data recommendations follow the XDF file format project * (github.com/sccn/xdf/wiki/Meta-Data or web search for: XDF meta-data). * * @attention if you use a stream content type for which meta-data recommendations exist, please * try to lay out your meta-data in agreement with these recommendations for compatibility with other applications. */ extern LIBLSL_C_API lsl_xml_ptr lsl_get_desc(lsl_streaminfo info); /** * Retrieve the entire streaminfo in XML format. * * This yields an XML document (in string form) whose top-level element is ``. The info * element contains one element for each field of the streaminfo class, including: * * - the core elements ``, ``, ``, * ``, `` * - the misc elements ``, ``, ``, ``, * ``, ``, ``, ``, ``, * `` * - the extended description element `` with user-defined sub-elements. * @return A pointer to a copy of the XML text or NULL in the event that an error occurred. * @note It is the user's responsibility to deallocate this string when it is no longer needed. */ extern LIBLSL_C_API char *lsl_get_xml(lsl_streaminfo info); /// Number of bytes occupied by a channel (0 for string-typed channels). extern LIBLSL_C_API int32_t lsl_get_channel_bytes(lsl_streaminfo info); /// Number of bytes occupied by a sample (0 for string-typed channels). extern LIBLSL_C_API int32_t lsl_get_sample_bytes(lsl_streaminfo info); /** * Tries to match the stream info XML element @p info against an * XPath query. * * Example query strings: * @code * channel_count>5 and type='EEG' * type='TestStream' or contains(name,'Brain') * name='ExampleStream' * @endcode */ extern LIBLSL_C_API int32_t lsl_stream_info_matches_query(lsl_streaminfo info, const char *query); /// Create a streaminfo object from an XML representation extern LIBLSL_C_API lsl_streaminfo lsl_streaminfo_from_xml(const char *xml); /// @} /** @defgroup outlet The lsl_outlet object * * This object represents an outlet sending data to all connected inlets. * * The data is pushed sample-by-sample or chunk-by-chunk into the outlet, and can consist of single- * or multichannel data, regular or irregular sampling rate, with uniform value types (integers, * floats, doubles, strings). * * Streams can have arbitrary XML meta-data (akin to a file header). * By creating an outlet the stream is made visible to a collection of computers (defined by the * network settings/layout) where one can subscribe to it by creating an inlet. * @{ */ /** * Establish a new stream outlet. This makes the stream discoverable. * @param info The stream information to use for creating this stream. * Stays constant over the lifetime of the outlet. * @note the outlet makes a copy of the streaminfo object upon construction (so the old info should * still be destroyed.) * @param chunk_size Optionally the desired chunk granularity (in samples) for transmission. * If specified as 0, each push operation yields one chunk. * Stream recipients can have this setting bypassed. * @param max_buffered Optionally the maximum amount of data to buffer (in seconds if there is a * nominal sampling rate, otherwise x100 in samples). A good default is 360, which corresponds to 6 * minutes of data. Note that, for high-bandwidth data you will almost certainly want to use a lower * value here to avoid running out of RAM. * @return A newly created lsl_outlet handle or NULL in the event that an error occurred. */ extern LIBLSL_C_API lsl_outlet lsl_create_outlet(lsl_streaminfo info, int32_t chunk_size, int32_t max_buffered); /** * Destroy an outlet. * The outlet will no longer be discoverable after destruction and all connected inlets will stop * delivering data. */ extern LIBLSL_C_API void lsl_destroy_outlet(lsl_outlet out); /** Push a pointer to some values as a sample into the outlet. * Handles type checking & conversion. * @param out The lsl_outlet object through which to push the data. * @param data A pointer to values to push. The number of values pointed to must be no less than the * number of channels in the sample. * #lsl_local_clock(); if omitted, the current time is used. * @return Error code of the operation or lsl_no_error if successful (usually attributed to the * wrong data type). * @{ */ extern LIBLSL_C_API int32_t lsl_push_sample_f(lsl_outlet out, const float *data); extern LIBLSL_C_API int32_t lsl_push_sample_d(lsl_outlet out, const double *data); extern LIBLSL_C_API int32_t lsl_push_sample_l(lsl_outlet out, const long *data); extern LIBLSL_C_API int32_t lsl_push_sample_i(lsl_outlet out, const int32_t *data); extern LIBLSL_C_API int32_t lsl_push_sample_s(lsl_outlet out, const int16_t *data); extern LIBLSL_C_API int32_t lsl_push_sample_c(lsl_outlet out, const char *data); extern LIBLSL_C_API int32_t lsl_push_sample_str(lsl_outlet out, const char **data); extern LIBLSL_C_API int32_t lsl_push_sample_v(lsl_outlet out, const void *data); /// @} /** @copydoc lsl_push_sample_f * @param timestamp Optionally the capture time of the sample, in agreement with * @{ */ extern LIBLSL_C_API int32_t lsl_push_sample_ft(lsl_outlet out, const float *data, double timestamp); extern LIBLSL_C_API int32_t lsl_push_sample_dt(lsl_outlet out, const double *data, double timestamp); extern LIBLSL_C_API int32_t lsl_push_sample_lt(lsl_outlet out, const long *data, double timestamp); extern LIBLSL_C_API int32_t lsl_push_sample_it(lsl_outlet out, const int32_t *data, double timestamp); extern LIBLSL_C_API int32_t lsl_push_sample_st(lsl_outlet out, const int16_t *data, double timestamp); extern LIBLSL_C_API int32_t lsl_push_sample_ct(lsl_outlet out, const char *data, double timestamp); extern LIBLSL_C_API int32_t lsl_push_sample_strt(lsl_outlet out, const char **data, double timestamp); extern LIBLSL_C_API int32_t lsl_push_sample_vt(lsl_outlet out, const void *data, double timestamp); /// @} /** @copydoc lsl_push_sample_ft * @param pushthrough Whether to push the sample through to the receivers instead of buffering it * with subsequent samples. Note that the chunk_size, if specified at outlet construction, takes * precedence over the pushthrough flag. * @{ */ extern LIBLSL_C_API int32_t lsl_push_sample_ftp(lsl_outlet out, const float *data, double timestamp, int32_t pushthrough); extern LIBLSL_C_API int32_t lsl_push_sample_dtp(lsl_outlet out, const double *data, double timestamp, int32_t pushthrough); extern LIBLSL_C_API int32_t lsl_push_sample_ltp(lsl_outlet out, const long *data, double timestamp, int32_t pushthrough); extern LIBLSL_C_API int32_t lsl_push_sample_itp(lsl_outlet out, const int32_t *data, double timestamp, int32_t pushthrough); extern LIBLSL_C_API int32_t lsl_push_sample_stp(lsl_outlet out, const int16_t *data, double timestamp, int32_t pushthrough); extern LIBLSL_C_API int32_t lsl_push_sample_ctp(lsl_outlet out, const char *data, double timestamp, int32_t pushthrough); extern LIBLSL_C_API int32_t lsl_push_sample_strtp(lsl_outlet out, const char **data, double timestamp, int32_t pushthrough); extern LIBLSL_C_API int32_t lsl_push_sample_vtp(lsl_outlet out, const void *data, double timestamp, int32_t pushthrough); ///@} /** @copybrief lsl_push_sample_ftp * @see lsl_push_sample_ftp * @param out The lsl_outlet object through which to push the data. * @param data A pointer to values to push. The number of values pointed to must be no less than the number of channels in the sample. * @param lengths A pointer the number of elements to push for each channel (string lengths). */ extern LIBLSL_C_API int32_t lsl_push_sample_buf(lsl_outlet out, const char **data, const uint32_t *lengths); /** @copydoc lsl_push_sample_buf * @param timestamp @see lsl_push_sample_ftp */ extern LIBLSL_C_API int32_t lsl_push_sample_buft(lsl_outlet out, const char **data, const uint32_t *lengths, double timestamp); /** @copydoc lsl_push_sample_buft * @param pushthrough @see lsl_push_sample_ftp */ extern LIBLSL_C_API int32_t lsl_push_sample_buftp(lsl_outlet out, const char **data, const uint32_t *lengths, double timestamp, int32_t pushthrough); /** Push a chunk of multiplexed samples into the outlet. One timestamp per sample is provided. * * @attention Note that the provided buffer size is measured in channel values (e.g. floats) rather * than in samples. * * Handles type checking & conversion. * @param out The lsl_outlet object through which to push the data. * @param data A buffer of channel values holding the data for zero or more successive samples to * send. * @param data_elements The number of data values (of type T) in the data buffer. Must be a multiple * of the channel count. * @return Error code of the operation (usually attributed to the wrong data type). * @{ */ extern LIBLSL_C_API int32_t lsl_push_chunk_f(lsl_outlet out, const float *data, unsigned long data_elements); extern LIBLSL_C_API int32_t lsl_push_chunk_d(lsl_outlet out, const double *data, unsigned long data_elements); extern LIBLSL_C_API int32_t lsl_push_chunk_l(lsl_outlet out, const long *data, unsigned long data_elements); extern LIBLSL_C_API int32_t lsl_push_chunk_i(lsl_outlet out, const int32_t *data, unsigned long data_elements); extern LIBLSL_C_API int32_t lsl_push_chunk_s(lsl_outlet out, const int16_t *data, unsigned long data_elements); extern LIBLSL_C_API int32_t lsl_push_chunk_c(lsl_outlet out, const char *data, unsigned long data_elements); extern LIBLSL_C_API int32_t lsl_push_chunk_str(lsl_outlet out, const char **data, unsigned long data_elements); /// @} /** @copydoc lsl_push_chunk_f * @param timestamp Optionally the capture time of the most recent sample, in agreement with * lsl_local_clock(); if omitted, the current time is used. * The time stamps of other samples are automatically derived based on the sampling rate of the * stream. * @{ */ extern LIBLSL_C_API int32_t lsl_push_chunk_ft(lsl_outlet out, const float *data, unsigned long data_elements, double timestamp); extern LIBLSL_C_API int32_t lsl_push_chunk_dt(lsl_outlet out, const double *data, unsigned long data_elements, double timestamp); extern LIBLSL_C_API int32_t lsl_push_chunk_lt(lsl_outlet out, const long *data, unsigned long data_elements, double timestamp); extern LIBLSL_C_API int32_t lsl_push_chunk_it(lsl_outlet out, const int32_t *data, unsigned long data_elements, double timestamp); extern LIBLSL_C_API int32_t lsl_push_chunk_st(lsl_outlet out, const int16_t *data, unsigned long data_elements, double timestamp); extern LIBLSL_C_API int32_t lsl_push_chunk_ct(lsl_outlet out, const char *data, unsigned long data_elements, double timestamp); extern LIBLSL_C_API int32_t lsl_push_chunk_strt(lsl_outlet out, const char **data, unsigned long data_elements, double timestamp); /// @} /** @copydoc lsl_push_chunk_ft * @param pushthrough Whether to push the chunk through to the receivers instead of buffering it * with subsequent samples. Note that the chunk_size, if specified at outlet construction, takes * precedence over the pushthrough flag. * @{ */ extern LIBLSL_C_API int32_t lsl_push_chunk_ftp(lsl_outlet out, const float *data, unsigned long data_elements, double timestamp, int32_t pushthrough); extern LIBLSL_C_API int32_t lsl_push_chunk_dtp(lsl_outlet out, const double *data, unsigned long data_elements, double timestamp, int32_t pushthrough); extern LIBLSL_C_API int32_t lsl_push_chunk_ltp(lsl_outlet out, const long *data, unsigned long data_elements, double timestamp, int32_t pushthrough); extern LIBLSL_C_API int32_t lsl_push_chunk_itp(lsl_outlet out, const int32_t *data, unsigned long data_elements, double timestamp, int32_t pushthrough); extern LIBLSL_C_API int32_t lsl_push_chunk_stp(lsl_outlet out, const int16_t *data, unsigned long data_elements, double timestamp, int32_t pushthrough); extern LIBLSL_C_API int32_t lsl_push_chunk_ctp(lsl_outlet out, const char *data, unsigned long data_elements, double timestamp, int32_t pushthrough); extern LIBLSL_C_API int32_t lsl_push_chunk_strtp(lsl_outlet out, const char **data, unsigned long data_elements, double timestamp, int32_t pushthrough); /// @} /** @copydoc lsl_push_chunk_f * @param timestamps Buffer holding one time stamp for each sample in the data buffer. * @{ */ extern LIBLSL_C_API int32_t lsl_push_chunk_ftn(lsl_outlet out, const float *data, unsigned long data_elements, const double *timestamps); extern LIBLSL_C_API int32_t lsl_push_chunk_dtn(lsl_outlet out, const double *data, unsigned long data_elements, const double *timestamps); extern LIBLSL_C_API int32_t lsl_push_chunk_ltn(lsl_outlet out, const long *data, unsigned long data_elements, const double *timestamps); extern LIBLSL_C_API int32_t lsl_push_chunk_itn(lsl_outlet out, const int32_t *data, unsigned long data_elements, const double *timestamps); extern LIBLSL_C_API int32_t lsl_push_chunk_stn(lsl_outlet out, const int16_t *data, unsigned long data_elements, const double *timestamps); extern LIBLSL_C_API int32_t lsl_push_chunk_ctn(lsl_outlet out, const char *data, unsigned long data_elements, const double *timestamps); extern LIBLSL_C_API int32_t lsl_push_chunk_strtn(lsl_outlet out, const char **data, unsigned long data_elements, const double *timestamps); /// @} /** @copydoc lsl_push_chunk_ftn * @param pushthrough Whether to push the chunk through to the receivers instead of buffering it * with subsequent samples. Note that the chunk_size, if specified at outlet construction, takes * precedence over the pushthrough flag. * @{ */ extern LIBLSL_C_API int32_t lsl_push_chunk_ftnp(lsl_outlet out, const float *data, unsigned long data_elements, const double *timestamps, int32_t pushthrough); extern LIBLSL_C_API int32_t lsl_push_chunk_dtnp(lsl_outlet out, const double *data, unsigned long data_elements, const double *timestamps, int32_t pushthrough); extern LIBLSL_C_API int32_t lsl_push_chunk_ltnp(lsl_outlet out, const long *data, unsigned long data_elements, const double *timestamps, int32_t pushthrough); extern LIBLSL_C_API int32_t lsl_push_chunk_itnp(lsl_outlet out, const int32_t *data, unsigned long data_elements, const double *timestamps, int32_t pushthrough); extern LIBLSL_C_API int32_t lsl_push_chunk_stnp(lsl_outlet out, const int16_t *data, unsigned long data_elements, const double *timestamps, int32_t pushthrough); extern LIBLSL_C_API int32_t lsl_push_chunk_ctnp(lsl_outlet out, const char *data, unsigned long data_elements, const double *timestamps, int32_t pushthrough); extern LIBLSL_C_API int32_t lsl_push_chunk_strtnp(lsl_outlet out, const char **data, unsigned long data_elements, const double *timestamps, int32_t pushthrough); ///@} /** @copybrief lsl_push_chunk_ftp * @sa lsl_push_chunk_ftp * @param out The lsl_outlet object through which to push the data. * @param data An array of channel values holding the data to push. * @param lengths Pointer the number of elements to push for each value (string lengths) so that * `size(data[i])==lengths[i]`. * @param data_elements The number of data values in the data buffer. * Must be a multiple of the channel count. */ extern LIBLSL_C_API int32_t lsl_push_chunk_buf(lsl_outlet out, const char **data, const uint32_t *lengths, unsigned long data_elements); /** @copydoc lsl_push_chunk_buf @sa lsl_push_chunk_ftp @sa lsl_push_chunk_buf * @param timestamp Optionally the capture time of the most recent sample, in agreement with * lsl_local_clock(); if omitted, the current time is used. * The time stamps of other samples are automatically derived based on the sampling rate of the * stream. */ extern LIBLSL_C_API int32_t lsl_push_chunk_buft(lsl_outlet out, const char **data, const uint32_t *lengths, unsigned long data_elements, double timestamp); /** @copydoc lsl_push_chunk_buft @sa lsl_push_chunk_ftp @sa lsl_push_chunk_buf * @param pushthrough Whether to push the chunk through to the receivers instead of buffering it * with subsequent samples. Note that the chunk_size, if specified at outlet construction, takes * precedence over the pushthrough flag. */ extern LIBLSL_C_API int32_t lsl_push_chunk_buftp(lsl_outlet out, const char **data, const uint32_t *lengths, unsigned long data_elements, double timestamp, int32_t pushthrough); /** @copydoc lsl_push_chunk_buf @sa lsl_push_chunk_ftp @sa lsl_push_chunk_buf * @param timestamps Buffer holding one time stamp for each sample in the data buffer. */ extern LIBLSL_C_API int32_t lsl_push_chunk_buftn(lsl_outlet out, const char **data, const uint32_t *lengths, unsigned long data_elements, const double *timestamps); /** @copydoc lsl_push_chunk_buftn @sa lsl_push_chunk_ftp @sa lsl_push_chunk_buf * @param pushthrough Whether to push the chunk through to the receivers instead of buffering it * with subsequent samples. Note that the chunk_size, if specified at outlet construction, takes * precedence over the pushthrough flag. */ extern LIBLSL_C_API int32_t lsl_push_chunk_buftnp(lsl_outlet out, const char **data, const uint32_t *lengths, unsigned long data_elements, const double *timestamps, int32_t pushthrough); /** * Check whether consumers are currently registered. * While it does not hurt, there is technically no reason to push samples if there is no consumer. */ extern LIBLSL_C_API int32_t lsl_have_consumers(lsl_outlet out); /** * Wait until some consumer shows up (without wasting resources). * @return True if the wait was successful, false if the timeout expired. */ extern LIBLSL_C_API int32_t lsl_wait_for_consumers(lsl_outlet out, double timeout); /** * Retrieve a handle to the stream info provided by this outlet. * This is what was used to create the stream (and also has the Additional Network Information * fields assigned). * @return A copy of the streaminfo of the outlet or NULL in the event that an error occurred. * @note It is the user's responsibility to destroy it when it is no longer needed. * @sa lsl_destroy_string() */ extern LIBLSL_C_API lsl_streaminfo lsl_get_info(lsl_outlet out); ///@} /** @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, long *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, long *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); /** * 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); /// @} /** @defgroup xml_ptr The lsl_xml_ptr object * @{ */ // XML Tree Navigation /** Get the first child of the element. */ extern LIBLSL_C_API lsl_xml_ptr lsl_first_child(lsl_xml_ptr e); /** Get the last child of the element. */ extern LIBLSL_C_API lsl_xml_ptr lsl_last_child(lsl_xml_ptr e); /** Get the next sibling in the children list of the parent node. */ extern LIBLSL_C_API lsl_xml_ptr lsl_next_sibling(lsl_xml_ptr e); /** Get the previous sibling in the children list of the parent node. */ extern LIBLSL_C_API lsl_xml_ptr lsl_previous_sibling(lsl_xml_ptr e); /** Get the parent node. */ extern LIBLSL_C_API lsl_xml_ptr lsl_parent(lsl_xml_ptr e); // XML Tree Navigation by Name /** Get a child with a specified name. */ extern LIBLSL_C_API lsl_xml_ptr lsl_child(lsl_xml_ptr e, const char *name); /** Get the next sibling with the specified name. */ extern LIBLSL_C_API lsl_xml_ptr lsl_next_sibling_n(lsl_xml_ptr e, const char *name); /** Get the previous sibling with the specified name. */ extern LIBLSL_C_API lsl_xml_ptr lsl_previous_sibling_n(lsl_xml_ptr e, const char *name); // Content Queries /** Whether this node is empty. */ extern LIBLSL_C_API int32_t lsl_empty(lsl_xml_ptr e); /** Whether this is a text body (instead of an XML element). True both for plain char data and CData. */ extern LIBLSL_C_API int32_t lsl_is_text(lsl_xml_ptr e); /** Name of the element. */ extern LIBLSL_C_API const char *lsl_name(lsl_xml_ptr e); /** Value of the element. */ extern LIBLSL_C_API const char *lsl_value(lsl_xml_ptr e); /** Get child value (value of the first child that is text). */ extern LIBLSL_C_API const char *lsl_child_value(lsl_xml_ptr e); /** Get child value of a child with a specified name. */ extern LIBLSL_C_API const char *lsl_child_value_n(lsl_xml_ptr e, const char *name); // Data Modification /// Append a child node with a given name, which has a (nameless) plain-text child with the given text value. extern LIBLSL_C_API lsl_xml_ptr lsl_append_child_value(lsl_xml_ptr e, const char *name, const char *value); /// Prepend a child node with a given name, which has a (nameless) plain-text child with the given text value. extern LIBLSL_C_API lsl_xml_ptr lsl_prepend_child_value(lsl_xml_ptr e, const char *name, const char *value); /// Set the text value of the (nameless) plain-text child of a named child node. extern LIBLSL_C_API int32_t lsl_set_child_value(lsl_xml_ptr e, const char *name, const char *value); /** * Set the element's name. * @return 0 if the node is empty (or if out of memory). */ extern LIBLSL_C_API int32_t lsl_set_name(lsl_xml_ptr e, const char *rhs); /** * Set the element's value. * @return 0 if the node is empty (or if out of memory). */ extern LIBLSL_C_API int32_t lsl_set_value(lsl_xml_ptr e, const char *rhs); /** Append a child element with the specified name. */ extern LIBLSL_C_API lsl_xml_ptr lsl_append_child(lsl_xml_ptr e, const char *name); /** Prepend a child element with the specified name. */ extern LIBLSL_C_API lsl_xml_ptr lsl_prepend_child(lsl_xml_ptr e, const char *name); /** Append a copy of the specified element as a child. */ extern LIBLSL_C_API lsl_xml_ptr lsl_append_copy(lsl_xml_ptr e, lsl_xml_ptr e2); /** Prepend a child element with the specified name. */ extern LIBLSL_C_API lsl_xml_ptr lsl_prepend_copy(lsl_xml_ptr e, lsl_xml_ptr e2); /** Remove a child element with the specified name. */ extern LIBLSL_C_API void lsl_remove_child_n(lsl_xml_ptr e, const char *name); /** Remove a specified child element. */ extern LIBLSL_C_API void lsl_remove_child(lsl_xml_ptr e, lsl_xml_ptr e2); /// @} /** @defgroup continuous_resolver The lsl_continuous_resolver * @ingroup resolve * * Streams can be resolved at a single timepoint once (@ref resolve) or continuously in the * background. * @{ */ /** * Construct a new #lsl_continuous_resolver that resolves all streams on the network. * * This is analogous to the functionality offered by the free function lsl_resolve_streams(). * @param forget_after When a stream is no longer visible on the network (e.g. because it was shut * down), this is the time in seconds after which it is no longer reported by the resolver. * * The recommended default value is 5.0. */ extern LIBLSL_C_API lsl_continuous_resolver lsl_create_continuous_resolver(double forget_after); /** * Construct a new lsl_continuous_resolver that resolves all streams with a specific value for a given * property. * * This is analogous to the functionality provided by the free function lsl_resolve_byprop() * @param prop The #lsl_streaminfo property that should have a specific value (e.g., "name", "type", * "source_id", or "desc/manufaturer"). * @param value The string value that the property should have (e.g., "EEG" as the type property). * @param forget_after When a stream is no longer visible on the network (e.g., because it was shut * down), this is the time in seconds after which it is no longer reported by the resolver. * The recommended default value is 5.0. */ extern LIBLSL_C_API lsl_continuous_resolver lsl_create_continuous_resolver_byprop(const char *prop, const char *value, double forget_after); /** * Construct a new lsl_continuous_resolver that resolves all streams that match a given XPath 1.0 * predicate. * * This is analogous to the functionality provided by the free function lsl_resolve_bypred() * @param pred The predicate string, e.g. * `"name='BioSemi'" or "type='EEG' and starts-with(name,'BioSemi') and count(info/desc/channel)=32"` * @param forget_after When a stream is no longer visible on the network (e.g., because it was shut * down), this is the time in seconds after which it is no longer reported by the resolver. * The recommended default value is 5.0. */ extern LIBLSL_C_API lsl_continuous_resolver lsl_create_continuous_resolver_bypred(const char *pred, double forget_after); /** * Obtain the set of currently present streams on the network (i.e. resolve result). * * @param res A continuous resolver (previously created with one of the * lsl_create_continuous_resolver() functions). * @param buffer A user-allocated buffer to hold the current resolve results.
* @attention It is the user's responsibility to either destroy the resulting streaminfo objects or * to pass them back to the LSL during during creation of an inlet. * @attention The stream_infos returned by the resolver are only short versions that do not include * the lsl_get_desc() field (which can be arbitrarily big). * * To obtain the full stream information you need to call lsl_get_info() on the inlet after you have * created one. * @param buffer_elements The user-provided buffer length. * @return The number of results written into the buffer (never more than the provided # of slots) * or a negative number if an error has occurred (values corresponding to #lsl_error_code_t). */ extern LIBLSL_C_API int32_t lsl_resolver_results(lsl_continuous_resolver res, lsl_streaminfo *buffer, uint32_t buffer_elements); /// Destructor for the continuous resolver. extern LIBLSL_C_API void lsl_destroy_continuous_resolver(lsl_continuous_resolver res); /// @} #ifdef __cplusplus } /* end extern "C" */ #endif #endif