Softube Console1 add surface (libs)

This commit is contained in:
Hoger Dehnhardt 2023-05-07 16:21:37 +02:00 committed by Robin Gareus
parent 63e0ac11ad
commit 1dc879eb8d
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
13 changed files with 3334 additions and 0 deletions

View File

@ -48,6 +48,7 @@ namespace PBD {
LIBARDOUR_API extern DebugBits CC121;
LIBARDOUR_API extern DebugBits CaptureAlignment;
LIBARDOUR_API extern DebugBits ChanMapping;
LIBARDOUR_API extern DebugBits Console1;
LIBARDOUR_API extern DebugBits ContourDesignControl;
LIBARDOUR_API extern DebugBits ControlProtocols;
LIBARDOUR_API extern DebugBits CycleTimers;

View File

@ -43,6 +43,7 @@ PBD::DebugBits PBD::DEBUG::Butler = PBD::new_debug_bit ("Butler");
PBD::DebugBits PBD::DEBUG::CC121 = PBD::new_debug_bit ("cc121");
PBD::DebugBits PBD::DEBUG::CaptureAlignment = PBD::new_debug_bit ("capturealignment");
PBD::DebugBits PBD::DEBUG::ChanMapping = PBD::new_debug_bit ("chanmapping");
PBD::DebugBits PBD::DEBUG::Console1 = PBD::new_debug_bit ("console1");
PBD::DebugBits PBD::DEBUG::ContourDesignControl = PBD::new_debug_bit ("contourdesigncontrol");
PBD::DebugBits PBD::DEBUG::ControlProtocols = PBD::new_debug_bit ("controlprotocols");
PBD::DebugBits PBD::DEBUG::CycleTimers = PBD::new_debug_bit ("cycletimers");

View File

@ -699,6 +699,8 @@ ARDOUR::init (bool try_optimization, const char* localedir, bool with_gui)
reserved_io_names[_("FaderPort8 Send")] = false;
reserved_io_names[_("FaderPort16 Recv")] = false;
reserved_io_names[_("FaderPort16 Send")] = false;
reserved_io_names[_("Console1 Recv")] = false;
reserved_io_names[_("Console1 Send")] = false;
MIDI::Name::MidiPatchManager::instance ().load_midnams_in_thread ();

View File

@ -1477,6 +1477,7 @@ PortManager::port_is_control_only (std::string const& name)
X_(".*US-2400 .*"),
X_(".*Mackie .*"),
X_(".*MIDI Control .*"),
X_(".*Console1 .*"),
};
pattern = "(";

View File

