musalce-server 0.8.0 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/notify-plugin.yml +2 -2
- data/README.md +26 -37
- data/docs/architecture.md +33 -97
- data/lib/midi-devices.rb +15 -5
- data/lib/version.rb +1 -1
- data/musalce-server.gemspec +2 -2
- metadata +8 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 10e3d4f033d3eacba2acafbb6e99abc3306296254ea044f9b23fc1ed266444a1
|
|
4
|
+
data.tar.gz: f0d2d8eb2af59d4c257afb52f0e51ce34a896d087cff4caaf91d45c264e30b42
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a8e4291be4780a9b13f0bc42076806a09c2107759696e51c7dd1121226572edc3d8fec28b28e3feda9ab50b2f3db16f15cd7b5cdb1be1b48db303e72df49879a
|
|
7
|
+
data.tar.gz: 5ebb527af34b1776cd7574eaa82b4a2a565a4ed8859e104a955336d598a272fa4d3c5ba3f79d10623054a9881b41129f1b80f211d0a9a0b166e06df7705e19bd
|
|
@@ -8,10 +8,10 @@ jobs:
|
|
|
8
8
|
notify:
|
|
9
9
|
runs-on: ubuntu-latest
|
|
10
10
|
steps:
|
|
11
|
-
- name: Trigger nota-plugin
|
|
11
|
+
- name: Trigger nota-plugin rebuild
|
|
12
12
|
uses: peter-evans/repository-dispatch@v3
|
|
13
13
|
with:
|
|
14
14
|
token: ${{ secrets.PLUGIN_REBUILD_PAT }}
|
|
15
|
-
repository: javier-sy/nota-plugin
|
|
15
|
+
repository: javier-sy/nota-plugin
|
|
16
16
|
event-type: source-updated
|
|
17
17
|
client-payload: '{"repo": "${{ github.repository }}", "sha": "${{ github.sha }}"}'
|
data/README.md
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
# MusaLCE Server
|
|
1
|
+
# MusaLCE Server Suite
|
|
2
2
|
|
|
3
3
|
[](https://www.ruby-lang.org/)
|
|
4
4
|
[](https://www.gnu.org/licenses/gpl-3.0.html)
|
|
5
5
|
|
|
6
|
-
**Musa-DSL Live Coding Environment Server for Ableton Live 11+ and Bitwig Studio 5+**
|
|
6
|
+
**Musa-DSL Live Coding Environment Server Suite for Ableton Live 11+ and Bitwig Studio 5+**
|
|
7
7
|
|
|
8
8
|
This server enables live coding music composition using [Musa-DSL](https://github.com/javier-sy/musa-dsl) with your favorite DAW and code editor.
|
|
9
9
|
|
|
10
10
|
## Overview
|
|
11
11
|
|
|
12
|
-
The MusaLCE system allows you to write Ruby code in your editor (Visual Studio Code
|
|
12
|
+
The MusaLCE Server Suite system allows you to write Ruby code in your editor (Visual Studio Code) and have it executed in real-time, sending MIDI to tracks in your DAW. The typical workflow is:
|
|
13
13
|
|
|
14
|
-
1. Start the MusaLCE Server with your DAW choice
|
|
15
|
-
2. Open your
|
|
14
|
+
1. Start the MusaLCE Server Suite with/inside your DAW choice (Bitwig Studio or Ableton Live)
|
|
15
|
+
2. Open your VS Code editor with the MusaLCE extension (MusaLCEforVSCode)
|
|
16
16
|
3. Write and execute Musa-DSL code interactively
|
|
17
|
-
4. The code controls MIDI instruments in your DAW
|
|
17
|
+
4. The code controls MIDI instruments and transport in your DAW
|
|
18
18
|
|
|
19
19
|
## Requirements
|
|
20
20
|
|
|
@@ -25,7 +25,7 @@ The MusaLCE system allows you to write Ruby code in your editor (Visual Studio C
|
|
|
25
25
|
- **Ableton Live 11+** with [MusaLCE for Live](https://github.com/javier-sy/MusaLCEforLive) MIDI Remote Script
|
|
26
26
|
- A code editor with MusaLCE client extension:
|
|
27
27
|
- **Visual Studio Code** (recommended) with [MusaLCE Client for VSCode](https://github.com/javier-sy/MusaLCEClientForVSCode)
|
|
28
|
-
- Atom with [MusaLCE Client for Atom](https://github.com/javier-sy/MusaLCEClientForAtom) (Atom is discontinued)
|
|
28
|
+
- Atom with [MusaLCE Client for Atom](https://github.com/javier-sy/MusaLCEClientForAtom) (not recommended because Atom is discontinued)
|
|
29
29
|
|
|
30
30
|
## Installation
|
|
31
31
|
|
|
@@ -43,12 +43,12 @@ gem install musalce-server
|
|
|
43
43
|
|
|
44
44
|
## Quick Start
|
|
45
45
|
|
|
46
|
-
1. **Install the DAW controller extension** for your DAW (Bitwig
|
|
46
|
+
1. **Install the DAW controller extension** for your DAW (for Bitwig: [MusaLCE for Bitwig](https://github.com/javier-sy/MusaLCEforBitwig), for Ableton Live: [MusaLCE for Live](https://github.com/javier-sy/MusaLCEforLive))
|
|
47
47
|
2. **Install the VSCode extension** [MusaLCE Client for VSCode](https://github.com/javier-sy/MusaLCEClientForVSCode)
|
|
48
|
-
3. **Start your DAW** and ensure the MusaLCE controller is loaded
|
|
48
|
+
3. **Start your DAW** and ensure the MusaLCE controller is loaded and configured
|
|
49
49
|
4. **Start the server** (see below)
|
|
50
50
|
5. **Open VSCode** and create a `.rb` file
|
|
51
|
-
6. **Execute code** using the MusaLCE extension commands
|
|
51
|
+
6. **Execute code** using the MusaLCE extension commands (Ctrl+Alt+Return, Ctrl+Alt+M)
|
|
52
52
|
|
|
53
53
|
## Starting the Server
|
|
54
54
|
|
|
@@ -73,7 +73,7 @@ The server runs in the foreground and logs activity to the console. Use `Ctrl+C`
|
|
|
73
73
|
|
|
74
74
|
## Running Environment
|
|
75
75
|
|
|
76
|
-
A complete MusaLCE live coding session requires **three components running simultaneously**:
|
|
76
|
+
A complete MusaLCE Server Suite live coding session requires **three components running simultaneously**:
|
|
77
77
|
|
|
78
78
|
1. **Code Editor** (Visual Studio Code with MusaLCE extension)
|
|
79
79
|
- Where you write and execute Ruby/Musa-DSL code
|
|
@@ -133,10 +133,10 @@ The following commands are available in the REPL context (executed from your edi
|
|
|
133
133
|
```ruby
|
|
134
134
|
daw # Access the DAW controller object
|
|
135
135
|
daw.sequencer # Access the Musa-DSL sequencer
|
|
136
|
-
daw.clock # Access the MIDI clock
|
|
137
|
-
daw.transport # Access the transport
|
|
138
|
-
daw.tracks # Access all tracks
|
|
139
|
-
daw.surface # Access the control surface (Stream Deck
|
|
136
|
+
daw.clock # Access the Musa-DSL MIDI clock
|
|
137
|
+
daw.transport # Access the Musa-DSL transport
|
|
138
|
+
daw.tracks # Access all tracks on the daw by name
|
|
139
|
+
daw.surface # Access the control surface (currently elgato Stream Deck)
|
|
140
140
|
```
|
|
141
141
|
|
|
142
142
|
#### Persistent actions across DAW Stop/Play
|
|
@@ -181,7 +181,7 @@ bass.out.all_notes_off
|
|
|
181
181
|
|
|
182
182
|
### Transport Controls
|
|
183
183
|
|
|
184
|
-
Transport controls send commands to the DAW. **Only available for Bitwig Studio** (Live's
|
|
184
|
+
Transport controls send commands to the DAW. **Only available for Bitwig Studio** (Live's controller doesn't support transport control by now).
|
|
185
185
|
|
|
186
186
|
```ruby
|
|
187
187
|
daw.play # Start playback
|
|
@@ -260,18 +260,18 @@ daw.panic! # Send All Notes Off to all tracks
|
|
|
260
260
|
shutdown # Stop the server
|
|
261
261
|
```
|
|
262
262
|
|
|
263
|
-
###
|
|
263
|
+
### File Require
|
|
264
264
|
|
|
265
265
|
```ruby
|
|
266
|
-
#
|
|
267
|
-
|
|
266
|
+
# Require files relative to your editor's current file
|
|
267
|
+
require_relative 'my_patterns'
|
|
268
268
|
```
|
|
269
269
|
|
|
270
|
-
###
|
|
270
|
+
### Module Import
|
|
271
271
|
|
|
272
272
|
```ruby
|
|
273
|
-
#
|
|
274
|
-
|
|
273
|
+
# Import additional modules into the REPL context
|
|
274
|
+
import(MyHelperModule)
|
|
275
275
|
```
|
|
276
276
|
|
|
277
277
|
## DAW-Specific Notes
|
|
@@ -283,15 +283,15 @@ Requires [MusaLCE for Bitwig](https://github.com/javier-sy/MusaLCEforBitwig) con
|
|
|
283
283
|
- Full transport control support (play, stop, continue, goto, record)
|
|
284
284
|
- Track names must be unique
|
|
285
285
|
- MIDI clock sync from any controller marked as clock source
|
|
286
|
-
- Controllers and channels configured in the Bitwig extension
|
|
286
|
+
- Controllers and channels should be configured in the Bitwig extension
|
|
287
287
|
|
|
288
288
|
### Ableton Live
|
|
289
289
|
|
|
290
290
|
Requires [MusaLCE for Live](https://github.com/javier-sy/MusaLCEforLive) MIDI Remote Script.
|
|
291
291
|
|
|
292
|
-
- **No transport control**
|
|
292
|
+
- **No transport control** by now
|
|
293
293
|
- Multiple tracks can have the same name
|
|
294
|
-
- Use `daw.midi_sync('Device Name')` to set MIDI clock source
|
|
294
|
+
- Use `daw.midi_sync('MIDI Device Name')` to set MIDI clock source
|
|
295
295
|
- Track routing configured in Live's preferences
|
|
296
296
|
|
|
297
297
|
```ruby
|
|
@@ -307,20 +307,9 @@ daw.midi_sync('IAC Driver Bus 1')
|
|
|
307
307
|
| [MusaLCE Server](https://github.com/javier-sy/musalce-server) | Live coding server (this gem) |
|
|
308
308
|
| [MusaLCE for Bitwig](https://github.com/javier-sy/MusaLCEforBitwig) | Bitwig Studio controller extension |
|
|
309
309
|
| [MusaLCE for Live](https://github.com/javier-sy/MusaLCEforLive) | Ableton Live MIDI Remote Script |
|
|
310
|
-
| [MusaLCE Client for VSCode](https://github.com/javier-sy/MusaLCEClientForVSCode) | VSCode extension
|
|
310
|
+
| [MusaLCE Client for VSCode](https://github.com/javier-sy/MusaLCEClientForVSCode) | VSCode extension |
|
|
311
311
|
| [MusaLCE Client for Atom](https://github.com/javier-sy/MusaLCEClientForAtom) | Atom plugin (discontinued) |
|
|
312
312
|
|
|
313
|
-
## Documentation
|
|
314
|
-
|
|
315
|
-
API documentation is available via YARD:
|
|
316
|
-
|
|
317
|
-
```bash
|
|
318
|
-
bundle exec yard doc
|
|
319
|
-
bundle exec yard server
|
|
320
|
-
```
|
|
321
|
-
|
|
322
|
-
Then open http://localhost:8808 in your browser.
|
|
323
|
-
|
|
324
313
|
## Author
|
|
325
314
|
|
|
326
315
|
* [Javier Sánchez Yeste](https://github.com/javier-sy)
|
data/docs/architecture.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
# MusaLCE Suite Architecture
|
|
1
|
+
# MusaLCE Server Suite Architecture
|
|
2
2
|
|
|
3
|
-
This document is the canonical reference for the **suite
|
|
3
|
+
This document is the canonical reference for the **musalce-server suite** — running [musalce-server](https://github.com/javier-sy/musalce-server) together with the per-DAW extension to drive Bitwig Studio ([MusaLCEforBitwig](https://github.com/javier-sy/MusaLCEforBitwig)) or Ableton Live ([MusaLCEforLive](https://github.com/javier-sy/MusaLCEforLive)) from a code editor (VSCode + [MusaLCEClientForVSCode](https://github.com/javier-sy/MusaLCEClientForVSCode)) in real time, optionally with **elgato Stream Deck** integration via **Pulso** — [yeste.studio](https://yeste.studio)'s upcoming Stream Deck workflow system for DAWs.
|
|
4
4
|
|
|
5
|
-
It is a companion to (not a replacement for) the lower-level [musa-dsl REPL
|
|
5
|
+
It is a companion to (not a replacement for) the lower-level [musa-dsl REPL component](https://github.com/javier-sy/musa-dsl/blob/master/docs/subsystems/repl.md), which covers the **standalone REPL** workflow. The **musalce-server suite** documented here is **a specialization** of that case — `musalce-server` opens `Musa::REPL::REPL.new(binding)` after pre-building the sequencer, clock, transport, DAW handler and surface, so you don't have to. It also adds the connection to the DAW (Bitwig or Ableton Live) through **MusaLCEforBitwig**/**MusaLCEforLive** and exposes a `daw.*` object to access and to control the DAW from your editor.
|
|
6
6
|
|
|
7
7
|
## When to use this (vs the standalone REPL)
|
|
8
8
|
|
|
@@ -10,10 +10,10 @@ It is a companion to (not a replacement for) the lower-level [musa-dsl REPL subs
|
|
|
10
10
|
|---|---|
|
|
11
11
|
| Target is Bitwig Studio or Ableton Live | Target is SuperCollider, Max/MSP, OSC apps, custom hardware |
|
|
12
12
|
| You want `daw.*`, `surface[:event]` and DAW transport out of the box | You want full control over the wiring |
|
|
13
|
-
| You want Stream Deck
|
|
13
|
+
| You want a Stream Deck wired into your score via Pulso's MusaLCE Surface integration (Bitwig only today) | You're prototyping a personal live-coding DSL |
|
|
14
14
|
| Worked example: `_demo-13b-live-coding-suite` (planned) | Worked example: [`_demo-13-live-coding`](https://github.com/javier-sy/musadsl-demo) |
|
|
15
15
|
|
|
16
|
-
Both workflows use the same [MusaLCEClientForVSCode](https://github.com/javier-sy/MusaLCEClientForVSCode)
|
|
16
|
+
Both workflows use VS Code as editor and the same [MusaLCEClientForVSCode](https://github.com/javier-sy/MusaLCEClientForVSCode) editor extension. The editor extension connects to the server via TCP socket on port 1327.
|
|
17
17
|
|
|
18
18
|
## The big picture
|
|
19
19
|
|
|
@@ -21,25 +21,26 @@ Both workflows use the same [MusaLCEClientForVSCode](https://github.com/javier-s
|
|
|
21
21
|
┌────────────────────────────┐
|
|
22
22
|
│ Stream Deck plugin │
|
|
23
23
|
│ (Pulso Workflow .sdPlugin) │
|
|
24
|
-
|
|
24
|
+
└────────────────────────────┘
|
|
25
|
+
^
|
|
25
26
|
│ OSC over UDP (Pulso wire)
|
|
26
27
|
▼
|
|
27
|
-
┌────────────────────┐ TCP 1327 ┌──────────────────┐ ┌─────────────────────────┐
|
|
28
|
-
│ VSCode + │ ◀──────────▶ │ musalce-server │
|
|
29
|
-
│ MusaLCEClient │ (REPL) │ (Ruby gem) │ │ + Pulso Bridge relay │
|
|
28
|
+
┌────────────────────┐ TCP 1327 ┌──────────────────┐ ┌─────────────────────────┐ ┌──────────────────┐
|
|
29
|
+
│ VSCode + │ ◀──────────▶ │ musalce-server │ ◀────▶ │ MusaLCEforBitwig │ ◀────▶ │ Bitwig Studio │
|
|
30
|
+
│ MusaLCEClient │ (REPL) │ (Ruby gem) │ │ + Pulso Bridge relay │ └──────────────────┘
|
|
30
31
|
│ ForVSCode │ │ │ UDP └─────────────────────────┘
|
|
31
32
|
└────────────────────┘ │ • REPL │ OSC OR
|
|
32
33
|
│ • Sequencer │
|
|
33
|
-
│ • DAW handler │
|
|
34
|
+
│ • DAW handler │ ◀────▶ ┌─────────────────────────┐ ┌──────────────────┐
|
|
34
35
|
│ • Surface │ │ MusaLCEforLive │ ◀────▶ │ Ableton Live │
|
|
35
|
-
│ • MIDI out │ │ (Python) │
|
|
36
|
+
│ • MIDI out │ │ (Python) │ └──────────────────┘
|
|
36
37
|
└──────────────────┘ └─────────────────────────┘
|
|
37
38
|
```
|
|
38
39
|
|
|
39
40
|
Two parallel OSC contracts cross the server ↔ extension boundary:
|
|
40
41
|
|
|
41
42
|
- **Handler protocol** — `/musalce4bitwig/*` or `/musalce4live/*` plus a common `/hello`, `/version`, `/reload`. Carries DAW control (transport, track sync, channels). Documented [below](#osc-handler-protocol).
|
|
42
|
-
- **Surface protocol** — `/musalce/surface/*`. Carries Stream Deck control state (inventory, triggers, state propagation).
|
|
43
|
+
- **Surface protocol** — `/musalce/surface/*`. Carries elgato Stream Deck control state (inventory, triggers, state propagation). The canonical Pulso-side spec will be linked here once Pulso publishes.
|
|
43
44
|
|
|
44
45
|
## Component responsibilities
|
|
45
46
|
|
|
@@ -48,13 +49,13 @@ Two parallel OSC contracts cross the server ↔ extension boundary:
|
|
|
48
49
|
| **musa-dsl** | [musa-dsl](https://github.com/javier-sy/musa-dsl) | The composition framework: series, sequencer, neumas, transport, REPL primitive. | Ruby |
|
|
49
50
|
| **musalce-server** | [musalce-server](https://github.com/javier-sy/musalce-server) | Packages the REPL + sequencer + per-DAW handler + surface into a single command (`musalce-server bitwig\|live`). | Ruby |
|
|
50
51
|
| **MusaLCEforBitwig** | [MusaLCEforBitwig](https://github.com/javier-sy/MusaLCEforBitwig) | Bitwig controller extension; bridges Bitwig and musalce-server over OSC, includes the `MusaLCESurfaceRelay` for Pulso. | Java (Bitwig Extension API 18) |
|
|
51
|
-
| **MusaLCEforLive** | [MusaLCEforLive](https://github.com/javier-sy/MusaLCEforLive) | Ableton Live MIDI Remote Script; bridges Live and musalce-server over OSC.
|
|
52
|
+
| **MusaLCEforLive** | [MusaLCEforLive](https://github.com/javier-sy/MusaLCEforLive) | Ableton Live MIDI Remote Script; bridges Live and musalce-server over OSC. | Python |
|
|
52
53
|
| **MusaLCEClientForVSCode** | [MusaLCEClientForVSCode](https://github.com/javier-sy/MusaLCEClientForVSCode) | VSCode extension that is a REPL client over TCP/1327. | TypeScript |
|
|
53
|
-
| **Pulso Bridge** *(optional)* | [
|
|
54
|
+
| **Pulso Bridge** *(optional)* | *public release pending* | The DAW-side component of [yeste.studio](https://yeste.studio)'s upcoming Pulso, a Stream Deck workflow system for DAWs (Bitwig today; Ableton planned). Pulso's primary scope is generic DAW control (transport, tracks, devices, browser, parameter encoders); Pulso Bridge can also relay user actions and feedback data to/from the Stream Deck through the MusaLCE Surface protocol in MusaLCEforBitwig/Live — that's the integration described in this doc. | --- |
|
|
54
55
|
|
|
55
|
-
##
|
|
56
|
+
## Accessing the DAW (`daw.*`)
|
|
56
57
|
|
|
57
|
-
|
|
58
|
+
**musalce-server** exposes to the user access to the daw through a `daw.*` accessor. Quick reference:
|
|
58
59
|
|
|
59
60
|
| Accessor | Returns | What it's for |
|
|
60
61
|
|---|---|---|
|
|
@@ -67,58 +68,6 @@ The DSL context exposed in the REPL of the suite workflow extends what's availab
|
|
|
67
68
|
| `daw.play`, `daw.stop`, `daw.continue`, `daw.goto(bar)`, `daw.record` | — | Transport remote control. **Bitwig only** (Live API limitation). |
|
|
68
69
|
| `daw.panic!` | — | All-notes-off to every track |
|
|
69
70
|
|
|
70
|
-
## `surface[:event]` DSL — Stream Deck integration
|
|
71
|
-
|
|
72
|
-
A *Surface* control is named by an **event Symbol** that doubles as the identifier the sequencer uses when dispatching from a physical control. The surface is registered by the Pulso Bridge (via the inventory protocol — see [pulso/docs/osc-protocol.md](https://github.com/javier-sy/pulso/blob/main/docs/osc-protocol.md)); the server **owns the state** (message, enabled, value, range) and propagates changes outbound.
|
|
73
|
-
|
|
74
|
-
There are three control types: **Toggle**, **Trigger** and **Encoder**.
|
|
75
|
-
|
|
76
|
-
### Trigger — momentary
|
|
77
|
-
|
|
78
|
-
```ruby
|
|
79
|
-
# In score code:
|
|
80
|
-
surface[:launch_chorus].set(message: "Chorus")
|
|
81
|
-
|
|
82
|
-
on :launch_chorus do |payload|
|
|
83
|
-
puts "Stream Deck button fired (#{payload.inspect})"
|
|
84
|
-
# ... schedule the chorus section ...
|
|
85
|
-
end
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
A Trigger has no persistent state beyond an optional `message`. Pressing the Stream Deck button reaches the `on :launch_chorus do |payload| … end` handler through the sequencer's event dispatch.
|
|
89
|
-
|
|
90
|
-
### Toggle — three-state (Action / Ready / Idle)
|
|
91
|
-
|
|
92
|
-
```ruby
|
|
93
|
-
surface[:mode].set(message: "Verse", enabled: true)
|
|
94
|
-
|
|
95
|
-
on :mode do |payload|
|
|
96
|
-
if surface[:mode].enabled
|
|
97
|
-
surface[:mode].enabled = false
|
|
98
|
-
# ... toggle off behaviour ...
|
|
99
|
-
else
|
|
100
|
-
surface[:mode].enabled = true
|
|
101
|
-
# ... toggle on behaviour ...
|
|
102
|
-
end
|
|
103
|
-
end
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
`enabled` accepts `true` / `false` / `:inactive` — Pulso paints the three states with distinct palettes (Action / Ready / Idle).
|
|
107
|
-
|
|
108
|
-
### Encoder — integer with range
|
|
109
|
-
|
|
110
|
-
```ruby
|
|
111
|
-
surface[:tempo].set(value: 120, range: [60, 200], message: "BPM")
|
|
112
|
-
|
|
113
|
-
on :tempo do |payload|
|
|
114
|
-
new_value = payload[:value].to_i
|
|
115
|
-
surface[:tempo].value = new_value
|
|
116
|
-
# ... apply tempo change ...
|
|
117
|
-
end
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
The encoder owns its `value` (an integer) and its `range` (min, max integers). State propagates back to the Stream Deck plugin so the key/dial repaints.
|
|
121
|
-
|
|
122
71
|
## Stop/Play semantics
|
|
123
72
|
|
|
124
73
|
The server registers exactly one built-in callback on the transport:
|
|
@@ -145,11 +94,9 @@ What survives a Stop/Play cycle:
|
|
|
145
94
|
| `surface[:event]` **handler blocks** (`on :event do … end`) | ❌ (wiped with `@event_handlers`) |
|
|
146
95
|
| `at`, `every`, `play`, `move` | ❌ |
|
|
147
96
|
|
|
148
|
-
**Asymmetry warning**: the Stream Deck button keeps painting after a Stop, but pressing it dispatches to a handler that is no longer registered — silence.
|
|
149
|
-
|
|
150
97
|
### Rehydration pattern
|
|
151
98
|
|
|
152
|
-
Use `daw.transport.on_start`
|
|
99
|
+
Use `daw.transport.on_start` to re-install handlers and schedules on every Play:
|
|
153
100
|
|
|
154
101
|
```ruby
|
|
155
102
|
daw.transport.on_start do
|
|
@@ -157,7 +104,17 @@ daw.transport.on_start do
|
|
|
157
104
|
end
|
|
158
105
|
```
|
|
159
106
|
|
|
160
|
-
`on_start` callbacks accumulate (append-only list), so you can register more from the REPL at any time. Use `before_begin` for callbacks that should run **only on the first Start of the session**, and `after_stop` for cleanup (e.g. `voices.panic`).
|
|
107
|
+
`on_start` callbacks accumulate (it's an append-only list), so you can register more from the REPL at any time. Use `before_begin` for callbacks that should run **only on the first Start of the session**, and `after_stop` for cleanup (e.g. `voices.panic`).
|
|
108
|
+
|
|
109
|
+
## Accessing the Stream Deck (`on :event` and `surface[:event]`)
|
|
110
|
+
|
|
111
|
+
In Stream Deck Pulso Workflow plugin the user has several kinds of buttons and encoders that can trigger events on the user MusaDSL code (as MusaDSL Sequencer Events with parameters). This allows the user to control the behaviour of his MusaDSL code in realtime using an elgato Stream Deck device.
|
|
112
|
+
|
|
113
|
+
The buttons and encoders are identified with a `event` name. This `event` name is the one launched on the `musalce-server` **Sequencer** and the one the user can subscribe from his code with `on :event |parameters| do ... end` commands.
|
|
114
|
+
|
|
115
|
+
Also, the user can update the visible content on the buttons and encoders on the Stream Deck device using the `surface[:event].set parameter: value, parameter: value` commands.
|
|
116
|
+
|
|
117
|
+
Pulso Bridge is aware of MusaLCEforBitwig/Live through a pair of configurable OSC ports and both coordinate the bidirectional communication between Stream Deck and MusaDSL code in the user session.
|
|
161
118
|
|
|
162
119
|
## OSC handler protocol
|
|
163
120
|
|
|
@@ -202,41 +159,20 @@ Both ports are **hardcoded** on the server side (`musalce-server/lib/daw.rb`). T
|
|
|
202
159
|
| ext → server | `/musalce4live/track/audio` | bulk (sliced 3) | Audio track metadata. |
|
|
203
160
|
| ext → server | `/musalce4live/track/routings` | bulk (sliced 5) | Routing metadata. |
|
|
204
161
|
|
|
205
|
-
|
|
162
|
+
## MusaLCE Surface protocol — elgato Stream Deck via Pulso's MusaLCE integration (Bitwig only)
|
|
206
163
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
## Surface protocol — Stream Deck via Pulso (Bitwig only)
|
|
210
|
-
|
|
211
|
-
The protocol carrying surface inventory, triggers and state between musalce-server, MusaLCEforBitwig (`MusaLCESurfaceRelay`) and the Pulso Bridge is documented end-to-end in [pulso/docs/osc-protocol.md → MusaLCE surface relay](https://github.com/javier-sy/pulso/blob/main/docs/osc-protocol.md#musalce-surface-relay).
|
|
212
|
-
|
|
213
|
-
Quick summary of address space:
|
|
164
|
+
The MusaLCE Surface protocol carries surface inventory, triggers and state between **musalce-server**, **MusaLCEforBitwig** and **Pulso Bridge**.
|
|
214
165
|
|
|
215
166
|
- `/musalce/surface/inventory/{begin,add,remove,end}` — surface inventory (Pulso → server)
|
|
216
167
|
- `/musalce/surface/trigger event payload` — Pulso → server, dispatched to `on :event` via `@sequencer.launch`
|
|
217
168
|
- `/musalce/surface/state/{message,enabled,value,range} event …` — server → Pulso, repaints the Stream Deck
|
|
218
169
|
- `/musalce/surface/sync_request`, `/musalce/surface/state_request` — handshake messages
|
|
219
170
|
|
|
220
|
-
In the suite the relay is implemented on the Bitwig side only (`MusaLCEforBitwig/.../MusaLCESurfaceRelay.java`). **There is no Live-side relay yet** — Stream Deck integration is Bitwig-only at the time of writing.
|
|
221
|
-
|
|
222
|
-
## Current versions
|
|
223
|
-
|
|
224
|
-
| Component | Version |
|
|
225
|
-
|---|---|
|
|
226
|
-
| musa-dsl | 0.42.7+ |
|
|
227
|
-
| musalce-server | 0.7.2 |
|
|
228
|
-
| MusaLCEforBitwig | from `git describe` (typically `0.x`) |
|
|
229
|
-
| MusaLCEforLive | (no semver published) |
|
|
230
|
-
| MusaLCEClientForVSCode | 0.1.0 |
|
|
231
|
-
| Pulso Bridge | 0.x (see pulso/docs/osc-protocol.md changelog) |
|
|
232
|
-
| Pulso Workflow (Stream Deck plugin) | matches Bridge |
|
|
233
|
-
|
|
234
|
-
Stay on the same release branch across components — pin musalce-server in your `Gemfile.lock`, build the matching `.bwextension`/Remote Script from the same point in time. There's no semantic compatibility matrix today; protocol changes are coordinated across components by commit (see e.g. the simultaneous `id → event` rename in musalce-server `346fe51` ↔ pulso `0c6536f` ↔ MusaLCEforBitwig `33e4d7c`).
|
|
235
|
-
|
|
236
171
|
## Where to go next
|
|
237
172
|
|
|
238
173
|
- Reference the **standalone REPL** workflow: [musa-dsl/docs/subsystems/repl.md](https://github.com/javier-sy/musa-dsl/blob/master/docs/subsystems/repl.md).
|
|
239
174
|
- Reference the **REPL commands** (`daw.*`, transport controls, sequencer DSL) of the suite: [musalce-server README](https://github.com/javier-sy/musalce-server#readme).
|
|
240
175
|
- Configure the **DAW extensions**: [MusaLCEforBitwig README](https://github.com/javier-sy/MusaLCEforBitwig#readme), [MusaLCEforLive README](https://github.com/javier-sy/MusaLCEforLive#readme).
|
|
241
176
|
- Wire the **VSCode editor**: [MusaLCEClientForVSCode README](https://github.com/javier-sy/MusaLCEClientForVSCode#readme).
|
|
242
|
-
- Wire the **Stream Deck** (Bitwig only):
|
|
177
|
+
- Wire the **Stream Deck** (Bitwig only): pending Pulso's public release.
|
|
178
|
+
|
data/lib/midi-devices.rb
CHANGED
|
@@ -32,18 +32,28 @@ module MusaLCEServer
|
|
|
32
32
|
#
|
|
33
33
|
# @return [void]
|
|
34
34
|
def sync
|
|
35
|
-
|
|
35
|
+
# Without this, MIDICommunications answers from the list it built the
|
|
36
|
+
# first time it was asked, and nothing plugged in since would ever be
|
|
37
|
+
# seen -- which made the sentence above false.
|
|
38
|
+
MIDICommunications::Loader.refresh
|
|
39
|
+
|
|
40
|
+
missing = @low_level_devices.keys
|
|
36
41
|
|
|
37
42
|
MIDICommunications::Output.all.each do |low_level_device|
|
|
38
|
-
|
|
43
|
+
name = low_level_device.name
|
|
44
|
+
|
|
45
|
+
# Outside the guard below, deliberately: seeing a device is what marks
|
|
46
|
+
# it as still connected, whether or not it is one we already had.
|
|
47
|
+
missing.delete name
|
|
48
|
+
|
|
49
|
+
next if @low_level_devices.key?(name)
|
|
39
50
|
|
|
40
|
-
@low_level_devices[
|
|
41
|
-
names.delete low_level_device.name
|
|
51
|
+
@low_level_devices[name] = MIDIDevice.new(@sequencer, low_level_device)
|
|
42
52
|
end
|
|
43
53
|
|
|
44
54
|
# remove disconnected devices
|
|
45
55
|
#
|
|
46
|
-
|
|
56
|
+
missing.each do |name|
|
|
47
57
|
@low_level_devices.delete name
|
|
48
58
|
end
|
|
49
59
|
end
|
data/lib/version.rb
CHANGED
data/musalce-server.gemspec
CHANGED
|
@@ -3,7 +3,7 @@ require_relative 'lib/version'
|
|
|
3
3
|
Gem::Specification.new do |s|
|
|
4
4
|
s.name = 'musalce-server'
|
|
5
5
|
s.version = MusaLCEServer::VERSION
|
|
6
|
-
s.date = '2026-
|
|
6
|
+
s.date = '2026-09-06'
|
|
7
7
|
s.summary = 'A Musa DSL live coding environment for Ableton Live 11 and Bitwig Studio 5'
|
|
8
8
|
s.description = 'This package implements the Server part of the Musa DSL Live Coding Environment for Ableton Live and Bitwig Studio'
|
|
9
9
|
s.authors = ['Javier Sánchez Yeste']
|
|
@@ -23,7 +23,7 @@ Gem::Specification.new do |s|
|
|
|
23
23
|
|
|
24
24
|
s.add_runtime_dependency 'musa-dsl', '~> 0.40'
|
|
25
25
|
|
|
26
|
-
s.add_runtime_dependency 'midi-communications', '~> 0.7'
|
|
26
|
+
s.add_runtime_dependency 'midi-communications', '~> 0.7', '>= 0.7.1'
|
|
27
27
|
s.add_runtime_dependency 'midi-events', '~> 0.7'
|
|
28
28
|
s.add_runtime_dependency 'midi-parser', '~> 0.5'
|
|
29
29
|
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: musalce-server
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.8.
|
|
4
|
+
version: 0.8.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Javier Sánchez Yeste
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-
|
|
10
|
+
date: 2026-09-06 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: musa-dsl
|
|
@@ -30,6 +30,9 @@ dependencies:
|
|
|
30
30
|
- - "~>"
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
32
|
version: '0.7'
|
|
33
|
+
- - ">="
|
|
34
|
+
- !ruby/object:Gem::Version
|
|
35
|
+
version: 0.7.1
|
|
33
36
|
type: :runtime
|
|
34
37
|
prerelease: false
|
|
35
38
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -37,6 +40,9 @@ dependencies:
|
|
|
37
40
|
- - "~>"
|
|
38
41
|
- !ruby/object:Gem::Version
|
|
39
42
|
version: '0.7'
|
|
43
|
+
- - ">="
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: 0.7.1
|
|
40
46
|
- !ruby/object:Gem::Dependency
|
|
41
47
|
name: midi-events
|
|
42
48
|
requirement: !ruby/object:Gem::Requirement
|