Skip to content

Commit

Permalink
Merge pull request #51 from labstreaminglayer/qt6
Browse files Browse the repository at this point in the history
Qt6
  • Loading branch information
cboulay authored Jun 12, 2021
2 parents 5055f4d + f606754 commit a498a44
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 66 deletions.
51 changes: 30 additions & 21 deletions .github/workflows/cppcmake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ on:
types: ['created']

env:
LSL_RELEASE_URL: 'https://github.com/sccn/liblsl/releases/download/v1.14.0'
LSL_RELEASE: '1.14.0'
LSL_RELEASE_URL: 'https://github.com/sccn/liblsl/releases/download/v1.14.1b9'
LSL_RELEASE: '1.14.1'

defaults:
run:
shell: bash


# Check qt_ver on # https://download.qt.io/online/qtsdkrepository/
jobs:
build:
name: ${{ matrix.config.name }}
Expand All @@ -27,31 +27,32 @@ jobs:
fail-fast: false
matrix:
config:
- {name: "ubuntu-20.04", os: "ubuntu-20.04"}
- {name: "ubuntu-18.04", os: "ubuntu-18.04"}
- {name: "ubuntu-16.04", os: "ubuntu-16.04"}
- name: "ubuntu-20.04"
os: "ubuntu-20.04"
- name: "ubuntu-18.04"
os: "ubuntu-18.04"
- name: "windows-x64"
os: "windows-latest"
cmake_extra: "-T v142,host=x86"
arch: "amd64"
qt: "win64_msvc2019_64"
qt_arch: "win64_msvc2019_64"
qt_ver: "6.1.0"
- name: "windows-x86"
os: "windows-latest"
cmake_extra: "-T v142,host=x86 -A Win32"
arch: "i386"
qt: "win32_msvc2019"
- {name: "macOS-latest", os: "macOS-latest"}
qt_arch: "win32_msvc2019"
qt_ver: "5.15.2"
- name: "macOS-10"
os: "macos-10.15"
qt_ver: "6.1.0"
steps:
- uses: actions/checkout@v2

- name: Install Qt
uses: jurplel/[email protected]
with:
arch: ${{ matrix.config.qt }}

- name: Install liblsl (Ubuntu)
if: startsWith(matrix.config.os, 'ubuntu-')
run: |
sudo apt install -y libpugixml-dev
curl -L ${LSL_RELEASE_URL}/liblsl-${LSL_RELEASE}-$(lsb_release -sc)_amd64.deb -o liblsl.deb
sudo dpkg -i liblsl.deb
Expand All @@ -62,11 +63,19 @@ jobs:
7z x liblsl.zip -oLSL
- name: Download liblsl (macOS)
if: matrix.config.os == 'macOS-latest'
run: |
curl -L ${LSL_RELEASE_URL}/liblsl-${LSL_RELEASE}-OSX_amd64.tar.bz2 -o liblsl.tar.bz2
mkdir LSL
tar -xvf liblsl.tar.bz2 -C LSL
if: startsWith(matrix.config.os, 'macos-')
run: brew install labstreaminglayer/tap/lsl

- name: Install Qt .deb packages
if: startsWith(matrix.config.os, 'ubuntu-')
run: sudo apt install -y qtbase5-dev

- name: Install Qt (Win and Mac)
if: startsWith(matrix.config.os, 'windows') || startsWith(matrix.config.os, 'macos')
uses: jurplel/[email protected]
with:
version: ${{ matrix.config.qt_ver }}
arch: ${{ matrix.config.qt_arch }}

- name: Configure CMake
run: |
Expand All @@ -85,10 +94,10 @@ jobs:

- name: package
run: |
export LD_LIBRARY_PATH=$Qt5_Dir/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=$Qt5_DIR/lib:$Qt6_DIR/lib:$LD_LIBRARY_PATH
cmake --build build --config Release -j --target package
cmake -E remove_directory package/_CPack_Packages
- name: Upload Artifacts
uses: actions/upload-artifact@v2
with:
Expand Down
97 changes: 66 additions & 31 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,38 +1,63 @@
cmake_minimum_required(VERSION 3.5)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14" CACHE STRING "Minimum MacOS deployment version")
cmake_minimum_required(VERSION 3.12)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum MacOS deployment version")

