liblsl_coordinator
A performance-focused Dart library for multi-layer LSL-based device coordination. This library provides a robust foundation for coordinating multiple devices in real-time applications using Lab Streaming Layer (LSL) with support for different communication layers.
Open file limit
Every LSL outlet, inlet and resolver holds several sockets. On macOS and Linux,
liblsl raises the process's open-file
limit when it is loaded, so sessions with many nodes and streams no longer run
into Too many open files. If it warns that it could not (e.g. in a sandbox),
raise the limit yourself with ulimit -n 4096 before starting the app. See the
liblsl README for details.
Features
- Multi-layer Architecture: Support for coordination, gaming, high-frequency, and custom stream layers
- Automatic Coordinator Discovery: Devices automatically find existing coordinators or promote themselves
- Protocol Configuration: Predefined and custom protocol configurations for different use cases
- Pausable/Resumable Streams: Game and sensor streams can be paused and resumed as needed
- Isolate-based Processing: Each layer runs in its own isolate for optimal performance
- Flexible Stream Management: Support for irregular frequency coordination and regular high-frequency data streams
- Self-promotion Logic: Automatic coordinator election when no coordinator is present
Architecture
The library implements a layered approach where:
- Coordination Layer: Always present, handles device discovery, role assignment, and protocol setup
- Data Layers: Optional layers for specific data types (game, sensors, etc.)
- Stream Management: Each layer has its own outlets and inlets managed in isolates
- Protocol System: Configurable protocols define which layers are active and their properties
Getting Started
dart pub add liblsl_coordinator
Usage
Every node runs the same code: it discovers the others over LSL, one of them is elected coordinator, and the rest join as participants.
import 'package:liblsl_coordinator/liblsl_coordinator.dart';
import 'package:liblsl_coordinator/transports/lsl.dart';
Future<void> main() async {
final config = CoordinationConfig(
name: 'my_experiment',
sessionConfig: CoordinationSessionConfig(name: 'session_1', maxNodes: 4),
topologyConfig: HierarchicalTopologyConfig(
promotionStrategy: PromotionStrategyRandom(),
maxNodes: 4,
),
streamConfig: CoordinationStreamConfig(
name: 'coordination',
sampleRate: 50.0,
),
transportConfig: LSLTransportConfig(coordinationFrequency: 50.0),
);
final session = PeerSession.create(
config,
thisNodeConfig: NodeConfigFactory().defaultConfig().copyWith(name: 'node_a'),
);
await session.initialize();
await session.join();
print(session.isCoordinator ? 'coordinator' : 'participant');
// Messages between nodes...
session.events.userCoordinationMessages.listen((m) => print(m));
await session.sendUserMessage('hello', 'Hello from node_a', {});
// ...and data streams (the coordinator creates and starts them).
if (session.isCoordinator) {
await session.createDataStream(
DataStreamConfig(
name: 'Samples',
channels: 2,
sampleRate: 100.0,
dataType: StreamDataType.double64,
),
);
await session.startStream('Samples');
}
await session.dispose();
}
The transport is pluggable: the same session code runs over the in-memory
transport from peer_coordinator
(package:peer_coordinator/in_memory.dart, used by the
example),
or over WebRTC with
webrtc_coordinator.
For more information, see the liblsl.dart repository.
Libraries
- config
- Moved to
package:peer_coordinator/config.dart. - coordination
- Moved to
package:peer_coordinator/coordination.dart. - data
- Moved to
package:peer_coordinator/data.dart. - discovery
- Moved to
package:peer_coordinator/discovery.dart. - framework
- Moved to
package:peer_coordinator/framework.dart. - interfaces
- Moved to
package:peer_coordinator/interfaces.dart. - liblsl_coordinator
- Device coordination over Lab Streaming Layer.
- logging
- Moved to
package:peer_coordinator/logging.dart. - network
- Moved to
package:peer_coordinator/network.dart. - transports/lsl
- transports/lsl/isolate/isolate_manager
- transports/lsl/isolate/outlet_buffer_pool
- transports/lsl/isolate/time_correction_schedule
- transports/lsl/lsl_coordination
- transports/lsl/lsl_discovery
- transports/lsl/lsl_predicate_compiler
- transports/lsl/lsl_resource
- transports/lsl/lsl_stream
- transports/lsl/lsl_transport