diff --git a/gtk2_ardour/audio_region_view.cc b/gtk2_ardour/audio_region_view.cc index e2ce727c79..fbfc1d513f 100644 --- a/gtk2_ardour/audio_region_view.cc +++ b/gtk2_ardour/audio_region_view.cc @@ -1423,18 +1423,25 @@ AudioRegionView::set_one_waveform_color (ArdourCanvas::WaveView* wave) } } } +#if 0 //Removed for Tracks + if (ARDOUR_UI::config()->get_color_regions_using_track_color()) { - //if (ARDOUR_UI::config()->get_color_regions_using_track_color()) { + /* just use a slightly transparent version of the selected + * color so that some of the track color bleeds through + */ - // /* just use a slightly transparent version of the selected - // * color so that some of the track color bleeds through - // */ + double r, g, b, a; + ArdourCanvas::color_to_rgba (fill, r, g, b, a); + fill = ArdourCanvas::rgba_to_color (r, g, b, 0.85); /* magic number, not user controllable */ + outline = ARDOUR_UI::config()->get_canvasvar_WaveForm(); - // double r, g, b, a; - // ArdourCanvas::color_to_rgba (fill, r, g, b, a); - // fill = ArdourCanvas::rgba_to_color (r, g, b, 0.85); /* magic number, not user controllable */ - // outline = ARDOUR_UI::config()->get_canvasvar_WaveForm(); - //} + if (!Config->get_show_name_highlight()) { + /* recolor name text because it needs to contrast with + the waveform background, not the name highlight. + */ + } + } +#endif wave->set_fill_color (fill); wave->set_outline_color (outline); diff --git a/gtk2_ardour/plugin_selector.cc b/gtk2_ardour/plugin_selector.cc index abdb5c39c1..0a1f2c263a 100644 --- a/gtk2_ardour/plugin_selector.cc +++ b/gtk2_ardour/plugin_selector.cc @@ -311,8 +311,11 @@ PluginSelector::refiller (const PluginInfoList& plugs, const::std::string& filte string::size_type pos = 0; /* stupid LADSPA creator strings */ - +#ifdef PLATFORM_WINDOWS + while (pos < creator.length() && creator[pos] > -2 && creator[pos] < 256 && (isalnum (creator[pos]) || isspace (creator[pos]))) ++pos; +#else while (pos < creator.length() && (isalnum (creator[pos]) || isspace (creator[pos]))) ++pos; +#endif creator = creator.substr (0, pos); newrow[plugin_columns.creator] = creator; @@ -681,7 +684,11 @@ PluginSelector::create_by_creator_menu (ARDOUR::PluginInfoList& all_plugs) /* stupid LADSPA creator strings */ string::size_type pos = 0; +#ifdef PLATFORM_WINDOWS + while (pos < creator.length() && creator[pos] > -2 && creator[pos] < 256 && (isalnum (creator[pos]) || isspace (creator[pos]))) ++pos; +#else while (pos < creator.length() && (isalnum (creator[pos]) || isspace (creator[pos]))) ++pos; +#endif creator = creator.substr (0, pos); SubmenuMap::iterator x; diff --git a/gtk2_ardour/plugin_ui.cc b/gtk2_ardour/plugin_ui.cc index ac5f7fd9a6..190fd2ad96 100644 --- a/gtk2_ardour/plugin_ui.cc +++ b/gtk2_ardour/plugin_ui.cc @@ -227,7 +227,7 @@ PluginUIWindow::create_windows_vst_editor(boost::shared_ptr) << endmsg; throw failed_constructor (); } else { - WindowsVSTPluginUI* vpu = new WindowsVSTPluginUI (insert, vp); + WindowsVSTPluginUI* vpu = new WindowsVSTPluginUI (insert, vp, GTK_WIDGET(this->gobj())); _pluginui = vpu; _pluginui->KeyboardFocused.connect (sigc::mem_fun (*this, &PluginUIWindow::keyboard_focused)); diff --git a/gtk2_ardour/rc_option_editor.cc b/gtk2_ardour/rc_option_editor.cc index d4a5c57705..7d6be32e22 100644 --- a/gtk2_ardour/rc_option_editor.cc +++ b/gtk2_ardour/rc_option_editor.cc @@ -1358,8 +1358,18 @@ RCOptionEditor::RCOptionEditor () Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), string_compose (_("When enabled %1 will stop recording if an over- or underrun is detected by the audio engine"), PROGRAM_NAME)); - add_option (_("Transport"), tsf); + tsf = new BoolOption ( + "loop-is-mode", + _("Play loop is a transport mode"), + sigc::mem_fun (*_rc_config, &RCConfiguration::get_loop_is_mode), + sigc::mem_fun (*_rc_config, &RCConfiguration::set_loop_is_mode) + ); + Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), + (_("When enabled the loop button does not start playback but forces playback to always play the loop\n\n" + "When disabled the loop button starts playing the loop, but stop then cancels loop playback"))); + add_option (_("Transport"), tsf); + tsf = new BoolOption ( "create-xrun-marker", _("Create markers where xruns occur"), diff --git a/gtk2_ardour/time_axis_view_item.cc b/gtk2_ardour/time_axis_view_item.cc index ad2ab9c344..33a517ca17 100644 --- a/gtk2_ardour/time_axis_view_item.cc +++ b/gtk2_ardour/time_axis_view_item.cc @@ -209,7 +209,11 @@ TimeAxisViewItem::init (ArdourCanvas::Group* parent, double fpp, Gdk::Color cons CANVAS_DEBUG_NAME (frame, string_compose ("frame for %1", get_item_name())); - frame->set_outline_what (ArdourCanvas::Rectangle::What (ArdourCanvas::Rectangle::LEFT|ArdourCanvas::Rectangle::RIGHT)); + if (Config->get_show_name_highlight()) { + frame->set_outline_what (ArdourCanvas::Rectangle::What (ArdourCanvas::Rectangle::LEFT|ArdourCanvas::Rectangle::RIGHT)); + } else { + frame->set_outline_what (ArdourCanvas::Rectangle::What (ArdourCanvas::Rectangle::LEFT|ArdourCanvas::Rectangle::RIGHT|ArdourCanvas::Rectangle::BOTTOM)); + } if (_recregion) { frame->set_outline_color (ARDOUR_UI::config()->get_canvasvar_RecordingRect()); @@ -217,8 +221,6 @@ TimeAxisViewItem::init (ArdourCanvas::Group* parent, double fpp, Gdk::Color cons frame->set_outline_color (ARDOUR_UI::config()->get_canvasvar_TimeAxisFrame()); } - frame->set_outline_what (ArdourCanvas::Rectangle::What (ArdourCanvas::Rectangle::RIGHT|ArdourCanvas::Rectangle::LEFT)); - } else { frame = 0; diff --git a/gtk2_ardour/windows_vst_plugin_ui.cc b/gtk2_ardour/windows_vst_plugin_ui.cc index 1ce83f8992..45111f840d 100644 --- a/gtk2_ardour/windows_vst_plugin_ui.cc +++ b/gtk2_ardour/windows_vst_plugin_ui.cc @@ -38,22 +38,18 @@ using namespace Gtk; using namespace ARDOUR; using namespace PBD; -WindowsVSTPluginUI::WindowsVSTPluginUI (boost::shared_ptr pi, boost::shared_ptr vp) +WindowsVSTPluginUI::WindowsVSTPluginUI (boost::shared_ptr pi, boost::shared_ptr vp, GtkWidget *parent) : VSTPluginUI (pi, vp) { #ifdef GDK_WINDOWING_WIN32 - -#if 0 // TODO verify window vs vbox-widget WRT to plugin_analysis_expander - GtkWindow* wobj = GTK_WINDOW(gtk_widget_get_toplevel(this->gobj())); -#else - GtkVBox* wobj = this->gobj(); -#endif - - gtk_widget_realize(GTK_WIDGET(wobj)); - void* hWndHost = gdk_win32_drawable_get_handle(GTK_WIDGET(wobj)->window); + gtk_widget_realize(parent); + void* hWndHost = gdk_win32_drawable_get_handle(parent->window); fst_run_editor (_vst->state(), hWndHost); + // TODO pack a placeholder (compare to VSTPluginUI::VSTPluginUI X11 socket) + // have placeholder use VSTPluginUI::get_preferred_height(), width() + // TODO pack plugin_analysis_expander at the bottom. #else fst_run_editor (_vst->state(), NULL); pack_start (plugin_analysis_expander, true, true); diff --git a/gtk2_ardour/windows_vst_plugin_ui.h b/gtk2_ardour/windows_vst_plugin_ui.h index 7b23f2cb33..2fa0bbc705 100644 --- a/gtk2_ardour/windows_vst_plugin_ui.h +++ b/gtk2_ardour/windows_vst_plugin_ui.h @@ -22,7 +22,7 @@ class WindowsVSTPluginUI : public VSTPluginUI { public: - WindowsVSTPluginUI (boost::shared_ptr, boost::shared_ptr); + WindowsVSTPluginUI (boost::shared_ptr, boost::shared_ptr, GtkWidget *parent); ~WindowsVSTPluginUI (); bool start_updating (GdkEventAny*) { return false; } diff --git a/libs/ardour/ardour/rc_configuration_vars.h b/libs/ardour/ardour/rc_configuration_vars.h index 677b53ae8d..57275f4783 100644 --- a/libs/ardour/ardour/rc_configuration_vars.h +++ b/libs/ardour/ardour/rc_configuration_vars.h @@ -135,6 +135,7 @@ CONFIG_VARIABLE (bool, stop_recording_on_xrun, "stop-recording-on-xrun", false) CONFIG_VARIABLE (bool, create_xrun_marker, "create-xrun-marker", true) CONFIG_VARIABLE (bool, stop_at_session_end, "stop-at-session-end", false) CONFIG_VARIABLE (bool, seamless_loop, "seamless-loop", false) +CONFIG_VARIABLE (bool, loop_is_mode, "loop-is-mode", false) CONFIG_VARIABLE (framecnt_t, preroll, "preroll", 0) CONFIG_VARIABLE (framecnt_t, postroll, "postroll", 0) CONFIG_VARIABLE (float, rf_speed, "rf-speed", 2.0f) diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index c8ffb5ae3c..4c61c72276 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -1263,7 +1263,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop int start_midi_thread (); - void set_play_loop (bool yn); + void set_play_loop (bool yn, double speed); void unset_play_loop (); void overwrite_some_buffers (Track *); void flush_all_inserts (); diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc index 6bfb250aec..eb5c0de294 100644 --- a/libs/ardour/session_process.cc +++ b/libs/ardour/session_process.cc @@ -1010,7 +1010,7 @@ Session::process_event (SessionEvent* ev) switch (ev->type) { case SessionEvent::SetLoop: - set_play_loop (ev->yes_or_no); + set_play_loop (ev->yes_or_no, ev->speed); break; case SessionEvent::AutoLoop: diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index 38ad521235..ea9f5d28dd 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -30,6 +30,7 @@ #include "pbd/enumwriter.h" #include "pbd/pthread_utils.h" #include "pbd/memento_command.h" +#include "pbd/stacktrace.h" #include "midi++/mmc.h" #include "midi++/port.h" @@ -40,6 +41,7 @@ #include "ardour/click.h" #include "ardour/debug.h" #include "ardour/location.h" +#include "ardour/profile.h" #include "ardour/session.h" #include "ardour/slave.h" #include "ardour/operations.h" @@ -158,10 +160,11 @@ Session::force_locate (framepos_t target_frame, bool with_roll) } void -Session::request_play_loop (bool yn, bool leave_rolling) +Session::request_play_loop (bool yn, bool change_transport_roll) { SessionEvent* ev; Location *location = _locations->auto_loop_location(); + double target_speed; if (location == 0 && yn) { error << _("Cannot loop - no loop range defined") @@ -169,14 +172,44 @@ Session::request_play_loop (bool yn, bool leave_rolling) return; } - ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0), yn); - DEBUG_TRACE (DEBUG::Transport, string_compose ("Request set loop = %1, leave rolling ? %2\n", yn, leave_rolling)); + if (change_transport_roll) { + if (transport_rolling()) { + /* start looping at current speed */ + target_speed = transport_speed (); + } else { + /* currently stopped */ + if (yn) { + /* start looping at normal speed */ + target_speed = 1.0; + } else { + target_speed = 0.0; + } + } + } else { + /* leave the speed alone */ + target_speed = transport_speed (); + } + + ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, target_speed, yn); + DEBUG_TRACE (DEBUG::Transport, string_compose ("Request set loop = %1, change roll state ? %2\n", yn, change_transport_roll)); queue_event (ev); - if (!leave_rolling && !yn && Config->get_seamless_loop() && transport_rolling()) { - // request an immediate locate to refresh the tracks - // after disabling looping - request_locate (_transport_frame-1, false); + if (yn) { + if (!change_transport_roll) { + if (!transport_rolling()) { + /* we're not changing transport state, but we do want + to set up position for the new loop. Don't + do this if we're rolling already. + */ + request_locate (location->start(), false); + } + } + } else { + if (!change_transport_roll && Config->get_seamless_loop() && transport_rolling()) { + // request an immediate locate to refresh the tracks + // after disabling looping + request_locate (_transport_frame-1, false); + } } } @@ -531,8 +564,6 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished) /* explicit return request pre-queued in event list. overrides everything else */ - cerr << "explicit auto-return to " << _requested_return_frame << endl; - _transport_frame = _requested_return_frame; do_locate = true; @@ -589,8 +620,10 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished) */ if (ptw & PostTransportClearSubstate) { - _play_range = false; - unset_play_loop (); + unset_play_range (); + if (!Config->get_loop_is_mode()) { + unset_play_loop (); + } } /* this for() block can be put inside the previous if() and has the effect of ... ??? what */ @@ -657,8 +690,10 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished) } if (ptw & PostTransportStop) { - _play_range = false; - play_loop = false; + unset_play_range (); + if (!Config->get_loop_is_mode()) { + unset_play_loop (); + } } PositionChanged (_transport_frame); /* EMIT SIGNAL */ @@ -723,7 +758,7 @@ Session::unset_play_loop () } void -Session::set_play_loop (bool yn) +Session::set_play_loop (bool yn, double speed) { /* Called from event-handling context */ @@ -782,12 +817,24 @@ Session::set_play_loop (bool yn) merge_event (new SessionEvent (SessionEvent::AutoLoopDeclick, SessionEvent::Replace, dcp, dcl, 0.0f)); merge_event (new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f)); - /* locate to start of loop and roll. + /* if requested to roll, locate to start of loop and + * roll but ONLY if we're not already rolling. args: positition, roll=true, flush=true, with_loop=false, force buffer refill if seamless looping */ - start_locate (loc->start(), true, true, false, Config->get_seamless_loop()); + if (Config->get_loop_is_mode()) { + /* loop IS a transport mode: if already + rolling, do not locate to loop start. + */ + if (!transport_rolling() && (speed != 0.0)) { + start_locate (loc->start(), true, true, false, Config->get_seamless_loop()); + } + } else { + if (speed != 0.0) { + start_locate (loc->start(), true, true, false, Config->get_seamless_loop()); + } + } } } else { @@ -983,7 +1030,9 @@ Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool // located outside the loop: cancel looping directly, this is called from event handling context - set_play_loop (false); + if (!Config->get_loop_is_mode()) { + set_play_loop (false, _transport_speed); + } } else if (_transport_frame == al->start()) { @@ -1080,12 +1129,27 @@ Session::set_transport_speed (double speed, bool abort, bool clear_state, bool a stop_transport (abort); } - unset_play_loop (); + if (!Config->get_loop_is_mode()) { + unset_play_loop (); + } } else if (transport_stopped() && speed == 1.0) { /* we are stopped and we want to start rolling at speed 1 */ + if (Config->get_loop_is_mode() && play_loop) { + + Location *location = _locations->auto_loop_location(); + + if (location != 0) { + if (_transport_frame != location->start()) { + /* jump to start and then roll from there */ + request_locate (location->start(), true); + return; + } + } + } + if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) { set_track_monitor_input_status (false); } diff --git a/libs/fst/vstwin.c b/libs/fst/vstwin.c index a55d4e59aa..27fb3cbead 100644 --- a/libs/fst/vstwin.c +++ b/libs/fst/vstwin.c @@ -223,7 +223,7 @@ fst_new (void) fst->n_pending_keys = 0; fst->has_editor = 0; #ifdef PLATFORM_WINDOWS - fst->voffset = 36; + fst->voffset = 50; fst->hoffset = 0; #else /* linux + wine */ fst->voffset = 24; @@ -465,7 +465,7 @@ fst_move_window_into_view (VSTState* fst) { if (fst->windows_window) { #ifdef PLATFORM_WINDOWS - SetWindowPos ((HWND)(fst->windows_window), 0, fst->hoffset, fst->voffset, fst->width, fst->height, 0); + SetWindowPos ((HWND)(fst->windows_window), 0, fst->hoffset, fst->voffset, fst->width + fst->hoffset, fst->height + fst->voffset, 0); #else /* linux + wine */ SetWindowPos ((HWND)(fst->windows_window), 0, 0, 0, fst->width + fst->hoffset, fst->height + fst->voffset, 0); #endif