@ -0,0 +1,181 @@
#ifndef ardour_surface_console1_button_h
#define ardour_surface_console1_button_h
#include "ardour/debug.h"
#include "console1.h"
namespace ArdourSurface {
using namespace PBD;
using ControllerID = Console1::ControllerID;
class Controller
{
public:
enum ControllerType
{
CONTROLLER,
CONTROLLER_BUTTON,
MULTISTATE_BUTTON,
ENCODER,
METER
};
Controller (Console1& console1, ControllerID id)
: console1 (console1)
, _id (id)
{
}
virtual ~Controller () {}
Console1& console1;
ControllerID id () const { return _id; }
virtual ControllerType get_type () { return CONTROLLER; }
protected:
ControllerID _id;
};
class ControllerButton : public Controller
{
public:
ControllerButton (Console1& console1,
ControllerID id,
boost::function<void (uint32_t)> action,
boost::function<void (uint32_t)> shift_action = 0)
: Controller (console1, id)
, action (action)
, shift_action (shift_action)
{
console1.buttons.insert (std::make_pair (id, *this));
}
ControllerType get_type () { return CONTROLLER_BUTTON; }
virtual void set_led_state (bool onoff)
{
// DEBUG_TRACE(DEBUG::Console1, "ControllerButton::set_led_state ...\n");
MIDI::byte buf[3];
buf[0] = 0xB0;
buf[1] = _id;
buf[2] = onoff ? 127 : 0;
console1.write (buf, 3);
}
virtual void set_led_value (uint32_t val)
{
// DEBUG_TRACE(DEBUG::Console1, "ControllerButton::set_led_state ...\n");
MIDI::byte buf[3];
buf[0] = 0xB0;
buf[1] = _id;
buf[2] = val;
console1.write (buf, 3);
}
boost::function<void (uint32_t)> action;
boost::function<void (uint32_t)> shift_action;
};
class MultiStateButton : public Controller
{
public:
MultiStateButton (Console1& console1,
ControllerID id,
std::vector<uint32_t> state_values,
boost::function<void (uint32_t)> action,
boost::function<void (uint32_t)> shift_action = 0)
: Controller (console1, id)
, action (action)
, shift_action (shift_action)
, state_values (state_values)
{
console1.multi_buttons.insert (std::make_pair (id, *this));
}
ControllerType get_type () { return MULTISTATE_BUTTON; }
virtual void set_led_state (uint32_t state)
{
if (state >= state_values.size ())
return;
MIDI::byte buf[3];
buf[0] = 0xB0;
buf[1] = _id;
buf[2] = state_values[state];
console1.write (buf, 3);
}
uint32_t state_count () { return state_values.size (); }
boost::function<void (uint32_t)> action;
boost::function<void (uint32_t)> shift_action;
private:
std::vector<uint32_t> state_values;
};
class Meter : public Controller
{
public:
Meter (Console1& console1,
ControllerID id,
boost::function<void ()> action,
boost::function<void ()> shift_action = 0)
: Controller (console1, id)
, action (action)
, shift_action (shift_action)
{
console1.meters.insert (std::make_pair (id, *this));
}
ControllerType get_type () { return METER; }
virtual void set_value (uint32_t value)
{
MIDI::byte buf[3];
buf[0] = 0xB0;
buf[1] = _id;
buf[2] = value;
console1.write (buf, 3);
}
boost::function<void ()> action;
boost::function<void ()> shift_action;
};
class Encoder : public Controller
{
public:
Encoder (Console1& console1,
ControllerID id,
boost::function<void (uint32_t)> action,
boost::function<void (uint32_t)> shift_action = 0)
: Controller (console1, id)
, action (action)
, shift_action (shift_action)
{
console1.encoders.insert (std::make_pair (id, *this));
}
ControllerType get_type () { return ENCODER; }
virtual void set_value (uint32_t value)
{
MIDI::byte buf[3];
buf[0] = 0xB0;
buf[1] = _id;
buf[2] = value;
console1.write (buf, 3);
}
boost::function<void (uint32_t)> action;
boost::function<void (uint32_t val)> shift_action;
};
}
#endif // ardour_surface_console1_button_h

View File

