summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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}