WS: properly support MIDI strips
This commit is contained in:
parent
dd833c89b9
commit
9ee828b47b
@ -65,7 +65,7 @@ WebsocketsDispatcher::update_all_nodes (Client client)
|
|||||||
|
|
||||||
ValueVector strip_desc = ValueVector ();
|
ValueVector strip_desc = ValueVector ();
|
||||||
strip_desc.push_back (strip.name ());
|
strip_desc.push_back (strip.name ());
|
||||||
strip_desc.push_back (strip.has_pan ());
|
strip_desc.push_back ((int)strip.stripable ()->presentation_info ().flags ());
|
||||||
|
|
||||||
update (client, Node::strip_description, strip_addr, strip_desc);
|
update (client, Node::strip_description, strip_addr, strip_desc);
|
||||||
|
|
||||||
|
@ -219,12 +219,12 @@ void
|
|||||||
ArdourFeedback::observe_strip_plugins (uint32_t strip_id, ArdourMixerStrip::PluginMap& plugins)
|
ArdourFeedback::observe_strip_plugins (uint32_t strip_id, ArdourMixerStrip::PluginMap& plugins)
|
||||||
{
|
{
|
||||||
for (ArdourMixerStrip::PluginMap::iterator it = plugins.begin(); it != plugins.end(); ++it) {
|
for (ArdourMixerStrip::PluginMap::iterator it = plugins.begin(); it != plugins.end(); ++it) {
|
||||||
uint32_t plugin_id = it->first;
|
uint32_t plugin_id = it->first;
|
||||||
boost::shared_ptr<ArdourMixerPlugin> plugin = it->second;
|
boost::shared_ptr<ArdourMixerPlugin> plugin = it->second;
|
||||||
boost::shared_ptr<PluginInsert> insert = plugin->insert ();
|
boost::shared_ptr<PluginInsert> insert = plugin->insert ();
|
||||||
uint32_t bypass = insert->plugin ()->designated_bypass_port ();
|
uint32_t bypass = insert->plugin ()->designated_bypass_port ();
|
||||||
Evoral::Parameter param = Evoral::Parameter (PluginAutomation, 0, bypass);
|
Evoral::Parameter param = Evoral::Parameter (PluginAutomation, 0, bypass);
|
||||||
boost::shared_ptr<AutomationControl> control = insert->automation_control (param);
|
boost::shared_ptr<AutomationControl> control = insert->automation_control (param);
|
||||||
|
|
||||||
if (control) {
|
if (control) {
|
||||||
control->Changed.connect (*plugin, MISSING_INVALIDATOR,
|
control->Changed.connect (*plugin, MISSING_INVALIDATOR,
|
||||||
|
@ -174,13 +174,15 @@ ArdourMixerStrip::plugins ()
|
|||||||
double
|
double
|
||||||
ArdourMixerStrip::gain () const
|
ArdourMixerStrip::gain () const
|
||||||
{
|
{
|
||||||
return to_db (_stripable->gain_control ()->get_value ());
|
double val = _stripable->gain_control ()->get_value ();
|
||||||
|
return is_midi () ? static_cast<double> (to_velocity (val)) : to_db (val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ArdourMixerStrip::set_gain (double db)
|
ArdourMixerStrip::set_gain (double gain)
|
||||||
{
|
{
|
||||||
_stripable->gain_control ()->set_value (from_db (db), PBD::Controllable::NoGroup);
|
double val = is_midi () ? from_velocity (static_cast<int> (gain)) : from_db (gain);
|
||||||
|
_stripable->gain_control ()->set_value (val, PBD::Controllable::NoGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -238,6 +240,12 @@ ArdourMixerStrip::name () const
|
|||||||
return _stripable->name ();
|
return _stripable->name ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ArdourMixerStrip::is_midi () const
|
||||||
|
{
|
||||||
|
return _stripable->presentation_info ().flags () & PresentationInfo::Flag::MidiTrack;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ArdourMixerStrip::on_drop_plugin (uint32_t plugin_id)
|
ArdourMixerStrip::on_drop_plugin (uint32_t plugin_id)
|
||||||
{
|
{
|
||||||
@ -267,6 +275,18 @@ ArdourMixerStrip::from_db (double db)
|
|||||||
|
|
||||||
return static_cast<double> (k);
|
return static_cast<double> (k);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ArdourMixerStrip::to_velocity (double k)
|
||||||
|
{
|
||||||
|
return static_cast<int> (127.0 * k / 2.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
ArdourMixerStrip::from_velocity (int k)
|
||||||
|
{
|
||||||
|
return 2.0 * static_cast<double> (k) / 127.0;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ArdourMixer::start ()
|
ArdourMixer::start ()
|
||||||
|
@ -48,8 +48,7 @@ public:
|
|||||||
ArdourMixerPlugin (boost::shared_ptr<ARDOUR::PluginInsert>);
|
ArdourMixerPlugin (boost::shared_ptr<ARDOUR::PluginInsert>);
|
||||||
~ArdourMixerPlugin ();
|
~ArdourMixerPlugin ();
|
||||||
|
|
||||||
boost::shared_ptr<ARDOUR::PluginInsert> insert () const;
|
boost::shared_ptr<ARDOUR::PluginInsert> insert () const;
|
||||||
boost::shared_ptr<PBD::ScopedConnectionList> connections () const;
|
|
||||||
|
|
||||||
bool enabled () const;
|
bool enabled () const;
|
||||||
void set_enabled (bool);
|
void set_enabled (bool);
|
||||||
@ -63,7 +62,7 @@ public:
|
|||||||
static TypedValue param_value (boost::shared_ptr<ARDOUR::AutomationControl>);
|
static TypedValue param_value (boost::shared_ptr<ARDOUR::AutomationControl>);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
boost::shared_ptr<ARDOUR::PluginInsert> _insert;
|
boost::shared_ptr<ARDOUR::PluginInsert> _insert;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ArdourMixerStrip : public PBD::ScopedConnectionList
|
class ArdourMixerStrip : public PBD::ScopedConnectionList
|
||||||
@ -72,8 +71,7 @@ public:
|
|||||||
ArdourMixerStrip (boost::shared_ptr<ARDOUR::Stripable>, PBD::EventLoop*);
|
ArdourMixerStrip (boost::shared_ptr<ARDOUR::Stripable>, PBD::EventLoop*);
|
||||||
~ArdourMixerStrip ();
|
~ArdourMixerStrip ();
|
||||||
|
|
||||||
boost::shared_ptr<ARDOUR::Stripable> stripable () const;
|
boost::shared_ptr<ARDOUR::Stripable> stripable () const;
|
||||||
boost::shared_ptr<PBD::ScopedConnectionList> connections () const;
|
|
||||||
|
|
||||||
typedef std::map<uint32_t, boost::shared_ptr<ArdourMixerPlugin> > PluginMap;
|
typedef std::map<uint32_t, boost::shared_ptr<ArdourMixerPlugin> > PluginMap;
|
||||||
|
|
||||||
@ -97,11 +95,16 @@ public:
|
|||||||
static double to_db (double);
|
static double to_db (double);
|
||||||
static double from_db (double);
|
static double from_db (double);
|
||||||
|
|
||||||
|
static int to_velocity (double);
|
||||||
|
static double from_velocity (int);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
boost::shared_ptr<ARDOUR::Stripable> _stripable;
|
boost::shared_ptr<ARDOUR::Stripable> _stripable;
|
||||||
|
|
||||||
PluginMap _plugins;
|
PluginMap _plugins;
|
||||||
|
|
||||||
|
bool is_midi () const;
|
||||||
|
|
||||||
void on_drop_plugin (uint32_t);
|
void on_drop_plugin (uint32_t);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -19,7 +19,8 @@
|
|||||||
import ArdourClient from '/shared/ardour.js';
|
import ArdourClient from '/shared/ardour.js';
|
||||||
import { createRootContainer, Container, Dialog, Label, Button, Toggle,
|
import { createRootContainer, Container, Dialog, Label, Button, Toggle,
|
||||||
DiscreteKnob, LinearKnob, LogKnob, PanKnob,
|
DiscreteKnob, LinearKnob, LogKnob, PanKnob,
|
||||||
StripGainFader, StripMeter } from './tkwidget.js';
|
AudioStripGainFader, MidiStripGainFader,
|
||||||
|
AudioStripMeter, MidiStripMeter } from './tkwidget.js';
|
||||||
|
|
||||||
(() => {
|
(() => {
|
||||||
|
|
||||||
@ -95,6 +96,10 @@ import { createRootContainer, Container, Dialog, Label, Button, Toggle,
|
|||||||
plugins.callback = () => openPlugins (strip);
|
plugins.callback = () => openPlugins (strip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (strip.isMidi || strip.isVca) {
|
||||||
|
plugins.element.style.visibility = 'hidden';
|
||||||
|
}
|
||||||
|
|
||||||
const pan = new PanKnob();
|
const pan = new PanKnob();
|
||||||
pan.appendTo(container);
|
pan.appendTo(container);
|
||||||
|
|
||||||
@ -114,11 +119,11 @@ import { createRootContainer, Container, Dialog, Label, Button, Toggle,
|
|||||||
meterFader.classList.add('strip-meter-fader');
|
meterFader.classList.add('strip-meter-fader');
|
||||||
meterFader.appendTo(container);
|
meterFader.appendTo(container);
|
||||||
|
|
||||||
const gain = new StripGainFader();
|
const gain = strip.isMidi ? new MidiStripGainFader : new AudioStripGainFader();
|
||||||
gain.appendTo(meterFader);
|
gain.appendTo(meterFader);
|
||||||
gain.bindTo(strip, 'gain');
|
gain.bindTo(strip, 'gain');
|
||||||
|
|
||||||
const meter = new StripMeter();
|
const meter = strip.isMidi ? new MidiStripMeter() : new AudioStripMeter();
|
||||||
meter.appendTo(meterFader);
|
meter.appendTo(meterFader);
|
||||||
meter.bindTo(strip, 'meter');
|
meter.bindTo(strip, 'meter');
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ export async function createRootContainer () {
|
|||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Widget extends BaseWidget {
|
class TkWidget extends BaseWidget {
|
||||||
|
|
||||||
constructor (tk) {
|
constructor (tk) {
|
||||||
super();
|
super();
|
||||||
@ -40,19 +40,7 @@ class Widget extends BaseWidget {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Label extends Widget {
|
class TkControl extends BaseControl {
|
||||||
|
|
||||||
constructor () {
|
|
||||||
super(new TK.Label());
|
|
||||||
}
|
|
||||||
|
|
||||||
set text (text) {
|
|
||||||
this.tk.set('label', text);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class Control extends BaseControl {
|
|
||||||
|
|
||||||
constructor (tk) {
|
constructor (tk) {
|
||||||
super();
|
super();
|
||||||
@ -65,7 +53,7 @@ class Control extends BaseControl {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class RangeControl extends Control {
|
class TkRangeControl extends TkControl {
|
||||||
|
|
||||||
constructor (tk) {
|
constructor (tk) {
|
||||||
super(tk);
|
super(tk);
|
||||||
@ -91,7 +79,7 @@ class RangeControl extends Control {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Knob extends RangeControl {
|
class TkKnob extends TkRangeControl {
|
||||||
|
|
||||||
constructor (options) {
|
constructor (options) {
|
||||||
super(new TK.Knob(options));
|
super(new TK.Knob(options));
|
||||||
@ -99,6 +87,38 @@ class Knob extends RangeControl {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TkFader extends TkRangeControl {
|
||||||
|
|
||||||
|
constructor (options) {
|
||||||
|
super(new TK.Fader(options));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class TkMeter extends TkRangeControl {
|
||||||
|
|
||||||
|
constructor (options) {
|
||||||
|
super(new TK.LevelMeter(options));
|
||||||
|
}
|
||||||
|
|
||||||
|
set value (val) {
|
||||||
|
this.tk.set('value', val);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Label extends TkWidget {
|
||||||
|
|
||||||
|
constructor () {
|
||||||
|
super(new TK.Label());
|
||||||
|
}
|
||||||
|
|
||||||
|
set text (text) {
|
||||||
|
this.tk.set('label', text);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
export class Container extends BaseContainer {
|
export class Container extends BaseContainer {
|
||||||
|
|
||||||
constructor () {
|
constructor () {
|
||||||
@ -161,7 +181,7 @@ export class Dialog extends BaseDialog {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Button extends Control {
|
export class Button extends TkControl {
|
||||||
|
|
||||||
constructor () {
|
constructor () {
|
||||||
super(new TK.Button());
|
super(new TK.Button());
|
||||||
@ -180,7 +200,7 @@ export class Button extends Control {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Toggle extends Control {
|
export class Toggle extends TkControl {
|
||||||
|
|
||||||
constructor () {
|
constructor () {
|
||||||
super(new TK.Toggle());
|
super(new TK.Toggle());
|
||||||
@ -207,36 +227,59 @@ export class Toggle extends Control {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class StripGainFader extends RangeControl {
|
export class AudioStripGainFader extends TkFader {
|
||||||
|
|
||||||
constructor () {
|
constructor () {
|
||||||
super(new TK.Fader({
|
super({
|
||||||
scale: 'decibel',
|
scale: 'decibel',
|
||||||
|
labels: TK.FORMAT("%d"),
|
||||||
min: -58.0,
|
min: -58.0,
|
||||||
max: 6.0
|
max: 6.0
|
||||||
}));
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class StripMeter extends RangeControl {
|
export class MidiStripGainFader extends TkFader {
|
||||||
|
|
||||||
constructor () {
|
constructor () {
|
||||||
super(new TK.LevelMeter({
|
super({
|
||||||
|
scale: 'linear',
|
||||||
|
labels: TK.FORMAT("%d"),
|
||||||
|
min: 0,
|
||||||
|
max: 127
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export class AudioStripMeter extends TkMeter {
|
||||||
|
|
||||||
|
constructor () {
|
||||||
|
super({
|
||||||
show_scale: false,
|
show_scale: false,
|
||||||
scale: 'decibel',
|
scale: 'decibel',
|
||||||
min: -58.0,
|
min: -58.0,
|
||||||
max: 6.0
|
max: 6.0
|
||||||
}));
|
});
|
||||||
}
|
|
||||||
|
|
||||||
set value (val) {
|
|
||||||
this.tk.set('value', val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class LinearKnob extends Knob {
|
export class MidiStripMeter extends TkMeter {
|
||||||
|
|
||||||
|
constructor () {
|
||||||
|
super({
|
||||||
|
show_scale: false,
|
||||||
|
scale: 'linear',
|
||||||
|
min: 0,
|
||||||
|
max: 127
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export class LinearKnob extends TkKnob {
|
||||||
|
|
||||||
constructor (min, max) {
|
constructor (min, max) {
|
||||||
super({
|
super({
|
||||||
@ -252,7 +295,7 @@ export class LinearKnob extends Knob {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class LogKnob extends Knob {
|
export class LogKnob extends TkKnob {
|
||||||
|
|
||||||
constructor (min, max) {
|
constructor (min, max) {
|
||||||
super({
|
super({
|
||||||
@ -268,7 +311,7 @@ export class LogKnob extends Knob {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DiscreteKnob extends Knob {
|
export class DiscreteKnob extends TkKnob {
|
||||||
|
|
||||||
constructor (min, max, step) {
|
constructor (min, max, step) {
|
||||||
super({
|
super({
|
||||||
@ -285,7 +328,7 @@ export class DiscreteKnob extends Knob {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PanKnob extends Knob {
|
export class PanKnob extends TkKnob {
|
||||||
|
|
||||||
constructor () {
|
constructor () {
|
||||||
super({
|
super({
|
||||||
|
@ -12,6 +12,7 @@ body {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
overflow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
div {
|
div {
|
||||||
|
@ -27,13 +27,25 @@ const NodeToProperty = Object.freeze({
|
|||||||
[StateNode.STRIP_MUTE] : 'mute'
|
[StateNode.STRIP_MUTE] : 'mute'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// from presentation_info.h
|
||||||
|
const StripFlags = Object.freeze({
|
||||||
|
AUDIO_TRACK: 0x1,
|
||||||
|
MIDI_TRACK: 0x2,
|
||||||
|
AUDIO_BUS: 0x4,
|
||||||
|
MIDI_BUS: 0x8,
|
||||||
|
VCA: 0x10,
|
||||||
|
MASTER_OUT: 0x20,
|
||||||
|
MONITOR_OUT: 0x40,
|
||||||
|
AUDITIONER: 0x80
|
||||||
|
});
|
||||||
|
|
||||||
export default class Strip extends AddressableComponent {
|
export default class Strip extends AddressableComponent {
|
||||||
|
|
||||||
constructor (parent, addr, desc) {
|
constructor (parent, addr, desc) {
|
||||||
super(parent, addr);
|
super(parent, addr);
|
||||||
this._plugins = {};
|
this._plugins = {};
|
||||||
this._name = desc[0];
|
this._name = desc[0];
|
||||||
this._hasPan = desc[1];
|
this._flags = desc[1];
|
||||||
this._meter = 0;
|
this._meter = 0;
|
||||||
this._gain = 0;
|
this._gain = 0;
|
||||||
this._pan = 0;
|
this._pan = 0;
|
||||||
@ -48,8 +60,8 @@ export default class Strip extends AddressableComponent {
|
|||||||
return this._name;
|
return this._name;
|
||||||
}
|
}
|
||||||
|
|
||||||
get hasPan () {
|
get flags () {
|
||||||
return this._hasPan;
|
return this._flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
get meter () {
|
get meter () {
|
||||||
@ -64,6 +76,10 @@ export default class Strip extends AddressableComponent {
|
|||||||
this.updateRemote('gain', db, StateNode.STRIP_GAIN);
|
this.updateRemote('gain', db, StateNode.STRIP_GAIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get hasPan () {
|
||||||
|
return !this.isMidi && !this.isVca;
|
||||||
|
}
|
||||||
|
|
||||||
get pan () {
|
get pan () {
|
||||||
return this._pan;
|
return this._pan;
|
||||||
}
|
}
|
||||||
@ -80,6 +96,18 @@ export default class Strip extends AddressableComponent {
|
|||||||
this.updateRemote('mute', value, StateNode.STRIP_MUTE);
|
this.updateRemote('mute', value, StateNode.STRIP_MUTE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get isAudio () {
|
||||||
|
return this._flags & StripFlags.AUDIO_TRACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
get isMidi () {
|
||||||
|
return this._flags & StripFlags.MIDI_TRACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
get isVca () {
|
||||||
|
return this._flags & StripFlags.VCA;
|
||||||
|
}
|
||||||
|
|
||||||
handle (node, addr, val) {
|
handle (node, addr, val) {
|
||||||
if (node.startsWith('strip_plugin')) {
|
if (node.startsWith('strip_plugin')) {
|
||||||
if (node == StateNode.STRIP_PLUGIN_DESCRIPTION) {
|
if (node == StateNode.STRIP_PLUGIN_DESCRIPTION) {
|
||||||
|
Loading…
Reference in New Issue
Block a user