Blackout provides a versatile DMX (Digital Multiplex) control platform, compatible with industry-standard sACN E1.31 and Art-Net protocols via WiFi or Ethernet. Additional Bluetooth control is also available via LumenRadio TimoTwo chip devices.
Used and endorsed by experts in TV, film, and live events across the globe, Blackout is the go-to DMX control solution trusted by industry professionals for unmatched reliability and performance.
Challenge
The Blackout Lighting Console iPad app must maintain a constant and uninterrupted ~23ms transmission rate of data to hundreds of wirelessly connected lights while delivering uncompromised 60-120fps of interactive UI with hundreds of realtime data indicators alongside detailed fixture controls. DMX has a max refresh rate of 44Hz and the app must be in lock step with user control across realtime lighting updates.
The app had undergone various stages of development over ~4 years by different groups whereby the data model had grown entangled with a state management layer leading to performance degradations to be identified alongside a sophisticated set of user expectations in the field.
An aggressive timeline of 4 months was provided to the team to address these concerns in addition to an entirely new v2 design refresh.
Process
The process began by mapping out the existing data model implemented throughout the app's service layer architecture and confirming expectations with the product owner to deeply understand the app's behavior. This began a series of systematic phases of reworking the data flow to complement the UI interactions in optimal ways; allowing us to reduce extraneous code execution paths where unnecessary.
In parallel to data flow reworking, various UI component setups were being rethought and redesigned to match new design requirements as well as optimize how they interact with the replumbing of the data flow. It was during this time it was decided to switch from individual component .scss
styling setups to Tailwind CSS across the board (more on the benefit this brought to the project below).
Solution
Using NativeScript 8.6.x with Angular 17.x in tandem with ngrx state management offered a powerful set of features useful to all the development demands.
The team was able to combine Angular's DI, expressive directives, control flow templating and reactive view bindings with SwiftUI open source libraries such as DynamicColor, ColorPicker and FoggyColors as well as tap into iOS CoreMIDI directly with NativeScript to bring the UI and advanced capabilities to life with powerful expressiveness.
Design Polish
Performance Improvements
Before nStudio's involvement there had been reports of instability including a memory leak leading to eventual app crashes with continuous use beyond 3+ hours.
The team identified critical memory leaks in @nativescript/ios, submitted a pull request and helped release the patch within days.
We also decreased memory consumption by 221 MB just off it's resting footprint by switching from the legacy @nativescript/theme package to using Tailwind CSS. Before and after:
Tailwind can improve performance with NativeScript apps?
Yes. Just how optimizing JavaScript code execution paths can amount to performance gains, you can also optimize CSS handling in NativeScript apps by introducing more consistent and ultimately less CSS style definitions applying across the entire app. Tailwind does an excellent job of this by reducing redundant and even accidental duplicate classing as well as helping optimize the build to include only what the app needs for styling to spec. This all equates to more optimized code execution pathways.
Total app size?
Blackout requires offline usage in the field while still being able to patch from tens of thousands of possible fixtures in the industry. There is a SQLite database (with ability to sync from remote changes) shipped with the app which contains >30,000 fixtures, >320,000 channels to control them, >1,350,000 channel functions with unique conditions per manufacturer and thus the database is critical for the operation of the app in the field. The database itself is >420 Mb but arms each user with a complete arsenal ready for the demanding environments around professional lighting conditions.
Tech Stack
- Angular 17.x
- NativeScript 8.6.x using Node 21.x
- Allowed usage of platform optimized views -- UIKit -- using declarative JavaScript view templating
- Allowed for targeted SwiftUI just where desired via @nativescript/swift-ui, more info here.
- Tailwind CSS of all platform optimized views via NativeScript
- State Management via NgRx 17.x
- SQLite for local offline database
- Supabase for remote syncable database
- Mobile UI Testing: Maestro
Human Resources
- Product Owner/Node Extraordinaire: Jeff Brink
- Team Lead/Project Manager and UX Engineer: Nathan Walker
- Software Architect: Eduardo Speroni of Valor Software
- Software Architect and UX Engineer: Igor Randjelovic
- Senior Software Engineer: Osei Fortune
- Intern Software Developer and UI styling assistance: Owen Carey
Jeff Brink - Product Owner
Jeffrey Steven Brink is a force of nature as can be seen from his IMDb profile.
It's rare that we get the opportunity to work with a product owner as hands on with the code as Jeff. He is the MVP on the team not just because he's the product owner but because of his tireless commitment to his customers, his in depth understanding of the lighting industry, as well as his acute ability to learn on his feet - he picked up Node on the fly to write a database parsing engine to aid development with a vast lighting fixture database.
Transitioning from full-time film work, Jeff is now dedicating himself to learning to code to further his role in Blackout's development and improve his collaboration with the team.
The Angular Advantage
Angular offers a complete development surface from routing to templating to dependency injection to help project organization as well as features to aid in complex orchestration of UI like directives.
Along with Angular comes a robust ecosystem including ngrx for state management.
The team was able to use Angular 17 the day of release due to how well maintained NativeScript is. This allowed the team to use control flow syntax to improve templating conditions while at the same time gaining performance benefits from the new syntax that works in conjunction with the Angular compiler.
There was one UI feature in particular where Angular directives really delivered:
- MIDI Learn Mode
This mode allows the user to enter an interactive UI state where MIDI controls can be assigned to different highlighted UI. The feature itself was managed by a single Angular directive which orchestrates the connections between a MIDIService
and the various UI controls.
The simplicity of the directive looked a bit like this:
import { Directive } from '@angular/core'
@Directive({
selector: '[midiLink]',
})
export class MidiLinkDirective {
midiService = inject(MidiService)
activate() {
// impl
}
}
Allowing any UI to engage with the feature implementation by just declaring it as so:
<GridLayout midiLink="midi-link-fader-1" />
MIDI in Action at LDI Show:
Solidifying state management with NgRX
Workers (aka, multithreading) are a necessity in the app as we need constant transmission rate where any interruption is noticeable. Having a rock-solid state layer which can provide the correct data to workers and the UI is absolutely paramount. Previous iterations of the app relied on mutable state reacting to changes, where our approach now relies heavily on a well groomed state layer with carefully crafted selectors and memoization to ensure we don’t waste precious CPU cycles with unnecessary calculations. NgRX was the right tool for the job.
A fixture has many layers to go through until we get to the final value that needs to be transmitted to lights. The values must be calculated in order of priority through each fader that affects it, including mapping from the user facing value to the DMX (8/16 bit) value. Since this is a costly operation, we must consider custom NgRx memoization techniques for both inputs and outputs of selectors, as well as handling of back pressure from the state.
The NativeScript Advantage
The ability to bring together vast talent across the entire JavaScript ecosystem (not just one corner) into unity with platform development is unparalleled in expressiveness, creative control, performance and options to deliver no matter the objective.
To illustrate a small example which brought joy to our developers was the MIDI integration challenge involving interwoven Bluetooth and hard wired devices. iOS presents a unique condition with MIDI integrations which will cache connected devices at a low level and presents challenges in getting newly connected devices available for use in various MIDI systems. Most off the shelf MIDI plugins do not handle this condition well as it can vary based on various Bluetooth and hard wired device interaction UX flows per app requirements.
With NativeScript we were able to reference the iOS docs directly to find that MIDIRestart can be called to force Core MIDI to ask its drivers to rescan for hardware.
Without jumping IDE's or languages, we were able to invoke it directly using TypeScript (the app's base language) without fiddling with 3rd party plugins or other integrations, saving the team critical time. Use the platform.
// With NativeScript, true platform development is enabled.
// Allow CoreMIDI devices to retrieve accurate state.
MIDIRestart()
This platform API is defined in TypeScript via objc!CoreMIDI.d.ts
from @nativescript/types
whereby you can configure any project to include types for more advanced APIs per needs: https://blog.nativescript.org/where-did-my-types-go/
Highlighted Transformations
Due to new @nativescript/core
features introduced just earlier this year, the team was able to improve the login flow:
This flow utilizes Shared Element Transitions from @nativescript/core, introduced just this year 2023, for a sleek user experience.
The color picking which translates in real time between different color modes such as RGB > CMYK > HSB > XY was not possible in v1 but v2 brings fluidity in color handling:
LDI in Las Vegas - Live Product Demonstration
The team traveled to Las Vegas in December 2023 for the LDI (Live Design International) Conference to help demonstrate the app.
Takeaways
Our team finds that technologies found within the OpenJS Foundation such as Node, NativeScript and the various technologies built on them like Angular and beyond serve as fundamental technical tools to achieve project objectives from simple to the incredibly complex.
For demanding platform projects, using NativeScript is a great way to increase talent hiring potential because it leverages innovation from all popular ecosystems (SwiftUI, Kotlin/Compose, React Native, Capacitor or Flutter including your desired choice of JavaScript framework) leaving no barrier in the way to unlock the richness and demanding nature of rich platform development.
Blackout v2 is currently in Private Beta, you may contact [email protected] if interested in providing feedback.