Giter Club home page Giter Club logo

app-labrecorder's Introduction

Overview

The LabRecorder is the default recording program that comes with LSL. It allows to record all streams on the lab network (or a subset) into a single file, with time synchronization between streams.

File Format

The file format used by the LabRecorder is XDF. This is an open general-purpose format that was designed concurrently with LSL and supports all features of LSL streams. The project page is here. There are importers for MATLAB, EEGLAB, BCILAB, Python, and MoBILAB.

Getting LabRecorder

The releases page contains archives of past LabRecorder builds. Try downloading and installing an archive that matches your platform. Note for Ubuntu users: The deb will install LabRecorder to /usr/LabRecorder though we might change this to /usr/local/bin/LabRecorder in the future.

If there are no archives matching your target platform, or the ones available don't run, then continue reading below. If the instructions don't help then please post an issue to the repo's issues page.

Dependencies

For LabRecorder to work on your system, you might need to first install some dependencies, specifically liblsl and optionally Qt.

Windows

The Windows archives ship with nearly all required dependencies. If you have not already installed it via another program, you may need to install the Visual C++ Runtime Redistributable.

If you suspect you are missing a dependency, try running DependenciesGui.exe then navigating to the LabRecorder.exe. It's important to launch Dependencies.exe from the same environment that you would use to launch this application: if you launch this application by double-clicking the executable in Windows' finder then do the same on the Dependencies.exe icon; if you launch this application in a Terminal window, then use that same Terminal to launch Dependencies.

MacOS

In the near future, many LSL Apps (especially LabRecorder) will not ship with their dependencies and will look for the dependencies to be installed on the system. The easiest way to manage the dependencies is by using homebrew:

  • Install homebrew: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
  • brew install labstreaminglayer/tap/lsl
  • brew install qt

You can then install LabRecorder directly from homebrew: brew install labrecorder

Run it with open /usr/local/opt/labrecorder/LabRecorder/LabRecorder.app

Linux Ubuntu

The Ubuntu releases do not typically ship with their dependencies, so you must download and install those:

  • Download, extract, and install the latest liblsl-{version}-{target}_amd64.deb from its release page
    • We hope to make this available via a package manager soon.
      • Quick ref Ubuntu 20.04: curl -L https://github.com/sccn/liblsl/releases/download/v1.16.0/liblsl-1.16.0-bionic_amd64.deb -o liblsl.deb
      • Quick ref Ubuntu 22.04: curl -L https://github.com/sccn/liblsl/releases/download/v1.16.0/liblsl-1.16.0-jammy_amd64.deb -o liblsl.deb
    • You can install liblsl directly by double-clicking on the deb, or with sudo dpkg -i {filename}.deb or sudo apt install {filename}.deb
  • See the bottom of the lsl build env docs.
    • For most cases, this will amount to installing Qt and its dependencies:
      • Ubuntu 18.xx or 20.xx: sudo apt-get install build-essential qtbase5-dev libpugixml-dev
      • Ubuntu >= 22.04: sudo apt-get install qt6-base-dev freeglut3-dev

Usage

The LabRecorder displays a list of currently present device streams under "Record from Streams". If you have turned on a device after you have already started the recorder, click the "Update" button to update the list (this takes ca. 2 seconds).

For testing, you can use a "dummy" device from the lslexamples found in the liblsl release assets (for example SendData).

If you cannot see streams that are provided on another computer, read the section Network Troubleshooting on the NetworkConnectivity page.

You can select which streams you want to record from and which not by checking the checkboxes next to them.

labrecorder-default.png

Note that if you have multiple streams with the same name and host, it is impossible to check only 1. If any is checked then they will all be recorded.

The entry in "Saving to..." shows you the file name (or file name template) where your recording will be stored. You can change this by modifying the Study Root folder (e.g., by clicking the browse button) and the File Name / Template field. If the respective directory does not yet exist, it will be created automatically (except if you do not have the permissions to create it). The file name string may contain placeholders that will be replaced by the values in the fields below. Checking the BIDS box will automatically change the filename template to be BIDS compliant. If the file that you are trying to record to already exists, the existing file will be renamed (the string _oldX will be appended where X is the lowest number that is not yet occupied by another existing file). This way, it is impossible to accidentally overwrite data.

The Block/Task field can be overwriten or selected among a list of items found in the configuration file.

Click "Start" to start a recording. If everything goes well, the status bar will now display the time since you started the recording, and more importantly, the current file size (the number before the kb) will grow slowly. This is a way to check whether you are still in fact recording data. The recording program cannot be closed while you are recording (as a safety measure).

When you are done recording, click the "Stop" button. You can now close the program. See the xdf repository for tools and information on how to use the XDF files.

Preparing a Full Study

When preparing a new study, it is a good idea to make a custom configuration file which at least sets up a custom storage location for the study. See the documentation in the file LabRecorder.cfg for how to do this -- it is very easy! You can override this by making a shortcut for the LabRecorder program (e.g. on the desktop) and appending in its properties the command-line arguments -c name_of_you_config.cfg. You can also create a batch script. You can also load the config while the program is already running, but this can easily be forgotten during an experiment, so we recommend to follow the shortcut route.

In addition to the storage location, if your experiment has multiple blocks (e.g., SubjectTraining, PreBaseline, MainBlock, PostBaseline or the like) you can make the recording process even more straightforward for the experimenters by setting up a default list of block names. Again, take a look at the existing config files.

Since it is too easy to forget to turn on or check all necessary recording devices for a study, we recommend to also make a list of "required" streams (by their name) and put it into the config file. These streams will be pre-checked when starting the program, and any missing stream will be displayed in red. If such a stream is still not green when starting the recording, the experimenter will get a message box to confirm that he/she really wants to record without including the device.

Remote Control

If you check the box to EnableRCS then LabRecorder exposes some rudimentary controls via TCP socket.

Currently supported commands include:

  • select all
  • select none
  • start
  • stop
  • update
  • filename ...

filename is followed by a series of space-delimited options enclosed in curly braces. e.g. {root:C:\root_data_dir}

  • root - Sets the root data directory.
  • template - sets the File Name / Template. Will unselect BIDS option. May contain wildcards.
  • task - will replace %b in template
  • run - will replace %n in template (not working?)
  • participant - will replace %p in template
  • session - will replace %s in template
  • acquisition - will replace %a in template
  • modality - will replace %m in template. suggested values: eeg, ieeg, meg, beh

For example, in Python:

import socket
s = socket.create_connection(("localhost", 22345))
s.sendall(b"select all\n")
s.sendall(b"filename {root:C:\\Data\\} {template:exp%n\\%p_block_%b.xdf} {run:2} {participant:P003} {task:MemoryGuided}\n")
s.sendall(b"start\n")
lr = tcpip('localhost', 22345); 
fopen(lr)
fprintf(lr, 'select all');
fprintf(lr, ['filename {root:C:\Data\} '...
            '{task:MemoryGuided} ' ...
            '{template:s_%p_%n.xdf ' ...
            '{modality:ieeg}']); 
fprintf(lr, 'start');

Misc Features

The LabRecorder has some useful features that can add robustness if things go wrong during the experiment:

If a network connectivity error happens while recording (e.g., a network cable pops out that connects to the source of a data stream), you have usually 6 minutes (think 5) to plug it back it in during which the data will be buffered on the sending machine. If it takes you longer to fix the problem, you will have some gap in your recording.

If a device program or computer crashes while recording, you will for sure lose data, but any device program that transmits an associated device serial number will be picked up automatically by the recorder when it comes back online (these programs are called "recoverable"), without a need to stop and re-start the recording.

You should check the health of your device to be sure, however, for example using an online stream viewer program (see, for example, ViewingStreamsInMatlab). Also, be sure to test whether it is in fact recoverable before relying on this feature (you can test this with a viewer by turning the device app off and back on).

If a device is displayed in red when you start recording (and it is checked), it will be added to the ongoing recording by the time when it comes online. This can be useful when a device can only be turned on while the recording is already in progress. Again, it is advisable to check that the device is in fact discoverable and added. The LabRecorder brings up a console window in the background which shows a list of all streams that are added to the recording -- this is a good place to check whether a late stream did get picked up successfully during a live recording.

Build Instructions

Please follow the general LSL App build instructions.

app-labrecorder's People

Contributors

agricolab avatar brifsttar avatar cboulay avatar dcsjjagielski avatar doug1983 avatar mgrivich avatar roedy13 avatar tstenner avatar xloem avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

