Commit 1aaf4c6c authored by Günter Windau's avatar Günter Windau

added lsl win64 binaries

parent a556f192
This is liblsl-Matlab 1.13.0_b13 downloaded from https://github.com/labstreaminglayer/liblsl-Matlab/releases
% This file is here only so that you can put this directory into the dependencies folder of a BCILAB installation.
\ No newline at end of file
classdef lsl_inlet < handle
% A stream inlet.
% Inlets are used to receive streaming data (and meta-data) from the lab network.
%
% Note:
% Most functions of the inlet can throw an error of type 'lsl:lost_error' if the stream
% read by this inlet has been lost irretrievably. Those functions that take a timeout can in
% addition throw an error of type 'lsl:timeout_error'.
properties (Hidden)
LibHandle = 0; % this is a handle to the liblsl library (to call its functions)
InletHandle = 0; % this is a handle to an lsl_inlet object within the library.
ChannelCount = 0; % copy of the inlet's channel count
IsString = 0; % whether this is a string-formatted inlet
end
methods
function self = lsl_inlet(info, maxbuffered, chunksize, recover, process)
% Inlet = lsl_inlet(Streaminfo, MaxBuffered, ChunkSize, Recover)
% Construct a new stream inlet from a resolved stream info.
%
% In:
% Streaminfo : A resolved stream info object (as coming from one of the lsl_resolve_* functions).
%
% MaxBuffered : 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. (default: 360)
%
% ChunkSize : Optionally the maximum size, in samples, at which chunks are transmitted
% (0 corresponds to the chunk sizes used by the sender).
% 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.
% (default 0)
%
% Recover : Try to silently recover lost streams that are recoverable (=those that that have a source_id set).
% In all other cases (recover is false or the stream is not recoverable) functions may throw a
% lost_error if the stream's source is lost (e.g., due to an app or computer crash).
% (default: 1)
%
if ~exist('maxbuffered','var') || isempty(maxbuffered) maxbuffered = 360; end
if ~exist('chunksize','var') || isempty(chunksize) chunksize = 0; end
if ~exist('recover','var') || isempty(recover) recover = 1; end
self.LibHandle = info.LibHandle;
self.ChannelCount = info.channel_count();
self.IsString = strcmp(info.channel_format(),'cf_string');
self.InletHandle = lsl_create_inlet(info.LibHandle,info.InfoHandle,maxbuffered,chunksize,recover);
end
function delete(self)
% Destroy the inlet when it is deleted.
% The inlet will automatically disconnect if destroyed.
lsl_destroy_inlet(self.LibHandle,self.InletHandle);
end
function result = info(self, timeout)
% Retrieve the complete information of the given stream, including the extended description.
% Fullinfo = info(Timeout)
%
% Can be invoked at any point of the stream's lifetime.
%
% In:
% Timeout : Timeout of the operation, in seconds (default: 60).
%
% Out:
% Fullinfo : the full information, including description field, of the stream.
if ~exist('timeout','var') || isempty(timeout) timeout = 60; end
result = lsl_streaminfo(self.LibHandle,lsl_get_fullinfo(self.LibHandle, self.InletHandle, timeout));
end
function open_stream(self, timeout)
% Subscribe to the data stream from this moment onwards.
% open_stream(Timeout)
%
% All samples pushed in at the other end from this moment onwards will be queued and
% eventually be delivered in response to pull_sample() or pull_chunk() calls.
% Pulling a sample without some preceding open_stream is permitted (the stream will then
% be opened implicitly).
%
% In:
% Timeout : Timeout of the operation (default: 60).
%
% Out:
% Fullinfo : the full information, including description field, of the stream.
if ~exist('timeout','var') || isempty(timeout) timeout = 60; end
lsl_open_stream(self.LibHandle, self.InletHandle, timeout);
end
function close_stream(self)
% Drop the current data stream.
% close_stream()
%
% All samples that are still buffered or in flight will be dropped and the source will halt its buffering of data for this inlet.
% If an application stops being interested in data from a source (temporarily or not) but keeps the outlet alive, it should
% call close_streams() to not pressure the source outlet to buffer unnecessarily large amounts of data.
lsl_close_stream(self.LibHandle, self.InletHandle);
end
function result = time_correction(self,timeout)
% Retrieve an estimated time correction offset for the given stream.
%
% The first call to this function takes several miliseconds until a reliable first estimate is obtained.
% Subsequent calls are instantaneous (and rely on periodic background updates).
% The precision of these estimates should be below 1 ms (empirically within +/-0.2 ms).
%
% In:
% Timeout : Timeout to acquire the first time-correction estimate (default: 60).
%
% Out:
% Offset : The time correction estimate. If the first estimate cannot within the alloted time,
% the result is NaN.
if ~exist('timeout','var') || isempty(timeout) timeout = 60; end
result = lsl_time_correction(self.LibHandle, self.InletHandle,timeout);
end
function result = set_postprocessing(self, processing_flags)
% Set timestamp correction postprocessing flags. This should
% only be done in online scenarios. This option will destroy a
% stream's original, ground-truth timestamps.
%
% In:
% processing_flags :
% 0 : no automatic post_processing
% 1 : perform automatic clock synchronization
% 2 : remove jitter from time stamps
% 4 : force time-stamps to be monotonically ascending (only makes sense if also dejittered)
% 8 : post-processing is threadsafe (same inlet can be read from by multiple threads)
% 15 : combination of all options
% These options can be combined by adding them
% (default: proc_none)
if ~exist('processing_flags','var') || isempty(processing_flags) processing_flags = 0; end
lsl_set_postprocessing(self.LibHandle, self.InletHandle, processing_flags);
end
function [data,timestamp] = pull_sample(self,timeout,binary_blobs)
% Pull a sample from the inlet and read it into an array of values.
% [SampleData,Timestamp] = pull_sample(Timeout)
%
% In:
% Timeout : The timeout for this operation, if any. (default: 60)
% Use 0 to make the function non-blocking.
%
% Out:
% SampleData : The sample's contents. This is either a numeric vector (type: double) if
% the stream holds numeric contents, or a cell array of strings if the stream
% is string-formatted, or a cell array of uint8 vectors if BinaryBlobs is set
% to true.
%
% Note: this is empty if the operation times out.
%
% Timeout : Timeout for the operation. (default: 60)
%
% BinaryBlobs : If true, strings will be received as uint8
% arrays that may contain the \0 character.
% Otherwise strings will be received as char,
% which cannot contain \0's. (default: false)
%
% Notes:
% It is not a good idea to set the timeout to a very large value since MATLAB would
% otherwise become unresponsive - better call pull_sample in a loop until it succeeds.
if ~exist('timeout','var') || isempty(timeout) timeout = 60; end
if self.IsString
if ~exist('binary_blobs','var') || isempty(binary_blobs) binary_blobs = false; end
if binary_blobs
[data,timestamp] = lsl_pull_sample_buf(self.LibHandle,self.InletHandle,self.ChannelCount,timeout);
else
[data,timestamp] = lsl_pull_sample_str(self.LibHandle,self.InletHandle,self.ChannelCount,timeout);
end
else
[data,timestamp] = lsl_pull_sample_d(self.LibHandle,self.InletHandle,self.ChannelCount,timeout);
end
end
function [chunk,timestamps] = pull_chunk(self)
% Pull a chunk of numeric samples and their timestamps from the inlet.
% [ChunkData,Timestamps] = pull_chunk()
%
% This function obtains a chunk of data from the inlet; the chunk contains all samples
% that have become available since the last chunk/sample was requested. Note that the
% result may be empty. For each returned sample there is also a timestamp being
% returned.
%
% Out:
% ChunkData : The chunk contents; this is a MxN matrix with one column per returned
% sample (and as many rows as the stream has channels).
%
% Timestamps : A vector of timestamps for the returned samples.
[chunk,timestamps] = lsl_pull_chunk_d(self.LibHandle,self.InletHandle,self.ChannelCount);
end
function h = get_libhandle(self)
% get the library handle (e.g., to query the clock)
h = self.LibHandle;
end
end
end
function hlib = lsl_loadlib(binarypath,debugging,keep_persistent)
% Load the lab streaming layer library.
% [LibHandle] = lsl_loadlib(BinaryPath,DebugVersion)
%
% This operation loads the library, after which its functions (starting with lsl_) can be used.
%
% In:
% BinaryPath : Optionally the path to the locations of the liblsl bin folder (default: relative
% to this .m file).
%
% DebugVersion : Optionally load the debug version of the library (default: false)
%
% Persistent : keep the library handle around until shutdown (default: true)
%
% Out:
% Handle : handle to the library
% when the handle is deleted, the library will be unloaded
%
% Notes:
% Do not delete this handle while you still have LSL objects (streaminfos, inlets, outlets)
% alive.
%
% Christian Kothe, Swartz Center for Computational Neuroscience, UCSD
% 2012-03-05
if ~exist('binarypath','var') || isempty(binarypath)
binarypath = [fileparts(mfilename('fullpath')) filesep 'bin']; end
if ~exist('debugging','var') || isempty(debugging)
debugging = false; end
if ~exist('keep_persistent','var') || isempty(keep_persistent)
keep_persistent = true; end
persistent lib;
if keep_persistent && ~isempty(lib)
hlib = lib;
else
if ispc
ext = '.dll';
elseif ismac
ext = '.dylib';
elseif isunix
ext = '.so';
else
error('Your operating system is not supported by this version of the lab streaming layer API.');
end
if strfind(computer,'64')
bitness = '64';
else
bitness = '32';
end
if debugging
debug = '-debug';
else
debug = '';
end
dllpath = [binarypath filesep 'liblsl' bitness debug ext];
if ~exist(dllpath,'file')
error(['Apparently the file "' dllpath '" is missing on your computer. Cannot load the lab streaming layer.']); end
% open the library and make sure that it gets auto-deleted when the handle is erased
try
hlib = lsl_loadlib_(dllpath);
catch e
disp('See https://github.com/labstreaminglayer/liblsl-Matlab/#troubleshooting for troubleshooting tips');
error(['Error loading the liblsl library: ', e.message]);
end
hlib.on_cleanup = onCleanup(@()lsl_freelib_(hlib));
if keep_persistent
lib = hlib; end
end
classdef lsl_outlet < handle
% A stream outlet.
% Outlets are used to make streaming data (and the meta-data) available on the lab network.
properties (Hidden)
LibHandle = 0; % this is a handle to the liblsl library (to call its functions)
OutletHandle = 0; % this is a handle to an lsl_outlet object within the library.
SampleRate = 0; % copy of the sample rate...
end
methods
function self = lsl_outlet(info, chunksize, maxbuffered)
% Outlet = lsl_outlet(Streaminfo, ChunkSize, MaxBuffered)
% Establish a new stream outlet. This makes the stream discoverable.
%
% In:
% Streaminfo : The lsl_streaminfo object to use for creating this stream. Stays constant over the lifetime of the outlet.
%
% ChunkSize : Optionally the desired chunk granularity (in samples) for transmission. If 0,
% each push operation yields one chunk. Stream recipients can have this setting bypassed.
% (default: 0)
%
% MaxBuffered : Optionally the maximum amount of data to buffer (in seconds if there is a nominal
% sampling rate, otherwise x100 in samples). Stream recipients can elect to use
% a smaller (but not larger) buffer size than the one specified here.
% (default: 360)
%
if ~exist('chunksize','var') || isempty(chunksize) chunksize = 0; end
if ~exist('maxbuffered','var') || isempty(maxbuffered) maxbuffered = 360; end
self.LibHandle = info.LibHandle;
self.SampleRate = info.nominal_srate();
self.OutletHandle = lsl_create_outlet(info.LibHandle,info.InfoHandle,chunksize,maxbuffered);
end
function delete(self)
% Destroy the outlet when it is deleted.
% The outlet will no longer be discoverable after destruction and all paired inlets will
% stop delivering data.
lsl_destroy_outlet(self.LibHandle,self.OutletHandle);
end
function push_sample(self,sampledata,timestamp,pushthrough)
% push_sample(SampleData,Timestamp,Pushthrough)
% Push a sample into the outlet.
%
% In:
% SampleData : either a numeric vector (as double, converted implicitly) with as many
% elements as the stream has channels, or a cell array of strings (if the
% stream is string-formatted), or a cell array of uint8 vectors to submit
% variable-length binary data.
%
% Timestamp : Optionally the capture time of the most recent sample, in agreement with lsl_local_clock();
% if 0, the current time is used.
%
% 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.
% (default: 1)
if ~exist('timestamp','var') || isempty(timestamp) timestamp = 0; end
if ~exist('pushthrough','var') || isempty(pushthrough) pushthrough = 1; end
lsl_push_sample(self.LibHandle,self.OutletHandle,sampledata,timestamp,pushthrough);
end
function push_chunk(self,chunkdata,timestamps,pushthrough)
% push_sample(ChunkData,Timestamps,Pushthrough)
% Push a chunk into the outlet.
%
% In:
% ChunkData : Numeric matrix with one column for each sample that shall be
% transmitted. May also be empty.
%
% Timestamps : Optionally the capture time of the most recent sample, in agreement with lsl_local_clock();
% if 0, the current time is used. The time stamps of other samples are automatically
% derived based on the sampling rate of the stream, or replicated if the stream is irregular-rate
% If this is a vector, it is assumed that it contains one time stamp for each sample. (default: 0)
%
% 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.
% (default: 1)
if ~exist('timestamps','var') || isempty(timestamps) timestamps = 0; end
if ~exist('pushthrough','var') || isempty(pushthrough) pushthrough = 1; end
if timestamps == 0
timestamps = lsl_local_clock(self.LibHandle); end
if isscalar(timestamps)
if self.SampleRate == 0
timestamps = [timestamps; -ones(size(chunkdata,2)-1,1)];
else
% otherwise infer the timestamp of the first sample in the chunk and let the
% library deduce the timestamps for the remaining samples (using -1.0 as the
% stamps).
timestamps = [timestamps - (size(chunkdata,2)-1)/self.SampleRate; -ones(size(chunkdata,2)-1,1)];
end
end
lsl_push_chunk(self.LibHandle,self.OutletHandle,chunkdata,timestamps,pushthrough);
end
% === Miscellaneous Features ===
function result = have_consumers(self)
% Check whether consumers are currently registered.
% While it does not hurt, there is technically no reason to push samples if there is no consumer.
result = lsl_have_consumers(self.LibHandle,self.OutletHandle);
end
function success = wait_for_consumers(self,timeout)
% Wait until some consumer shows up (without wasting resources).
%
% In:
% Timeout : Timeout for the operation. (default: 60)
%
% Out:
% Success : True if the wait was successful, false if the timeout expired.
if ~exist('timeout','var') || isempty(timeout) timeout = 60; end
success = lsl_wait_for_consumers(self.LibHandle,self.OutletHandle,timeout);
end
function result = info(self)
% Retrieve 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).
result = lsl_streaminfo(self.LibHandle,lsl_get_info(self.LibHandle,self.OutletHandle));
end
function h = get_libhandle(self)
% get the library handle (e.g., to query the clock)
h = self.LibHandle;
end
end
end
\ No newline at end of file
function streaminfos = lsl_resolve_all(lib,timeout)
% [Streaminfos] = lsl_resolve_all(LibHandle,Timeout)
% 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 list of hostnames.
% These details may optionally be customized by the experimenter in a configuration file
% (see Network Connectivity in the LSL wiki).
% This is the default mechanism used by the browsing programs and the recording program.
%
% In:
% LibHandle : handle to the API library, as obtained via lsl_loadlib();
%
% Timeout : The timeout for the operation, in seconds.
%
% Out
% Streaminfos : A cell array of stream info objects (excluding their desc field), any of which can
% subsequently be used to open an inlet. The full info can be retrieved from the
% inlet.
if ~exist('timeout','var') || isempty(timeout)
timeout = 3.0; end
% first do a raw resolve
tmpresults = lsl_resolve_all_(lib,timeout);
% create an lsl_streaminfo instance for each result
streaminfos = cell(1,length(tmpresults));
for r=1:length(tmpresults)
streaminfos{r} = lsl_streaminfo(lib,tmpresults(r)); end
function streaminfos = lsl_resolve_bypred(lib,pred,minimum,timeout)
% [Streaminfos] = lsl_resolve_byprop(LibHandle,Predicate,Minimum,Timeout)
% Resolve streams of the network whose contents 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 for the <info> node (omitting the surrounding []'s), see also
% http://en.wikipedia.org/w/index.php?title=XPath_1.0&oldid=474981951.
%
% In:
% LibHandle : handle to the API library, as obtained via lsl_loadlib();
%
% Predicate : The predicate string, e.g. 'name=''BioSemi''' or
% 'type=''EEG'' and starts-with(name,''BioSemi'') and count(info/desc/channel)=32'
%
% Minimum : Return at least this number of results. (default: 1)
%
% Timeout : Optionally a timeout of the operation, in seconds (default: 5s). If the timeout
% expires, less than the desired number of streams (possibly none) will be returned.
%
% Out:
% Streaminfos : A vector of matching stream info objects (excluding their meta-data), any of
% which can subsequently be used to open an inlet.
%
% Notes:
% If you want to wait until a stream shows up it is usually a better idea to call resolve
% in a loop with a few-second timeout than to set the timeout to infinite (since MATLAB would
% otherwise become unresponsive).
if ~exist('minimum','var') || isempty(minimum)
minimum = 1; end