Softube Console1 add surface (libs)
This commit is contained in:
parent
63e0ac11ad
commit
1dc879eb8d
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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 ();
|
||||
|
||||
|
|
|
@ -1477,6 +1477,7 @@ PortManager::port_is_control_only (std::string const& name)
|
|||
X_(".*US-2400 .*"),
|
||||
X_(".*Mackie .*"),
|
||||
X_(".*MIDI Control .*"),
|
||||
X_(".*Console1 .*"),
|
||||
};
|
||||
|
||||
pattern = "(";
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
@ -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 */
|
|
@ -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; }
|
||||
|
|
@ -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()
|
|
@ -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')
|
||||
|
|
Loading…
Reference in New Issue