fix redrawing of canvas with an optimized build
Best guess right now is that optimization does something bad when ceil() is called twice on a very large dbl-precision number, which results in a zero (empty) redraw area. Without the removal of the redundant ceil & floor functions, no expose events would be delivered to the canvas in an optimized build during drags (and maybe more).
This commit is contained in:
@@ -3569,7 +3569,8 @@ ARDOUR_UI::add_video (Gtk::Window* float_window)
|
||||
if (!transcode_video_dialog->get_audiofile().empty()) {
|
||||
editor->embed_audio_from_video(
|
||||
transcode_video_dialog->get_audiofile(),
|
||||
video_timeline->get_offset()
|
||||
video_timeline->get_offset(),
|
||||
(transcode_video_dialog->import_option() != VTL_IMPORT_NO_VIDEO)
|
||||
);
|
||||
}
|
||||
switch (transcode_video_dialog->import_option()) {
|
||||
|
||||
@@ -186,6 +186,11 @@ ARDOUR_UI::set_session (Session *s)
|
||||
|
||||
update_format ();
|
||||
|
||||
if (meter_box.get_parent()) {
|
||||
transport_tearoff_hbox.remove (meter_box);
|
||||
transport_tearoff_hbox.remove (editor_meter_peak_display);
|
||||
}
|
||||
|
||||
if (editor_meter) {
|
||||
meter_box.remove(*editor_meter);
|
||||
delete editor_meter;
|
||||
@@ -222,15 +227,8 @@ ARDOUR_UI::set_session (Session *s)
|
||||
transport_tearoff_hbox.pack_start (editor_meter_peak_display, false, false);
|
||||
meter_box.show();
|
||||
editor_meter_peak_display.show();
|
||||
} else if (meter_box.get_parent()) {
|
||||
transport_tearoff_hbox.remove (meter_box);
|
||||
transport_tearoff_hbox.remove (editor_meter_peak_display);
|
||||
}
|
||||
} else if (meter_box.get_parent()) {
|
||||
transport_tearoff_hbox.remove (meter_box);
|
||||
transport_tearoff_hbox.remove (editor_meter_peak_display);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
@@ -403,14 +403,19 @@ ARDOUR_UI::parameter_changed (std::string p)
|
||||
ArdourCanvas::WaveView::set_global_gradient_depth (config()->get_waveform_gradient_depth());
|
||||
} else if (p == "show-editor-meter") {
|
||||
bool show = Config->get_show_editor_meter();
|
||||
if (editor_meter && show) {
|
||||
transport_tearoff_hbox.pack_start (meter_box, false, false);
|
||||
transport_tearoff_hbox.pack_start (editor_meter_peak_display, false, false);
|
||||
meter_box.show();
|
||||
editor_meter_peak_display.show();
|
||||
} else if (editor_meter && !show && meter_box.get_parent()) {
|
||||
transport_tearoff_hbox.remove (meter_box);
|
||||
transport_tearoff_hbox.remove (editor_meter_peak_display);
|
||||
|
||||
if (editor_meter) {
|
||||
if (meter_box.get_parent()) {
|
||||
transport_tearoff_hbox.remove (meter_box);
|
||||
transport_tearoff_hbox.remove (editor_meter_peak_display);
|
||||
}
|
||||
|
||||
if (show) {
|
||||
transport_tearoff_hbox.pack_start (meter_box, false, false);
|
||||
transport_tearoff_hbox.pack_start (editor_meter_peak_display, false, false);
|
||||
meter_box.show();
|
||||
editor_meter_peak_display.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1415,7 +1415,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
||||
void toggle_video_timeline_locked ();
|
||||
void set_video_timeline_locked (const bool);
|
||||
void queue_visual_videotimeline_update ();
|
||||
void embed_audio_from_video (std::string, framepos_t n = 0);
|
||||
void embed_audio_from_video (std::string, framepos_t n = 0, bool lock_position_to_video = true);
|
||||
|
||||
PBD::Signal0<void> EditorFreeze;
|
||||
PBD::Signal0<void> EditorThaw;
|
||||
|
||||
@@ -80,13 +80,10 @@ Editor::toggle_video_timeline_locked ()
|
||||
}
|
||||
|
||||
void
|
||||
Editor::embed_audio_from_video (std::string path, framepos_t n)
|
||||
Editor::embed_audio_from_video (std::string path, framepos_t n, bool lock_position_to_video)
|
||||
{
|
||||
vector<std::string> paths;
|
||||
paths.push_back(path);
|
||||
#if 0
|
||||
do_import (paths, Editing::ImportDistinctFiles, Editing::ImportAsTrack, ARDOUR::SrcBest, n);
|
||||
#else
|
||||
current_interthread_info = &import_status;
|
||||
import_status.current = 1;
|
||||
import_status.total = paths.size ();
|
||||
@@ -98,13 +95,14 @@ Editor::embed_audio_from_video (std::string path, framepos_t n)
|
||||
boost::shared_ptr<ARDOUR::Track> track;
|
||||
bool ok = (import_sndfiles (paths, Editing::ImportDistinctFiles, Editing::ImportAsTrack, ARDOUR::SrcBest, n, 1, 1, track, false) == 0);
|
||||
if (ok && track) {
|
||||
boost::shared_ptr<ARDOUR::Playlist> pl = track->playlist();
|
||||
pl->find_next_region(n, ARDOUR::End, 0)->set_video_locked(true);
|
||||
if (lock_position_to_video) {
|
||||
boost::shared_ptr<ARDOUR::Playlist> pl = track->playlist();
|
||||
pl->find_next_region(n, ARDOUR::End, 0)->set_video_locked(true);
|
||||
}
|
||||
_session->save_state ("");
|
||||
}
|
||||
|
||||
import_status.all_done = true;
|
||||
#endif
|
||||
unlink(path.c_str());
|
||||
}
|
||||
|
||||
|
||||
@@ -157,6 +157,8 @@ LevelMeterBase::update_meters ()
|
||||
(*i).meter->set (meter_deflect_ppm (peak + meter_lineup(0)));
|
||||
} else if (meter_type == MeterVU) {
|
||||
(*i).meter->set (meter_deflect_vu (peak + vu_standard() + meter_lineup(0)));
|
||||
} else if (meter_type == MeterK12) {
|
||||
(*i).meter->set (meter_deflect_k (peak, 12), meter_deflect_k(_meter->meter_level(n, MeterPeak), 12));
|
||||
} else if (meter_type == MeterK14) {
|
||||
(*i).meter->set (meter_deflect_k (peak, 14), meter_deflect_k(_meter->meter_level(n, MeterPeak), 14));
|
||||
} else if (meter_type == MeterK20) {
|
||||
@@ -320,6 +322,17 @@ LevelMeterBase::setup_meters (int len, int initial_width, int thin_width)
|
||||
c[6] = c[7] = 0xffff00ff;
|
||||
c[8] = c[9] = 0xff0000ff;
|
||||
break;
|
||||
case MeterK12:
|
||||
stp[0] = 115.0 * meter_deflect_k(-32, 12); //-20
|
||||
stp[1] = 115.0 * meter_deflect_k(-12, 12); // 0
|
||||
stp[2] = 115.0 * meter_deflect_k(-10, 12); // +2
|
||||
stp[3] = 115.0 * meter_deflect_k( -8, 12); // +4
|
||||
c[0] = c[1] = 0x008800ff;
|
||||
c[2] = c[3] = 0x00ff00ff;
|
||||
c[4] = c[5] = 0xffff00ff;
|
||||
c[6] = c[7] = 0xffff00ff;
|
||||
c[8] = c[9] = 0xff0000ff;
|
||||
break;
|
||||
case MeterIEC2BBC:
|
||||
c[0] = c[1] = c[2] = c[3] = c[4] = c[5] = c[6] = c[7] = c[8] = c[9] =
|
||||
ARDOUR_UI::config()->color_by_name ("meter color BBC");
|
||||
|
||||
@@ -101,6 +101,9 @@ ArdourMeter::meter_type_string (ARDOUR::MeterType mt)
|
||||
case MeterK14:
|
||||
return _("K14");
|
||||
break;
|
||||
case MeterK12:
|
||||
return _("K12");
|
||||
break;
|
||||
case MeterVU:
|
||||
return _("VU");
|
||||
break;
|
||||
@@ -199,6 +202,16 @@ static inline float mtr_col_and_fract(
|
||||
}
|
||||
fraction = meter_deflect_k (val, 14);
|
||||
break;
|
||||
case MeterK12:
|
||||
if (val >= -8.0) {
|
||||
cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); // red
|
||||
} else if (val >= -12.0) {
|
||||
cairo_set_source_rgb (cr, 0.8, 0.8, 0.0); // yellow
|
||||
} else {
|
||||
cairo_set_source_rgb (cr, 0.0, 1.0, 0.0); // green
|
||||
}
|
||||
fraction = meter_deflect_k (val, 12);
|
||||
break;
|
||||
}
|
||||
return fraction;
|
||||
}
|
||||
@@ -226,6 +239,7 @@ static void set_bg_color(Gtk::Widget& w, cairo_t* cr, MeterType type) {
|
||||
case MeterIEC1NOR:
|
||||
case MeterIEC2BBC:
|
||||
case MeterIEC2EBU:
|
||||
case MeterK12:
|
||||
case MeterK14:
|
||||
case MeterK20:
|
||||
if (rgba_p_from_style("meterstripPPM", &r, &g, &b, "bg")) {
|
||||
@@ -334,6 +348,20 @@ meter_render_ticks (Gtk::Widget& w, MeterType type, vector<ARDOUR::DataType> typ
|
||||
case DataType::AUDIO:
|
||||
|
||||
switch (type) {
|
||||
case MeterK12:
|
||||
points.insert (std::pair<float,float>(-52.0f, 1.0));
|
||||
points.insert (std::pair<float,float>(-42.0f, 1.0));
|
||||
points.insert (std::pair<float,float>(-32.0f, 1.0));
|
||||
points.insert (std::pair<float,float>(-22.0f, 1.0));
|
||||
points.insert (std::pair<float,float>(-18.0f, 1.0));
|
||||
points.insert (std::pair<float,float>(-15.0f, 1.0));
|
||||
points.insert (std::pair<float,float>(-12.0f, 1.0));
|
||||
points.insert (std::pair<float,float>( -9.0f, 1.0));
|
||||
points.insert (std::pair<float,float>( -8.0f, 0.8));
|
||||
points.insert (std::pair<float,float>( -6.0f, 1.0));
|
||||
points.insert (std::pair<float,float>( -3.0f, 1.0));
|
||||
points.insert (std::pair<float,float>( 0.0f, 1.0));
|
||||
break;
|
||||
case MeterK14:
|
||||
points.insert (std::pair<float,float>(-54.0f, 1.0));
|
||||
points.insert (std::pair<float,float>(-44.0f, 1.0));
|
||||
@@ -645,6 +673,20 @@ meter_render_metrics (Gtk::Widget& w, MeterType type, vector<DataType> types)
|
||||
case DataType::AUDIO:
|
||||
layout->set_attributes (audio_font_attributes);
|
||||
switch (type) {
|
||||
case MeterK12:
|
||||
overlay_midi = 0;
|
||||
points.insert (std::pair<float,string>(-52.0f, "-40"));
|
||||
points.insert (std::pair<float,string>(-42.0f, "-30"));
|
||||
points.insert (std::pair<float,string>(-32.0f, "-20"));
|
||||
points.insert (std::pair<float,string>(-22.0f, "-10"));
|
||||
points.insert (std::pair<float,string>(-18.0f, "-6"));
|
||||
points.insert (std::pair<float,string>(-15.0f, "-3"));
|
||||
points.insert (std::pair<float,string>(-12.0f, " 0"));
|
||||
points.insert (std::pair<float,string>( -9.0f, "+3"));
|
||||
points.insert (std::pair<float,string>( -6.0f, "+6"));
|
||||
points.insert (std::pair<float,string>( -3.0f, "+9"));
|
||||
points.insert (std::pair<float,string>( 0.0f, "+12"));
|
||||
break;
|
||||
case MeterK14:
|
||||
overlay_midi = 0;
|
||||
points.insert (std::pair<float,string>(-54.0f, "-40"));
|
||||
@@ -903,6 +945,9 @@ meter_render_metrics (Gtk::Widget& w, MeterType type, vector<DataType> types)
|
||||
case MeterK14:
|
||||
layout->set_text("K14");
|
||||
break;
|
||||
case MeterK12:
|
||||
layout->set_text("K12");
|
||||
break;
|
||||
default:
|
||||
case MeterPeak:
|
||||
case MeterKrms:
|
||||
|
||||
@@ -562,6 +562,7 @@ MeterStrip::update_background(MeterType type)
|
||||
case MeterIEC1NOR:
|
||||
case MeterIEC2BBC:
|
||||
case MeterIEC2EBU:
|
||||
case MeterK12:
|
||||
case MeterK14:
|
||||
case MeterK20:
|
||||
mtr_container.set_name ("meterstripPPM");
|
||||
@@ -747,6 +748,7 @@ MeterStrip::popup_level_meter_menu (GdkEventButton* ev)
|
||||
add_level_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC2EBU), MeterIEC2EBU);
|
||||
add_level_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterK20), MeterK20);
|
||||
add_level_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterK14), MeterK14);
|
||||
add_level_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterK12), MeterK12);
|
||||
add_level_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterVU), MeterVU);
|
||||
|
||||
MeterType cmt = _route->meter_type();
|
||||
|
||||
@@ -2141,6 +2141,7 @@ MixerStrip::popup_level_meter_menu (GdkEventButton* ev)
|
||||
add_level_meter_item_type (items, tgroup, ArdourMeter::meter_type_string(MeterIEC2EBU), MeterIEC2EBU);
|
||||
add_level_meter_item_type (items, tgroup, ArdourMeter::meter_type_string(MeterK20), MeterK20);
|
||||
add_level_meter_item_type (items, tgroup, ArdourMeter::meter_type_string(MeterK14), MeterK14);
|
||||
add_level_meter_item_type (items, tgroup, ArdourMeter::meter_type_string(MeterK12), MeterK12);
|
||||
add_level_meter_item_type (items, tgroup, ArdourMeter::meter_type_string(MeterVU), MeterVU);
|
||||
|
||||
int _strip_type;
|
||||
|
||||
@@ -438,7 +438,7 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp
|
||||
ardour->add_bundle (ltc);
|
||||
}
|
||||
|
||||
/* Ardour's surfaces */
|
||||
/* Ardour's control surfaces */
|
||||
|
||||
ControlProtocolManager& m = ControlProtocolManager::instance ();
|
||||
for (list<ControlProtocolInfo*>::iterator i = m.control_protocol_info.begin(); i != m.control_protocol_info.end(); ++i) {
|
||||
|
||||
@@ -295,7 +295,7 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible, publi
|
||||
virtual void set_xjadeo_sensitive (bool onoff) = 0;
|
||||
virtual int get_videotl_bar_height () const = 0;
|
||||
virtual void set_video_timeline_height (const int h) = 0;
|
||||
virtual void embed_audio_from_video (std::string, framepos_t n = 0) = 0;
|
||||
virtual void embed_audio_from_video (std::string, framepos_t n = 0, bool lock_position_to_video = true) = 0;
|
||||
virtual void export_video (bool range = false) = 0;
|
||||
|
||||
virtual RouteTimeAxisView* get_route_view_by_route_id (const PBD::ID& id) const = 0;
|
||||
|
||||
@@ -648,6 +648,7 @@ class ControlSurfacesOptions : public OptionEditorBox
|
||||
public:
|
||||
ControlSurfacesOptions (Gtk::Window& parent)
|
||||
: _parent (parent)
|
||||
, _ignore_view_change (0)
|
||||
{
|
||||
_store = ListStore::create (_model);
|
||||
_view.set_model (_store);
|
||||
@@ -700,9 +701,14 @@ private:
|
||||
void protocol_status_changed (ControlProtocolInfo* cpi) {
|
||||
/* find the row */
|
||||
TreeModel::Children rows = _store->children();
|
||||
|
||||
for (TreeModel::Children::iterator x = rows.begin(); x != rows.end(); ++x) {
|
||||
string n = ((*x)[_model.name]);
|
||||
|
||||
if ((*x)[_model.protocol_info] == cpi) {
|
||||
_ignore_view_change++;
|
||||
(*x)[_model.enabled] = (cpi->protocol || cpi->requested);
|
||||
_ignore_view_change--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -712,6 +718,10 @@ private:
|
||||
{
|
||||
TreeModel::Row r = *i;
|
||||
|
||||
if (_ignore_view_change) {
|
||||
return;
|
||||
}
|
||||
|
||||
ControlProtocolInfo* cpi = r[_model.protocol_info];
|
||||
if (!cpi) {
|
||||
return;
|
||||
@@ -720,22 +730,23 @@ private:
|
||||
bool const was_enabled = (cpi->protocol != 0);
|
||||
bool const is_enabled = r[_model.enabled];
|
||||
|
||||
|
||||
if (was_enabled != is_enabled) {
|
||||
|
||||
if (!was_enabled) {
|
||||
ControlProtocolManager::instance().instantiate (*cpi);
|
||||
ControlProtocolManager::instance().activate (*cpi);
|
||||
} else {
|
||||
Gtk::Window* win = r[_model.editor];
|
||||
if (win) {
|
||||
win->hide ();
|
||||
}
|
||||
|
||||
ControlProtocolManager::instance().teardown (*cpi);
|
||||
ControlProtocolManager::instance().deactivate (*cpi);
|
||||
|
||||
if (win) {
|
||||
delete win;
|
||||
r[_model.editor] = 0;
|
||||
}
|
||||
r[_model.editor] = 0;
|
||||
cpi->requested = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -805,6 +816,7 @@ private:
|
||||
TreeView _view;
|
||||
Gtk::Window& _parent;
|
||||
PBD::ScopedConnection protocol_status_connection;
|
||||
uint32_t _ignore_view_change;
|
||||
};
|
||||
|
||||
class VideoTimelineOptions : public OptionEditorBox
|
||||
|
||||
@@ -357,14 +357,17 @@ def build(bld):
|
||||
if bld.is_defined('WINDOWS_VST_SUPPORT'):
|
||||
# If we require VST support we build a stub main() and the FST library
|
||||
# here using winegcc, and link it to the GTK front-end library
|
||||
obj = bld(features = 'cxx c cxxprogram wine')
|
||||
obj.source = '''
|
||||
../libs/fst/fst.c
|
||||
../libs/fst/fstinfofile.c
|
||||
../libs/fst/vsti.c
|
||||
../libs/fst/vstwin.c
|
||||
../vst/winmain.c
|
||||
'''
|
||||
obj = bld (features = 'cxx c cxxprogram wine')
|
||||
obj.source = (
|
||||
'../libs/fst/fst.c',
|
||||
'../libs/fst/fstinfofile.c',
|
||||
'../libs/fst/vsti.c',
|
||||
'../libs/fst/vstwin.c',
|
||||
'../vst/winmain.c',
|
||||
)
|
||||
#
|
||||
# XXX do we really need to explicitly link to all of these for the wine executable?
|
||||
#
|
||||
obj.use = [ 'libpbd',
|
||||
'libmidipp',
|
||||
'libardour',
|
||||
@@ -390,19 +393,22 @@ def build(bld):
|
||||
obj.target = 'gtk2_ardour'
|
||||
else:
|
||||
# just the normal executable version of the GTK GUI
|
||||
obj = bld(features = 'cxx c cxxprogram')
|
||||
obj = bld (features = 'cxx c cxxprogram')
|
||||
obj.source = gtk2_ardour_sources
|
||||
obj.target = 'ardour-' + bld.env['VERSION']
|
||||
obj.includes = ['.']
|
||||
obj.use = [ 'libpbd',
|
||||
'libardour',
|
||||
'libardour_cp',
|
||||
'libtimecode',
|
||||
'libmidipp',
|
||||
'libgtk2_ardour',
|
||||
'libgtkmm2ext',
|
||||
'libcanvas',
|
||||
]
|
||||
|
||||
# at this point, "obj" refers to either the normal native executable
|
||||
# OR the shared library built for use with wine on linux.
|
||||
|
||||
obj.use = [ 'libpbd',
|
||||
'libardour',
|
||||
'libardour_cp',
|
||||
'libtimecode',
|
||||
'libmidipp',
|
||||
'libgtkmm2ext',
|
||||
'libcanvas',
|
||||
]
|
||||
|
||||
# continue with setup of obj, which could be a shared library
|
||||
# or an executable.
|
||||
@@ -415,7 +421,7 @@ def build(bld):
|
||||
if bld.is_defined('USE_EXTERNAL_LIBS'):
|
||||
obj.uselib += ' TAGLIB'
|
||||
else:
|
||||
obj.use.append('libtaglib')
|
||||
obj.use += ('libtaglib')
|
||||
if sys.platform == 'darwin':
|
||||
obj.uselib += ' AUDIOUNITS OSX GTKOSX'
|
||||
obj.use += ' libappleutility'
|
||||
|
||||
@@ -65,8 +65,8 @@ class ControlProtocolManager : public PBD::Stateful, public ARDOUR::SessionHandl
|
||||
void load_mandatory_protocols ();
|
||||
void midi_connectivity_established ();
|
||||
|
||||
ControlProtocol* instantiate (ControlProtocolInfo&);
|
||||
int teardown (ControlProtocolInfo&);
|
||||
int activate (ControlProtocolInfo&);
|
||||
int deactivate (ControlProtocolInfo&);
|
||||
|
||||
std::list<ControlProtocolInfo*> control_protocol_info;
|
||||
|
||||
@@ -89,6 +89,8 @@ class ControlProtocolManager : public PBD::Stateful, public ARDOUR::SessionHandl
|
||||
int control_protocol_discover (std::string path);
|
||||
ControlProtocolDescriptor* get_descriptor (std::string path);
|
||||
ControlProtocolInfo* cpi_by_name (std::string);
|
||||
ControlProtocol* instantiate (ControlProtocolInfo&);
|
||||
int teardown (ControlProtocolInfo&);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -183,12 +183,14 @@ class Slave {
|
||||
class ISlaveSessionProxy {
|
||||
public:
|
||||
virtual ~ISlaveSessionProxy() {}
|
||||
virtual TempoMap& tempo_map() const { return *((TempoMap *) 0); }
|
||||
virtual framecnt_t frame_rate() const { return 0; }
|
||||
virtual framepos_t audible_frame () const { return 0; }
|
||||
virtual framepos_t transport_frame () const { return 0; }
|
||||
virtual pframes_t frames_since_cycle_start () const { return 0; }
|
||||
virtual framepos_t frame_time () const { return 0; }
|
||||
virtual TempoMap& tempo_map() const { return *((TempoMap *) 0); }
|
||||
virtual framecnt_t frame_rate() const { return 0; }
|
||||
virtual pframes_t frames_per_cycle() const { return 0; }
|
||||
virtual framepos_t audible_frame () const { return 0; }
|
||||
virtual framepos_t transport_frame () const { return 0; }
|
||||
virtual pframes_t frames_since_cycle_start () const { return 0; }
|
||||
virtual pframes_t sample_time_at_cycle_start() const { return 0; }
|
||||
virtual framepos_t frame_time () const { return 0; }
|
||||
|
||||
virtual void request_locate (framepos_t /*frame*/, bool with_roll = false) {
|
||||
(void) with_roll;
|
||||
@@ -204,12 +206,14 @@ class SlaveSessionProxy : public ISlaveSessionProxy {
|
||||
public:
|
||||
SlaveSessionProxy(Session &s) : session(s) {}
|
||||
|
||||
TempoMap& tempo_map() const;
|
||||
framecnt_t frame_rate() const;
|
||||
framepos_t audible_frame () const;
|
||||
framepos_t transport_frame () const;
|
||||
pframes_t frames_since_cycle_start () const;
|
||||
framepos_t frame_time () const;
|
||||
TempoMap& tempo_map() const;
|
||||
framecnt_t frame_rate() const;
|
||||
pframes_t frames_per_cycle() const;
|
||||
framepos_t audible_frame () const;
|
||||
framepos_t transport_frame () const;
|
||||
pframes_t frames_since_cycle_start () const;
|
||||
pframes_t sample_time_at_cycle_start() const;
|
||||
framepos_t frame_time () const;
|
||||
|
||||
void request_locate (framepos_t frame, bool with_roll = false);
|
||||
void request_transport_speed (double speed);
|
||||
|
||||
@@ -187,7 +187,8 @@ namespace ARDOUR {
|
||||
MeterIEC1NOR = 0x080,
|
||||
MeterIEC2BBC = 0x100,
|
||||
MeterIEC2EBU = 0x200,
|
||||
MeterVU = 0x400
|
||||
MeterVU = 0x400,
|
||||
MeterK12 = 0x800
|
||||
};
|
||||
|
||||
enum TrackMode {
|
||||
|
||||
@@ -72,26 +72,54 @@ ControlProtocolManager::set_session (Session* s)
|
||||
|
||||
for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
|
||||
if ((*i)->requested || (*i)->mandatory) {
|
||||
|
||||
instantiate (**i);
|
||||
(*i)->requested = false;
|
||||
|
||||
if ((*i)->protocol) {
|
||||
if ((*i)->state) {
|
||||
(*i)->protocol->set_state (*(*i)->state, Stateful::loading_state_version);
|
||||
} else {
|
||||
/* guarantee a call to
|
||||
set_state() whether we have
|
||||
existing state or not
|
||||
*/
|
||||
(*i)->protocol->set_state (XMLNode(""), Stateful::loading_state_version);
|
||||
}
|
||||
}
|
||||
(void) activate (**i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ControlProtocolManager::activate (ControlProtocolInfo& cpi)
|
||||
{
|
||||
ControlProtocol* cp;
|
||||
|
||||
cpi.requested = true;
|
||||
|
||||
if ((cp = instantiate (cpi)) == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* we split the set_state() and set_active() operations so that
|
||||
protocols that need state to configure themselves (e.g. "What device
|
||||
is connected, or supposed to be connected?") can get it before
|
||||
actually starting any interaction.
|
||||
*/
|
||||
|
||||
if (cpi.state) {
|
||||
/* force this by tweaking the internals of the state
|
||||
* XMLNode. Ugh.
|
||||
*/
|
||||
cp->set_state (*cpi.state, Stateful::loading_state_version);
|
||||
} else {
|
||||
/* guarantee a call to
|
||||
set_state() whether we have
|
||||
existing state or not
|
||||
*/
|
||||
cp->set_state (XMLNode(""), Stateful::loading_state_version);
|
||||
}
|
||||
|
||||
cp->set_active (true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ControlProtocolManager::deactivate (ControlProtocolInfo& cpi)
|
||||
{
|
||||
cpi.requested = false;
|
||||
return teardown (cpi);
|
||||
}
|
||||
|
||||
void
|
||||
ControlProtocolManager::session_going_away()
|
||||
{
|
||||
@@ -163,6 +191,12 @@ ControlProtocolManager::teardown (ControlProtocolInfo& cpi)
|
||||
if (cpi.mandatory) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* save current state */
|
||||
|
||||
delete cpi.state;
|
||||
cpi.state = new XMLNode (cpi.protocol->get_state());
|
||||
cpi.state->add_property (X_("active"), "no");
|
||||
|
||||
cpi.descriptor->destroy (cpi.descriptor, cpi.protocol);
|
||||
|
||||
@@ -177,8 +211,6 @@ ControlProtocolManager::teardown (ControlProtocolInfo& cpi)
|
||||
}
|
||||
|
||||
cpi.protocol = 0;
|
||||
delete cpi.state;
|
||||
cpi.state = 0;
|
||||
dlclose (cpi.descriptor->module);
|
||||
|
||||
ProtocolStatusChange (&cpi);
|
||||
@@ -379,22 +411,21 @@ ControlProtocolManager::get_state ()
|
||||
|
||||
for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
|
||||
|
||||
XMLNode * child;
|
||||
|
||||
if ((*i)->protocol) {
|
||||
child = &((*i)->protocol->get_state());
|
||||
child->add_property (X_("active"), "yes");
|
||||
// should we update (*i)->state here? probably.
|
||||
root->add_child_nocopy (*child);
|
||||
XMLNode& child_state ((*i)->protocol->get_state());
|
||||
child_state.add_property (X_("active"), "yes");
|
||||
root->add_child_nocopy (child_state);
|
||||
} else if ((*i)->state) {
|
||||
// keep ownership clear
|
||||
root->add_child_copy (*(*i)->state);
|
||||
XMLNode* child_state = new XMLNode (*(*i)->state);
|
||||
child_state->add_property (X_("active"), "no");
|
||||
root->add_child_nocopy (*child_state);
|
||||
} else {
|
||||
child = new XMLNode (X_("Protocol"));
|
||||
child->add_property (X_("name"), (*i)->name);
|
||||
child->add_property (X_("active"), "no");
|
||||
root->add_child_nocopy (*child);
|
||||
XMLNode* child_state = new XMLNode (X_("Protocol"));
|
||||
child_state->add_property (X_("name"), (*i)->name);
|
||||
child_state->add_property (X_("active"), "no");
|
||||
root->add_child_nocopy (*child_state);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return *root;
|
||||
|
||||
@@ -179,6 +179,7 @@ setup_enum_writer ()
|
||||
REGISTER_ENUM (MeterKrms);
|
||||
REGISTER_ENUM (MeterK20);
|
||||
REGISTER_ENUM (MeterK14);
|
||||
REGISTER_ENUM (MeterK12);
|
||||
REGISTER_ENUM (MeterIEC1DIN);
|
||||
REGISTER_ENUM (MeterIEC1NOR);
|
||||
REGISTER_ENUM (MeterIEC2BBC);
|
||||
|
||||
@@ -108,7 +108,7 @@ PeakMeter::run (BufferSet& bufs, framepos_t /*start_frame*/, framepos_t /*end_fr
|
||||
// Meter audio in to the rest of the peaks
|
||||
for (uint32_t i = 0; i < n_audio; ++i, ++n) {
|
||||
_peak_signal[n] = compute_peak (bufs.get_audio(i).data(), nframes, _peak_signal[n]);
|
||||
if (_meter_type & (MeterKrms | MeterK20 | MeterK14)) {
|
||||
if (_meter_type & (MeterKrms | MeterK20 | MeterK14 | MeterK12)) {
|
||||
_kmeter[i]->process(bufs.get_audio(i).data(), nframes);
|
||||
}
|
||||
if (_meter_type & (MeterIEC1DIN | MeterIEC1NOR)) {
|
||||
@@ -288,7 +288,7 @@ PeakMeter::meter ()
|
||||
/* 0.01f ^= 100 Hz update rate */
|
||||
const float midi_meter_falloff = Config->get_meter_falloff() * 0.01f;
|
||||
/* kmeters: 24dB / 2 sec */
|
||||
const float audio_meter_falloff = (_meter_type & (MeterK20 | MeterK14)) ? 0.12f : midi_meter_falloff;
|
||||
const float audio_meter_falloff = (_meter_type & (MeterK20 | MeterK14 | MeterK12)) ? 0.12f : midi_meter_falloff;
|
||||
|
||||
for (size_t n = 0; n < limit; ++n) {
|
||||
|
||||
@@ -345,6 +345,7 @@ PeakMeter::meter_level(uint32_t n, MeterType type) {
|
||||
case MeterKrms:
|
||||
case MeterK20:
|
||||
case MeterK14:
|
||||
case MeterK12:
|
||||
{
|
||||
const uint32_t n_midi = current_meters.n_midi();
|
||||
if (CHECKSIZE(_kmeter)) {
|
||||
@@ -404,7 +405,7 @@ PeakMeter::set_type(MeterType t)
|
||||
|
||||
_meter_type = t;
|
||||
|
||||
if (t & (MeterKrms | MeterK20 | MeterK14)) {
|
||||
if (t & (MeterKrms | MeterK20 | MeterK14 | MeterK12)) {
|
||||
const size_t n_audio = current_meters.n_audio();
|
||||
for (size_t n = 0; n < n_audio; ++n) {
|
||||
_kmeter[n]->reset();
|
||||
|
||||
@@ -45,7 +45,7 @@ using namespace PBD;
|
||||
|
||||
MIDIClock_Slave::MIDIClock_Slave (Session& s, MidiPort& p, int ppqn)
|
||||
: ppqn (ppqn)
|
||||
, bandwidth (10.0 / 60.0) // 1 BpM = 1 / 60 Hz
|
||||
, bandwidth (2.0 / 60.0) // 1 BpM = 1 / 60 Hz
|
||||
{
|
||||
session = (ISlaveSessionProxy *) new SlaveSessionProxy(s);
|
||||
rebind (p);
|
||||
@@ -55,7 +55,7 @@ MIDIClock_Slave::MIDIClock_Slave (Session& s, MidiPort& p, int ppqn)
|
||||
MIDIClock_Slave::MIDIClock_Slave (ISlaveSessionProxy* session_proxy, int ppqn)
|
||||
: session(session_proxy)
|
||||
, ppqn (ppqn)
|
||||
, bandwidth (10.0 / 60.0) // 1 BpM = 1 / 60 Hz
|
||||
, bandwidth (2.0 / 60.0) // 1 BpM = 1 / 60 Hz
|
||||
{
|
||||
reset ();
|
||||
}
|
||||
@@ -123,6 +123,8 @@ MIDIClock_Slave::update_midi_clock (Parser& /*parser*/, framepos_t timestamp)
|
||||
return;
|
||||
}
|
||||
|
||||
pframes_t cycle_offset = timestamp - session->sample_time_at_cycle_start();
|
||||
|
||||
calculate_one_ppqn_in_frames_at(should_be_position);
|
||||
|
||||
framepos_t elapsed_since_start = timestamp - first_timestamp;
|
||||
@@ -134,6 +136,8 @@ MIDIClock_Slave::update_midi_clock (Parser& /*parser*/, framepos_t timestamp)
|
||||
first_timestamp = timestamp;
|
||||
elapsed_since_start = should_be_position;
|
||||
|
||||
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("first clock message after start received @ %1\n", timestamp));
|
||||
|
||||
// calculate filter coefficients
|
||||
calculate_filter_coefficients();
|
||||
|
||||
@@ -153,7 +157,7 @@ MIDIClock_Slave::update_midi_clock (Parser& /*parser*/, framepos_t timestamp)
|
||||
// we use session->transport_frame() instead of t1 here
|
||||
// because t1 is used to calculate the transport speed,
|
||||
// so the loop will compensate for accumulating rounding errors
|
||||
error = (double(should_be_position) - double(session->transport_frame()));
|
||||
error = (double(should_be_position) - (double(session->transport_frame()) + double(cycle_offset)));
|
||||
e = error / double(session->frame_rate());
|
||||
current_delta = error;
|
||||
|
||||
@@ -163,21 +167,23 @@ MIDIClock_Slave::update_midi_clock (Parser& /*parser*/, framepos_t timestamp)
|
||||
e2 += c * e;
|
||||
}
|
||||
|
||||
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("clock #%1 @ %2 arrived %3 (theoretical) audible %4 transport %5 error %6 "
|
||||
"read delta %7 should-be delta %8 t1-t0 %9 t0 %10 t1 %11 framerate %12 appspeed %13\n",
|
||||
midi_clock_count,
|
||||
elapsed_since_start,
|
||||
should_be_position,
|
||||
session->audible_frame(),
|
||||
session->transport_frame(),
|
||||
error,
|
||||
timestamp - last_timestamp,
|
||||
one_ppqn_in_frames,
|
||||
(t1 -t0) * session->frame_rate(),
|
||||
t0 * session->frame_rate(),
|
||||
t1 * session->frame_rate(),
|
||||
session->frame_rate(),
|
||||
((t1 - t0) * session->frame_rate()) / one_ppqn_in_frames));
|
||||
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("clock #%1 @ %2 should-be %3 transport %4 error %5 appspeed %6 "
|
||||
"read-delta %7 should-be delta %8 t1-t0 %9 t0 %10 t1 %11 framerate %12 engine %13\n",
|
||||
midi_clock_count, // #
|
||||
elapsed_since_start, // @
|
||||
should_be_position, // should-be
|
||||
session->transport_frame(), // transport
|
||||
error, // error
|
||||
((t1 - t0) * session->frame_rate()) / one_ppqn_in_frames, // appspeed
|
||||
timestamp - last_timestamp, // read delta
|
||||
one_ppqn_in_frames, // should-be delta
|
||||
(t1 - t0) * session->frame_rate(), // t1-t0
|
||||
t0 * session->frame_rate(), // t0
|
||||
t1 * session->frame_rate(), // t1
|
||||
session->frame_rate(), // framerate
|
||||
session->frame_time()
|
||||
|
||||
));
|
||||
|
||||
last_timestamp = timestamp;
|
||||
}
|
||||
@@ -185,7 +191,7 @@ MIDIClock_Slave::update_midi_clock (Parser& /*parser*/, framepos_t timestamp)
|
||||
void
|
||||
MIDIClock_Slave::start (Parser& /*parser*/, framepos_t timestamp)
|
||||
{
|
||||
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("MIDIClock_Slave got start message at time %1 engine time %2\n", timestamp, session->frame_time()));
|
||||
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("MIDIClock_Slave got start message at time %1 engine time %2 transport_frame %3\n", timestamp, session->frame_time(), session->transport_frame()));
|
||||
|
||||
if (!_started) {
|
||||
reset();
|
||||
@@ -200,6 +206,8 @@ MIDIClock_Slave::start (Parser& /*parser*/, framepos_t timestamp)
|
||||
void
|
||||
MIDIClock_Slave::reset ()
|
||||
{
|
||||
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("MidiClock_Slave reset(): calculated filter bandwidth is %1 for period size %2\n", bandwidth, session->frames_per_cycle()));
|
||||
|
||||
should_be_position = session->transport_frame();
|
||||
last_timestamp = 0;
|
||||
|
||||
@@ -345,7 +353,7 @@ MIDIClock_Slave::speed_and_position (double& speed, framepos_t& pos)
|
||||
pos = should_be_position;
|
||||
}
|
||||
|
||||
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("speed_and_position: %1 & %2 <-> %3 (transport)\n", speed, pos, session->transport_frame()));
|
||||
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("speed_and_position: speed %1 should-be %2 transport %3 \n", speed, pos, session->transport_frame()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -61,6 +61,8 @@ MidiControlUI::do_request (MidiUIRequest* req)
|
||||
{
|
||||
if (req->type == Quit) {
|
||||
BaseUI::quit ();
|
||||
} else if (req->type == CallSlot) {
|
||||
req->the_slot ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,12 @@ SlaveSessionProxy::frame_rate() const
|
||||
return session.frame_rate();
|
||||
}
|
||||
|
||||
pframes_t
|
||||
SlaveSessionProxy::frames_per_cycle() const
|
||||
{
|
||||
return session.engine().samples_per_cycle();
|
||||
}
|
||||
|
||||
framepos_t
|
||||
SlaveSessionProxy::audible_frame() const
|
||||
{
|
||||
@@ -53,6 +59,13 @@ SlaveSessionProxy::frames_since_cycle_start() const
|
||||
return session.engine().samples_since_cycle_start();
|
||||
}
|
||||
|
||||
pframes_t
|
||||
SlaveSessionProxy::sample_time_at_cycle_start() const
|
||||
{
|
||||
return session.engine().sample_time_at_cycle_start();
|
||||
}
|
||||
|
||||
|
||||
framepos_t
|
||||
SlaveSessionProxy::frame_time() const
|
||||
{
|
||||
|
||||
@@ -106,6 +106,7 @@ InterpolationTest::cubicInterpolationTest ()
|
||||
cubic.set_speed (1.0);
|
||||
cubic.set_target_speed (cubic.speed());
|
||||
result = cubic.interpolate (0, NUM_SAMPLES, input, output);
|
||||
CPPUNIT_ASSERT_EQUAL (result, cubic.interpolate (0, NUM_SAMPLES, NULL, NULL));
|
||||
CPPUNIT_ASSERT_EQUAL ((framecnt_t)(NUM_SAMPLES * cubic.speed()), result);
|
||||
for (int i = 0; i < NUM_SAMPLES; i += INTERVAL) {
|
||||
CPPUNIT_ASSERT_EQUAL (1.0f, output[i]);
|
||||
@@ -116,6 +117,7 @@ InterpolationTest::cubicInterpolationTest ()
|
||||
cubic.set_speed (0.5);
|
||||
cubic.set_target_speed (cubic.speed());
|
||||
result = cubic.interpolate (0, NUM_SAMPLES, input, output);
|
||||
CPPUNIT_ASSERT_EQUAL (result, cubic.interpolate (0, NUM_SAMPLES, NULL, NULL));
|
||||
CPPUNIT_ASSERT_EQUAL ((framecnt_t)(NUM_SAMPLES * cubic.speed()), result);
|
||||
for (int i = 0; i < NUM_SAMPLES; i += (INTERVAL / cubic.speed() +0.5)) {
|
||||
CPPUNIT_ASSERT_EQUAL (1.0f, output[i]);
|
||||
@@ -126,6 +128,7 @@ InterpolationTest::cubicInterpolationTest ()
|
||||
cubic.set_speed (0.2);
|
||||
cubic.set_target_speed (cubic.speed());
|
||||
result = cubic.interpolate (0, NUM_SAMPLES, input, output);
|
||||
CPPUNIT_ASSERT_EQUAL (result, cubic.interpolate (0, NUM_SAMPLES, NULL, NULL));
|
||||
CPPUNIT_ASSERT_EQUAL ((framecnt_t)(NUM_SAMPLES * cubic.speed()), result);
|
||||
|
||||
// cout << "\nSpeed: 0.02";
|
||||
@@ -133,6 +136,7 @@ InterpolationTest::cubicInterpolationTest ()
|
||||
cubic.set_speed (0.02);
|
||||
cubic.set_target_speed (cubic.speed());
|
||||
result = cubic.interpolate (0, NUM_SAMPLES, input, output);
|
||||
CPPUNIT_ASSERT_EQUAL (result, cubic.interpolate (0, NUM_SAMPLES, NULL, NULL));
|
||||
CPPUNIT_ASSERT_EQUAL ((framecnt_t)(NUM_SAMPLES * cubic.speed()), result);
|
||||
|
||||
/* This one fails due too error accumulation
|
||||
@@ -150,6 +154,7 @@ InterpolationTest::cubicInterpolationTest ()
|
||||
cubic.set_speed (2.0);
|
||||
cubic.set_target_speed (cubic.speed());
|
||||
result = cubic.interpolate (0, NUM_SAMPLES / 2, input, output);
|
||||
CPPUNIT_ASSERT_EQUAL (result, cubic.interpolate (0, NUM_SAMPLES / 2, NULL, NULL));
|
||||
CPPUNIT_ASSERT_EQUAL ((framecnt_t)(NUM_SAMPLES / 2 * cubic.speed()), result);
|
||||
for (int i = 0; i < NUM_SAMPLES / 2; i += (INTERVAL / cubic.speed() +0.5)) {
|
||||
CPPUNIT_ASSERT_EQUAL (1.0f, output[i]);
|
||||
@@ -159,6 +164,7 @@ InterpolationTest::cubicInterpolationTest ()
|
||||
cubic.set_speed (10.0);
|
||||
cubic.set_target_speed (cubic.speed());
|
||||
result = cubic.interpolate (0, NUM_SAMPLES / 10, input, output);
|
||||
CPPUNIT_ASSERT_EQUAL (result, cubic.interpolate (0, NUM_SAMPLES / 10, NULL, NULL));
|
||||
CPPUNIT_ASSERT_EQUAL ((framecnt_t)(NUM_SAMPLES / 10 * cubic.speed()), result);
|
||||
for (int i = 0; i < NUM_SAMPLES / 10; i += (INTERVAL / cubic.speed() +0.5)) {
|
||||
CPPUNIT_ASSERT_EQUAL (1.0f, output[i]);
|
||||
|
||||
@@ -86,16 +86,18 @@ Canvas::render (Rect const & area, Cairo::RefPtr<Cairo::Context> const & context
|
||||
|
||||
boost::optional<Rect> draw = root_bbox->intersection (area);
|
||||
if (draw) {
|
||||
|
||||
// context->rectangle (area.x0, area.y0, area.x1 - area.x0, area.y1 - area.y0);
|
||||
// context->set_source_rgba (1.0, 0, 0, 1.0);
|
||||
// context->fill ();
|
||||
|
||||
|
||||
/* there's a common area between the root and the requested
|
||||
area, so render it.
|
||||
*/
|
||||
|
||||
_root.render (*draw, context);
|
||||
|
||||
// This outlines the rect being rendered, after it has been drawn.
|
||||
// context->rectangle (draw->x0, draw->y0, draw->x1 - draw->x0, draw->y1 - draw->y0);
|
||||
// context->set_source_rgba (1.0, 0, 0, 1.0);
|
||||
// context->stroke ();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -704,7 +706,7 @@ void
|
||||
GtkCanvas::request_redraw (Rect const & request)
|
||||
{
|
||||
Rect area = canvas_to_window (request);
|
||||
queue_draw_area (floor (area.x0), floor (area.y0), ceil (area.width()), ceil (area.height()));
|
||||
queue_draw_area (area.x0, area.y0, area.width(), area.height());
|
||||
}
|
||||
|
||||
/** Called to request that we try to get a particular size for ourselves.
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
|
||||
/* LV2 */
|
||||
#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
|
||||
@@ -56,6 +57,7 @@ typedef struct {
|
||||
|
||||
double SampleRateD;
|
||||
void *synth;
|
||||
bool xmas;
|
||||
} RSynth;
|
||||
|
||||
/* main LV2 */
|
||||
@@ -98,6 +100,16 @@ instantiate(const LV2_Descriptor* descriptor,
|
||||
self->synth = synth_alloc();
|
||||
synth_init(self->synth, rate);
|
||||
|
||||
|
||||
struct tm date;
|
||||
time_t now;
|
||||
time(&now);
|
||||
localtime_r(&now, &date);
|
||||
if (getenv("ITSXMAS") || (date.tm_mon == 11 /*dec*/ && date.tm_mday == 25)) {
|
||||
printf("reasonable synth.lv2 says: happy holidays!\n");
|
||||
self->xmas = true;
|
||||
}
|
||||
|
||||
return (LV2_Handle)self;
|
||||
}
|
||||
|
||||
@@ -146,7 +158,11 @@ run(LV2_Handle handle, uint32_t n_samples)
|
||||
written = synth_sound(self->synth, written, ev->time.frames, audio);
|
||||
}
|
||||
/* send midi message to synth */
|
||||
synth_parse_midi(self->synth, (const uint8_t*)(ev+1), ev->body.size);
|
||||
if (self->xmas) {
|
||||
synth_parse_xmas(self->synth, (const uint8_t*)(ev+1), ev->body.size);
|
||||
} else {
|
||||
synth_parse_midi(self->synth, (const uint8_t*)(ev+1), ev->body.size);
|
||||
}
|
||||
}
|
||||
ev = (LV2_Atom_Event const*) // lv2_atom_sequence_next()
|
||||
((const uint8_t*)ev + sizeof(LV2_Atom_Event) + ((ev->body.size + 7) & ~7));
|
||||
|
||||
@@ -71,6 +71,7 @@ typedef struct _RSSynthChannel {
|
||||
float adsr_amp[128];
|
||||
float phase[128]; // various use, zero'ed on note-on
|
||||
int8_t miditable[128]; // internal, note-on/off velocity
|
||||
int8_t midimsgs [128]; // internal, note-off + on in same cycle
|
||||
ADSRcfg adsr;
|
||||
void (*synthesize) (struct _RSSynthChannel* sc,
|
||||
const uint8_t note, const float vol, const float pc,
|
||||
@@ -89,6 +90,8 @@ typedef struct {
|
||||
float kcgain;
|
||||
float kcfilt;
|
||||
double rate;
|
||||
uint32_t xmas_on;
|
||||
uint32_t xmas_off;
|
||||
} RSSynthesizer;
|
||||
|
||||
|
||||
@@ -216,8 +219,10 @@ static void process_key (void *synth,
|
||||
RSSynthesizer* rs = (RSSynthesizer*)synth;
|
||||
RSSynthChannel* sc = &rs->sc[chn];
|
||||
const int8_t vel = sc->miditable[note];
|
||||
const int8_t msg = sc->midimsgs[note];
|
||||
const float vol = /* master_volume */ 0.25 * fabsf(vel) / 127.0;
|
||||
const float phase = sc->phase[note];
|
||||
sc->midimsgs[note] = 0;
|
||||
|
||||
if (phase == -10 && vel > 0) {
|
||||
// new note on
|
||||
@@ -230,7 +235,7 @@ static void process_key (void *synth,
|
||||
}
|
||||
else if (phase >= -1.0 && phase <= 1.0 && vel > 0) {
|
||||
// sustain note or re-start note while adsr in progress:
|
||||
if (sc->adsr_cnt[note] > sc->adsr.off[1]) {
|
||||
if (sc->adsr_cnt[note] > sc->adsr.off[1] || msg == 3) {
|
||||
// x-fade to attack
|
||||
sc->adsr_amp[note] = adsr_env(sc, note);
|
||||
sc->adsr_cnt[note] = 0;
|
||||
@@ -305,6 +310,7 @@ static void synth_reset_channel(RSSynthChannel* sc) {
|
||||
sc->adsr_amp[k] = 0;
|
||||
sc->phase[k] = -10;
|
||||
sc->miditable[k] = 0;
|
||||
sc->midimsgs[k] = 0;
|
||||
}
|
||||
sc->keycomp = 0;
|
||||
}
|
||||
@@ -336,10 +342,12 @@ static void synth_process_midi_event(void *synth, struct rmidi_event_t *ev) {
|
||||
RSSynthesizer* rs = (RSSynthesizer*)synth;
|
||||
switch(ev->type) {
|
||||
case NOTE_ON:
|
||||
rs->sc[ev->channel].midimsgs[ev->d.tone.note] |= 1;
|
||||
if (rs->sc[ev->channel].miditable[ev->d.tone.note] <= 0)
|
||||
rs->sc[ev->channel].miditable[ev->d.tone.note] = ev->d.tone.velocity;
|
||||
break;
|
||||
case NOTE_OFF:
|
||||
rs->sc[ev->channel].midimsgs[ev->d.tone.note] |= 2;
|
||||
if (rs->sc[ev->channel].miditable[ev->d.tone.note] > 0)
|
||||
rs->sc[ev->channel].miditable[ev->d.tone.note] *= -1.0;
|
||||
break;
|
||||
@@ -446,6 +454,44 @@ static void synth_parse_midi(void *synth, const uint8_t *data, const size_t size
|
||||
synth_process_midi_event(synth, &ev);
|
||||
}
|
||||
|
||||
static const uint8_t jingle[] = { 71 ,71 ,71 ,71 ,71 ,71 ,71 ,74 ,67 ,69 ,71 ,72 ,72 ,72 ,72 ,72 ,71 ,71 ,71 ,71 ,71 ,69 ,69 ,71 ,69 ,74 ,71 ,71 ,71 ,71 ,71 ,71 ,71 ,74 ,67 ,69 ,71 ,72 ,72 ,72 ,72 ,72 ,71 ,71 ,71 ,71 ,74 ,74 ,72 ,69 ,67 ,62 ,62 ,71 ,69 ,67 ,62 ,62 ,62 ,62 ,71 ,69 ,67 ,64 ,64 ,64 ,72 ,71 ,69 ,66 ,74 ,76 ,74 ,72 ,69 ,71 ,62 ,62 ,71 ,69 ,67 ,62 ,62 ,62 ,62 ,71 ,69 ,67 ,64 ,64 ,64 ,72 ,71 ,69 ,74 ,74 ,74 ,74 ,76 ,74 ,72 ,69 ,67 ,74 ,71 ,71 ,71 ,71 ,71 ,71 ,71 ,74 ,67 ,69 ,71 ,72 ,72 ,72 ,72 ,72 ,71 ,71 ,71 ,71 ,71 ,69 ,69 ,71 ,69 ,74 ,71 ,71 ,71 ,71 ,71 ,71 ,71 ,74 ,67 ,69 ,71 ,72 ,72 ,72 ,72 ,72 ,71 ,71 ,71 ,71 ,74 ,74 ,72 ,69 ,67 };
|
||||
|
||||
static void synth_parse_xmas(void *synth, const uint8_t *data, const size_t size) {
|
||||
RSSynthesizer* rs = (RSSynthesizer*)synth;
|
||||
if (size < 2 || size > 3) return;
|
||||
// All messages need to be 3 bytes; except program-changes: 2bytes.
|
||||
if (size == 2 && (data[0] & 0xf0) != 0xC0) return;
|
||||
|
||||
struct rmidi_event_t ev;
|
||||
|
||||
ev.channel = data[0]&0x0f;
|
||||
switch (data[0] & 0xf0) {
|
||||
case 0x80:
|
||||
ev.type=NOTE_OFF;
|
||||
ev.d.tone.note=jingle[rs->xmas_off++];
|
||||
ev.d.tone.velocity=data[2]&0x7f;
|
||||
if (rs->xmas_off >= sizeof(jingle)) rs->xmas_off = 0;
|
||||
break;
|
||||
case 0x90:
|
||||
ev.type=NOTE_ON;
|
||||
ev.d.tone.note=jingle[rs->xmas_on++];
|
||||
ev.d.tone.velocity=data[2]&0x7f;
|
||||
if (rs->xmas_on >= sizeof(jingle)) rs->xmas_on = 0;
|
||||
break;
|
||||
case 0xB0:
|
||||
ev.type=CONTROL_CHANGE;
|
||||
ev.d.control.param=data[1]&0x7f;
|
||||
ev.d.control.value=data[2]&0x7f;
|
||||
break;
|
||||
case 0xC0:
|
||||
ev.type=PROGRAM_CHANGE;
|
||||
ev.d.control.value=data[1]&0x7f;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
synth_process_midi_event(synth, &ev);
|
||||
}
|
||||
/**
|
||||
* initialize the synth
|
||||
* This should be called after synth_alloc()
|
||||
@@ -461,7 +507,7 @@ static void synth_init(void *synth, double rate) {
|
||||
const float tuning = 440;
|
||||
int c,k;
|
||||
for (k=0; k < 128; k++) {
|
||||
rs->freqs[k] = (2.0 * tuning / 32.0f) * powf(2, (k - 9.0) / 12.0) / rate;
|
||||
rs->freqs[k] = (tuning / 32.0f) * powf(2, (k - 9.0) / 12.0) / rate;
|
||||
assert(rs->freqs[k] < M_PI/2); // otherwise spatialization may phase out..
|
||||
}
|
||||
rs->kcfilt = 12.0 / rate;
|
||||
@@ -470,6 +516,8 @@ static void synth_init(void *synth, double rate) {
|
||||
for (c=0; c < 16; c++) {
|
||||
synth_load(&rs->sc[c], rate, &synthesize_sineP, &piano_adsr);
|
||||
}
|
||||
rs->xmas_on = 0;
|
||||
rs->xmas_off = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -53,6 +53,8 @@ PBD::Signal0<void> ControlProtocol::ClearRouteSelection;
|
||||
PBD::Signal0<void> ControlProtocol::StepTracksDown;
|
||||
PBD::Signal0<void> ControlProtocol::StepTracksUp;
|
||||
|
||||
const std::string ControlProtocol::state_node_name ("Protocol");
|
||||
|
||||
ControlProtocol::ControlProtocol (Session& s, string str)
|
||||
: BasicUI (s)
|
||||
, _name (str)
|
||||
@@ -64,6 +66,13 @@ ControlProtocol::~ControlProtocol ()
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
ControlProtocol::set_active (bool yn)
|
||||
{
|
||||
_active = yn;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ControlProtocol::next_track (uint32_t initial_id)
|
||||
{
|
||||
@@ -356,5 +365,15 @@ ControlProtocol:: route_get_name (uint32_t table_index)
|
||||
list<boost::shared_ptr<Bundle> >
|
||||
ControlProtocol::bundles ()
|
||||
{
|
||||
return list<boost::shared_ptr<Bundle> > ();
|
||||
return list<boost::shared_ptr<Bundle> > ();
|
||||
}
|
||||
|
||||
XMLNode&
|
||||
ControlProtocol::get_state ()
|
||||
{
|
||||
XMLNode* node = new XMLNode (state_node_name);
|
||||
|
||||
node->add_property ("name", _name);
|
||||
|
||||
return *node;
|
||||
}
|
||||
|
||||
@@ -47,8 +47,8 @@ class ControlProtocol : public PBD::Stateful, public PBD::ScopedConnectionList,
|
||||
|
||||
std::string name() const { return _name; }
|
||||
|
||||
virtual int set_active (bool yn) = 0;
|
||||
bool get_active() const { return _active; }
|
||||
virtual int set_active (bool yn);
|
||||
bool active() const { return _active; }
|
||||
|
||||
virtual int set_feedback (bool /*yn*/) { return 0; }
|
||||
virtual bool get_feedback () const { return false; }
|
||||
@@ -133,16 +133,19 @@ class ControlProtocol : public PBD::Stateful, public PBD::ScopedConnectionList,
|
||||
virtual void* get_gui() const { return 0; }
|
||||
virtual void tear_down_gui() { }
|
||||
|
||||
XMLNode& get_state ();
|
||||
static const std::string state_node_name;
|
||||
|
||||
protected:
|
||||
std::vector<boost::shared_ptr<ARDOUR::Route> > route_table;
|
||||
std::string _name;
|
||||
bool _active;
|
||||
|
||||
void next_track (uint32_t initial_id);
|
||||
void prev_track (uint32_t initial_id);
|
||||
|
||||
private:
|
||||
ControlProtocol (const ControlProtocol&); /* noncopyable */
|
||||
bool _active;
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
|
||||
@@ -1921,9 +1921,7 @@ TranzportControlProtocol::print_noretry (int row, int col, const char *text)
|
||||
XMLNode&
|
||||
TranzportControlProtocol::get_state ()
|
||||
{
|
||||
XMLNode* node = new XMLNode (X_("Protocol"));
|
||||
node->add_property (X_("name"), _name);
|
||||
return *node;
|
||||
return ControlProtocol::get_state();
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
@@ -80,16 +80,14 @@ GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
|
||||
Controllable::CreateBinding.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::create_binding, this, _1, _2, _3));
|
||||
Controllable::DeleteBinding.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::delete_binding, this, _1));
|
||||
|
||||
Session::SendFeedback.connect (*this, MISSING_INVALIDATOR, boost::bind (&GenericMidiControlProtocol::send_feedback, this), midi_ui_context());;
|
||||
#if 0
|
||||
/* XXXX SOMETHING GOES WRONG HERE (april 2012) - STILL DEBUGGING */
|
||||
/* this signal is emitted by the process() callback, and if
|
||||
* send_feedback() is going to do anything, it should do it in the
|
||||
* context of the process() callback itself.
|
||||
*/
|
||||
|
||||
Session::SendFeedback.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::send_feedback, this));
|
||||
#endif
|
||||
//Session::SendFeedback.connect (*this, MISSING_INVALIDATOR, boost::bind (&GenericMidiControlProtocol::send_feedback, this), midi_ui_context());;
|
||||
|
||||
/* this one is cross-thread */
|
||||
|
||||
Route::RemoteControlIDChange.connect (*this, MISSING_INVALIDATOR, boost::bind (&GenericMidiControlProtocol::reset_controllables, this), midi_ui_context());
|
||||
@@ -466,23 +464,22 @@ GenericMidiControlProtocol::create_binding (PBD::Controllable* control, int pos,
|
||||
XMLNode&
|
||||
GenericMidiControlProtocol::get_state ()
|
||||
{
|
||||
XMLNode* node = new XMLNode ("Protocol");
|
||||
XMLNode& node (ControlProtocol::get_state());
|
||||
char buf[32];
|
||||
|
||||
node->add_property (X_("name"), _name);
|
||||
node->add_property (X_("feedback"), do_feedback ? "1" : "0");
|
||||
node.add_property (X_("feedback"), do_feedback ? "1" : "0");
|
||||
snprintf (buf, sizeof (buf), "%" PRIu64, _feedback_interval);
|
||||
node->add_property (X_("feedback_interval"), buf);
|
||||
node.add_property (X_("feedback_interval"), buf);
|
||||
snprintf (buf, sizeof (buf), "%d", _threshold);
|
||||
node->add_property (X_("threshold"), buf);
|
||||
node.add_property (X_("threshold"), buf);
|
||||
|
||||
if (!_current_binding.empty()) {
|
||||
node->add_property ("binding", _current_binding);
|
||||
node.add_property ("binding", _current_binding);
|
||||
}
|
||||
|
||||
XMLNode* children = new XMLNode (X_("Controls"));
|
||||
|
||||
node->add_child_nocopy (*children);
|
||||
node.add_child_nocopy (*children);
|
||||
|
||||
Glib::Threads::Mutex::Lock lm2 (controllables_lock);
|
||||
for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
|
||||
@@ -497,7 +494,7 @@ GenericMidiControlProtocol::get_state ()
|
||||
}
|
||||
}
|
||||
|
||||
return *node;
|
||||
return node;
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
@@ -453,8 +453,6 @@ MackieControlProtocolGUI::action_changed (const Glib::ustring &sPath, const Glib
|
||||
return;
|
||||
}
|
||||
|
||||
cerr << "Changed to " << i->first << " aka " << i->second << endl;
|
||||
|
||||
Glib::RefPtr<Gtk::Action> act = ActionManager::get_action (i->second.c_str());
|
||||
|
||||
if (act) {
|
||||
@@ -504,8 +502,6 @@ MackieControlProtocolGUI::surface_combo_changed ()
|
||||
|
||||
/* update ipMIDI field */
|
||||
|
||||
cerr << "New device called " << _cp.device_info().name() << " with ipMIDI ? " << _cp.device_info().uses_ipmidi() << endl;
|
||||
|
||||
ipmidi_base_port_spinner.set_sensitive (_cp.device_info().uses_ipmidi());
|
||||
}
|
||||
|
||||
@@ -522,7 +518,6 @@ MackieControlProtocolGUI::profile_combo_changed ()
|
||||
void
|
||||
MackieControlProtocolGUI::ipmidi_spinner_changed ()
|
||||
{
|
||||
cerr << "Set IP MIDI base to " << ipmidi_base_port_spinner.get_value() << endl;
|
||||
_cp.set_ipmidi_base ((int16_t) lrintf (ipmidi_base_port_spinner.get_value()));
|
||||
}
|
||||
|
||||
|
||||
@@ -96,8 +96,6 @@ MackieControlProtocol::MackieControlProtocol (Session& session)
|
||||
, AbstractUI<MackieControlUIRequest> ("mackie")
|
||||
, _current_initial_bank (0)
|
||||
, _timecode_type (ARDOUR::AnyTime::BBT)
|
||||
, _input_bundle (new ARDOUR::Bundle (_("Mackie Control In"), true))
|
||||
, _output_bundle (new ARDOUR::Bundle (_("Mackie Control Out"), false))
|
||||
, _gui (0)
|
||||
, _zoom_mode (false)
|
||||
, _scrub_mode (false)
|
||||
@@ -109,6 +107,8 @@ MackieControlProtocol::MackieControlProtocol (Session& session)
|
||||
, needs_ipmidi_restart (false)
|
||||
, _metering_active (true)
|
||||
, _initialized (false)
|
||||
, _surfaces_state (0)
|
||||
, _surfaces_version (0)
|
||||
{
|
||||
DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::MackieControlProtocol\n");
|
||||
|
||||
@@ -132,7 +132,7 @@ MackieControlProtocol::~MackieControlProtocol()
|
||||
DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::~MackieControlProtocol tear_down_gui ()\n");
|
||||
tear_down_gui ();
|
||||
|
||||
_active = false;
|
||||
delete _surfaces_state;
|
||||
|
||||
/* stop event loop */
|
||||
DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::~MackieControlProtocol BaseUI::quit ()\n");
|
||||
@@ -383,7 +383,7 @@ MackieControlProtocol::set_active (bool yn)
|
||||
{
|
||||
DEBUG_TRACE (DEBUG::MackieControl, string_compose("MackieControlProtocol::set_active init with yn: '%1'\n", yn));
|
||||
|
||||
if (yn == _active) {
|
||||
if (yn == active()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -397,7 +397,6 @@ MackieControlProtocol::set_active (bool yn)
|
||||
return -1;
|
||||
}
|
||||
connect_session_signals ();
|
||||
_active = true;
|
||||
update_surfaces ();
|
||||
|
||||
/* set up periodic task for metering and automation
|
||||
@@ -411,10 +410,11 @@ MackieControlProtocol::set_active (bool yn)
|
||||
|
||||
BaseUI::quit ();
|
||||
close ();
|
||||
_active = false;
|
||||
|
||||
}
|
||||
|
||||
ControlProtocol::set_active (yn);
|
||||
|
||||
DEBUG_TRACE (DEBUG::MackieControl, string_compose("MackieControlProtocol::set_active done with yn: '%1'\n", yn));
|
||||
|
||||
return 0;
|
||||
@@ -423,7 +423,7 @@ MackieControlProtocol::set_active (bool yn)
|
||||
bool
|
||||
MackieControlProtocol::periodic ()
|
||||
{
|
||||
if (!_active) {
|
||||
if (!active()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -526,7 +526,7 @@ void
|
||||
MackieControlProtocol::update_surfaces()
|
||||
{
|
||||
DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::update_surfaces() init\n");
|
||||
if (!_active) {
|
||||
if (!active()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -609,34 +609,36 @@ MackieControlProtocol::set_profile (const string& profile_name)
|
||||
}
|
||||
|
||||
int
|
||||
MackieControlProtocol::set_device (const string& device_name, bool allow_activation)
|
||||
MackieControlProtocol::set_device_info (const string& device_name)
|
||||
{
|
||||
map<string,DeviceInfo>::iterator d = DeviceInfo::device_info.find (device_name);
|
||||
|
||||
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("new device chosen %1, activation allowed ? %2\n",
|
||||
device_name, allow_activation));
|
||||
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("new device chosen %1\n", device_name));
|
||||
|
||||
if (d == DeviceInfo::device_info.end()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_active) {
|
||||
clear_ports ();
|
||||
clear_surfaces ();
|
||||
}
|
||||
|
||||
_device_info = d->second;
|
||||
|
||||
if (allow_activation) {
|
||||
set_active (true);
|
||||
} else {
|
||||
if (_active) {
|
||||
if (create_surfaces ()) {
|
||||
return -1;
|
||||
}
|
||||
switch_banks (0, true);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
MackieControlProtocol::set_device (const string& device_name)
|
||||
{
|
||||
if (set_device_info (device_name)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
clear_surfaces ();
|
||||
|
||||
if (create_surfaces ()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch_banks (0, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -665,6 +667,10 @@ MackieControlProtocol::create_surfaces ()
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_surfaces_state) {
|
||||
surface->set_state (*_surfaces_state, _surfaces_version);
|
||||
}
|
||||
|
||||
{
|
||||
Glib::Threads::Mutex::Lock lm (surfaces_lock);
|
||||
surfaces.push_back (surface);
|
||||
@@ -681,6 +687,10 @@ MackieControlProtocol::create_surfaces ()
|
||||
stype = ext;
|
||||
|
||||
if (!_device_info.uses_ipmidi()) {
|
||||
|
||||
_input_bundle.reset (new ARDOUR::Bundle (_("Mackie Control In"), true));
|
||||
_output_bundle.reset (new ARDOUR::Bundle (_("Mackie Control Out"), false));
|
||||
|
||||
_input_bundle->add_channel (
|
||||
surface->port().input_port().name(),
|
||||
ARDOUR::DataType::MIDI,
|
||||
@@ -692,6 +702,16 @@ MackieControlProtocol::create_surfaces ()
|
||||
ARDOUR::DataType::MIDI,
|
||||
session->engine().make_port_name_non_relative (surface->port().output_port().name())
|
||||
);
|
||||
|
||||
session->BundleAdded (_input_bundle);
|
||||
session->BundleAdded (_output_bundle);
|
||||
|
||||
} else {
|
||||
_input_bundle.reset ((ARDOUR::Bundle*) 0);
|
||||
_output_bundle.reset ((ARDOUR::Bundle*) 0);
|
||||
|
||||
session->BundleRemoved (_input_bundle);
|
||||
session->BundleRemoved (_output_bundle);
|
||||
}
|
||||
|
||||
int fd;
|
||||
@@ -716,9 +736,6 @@ MackieControlProtocol::create_surfaces ()
|
||||
void
|
||||
MackieControlProtocol::close()
|
||||
{
|
||||
clear_ports ();
|
||||
|
||||
port_connections.drop_connections ();
|
||||
session_connections.drop_connections ();
|
||||
route_connections.drop_connections ();
|
||||
periodic_connection.disconnect ();
|
||||
@@ -729,38 +746,42 @@ MackieControlProtocol::close()
|
||||
XMLNode&
|
||||
MackieControlProtocol::get_state()
|
||||
{
|
||||
XMLNode& node (ControlProtocol::get_state());
|
||||
|
||||
DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::get_state init\n");
|
||||
char buf[16];
|
||||
|
||||
// add name of protocol
|
||||
XMLNode* node = new XMLNode (X_("Protocol"));
|
||||
node->add_property (X_("name"), ARDOUR::ControlProtocol::_name);
|
||||
|
||||
// add current bank
|
||||
snprintf (buf, sizeof (buf), "%d", _current_initial_bank);
|
||||
node->add_property (X_("bank"), buf);
|
||||
node.add_property (X_("bank"), buf);
|
||||
|
||||
// ipMIDI base port (possibly not used)
|
||||
snprintf (buf, sizeof (buf), "%d", _ipmidi_base);
|
||||
node->add_property (X_("ipmidi-base"), buf);
|
||||
node.add_property (X_("ipmidi-base"), buf);
|
||||
|
||||
node->add_property (X_("device-profile"), _device_profile.name());
|
||||
node->add_property (X_("device-name"), _device_info.name());
|
||||
node.add_property (X_("device-profile"), _device_profile.name());
|
||||
node.add_property (X_("device-name"), _device_info.name());
|
||||
|
||||
XMLNode* snode = new XMLNode (X_("Surfaces"));
|
||||
for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
|
||||
snode->add_child_nocopy ((*s)->get_state());
|
||||
}
|
||||
|
||||
node.add_child_nocopy (*snode);
|
||||
|
||||
DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::get_state done\n");
|
||||
|
||||
return *node;
|
||||
return node;
|
||||
}
|
||||
|
||||
int
|
||||
MackieControlProtocol::set_state (const XMLNode & node, int /*version*/)
|
||||
MackieControlProtocol::set_state (const XMLNode & node, int version)
|
||||
{
|
||||
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("MackieControlProtocol::set_state: active %1\n", _active));
|
||||
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("MackieControlProtocol::set_state: active %1\n", active()));
|
||||
|
||||
int retval = 0;
|
||||
const XMLProperty* prop;
|
||||
uint32_t bank = 0;
|
||||
bool active = _active;
|
||||
|
||||
if ((prop = node.property (X_("ipmidi-base"))) != 0) {
|
||||
set_ipmidi_base (atoi (prop->value()));
|
||||
@@ -771,24 +792,26 @@ MackieControlProtocol::set_state (const XMLNode & node, int /*version*/)
|
||||
bank = atoi (prop->value());
|
||||
}
|
||||
|
||||
if ((prop = node.property (X_("active"))) != 0) {
|
||||
active = string_is_affirmative (prop->value());
|
||||
}
|
||||
|
||||
if ((prop = node.property (X_("device-name"))) != 0) {
|
||||
set_device (prop->value(), false);
|
||||
set_device_info (prop->value());
|
||||
}
|
||||
|
||||
if ((prop = node.property (X_("device-profile"))) != 0) {
|
||||
set_profile (prop->value());
|
||||
}
|
||||
|
||||
XMLNode* snode = node.child (X_("Surfaces"));
|
||||
|
||||
delete _surfaces_state;
|
||||
_surfaces_state = 0;
|
||||
|
||||
set_active (active);
|
||||
|
||||
if (_active) {
|
||||
switch_banks (bank, true);
|
||||
if (snode) {
|
||||
_surfaces_state = new XMLNode (*snode);
|
||||
_surfaces_version = version;
|
||||
}
|
||||
|
||||
switch_banks (bank, true);
|
||||
|
||||
DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::set_state done\n");
|
||||
|
||||
return retval;
|
||||
@@ -1035,8 +1058,12 @@ list<boost::shared_ptr<ARDOUR::Bundle> >
|
||||
MackieControlProtocol::bundles ()
|
||||
{
|
||||
list<boost::shared_ptr<ARDOUR::Bundle> > b;
|
||||
b.push_back (_input_bundle);
|
||||
b.push_back (_output_bundle);
|
||||
|
||||
if (_input_bundle) {
|
||||
b.push_back (_input_bundle);
|
||||
b.push_back (_output_bundle);
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
@@ -1259,8 +1286,10 @@ MackieControlProtocol::midi_input_handler (IOCondition ioc, MIDI::Port* port)
|
||||
void
|
||||
MackieControlProtocol::clear_ports ()
|
||||
{
|
||||
_input_bundle->remove_channels ();
|
||||
_output_bundle->remove_channels ();
|
||||
if (_input_bundle) {
|
||||
_input_bundle->remove_channels ();
|
||||
_output_bundle->remove_channels ();
|
||||
}
|
||||
|
||||
for (PortSources::iterator i = port_sources.begin(); i != port_sources.end(); ++i) {
|
||||
g_source_destroy (*i);
|
||||
@@ -1581,7 +1610,7 @@ MackieControlProtocol::set_ipmidi_base (int16_t portnum)
|
||||
to restart.
|
||||
*/
|
||||
|
||||
if (_active && _device_info.uses_ipmidi()) {
|
||||
if (active() && _device_info.uses_ipmidi()) {
|
||||
needs_ipmidi_restart = true;
|
||||
}
|
||||
}
|
||||
@@ -1589,7 +1618,6 @@ MackieControlProtocol::set_ipmidi_base (int16_t portnum)
|
||||
int
|
||||
MackieControlProtocol::ipmidi_restart ()
|
||||
{
|
||||
clear_ports ();
|
||||
clear_surfaces ();
|
||||
if (create_surfaces ()) {
|
||||
return -1;
|
||||
@@ -1602,6 +1630,7 @@ MackieControlProtocol::ipmidi_restart ()
|
||||
void
|
||||
MackieControlProtocol::clear_surfaces ()
|
||||
{
|
||||
clear_ports ();
|
||||
Glib::Threads::Mutex::Lock lm (surfaces_lock);
|
||||
surfaces.clear ();
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ class MackieControlProtocol
|
||||
Mackie::DeviceProfile& device_profile() { return _device_profile; }
|
||||
|
||||
int set_active (bool yn);
|
||||
int set_device (const std::string&, bool allow_activation = true);
|
||||
int set_device (const std::string&);
|
||||
void set_profile (const std::string&);
|
||||
|
||||
FlipMode flip_mode () const { return _flip_mode; }
|
||||
@@ -262,7 +262,6 @@ class MackieControlProtocol
|
||||
uint32_t _current_initial_bank;
|
||||
PBD::ScopedConnectionList audio_engine_connections;
|
||||
PBD::ScopedConnectionList session_connections;
|
||||
PBD::ScopedConnectionList port_connections;
|
||||
PBD::ScopedConnectionList route_connections;
|
||||
PBD::ScopedConnectionList gui_connections;
|
||||
// timer for two quick marker left presses
|
||||
@@ -288,8 +287,9 @@ class MackieControlProtocol
|
||||
bool needs_ipmidi_restart;
|
||||
bool _metering_active;
|
||||
bool _initialized;
|
||||
|
||||
ARDOUR::RouteNotificationList _last_selected_routes;
|
||||
XMLNode* _surfaces_state;
|
||||
int _surfaces_version;
|
||||
|
||||
int create_surfaces ();
|
||||
bool periodic();
|
||||
@@ -303,7 +303,8 @@ class MackieControlProtocol
|
||||
void _gui_track_selection_changed (ARDOUR::RouteNotificationList*, bool save_list);
|
||||
int ipmidi_restart ();
|
||||
void initialize ();
|
||||
|
||||
int set_device_info (const std::string& device_name);
|
||||
|
||||
/* BUTTON HANDLING */
|
||||
|
||||
typedef std::set<uint32_t> DownButtonList;
|
||||
|
||||
@@ -141,6 +141,39 @@ Surface::~Surface ()
|
||||
DEBUG_TRACE (DEBUG::MackieControl, "Surface::~Surface done\n");
|
||||
}
|
||||
|
||||
XMLNode&
|
||||
Surface::get_state()
|
||||
{
|
||||
char buf[64];
|
||||
snprintf (buf, sizeof (buf), X_("surface-%u"), _number);
|
||||
XMLNode* node = new XMLNode (buf);
|
||||
|
||||
node->add_child_nocopy (_port->get_state());
|
||||
|
||||
return *node;
|
||||
}
|
||||
|
||||
int
|
||||
Surface::set_state (const XMLNode& node, int version)
|
||||
{
|
||||
char buf[64];
|
||||
snprintf (buf, sizeof (buf), X_("surface-%u"), _number);
|
||||
XMLNode* mynode = node.child (buf);
|
||||
|
||||
if (!mynode) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
XMLNode* portnode = mynode->child (X_("Port"));
|
||||
if (portnode) {
|
||||
if (_port->set_state (*portnode, version)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const MidiByteArray&
|
||||
Surface::sysex_hdr() const
|
||||
{
|
||||
@@ -588,12 +621,6 @@ Surface::turn_it_on ()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Surface::handle_port_inactive (SurfacePort*)
|
||||
{
|
||||
_active = false;
|
||||
}
|
||||
|
||||
void
|
||||
Surface::write_sysex (const MidiByteArray & mba)
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "pbd/xml++.h"
|
||||
#include "midi++/types.h"
|
||||
|
||||
#include "control_protocol/types.h"
|
||||
@@ -92,9 +93,6 @@ public:
|
||||
/// unless it's already connected
|
||||
void connect_to_signals ();
|
||||
|
||||
/// notification from a MackiePort that it's now inactive
|
||||
void handle_port_inactive(Mackie::SurfacePort *);
|
||||
|
||||
/// write a sysex message
|
||||
void write_sysex (const MidiByteArray& mba);
|
||||
void write_sysex (MIDI::byte msg);
|
||||
@@ -149,6 +147,9 @@ public:
|
||||
void notify_metering_state_changed();
|
||||
void turn_it_on ();
|
||||
|
||||
XMLNode& get_state ();
|
||||
int set_state (const XMLNode&, int version);
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
|
||||
@@ -51,11 +51,12 @@ using namespace ARDOUR;
|
||||
SurfacePort::SurfacePort (Surface& s)
|
||||
: _surface (&s)
|
||||
{
|
||||
|
||||
if (_surface->mcp().device_info().uses_ipmidi()) {
|
||||
_input_port = new MIDI::IPMIDIPort (_surface->mcp().ipmidi_base() +_surface->number());
|
||||
_output_port = _input_port;
|
||||
|
||||
} else {
|
||||
|
||||
_async_in = AudioEngine::instance()->register_input_port (DataType::MIDI, string_compose (_("%1 in"), _surface->name()), true);
|
||||
_async_out = AudioEngine::instance()->register_output_port (DataType::MIDI, string_compose (_("%1 out"), _surface->name()), true);
|
||||
|
||||
@@ -70,23 +71,73 @@ SurfacePort::SurfacePort (Surface& s)
|
||||
|
||||
SurfacePort::~SurfacePort()
|
||||
{
|
||||
if (_surface->mcp().device_info().uses_ipmidi()) {
|
||||
if (dynamic_cast<MIDI::IPMIDIPort*>(_input_port)) {
|
||||
delete _input_port;
|
||||
} else {
|
||||
|
||||
if (_async_in) {
|
||||
AudioEngine::instance()->unregister_port (_async_in);
|
||||
_async_in.reset ();
|
||||
_async_in.reset ((ARDOUR::Port*) 0);
|
||||
}
|
||||
|
||||
if (_async_out) {
|
||||
_output_port->drain (10000);
|
||||
AudioEngine::instance()->unregister_port (_async_out);
|
||||
_async_out.reset ();
|
||||
_async_out.reset ((ARDOUR::Port*) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
XMLNode&
|
||||
SurfacePort::get_state ()
|
||||
{
|
||||
XMLNode* node = new XMLNode (X_("Port"));
|
||||
|
||||
if (dynamic_cast<MIDI::IPMIDIPort*>(_input_port)) {
|
||||
/* no state required for IPMidi ports */
|
||||
return *node;
|
||||
}
|
||||
|
||||
XMLNode* child;
|
||||
|
||||
child = new XMLNode (X_("Input"));
|
||||
child->add_child_nocopy (_async_in->get_state());
|
||||
node->add_child_nocopy (*child);
|
||||
|
||||
|
||||
child = new XMLNode (X_("Output"));
|
||||
child->add_child_nocopy (_async_out->get_state());
|
||||
node->add_child_nocopy (*child);
|
||||
|
||||
return *node;
|
||||
}
|
||||
|
||||
int
|
||||
SurfacePort::set_state (const XMLNode& node, int version)
|
||||
{
|
||||
if (dynamic_cast<MIDI::IPMIDIPort*>(_input_port)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
XMLNode* child;
|
||||
|
||||
if ((child = node.child (X_("Input"))) != 0) {
|
||||
XMLNode* portnode = child->child (Port::state_node_name.c_str());
|
||||
if (portnode) {
|
||||
_async_in->set_state (*portnode, version);
|
||||
}
|
||||
}
|
||||
|
||||
if ((child = node.child (X_("Output"))) != 0) {
|
||||
XMLNode* portnode = child->child (Port::state_node_name.c_str());
|
||||
if (portnode) {
|
||||
_async_out->set_state (*portnode, version);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// wrapper for one day when strerror_r is working properly
|
||||
string fetch_errmsg (int error_number)
|
||||
{
|
||||
|
||||
@@ -50,15 +50,18 @@ class Surface;
|
||||
class SurfacePort
|
||||
{
|
||||
public:
|
||||
SurfacePort (Mackie::Surface&);
|
||||
virtual ~SurfacePort();
|
||||
|
||||
/// an easier way to output bytes via midi
|
||||
int write (const MidiByteArray&);
|
||||
SurfacePort (Mackie::Surface&);
|
||||
virtual ~SurfacePort();
|
||||
|
||||
/// an easier way to output bytes via midi
|
||||
int write (const MidiByteArray&);
|
||||
|
||||
MIDI::Port& input_port() const { return *_input_port; }
|
||||
MIDI::Port& output_port() const { return *_output_port; }
|
||||
|
||||
XMLNode& get_state ();
|
||||
int set_state (const XMLNode&, int version);
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
#include <glibmm/miscutils.h>
|
||||
|
||||
#include <pbd/convert.h>
|
||||
#include <pbd/pthread_utils.h>
|
||||
#include <pbd/file_utils.h>
|
||||
#include <pbd/failed_constructor.h>
|
||||
@@ -71,22 +72,20 @@ static void error_callback(int, const char *, const char *)
|
||||
#endif
|
||||
|
||||
OSC::OSC (Session& s, uint32_t port)
|
||||
: ControlProtocol (s, "OSC")
|
||||
: ControlProtocol (s, X_("Open Sound Control (OSC)"))
|
||||
, AbstractUI<OSCUIRequest> ("osc")
|
||||
, local_server (0)
|
||||
, remote_server (0)
|
||||
, _port(port)
|
||||
, _ok (true)
|
||||
, _shutdown (false)
|
||||
, _osc_server (0)
|
||||
, _osc_unix_server (0)
|
||||
, _namespace_root ("/ardour")
|
||||
, _send_route_changes (true)
|
||||
{
|
||||
_instance = this;
|
||||
_shutdown = false;
|
||||
_osc_server = 0;
|
||||
_osc_unix_server = 0;
|
||||
_namespace_root = "/ardour";
|
||||
_send_route_changes = true;
|
||||
|
||||
/* glibmm hack */
|
||||
local_server = 0;
|
||||
remote_server = 0;
|
||||
|
||||
// "Application Hooks"
|
||||
session_loaded (s);
|
||||
session->Exported.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::session_exported, this, _1, _2), this);
|
||||
}
|
||||
@@ -113,11 +112,21 @@ OSC::do_request (OSCUIRequest* req)
|
||||
int
|
||||
OSC::set_active (bool yn)
|
||||
{
|
||||
if (yn) {
|
||||
return start ();
|
||||
} else {
|
||||
return stop ();
|
||||
if (yn != active()) {
|
||||
|
||||
if (yn) {
|
||||
if (start ()) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (stop ()) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ControlProtocol::set_active (yn);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -1059,16 +1068,26 @@ OSC::route_plugin_parameter_print (int rid, int piid, int par)
|
||||
XMLNode&
|
||||
OSC::get_state ()
|
||||
{
|
||||
XMLNode* node = new XMLNode ("Protocol");
|
||||
XMLNode& node (ControlProtocol::get_state());
|
||||
|
||||
node->add_property (X_("name"), "Open Sound Control (OSC)");
|
||||
node->add_property (X_("feedback"), _send_route_changes ? "1" : "0");
|
||||
|
||||
return *node;
|
||||
node.add_property (X_("feedback"), _send_route_changes ? "1" : "0");
|
||||
return node;
|
||||
}
|
||||
|
||||
int
|
||||
OSC::set_state (const XMLNode&, int /*version*/)
|
||||
OSC::set_state (const XMLNode& node, int /*version*/)
|
||||
{
|
||||
const XMLProperty* prop = node.property (X_("feedback"));
|
||||
|
||||
if (prop) {
|
||||
if (PBD::string_is_affirmative (prop->value())) {
|
||||
_send_route_changes = true;
|
||||
} else {
|
||||
_send_route_changes = false;
|
||||
}
|
||||
} else {
|
||||
/* leave it alone */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -50,9 +50,7 @@ using namespace PBD;
|
||||
XMLNode&
|
||||
TranzportControlProtocol::get_state ()
|
||||
{
|
||||
XMLNode* node = new XMLNode (X_("Protocol"));
|
||||
node->add_property (X_("name"), _name);
|
||||
return *node;
|
||||
return ControlProtocol::get_state();
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
@@ -65,7 +65,8 @@ WiimoteControlProtocol::set_active (bool yn)
|
||||
DEBUG_TRACE (DEBUG::WiimoteControl, string_compose ("WiimoteControlProtocol::set_active init with yn: '%1'\n", yn));
|
||||
|
||||
/* do nothing if the active state is not changing */
|
||||
if (yn == _active) {
|
||||
|
||||
if (yn == active()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -77,8 +78,7 @@ WiimoteControlProtocol::set_active (bool yn)
|
||||
result = stop ();
|
||||
}
|
||||
|
||||
/* remember new active state */
|
||||
_active = yn;
|
||||
ControlProtocol::set_active (yn);
|
||||
|
||||
DEBUG_TRACE (DEBUG::WiimoteControl, "WiimoteControlProtocol::set_active done\n");
|
||||
|
||||
@@ -88,10 +88,9 @@ WiimoteControlProtocol::set_active (bool yn)
|
||||
XMLNode&
|
||||
WiimoteControlProtocol::get_state ()
|
||||
{
|
||||
XMLNode *node = new XMLNode ("Protocol");
|
||||
node->add_property (X_("name"), ARDOUR::ControlProtocol::_name);
|
||||
node->add_property (X_("feedback"), "0");
|
||||
return *node;
|
||||
XMLNode& node (ControlProtocol::get_state());
|
||||
node.add_property (X_("feedback"), "0");
|
||||
return node;
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
@@ -369,6 +369,8 @@ if ($html) {
|
||||
|
||||
$boilerplate_header = <<END_HEADER;
|
||||
\\documentclass[10pt,landscape]{article}
|
||||
%\\documentclass[10pt,landscape,a4paper]{article}
|
||||
%\\documentclass[10pt,landscape,letterpaper]{article}
|
||||
\\usepackage{multicol}
|
||||
\\usepackage{calc}
|
||||
\\usepackage{ifthen}
|
||||
@@ -387,7 +389,7 @@ $boilerplate_header = <<END_HEADER;
|
||||
% if using A4 paper. (This probably isnott strictly necessary.)
|
||||
% If using another size paper, use default 1cm margins.
|
||||
\\ifthenelse{\\lengthtest { \\paperwidth = 11in}}
|
||||
{ \\geometry{top=.5in,left=1in,right=0in,bottom=.5in} }
|
||||
{ \\geometry{top=.5in,left=.5in,right=.5in,bottom=.5in} }
|
||||
{\\ifthenelse{ \\lengthtest{ \\paperwidth = 297mm}}
|
||||
{\\geometry{top=1cm,left=1cm,right=1cm,bottom=1cm} }
|
||||
{\\geometry{top=1cm,left=1cm,right=1cm,bottom=1cm} }
|
||||
@@ -431,12 +433,11 @@ $boilerplate_footer = <<END_FOOTER;
|
||||
\\rule{0.3\\linewidth}{0.25pt}
|
||||
\\scriptsize
|
||||
|
||||
Copyright \\copyright\\ 2009 ardour.org
|
||||
Copyright \\copyright\\ 2013 ardour.org
|
||||
|
||||
% Should change this to be date of file, not current date.
|
||||
%\\verb!$Revision: 1.13 $, $Date: 2008/05/29 06:11:56 $.!
|
||||
|
||||
http://ardour.org/manual
|
||||
http://manual.ardour.org
|
||||
|
||||
\\end{multicols}
|
||||
\\end{document}
|
||||
|
||||
Reference in New Issue
Block a user