@ -0,0 +1,270 @@
/*
* Copyright (C) 2023 Holger Dehnhardt <holger@dehnhardt.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <gtkmm/alignment.h>
#include <gtkmm/label.h>
#include <gtkmm/liststore.h>
#include "pbd/unwind.h"
#include "pbd/strsplit.h"
#include "pbd/file_utils.h"
#include "gtkmm2ext/bindings.h"
#include "gtkmm2ext/gui_thread.h"
#include "gtkmm2ext/utils.h"
#include "ardour/audioengine.h"
#include "ardour/filesystem_paths.h"
#include "ardour/parameter_descriptor.h"
#include "ardour/debug.h"
#include "console1.h"
#include "c1_gui.h"
#include "pbd/i18n.h"
using namespace PBD;
using namespace ARDOUR;
using namespace ArdourSurface;
using namespace std;
using namespace Gtk;
using namespace Gtkmm2ext;
void*
Console1::get_gui () const
{
if (!gui) {
const_cast<Console1*>(this)->build_gui ();
}
static_cast<Gtk::VBox*>(gui)->show_all();
return gui;
}
void
Console1::tear_down_gui ()
{
if (gui) {
Gtk::Widget *w = static_cast<Gtk::VBox*>(gui)->get_parent();
if (w) {
w->hide();
delete w;
}
}
delete gui;
gui = 0;
}
void
Console1::build_gui ()
{
gui = new C1GUI (*this);
}
/*--------------------*/
C1GUI::C1GUI (Console1& p)
: c1 (p)
, table (2, 5)
, action_table (5, 4)
, ignore_active_change (false)
{
set_border_width (12);
table.set_row_spacings (4);
table.set_col_spacings (6);
table.set_border_width (12);
table.set_homogeneous (false);
std::string data_file_path;
string name = "console1.png";
Searchpath spath(ARDOUR::ardour_data_search_path());
spath.add_subdirectory_to_paths ("icons");
find_file (spath, name, data_file_path);
if (!data_file_path.empty()) {
image.set (data_file_path);
hpacker.pack_start (image, false, false);
}
Gtk::Label* l;
Gtk::Alignment* align;
int row = 0;
input_combo.pack_start (midi_port_columns.short_name);
output_combo.pack_start (midi_port_columns.short_name);
input_combo.signal_changed().connect (sigc::bind (sigc::mem_fun (*this, &C1GUI::active_port_changed), &input_combo, true));
output_combo.signal_changed().connect (sigc::bind (sigc::mem_fun (*this, &C1GUI::active_port_changed), &output_combo, false));
l = manage (new Gtk::Label);
l->set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Incoming MIDI on:")));
l->set_alignment (1.0, 0.5);
table.attach (*l, 0, 1, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
table.attach (input_combo, 1, 2, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
row++;
l = manage (new Gtk::Label);
l->set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Outgoing MIDI on:")));
l->set_alignment (1.0, 0.5);
table.attach (*l, 0, 1, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
table.attach (output_combo, 1, 2, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
row++;
hpacker.pack_start (table, true, true);
set_spacing (12);
pack_start (hpacker, false, false);
/* update the port connection combos */
update_port_combos ();
/* catch future changes to connection state */
ARDOUR::AudioEngine::instance()->PortRegisteredOrUnregistered.connect (_port_connections, invalidator (*this), boost::bind (&C1GUI::connection_handler, this), gui_context());
ARDOUR::AudioEngine::instance()->PortPrettyNameChanged.connect (_port_connections, invalidator (*this), boost::bind (&C1GUI::connection_handler, this), gui_context());
c1.ConnectionChange.connect (_port_connections, invalidator (*this), boost::bind (&C1GUI::connection_handler, this), gui_context());
}
C1GUI::~C1GUI ()
{
}
void
C1GUI::connection_handler ()
{
/* ignore all changes to combobox active strings here, because we're
updating them to match a new ("external") reality - we were called
because port connections have changed.
*/
PBD::Unwinder<bool> ici (ignore_active_change, true);
update_port_combos ();
}
void
C1GUI::update_port_combos ()
{
vector<string> midi_inputs;
vector<string> midi_outputs;
ARDOUR::AudioEngine::instance()->get_ports ("", ARDOUR::DataType::MIDI, ARDOUR::PortFlags (ARDOUR::IsOutput|ARDOUR::IsTerminal), midi_inputs);
ARDOUR::AudioEngine::instance()->get_ports ("", ARDOUR::DataType::MIDI, ARDOUR::PortFlags (ARDOUR::IsInput|ARDOUR::IsTerminal), midi_outputs);
Glib::RefPtr<Gtk::ListStore> input = build_midi_port_list (midi_inputs, true);
Glib::RefPtr<Gtk::ListStore> output = build_midi_port_list (midi_outputs, false);
bool input_found = false;
bool output_found = false;
int n;
input_combo.set_model (input);
output_combo.set_model (output);
Gtk::TreeModel::Children children = input->children();
Gtk::TreeModel::Children::iterator i;
i = children.begin();
++i; /* skip "Disconnected" */
for (n = 1; i != children.end(); ++i, ++n) {
string port_name = (*i)[midi_port_columns.full_name];
if (c1.input_port()->connected_to (port_name)) {
input_combo.set_active (n);
input_found = true;
break;
}
}
if (!input_found) {
input_combo.set_active (0); /* disconnected */
}
children = output->children();
i = children.begin();
++i; /* skip "Disconnected" */
for (n = 1; i != children.end(); ++i, ++n) {
string port_name = (*i)[midi_port_columns.full_name];
if (c1.output_port()->connected_to (port_name)) {
output_combo.set_active (n);
output_found = true;
break;
}
}
if (!output_found) {
output_combo.set_active (0); /* disconnected */
}
}
Glib::RefPtr<Gtk::ListStore>
C1GUI::build_midi_port_list (vector<string> const & ports, bool for_input)
{
Glib::RefPtr<Gtk::ListStore> store = ListStore::create (midi_port_columns);
TreeModel::Row row;
row = *store->append ();
row[midi_port_columns.full_name] = string();
row[midi_port_columns.short_name] = _("Disconnected");
for (vector<string>::const_iterator p = ports.begin(); p != ports.end(); ++p) {
row = *store->append ();
row[midi_port_columns.full_name] = *p;
std::string pn = ARDOUR::AudioEngine::instance()->get_pretty_name_by_name (*p);
if (pn.empty ()) {
pn = (*p).substr ((*p).find (':') + 1);
}
row[midi_port_columns.short_name] = pn;
}
return store;
}
void
C1GUI::active_port_changed (Gtk::ComboBox* combo, bool for_input)
{
if (ignore_active_change) {
return;
}
TreeModel::iterator active = combo->get_active ();
string new_port = (*active)[midi_port_columns.full_name];
if (new_port.empty()) {
if (for_input) {
c1.input_port()->disconnect_all ();
} else {
c1.output_port()->disconnect_all ();
}
return;
}
if (for_input) {
if (!c1.input_port()->connected_to (new_port)) {
c1.input_port()->disconnect_all ();
c1.input_port()->connect (new_port);
}
} else {
if (!c1.output_port()->connected_to (new_port)) {
c1.output_port()->disconnect_all ();
c1.output_port()->connect (new_port);
}
}
}

View File

@ -0,0 +1,84 @@
/*
* Copyright (C) 2023 Holger Dehnhardt <holger@dehnhardt.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __ardour_console1_gui_h__
#define __ardour_console1_gui_h__
#include <vector>
#include <string>
#include <gtkmm/box.h>
#include <gtkmm/combobox.h>
#include <gtkmm/image.h>
#include <gtkmm/table.h>
#include <gtkmm/treestore.h>
#include <gtkmm/spinbutton.h>
#include <gtkmm/notebook.h>
namespace Gtk {
class CellRendererCombo;
class ListStore;
}
#include "ardour/mode.h"
#include "console1.h"
namespace ArdourSurface {
class C1GUI : public Gtk::VBox
{
public:
C1GUI (Console1&);
~C1GUI ();
private:
Console1& c1;
PBD::ScopedConnectionList lcxl_connections;
Gtk::VBox hpacker;
Gtk::Table table;
Gtk::Table action_table;
Gtk::ComboBox input_combo;
Gtk::ComboBox output_combo;
Gtk::Image image;
void update_port_combos ();
PBD::ScopedConnection connection_change_connection;
void connection_handler ();
PBD::ScopedConnectionList _port_connections;
struct MidiPortColumns : public Gtk::TreeModel::ColumnRecord {
MidiPortColumns() {
add (short_name);
add (full_name);
}
Gtk::TreeModelColumn<std::string> short_name;
Gtk::TreeModelColumn<std::string> full_name;
};
MidiPortColumns midi_port_columns;
bool ignore_active_change;
Glib::RefPtr<Gtk::ListStore> build_midi_port_list (std::vector<std::string> const & ports, bool for_input);
void active_port_changed (Gtk::ComboBox*,bool for_input);
};
}
#endif /* __ardour_console1_gui_h__ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,468 @@
/*
* Copyright (C) 2023 Holger Dehnhardt <holger@dehnhardt.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef ardour_surface_console1_h
#define ardour_surface_console1_h
#include <list>
#include <map>
#include <set>
#include <glibmm/threads.h>
#define ABSTRACT_UI_EXPORTS
#include <midi++/types.h>
#include "glibmm/main.h"
#include "pbd/abstract_ui.h"
#include "pbd/controllable.h"
#include "ardour/presentation_info.h"
#include "ardour/readonly_control.h"
#include "ardour/types.h"
#include "control_protocol/control_protocol.h"
#include "gdk/gdkevents.h"
#include "midi_surface/midi_byte_array.h"
#include "midi_surface/midi_surface.h"
namespace MIDI {
class Parser;
class Port;
}
namespace ARDOUR {
class AsyncMIDIPort;
class Bundle;
class Port;
class Session;
class MidiPort;
}
namespace PBD {
class Controllable;
}
class MIDIControllable;
class MIDIFunction;
class MIDIAction;
namespace ArdourSurface {
class C1GUI;
class Controller;
class ControllerButton;
class MultiStateButton;
class Meter;
class Encoder;
using Controllable = std::shared_ptr<PBD::Controllable>;
using order_t = ARDOUR::PresentationInfo::order_t;
class ControlNotFoundException : public std::exception
{
public:
ControlNotFoundException () {}
virtual ~ControlNotFoundException () {}
};
class Console1 : public MIDISurface
{
friend Controller;
friend ControllerButton;
friend MultiStateButton;
friend Meter;
friend Encoder;
public:
Console1 (ARDOUR::Session&);
virtual ~Console1 ();
int set_active (bool yn);
bool has_editor () const { return true; }
void* get_gui () const;
void tear_down_gui () override;
std::string input_port_name () const override;
std::string output_port_name () const override;
/*XMLNode& get_state () const;
int set_state (const XMLNode&, int version);*/
PBD::Signal0<void> ConnectionChange;
/* Timer Events */
PBD::Signal1<void, bool> BlinkIt;
PBD::Signal0<void> Periodic;
/* Local Signals */
PBD::Signal0<void> BankChange;
PBD::Signal1<void, bool> ShiftChange;
enum ControllerID
{
CONTROLLER_NONE = 0,
VOLUME = 7,
PAN = 10,
MUTE = 12,
SOLO = 13,
ORDER = 14,
DRIVE = 15,
EXTERNAL_SIDECHAIN = 17,
CHARACTER = 18,
FOCUS1 = 21,
FOCUS2,
FOCUS3,
FOCUS4,
FOCUS5,
FOCUS6,
FOCUS7,
FOCUS8,
FOCUS9,
FOCUS10,
FOCUS11,
FOCUS12,
FOCUS13,
FOCUS14,
FOCUS15,
FOCUS16,
FOCUS17,
FOCUS18,
FOCUS19,
FOCUS20 = 40,
COMP = 46,
COMP_THRESH = 47,
COMP_RELEASE = 48,
COMP_RATIO = 49,
COMP_PAR = 50,
COMP_ATTACK = 51,
SHAPE = 53,
SHAPE_GATE = 54,
SHAPE_SUSTAIN = 55,
SHAPE_RELEASE = 56,
SHAPE_PUNCH = 57,
PRESET = 58,
HARD_GATE = 59,
FILTER_TO_COMPRESSORS = 61,
HIGH_SHAPE = 65,
EQ = 80,
HIGH_GAIN = 82,
HIGH_FREQ = 83,
HIGH_MID_GAIN = 85,
HIGH_MID_FREQ = 86,
HIGH_MID_SHAPE = 87,
LOW_MID_GAIN = 88,
LOW_MID_FREQ = 89,
LOW_MID_SHAPE = 90,
LOW_GAIN = 91,
LOW_FREQ = 92,
LOW_SHAPE = 93,
PAGE_UP = 96,
PAGE_DOWN = 97,
DISPLAY_ON = 102,
LOW_CUT = 103,
MODE = 104,
HIGH_CUT = 105,
GAIN = 107,
PHASE_INV = 108,
INPUT_METER_L = 110,
INPUT_METER_R = 111,
OUTPUT_METER_L = 112,
OUTPUT_METER_R = 113,
SHAPE_METER = 114,
COMP_METER = 115,
TRACK_COPY = 120,
TRACK_GROUP = 123,
};
private:
/* GUI */
mutable C1GUI* gui;
void build_gui ();
/* Configuration */
const uint32_t bank_size = 20;
bool shift_state = false;
bool rolling = false;
uint32_t current_bank = 0;
uint32_t current_strippable_index = 0;
std::shared_ptr<ARDOUR::AutomationControl> current_pan_control = nullptr;
std::shared_ptr<ARDOUR::Stripable> _current_stripable;
std::weak_ptr<ARDOUR::Stripable> pre_master_stripable;
std::weak_ptr<ARDOUR::Stripable> pre_monitor_stripable;
void setup_controls ();
bool strip_recenabled = false;
ARDOUR::MonitorState monitor_state = ARDOUR::MonitorState::MonitoringSilence;
int begin_using_device ();
int stop_using_device ();
int device_acquire () { return 0; }
void device_release () {}
void connect_session_signals ();
void connect_internal_signals ();
/* MIDI-Message handler - we only have controller messages */
void handle_midi_controller_message (MIDI::Parser&, MIDI::EventTwoBytes* tb);
void tabbed_window_state_event_handler (GdkEventWindowState* ev, void* object);
/* Strip inventory */
typedef std::map<uint32_t, order_t> StripInventoryMap;
StripInventoryMap strip_inventory;
void create_strip_invetory ();
order_t get_inventory_order_by_index (const uint32_t index);
uint32_t get_index_by_inventory_order (order_t order);
void select_rid_by_index (const uint32_t index);
/* Controller Maps*/
typedef std::map<ControllerID, ArdourSurface::ControllerButton> ButtonMap;
typedef std::map<ControllerID, ArdourSurface::MultiStateButton> MultiStateButtonMap;
typedef std::map<ControllerID, ArdourSurface::Meter> MeterMap;
typedef std::map<ControllerID, ArdourSurface::Encoder> EncoderMap;
ButtonMap buttons;
ControllerButton& get_button (ControllerID) const;
MultiStateButtonMap multi_buttons;
MultiStateButton& get_mbutton (ControllerID id) const;
MeterMap meters;
Meter& get_meter (ControllerID) const;
EncoderMap encoders;
Encoder& get_encoder (ControllerID) const;
typedef std::map<uint32_t, ControllerID> SendControllerMap;
SendControllerMap send_controllers{ { 0, LOW_FREQ }, { 1, LOW_MID_FREQ }, { 2, HIGH_MID_FREQ },
{ 3, HIGH_FREQ }, { 4, LOW_GAIN }, { 5, LOW_MID_GAIN },
{ 6, HIGH_MID_GAIN }, { 7, HIGH_GAIN }, { 8, LOW_MID_SHAPE },
{ 9, HIGH_MID_SHAPE }, { 10, LOW_MID_SHAPE }, { 11, HIGH_MID_SHAPE } };
ControllerID get_send_controllerid (uint32_t);
/* */
void all_lights_out ();
void notify_transport_state_changed () override;
void notify_solo_active_changed (bool) override;
sigc::connection periodic_connection;
bool periodic ();
void periodic_update_meter ();
// Meter Handlig
uint32_t last_output_meter_l = 0;
uint32_t last_output_meter_r = 0;
std::shared_ptr<ARDOUR::ReadOnlyControl> gate_redux_meter = 0;
uint32_t last_gate_meter = 0;
std::shared_ptr<ARDOUR::ReadOnlyControl> comp_redux_meter = 0;
uint32_t last_comp_redux = 0;
sigc::connection blink_connection;
typedef std::list<ControllerID> Blinkers;
Blinkers blinkers;
bool blink_state;
bool blinker ();
void start_blinking (ControllerID);
void stop_blinking (ControllerID);
void set_current_stripable (std::shared_ptr<ARDOUR::Stripable>);
void drop_current_stripable ();
/*void use_master ();
void use_monitor ();*/
void stripable_selection_changed ();
/*PBD::ScopedConnection selection_connection;*/
PBD::ScopedConnectionList stripable_connections;
PBD::ScopedConnectionList console1_connections;
void map_stripable_state ();
void notify_parameter_changed (std::string);
/* operations (defined in c1_operations.cc) */
void bank (bool up);
void drive (uint32_t value);
void gain (const uint32_t value);
void mute (const uint32_t);
void pan (const uint32_t value);
void phase (const uint32_t);
void rude_solo (const uint32_t);
void select (const uint32_t i);
void shift (const uint32_t);
void solo (const uint32_t);
void trim (const uint32_t value);
void window (const uint32_t value);
void zoom (const uint32_t value);
// Filter Section
void filter (const uint32_t value);
void low_cut (const uint32_t value);
void high_cut (const uint32_t value);
// Gate Section
void gate (const uint32_t value);
void gate_scf (const uint32_t value);
void gate_listen (const uint32_t value);
void gate_thresh (const uint32_t value);
void gate_depth (const uint32_t value);
void gate_release (const uint32_t value);
void gate_attack (const uint32_t value);
void gate_hyst (const uint32_t value);
void gate_hold (const uint32_t value);
void gate_filter_freq (const uint32_t value);
// EQ section
void eq (const uint32_t);
void eq_freq (const uint32_t band, uint32_t value);
void eq_gain (const uint32_t band, uint32_t value);
void eq_high_shape (const uint32_t value);
void eq_low_shape (const uint32_t value);
ControllerID eq_freq_controller_for_band (const uint32_t band)
{
ControllerID eq_freq_id;
switch (band) {
case 0:
eq_freq_id = ControllerID::LOW_FREQ;
break;
case 1:
eq_freq_id = ControllerID::LOW_MID_FREQ;
break;
case 2:
eq_freq_id = ControllerID::HIGH_MID_FREQ;
break;
case 3:
eq_freq_id = ControllerID::HIGH_FREQ;
break;
}
return eq_freq_id;
}
ControllerID eq_gain_controller_for_band (const uint32_t band)
{
ControllerID eq_gain_id;
switch (band) {
case 0:
eq_gain_id = ControllerID::LOW_GAIN;
break;
case 1:
eq_gain_id = ControllerID::LOW_MID_GAIN;
break;
case 2:
eq_gain_id = ControllerID::HIGH_MID_GAIN;
break;
case 3:
eq_gain_id = ControllerID::HIGH_GAIN;
break;
}
return eq_gain_id;
}
// Mixbus sends
void mb_send_level (const uint32_t n, const uint32_t value);
// Comp Section
void comp (const uint32_t value);
void comp_mode (const uint32_t value);
void comp_thresh (const uint32_t value);
void comp_attack (const uint32_t value);
void comp_release (const uint32_t value);
void comp_ratio (const uint32_t value);
void comp_makeup (const uint32_t value);
void comp_emph (const uint32_t value);
bool map_encoder (ControllerID controllerID);
void map_encoder (ControllerID controllerID, std::shared_ptr<ARDOUR::AutomationControl> control);
void map_bank ();
void map_drive ();
void map_gain ();
void map_monitoring ();
void map_mute ();
void map_pan ();
void map_phase ();
void map_recenable ();
void map_select ();
void map_shift (bool shift);
void map_solo ();
void map_trim ();
// Filter Section
void map_filter ();
void map_low_cut ();
void map_high_cut ();
// Gate Section
void map_gate ();
void map_gate_scf ();
void map_gate_listen ();
void map_gate_thresh ();
void map_gate_depth ();
void map_gate_release ();
void map_gate_attack ();
void map_gate_hyst ();
void map_gate_hold ();
void map_gate_filter_freq ();
// EQ section
void map_eq ();
void map_eq_freq (const uint32_t band);
void map_eq_gain (const uint32_t band);
void map_eq_low_shape ();
void map_eq_high_shape ();
// MB Sends
void map_mb_send_level (const uint32_t n);
// Comp Section
void map_comp ();
void map_comp_mode ();
void map_comp_thresh ();
void map_comp_attack ();
void map_comp_release ();
void map_comp_ratio ();
void map_comp_makeup ();
void map_comp_emph ();
bool rec_enable_state;
float calculate_meter (float dB);
uint32_t control_to_midi (Controllable controllable, float val, uint32_t max_value_for_type = 127);
float midi_to_control (Controllable controllable, uint32_t val, uint32_t max_value_for_type = 127);
};
}
#endif /* ardour_surface_console1_h */

View File

@ -0,0 +1,61 @@
/*
* Copyright (C) 2023 Holger Dehnhardt <holger@dehnhardt.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <pbd/failed_constructor.h>
#include "control_protocol/control_protocol.h"
#include "console1.h"
using namespace ARDOUR;
using namespace ArdourSurface;
static ControlProtocol*
new_console1 (Session* s)
{
Console1* console1 = 0;
try {
console1 = new Console1 (*s);
} catch (failed_constructor& err) {
delete console1;
console1 = 0;
return 0;
}
return console1;
}
static void
delete_console1 (ControlProtocol* cp)
{
delete cp;
}
static ControlProtocolDescriptor console1_descriptor = {
/* name : */ "Softube Console1",
/* id : */ "uri://ardour.org/surfaces/console1:0",
/* module : */ 0,
/* available */ 0,
/* probe port : */ 0,
/* match usb */ 0,
/* initialize : */ new_console1,
/* destroy : */ delete_console1,
};
extern "C" ARDOURSURFACE_API ControlProtocolDescriptor* protocol_descriptor () { return &console1_descriptor; }

View File

@ -0,0 +1,33 @@
#!/usr/bin/env python
from waflib.extras import autowaf as autowaf
import os
# Mandatory variables
top = '.'
out = 'build'
def options(opt):
autowaf.set_options(opt)
def configure(conf):
pass
def build(bld):
obj = bld(features = 'cxx cxxshlib')
obj.source = '''
console1_interface.cc
console1.cc
c1_operations.cc
c1_gui.cc
'''
obj.defines = [ 'PACKAGE="ardour_console1"' ]
obj.defines += [ 'ARDOURSURFACE_DLL_EXPORTS' ]
obj.includes = [ '.', './console1', './midi_surface/midi_surface']
obj.name = 'libardour_console1'
obj.target = 'ardour_console1'
obj.uselib = 'GTKMM GTK GDK XML OSX'
obj.use = 'libardour libardour_cp libardour_midisurface libcanvas libgtkmm2ext libpbd'
obj.install_path = os.path.join(bld.env['LIBDIR'], 'surfaces')
def shutdown():
autowaf.shutdown()

View File

@ -28,6 +28,7 @@ children = [
'us2400',
'launch_control_xl',
'osc',
'console1'
]
def options(opt):
@ -87,6 +88,7 @@ def build(bld):
bld.recurse('us2400')
bld.recurse('launch_control_xl')
bld.recurse('osc')
bld.recurse('console1')
if bld.is_defined('BUILD_WIIMOTE'):
bld.recurse('wiimote')