-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathlsl_inlet.m
213 lines (185 loc) · 10.8 KB
/
lsl_inlet.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
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