diff options
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} |