Skip to content

Commit 6bd1d58

Browse files
authored
Merge pull request #41 from tstenner/readdexamples
Re-add examples
2 parents dc00555 + 70cc090 commit 6bd1d58

23 files changed

+1046
-0
lines changed

Diff for: CMakeLists.txt

+5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ endif()
1313
option(LSL_UNIXFOLDERS "Use the unix folder layout for install targets" On)
1414
option(LSL_NO_FANCY_LIBNAME "Skip library name decorations (32/64/-debug)")
1515
option(LSL_LEGACY_CPP_ABI "Build legacy C++ ABI" OFF)
16+
option(LSL_BUILD_EXAMPLES "Build example programs in examples/" OFF)
1617

1718
# lsl uses boost, but several other projects (e.g. Matlab) also use boost.
1819
# To prevent clashes with different boost versions, lsl ships a subset of
@@ -219,4 +220,8 @@ if(LSL_UNITTESTS)
219220
add_subdirectory(testing)
220221
endif()
221222

223+
if(LSL_BUILD_EXAMPLES)
224+
add_subdirectory(examples)
225+
endif()
226+
222227
LSLGenerateCPackConfig()

Diff for: examples/CMakeLists.txt

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
cmake_minimum_required(VERSION 3.5)
2+
project(Examples
3+
LANGUAGES C CXX
4+
VERSION 0.2.0)
5+
6+
# convenience function to add an example file
7+
# this creates a target, links the necessary libraries and
8+
# creates an install target
9+
function(addlslexample name extension)
10+
add_executable(${name}
11+
${name}.${extension}
12+
)
13+
target_link_libraries(${name} PRIVATE LSL::lsl)
14+
target_compile_features(${name} PRIVATE cxx_constexpr)
15+
installLSLApp(${name})
16+
endfunction()
17+
18+
find_package(Threads)
19+
20+
addlslexample(GetAllStreams cpp)
21+
addlslexample(GetFullinfo cpp)
22+
addlslexample(GetTimeCorrection cpp)
23+
addlslexample(HandleMetaData cpp)
24+
addlslexample(HandleMetaDataC c)
25+
addlslexample(ReceiveData cpp)
26+
addlslexample(ReceiveDataC c)
27+
addlslexample(ReceiveDataInChunks cpp)
28+
addlslexample(ReceiveDataSimple cpp)
29+
addlslexample(ReceiveStringMarkers cpp)
30+
addlslexample(ReceiveStringMarkersC c)
31+
addlslexample(SendDataC c)
32+
addlslexample(SendDataInChunks cpp)
33+
addlslexample(SendDataSimple cpp)
34+
addlslexample(SendMultipleStreams cpp)
35+
addlslexample(SendStringMarkers cpp)
36+
addlslexample(SendStringMarkersC c)
37+
addlslexample(TestSyncWithoutData cpp)
38+
39+
target_link_libraries(TestSyncWithoutData PRIVATE Threads::Threads)
40+

Diff for: examples/GetAllStreams.cpp

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#include <iostream>
2+
#include <lsl_cpp.h>
3+
4+
/**
5+
* This example program shows how all streams that are currently present on the lab network can be
6+
* resolved and displayed. This is useful for browsing applications.
7+
*/
8+
9+
int main(int argc, char* argv[]) {
10+
try {
11+
std::cout << "Here is a one-shot resolve of all current streams:" << std::endl;
12+
13+
// discover all streams on the network
14+
std::vector<lsl::stream_info> results = lsl::resolve_streams();
15+
16+
// display them
17+
for (auto& stream: results) std::cout << stream.as_xml() << "\n\n";
18+
19+
std::cout << "Press any key to switch to the continuous resolver test: " << std::endl;
20+
std::cin.get();
21+
22+
lsl::continuous_resolver r;
23+
while (true) {
24+
std::vector<lsl::stream_info> tmp = r.results();
25+
for (auto& val : tmp) std::cout << val.name() << " ";
26+
std::cout << std::endl;
27+
}
28+
29+
} catch (std::exception& e) { std::cerr << "Got an exception: " << e.what() << std::endl; }
30+
std::cout << "Press any key to exit. " << std::endl;
31+
std::cin.get();
32+
return 0;
33+
}

