summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2013-12-23 15:35:49 -0500
committerPaul Davis <paul@linuxaudiosystems.com>2013-12-23 15:35:49 -0500
commit84f55440a3c6317dd2ab5d7e3d638016609e4d03 (patch)
tree2329f57523432a698f99927a2f070555fd31fe20
parente1bca03857070ba390bba729933c2d72ad5169fd (diff)
parentdc7878760da040ad74b077318d2e9868d427199a (diff)
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).
-rw-r--r--gtk2_ardour/ardour_ui.cc3
-rw-r--r--gtk2_ardour/ardour_ui_dialogs.cc14
-rw-r--r--gtk2_ardour/ardour_ui_options.cc21
-rw-r--r--gtk2_ardour/editor.h2
-rw-r--r--gtk2_ardour/editor_videotimeline.cc12
-rw-r--r--gtk2_ardour/level_meter.cc13
-rw-r--r--gtk2_ardour/meter_patterns.cc45
-rw-r--r--gtk2_ardour/meter_strip.cc2
-rw-r--r--gtk2_ardour/mixer_strip.cc1
-rw-r--r--gtk2_ardour/port_group.cc2
-rw-r--r--gtk2_ardour/public_editor.h2
-rw-r--r--gtk2_ardour/rc_option_editor.cc20
-rw-r--r--gtk2_ardour/wscript44
-rw-r--r--libs/ardour/ardour/control_protocol_manager.h6
-rw-r--r--libs/ardour/ardour/slave.h28
-rw-r--r--libs/ardour/ardour/types.h3
-rw-r--r--libs/ardour/control_protocol_manager.cc89
-rw-r--r--libs/ardour/enums.cc1
-rw-r--r--libs/ardour/meter.cc7
-rw-r--r--libs/ardour/midi_clock_slave.cc48
-rw-r--r--libs/ardour/midi_ui.cc2
-rw-r--r--libs/ardour/slave.cc13
-rw-r--r--libs/ardour/test/interpolation_test.cc6
-rw-r--r--libs/canvas/canvas.cc14
-rw-r--r--libs/plugins/reasonablesynth.lv2/lv2.c18
-rw-r--r--libs/plugins/reasonablesynth.lv2/rsynth.c52
-rw-r--r--libs/surfaces/control_protocol/control_protocol.cc21
-rw-r--r--libs/surfaces/control_protocol/control_protocol/control_protocol.h9
-rw-r--r--libs/surfaces/frontier/tranzport/tranzport_control_protocol.cc4
-rw-r--r--libs/surfaces/generic_midi/generic_midi_control_protocol.cc21
-rw-r--r--libs/surfaces/mackie/gui.cc5
-rw-r--r--libs/surfaces/mackie/mackie_control_protocol.cc137
-rw-r--r--libs/surfaces/mackie/mackie_control_protocol.h9
-rw-r--r--libs/surfaces/mackie/surface.cc39
-rw-r--r--libs/surfaces/mackie/surface.h7
-rw-r--r--libs/surfaces/mackie/surface_port.cc59
-rw-r--r--libs/surfaces/mackie/surface_port.h13
-rw-r--r--libs/surfaces/osc/osc.cc61
-rw-r--r--libs/surfaces/tranzport/state.cc4
-rw-r--r--libs/surfaces/wiimote/wiimote.cc13
-rwxr-xr-xtools/fmt-bindings9
41 files changed, 618 insertions, 261 deletions
diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc
index 6afc359eb8..6337b1919f 100644
--- a/gtk2_ardour/ardour_ui.cc
+++ b/gtk2_ardour/ardour_ui.cc
@@ -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()) {
diff --git a/gtk2_ardour/ardour_ui_dialogs.cc b/gtk2_ardour/ardour_ui_dialogs.cc
index 0dd61778ae..b0ac528b79 100644
--- a/gtk2_ardour/ardour_ui_dialogs.cc
+++ b/gtk2_ardour/ardour_ui_dialogs.cc
@@ -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
diff --git a/gtk2_ardour/ardour_ui_options.cc b/gtk2_ardour/ardour_ui_options.cc
index 22f88114d9..e1435f7a8d 100644
--- a/gtk2_ardour/ardour_ui_options.cc
+++ b/gtk2_ardour/ardour_ui_options.cc
@@ -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();
+ }
}
}
}
diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h
index 233816295b..7366c601d2 100644
--- a/gtk2_ardour/editor.h
+++ b/gtk2_ardour/editor.h
@@ -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;
diff --git a/gtk2_ardour/editor_videotimeline.cc b/gtk2_ardour/editor_videotimeline.cc
index 83a9745b89..458393708a 100644
--- a/gtk2_ardour/editor_videotimeline.cc
+++ b/gtk2_ardour/editor_videotimeline.cc
@@ -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());
}
diff --git a/gtk2_ardour/level_meter.cc b/gtk2_ardour/level_meter.cc
index 194e446115..e428958343 100644
--- a/gtk2_ardour/level_meter.cc
+++ b/gtk2_ardour/level_meter.cc
@@ -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");
diff --git a/gtk2_ardour/meter_patterns.cc b/gtk2_ardour/meter_patterns.cc
index f392dc0872..7db2924697 100644
--- a/gtk2_ardour/meter_patterns.cc
+++ b/gtk2_ardour/meter_patterns.cc
@@ -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:
diff --git a/gtk2_ardour/meter_strip.cc b/gtk2_ardour/meter_strip.cc
index 886374c61a..632c6ef82c 100644
--- a/gtk2_ardour/meter_strip.cc
+++ b/gtk2_ardour/meter_strip.cc
@@ -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();
diff --git a/gtk2_ardour/mixer_strip.cc b/gtk2_ardour/mixer_strip.cc
index 50594378de..aa49e20d0c 100644
--- a/gtk2_ardour/mixer_strip.cc
+++ b/gtk2_ardour/mixer_strip.cc
@@ -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;
diff --git a/gtk2_ardour/port_group.cc b/gtk2_ardour/port_group.cc
index 213c818b0b..cafcaad51f 100644
--- a/gtk2_ardour/port_group.cc
+++ b/gtk2_ardour/port_group.cc
@@ -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) {
diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h
index a99dcdd253..8e673a7824 100644
--- a/gtk2_ardour/public_editor.h
+++ b/gtk2_ardour/public_editor.h
@@ -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;
diff --git a/gtk2_ardour/rc_option_editor.cc b/gtk2_ardour/rc_option_editor.cc
index da6d2344c2..3a5cab0289 100644
--- a/gtk2_ardour/rc_option_editor.cc
+++ b/gtk2_ardour/rc_option_editor.cc
@@ -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
diff --git a/gtk2_ardour/wscript b/gtk2_ardour/wscript
index db6116c3c3..28a8ad5b5a 100644
--- a/gtk2_ardour/wscript
+++ b/gtk2_ardour/wscript
@@ -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'
diff --git a/libs/ardour/ardour/control_protocol_manager.h b/libs/ardour/ardour/control_protocol_manager.h
index 519c762eee..7d3d4872e6 100644
--- a/libs/ardour/ardour/control_protocol_manager.h
+++ b/libs/ardour/ardour/control_protocol_manager.h
@@ -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
diff --git a/libs/ardour/ardour/slave.h b/libs/ardour/ardour/slave.h
index ca3f618af1..364929eaab 100644
--- a/libs/ardour/ardour/slave.h
+++ b/libs/ardour/ardour/slave.h
@@ -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);
diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h
index 91b8888f52..50a96030b1 100644
--- a/libs/ardour/ardour/types.h
+++ b/libs/ardour/ardour/types.h
@@ -187,7 +187,8 @@ namespace ARDOUR {
MeterIEC1NOR = 0x080,
MeterIEC2BBC = 0x100,
MeterIEC2EBU = 0x200,
- MeterVU = 0x400
+ MeterVU = 0x400,
+ MeterK12 = 0x800
};
enum TrackMode {
diff --git a/libs/ardour/control_protocol_manager.cc b/libs/ardour/control_protocol_manager.cc
index 2e65a8d6f8..974258a5c2 100644
--- a/libs/ardour/control_protocol_manager.cc
+++ b/libs/ardour/control_protocol_manager.cc
@@ -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;
diff --git a/libs/ardour/enums.cc b/libs/ardour/enums.cc
index 72125f8772..e32fe329af 100644
--- a/libs/ardour/enums.cc
+++ b/libs/ardour/enums.cc
@@ -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);
diff --git a/libs/ardour/meter.cc b/libs/ardour/meter.cc
index a7857f5859..5310fd747b 100644
--- a/libs/ardour/meter.cc
+++ b/libs/ardour/meter.cc
@@ -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();
diff --git a/libs/ardour/midi_clock_slave.cc b/libs/ardour/midi_clock_slave.cc
index 7eaeeb9e07..762d94469c 100644
--- a/libs/ardour/midi_clock_slave.cc
+++ b/libs/ardour/midi_clock_slave.cc
@@ -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;
}
diff --git a/libs/ardour/midi_ui.cc b/libs/ardour/midi_ui.cc
index 0729132d6c..b80370ec6a 100644
--- a/libs/ardour/midi_ui.cc
+++ b/libs/ardour/midi_ui.cc
@@ -61,6 +61,8 @@ MidiControlUI::do_request (MidiUIRequest* req)
{
if (req->type == Quit) {
BaseUI::quit ();
+ } else if (req->type == CallSlot) {
+ req->the_slot ();
}
}
diff --git a/libs/ardour/slave.cc b/libs/ardour/slave.cc
index e8c63b43c1..c0678ce252 100644
--- a/libs/ardour/slave.cc
+++ b/libs/ardour/slave.cc
@@ -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
{
diff --git a/libs/ardour/test/interpolation_test.cc b/libs/ardour/test/interpolation_test.cc
index 23789f826f..e8ed22d03b 100644
--- a/libs/ardour/test/interpolation_test.cc
+++ b/libs/ardour/test/interpolation_test.cc
@@ -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]);
diff --git a/libs/canvas/canvas.cc b/libs/canvas/canvas.cc
index 93637db2ae..18cf3104fa 100644
--- a/libs/canvas/canvas.cc
+++ b/libs/canvas/canvas.cc
@@ -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.
diff --git a/libs/plugins/reasonablesynth.lv2/lv2.c b/libs/plugins/reasonablesynth.lv2/lv2.c
index b29590c78a..6b9c81d8dd 100644
--- a/libs/plugins/reasonablesynth.lv2/lv2.c
+++ b/libs/plugins/reasonablesynth.lv2/lv2.c
@@ -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));
diff --git a/libs/plugins/reasonablesynth.lv2/rsynth.c b/libs/plugins/reasonablesynth.lv2/rsynth.c
index d2d5b3e905..061d72dbff 100644
--- a/libs/plugins/reasonablesynth.lv2/rsynth.c
+++ b/libs/plugins/reasonablesynth.lv2/rsynth.c
@@ -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;
}
/**
diff --git a/libs/surfaces/control_protocol/control_protocol.cc b/libs/surfaces/control_protocol/control_protocol.cc
index e0eb57fc87..cd379b10dc 100644
--- a/libs/surfaces/control_protocol/control_protocol.cc
+++ b/libs/surfaces/control_protocol/control_protocol.cc
@@ -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;
}
diff --git a/libs/surfaces/control_protocol/control_protocol/control_protocol.h b/libs/surfaces/control_protocol/control_protocol/control_protocol.h
index 0c849064bb..8dddfdcdb3 100644
--- a/libs/surfaces/control_protocol/control_protocol/control_protocol.h
+++ b/libs/surfaces/control_protocol/control_protocol/control_protocol.h
@@ -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" {
diff --git a/libs/surfaces/frontier/tranzport/tranzport_control_protocol.cc b/libs/surfaces/frontier/tranzport/tranzport_control_protocol.cc
index 550daef37b..f83e55c9d9 100644
--- a/libs/surfaces/frontier/tranzport/tranzport_control_protocol.cc
+++ b/libs/surfaces/frontier/tranzport/tranzport_control_protocol.cc
@@ -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
diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
index ba1858a174..2ea9079b49 100644
--- a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
+++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
@@ -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
diff --git a/libs/surfaces/mackie/gui.cc b/libs/surfaces/mackie/gui.cc
index ebb9fd584e..7425b38826 100644
--- a/libs/surfaces/mackie/gui.cc
+++ b/libs/surfaces/mackie/gui.cc
@@ -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()));
}
diff --git a/libs/surfaces/mackie/mackie_control_protocol.cc b/libs/surfaces/mackie/mackie_control_protocol.cc
index b55ac74c35..e9bef5a9b0 100644
--- a/libs/surfaces/mackie/mackie_control_protocol.cc
+++ b/libs/surfaces/mackie/mackie_control_protocol.cc
@@ -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;
+
+ return 0;
+}
+
+int
+MackieControlProtocol::set_device (const string& device_name)
+{
+ if (set_device_info (device_name)) {
+ return -1;
}
- _device_info = d->second;
+ clear_surfaces ();
- if (allow_activation) {
- set_active (true);
- } else {
- if (_active) {
- if (create_surfaces ()) {
- return -1;
- }
- switch_banks (0, true);
- }
+ 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());
+
+ 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_property (X_("device-profile"), _device_profile.name());
- node->add_property (X_("device-name"), _device_info.name());
+ 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 ();
}
diff --git a/libs/surfaces/mackie/mackie_control_protocol.h b/libs/surfaces/mackie/mackie_control_protocol.h
index 4669247726..e1a71a2460 100644
--- a/libs/surfaces/mackie/mackie_control_protocol.h
+++ b/libs/surfaces/mackie/mackie_control_protocol.h
@@ -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;
diff --git a/libs/surfaces/mackie/surface.cc b/libs/surfaces/mackie/surface.cc
index 507491d84c..694c73b1bc 100644
--- a/libs/surfaces/mackie/surface.cc
+++ b/libs/surfaces/mackie/surface.cc
@@ -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
{
@@ -589,12 +622,6 @@ Surface::turn_it_on ()
}
void
-Surface::handle_port_inactive (SurfacePort*)
-{
- _active = false;
-}
-
-void
Surface::write_sysex (const MidiByteArray & mba)
{
if (mba.empty()) {
diff --git a/libs/surfaces/mackie/surface.h b/libs/surfaces/mackie/surface.h
index ecaa4171f7..1ed83aef1d 100644
--- a/libs/surfaces/mackie/surface.h
+++ b/libs/surfaces/mackie/surface.h
@@ -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:
diff --git a/libs/surfaces/mackie/surface_port.cc b/libs/surfaces/mackie/surface_port.cc
index 508f501f59..013a0019c7 100644
--- a/libs/surfaces/mackie/surface_port.cc
+++ b/libs/surfaces/mackie/surface_port.cc
@@ -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,21 +71,71 @@ 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
diff --git a/libs/surfaces/mackie/surface_port.h b/libs/surfaces/mackie/surface_port.h
index 751ee848d7..b361294fa9 100644
--- a/libs/surfaces/mackie/surface_port.h
+++ b/libs/surfaces/mackie/surface_port.h
@@ -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:
diff --git a/libs/surfaces/osc/osc.cc b/libs/surfaces/osc/osc.cc
index 0c7c8455a4..37fe0715eb 100644
--- a/libs/surfaces/osc/osc.cc
+++ b/libs/surfaces/osc/osc.cc
@@ -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");
-
- node->add_property (X_("name"), "Open Sound Control (OSC)");
- node->add_property (X_("feedback"), _send_route_changes ? "1" : "0");
+ XMLNode& node (ControlProtocol::get_state());
- 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;
}
diff --git a/libs/surfaces/tranzport/state.cc b/libs/surfaces/tranzport/state.cc
index 7995e1aa02..119e7953d2 100644
--- a/libs/surfaces/tranzport/state.cc
+++ b/libs/surfaces/tranzport/state.cc
@@ -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
diff --git a/libs/surfaces/wiimote/wiimote.cc b/libs/surfaces/wiimote/wiimote.cc
index 68f2125dcb..963bf90df7 100644
--- a/libs/surfaces/wiimote/wiimote.cc
+++ b/libs/surfaces/wiimote/wiimote.cc
@@ -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
diff --git a/tools/fmt-bindings b/tools/fmt-bindings
index cd69e04a59..ab4595d965 100755
--- a/tools/fmt-bindings
+++ b/tools/fmt-bindings
@@ -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}