Skip to content

Repository files navigation

LSL Application Template

This is the reference template for building Lab Streaming Layer (LSL) applications in C++ with Qt6. Use this as a starting point for creating new LSL-compatible applications.

Features

  • Modern CMake (3.28+) with clean, documented structure
  • 4-tier liblsl discovery: source, install_root, system, FetchContent
  • CLI and GUI separation with shared core library
  • Qt6 for the GUI (with Qt5 intentionally dropped for simplicity)
  • Cross-platform: Linux, macOS, Windows
  • macOS code signing with entitlements for network capabilities
  • Automated CI/CD via GitHub Actions

Project Structure

LSLTemplate/
├── CMakeLists.txt # Root build configuration
├── app.entitlements # macOS network capabilities
├── LSLTemplate.cfg # Default configuration file
├── src/
│ ├── core/ # Qt-independent core library
│ │ ├── include/lsltemplate/
│ │ │ ├── Device.hpp # Device interface
│ │ │ ├── LSLOutlet.hpp # LSL outlet wrapper
│ │ │ ├── Config.hpp # Configuration management
│ │ │ └── StreamThread.hpp # Background streaming
│ │ └── src/
│ ├── cli/ # Command-line application
│ │ └── main.cpp
│ └── gui/ # Qt6 GUI application
│ ├── MainWindow.hpp/cpp
│ ├── MainWindow.ui
│ └── main.cpp
├── scripts/
│ └── sign_and_notarize.sh # macOS signing script
└── .github/workflows/
└── build.yml # CI/CD workflow

Building

Prerequisites

  • CMake 3.28 or later
  • C++20 compatible compiler
  • Qt6.8 (for GUI build)
  • liblsl (optional - will be fetched automatically if not found)

Installing Qt 6.8 on Ubuntu

Ubuntu's default repositories don't include Qt 6.8. Use aqtinstall to install it:

# Install aqtinstall
pip install aqtinstall
# Install Qt 6.8 (adjust version as needed)
aqt install-qt linux desktop 6.8.3 gcc_64 -O ~/Qt
# Set environment for CMake to find Qtexport CMAKE_PREFIX_PATH=~/Qt/6.8.3/gcc_64
# Install system dependencies
sudo apt-get install libgl1-mesa-dev libxkbcommon-dev libxcb-cursor0

To run the GUI application, ensure Qt libraries are in your library path:

export LD_LIBRARY_PATH=~/Qt/6.8.3/gcc_64/lib:$LD_LIBRARY_PATH

Alternatively, build CLI-only with -DLSLTEMPLATE_BUILD_GUI=OFF to avoid the Qt dependency.

Quick Start

# Clone and build
git clone https://github.com/labstreaminglayer/AppTemplate_cpp_qt.git
cd AppTemplate_cpp_qt
# Configure (liblsl will be fetched automatically)
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
# Build
cmake --build build --parallel
# Install
cmake --install build --prefix build/install
# Packagecd build && cpack

Build Options

OptionDefaultDescription
LSLTEMPLATE_BUILD_GUIONBuild the GUI application
LSLTEMPLATE_BUILD_CLIONBuild the CLI application
LSL_FETCH_IF_MISSINGONAuto-fetch liblsl from GitHub
LSL_FETCH_REF(see CMakeLists.txt)liblsl git ref to fetch (tag, branch, or commit)
LSL_SOURCE_DIR-Path to liblsl source (for development)
LSL_INSTALL_ROOT-Path to installed liblsl

liblsl Discovery Priority

The build system searches for liblsl in this order:

  1. LSL_SOURCE_DIR - Build from local source (for parallel liblsl development)
  2. LSL_INSTALL_ROOT - Explicit installation path
  3. System - Standard CMake search paths
  4. FetchContent - Automatic download from GitHub

CLI-Only Build

For headless systems or servers:

cmake -S . -B build -DLSLTEMPLATE_BUILD_GUI=OFF
cmake --build build

Building with Local liblsl

For parallel development with liblsl:

cmake -S . -B build -DLSL_SOURCE_DIR=/path/to/liblsl

Usage

GUI Application

./LSLTemplate # Use default config
./LSLTemplate myconfig.cfg # Use custom config

CLI Application

./LSLTemplateCLI --help
./LSLTemplateCLI --name MyStream --rate 256 --channels 8
./LSLTemplateCLI --config myconfig.cfg

Customizing for Your Device

  1. Fork/copy this template
  2. Rename the project in CMakeLists.txt
  3. Implement your device class by deriving from IDevice in src/core/include/lsltemplate/Device.hpp
  4. Update the GUI for device-specific settings in src/gui/MainWindow.ui
  5. Update configuration fields in src/core/include/lsltemplate/Config.hpp

macOS Code Signing

For local development, the build automatically applies ad-hoc signing with network entitlements. This allows the app to use LSL's multicast discovery.

For distribution, use the signing script:

# Sign only
./scripts/sign_and_notarize.sh build/install/LSLTemplate.app
# Sign and notarizeexport APPLE_CODE_SIGN_IDENTITY_APP="Developer ID Application: Your Name"export APPLE_NOTARIZE_KEYCHAIN_PROFILE="your-profile"
./scripts/sign_and_notarize.sh build/install/LSLTemplate.app --notarize

GitHub Actions Secrets

For automated signing and notarization, the workflow expects these secrets from the labstreaminglayer organization:

SecretDescription
PROD_MACOS_CERTIFICATEBase64-encoded Developer ID Application certificate (.p12)
PROD_MACOS_CERTIFICATE_PWDCertificate password
PROD_MACOS_CI_KEYCHAIN_PWDPassword for temporary CI keychain
PROD_MACOS_NOTARIZATION_APPLE_IDApple ID email for notarization
PROD_MACOS_NOTARIZATION_PWDApp-specific password for Apple ID
PROD_MACOS_NOTARIZATION_TEAM_IDApple Developer Team ID

Important: These organization secrets must be shared with your repository. In GitHub:

  1. Go to Organization Settings → Secrets and variables → Actions
  2. For each secret, click to edit and under "Repository access" select the repositories that need access

License

MIT License - see LICENSE

About

An example application to stream data from a device via the Labstreaminglayer

Resources

Stars

8 stars

Watchers

8 watching

Forks

Releases

Packages

Used by

Contributors

Languages