Diff for: examples/GetFullinfo.cpp

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#include <iostream>
2+
#include <lsl_cpp.h>
3+
4+
/**
5+
* This example program demonstrates how the full version of the stream info (i.e. including the
6+
* potentially large .desc() field) can be obtained from an inlet. Note that the output of the
7+
* resolve functions only includes the core information otherwise.
8+
*/
9+
10+
int main(int argc, char* argv[]) {
11+
std::string field, value;
12+
if (argc != 3) {
13+
std::cout << "This connects to a stream which has a particular value for a given field and "
14+
"displays its full stream_info contentss."
15+
<< std::endl;
16+
std::cout << "Please enter a field name and the desired value (e.g. \"type EEG\" (without "
17+
"the quotes)):"
18+
<< std::endl;
19+
std::cin >> field >> value;
20+
} else {
21+
field = argv[1];
22+
value = argv[2];
23+
}
24+
25+
try {
26+
// resolve the stream of interet
27+
std::cout << "Now resolving streams..." << std::endl;
28+
std::vector<lsl::stream_info> results = lsl::resolve_stream(field, value);
29+
30+
std::cout << "Here is what was resolved: " << std::endl;
31+
std::cout << results[0].as_xml() << std::endl;
32+
33+
// make an inlet to get data from it
34+
std::cout << "Now creating the inlet..." << std::endl;
35+
lsl::stream_inlet inlet(results[0]);
36+
37+
// get & display the info
38+
std::cout << "The information about this stream is displayed in the following: "
39+
<< std::endl;
40+
lsl::stream_info info = inlet.info();
41+
std::cout << info.as_xml() << std::endl;
42+
43+
} catch (std::exception& e) { std::cerr << "Got an exception: " << e.what() << std::endl; }
44+
std::cout << "Press any key to exit. " << std::endl;
45+
std::cin.get();
46+
return 0;
47+
}

Diff for: examples/GetTimeCorrection.cpp

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#include <iostream>
2+
#include <lsl_cpp.h>
3+
4+
/**
5+
* This example demonstrates how a time-correction value can be obtained on demand for a particular
6+
* stream on the net. This time-correction value, when added to the time stamp of an obtained
7+
* sample, remaps the sample's time stamp into the local clock domain (so it is in the same domain
8+
* as what lsl::local_clock() would return). For streams coming from the same computer, this value
9+
* should be approx. 0 (up to some tolerance).
10+
*/
11+
12+
int main(int argc, char* argv[]) {
13+
std::string field, value;
14+
if (argc != 3) {
15+
std::cout << "This connects to a stream which has a particular value for a given field and "
16+
"gets the time-synchronization information for it."
17+
<< std::endl;
18+
std::cout << "Please enter a field name and the desired value (e.g. \"type EEG\" (without "
19+
"the quotes)):"
20+
<< std::endl;
21+
std::cin >> field >> value;
22+
} else {
23+
field = argv[1];
24+
value = argv[2];
25+
}
26+
27+
try {
28+
// resolve the stream of interet
29+
std::cout << "Now resolving streams..." << std::endl;
30+
std::vector<lsl::stream_info> results = lsl::resolve_stream(field, value);
31+
32+
std::cout << "Here is what was resolved: " << std::endl;
33+
std::cout << results[0].as_xml() << std::endl;
34+
35+
// make an inlet to get data from it
36+
std::cout << "Now creating the inlet..." << std::endl;
37+
lsl::stream_inlet inlet(results[0]);
38+
39+
// start receiving & displaying the data
40+
std::cout << "Press [Enter] to query a new correction value (clocks may drift)..."
41+
<< std::endl;
42+
while (true) {
43+
std::cout << inlet.time_correction() << std::endl;
44+
std::cin.get();
45+
}
46+
47+
} catch (std::exception& e) { std::cerr << "Got an exception: " << e.what() << std::endl; }
48+
std::cout << "Press any key to exit. " << std::endl;
49+
std::cin.get();
50+
return 0;
51+
}

