mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-19 05:06:31 +01:00
restore excess calls to sync-order stuff (for now); allow MIDI controllers to use the same non-linear fader response as the gui; add various flags to PBD::Controllable and remove URI from that class
git-svn-id: svn://localhost/ardour2/branches/3.0@6414 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
8a17b0fb90
commit
74933f5865
22 changed files with 179 additions and 129 deletions
|
|
@ -3400,7 +3400,7 @@ ARDOUR_UI::store_clock_modes ()
|
||||||
|
|
||||||
|
|
||||||
ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
|
ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
|
||||||
: Controllable (name, string() /* missing URI */), ui (u), type(tp)
|
: Controllable (name), ui (u), type(tp)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -892,6 +892,8 @@ EditorRoutes::move_selected_tracks (bool up)
|
||||||
}
|
}
|
||||||
|
|
||||||
_model->reorder (neworder);
|
_model->reorder (neworder);
|
||||||
|
|
||||||
|
_session->sync_order_keys (N_ ("editor"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@
|
||||||
#include "ardour/session.h"
|
#include "ardour/session.h"
|
||||||
#include "ardour/session_route.h"
|
#include "ardour/session_route.h"
|
||||||
#include "ardour/dB.h"
|
#include "ardour/dB.h"
|
||||||
|
#include "ardour/utils.h"
|
||||||
|
|
||||||
#include <gtkmm/style.h>
|
#include <gtkmm/style.h>
|
||||||
#include <gdkmm/color.h>
|
#include <gdkmm/color.h>
|
||||||
|
|
@ -40,11 +41,11 @@
|
||||||
|
|
||||||
#include "ardour_ui.h"
|
#include "ardour_ui.h"
|
||||||
#include "gain_meter.h"
|
#include "gain_meter.h"
|
||||||
#include "utils.h"
|
|
||||||
#include "logmeter.h"
|
#include "logmeter.h"
|
||||||
#include "gui_thread.h"
|
#include "gui_thread.h"
|
||||||
#include "keyboard.h"
|
#include "keyboard.h"
|
||||||
#include "public_editor.h"
|
#include "public_editor.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
#include "ardour/session.h"
|
#include "ardour/session.h"
|
||||||
#include "ardour/route.h"
|
#include "ardour/route.h"
|
||||||
|
|
|
||||||
|
|
@ -689,9 +689,7 @@ void
|
||||||
Mixer_UI::track_list_reorder (const TreeModel::Path&, const TreeModel::iterator&, int* /*new_order*/)
|
Mixer_UI::track_list_reorder (const TreeModel::Path&, const TreeModel::iterator&, int* /*new_order*/)
|
||||||
{
|
{
|
||||||
strip_redisplay_does_not_sync_order_keys = true;
|
strip_redisplay_does_not_sync_order_keys = true;
|
||||||
if (!strip_redisplay_does_not_reset_order_keys) {
|
_session->set_remote_control_ids();
|
||||||
_session->set_remote_control_ids();
|
|
||||||
}
|
|
||||||
redisplay_track_list ();
|
redisplay_track_list ();
|
||||||
strip_redisplay_does_not_sync_order_keys = false;
|
strip_redisplay_does_not_sync_order_keys = false;
|
||||||
}
|
}
|
||||||
|
|
@ -701,6 +699,7 @@ Mixer_UI::track_list_change (const Gtk::TreeModel::Path&, const Gtk::TreeModel::
|
||||||
{
|
{
|
||||||
// never reset order keys because of a property change
|
// never reset order keys because of a property change
|
||||||
strip_redisplay_does_not_reset_order_keys = true;
|
strip_redisplay_does_not_reset_order_keys = true;
|
||||||
|
_session->set_remote_control_ids();
|
||||||
redisplay_track_list ();
|
redisplay_track_list ();
|
||||||
strip_redisplay_does_not_reset_order_keys = false;
|
strip_redisplay_does_not_reset_order_keys = false;
|
||||||
}
|
}
|
||||||
|
|
@ -710,6 +709,7 @@ Mixer_UI::track_list_delete (const Gtk::TreeModel::Path&)
|
||||||
{
|
{
|
||||||
/* this could require an order sync */
|
/* this could require an order sync */
|
||||||
if (_session && !_session->deletion_in_progress()) {
|
if (_session && !_session->deletion_in_progress()) {
|
||||||
|
_session->set_remote_control_ids();
|
||||||
redisplay_track_list ();
|
redisplay_track_list ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,22 +37,6 @@ namespace Gtk {
|
||||||
class Paned;
|
class Paned;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline double
|
|
||||||
gain_to_slider_position (ARDOUR::gain_t g)
|
|
||||||
{
|
|
||||||
if (g == 0) return 0;
|
|
||||||
return pow((6.0*log(g)/log(2.0)+192.0)/198.0, 8.0);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline ARDOUR::gain_t
|
|
||||||
slider_position_to_gain (double pos)
|
|
||||||
{
|
|
||||||
/* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
|
|
||||||
if (pos == 0.0) return 0;
|
|
||||||
return pow (2.0,(sqrt(sqrt(sqrt(pos)))*198.0-192.0)/6.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
Glib::ustring fit_to_pixels (const Glib::ustring&, int pixel_width, Pango::FontDescription& font, int& actual_width, bool with_ellipses = false);
|
Glib::ustring fit_to_pixels (const Glib::ustring&, int pixel_width, Pango::FontDescription& font, int& actual_width, bool with_ellipses = false);
|
||||||
|
|
||||||
std::pair<std::string, double> fit_to_pixels (cairo_t *, std::string, double);
|
std::pair<std::string, double> fit_to_pixels (cairo_t *, std::string, double);
|
||||||
|
|
|
||||||
|
|
@ -73,8 +73,9 @@ public:
|
||||||
GainControl (std::string name, Session& session, Amp* a, const Evoral::Parameter ¶m,
|
GainControl (std::string name, Session& session, Amp* a, const Evoral::Parameter ¶m,
|
||||||
boost::shared_ptr<AutomationList> al = boost::shared_ptr<AutomationList>() )
|
boost::shared_ptr<AutomationList> al = boost::shared_ptr<AutomationList>() )
|
||||||
: AutomationControl (session, param, al, name)
|
: AutomationControl (session, param, al, name)
|
||||||
, _amp (a)
|
, _amp (a) {
|
||||||
{}
|
set_flags (Controllable::Flag (flags() | Controllable::GainLike));
|
||||||
|
}
|
||||||
|
|
||||||
void set_value (float val);
|
void set_value (float val);
|
||||||
float get_value (void) const;
|
float get_value (void) const;
|
||||||
|
|
|
||||||
|
|
@ -304,7 +304,7 @@ class Route : public SessionObject, public AutomatableControls, public RouteGrou
|
||||||
void automation_snapshot (nframes_t now, bool force=false);
|
void automation_snapshot (nframes_t now, bool force=false);
|
||||||
void protect_automation ();
|
void protect_automation ();
|
||||||
|
|
||||||
void set_remote_control_id (uint32_t id);
|
void set_remote_control_id (uint32_t id, bool notify_class_listeners = true);
|
||||||
uint32_t remote_control_id () const;
|
uint32_t remote_control_id () const;
|
||||||
|
|
||||||
/* for things concerned about *this* route's RID */
|
/* for things concerned about *this* route's RID */
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,22 @@ const char* edit_mode_to_string (ARDOUR::EditMode);
|
||||||
ARDOUR::EditMode string_to_edit_mode (std::string);
|
ARDOUR::EditMode string_to_edit_mode (std::string);
|
||||||
|
|
||||||
|
|
||||||
|
static inline double
|
||||||
|
gain_to_slider_position (ARDOUR::gain_t g)
|
||||||
|
{
|
||||||
|
if (g == 0) return 0;
|
||||||
|
return pow((6.0*log(g)/log(2.0)+192.0)/198.0, 8.0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline ARDOUR::gain_t
|
||||||
|
slider_position_to_gain (double pos)
|
||||||
|
{
|
||||||
|
/* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
|
||||||
|
if (pos == 0.0) return 0;
|
||||||
|
return pow (2.0,(sqrt(sqrt(sqrt(pos)))*198.0-192.0)/6.0);
|
||||||
|
}
|
||||||
|
|
||||||
/* I don't really like hard-coding these falloff rates here
|
/* I don't really like hard-coding these falloff rates here
|
||||||
* Probably should use a map of some kind that could be configured
|
* Probably should use a map of some kind that could be configured
|
||||||
* These rates are db/sec.
|
* These rates are db/sec.
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ AutomationControl::AutomationControl(
|
||||||
const Evoral::Parameter& parameter,
|
const Evoral::Parameter& parameter,
|
||||||
boost::shared_ptr<ARDOUR::AutomationList> list,
|
boost::shared_ptr<ARDOUR::AutomationList> list,
|
||||||
const string& name)
|
const string& name)
|
||||||
: Controllable((name != "") ? name : EventTypeMap::instance().to_symbol(parameter), string("") /* XXX missing URI */)
|
: Controllable((name != "") ? name : EventTypeMap::instance().to_symbol(parameter))
|
||||||
, Evoral::Control(parameter, list)
|
, Evoral::Control(parameter, list)
|
||||||
, _session(session)
|
, _session(session)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ namespace ARDOUR {
|
||||||
void
|
void
|
||||||
setup_enum_writer ()
|
setup_enum_writer ()
|
||||||
{
|
{
|
||||||
EnumWriter* enum_writer = new EnumWriter();
|
EnumWriter& enum_writer (EnumWriter::instance());
|
||||||
vector<int> i;
|
vector<int> i;
|
||||||
vector<string> s;
|
vector<string> s;
|
||||||
|
|
||||||
|
|
@ -122,8 +122,8 @@ setup_enum_writer ()
|
||||||
Session::SlaveState _Session_SlaveState;
|
Session::SlaveState _Session_SlaveState;
|
||||||
MTC_Status _MIDI_MTC_Status;
|
MTC_Status _MIDI_MTC_Status;
|
||||||
|
|
||||||
#define REGISTER(e) enum_writer->register_distinct (typeid(e).name(), i, s); i.clear(); s.clear()
|
#define REGISTER(e) enum_writer.register_distinct (typeid(e).name(), i, s); i.clear(); s.clear()
|
||||||
#define REGISTER_BITS(e) enum_writer->register_bits (typeid(e).name(), i, s); i.clear(); s.clear()
|
#define REGISTER_BITS(e) enum_writer.register_bits (typeid(e).name(), i, s); i.clear(); s.clear()
|
||||||
#define REGISTER_ENUM(e) i.push_back (e); s.push_back (#e)
|
#define REGISTER_ENUM(e) i.push_back (e); s.push_back (#e)
|
||||||
#define REGISTER_CLASS_ENUM(t,e) i.push_back (t::e); s.push_back (#e)
|
#define REGISTER_CLASS_ENUM(t,e) i.push_back (t::e); s.push_back (#e)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -174,12 +174,14 @@ Route::~Route ()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Route::set_remote_control_id (uint32_t id)
|
Route::set_remote_control_id (uint32_t id, bool notify_class_listeners)
|
||||||
{
|
{
|
||||||
if (id != _remote_control_id) {
|
if (id != _remote_control_id) {
|
||||||
_remote_control_id = id;
|
_remote_control_id = id;
|
||||||
RemoteControlIDChanged ();
|
RemoteControlIDChanged ();
|
||||||
RemoteControlIDChange ();
|
if (notify_class_listeners) {
|
||||||
|
RemoteControlIDChange ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1863,20 +1863,27 @@ void
|
||||||
Session::set_remote_control_ids ()
|
Session::set_remote_control_ids ()
|
||||||
{
|
{
|
||||||
RemoteModel m = Config->get_remote_model();
|
RemoteModel m = Config->get_remote_model();
|
||||||
|
bool emit_signal = false;
|
||||||
|
|
||||||
shared_ptr<RouteList> r = routes.reader ();
|
shared_ptr<RouteList> r = routes.reader ();
|
||||||
|
|
||||||
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
||||||
if ( MixerOrdered == m) {
|
if (MixerOrdered == m) {
|
||||||
long order = (*i)->order_key(N_("signal"));
|
long order = (*i)->order_key(N_("signal"));
|
||||||
(*i)->set_remote_control_id( order+1 );
|
(*i)->set_remote_control_id (order+1, false);
|
||||||
} else if ( EditorOrdered == m) {
|
emit_signal = true;
|
||||||
|
} else if (EditorOrdered == m) {
|
||||||
long order = (*i)->order_key(N_("editor"));
|
long order = (*i)->order_key(N_("editor"));
|
||||||
(*i)->set_remote_control_id( order+1 );
|
(*i)->set_remote_control_id (order+1, false);
|
||||||
} else if ( UserOrdered == m) {
|
emit_signal = true;
|
||||||
|
} else if (UserOrdered == m) {
|
||||||
//do nothing ... only changes to remote id's are initiated by user
|
//do nothing ... only changes to remote id's are initiated by user
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (emit_signal) {
|
||||||
|
Route::RemoteControlIDChange();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2373,6 +2380,8 @@ Session::remove_route (shared_ptr<Route> route)
|
||||||
|
|
||||||
sync_order_keys (N_("session"));
|
sync_order_keys (N_("session"));
|
||||||
|
|
||||||
|
Route::RemoteControlIDChange(); /* EMIT SIGNAL */
|
||||||
|
|
||||||
/* save the new state of the world */
|
/* save the new state of the world */
|
||||||
|
|
||||||
if (save_state (_current_snapshot_name)) {
|
if (save_state (_current_snapshot_name)) {
|
||||||
|
|
@ -4184,9 +4193,11 @@ Session::sync_order_keys (std::string const & base)
|
||||||
}
|
}
|
||||||
|
|
||||||
Route::SyncOrderKeys (base); // EMIT SIGNAL
|
Route::SyncOrderKeys (base); // EMIT SIGNAL
|
||||||
Route::RemoteControlIDChange (); // EMIT SIGNAL
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* this might not do anything */
|
||||||
|
|
||||||
|
set_remote_control_ids ();
|
||||||
|
}
|
||||||
|
|
||||||
/** @return true if there is at least one record-enabled diskstream, otherwise false */
|
/** @return true if there is at least one record-enabled diskstream, otherwise false */
|
||||||
bool
|
bool
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,7 @@ Track::freeze_state() const
|
||||||
}
|
}
|
||||||
|
|
||||||
Track::RecEnableControllable::RecEnableControllable (Track& s)
|
Track::RecEnableControllable::RecEnableControllable (Track& s)
|
||||||
: Controllable (X_("recenable"), string() /* XXX missing URI */), track (s)
|
: Controllable (X_("recenable")), track (s)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pbd/controllable.h"
|
#include "pbd/controllable.h"
|
||||||
|
#include "pbd/enumwriter.h"
|
||||||
#include "pbd/xml++.h"
|
#include "pbd/xml++.h"
|
||||||
#include "pbd/error.h"
|
#include "pbd/error.h"
|
||||||
|
|
||||||
|
|
@ -34,13 +35,11 @@ PBD::Signal1<void,Controllable*> Controllable::DeleteBinding;
|
||||||
|
|
||||||
Glib::StaticRWLock Controllable::registry_lock = GLIBMM_STATIC_RW_LOCK_INIT;
|
Glib::StaticRWLock Controllable::registry_lock = GLIBMM_STATIC_RW_LOCK_INIT;
|
||||||
Controllable::Controllables Controllable::registry;
|
Controllable::Controllables Controllable::registry;
|
||||||
Controllable::ControllablesByURI Controllable::registry_by_uri;
|
|
||||||
PBD::ScopedConnectionList registry_connections;
|
PBD::ScopedConnectionList registry_connections;
|
||||||
|
|
||||||
Controllable::Controllable (const string& name, const string& uri)
|
Controllable::Controllable (const string& name, Flag f)
|
||||||
: _name (name)
|
: _name (name)
|
||||||
, _uri (uri)
|
, _flags (f)
|
||||||
, _touching (false)
|
|
||||||
{
|
{
|
||||||
add (*this);
|
add (*this);
|
||||||
}
|
}
|
||||||
|
|
@ -53,13 +52,6 @@ Controllable::add (Controllable& ctl)
|
||||||
Glib::RWLock::WriterLock lm (registry_lock);
|
Glib::RWLock::WriterLock lm (registry_lock);
|
||||||
registry.insert (&ctl);
|
registry.insert (&ctl);
|
||||||
|
|
||||||
if (!ctl.uri().empty()) {
|
|
||||||
pair<string,Controllable*> newpair;
|
|
||||||
newpair.first = ctl.uri();
|
|
||||||
newpair.second = &ctl;
|
|
||||||
registry_by_uri.insert (newpair);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Controllable::remove() is static - no need to manage this connection */
|
/* Controllable::remove() is static - no need to manage this connection */
|
||||||
|
|
||||||
ctl.DropReferences.connect_same_thread (registry_connections, boost::bind (&Controllable::remove, &ctl));
|
ctl.DropReferences.connect_same_thread (registry_connections, boost::bind (&Controllable::remove, &ctl));
|
||||||
|
|
@ -76,35 +68,6 @@ Controllable::remove (Controllable* ctl)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ctl->uri().empty()) {
|
|
||||||
ControllablesByURI::iterator i = registry_by_uri.find (ctl->uri());
|
|
||||||
if (i != registry_by_uri.end()) {
|
|
||||||
registry_by_uri.erase (i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Controllable::set_uri (const string& new_uri)
|
|
||||||
{
|
|
||||||
Glib::RWLock::WriterLock lm (registry_lock);
|
|
||||||
|
|
||||||
if (!_uri.empty()) {
|
|
||||||
ControllablesByURI::iterator i = registry_by_uri.find (_uri);
|
|
||||||
if (i != registry_by_uri.end()) {
|
|
||||||
registry_by_uri.erase (i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_uri = new_uri;
|
|
||||||
|
|
||||||
if (!_uri.empty()) {
|
|
||||||
pair<string,Controllable*> newpair;
|
|
||||||
newpair.first = _uri;
|
|
||||||
newpair.second = this;
|
|
||||||
registry_by_uri.insert (newpair);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Controllable*
|
Controllable*
|
||||||
|
|
@ -120,18 +83,6 @@ Controllable::by_id (const ID& id)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Controllable*
|
|
||||||
Controllable::by_uri (const string& uri)
|
|
||||||
{
|
|
||||||
Glib::RWLock::ReaderLock lm (registry_lock);
|
|
||||||
ControllablesByURI::iterator i;
|
|
||||||
|
|
||||||
if ((i = registry_by_uri.find (uri)) != registry_by_uri.end()) {
|
|
||||||
return i->second;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Controllable*
|
Controllable*
|
||||||
Controllable::by_name (const string& str)
|
Controllable::by_name (const string& str)
|
||||||
{
|
{
|
||||||
|
|
@ -154,11 +105,8 @@ Controllable::get_state ()
|
||||||
node->add_property (X_("name"), _name); // not reloaded from XML state, just there to look at
|
node->add_property (X_("name"), _name); // not reloaded from XML state, just there to look at
|
||||||
_id.print (buf, sizeof (buf));
|
_id.print (buf, sizeof (buf));
|
||||||
node->add_property (X_("id"), buf);
|
node->add_property (X_("id"), buf);
|
||||||
|
node->add_property (X_("flags"), enum_2_string (_flags));
|
||||||
|
|
||||||
if (!_uri.empty()) {
|
|
||||||
node->add_property (X_("uri"), _uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
return *node;
|
return *node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -175,7 +123,13 @@ Controllable::set_state (const XMLNode& node, int /*version*/)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((prop = node.property (X_("uri"))) != 0) {
|
if ((prop = node.property (X_("flags"))) != 0) {
|
||||||
set_uri (prop->value());
|
_flags = (Flag) string_2_enum (prop->value(), _flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Controllable::set_flags (Flag f)
|
||||||
|
{
|
||||||
|
_flags = f;
|
||||||
|
}
|
||||||
|
|
|
||||||
47
libs/pbd/enums.cc
Normal file
47
libs/pbd/enums.cc
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2009 Paul Davis
|
||||||
|
|
||||||
|
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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "pbd/controllable.h"
|
||||||
|
#include "pbd/enumwriter.h"
|
||||||
|
|
||||||
|
void setup_libpbd_enums () __attribute__ ((constructor));
|
||||||
|
|
||||||
|
using namespace PBD;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
void
|
||||||
|
setup_libpbd_enums ()
|
||||||
|
{
|
||||||
|
EnumWriter& enum_writer (EnumWriter::instance());
|
||||||
|
vector<int> i;
|
||||||
|
vector<string> s;
|
||||||
|
|
||||||
|
Controllable::Flag controllable_flags;
|
||||||
|
|
||||||
|
#define REGISTER(e) enum_writer.register_distinct (typeid(e).name(), i, s); i.clear(); s.clear()
|
||||||
|
#define REGISTER_BITS(e) enum_writer.register_bits (typeid(e).name(), i, s); i.clear(); s.clear()
|
||||||
|
#define REGISTER_ENUM(e) i.push_back (e); s.push_back (#e)
|
||||||
|
#define REGISTER_CLASS_ENUM(t,e) i.push_back (t::e); s.push_back (#e)
|
||||||
|
|
||||||
|
REGISTER_CLASS_ENUM (Controllable, Toggle);
|
||||||
|
REGISTER_CLASS_ENUM (Controllable, Discrete);
|
||||||
|
REGISTER_CLASS_ENUM (Controllable, GainLike);
|
||||||
|
REGISTER_CLASS_ENUM (Controllable, IntegerOnly);
|
||||||
|
REGISTER (controllable_flags);
|
||||||
|
}
|
||||||
|
|
@ -63,11 +63,18 @@ nocase_cmp(const string & s1, const string& s2)
|
||||||
return (size1 < size2) ? -1 : 1;
|
return (size1 < size2) ? -1 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
EnumWriter::EnumWriter ()
|
EnumWriter&
|
||||||
|
EnumWriter::instance()
|
||||||
{
|
{
|
||||||
if (_instance == 0) {
|
if (_instance == 0) {
|
||||||
_instance = this;
|
_instance = new EnumWriter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return *_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
EnumWriter::EnumWriter ()
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
EnumWriter::~EnumWriter ()
|
EnumWriter::~EnumWriter ()
|
||||||
|
|
|
||||||
|
|
@ -35,11 +35,15 @@ namespace PBD {
|
||||||
|
|
||||||
class Controllable : public PBD::StatefulDestructible {
|
class Controllable : public PBD::StatefulDestructible {
|
||||||
public:
|
public:
|
||||||
Controllable (const std::string& name, const std::string& uri);
|
enum Flag {
|
||||||
virtual ~Controllable() { Destroyed (this); }
|
Toggle = 0x1,
|
||||||
|
Discrete = 0x2,
|
||||||
|
GainLike = 0x4,
|
||||||
|
IntegerOnly = 0x8
|
||||||
|
};
|
||||||
|
|
||||||
void set_uri (const std::string&);
|
Controllable (const std::string& name, Flag f = Flag (0));
|
||||||
const std::string& uri() const { return _uri; }
|
virtual ~Controllable() { Destroyed (this); }
|
||||||
|
|
||||||
virtual void set_value (float) = 0;
|
virtual void set_value (float) = 0;
|
||||||
virtual float get_value (void) const = 0;
|
virtual float get_value (void) const = 0;
|
||||||
|
|
@ -59,27 +63,35 @@ class Controllable : public PBD::StatefulDestructible {
|
||||||
XMLNode& get_state ();
|
XMLNode& get_state ();
|
||||||
|
|
||||||
std::string name() const { return _name; }
|
std::string name() const { return _name; }
|
||||||
bool touching () const { return _touching; }
|
|
||||||
|
bool touching () const { return _touching; }
|
||||||
void set_touching (bool yn) { _touching = yn; }
|
void set_touching (bool yn) { _touching = yn; }
|
||||||
|
|
||||||
|
bool is_toggle() const { return _flags & Toggle; }
|
||||||
|
bool is_discrete() const { return _flags & Discrete; }
|
||||||
|
bool is_gain_like() const { return _flags & GainLike; }
|
||||||
|
bool is_integral_only() const { return _flags & IntegerOnly; }
|
||||||
|
|
||||||
|
Flag flags() const { return _flags; }
|
||||||
|
void set_flags (Flag f);
|
||||||
|
|
||||||
|
virtual uint32_t get_discrete_values (std::list<float>&) { return 0; /* no values returned */ }
|
||||||
|
|
||||||
static Controllable* by_id (const PBD::ID&);
|
static Controllable* by_id (const PBD::ID&);
|
||||||
static Controllable* by_name (const std::string&);
|
static Controllable* by_name (const std::string&);
|
||||||
static Controllable* by_uri (const std::string&);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string _name;
|
std::string _name;
|
||||||
std::string _uri;
|
|
||||||
|
Flag _flags;
|
||||||
bool _touching;
|
bool _touching;
|
||||||
|
|
||||||
static void add (Controllable&);
|
static void add (Controllable&);
|
||||||
static void remove (Controllable*);
|
static void remove (Controllable*);
|
||||||
|
|
||||||
typedef std::set<PBD::Controllable*> Controllables;
|
typedef std::set<PBD::Controllable*> Controllables;
|
||||||
typedef std::map<std::string,PBD::Controllable*> ControllablesByURI;
|
|
||||||
static Glib::StaticRWLock registry_lock;
|
static Glib::StaticRWLock registry_lock;
|
||||||
static Controllables registry;
|
static Controllables registry;
|
||||||
static ControllablesByURI registry_by_uri;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* a utility class for the occasions when you need but do not have
|
/* a utility class for the occasions when you need but do not have
|
||||||
|
|
@ -89,7 +101,7 @@ class Controllable : public PBD::StatefulDestructible {
|
||||||
class IgnorableControllable : public Controllable
|
class IgnorableControllable : public Controllable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
IgnorableControllable () : PBD::Controllable ("ignoreMe", std::string()) {}
|
IgnorableControllable () : PBD::Controllable ("ignoreMe") {}
|
||||||
~IgnorableControllable () {}
|
~IgnorableControllable () {}
|
||||||
|
|
||||||
void set_value (float /*v*/) {}
|
void set_value (float /*v*/) {}
|
||||||
|
|
|
||||||
|
|
@ -36,10 +36,7 @@ class unknown_enumeration : public std::exception {
|
||||||
|
|
||||||
class EnumWriter {
|
class EnumWriter {
|
||||||
public:
|
public:
|
||||||
EnumWriter ();
|
static EnumWriter& instance();
|
||||||
~EnumWriter ();
|
|
||||||
|
|
||||||
static EnumWriter& instance() { return *_instance; }
|
|
||||||
|
|
||||||
void register_distinct (std::string type, std::vector<int>, std::vector<std::string>);
|
void register_distinct (std::string type, std::vector<int>, std::vector<std::string>);
|
||||||
void register_bits (std::string type, std::vector<int>, std::vector<std::string>);
|
void register_bits (std::string type, std::vector<int>, std::vector<std::string>);
|
||||||
|
|
@ -50,6 +47,9 @@ class EnumWriter {
|
||||||
void add_to_hack_table (std::string str, std::string hacked_str);
|
void add_to_hack_table (std::string str, std::string hacked_str);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
EnumWriter ();
|
||||||
|
~EnumWriter ();
|
||||||
|
|
||||||
struct EnumRegistration {
|
struct EnumRegistration {
|
||||||
std::vector<int> values;
|
std::vector<int> values;
|
||||||
std::vector<std::string> names;
|
std::vector<std::string> names;
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,7 @@ def build(bld):
|
||||||
enumwriter.cc
|
enumwriter.cc
|
||||||
event_loop.cc
|
event_loop.cc
|
||||||
dmalloc.cc
|
dmalloc.cc
|
||||||
|
enums.cc
|
||||||
error.cc
|
error.cc
|
||||||
filesystem.cc
|
filesystem.cc
|
||||||
filesystem_paths.cc
|
filesystem_paths.cc
|
||||||
|
|
|
||||||
|
|
@ -274,7 +274,6 @@ GenericMidiControlProtocol::start_learning (Controllable* c)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Glib::Mutex::Lock lm (pending_lock);
|
|
||||||
Glib::Mutex::Lock lm2 (controllables_lock);
|
Glib::Mutex::Lock lm2 (controllables_lock);
|
||||||
|
|
||||||
MIDIControllables::iterator tmp;
|
MIDIControllables::iterator tmp;
|
||||||
|
|
@ -288,20 +287,23 @@ GenericMidiControlProtocol::start_learning (Controllable* c)
|
||||||
i = tmp;
|
i = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
MIDIPendingControllables::iterator ptmp;
|
{
|
||||||
for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ) {
|
Glib::Mutex::Lock lm (pending_lock);
|
||||||
ptmp = i;
|
|
||||||
++ptmp;
|
MIDIPendingControllables::iterator ptmp;
|
||||||
if (((*i)->first)->get_controllable() == c) {
|
for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ) {
|
||||||
(*i)->second.disconnect();
|
ptmp = i;
|
||||||
delete (*i)->first;
|
++ptmp;
|
||||||
delete *i;
|
if (((*i)->first)->get_controllable() == c) {
|
||||||
pending_controllables.erase (i);
|
(*i)->second.disconnect();
|
||||||
|
delete (*i)->first;
|
||||||
|
delete *i;
|
||||||
|
pending_controllables.erase (i);
|
||||||
|
}
|
||||||
|
i = ptmp;
|
||||||
}
|
}
|
||||||
i = ptmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MIDIControllable* mc = 0;
|
MIDIControllable* mc = 0;
|
||||||
|
|
||||||
for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
|
for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
|
||||||
|
|
@ -702,6 +704,7 @@ GenericMidiControlProtocol::create_binding (const XMLNode& node)
|
||||||
void
|
void
|
||||||
GenericMidiControlProtocol::reset_controllables ()
|
GenericMidiControlProtocol::reset_controllables ()
|
||||||
{
|
{
|
||||||
|
cerr << "GM::RC\n";
|
||||||
Glib::Mutex::Lock lm2 (controllables_lock);
|
Glib::Mutex::Lock lm2 (controllables_lock);
|
||||||
|
|
||||||
for (MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end(); ++iter) {
|
for (MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end(); ++iter) {
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
#include "midi++/channel.h"
|
#include "midi++/channel.h"
|
||||||
|
|
||||||
#include "ardour/automation_control.h"
|
#include "ardour/automation_control.h"
|
||||||
|
#include "ardour/utils.h"
|
||||||
|
|
||||||
#include "midicontrollable.h"
|
#include "midicontrollable.h"
|
||||||
|
|
||||||
|
|
@ -196,10 +197,14 @@ MIDIControllable::midi_to_control(float val)
|
||||||
control_max = ac->parameter().max();
|
control_max = ac->parameter().max();
|
||||||
}
|
}
|
||||||
|
|
||||||
const float control_range = control_max - control_min;
|
|
||||||
const float midi_range = 127.0f; // TODO: NRPN etc.
|
const float midi_range = 127.0f; // TODO: NRPN etc.
|
||||||
|
|
||||||
return val / midi_range * control_range + control_min;
|
if (ac->is_gain_like()) {
|
||||||
|
return slider_position_to_gain (val/midi_range);
|
||||||
|
}
|
||||||
|
|
||||||
|
const float control_range = control_max - control_min;
|
||||||
|
return val / midi_range * control_range + control_min;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -459,8 +464,11 @@ MIDIControllable::get_state ()
|
||||||
|
|
||||||
XMLNode* node = new XMLNode ("MIDIControllable");
|
XMLNode* node = new XMLNode ("MIDIControllable");
|
||||||
|
|
||||||
|
if (!_current_uri.empty()) {
|
||||||
|
node->add_property ("uri", _current_uri);
|
||||||
|
}
|
||||||
|
|
||||||
if (controllable) {
|
if (controllable) {
|
||||||
node->add_property ("uri", controllable->uri());
|
|
||||||
snprintf (buf, sizeof(buf), "0x%x", (int) control_type);
|
snprintf (buf, sizeof(buf), "0x%x", (int) control_type);
|
||||||
node->add_property ("event", buf);
|
node->add_property ("event", buf);
|
||||||
snprintf (buf, sizeof(buf), "%d", (int) control_channel);
|
snprintf (buf, sizeof(buf), "%d", (int) control_channel);
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,7 @@ class MIDIControllable : public PBD::Stateful
|
||||||
bool setting;
|
bool setting;
|
||||||
MIDI::byte last_value;
|
MIDI::byte last_value;
|
||||||
bool bistate;
|
bool bistate;
|
||||||
|
bool _is_gain_controller;
|
||||||
bool _learned;
|
bool _learned;
|
||||||
int midi_msg_id; /* controller ID or note number */
|
int midi_msg_id; /* controller ID or note number */
|
||||||
PBD::ScopedConnection midi_sense_connection[2];
|
PBD::ScopedConnection midi_sense_connection[2];
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue