}
void
-ARDOUR_UI::TransportControllable::set_value (float val)
+ARDOUR_UI::TransportControllable::set_value (double val)
{
if (type == ShuttleControl) {
double fract;
- if (val == 0.5f) {
+ if (val == 0.5) {
fract = 0.0;
} else {
- if (val < 0.5f) {
- fract = -((0.5f - val)/0.5f);
+ if (val < 0.5) {
+ fract = -((0.5 - val)/0.5);
} else {
- fract = ((val - 0.5f)/0.5f);
+ fract = ((val - 0.5)/0.5);
}
}
return;
}
- if (val < 0.5f) {
+ if (val < 0.5) {
/* do nothing: these are radio-style actions */
return;
}
}
}
-float
+double
ARDOUR_UI::TransportControllable::get_value (void) const
{
- float val = 0.0f;
+ float val = 0.0;
switch (type) {
case Roll:
};
TransportControllable (std::string name, ARDOUR_UI&, ToggleType);
- void set_value (float);
- float get_value (void) const;
+ void set_value (double);
+ double get_value (void) const;
void set_id (const std::string&);
double y,
string& model_name,
string& custom_device_mode,
- nframes_t event_time,
+ double event_time,
uint8_t channel,
uint8_t program)
: CanvasFlag(
initialize_popup_menus();
_popup_initialized = true;
}
- _popup.popup(ev->button.button, ev->button.time);
+ _popup.popup(ev->button.button, ev->button.time);
return true;
}
break;
+ case GDK_KEY_PRESS:
+ switch (ev->key.keyval) {
+ case GDK_Up:
+ case GDK_KP_Up:
+ case GDK_uparrow:
+ _region.previous_program(*this);
+ break;
+ case GDK_Down:
+ case GDK_KP_Down:
+ case GDK_downarrow:
+ _region.next_program(*this);
+ break;
+ default:
+ break;
+ }
+ break;
+
case GDK_SCROLL:
if (ev->scroll.direction == GDK_SCROLL_UP) {
_region.previous_program(*this);
double y,
string& model_name,
string& custom_device_mode,
- nframes_t event_time,
+ double _event_time,
uint8_t channel,
uint8_t program
);
string custom_device_mode() const { return _custom_device_mode; }
void set_custom_device_mode(string custom_device_mode) { _custom_device_mode = custom_device_mode; }
- nframes_t event_time() const { return _event_time; }
- void set_event_time(nframes_t new_time) { _event_time = new_time; };
+ double event_time() const { return _event_time; }
+ void set_event_time(double new_time) { _event_time = new_time; };
uint8_t program() const { return _program; }
void set_program(uint8_t new_program) { _program = new_program; };
private:
string _model_name;
string _custom_device_mode;
- nframes_t _event_time;
+ double _event_time;
uint8_t _channel;
uint8_t _program;
Gtk::Menu _popup;
#include "ardour/session.h"
#include "evoral/Parameter.hpp"
+#include "evoral/MIDIParameters.hpp"
#include "evoral/Control.hpp"
#include "evoral/midi_util.h"
void
MidiRegionView::display_program_changes()
{
- boost::shared_ptr<Evoral::Control> control = _model->control(MidiPgmChangeAutomation);
+ MidiTimeAxisView* const mtv = dynamic_cast<MidiTimeAxisView*>(&trackview);
+ uint16_t chn_mask = mtv->channel_selector().get_selected_channels();
+
+ for (uint8_t i = 0; i < 16; ++i) {
+ if (chn_mask & (1<<i)) {
+ display_program_changes_on_channel (i);
+ }
+ }
+}
+
+void
+MidiRegionView::display_program_changes_on_channel(uint8_t channel)
+{
+ boost::shared_ptr<Evoral::Control> control =
+ _model->control(Evoral::MIDI::ProgramChange (MidiPgmChangeAutomation, channel));
+
if (!control) {
return;
}
Glib::Mutex::Lock lock (control->list()->lock());
- uint8_t channel = control->parameter().channel();
-
for (AutomationList::const_iterator event = control->list()->begin();
event != control->list()->end(); ++event) {
double event_time = (*event)->when;
boost::shared_ptr<Evoral::Control> msb_control = _model->control(bank_select_msb);
uint8_t msb = 0;
if (msb_control != 0) {
- msb = uint8_t(floor(msb_control->get_float(true, event_time) + 0.5));
+ msb = uint8_t(floor(msb_control->get_double(true, event_time) + 0.5));
}
// Get current value of bank select LSB at time of the program change
boost::shared_ptr<Evoral::Control> lsb_control = _model->control(bank_select_lsb);
uint8_t lsb = 0;
if (lsb_control != 0) {
- lsb = uint8_t(floor(lsb_control->get_float(true, event_time) + 0.5));
+ lsb = uint8_t(floor(lsb_control->get_double(true, event_time) + 0.5));
}
MIDI::Name::PatchPrimaryKey patch_key(msb, lsb, program_number);
add_pgm_change(program_change, patch->name());
} else {
char buf[4];
- snprintf(buf, 4, "%d", int(program_number));
+ // program_number is zero-based: convert to one-based
+ snprintf(buf, 4, "%d", int(program_number+1));
add_pgm_change(program_change, buf);
}
}
void
MidiRegionView::get_patch_key_at(double time, uint8_t channel, MIDI::Name::PatchPrimaryKey& key)
{
- cerr << "getting patch key at " << time << " for channel " << channel << endl;
Evoral::Parameter bank_select_msb(MidiCCAutomation, channel, MIDI_CTL_MSB_BANK);
boost::shared_ptr<Evoral::Control> msb_control = _model->control(bank_select_msb);
- float msb = -1.0;
+ double msb = 0.0;
if (msb_control != 0) {
- msb = int(msb_control->get_float(true, time));
- cerr << "got msb " << msb;
+ msb = int(msb_control->get_double(true, time));
}
Evoral::Parameter bank_select_lsb(MidiCCAutomation, channel, MIDI_CTL_LSB_BANK);
boost::shared_ptr<Evoral::Control> lsb_control = _model->control(bank_select_lsb);
- float lsb = -1.0;
+ double lsb = 0.0;
if (lsb_control != 0) {
- lsb = lsb_control->get_float(true, time);
- cerr << " got lsb " << lsb;
+ lsb = lsb_control->get_double(true, time);
}
Evoral::Parameter program_change(MidiPgmChangeAutomation, channel, 0);
boost::shared_ptr<Evoral::Control> program_control = _model->control(program_change);
- float program_number = -1.0;
+ double program_number = -1.0;
if (program_control != 0) {
- program_number = program_control->get_float(true, time);
- cerr << " got program " << program_number << endl;
+ program_number = program_control->get_double(true, time);
}
key.msb = (int) floor(msb + 0.5);
Evoral::Parameter bank_select_msb(MidiCCAutomation, old_program.channel, MIDI_CTL_MSB_BANK);
boost::shared_ptr<Evoral::Control> msb_control = _model->control(bank_select_msb);
if (msb_control != 0) {
- msb_control->set_float(float(new_patch.msb), true, old_program.time);
+ msb_control->set_double(double(new_patch.msb), true, old_program.time);
}
// TODO: Get the real event here and alter them at the original times
Evoral::Parameter bank_select_lsb(MidiCCAutomation, old_program.channel, MIDI_CTL_LSB_BANK);
boost::shared_ptr<Evoral::Control> lsb_control = _model->control(bank_select_lsb);
if (lsb_control != 0) {
- lsb_control->set_float(float(new_patch.lsb), true, old_program.time);
+ lsb_control->set_double(double(new_patch.lsb), true, old_program.time);
}
Evoral::Parameter program_change(MidiPgmChangeAutomation, old_program.channel, 0);
boost::shared_ptr<Evoral::Control> program_control = _model->control(program_change);
assert(program_control != 0);
- program_control->set_float(float(new_patch.program_number), true, old_program.time);
+ program_control->set_double(float(new_patch.program_number), true, old_program.time);
- redisplay_model();
+ _pgm_changes.clear ();
+ display_program_changes (); // XXX would be nice to limit to just old_program.channel
}
void
void
MidiRegionView::previous_program(CanvasProgramChange& program)
{
- MIDI::Name::PatchPrimaryKey key;
- get_patch_key_at(program.event_time(), program.channel(), key);
-
- boost::shared_ptr<MIDI::Name::Patch> patch =
- MIDI::Name::MidiPatchManager::instance().previous_patch(
- _model_name,
- _custom_device_mode,
- program.channel(),
- key);
+ if (program.program() < 127) {
+ MIDI::Name::PatchPrimaryKey key;
+ get_patch_key_at(program.event_time(), program.channel(), key);
+ PCEvent program_change_event(program.event_time(), program.program(), program.channel());
- PCEvent program_change_event(program.event_time(), program.program(), program.channel());
- if (patch) {
- alter_program_change(program_change_event, patch->patch_primary_key());
- }
+ key.program_number++;
+ alter_program_change(program_change_event, key);
+ }
}
void
MidiRegionView::next_program(CanvasProgramChange& program)
{
- MIDI::Name::PatchPrimaryKey key;
- get_patch_key_at(program.event_time(), program.channel(), key);
-
- boost::shared_ptr<MIDI::Name::Patch> patch =
- MIDI::Name::MidiPatchManager::instance().next_patch(
- _model_name,
- _custom_device_mode,
- program.channel(),
- key);
+ if (program.program() > 0) {
+ MIDI::Name::PatchPrimaryKey key;
+ get_patch_key_at(program.event_time(), program.channel(), key);
+ PCEvent program_change_event(program.event_time(), program.program(), program.channel());
- PCEvent program_change_event(program.event_time(), program.program(), program.channel());
- if (patch) {
- alter_program_change(program_change_event, patch->patch_primary_key());
- }
+ key.program_number--;
+ alter_program_change(program_change_event, key);
+ }
}
void
void drop_down_keys ();
void maybe_select_by_position (GdkEventButton* ev, double x, double y);
void get_events (Events& e, Evoral::Sequence<Evoral::MusicalTime>::NoteOperator op, uint8_t val, int chan_mask = 0);
+
+ void display_program_changes_on_channel (uint8_t);
+
};
} else { /* manual (scalar) gain */
- gain_t const dg = _gain_control->user_float();
+ gain_t const dg = _gain_control->user_double();
if (_current_gain != dg) {
void
Amp::inc_gain (gain_t factor, void *src)
{
- float desired_gain = _gain_control->user_float();
+ float desired_gain = _gain_control->user_double();
if (desired_gain == 0.0f) {
set_gain (0.000001f + (0.000001f * factor), src);
return;
}
- _gain_control->set_float(val, false);
+ _gain_control->set_double(val, false);
_session.set_dirty();
}
}
void
-Amp::GainControl::set_value (float val)
+Amp::GainControl::set_value (double val)
{
// max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
if (val > 1.99526231f)
AutomationControl::set_value(val);
}
-float
+double
Amp::GainControl::get_value (void) const
{
return AutomationControl::get_value();
static void declick (BufferSet& bufs, nframes_t nframes, int dir);
- gain_t gain () const { return _gain_control->user_float(); }
+ gain_t gain () const { return _gain_control->user_double(); }
virtual void set_gain (gain_t g, void *src);
void inc_gain (gain_t delta, void *src);
set_flags (Controllable::Flag (flags() | Controllable::GainLike));
}
- void set_value (float val);
- float get_value (void) const;
+ void set_value (double val);
+ double get_value (void) const;
Amp* _amp;
};
/** Set the value and do the right thing based on automation state
* (e.g. record if necessary, etc.)
*/
- void set_value(float val);
+ void set_value(double val);
/** Get the current effective value based on automation state.
*/
- float get_value() const;
+ double get_value() const;
- float lower() const { return parameter().min(); }
- float upper() const { return parameter().max(); }
+ double lower() const { return parameter().min(); }
+ double upper() const { return parameter().max(); }
protected:
ARDOUR::Session& _session;
, _route (route)
{}
- void set_value (float val);
+ void set_value (double val);
MidiTrack* _route;
};
/* Controllable API */
- void set_value (float v) {
+ void set_value (double v) {
T newval = (T) v;
if (newval != _value) {
_value = newval;
}
}
- float get_value () const {
+ double get_value () const {
return (float) _value;
}
- float lower () const { return _lower; }
- float upper () const { return _upper; }
+ double lower () const { return _lower; }
+ double upper () const { return _upper; }
/* "access as T" API */
AutomationList* alist() { return (AutomationList*)_list.get(); }
Panner& panner;
- void set_value (float);
- float get_value (void) const;
+ void set_value (double);
+ double get_value (void) const;
};
boost::shared_ptr<AutomationControl> pan_control (int id, int chan=0) {
PluginControl (PluginInsert* p, const Evoral::Parameter ¶m,
boost::shared_ptr<AutomationList> list = boost::shared_ptr<AutomationList>());
- void set_value (float val);
- float get_value (void) const;
+ void set_value (double val);
+ double get_value (void) const;
private:
PluginInsert* _plugin;
struct SoloControllable : public AutomationControl {
SoloControllable (std::string name, Route&);
- void set_value (float);
- float get_value (void) const;
+ void set_value (double);
+ double get_value (void) const;
Route& route;
};
struct MuteControllable : public AutomationControl {
MuteControllable (std::string name, Route&);
- void set_value (float);
- float get_value (void) const;
+ void set_value (double);
+ double get_value (void) const;
Route& route;
};
struct RecEnableControllable : public PBD::Controllable {
RecEnableControllable (Track&);
- void set_value (float);
- float get_value (void) const;
+ void set_value (double);
+ double get_value (void) const;
Track& track;
};
boost::shared_ptr<AutomationControl> c
= boost::dynamic_pointer_cast<AutomationControl>(i->second);
if (c->automation_write()) {
- c->list()->rt_add (now, i->second->user_float());
+ c->list()->rt_add (now, i->second->user_double());
}
}
{
}
-
-float
+double
AutomationControl::get_value() const
{
bool from_list = _list && ((AutomationList*)_list.get())->automation_playback();
- return Control::get_float(from_list, _session.transport_frame());
+ return Control::get_double (from_list, _session.transport_frame());
}
-
void
-AutomationControl::set_value(float value)
+AutomationControl::set_value(double value)
{
bool to_list = _list && _session.transport_stopped()
&& ((AutomationList*)_list.get())->automation_write();
- Control::set_float(value, to_list, _session.transport_frame());
+ Control::set_double(value, to_list, _session.transport_frame());
Changed(); /* EMIT SIGNAL */
}
DEBUG_TRACE (DEBUG::MidiIO, DEBUG_STR(a).str());
#endif
- // cerr << "MidiBuffer: pushing event @ " << time
- // << " size = " << size << endl;
-
if (_size + stamp_size + size >= _capacity) {
cerr << "MidiBuffer::push_back failed (buffer is full)" << endl;
return false;
jack_midi_event_get (&ev, jack_buffer, i);
-#if 0
if (ev.buffer[0] == 0xfe) {
/* throw away active sensing */
continue;
}
-#endif
+
if (ev.time > off && ev.time < off+nframes) {
_buffer->push_back (ev);
}
if (time_frames < start + cnt) {
dst.write(time_frames + stamp_offset - negative_stamp_offset,
i->event_type(), i->size(), i->buffer());
+
if (tracker) {
Evoral::MIDIEvent<Evoral::MusicalTime>& ev (*(Evoral::MIDIEvent<Evoral::MusicalTime>*) (&(*i)));
if (ev.is_note_on()) {
- DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("\t%1 add note on %2 @ %3\n", _name, ev.note(), time_frames));
+ DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("\t%1 add note on %2 @ %3 velocity %4\n", _name, ev.note(), time_frames, (int) ev.velocity()));
tracker->add (ev.note(), ev.channel());
} else if (ev.is_note_off()) {
DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("\t%1 add note off %2 @ %3\n", _name, ev.note(), time_frames));
}
void
-MidiTrack::MidiControl::set_value(float val)
+MidiTrack::MidiControl::set_value(double val)
{
bool valid = false;
if (isinf(val)) {
/* specialize for bool because of set_value() semantics */
namespace ARDOUR {
- template<> void MPControl<bool>::set_value (float v) {
+ template<> void MPControl<bool>::set_value (double v) {
bool newval = fabs (v) >= 0.5;
if (newval != _value) {
_value = newval;
}
void
-Panner::PanControllable::set_value (float val)
+Panner::PanControllable::set_value (double val)
{
panner.streampanner (parameter().id()).set_position (direct_control_to_pan (val));
AutomationControl::set_value(val);
}
-float
+double
Panner::PanControllable::get_value (void) const
{
return AutomationControl::get_value();
}
void
-PluginInsert::PluginControl::set_value (float val)
+PluginInsert::PluginControl::set_value (double val)
{
/* FIXME: probably should be taking out some lock here.. */
AutomationControl::set_value(val);
}
-float
+double
PluginInsert::PluginControl::get_value (void) const
{
/* FIXME: probably should be taking out some lock here.. */
- float val = _plugin->get_parameter (_list->parameter());
+ double val = _plugin->get_parameter (_list->parameter());
return val;
}
void
-Route::SoloControllable::set_value (float val)
+Route::SoloControllable::set_value (double val)
{
bool bval = ((val >= 0.5f) ? true: false);
# if 0
#endif
}
-float
+double
Route::SoloControllable::get_value (void) const
{
if (Config->get_solo_control_is_listen_control()) {
}
void
-Route::MuteControllable::set_value (float val)
+Route::MuteControllable::set_value (double val)
{
bool bval = ((val >= 0.5f) ? true: false);
# if 0
#endif
}
-float
+double
Route::MuteControllable::get_value (void) const
{
return route.muted() ? 1.0f : 0.0f;
}
void
-Track::RecEnableControllable::set_value (float val)
+Track::RecEnableControllable::set_value (double val)
{
- bool bval = ((val >= 0.5f) ? true: false);
+ bool bval = ((val >= 0.5) ? true: false);
track.set_record_enabled (bval, this);
}
-float
+double
Track::RecEnableControllable::get_value (void) const
{
- if (track.record_enabled()) { return 1.0f; }
- return 0.0f;
+ if (track.record_enabled()) { return 1.0; }
+ return 0.0;
}
bool
Control(const Parameter& parameter, boost::shared_ptr<ControlList>);
virtual ~Control() {}
- virtual void set_float(float val, bool to_list=false, FrameTime frame=0);
- virtual float get_float(bool from_list=false, FrameTime frame=0) const;
+ virtual void set_double(double val, bool to_list=false, double frame=0);
+ virtual double get_double(bool from_list=false, double frame=0) const;
/** Get the latest user-set value
* Automation write/touch works by periodically sampling this value
* and adding it to the ControlList.
*/
- float user_float() const { return _user_value; }
+ double user_double() const { return _user_value; }
void set_list(boost::shared_ptr<ControlList>);
+
boost::shared_ptr<ControlList> list() { return _list; }
boost::shared_ptr<const ControlList> list() const { return _list; }
protected:
Parameter _parameter;
boost::shared_ptr<ControlList> _list;
- float _user_value;
+ double _user_value;
PBD::ScopedConnection _list_marked_dirty_connection;
private:
virtual void add_control(boost::shared_ptr<Control>);
- bool find_next_event(FrameTime start, FrameTime end, ControlEvent& ev) const;
+ bool find_next_event(double start, double end, ControlEvent& ev) const;
virtual bool controls_empty() const { return _controls.size() == 0; }
virtual void clear_controls();
/** Strict weak ordering
* See: http://www.sgi.com/tech/stl/StrictWeakOrdering.html
- * Sort Parameters first according to type then to id and lastly to channel.
- *
- * Proof:
- * <ol>
- * <li>Irreflexivity: f(x, x) is false because of the irreflexivity of \c < in each branch.</li>
- * <li>Antisymmetry: given x != y, f(x, y) implies !f(y, x) because of the same
- * property of \c < in each branch and the symmetry of operator==. </li>
- * <li>Transitivity: let f(x, y) and f(y, z) => f(x, z) be true.
- * We prove by contradiction, assuming the contrary:
- * f(x, y) and f(x, z) hold => !f(x, z)
- *
- * That implies one of the following:
- * <ol>
- * <li> x == z which contradicts the assumption f(x, y) and f(y, x)
- * because of antisymmetry.
- * </li>
- * <li> f(z, x) is true. That would imply that one of the ivars (we call it i)
- * of x is greater than the same ivar in z while all "previous" ivars
- * are equal. That would imply that also in y all those "previous"
- * ivars are equal and because if x.i > z.i it is impossible
- * that there is an y that satisfies x.i < y.i < z.i at the same
- * time which contradicts the assumption.
- * </li>
- * Therefore f(x, z) is true (transitivity)
- * </ol>
- * </li>
- * </ol>
+ * Sort Parameters first according to type then to channel and lastly to ID.
*/
inline bool operator<(const Parameter& other) const {
if (_type < other._type) {
typedef int32_t event_id_t;
-/** Frame count (i.e. length of time in audio frames) */
-typedef uint32_t FrameTime;
-
/** Musical time: beats relative to some defined origin */
typedef double MusicalTime;
const MusicalTime MaxMusicalTime = DBL_MAX;
/** Type to describe the movement of a time range */
template<typename T>
struct RangeMove {
- RangeMove (T f, FrameTime l, T t) : from (f), length (l), to (t) {}
+ RangeMove (T f, double l, T t) : from (f), length (l), to (t) {}
T from; ///< start of the range
- FrameTime length; ///< length of the range
+ double length; ///< length of the range
T to; ///< new start of the range
};
/** Get the currently effective value (ie the one that corresponds to current output)
*/
-float
-Control::get_float(bool from_list, FrameTime frame) const
+double
+Control::get_double (bool from_list, double frame) const
{
if (from_list) {
return _list->eval(frame);
void
-Control::set_float(float value, bool to_list, FrameTime frame)
+Control::set_double (double value, bool to_list, double frame)
{
_user_value = value;
if (to_list) {
- _list->add(frame, value);
+ _list->add (frame, value);
}
}
}
bool
-ControlSet::find_next_event (FrameTime now, FrameTime end, ControlEvent& next_event) const
+ControlSet::find_next_event (double now, double end, ControlEvent& next_event) const
{
Controls::const_iterator li;
- next_event.when = std::numeric_limits<FrameTime>::max();
+ next_event.when = std::numeric_limits<double>::max();
for (li = _controls.begin(); li != _controls.end(); ++li) {
ControlList::const_iterator i;
}
}
- return next_event.when != std::numeric_limits<FrameTime>::max();
+ return next_event.when != std::numeric_limits<double>::max();
}
void
return;
}
-
if (ev.is_note_on()) {
NotePtr note(new Note<Time>(ev.channel(), ev.time(), 0, ev.note(), ev.velocity()));
append_note_on_unlocked (note, evid);
Controllable (const std::string& name, Flag f = Flag (0));
virtual ~Controllable() { Destroyed (this); }
- virtual void set_value (float) = 0;
- virtual float get_value (void) const = 0;
+ virtual void set_value (double) = 0;
+ virtual double get_value (void) const = 0;
PBD::Signal0<void> LearningFinished;
static PBD::Signal3<void,PBD::Controllable*,int,int> CreateBinding;
bool is_gain_like() const { return _flags & GainLike; }
bool is_integral_only() const { return _flags & IntegerOnly; }
- virtual float lower() const { return 0.0f; }
- virtual float upper() const { return 1.0f; }
+ virtual double lower() const { return 0.0; }
+ virtual double upper() const { return 1.0; }
Flag flags() const { return _flags; }
void set_flags (Flag f);
IgnorableControllable () : PBD::Controllable ("ignoreMe") {}
~IgnorableControllable () {}
- void set_value (float /*v*/) {}
- float get_value () const { return 0.0; }
+ void set_value (double /*v*/) {}
+ double get_value () const { return 0.0; }
};
}