project(LabRecorder
DESCRIPTION "Record and write LabStreamingLayer streams to an XDF file"
HOMEPAGE_URL "https://github.com/labstreaminglayer/App-LabRecorder/"
LANGUAGES C CXX
VERSION 1.14.0)
VERSION 1.14.1)

# Needed for customized MacOSXBundleInfo.plist.in
SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake" ${CMAKE_MODULE_PATH})

find_package(LSL REQUIRED
HINTS ${LSL_INSTALL_ROOT}
"${CMAKE_CURRENT_LIST_DIR}/../../LSL/liblsl/build/"
"${CMAKE_CURRENT_LIST_DIR}/../../LSL/liblsl/build/install"
"${CMAKE_CURRENT_LIST_DIR}/../../LSL/liblsl/out/build/x64-Release"
"${CMAKE_CURRENT_LIST_DIR}/../../LSL/liblsl/out/install/x64-Release"
PATH_SUFFIXES share/LSL
)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED On)

set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
# Dependencies

## LSL
if(ANDROID)
set(LIBLSL_SOURCE_PATH "../../LSL/liblsl" CACHE STRING "Path to liblsl sources")

# force include liblsl as target to build with the android toolchain
# as path of the normal build process
add_subdirectory(${LIBLSL_SOURCE_PATH} liblsl_bin)
add_library(LSL::lsl ALIAS lsl)
else()
find_package(LSL REQUIRED
HINTS ${LSL_INSTALL_ROOT}
"${CMAKE_CURRENT_LIST_DIR}/../../LSL/liblsl/build/"
"${CMAKE_CURRENT_LIST_DIR}/../../LSL/liblsl/build/install"
"${CMAKE_CURRENT_LIST_DIR}/../../LSL/liblsl/out/build/x64-Release"
"${CMAKE_CURRENT_LIST_DIR}/../../LSL/liblsl/out/install/x64-Release"
PATH_SUFFIXES share/LSL
)
endif()

## Qt
set(CMAKE_AUTOMOC ON) # The later version of this in LSLCMake is somehow not enough.
set(CMAKE_AUTORCC ON)
find_package(Qt5 REQUIRED COMPONENTS Widgets Network)
set(CMAKE_AUTOUIC ON)
find_package(Qt6 COMPONENTS Core Widgets Network DBus)
if(NOT Qt6_FOUND)
# If we require 5.15 then we can use version-agnostic linking, but 5.15 not easily available on Ubuntu.
find_package(Qt5 COMPONENTS Core Widgets Network DBus REQUIRED)
add_executable(${PROJECT_NAME} MACOSX_BUNDLE)
set(LSLAPP_QT_VER Qt5)
else()
qt_add_executable(${PROJECT_NAME} MACOSX_BUNDLE MANUAL_FINALIZATION)
set(LSLAPP_QT_VER Qt)
endif()

## Threads
find_package(Threads REQUIRED)

# Targets

## xdfwriter - stand alone library
add_subdirectory(xdfwriter)

add_executable(${PROJECT_NAME} MACOSX_BUNDLE #WIN32
target_sources(${PROJECT_NAME} PRIVATE
src/main.cpp
src/mainwindow.cpp
src/mainwindow.h
Expand All @@ -52,8 +77,9 @@ add_executable(LabRecorderCLI MACOSX_BUNDLE
target_link_libraries(${PROJECT_NAME}
PRIVATE
xdfwriter
Qt5::Widgets
Qt5::Network
${LSLAPP_QT_VER}::Widgets
${LSLAPP_QT_VER}::Network
${LSLAPP_QT_VER}::DBus
Threads::Threads
LSL::lsl
)
Expand All @@ -76,25 +102,34 @@ installLSLAuxFiles(${PROJECT_NAME}
)

if (WIN32)
get_target_property(QT5_QMAKE_EXECUTABLE Qt5::qmake IMPORTED_LOCATION)
get_filename_component(QT5_WINDEPLOYQT_EXECUTABLE ${QT5_QMAKE_EXECUTABLE} PATH)
set(QT5_WINDEPLOYQT_EXECUTABLE "${QT5_WINDEPLOYQT_EXECUTABLE}/windeployqt.exe")
get_target_property(QT_QMAKE_EXECUTABLE Qt::qmake IMPORTED_LOCATION)
get_filename_component(QT_WINDEPLOYQT_EXECUTABLE ${QT_QMAKE_EXECUTABLE} PATH)
set(QT_WINDEPLOYQT_EXECUTABLE "${QT_WINDEPLOYQT_EXECUTABLE}/windeployqt.exe")

add_custom_command(
TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${QT5_WINDEPLOYQT_EXECUTABLE} --qmldir
${CMAKE_CURRENT_SOURCE_DIR} $<TARGET_FILE_DIR:${PROJECT_NAME}>)
COMMAND ${QT_WINDEPLOYQT_EXECUTABLE}
--no-translations --no-system-d3d-compiler
--qmldir ${CMAKE_CURRENT_SOURCE_DIR}
$<TARGET_FILE_DIR:${PROJECT_NAME}>)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:LSL::lsl>
$<TARGET_FILE:xdfwriter>
$<TARGET_FILE_DIR:${PROJECT_NAME}>)
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:LSL::lsl>
$<TARGET_FILE:xdfwriter>
$<TARGET_FILE_DIR:${PROJECT_NAME}>)
add_custom_command(
TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}//${PROJECT_NAME}.cfg
$<TARGET_FILE_DIR:${PROJECT_NAME}>)
${CMAKE_CURRENT_SOURCE_DIR}//${PROJECT_NAME}.cfg
$<TARGET_FILE_DIR:${PROJECT_NAME}>)
endif()