Diff for: examples/HandleMetaData.cpp

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#include <iostream>
2+
#include <lsl_cpp.h>
3+
4+
int main(int argc, char* argv[]) {
5+
try {
6+
// create a new stream_info and declare some meta-data (in accordance with XDF format)
7+
const char* name = argc > 1 ? argv[1] : "MetaTester";
8+
lsl::stream_info info(name, "EEG", 8, 100, lsl::cf_float32, "myuid323457");
9+
lsl::xml_element chns = info.desc().append_child("channels");
10+
const char* labels[] = {"C3", "C4", "Cz", "FPz", "POz", "CPz", "O1", "O2"};
11+
for (const char* label : labels)
12+
chns.append_child("channel")
13+
.append_child_value("label", label)
14+
.append_child_value("unit", "microvolts")
15+
.append_child_value("type", "EEG");
16+
info.desc().append_child_value("manufacturer", "SCCN");
17+
info.desc()
18+
.append_child("cap")
19+
.append_child_value("name", "EasyCap")
20+
.append_child_value("size", "54")
21+
.append_child_value("labelscheme", "10-20");
22+
23+
// create outlet for the stream
24+
lsl::stream_outlet outlet(info);
25+
26+
// === the following could run on another computer ===
27+
28+
// resolve the stream and open an inlet
29+
std::vector<lsl::stream_info> results = lsl::resolve_stream("name", name);
30+
lsl::stream_inlet inlet(results[0]);
31+
32+
// get the full stream info (including custom meta-data) and dissect it
33+
lsl::stream_info inf = inlet.info();
34+
std::cout << "The stream's XML meta-data is: \n"
35+
<< inf.as_xml()
36+
<< "\nThe manufacturer is: " << inf.desc().child_value("manufacturer")
37+
<< "\nThe cap circumference is: " << inf.desc().child("cap").child_value("size")
38+
<< "\nThe channel labels are as follows:\n";
39+
lsl::xml_element ch = inf.desc().child("channels").child("channel");
40+
for (int k = 0; k < info.channel_count(); k++) {
41+
std::cout << " " << ch.child_value("label") << std::endl;
42+
ch = ch.next_sibling();
43+
}
44+
45+
} catch (std::exception& e) { std::cerr << "Got an exception: " << e.what() << std::endl; }
46+
std::cout << "Press any key to exit. " << std::endl;
47+
std::cin.get();
48+
return 0;
49+
}

Diff for: examples/HandleMetaDataC.c

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#include <lsl_c.h>
2+
#include <stdio.h>
3+
4+
int main(int argc, char* argv[]) {
5+
int c; /* channel index */
6+
lsl_xml_ptr desc,chns,chn,cap; /* some xml element pointers */
7+
lsl_outlet outlet; /* stream outlet */
8+
lsl_streaminfo info,inf; /* streaminfo objects */
9+
lsl_inlet inlet; /* a stream inlet to get samples from */
10+
int errcode; /* error code (lsl_lost_error or timeouts) */
11+
const char* labels[] = {"C3","C4","Cz","FPz","POz","CPz","O1","O2"};
12+
13+
/* create a new streaminfo and declare some meta-data (in accordance with XDF format) */
14+
const char* name = argc > 1 ? argv[1] : "MetaTester";
15+
info = lsl_create_streaminfo(name,"EEG",8,100,cft_float32,"myuid323457");
16+
desc = lsl_get_desc(info);
17+
chns = lsl_append_child(desc,"channels");
18+
for (c=0;c<8;c++) {
19+
chn = lsl_append_child(chns,"channel");
20+
lsl_append_child_value(chn,"label",labels[c]);
21+
lsl_append_child_value(chn,"unit","microvolts");
22+
lsl_append_child_value(chn,"type","EEG");
23+
}
24+
lsl_append_child_value(desc,"manufacturer","SCCN");
25+
cap = lsl_append_child(desc,"cap");
26+
lsl_append_child_value(cap,"name","EasyCap");
27+
lsl_append_child_value(cap,"size","54");
28+
lsl_append_child_value(cap,"labelscheme","10-20");
29+
30+
/* create outlet for the stream */
31+
outlet = lsl_create_outlet(info,0,360);
32+
33+
/* === the following could run on another computer === */
34+
35+
/* resolve the stream and open an inlet */
36+
lsl_resolve_byprop(&info,1,"name","MetaTester",1,LSL_FOREVER);
37+
inlet = lsl_create_inlet(info, 360, LSL_NO_PREFERENCE, 1);
38+
inf = lsl_get_fullinfo(inlet,LSL_FOREVER,&errcode);
39+
printf("The stream's XML meta-data is: \n");
40+
printf("%s\n",lsl_get_xml(inf));
41+
printf("The manufacturer is: %s\n",lsl_child_value_n(lsl_get_desc(inf),"manufacturer"));
42+
printf("The cap circumference is: %s\n",lsl_child_value_n(lsl_child(lsl_get_desc(inf),"cap"),"size"));
43+
printf("The channel labels are as follows:\n");
44+
chn = lsl_child(lsl_child(lsl_get_desc(inf),"channels"),"channel");
45+
for (c=0; c<lsl_get_channel_count(inf); c++) {
46+
printf(" %s\n",lsl_child_value_n(chn,"label"));
47+
chn = lsl_next_sibling(chn);
48+
}
49+
50+
/* destroy objects and free memory */
51+
lsl_destroy_streaminfo(inf);
52+
lsl_destroy_inlet(inlet);
53+
lsl_destroy_outlet(outlet);
54+
lsl_destroy_streaminfo(info);
55+
56+
/* wait for keypress */
57+
getchar();
58+
return 0;
59+
}

Diff for: examples/LICENSE.txt

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2018 Christian Kothe, Tristan Stenner
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

0 commit comments

Comments
 (0)