app-labrecorder's Issues

What does `created_at` field means?

Hi all, I recorded some EEG data, and want to know actually file was created.
Is this field created_at telling something about it? e.g. I got 495259.50215359998 in my *.xdf file, how do I convert it to a timestamp like 2021/8/24 10:32:02?

note: I have tried to parse it with unix_timestamp, but the result is not what I want.

LabRecorder deadlocks writing a streams footer, if it has not yet received anything from this stream

I noticed that LabRecorderCLI won't shut down after sending process.communicate('b\n')(or pressing Enter when run from a terminal). Instead it hung at Offsets thread is finished. The same happens with LabRecorder.exe. I could trace it to the fact that it was waiting for a stream which has not yet send any sample. Once i sent a sample, it would write the footer for the stream, close the xdf-file and return.

Don't know whether bug or feature, but probably worthwile to know.

Labrecorder builds but crashes

We were previously using labrecorder 1.13 from the ftp site on our Windows 7 machine but occasionally we would have .xdf files that were unable to be opened in eeglab using load_xdf - they'd come back with a "matrix must be positive-definite" error. I thought that might be the clock offsets errors referenced in an issue here and cloned and built the latest labrecorder on master here in VS 2017 per the instructions. It built successfully with lots of warnings (but no errors) but it does not work properly on the machine - we can start the exe and it appears and we can see the streams but once we hit start files remain at 0 kb, it doesn't seem to record the data properly, and also crashes whenever we hit the stop button. Firewall settings appear correct, or at least the same as labrecorder 1.13 and we've rebuilt several times (always in x86-release mode) and have the correct versions of QT and Boost, but behavior is consistent. Is it possible we've built it wrong, or are we missing something simple in setup?

Full error we were getting with 1.13:

Error using chol
Matrix must be positive definite.