if(Qt6_FOUND)
set_target_properties(${PROJECT_NAME} PROPERTIES
QT_ANDROID_EXTRA_LIBS "${CMAKE_CURRENT_BINARY_DIR}/liblsl_bin/liblsl.so")
qt_finalize_executable(${PROJECT_NAME})
endif()

set(CPACK_DEBIAN_LABRECORDER_PACKAGE_SECTION "science" CACHE INTERNAL "")
LSLGenerateCPackConfig()

31 changes: 28 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,41 @@

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.

[Download it from the Releases page](https://github.com/labstreaminglayer/App-LabRecorder/releases).

# 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](https://github.com/sccn/xdf). There are importers for MATLAB, EEGLAB, BCILAB, Python, and MoBILAB.

# Getting LabRecorder

## Dependencies

For LabRecorder to work on your system, you might need to first install some dependencies.

### MacOS

In the near future it will be necessary to use [homebrew](https://brew.sh/) to manage LSL Apps and their dependencies:
* Install homebrew: `/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"`
* Install liblsl: `brew install labstreaminglayer/tap/lsl`
* Install Qt6: `brew install qt`

### Linux Ubuntu

The Ubuntu releases do not typically ship with their dependencies so you will also have to download and install those:
* Download and install the latest [liblsl-{version}-bionic_amd64.deb from its release page](https://github.com/sccn/liblsl/releases)
* We hope to make this available via a package manager soon.
* You can install liblsl directly by double clicking on it, or with with `sudo dpkg -i {filename}.deb`
* See the bottom of the [lsl build env docs](https://labstreaminglayer.readthedocs.io/dev/build_env.html).
* For most cases, this will amount to `sudo apt-get install qtbase5-dev`

## Downloading LabRecorder

### MacOS

* `brew install labrecorder`

### Others

Navigate to the [`releases` page](https://github.com/labstreaminglayer/App-LabRecorder/releases) and download the latest release for your platform.
The Ubuntu releases do not typically ship with the libsl dependencies so you will also have to download and install [liblsl from its release page](https://github.com/sccn/liblsl/releases).

# Usage

Expand Down
25 changes: 21 additions & 4 deletions src/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
#include <QMessageBox>
#include <QSettings>
#include <QStandardPaths>
#if QT_VERSION_MAJOR < 6
#include <QRegExp>
#else
#include <QRegularExpression>
using QRegExp = QRegularExpression;
#endif

#include <string>
#include <vector>
Expand Down Expand Up @@ -90,14 +96,14 @@ MainWindow::MainWindow(QWidget *parent, const char *config_file)

void MainWindow::statusUpdate() const {
if (currentRecording) {
auto elapsed = static_cast<unsigned int>(lsl::local_clock() - startTime);
auto elapsed = static_cast<int>(lsl::local_clock() - startTime);
QString recFilename = replaceFilename(QDir::cleanPath(ui->lineEdit_template->text()));
auto fileinfo = QFileInfo(QDir::cleanPath(ui->rootEdit->text()) + '/' + recFilename);
fileinfo.refresh();
auto size = fileinfo.size();
QString timeString = QStringLiteral("Recording to %1 (%2; %3kb)")
.arg(QDir::toNativeSeparators(recFilename),
QDateTime::fromTime_t(elapsed).toUTC().toString("hh:mm:ss"),
QTime(0,0).addSecs(elapsed).toString("hh:mm:ss"),
QString::number(size / 1000));
statusBar()->showMessage(timeString);
}
Expand Down Expand Up @@ -126,14 +132,25 @@ void MainWindow::load_config(QString filename) {
// ----------------------------
// required streams
// ----------------------------
missingStreams = pt.value("RequiredStreams").toStringList().toSet();
auto required = pt.value("RequiredStreams").toStringList();
#if QT_VERSION >= QT_VERSION_CHECK(5,14,0)
missingStreams = QSet<QString>(required.begin(), required.end());
#else
missingStreams = required.toSet();
#endif

// ----------------------------
// online sync streams
// ----------------------------
QStringList onlineSyncStreams = pt.value("OnlineSync", QStringList()).toStringList();
for (QString &oss : onlineSyncStreams) {
QStringList words = oss.split(' ', QString::SkipEmptyParts); // Deprecated --> Qt::SkipEmptyParts as of Qt 5.14, but not easily available to Ubuntu 18.04
#if QT_VERSION >= QT_VERSION_CHECK(5,14,0)
auto skipEmpty = Qt::SkipEmptyParts;
#else
auto skipEmpty = QString::SkipEmptyParts;
#endif

QStringList words = oss.split(' ', skipEmpty);
// The first two words ("StreamName (PC)") are the stream identifier
if (words.length() < 2) {
qInfo() << "Invalid sync stream config: " << oss;
Expand Down
14 changes: 7 additions & 7 deletions xdfwriter/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ project(xdfwriter
DESCRIPTION "C++ library for writing XDF files"
HOMEPAGE_URL "https://github.com/labstreaminglayer/App-LabRecorder/"
LANGUAGES C CXX
VERSION 1.14.0)
VERSION 1.14.1)

option(LABRECORDER_XDFZ "use Boost.Iostreams for XDFZ support" Off)
option(LABRECORDER_BOOST_TYPE_CONVERSIONS "Use boost for type conversions" Off)
Expand All @@ -16,7 +16,7 @@ add_library(${PROJECT_NAME} xdfwriter.cpp)

add_executable(testxdfwriter test_xdf_writer.cpp)

target_link_libraries(testxdfwriter PRIVATE xdfwriter)
target_link_libraries(testxdfwriter PRIVATE ${PROJECT_NAME})
target_include_directories(${PROJECT_NAME} PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)

# Test for floating point format and endianness
Expand All @@ -42,22 +42,22 @@ endif()
if(LABRECORDER_BOOST_TYPE_CONVERSIONS)
message(STATUS "Searching Boost for type conversions")
find_package(Boost REQUIRED)
target_link_libraries(xdfwriter PRIVATE Boost::boost)
target_compile_definitions(xdfwriter PUBLIC EXOTIC_ARCH_SUPPORT)
target_link_libraries(${PROJECT_NAME} PRIVATE Boost::boost)
target_compile_definitions(${PROJECT_NAME} PUBLIC EXOTIC_ARCH_SUPPORT)
endif()

# Enable xdfz support if Boost::iostreams and Boost.zlib (Windows) or plain zlib (Unix) was found
if(LABRECORDER_XDFZ)
find_package(Boost REQUIRED COMPONENTS iostreams)
if(WIN32)
find_package(Boost REQUIRED COMPONENTS zlib)
target_link_libraries(xdfwriter PRIVATE Boost::iostreams Boost::zlib)
target_link_libraries(${PROJECT_NAME} PRIVATE Boost::iostreams Boost::zlib)
else()
find_package(ZLIB REQUIRED)
target_link_libraries(xdfwriter PRIVATE Boost::iostreams ${ZLIB_LIBRARIES})
target_link_libraries(${PROJECT_NAME} PRIVATE Boost::iostreams ${ZLIB_LIBRARIES})
endif()
message(STATUS "Found zlib, enabling support for xdfz files")
target_compile_definitions(xdfwriter PUBLIC XDFZ_SUPPORT=1)
target_compile_definitions(${PROJECT_NAME} PUBLIC XDFZ_SUPPORT=1)
endif()


0 comments on commit a498a44

Please sign in to comment.