13
0

WS: properly support MIDI strips

This commit is contained in:
Luciano Iam 2020-09-05 13:12:04 +02:00 committed by Robin Gareus
parent dd833c89b9
commit 9ee828b47b
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
8 changed files with 154 additions and 54 deletions

View File

@ -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);

View File

@ -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,

View File

@ -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 ()

View File

@ -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);
}; };

View File

@ -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');

View File

@ -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({

View File

@ -12,6 +12,7 @@ body {
width: 100%; width: 100%;
position: fixed; position: fixed;
margin: 0; margin: 0;
overflow: none;
} }
div { div {

View File

@ -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) {