Error in load_xdf>robust_fit (line 695)
L = sparse(chol(A'*A,'lower')); U = L';

Error in load_xdf (line 435)
mappings{r} = robust_fit([ones(idx(2)-idx(1)+1,1) clock_times(idx(1):idx(2))']/opts.WinsorThreshold,
clock_values(idx(1):idx(2))'/opts.WinsorThreshold);

I cannot get output file. a problem on windows 11 ?

Dear colleagues,

Following a tutorial. I tried to get data from AudioCapture on my windows 11 PC.
https://github.com/sccn/labstreaminglayer/wiki/Tutorial-1.-Getting-started-with-LSL-single-stream
However, I failed to get an output .xdf file.
I do not get any error or warning messages.
but the value indicating the size of the output file remains zero (a below figure) and I do not find any files in the specified path.

スクリーンショット 2021-12-15 102551

I have confirmed that this problem occurs in the following version.
LabRecorder-1.13.1-win64
LabRecorder-1.14.2-Win_amd64
LabRecorder-1.14.2-Win_i386

the same problem occurs when I tried data from BlueMuse on my windows 11 PC.
https://github.com/kowalej/BlueMuse
I successfully get the output file from AudioCapture on my MAC PC.

therefore, I suspect that this problem is specific to my windows 11 PC.

It is very helpful if you give any advice about this problem.
Thank you in advance.

Pupil Capture data null from LabRecorder xdf file

Hi all,

I'm unsure if my problem is more a PupilLabs issue, xdf file format issue, or LabRecorder issue but i'll ask here anyway.

I'm currently reading in EEG data, Unity markers and Pupil-Capture data via the LSL in to the LabRecorder (Built from the latest GitHub repository), exporting the created xdf file to MatLab shows the data to look correct with markers and EEG data streaming as expected, the Pupil-Capture data however is all zero with with only one time stamp and one time_series value of zero. I don't suppose anyone has had any similar issues and could share their experience in resolving such problems?

I am currently using the Vive PupilLabs add on to record my gaze data, for clarification i'm not doing anything with the HMD-Eyes package and i've installed pylsl and the pupil lsl relay to the plugins folder of Pupil-Capture, the stream can be seen in LabRecorder just the GazeMetaData on review looks incorrect in MatLab.

Any help or comments would be greatly appreciated.

Is it possible to start recording LabRecorder from a shortcut?

I think the title says it all but here goes:
I have written a config file to pre-load all the required streams (with argument -c config_filename.cfg) but I would also like LabRecorder to start recording as soon as it is called (from batch file).
Is it possible? What is program argument?

Readme and license not in distribution

I noticed that the license and README files for LabRecorder are not getting copied into the release, at least on Windows. These files need to be included.

Regression: handling of streams with same name and host

Hello,

I am doing experiment involving multiple users, I use the LSL stream name to differentiate users in the system and in the recordings. Each user has a dedicated device, and several physiological signals running on it. Hence I happen to have LSL streams with same name, same hostname, different types, different ID. Let say I have 3 streams for one user.

In prior versions of LabRecorder, e.g. 1.12 from the (old) FTP I could see in the window the correct number of streams (3), even though because only name and hostname are listed it is difficult (if not impossible) to differentiate which physiological signals I am dealing with. Still, I could make sure that I record everything.

Starting with the 1.13 releases on github, I can only see one line per name/hostame in the GUI. Ticking it usually record all related streams (and I could see in the debug info of the terminal that 3 streams are being recorded), but it happened that I was missing some streams in the resulting xdf file -- maybe due to this odd behavior of the GUI, maybe due to an error on my side.

I managed to find the commit that changed the behavior of the GUI: 588243a

Because reverting to the old behavior (listing old streams but with duplicated info in the GUI) is not ideal, would it be possible to detail, instead of just name + hostame, all the info, e.g. name + type + hostname (and maybe ID as well, just to make sure?). Doing so will probably help to fix the bug :) Extra details such as sampling rate could also be useful, but it might start to get crowded in the UI.

Running Lab Recorder CLI from an external process records duplicate streams.

I encountered this issue when starting LabRecorderCLI from an external C# program that I'm working on (similar to @agricolab's project). I am able to start LabRecorderCLI with the file name and target streams as a separate process, but the resulting file contains multiple copies of the same stream.

To duplicate:

  • create a shortcut for LabRecorderCLI.exe

  • Right click the shortcut and select properties

  • Under the "Shortcut" tab, change the "Target" to include the arguments of multiple streams:
    "C:\Users\Deep Thought\source\repos\LabRemote\LabRemote\bin\Debug\LabRecorderCLI.exe" trialName.xdf 'name="Keyboard"' 'name="LabRemote"'
    image

  • Run the shortcut:
    image

Note that there appears to be 4 streams while there should only be 2.

Frustratingly, this error doesn't occur when starting the program directly from command line:
image

Any idea what's going on?

labrecorder on mac

I did the brew install on my mac but can't open the labrecorder. It gives the following error:

Process:               LabRecorder [25516]
Path:                  /usr/local/opt/labrecorder/LabRecorder/LabRecorder.app/Contents/MacOS/LabRecorder
Identifier:            ???
Version:               ??? (???)
Code Type:             X86-64 (Native)
Parent Process:        ??? [1]
Responsible:           LabRecorder [25516]
User ID:               502

Date/Time:             2021-09-25 16:28:21.516 -0400
OS Version:            macOS 11.5.2 (20G95)
Report Version:        12
Anonymous UUID:        BE12E238-B186-DF9B-E3F7-355CCEFACFAA

Sleep/Wake UUID:       A439D0BB-A0CE-4BD8-8DF1-801263BD1589

Time Awake Since Boot: 570000 seconds
Time Since Wake:       1800 seconds

System Integrity Protection: enabled

Crashed Thread:        0

Exception Type:        EXC_CRASH (SIGABRT)
Exception Codes:       0x0000000000000000, 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Termination Reason:    DYLD, [0x1] Library missing

Application Specific Information:
dyld: launch, loading dependent libraries

Dyld Error Message:
  dyld: Using shared cache: 0C9EB0DE-F5CE-3AFC-8F08-0C6DB1E7FC44
Library not loaded: /usr/local/opt/lsl/lib/liblsl.1.14.1.dylib
  Referenced from: /usr/local/opt/labrecorder/LabRecorder/LabRecorder.app/Contents/MacOS/LabRecorder
  Reason: image not found

Binary Images:
       0x10cc36000 -        0x10cc65fff + (??? - ???) <185BE82C-ECA2-3819-80E9-63149C2268AE> /usr/local/opt/labrecorder/LabRecorder/LabRecorder.app/Contents/MacOS/LabRecorder
       0x10e6a4000 -        0x10e73ffff  dyld (852.2) <57DB2053-BFD5-3683-97C6-F1DB2A1F1D09> /usr/lib/dyld

Model: MacBookAir7,2, BootROM 427.140.8.0.0, 2 processors, Dual-Core Intel Core i5, 1.8 GHz, 8 GB, SMC 2.27f2
Graphics: kHW_IntelHDGraphics6000Item, Intel HD Graphics 6000, spdisplays_builtin
Memory Module: BANK 0/DIMM0, 4 GB, DDR3, 1600 MHz, 0x802C, 0x4D5435324C3531324D3332443250462D3130
Memory Module: BANK 1/DIMM0, 4 GB, DDR3, 1600 MHz, 0x802C, 0x4D5435324C3531324D3332443250462D3130
AirPort: spairport_wireless_card_type_airport_extreme (0x14E4, 0x117), Broadcom BCM43xx 1.0 (7.77.111.1 AirPortDriverBrcmNIC-1680.8)
Bluetooth: Version 8.0.5d7, 3 services, 27 devices, 1 incoming serial ports
Network Service: Wi-Fi, AirPort, en0
Serial ATA Device: APPLE SSD SM0256G, 251 GB
USB Device: USB 3.0 Bus
USB Device: BRCM20702 Hub
USB Device: Bluetooth USB Host Controller
Thunderbolt Bus: MacBook Air, Apple Inc., 27.2

how do I go about fixing it? Thank you!

Mac OS - Records an empty file with steam metadata

Hi,
I'm using LabRecorder on Mac OS (Catalina v. 10.15.7).
I can see the streams and start recording. But the resulting file does not contain any data, only stream metadata and time offsets.
Here is the content of the file read by pyxdf.load_xdf().
I used python -m pylsl.examples.SendData to simulate a sensor.

([{'info': defaultdict(list,
               {'name': ['BioSemi'],
                'type': ['EEG'],
                'channel_count': ['8'],
                'channel_format': ['float32'],
                'source_id': ['myuid34234'],
                'nominal_srate': ['100.0000000000000'],
                'version': ['1.100000000000000'],
                'created_at': ['86.77403583500001'],
                'uid': ['50ba2ea7-d596-4b68-a10a-ce1c28865f64'],
                'session_id': ['default'],
                'hostname': ['mac-kate'],
                'v4address': [None],
                'v4data_port': ['16572'],
                'v4service_port': ['16572'],
                'v6address': [None],
                'v6data_port': ['0'],
                'v6service_port': ['0'],
                'desc': [None],
                'stream_id': 1,
                'effective_srate': 0}),
   'footer': {'info': defaultdict(list,
                {'first_timestamp': ['0'],
                 'last_timestamp': ['0'],
                 'sample_count': ['0'],
                 'clock_offsets': [defaultdict(list,
                              {'offset': [defaultdict(list,
                                            {'time': ['115.9061028785'],
                                             'value': ['-2.26375000025314e-05']}),
                                defaultdict(list,
                                            {'time': ['120.9062368245'],
                                             'value': ['-1.318649999859645e-05']}),
                                defaultdict(list,
                                            {'time': ['125.911398654'],
                                             'value': ['-2.933799999738085e-05']}),
                                defaultdict(list,
                                            {'time': ['130.914101721'],
                                             'value': ['-3.051899999206853e-05']}),
                                defaultdict(list,
                                            {'time': ['135.9167075955'],
                                             'value': ['-4.738350000366154e-05']}),
                                defaultdict(list,
                                            {'time': ['140.918574604'],
                                             'value': ['-5.005799998514249e-05']}),
                                defaultdict(list,
                                            {'time': ['145.9221213515'],
                                             'value': ['-2.135549999593422e-05']}),
                                defaultdict(list,
                                            {'time': ['150.9222015105'],
                                             'value': ['-8.195500001306755e-06']}),
                                defaultdict(list,
                                            {'time': ['155.9260812715'],
                                             'value': ['-1.91484999874092e-05']}),
                                defaultdict(list,
                                            {'time': ['160.9302503625'],
                                             'value': ['-2.403750001178651e-05']}),
                                defaultdict(list,
                                            {'time': ['165.9340586375'],
                                             'value': ['-3.840149999234654e-05']}),
                                defaultdict(list,
                                            {'time': ['170.9357685315'],
                                             'value': ['-2.407150000749425e-05']})]})]})},
   'time_series': array([], shape=(8, 0), dtype=float64),
   'time_stamps': array([], dtype=float64)}],
 {'info': defaultdict(list,
              {'version': ['1.0'], 'datetime': ['2021-08-05T22:15:27-0400']})})

Create Release for LabRecorder

I believe the most recent version of LabRecorder on the ftp includes the clock offsets bug. We should make a new release, and post it to this repository. I could do it, but I know that LabRecorder is under active development at the moment so I hesitate to step on any toes.

Remote LabRecorder: Variable 'offset' is being used without being initialized

I was attempting to record EEG data from BrainVisionRecorder, calling LabRecorderCLI.exe type='EEG'.
The console printed

Found BrainVision RDA@DESKTOP-79JUEJU matching 'type='EEG''
Starting the recording, press Enter to quit
Opened the stream BrainVision RDA.
Received header for stream BrainVision RDA.
Started data collection for stream BrainVision RDA.
Timeout in time correction query for stream 1

then it threw
grafik

This error was reproducible, although the same command run flawless a few days before on another machine. The error occurs also if i start the recording via the remote LabRecorderGUI. Note that the old LabRecorder version 1.13 records without error message, but when i attempt to load the data, it throws an LinAlgError("Matrix is not positive definite"). So both errors seems to be related to the clock-offset issue, but are throwing different errors. After a reboot, the error did no longer occur.

No "update" function from TCP remote control

Hello,
LabRecorder is going to be helpful in setting up an EEG experiment in my lab. Thank you for the great work !

I am remotely controlling labrecorder and fail to send an update command. I have to restart labrecorder which is not optimal in my case.

I am not very good in compiling c++ so I have laid out the code that I believe would work to unexpensively add such a function:
in tcpinterface.cpp

void RemoteControlSocket::handleLine(QString s, QTcpSocket *sock) {
	qInfo() << s;
	if (s == "start")
		emit start();
	else if (s == "update")
		emit refresh_streams();
		// todo: perhaps add a 1sec delay to match with lsl stream scan timeout duration

in tcpinterface.h

signals:
	void refresh_streams();
	void start();
	void stop();
	void filename(QString s);
	void select_all();
	void select_none();

in mainwindow.cpp

void MainWindow::enableRcs(bool bEnable) {
	[...]
		connect(rcs.get(), &RemoteControlSocket::start, this, &MainWindow::rcsStartRecording);
		connect(rcs.get(), &RemoteControlSocket::refresh_streams, this, &MainWindow::rcsRefreshStreams);
[...]

void MainWindow::rcsRefreshStreams() {
	// update streams from rcs
	
	hideWarnings = true;
	refreshStreams();
}

in mainwindow.h

private slots:
	[...]
	void rcsStartRecording();
	void rcsRefreshStreams();

Hope it helps.
Cheers !

Python wrapper for RemoteLabRecorder

I wrote python interfaces to remote control LabRecorder (i.e. the Delmenhorst Version). This is implemented a) via the LabRecorderCLI using win32com.client.Dispatch("WScript.Shell") and b) via the LabRecorderRCS with a TCP/IP client. What would be a preferred place to share them?

Remote Control Socket feature unable to handle spaces in filename updates?

I'm trying to control LabRecorder via RCS with Matlab. I'm able to send commands to start/stop recording as well as change the filename fields, however the Study Root field fails to update when I send a path that includes space characters. Similarly, I haven't been able to remotely update the template field (using %b,%s,%p). It looks like these are issues with the regex patterns specified in mainwindow.cpp. Just wondering if this feature is intentional or if it could be easily modified.

Clean up the writing of recording messages.

Since some messages such as "Offsets thread is finished.", "Received header for stream ", etc, are being outputted from multiple threads, they show up looking a mess inside a console window, especially when one has multiple LSL streams running. Perhaps you can lock a new "output mutex" when doing calls to cout and cerr to make sure the messages look nice.

Asking for feedback on LabRecorder distribution

Now that liblsl is available via homebrew (brew install labstreaminglayer/tap/lsl), I'm about to make LabRecorder and other LSL Apps available via homebrew as well.

There are some obvious wins here, but the biggest is that it'll be a very easy way for users to "build from source", so users who don't have whatever version of MacOS was used by me or the CI runner will still have an easy way to get the app, as long as their system is compatible with the dependencies (Qt6).

There are some implementation details that are attractive but have some consequences, so I'm asking for feedback.

Can I change it so that LabRecorder links to the homebrew-installed dependencies instead of dependencies packaged inside the app folder?

One of the most annoying parts about using cmake to build cross-platform qt-based apps is packaging the dependencies for the MacOS app. It doesn't work properly all the time, it's different on different computers, and it seems to break with every update.

If I can instead link to the homebrew-provided libraries, it becomes much simpler and we can ditch about 50 lines of CMake code.

The main disadvantage is that we will no longer have a all-in-one file that a user can download on one computer and bring to a different computer. Even if they download the bottle, they will still need the bottles for the dependencies, and I don't know how to do that for Qt. So this means users on not-internet-connected computers are left behind, or they have to download an offline installer for qt and do a manual build.

Thoughts?

Dependencies are mising in OSX release

It is not possible to run the last release of LabRecorder on out of the box OSX.
Besides security issues, for which workarounds are known, LabRecorder.app crashes because Qt is missing.
Installing qt with brew (easy) does not solve the problem (not hte same path).
I note that the W10 release includes the needed dependencies as dll files, and opens nicely (with W10 in VirtualBox).

For me, the latest usable version is the 1.13 from the .dmg file, and it works fine (OSX 11.2.3).

The bug report:

Process:               LabRecorder [29608]
Path:                  /private/var/folders/*/LabRecorder.app/Contents/MacOS/LabRecorder
Identifier:            ???
Version:               ??? (???)
Code Type:             X86-64 (Native)
Parent Process:        ??? [1]
Responsible:           LabRecorder [29608]
User ID:               502

Date/Time:             2021-04-22 14:24:49.054 +0200
OS Version:            macOS 11.2.3 (20D91)
Report Version:        12
Anonymous UUID:        88F1744F-F985-EE5E-45B3-6D13F0A75DDB


Time Awake Since Boot: 99000 seconds

System Integrity Protection: enabled

Notes:                 Translocated Process

Crashed Thread:        0

Exception Type:        EXC_CRASH (SIGABRT)
Exception Codes:       0x0000000000000000, 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Termination Reason:    DYLD, [0x1] Library missing

Application Specific Information:
dyld: launch, loading dependent libraries

Dyld Error Message:
  dyld: Using shared cache: 52762DF1-0E55-3F8B-9588-8169E6D0EB95
Library not loaded: /usr/local/opt/qt/lib/QtWidgets.framework/Versions/5/QtWidgets
  Referenced from: /private/var/folders/*/LabRecorder.app/Contents/MacOS/LabRecorder
  Reason: image not found

Binary Images:
       0x102f0e000 -        0x102f75fff + (??? - ???) <C42333DD-648D-3CBC-88BB-6D8721E036CE> /var/folders/*/LabRecorder.app/Contents/MacOS/LabRecorder
       0x106628000 -        0x1066c3fff  dyld (832.7.3) <0D4EA85F-7E30-338B-9215-314A5A5539B6> /usr/lib/dyld

MacOS to Window streaming Issue.

When Stream EEG data via LSL in MacOS (High Sierra), the same Macbook Pro can record the stream properly with LabRecorder.
However, the Windows machine in the same network can find lsl_inlet, and connect, but cannot pull samples.
Same issue happened both in Matlab and Compiled Lab Recorder.

Is there anything I should consider?

LabRecorder.app release compatibility with MacOS 10.15

In addition to code-signing and notarization issues which require Gatekeeper settings to be modified, the 1.13.1 and 1.14.0 LabRecorder.app releases do not appear to properly run on current versions of MacOS.

Associated logs follow.

default 09:27:06.332735-0700 Finder Found application to open application file:///Users/myusername/Downloads/LabRecorder%202/LabRecorder.app
default 09:27:06.340948-0700 lsd SecTranslocateCreateSecureDirectoryForURL: created /private/var/folders/_q/wsh40r6x2l33j4n_vg3r2znc0000gn/T/AppTranslocation/BFE599BC-DDFE-4027-9653-0E861606FF58/d/LabRecorder.app
default 09:27:06.343486-0700 Finder _LSLaunch('/private/var/folders/_q/wsh40r6x2l33j4n_vg3r2znc0000gn/T/AppTranslocation/BFE599BC-DDFE-4027-9653-0E861606FF58/d/LabRecorder.app')
default 09:27:06.345026-0700 Finder LAUNCHING:0x0-0x63063 LabRecorder foreground=1 bringForward=1 seed=138 userActivityCount=0
default 09:27:06.355951-0700 Finder OSStatus _LSLaunch(LSContext *, FSNode *, LSLaunchFlags, void *, CFArrayRef, const AppleEvent *, const AEDescList *, CFArrayRef, CFDictionaryRef, LSBundleID, const audit_token_t *, const _LSOpen2Options *, ProcessSerialNumber *, Boolean *, NSError **): launching '/private/var/folders/_q/wsh40r6x2l33j4n_vg3r2znc0000gn/T/AppTranslocation/BFE599BC-DDFE-4027-9653-0E861606FF58/d/LabRecorder.app' result=0
default 09:27:06.355986-0700 CommCenter #I handleLSNotitifcation_sync: Application launched: AppInfo[LabRecorder, , true, 1430, 0]
default 09:27:06.356347-0700 loginwindow -[PersistentAppsSupport applicationReady:] | App: LabRecorder, ready, updating active tracking timer
default 09:27:06.356417-0700 loginwindow -[ApplicationManager checkInAppContext:eventData:] | ApplicationManager: Checked in app : LabRecorder
default 09:27:06.362668-0700 runningboardd Resolved pid 1430 to [executable<LabRecorder(501)>:1430]
default 09:27:06.366048-0700 runningboardd [executable<LabRecorder(501)>:1430] This process will not be managed.
default 09:27:06.366091-0700 runningboardd Now tracking process: [executable<LabRecorder(501)>:1430]
default 09:27:06.366786-0700 runningboardd Acquiring assertion targeting executable<LabRecorder(501)> from originator [daemon<com.apple.coreservices.launchservicesd>:221] with description <RBSAssertionDescriptor; foregroundApp:1430; ID: 374-221-230; target: 1430> attributes = {
<RBSDomainAttribute: 0x7fd0ec5116e0; domain: com.apple.launchservicesd; name: RoleUserInteractiveNonFocal; sourceEnvironment: 0x0>;
}
default 09:27:06.366955-0700 runningboardd Assertion 374-221-230 (target:executable<LabRecorder(501)>) will be created as active
default 09:27:06.368329-0700 runningboardd Acquiring assertion targeting executable<LabRecorder(501)> from originator [daemon<com.apple.coreservices.launchservicesd>:221] with description <RBSAssertionDescriptor; foregroundApp:1430; ID: 374-221-231; target: 1430> attributes = {
<RBSDomainAttribute: 0x7fd0ec70fab0; domain: com.apple.launchservicesd; name: RoleUserInteractiveNonFocal; sourceEnvironment: 0x0>;
}
default 09:27:06.368949-0700 runningboardd Assertion 374-221-231 (target:executable<LabRecorder(501)>) will be created as active
default 09:27:06.368314-0700 runningboardd [executable<LabRecorder(501)>:1430] Ignoring jetsam update because this process is not memory-managed
default 09:27:06.369342-0700 runningboardd [executable<LabRecorder(501)>:1430] Ignoring resume because this process is not lifecycle managed
default 09:27:06.369767-0700 runningboardd [executable<LabRecorder(501)>:1430] Ignoring GPU update because this process is not GPU managed
default 09:27:06.369951-0700 runningboardd [executable<LabRecorder(501)>:1430] Death sentinel fired!
default 09:27:06.371547-0700 runningboardd Finished acquiring assertion 374-221-231 (target:executable<LabRecorder(501)>)
default 09:27:06.371571-0700 runningboardd Invalidating assertion 374-221-230 (target:executable<LabRecorder(501)>) from originator 221
default 09:27:06.372395-0700 runningboardd Finished acquiring assertion 374-221-230 (target:executable<LabRecorder(501)>)
default 09:27:06.374495-0700 diskarbitrationd unable to copy disk description, id = /dev//Users/myusername/Downloads/LabRecorder 2/LabRecorder.app (status code 0xF8DA0003).
error 09:27:06.400269-0700 ContextStoreAgent Unhandled notification: {
ApplicationType = Foreground;
BundleIdentifierLowerCase = "";
CFBundleExecutablePath = "/private/var/folders/_q/wsh40r6x2l33j4n_vg3r2znc0000gn/T/AppTranslocation/BFE599BC-DDFE-4027-9653-0E861606FF58/d/LabRecorder.app/Contents/MacOS/LabRecorder";
CFBundleExecutablePathDeviceID = 16777220;
CFBundleExecutablePathINode = 4352058337;
CFBundleIdentifier = "";
CFBundleName = "";
CFBundleNameLowerCase = "";
CFBundlePackageType = APPL;
ChangeCount = 516;
Hidden = 0;
LSASN = "LSASN:{hi=0x0;lo=0x63063}";
LSBundlePath = "/private/var/folders/_q/wsh40r6x2l33j4n_vg3r2znc0000gn/T/AppTranslocation/BFE599BC-DDFE-4027-9653-0E861606FF58/d/LabRecorder.app";
LSBundlePathDeviceID = 16777220;
LSBundlePathINode = 4352058332;
LSDisplayName = LabRecorder;
LSExecutableFormat = LSExecutableMachOFormat;
LSExitStatus = 6;
LSLaunchBeforeTranslocationExecutablePathDeviceID = 16777220;
LSLaunchBeforeTranslocationExecutablePathINode = 4352058337;
LS
default 09:27:06.399552-0700 CommCenter #I handleLSNotitifcation_sync: Application exited: AppInfo[LabRecorder, , false, 1430, 0]
default 09:27:06.401416-0700 loginwindow -[PersistentAppsSupport applicationQuit:] | for app:LabRecorder, _appTrackingState = 2
default 09:27:06.401248-0700 runningboardd Invalidating assertion 374-221-231 (target:executable<LabRecorder(501)>) from originator 221
default 09:27:06.401444-0700 loginwindow -[PersistentAppsSupport applicationQuit:] | App: LabRecorder, quit, updating active tracking timer
default 09:27:06.474941-0700 runningboardd Removing process: [executable<LabRecorder(501)>:1430]
default 09:27:06.492181-0700 runningboardd Removing assertions for terminated process: [executable<LabRecorder(501)>:1430]

LabRecorderCLI help example would fail on Win10

The help for LabRecorderCLI suggests the following example:
./LabRecorderCLI foo.xdf 'type="EEG"' 'host="LabPC1" or host="LabPC2"'

The way the " and ' are used would work fine on my bash shell on linux and git bash on Win10, but treated differently by Win10 cmd shell. We noticed that in this case, any stream-selection-argument would recognize all streams available. If multiple stream-selection-argument were given, all streams would be recorded multiple times.

Switching " and ' around, i.e. sth like LabRecorderCLI foo.xdf "type='EEG'" "type='Marker'" would work fine, at least when tested with git bash and cmd on Win10.

Bug in filename

From a user in Slack:

I would like to set up the Labrecorder to store recordings to C:\Recordings\exp_%p_%b.xdf (running Windows 10 OS)
When i set the storageLocation in the config File to:
StorageLocation="C:\Recordings\exp_%p_%b.xdf"
the result is that LabRecorder simply ignores the Recordings Subfolder and saves the File directly to C:
The only way to get it to save to the correct Folder is to add a (nonexistent) subfolder to the Storage Location:
StorageLocation="C:\Recordings\xyz\exp_%p_%b.xdf"
Now it again ignores the last subfolder before the FIleName and saves to the intended Location.
I don't think this is the intended behaviour. Am i doing something wrong?

I haven't investigated yet, but it's either in parsing the storage location somewhere around here or buildFilename or when starting recording here.

HDF5 Support

Hi there,

Just wondering if you thought of adding hdf5 support for the more widely used format and if there are any issues against?

Thanks
Andrew

Builds with BOOST_TYPE_CONVERSIONS=ON` fail on macOS

I am trying to build LabRecorded in Mac and getting build errors. The error is as follows: /labstreaminglayer/Apps/LabRecorder/src/conversions.h:37:5: error:
member reference type 'std::ostream' (aka 'basic_ostream') is not a
pointer; did you mean to use '.'?
dst->sputn(reinterpret_cast<const char *>(&t), sizeof(t));
~~~^~
.
/labstreaminglayer/Apps/LabRecorder/src/conversions.h:37:7: error:
no member named 'sputn' in 'std::__1::basic_ostream'
dst->sputn(reinterpret_cast<const char *>(&t), sizeof(t));

AppVeyor - CPack does not bundle Qt dlls

Here is a portion of the output from the AppVeyor console. While it looks rather normal, the generated 7zip files are missing the Qt dlls.

I'm well out of time to work on this today.

[18/19] Install the project...
-- Install configuration: "Release"
-- Installing: C:/projects/app-labrecorder/build/install/LabRecorder/LabRecorder.exe
-- Installing: C:/projects/app-labrecorder/build/install/LabRecorder/liblsl64.dll
-- Running Qt Deploy Tool...
C:\projects\app-labrecorder\build\install\LabRecorder\LabRecorder.exe 64 bit, release executable
Adding Qt5Svg for qsvgicon.dll
Skipping plugin qtvirtualkeyboardplugin.dll due to disabled dependencies (Qt5Qml Qt5Quick).
Direct dependencies: Qt5Core Qt5Gui Qt5Widgets
All dependencies   : Qt5Core Qt5Gui Qt5Widgets
To be deployed     : Qt5Core Qt5Gui Qt5Svg Qt5Widgets
Updating Qt5Core.dll.
Updating Qt5Gui.dll.
Updating Qt5Svg.dll.
Updating Qt5Widgets.dll.
Updating libGLESV2.dll.
Updating libEGL.dll.
Patching Qt5Core.dll...
Creating directory C:/projects/app-labrecorder/build/install/LabRecorder/iconengines.
Updating qsvgicon.dll.
Creating directory C:/projects/app-labrecorder/build/install/LabRecorder/imageformats.
Updating qgif.dll.
Updating qicns.dll.
Updating qico.dll.
Updating qjpeg.dll.
Updating qsvg.dll.
Updating qtga.dll.
Updating qtiff.dll.
Updating qwbmp.dll.
Updating qwebp.dll.
Creating directory C:/projects/app-labrecorder/build/install/LabRecorder/platforms.
Updating qwindows.dll.
Creating directory C:/projects/app-labrecorder/build/install/LabRecorder/styles.
Updating qwindowsvistastyle.dll.
-- Installing: C:/projects/app-labrecorder/build/install/LabRecorder/LabRecorderCLI.exe
-- Up-to-date: C:/projects/app-labrecorder/build/install/LabRecorder/liblsl64.dll
-- Installing: C:/projects/app-labrecorder/build/install/LabRecorder/testxdfwriter.exe
-- Up-to-date: C:/projects/app-labrecorder/build/install/LabRecorder/liblsl64.dll
-- Installing: C:/projects/app-labrecorder/build/install/LabRecorder/LabRecorder.cfg
cpack
CPack: Create package using 7Z
CPack: Install projects
CPack: - Install project: LabRecorder
CPack: -   Install component: LabRecorder
CPack: -   Install component: Unspecified
C:\projects\app-labrecorder\build\install\LabRecorder\LabRecorder.exe 64 bit, release executable
Adding Qt5Svg for qsvgicon.dll
Skipping plugin qtvirtualkeyboardplugin.dll due to disabled dependencies (Qt5Qml Qt5Quick).
Direct dependencies: Qt5Core Qt5Gui Qt5Widgets
All dependencies   : Qt5Core Qt5Gui Qt5Widgets
To be deployed     : Qt5Core Qt5Gui Qt5Svg Qt5Widgets
Qt5Core.dll is up to date.
Qt5Gui.dll is up to date.
Qt5Svg.dll is up to date.
Qt5Widgets.dll is up to date.
libGLESV2.dll is up to date.
libEGL.dll is up to date.
Patching Qt5Core.dll...
qsvgicon.dll is up to date.
qgif.dll is up to date.
qicns.dll is up to date.
qico.dll is up to date.
qjpeg.dll is up to date.
qsvg.dll is up to date.
qtga.dll is up to date.
qtiff.dll is up to date.
qwbmp.dll is up to date.
qwebp.dll is up to date.
qwindows.dll is up to date.
qwindowsvistastyle.dll is up to date.
CPack: Create package
CPack: - package: C:/projects/app-labrecorder/build/LabRecorder-1.13.0-Win64.7z generated.
CPack: - package: C:/projects/app-labrecorder/build/Unspecified-1.13.0-Win64.7z generated.

Store datetime of recording

Following up the discussion in sccn/labstreaminglayer#28, I think it would be a good idea to store the time and date of the recording somewhere in the file (i.e. the date and time when the file was created/when the inlet was created). The best place is probably the file header chunk, but this is open for discussion.

loading configuration doesn't work properly

I just noticed that with this latest release the fields Study Root doesn't behave correctly. When I load a saved config file, it fills in the Study Root field with what I had previously saved in the FileName/Template field.

This is a result of a bug on the save side. After saving the configuration file, 'StudyRoot' is equal to the entry I put in the FileName/Template field.

datetime not appearing in version 1.14.2 in Windows OS

Hello, following issue #28 , my files using labrecorder don't contain the datetime info and as such, unless I have access to the original file, it is impossible to know when was the file recorded. I am on Windows and was wondering if the datetime field was added to that platform.
EDIT: this is the version currently available in the releases website for windows64

Add LabRecorder to the winget Community Repository

winget is Windows' package manager, and I'm starting to use it more and more to automate experiment setup. I think it would be great to have LabRecorder available with it.

To add an app to winget, you have to create a PR with a manifest on the following repo: https://github.com/microsoft/winget-pkgs. I don't know if someone's willing to do that; but it looks like there's some paperwork involved, which is the best way to kill any motivation I might had to do it myself.

LabRecorderRCS writes backup in own, and not the original files directory.

Commanding LabRecorderRCS to start a measurement via TCP/IP works smoothly. If the file already exists, a backup file is created automatically. Yet, the backup is not stored in the folder of the original file, but in the folder of LabRecorder.exe. This is not linked to the filename set in the GUI. Maybe it is linked to the working directory of the shell that is started with the remote controlled LabRecorder?

Labrecorder freezers when trying to save a stream with markers

Dear all,
We are working on Windows PC with x64 processor and Windows 10 installed. For timing testing purposes we are sending out a marker stream and brainamp eeg stream. The recording starts as normal but when saving the lab recorder freezes and the markers are not saved in the data file. We tried all 4 releases of labrecorder. Any idea what could be the problem?
Best
Inge (Maastricht University)

Building 1.14.1 on Windows 10

In an upcoming experiment, I require the use of the update stream feature via RCS (introduced in 1.14.1). However, I am having issues with building from source. Is there a schedule for an upcoming release that would alleviate the need to build from source? If not, my current setup is using cmake (3.20.1) on Windows 10 to build the solution from source, using Qt5 (5.15.2) and LSL (1.14.0) and selecting Visual studio 2019 as the generator using the default native compiler . The configuration and generation of the solution works fine, but when I try to build the project in Visual Studio 2019 (16.9.4) the LabRecorder component can't be built. I get 763 errors, all of them being either LNK1120, LNK2001 and LNK2019. I think it can't properly link Qt since all of the errors are regarding Qt.

Cannot save file to local OneDrive folder

Hello,
This is a minor issue, as files can be moved to preferred folder afterwards, but nevertheless I was wondering if anyone has the answer to it.

I am using OneDrive (on Win10) to save all the data generated from my experiments, and want to save the LSL data here as well. The Study Root is set to wanted location within my OneDrive folder, and the subfolders from File Name/Template are generated when recording. But no .xdf file is created in the target folder and no errors are to been in the terminal alongside the LabRecorder GUI. The last line is written to the terminal Closing the file.
I have no issues writing to other folders besides OneDrive.

Anyone who has an idea of why this happens? Thanks.

building error in Mac OS Big SUR Chip M1

Dear community:

I was trying to build from source App-LabRecorder but I still don't know why with or without rosetta I cannot get it to work.

ld: warning: ignoring file /Users/andraderenew/opt/anaconda3/lib/liblsl64.1.13.0.dylib, building for macOS-arm64 but attempting to link with file built for macOS-x86_64
Undefined symbols for architecture arm64:
  "_lsl_copy_streaminfo", referenced from:
      _main in clirecorder.cpp.o
      recording::record_from_streaminfo(lsl::stream_info const&, bool) in recording.cpp.o
      std::__1::thread::thread<void (recording::*)(lsl::stream_info const&, bool), recording*, lsl::stream_info const&, bool, void>(void (recording::*&&)(lsl::stream_info const&, bool), recording*&&, lsl::stream_info const&, bool&&) in recording.cpp.o
      std::__1::thread::thread<void (recording::*)(lsl::stream_info const&, bool), recording*, lsl::stream_info&, bool, void>(void (recording::*&&)(lsl::stream_info const&, bool), recording*&&, lsl::stream_info&, bool&&) in recording.cpp.o
  "_lsl_create_inlet", referenced from:
      recording::record_from_streaminfo(lsl::stream_info const&, bool) in recording.cpp.o
  "_lsl_create_streaminfo", referenced from:
      recording::record_from_streaminfo(lsl::stream_info const&, bool) in recording.cpp.o
  "_lsl_destroy_inlet", referenced from:
      recording::record_from_streaminfo(lsl::stream_info const&, bool) in recording.cpp.o
      std::__1::__shared_ptr_pointer<lsl::stream_inlet*, std::__1::shared_ptr<lsl::stream_inlet>::__shared_ptr_default_delete<lsl::stream_inlet, lsl::stream_inlet>, std::__1::allocator<lsl::stream_inlet> >::__on_zero_shared() in recording.cpp.o
  "_lsl_destroy_streaminfo", referenced from:
      _main in clirecorder.cpp.o
      std::__1::vector<lsl::stream_info, std::__1::allocator<lsl::stream_info> >::vector<lsl::lsl_streaminfo_struct_**>(lsl::lsl_streaminfo_struct_**, std::__1::enable_if<(__is_cpp17_forward_iterator<lsl::lsl_streaminfo_struct_**>::value) && (is_constructible<lsl::stream_info, std::__1::iterator_traits<lsl::lsl_streaminfo_struct_**>::reference>::value), lsl::lsl_streaminfo_struct_**>::type) in clirecorder.cpp.o
      recording::record_from_streaminfo(lsl::stream_info const&, bool) in recording.cpp.o
      recording::record_from_query_results(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in recording.cpp.o
      std::__1::vector<lsl::stream_info, std::__1::allocator<lsl::stream_info> >::vector<lsl::lsl_streaminfo_struct_**>(lsl::lsl_streaminfo_struct_**, std::__1::enable_if<(__is_cpp17_forward_iterator<lsl::lsl_streaminfo_struct_**>::value) && (is_constructible<lsl::stream_info, std::__1::iterator_traits<lsl::lsl_streaminfo_struct_**>::reference>::value), lsl::lsl_streaminfo_struct_**>::type) in recording.cpp.o
      std::__1::thread::thread<void (recording::*)(lsl::stream_info const&, bool), recording*, lsl::stream_info const&, bool, void>(void (recording::*&&)(lsl::stream_info const&, bool), recording*&&, lsl::stream_info const&, bool&&) in recording.cpp.o
      void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void (recording::*)(lsl::stream_info const&, bool), recording*, lsl::stream_info, bool> >(void*) in recording.cpp.o
      ...
  "_lsl_destroy_string", referenced from:
      recording::record_from_streaminfo(lsl::stream_info const&, bool) in recording.cpp.o
      lsl::stream_inlet::pull_sample(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*, int, double) in recording.cpp.o
  "_lsl_get_channel_count", referenced from:
      recording::record_from_streaminfo(lsl::stream_info const&, bool) in recording.cpp.o
  "_lsl_get_channel_format", referenced from:
      recording::record_from_streaminfo(lsl::stream_info const&, bool) in recording.cpp.o
  "_lsl_get_fullinfo", referenced from:
      recording::record_from_streaminfo(lsl::stream_info const&, bool) in recording.cpp.o
  "_lsl_get_hostname", referenced from:
      _main in clirecorder.cpp.o
      recording::record_from_streaminfo(lsl::stream_info const&, bool) in recording.cpp.o
  "_lsl_get_name", referenced from:
      _main in clirecorder.cpp.o
      recording::record_from_streaminfo(lsl::stream_info const&, bool) in recording.cpp.o
      recording::record_from_query_results(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in recording.cpp.o
  "_lsl_get_nominal_srate", referenced from:
      recording::record_from_streaminfo(lsl::stream_info const&, bool) in recording.cpp.o
  "_lsl_get_source_id", referenced from:
      recording::record_from_query_results(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in recording.cpp.o
  "_lsl_get_uid", referenced from:
      recording::record_from_query_results(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in recording.cpp.o
  "_lsl_get_xml", referenced from:
      recording::record_from_streaminfo(lsl::stream_info const&, bool) in recording.cpp.o
  "_lsl_local_clock", referenced from:
      recording::record_offsets(unsigned int, std::__1::shared_ptr<lsl::stream_inlet> const&, std::__1::atomic<bool>&) in recording.cpp.o
  "_lsl_open_stream", referenced from:
      recording::record_from_streaminfo(lsl::stream_info const&, bool) in recording.cpp.o
  "_lsl_pull_sample_buf", referenced from:
      lsl::stream_inlet::pull_sample(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*, int, double) in recording.cpp.o
  "_lsl_pull_sample_c", referenced from:
      lsl::stream_inlet::pull_sample(std::__1::vector<char, std::__1::allocator<char> >&, double) in recording.cpp.o
  "_lsl_pull_sample_d", referenced from:
      void recording::typed_transfer_loop<double>(unsigned int, double, std::__1::shared_ptr<lsl::stream_inlet> const&, double&, double&, unsigned long long&) in recording.cpp.o
      bool lsl::stream_inlet::pull_chunk_multiplexed<double>(std::__1::vector<double, std::__1::allocator<double> >&, std::__1::vector<double, std::__1::allocator<double> >*, double, bool) in recording.cpp.o
  "_lsl_pull_sample_f", referenced from:
      void recording::typed_transfer_loop<float>(unsigned int, double, std::__1::shared_ptr<lsl::stream_inlet> const&, double&, double&, unsigned long long&) in recording.cpp.o
      bool lsl::stream_inlet::pull_chunk_multiplexed<float>(std::__1::vector<float, std::__1::allocator<float> >&, std::__1::vector<double, std::__1::allocator<double> >*, double, bool) in recording.cpp.o
  "_lsl_pull_sample_i", referenced from:
      void recording::typed_transfer_loop<int>(unsigned int, double, std::__1::shared_ptr<lsl::stream_inlet> const&, double&, double&, unsigned long long&) in recording.cpp.o
      bool lsl::stream_inlet::pull_chunk_multiplexed<int>(std::__1::vector<int, std::__1::allocator<int> >&, std::__1::vector<double, std::__1::allocator<double> >*, double, bool) in recording.cpp.o
  "_lsl_pull_sample_s", referenced from:
      void recording::typed_transfer_loop<short>(unsigned int, double, std::__1::shared_ptr<lsl::stream_inlet> const&, double&, double&, unsigned long long&) in recording.cpp.o
      bool lsl::stream_inlet::pull_chunk_multiplexed<short>(std::__1::vector<short, std::__1::allocator<short> >&, std::__1::vector<double, std::__1::allocator<double> >*, double, bool) in recording.cpp.o
  "_lsl_resolve_all", referenced from:
      _main in clirecorder.cpp.o
  "_lsl_resolve_bypred", referenced from:
      recording::record_from_query_results(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in recording.cpp.o
  "_lsl_samples_available", referenced from:
      bool lsl::stream_inlet::pull_chunk_multiplexed<char>(std::__1::vector<char, std::__1::allocator<char> >&, std::__1::vector<double, std::__1::allocator<double> >*, double, bool) in recording.cpp.o
      bool lsl::stream_inlet::pull_chunk_multiplexed<short>(std::__1::vector<short, std::__1::allocator<short> >&, std::__1::vector<double, std::__1::allocator<double> >*, double, bool) in recording.cpp.o
      bool lsl::stream_inlet::pull_chunk_multiplexed<int>(std::__1::vector<int, std::__1::allocator<int> >&, std::__1::vector<double, std::__1::allocator<double> >*, double, bool) in recording.cpp.o
      bool lsl::stream_inlet::pull_chunk_multiplexed<float>(std::__1::vector<float, std::__1::allocator<float> >&, std::__1::vector<double, std::__1::allocator<double> >*, double, bool) in recording.cpp.o
      bool lsl::stream_inlet::pull_chunk_multiplexed<double>(std::__1::vector<double, std::__1::allocator<double> >&, std::__1::vector<double, std::__1::allocator<double> >*, double, bool) in recording.cpp.o
      bool lsl::stream_inlet::pull_chunk_multiplexed<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&, std::__1::vector<double, std::__1::allocator<double> >*, double, bool) in recording.cpp.o
  "_lsl_set_postprocessing", referenced from:
      recording::record_from_streaminfo(lsl::stream_info const&, bool) in recording.cpp.o
  "_lsl_stream_info_matches_query", referenced from:
      _main in clirecorder.cpp.o
  "_lsl_time_correction", referenced from:
      recording::record_offsets(unsigned int, std::__1::shared_ptr<lsl::stream_inlet> const&, std::__1::atomic<bool>&) in recording.cpp.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [LabRecorderCLI.app/Contents/MacOS/LabRecorderCLI] Error 1
make[1]: *** [CMakeFiles/LabRecorderCLI.dir/all] Error 2
make: *** [all] Error 2

CMake error when using Qt5 on Debian

I'm attempting to build LabRecorder on an arm64 device (Raspberry Pi 4 Model B Rev 1.4) running Debian 10, cmake 3.13.4, Qt 5.11.3.

I successfully built liblsl, but seems that CMake insists on searching for Qt6, even though it looks like there's some logic to fallback to Qt5 in CMakeLists.txt. Because there are no Qt6 packages for Debian, and I want to run LabRecorder "headless" anyway, it'd be nice to not have to wrangle a Qt6 installation if possible.

root@rpi4-20210210:~/git/App-LabRecorder/build# LSL_DIR=../../liblsl/build cmake -DCMAKE_PREFIX_PATH=/usr/lib/aarch64-linux-gnu/cmake/qt5 ..
-- Included LSL CMake helpers, rev. 15, /root/git/liblsl/build
CMake Warning at CMakeLists.txt:41 (find_package):
  By not providing "FindQt6.cmake" in CMAKE_MODULE_PATH this project has
  asked CMake to find a package configuration file provided by "Qt6", but
  CMake did not find one.

  Could not find a package configuration file provided by "Qt6" with any of
  the following names:

    Qt6Config.cmake
    qt6-config.cmake

  Add the installation prefix of "Qt6" to CMAKE_PREFIX_PATH or set "Qt6_DIR"
  to a directory containing one of the above files.  If "Qt6" provides a
  separate development package or SDK, be sure it has been installed.


CMake Error at /root/git/liblsl/build/LSLCMake.cmake:140 (install):
  install TARGETS given no ARCHIVE DESTINATION for static library target
  "xdfwriter".
Call Stack (most recent call first):
  CMakeLists.txt:94 (installLSLApp)


-- Installing Components: LabRecorder
-- Configuring incomplete, errors occurred!
See also "/root/git/App-LabRecorder/build/CMakeFiles/CMakeOutput.log".
See also "/root/git/App-LabRecorder/build/CMakeFiles/CMakeError.log".

What should RecorderLib look like?

There are two different approaches to a recorderlib:

Tristan's approach:

  • have separate, well-tested libraries for the absolutely necessary parts, namely handling streams (liblsl) and writing xdf files (libxdf, already present in this repo)
  • recorder applications have to
    • resolve a list of streams from liblsl and pick some of them
    • create an xdfwriter with a suitable filename
    • subscribe to the streams and (in a loop) acquire data, save it to the xdf file

Pros

  • clients can use all the languages bells and whistles, e.g. cross-thread signals and slots for C++/Qt, exceptions with the offending part present in the stack trace, properties bound to the UI in Java etc.
  • the API isn't limited by what can be expressed in a C ABI
  • end users / developers can adjust the code without knowing C(++)
  • the common tasks have a much smaller API surface and can be tested better in isolation (e.g. the xdfwriter)
  • different requirements call for different languages and user's requirements correlate with the languages they choose, e.g.:
    • "just record these streams and stop some time later, bonus for easy redistribution" with the C++ labrecorder
    • maximum flexibility (remote control of required streams, changing filenames mid-experiment and notify some presentation software once all streams are present), but a complete Python distribution is required
  • unlike liblsl, recorder apps are mostly standalone and therefore can use a language appropriate for the task, instead of needing to integrate with a larger application / vendor SDK

Cons

  • duplicated code, efforts and bugs for common parts

Chad's approach:

Copied from Chad's comment:

For now, if Lab Recorder functionality is needed on Android, the developer would need to make a Java wrapper around some sort of Lab Recorder library. Is someone currently building such a library?

Tristan and I are not in agreement of what this library should look like.
I hope I'm not misrepresenting him, but I think he's of the opinion that the library-consuming client application should do quite a bit, including handling the data, handling the arrival of new streams, using signals and slots, etc.
I'm of the opinion that the library should do just about everything and the client should do as little as possible, maybe limited to things like get_list_of_stream_identifiers(*stream_ids, *stream_strings), set_stream_recording_status(stream_id, on_or_off), get_likely_filename(some, params), start_recording(filename), stop_recording(), get_recorder_status(*state_struct). The client will never touch the data or know for sure the data are being recorded; it only knows what the state_struct tells it and only when it asks for that info.
Tristan doesn't like my approach because it's not responsive to errors and because it'll make debugging difficult.
The reason I don't like Tristan's approach is because it will require repeating a lot of functionality for each implementation. The list of implementations that we feel are necessary are C++, Python, Java, maybe something for iOS, and I think there was a good reason to have C# but I can't remember right now.

Ubuntu release missing liblsl

Hello, whenever I try to call LabRecorder from the command line (Ubuntu 18.04) I get the following error:
LabRecorder: error while loading shared libraries: liblsl64.so.1.13.0: cannot open shared object file: No such file or directory

LabStreamingLayer transmission problem

This is the steram problem of LabRecorder reading two computers. The main computer is the window 10 system, and the other computer is the window 7 system. I let window 10 and window 7 each send a stream. When I open LabRecorder in window10, there is only its own stream, and I open window7's LabRecorder with two streams. Then I press Update in the LabRecorder of window10 and two streams will appear.
But after I started recording and stopped, he would show no response, but there is still a .xdf file.
I use matlab to read the .xdf file and only have one stream of window10.
I am recording a video. Both computers are on the same domain and the firewall is down.
This is the video URL: https://youtu.be/kfY2FsC0U8Y

Error using chol Matrix must be positive definite on liblsl 1.14 + LabRecorderCLI 1.13.1

Environment Info

debian@sr-imx8:~/liblsl-build/liblsl/build/install/bin$ ./lslver
LSL version: 114
git:v1.14.0b4-2-g1eaaf08c/branch:master/build:/compiler:GNU-10.2.0/link:shared

Tried both LabRecorderCLI tagged v1.13.1 and the latest from [master] branch, but still the same problem.

Issue

When using LSL v1.14 with LabRecorder (master branch from https://github.com/labstreaminglayer/App-LabRecorder), the following error occurred in 1 out of 5 XDF recordings (or none if I'm lucky). It is really hard to reproduce, and Google search points me to #15, which mentioned a clock offset bug introduced in liblsl1.13. Is it still unsolved and somehow creep to 1.14?

I'm running the consumer using the sample code, SendDataC. I also make sure to press 'Enter' to correctly closed the file, as follows:

debian@sr-imx8:~$ LabRecorderCLI SendDataC4.xdf 'type="EEG"'
Found SendDataC@sr-imx8 matching 'type="EEG"'
Starting the recording, press Enter to quit
2020-10-16 00:09:39.348 (   1.003s) [        AE0941C0]             common.cpp:50    INFO| git:v1.14.0b4-2-g1eaaf08c/branch:master/build:/compiler:GNU-10.2.0/link:shared
Opened the stream SendDataC.
Received header for stream SendDataC.
Started data collection for stream SendDataC.

Offsets thread is finished
Wrote footer for stream SendDataC.
Closing the file.

Not sure if this issue is related to liblsl or LabRecorderCLI.

LabRecorder-1.13.1-Linux64-bionic.deb depends from labrecorder-liblsl

Hi,
I cannot install LabRecorder-1.13.1 from the deb package as it asks for the dependency labrecorder-liblsl which I cannot find. It is supposed to be the liblsl deb package available as a release in the liblsl repo? if so the name does not match and the dependency cannot be satisfied.

Moreover I noticed the deb package lsl-1.13.1-Linux-liblsl.deb among the debs in the latest release of LabRecorder however is seems to be empty.

Thanks,
Alberto

Unmet dependency Ubuntu: Package 1 is not installed

Hello!
I get an error while installing LabRecorder-1.14.0-focal_amd64.deb on Ubuntu 20.04.2 LTS.
I first installed the liblsl 1.14.0 with no problem.
Then, when I try to install LabRecorder it gives a strange output:

dpkg: dependency problems prevent configuration of labrecorder:
labrecorder depends on 1; however:
Package 1 is not installed.

What is package 1?

LabRecorder crashes on open macOS Big Sur 11.3.1 (20E241)

Hi - Downloaded Big Sur 1.14 tar release here: https://github.com/labstreaminglayer/App-LabRecorder/releases/download/v1.14.0/LabRecorder-1.14.0-MacOS_BigSur.tar.bz2. Extracted the folder to Applications and then tried to open the application. Received this error report:

Process:               LabRecorder [8343]
Path:                  /private/var/folders/*/LabRecorder.app/Contents/MacOS/LabRecorder
Identifier:            ???
Version:               ??? (???)
Code Type:             X86-64 (Native)
Parent Process:        ??? [1]
Responsible:           LabRecorder [8343]
User ID:               501

Date/Time:             2021-05-27 18:20:17.644 -0700
OS Version:            macOS 11.3.1 (20E241)
Report Version:        12
Anonymous UUID:        2CB947F5-6D76-16D2-6B60-9EBF68C34E08

Sleep/Wake UUID:       35D38B3A-EF8D-4056-9105-1280F2B38C40

Time Awake Since Boot: 97000 seconds
Time Since Wake:       4300 seconds

System Integrity Protection: enabled

Notes:                 Translocated Process

Crashed Thread:        0

Exception Type:        EXC_CRASH (SIGABRT)
Exception Codes:       0x0000000000000000, 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Termination Reason:    DYLD, [0x1] Library missing

Application Specific Information:
dyld: launch, loading dependent libraries

Dyld Error Message:
  dyld: Using shared cache: 94BDF3EE-CD67-34B0-91E1-19D61487C096
Library not loaded: /usr/local/opt/qt/lib/QtWidgets.framework/Versions/5/QtWidgets
  Referenced from: /private/var/folders/*/LabRecorder.app/Contents/MacOS/LabRecorder
  Reason: image not found

Binary Images:
       0x105353000 -        0x1053bafff + (??? - ???) <C42333DD-648D-3CBC-88BB-6D8721E036CE> /var/folders/*/LabRecorder.app/Contents/MacOS/LabRecorder
       0x114df9000 -        0x114e94fff  dyld (851.27) <7EAA668B-F906-3BAA-A980-139BBE6E8766> /usr/lib/dyld

Model: MacBookAir6,2, BootROM 431.0.0.0.0, 2 processors, Dual-Core Intel Core i7, 1.7 GHz, 8 GB, SMC 2.13f15
Graphics: kHW_IntelHD5000Item, Intel HD Graphics 5000, spdisplays_builtin
Memory Module: BANK 0/DIMM0, 4 GB, DDR3, 1600 MHz, 0x02FE, -
Memory Module: BANK 1/DIMM0, 4 GB, DDR3, 1600 MHz, 0x02FE, -
AirPort: spairport_wireless_card_type_airport_extreme (0x14E4, 0x117), Broadcom BCM43xx 1.0 (7.77.111.1 AirPortDriverBrcmNIC-1680.7)
Bluetooth: Version 8.0.4d18, 3 services, 19 devices, 1 incoming serial ports
Network Service: Wi-Fi, AirPort, en0
Serial ATA Device: APPLE SSD SM0512F, 500.28 GB
USB Device: USB 3.0 Bus
USB Device: BRCM20702 Hub
USB Device: Bluetooth USB Host Controller
Thunderbolt Bus: MacBook Air, Apple Inc., 23.6

Looks like a Qt dependency issue? Any advice for fixing? Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.