mirror of
https://github.com/Ardour/ardour.git
synced 2026-01-03 20:29:35 +01:00
merge -r12436:12545 from 3.0
git-svn-id: svn://localhost/ardour2/branches/3.0-SG@12546 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
4f9eb9862c
commit
8e1db53556
131 changed files with 2056 additions and 996 deletions
|
|
@ -89,6 +89,7 @@ typedef uint64_t microseconds_t;
|
|||
#include "gui_thread.h"
|
||||
#include "keyboard.h"
|
||||
#include "location_ui.h"
|
||||
#include "main_clock.h"
|
||||
#include "missing_file_dialog.h"
|
||||
#include "missing_plugin_dialog.h"
|
||||
#include "mixer_ui.h"
|
||||
|
|
@ -123,15 +124,13 @@ sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
|
|||
sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
|
||||
sigc::signal<void, framepos_t, bool, framepos_t> ARDOUR_UI::Clock;
|
||||
|
||||
bool could_be_a_valid_path (const std::string& path);
|
||||
|
||||
ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
|
||||
|
||||
: Gtkmm2ext::UI (PROGRAM_NAME, argcp, argvp)
|
||||
|
||||
, gui_object_state (new GUIObjectState)
|
||||
, primary_clock (new AudioClock (X_("primary"), false, X_("transport"), true, true, false, true))
|
||||
, secondary_clock (new AudioClock (X_("secondary"), false, X_("secondary"), true, true, false, true))
|
||||
, primary_clock (new MainClock (X_("primary"), false, X_("transport"), true, true, true, false, true))
|
||||
, secondary_clock (new MainClock (X_("secondary"), false, X_("secondary"), true, true, false, false, true))
|
||||
|
||||
/* big clock */
|
||||
|
||||
|
|
@ -2845,9 +2844,8 @@ ARDOUR_UI::show_splash ()
|
|||
void
|
||||
ARDOUR_UI::hide_splash ()
|
||||
{
|
||||
if (splash) {
|
||||
splash->hide();
|
||||
}
|
||||
delete splash;
|
||||
splash = 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ class ButtonJoiner;
|
|||
class ConnectionEditor;
|
||||
class KeyEditor;
|
||||
class LocationUIWindow;
|
||||
class MainClock;
|
||||
class Mixer_UI;
|
||||
class PublicEditor;
|
||||
class RCOptionEditor;
|
||||
|
|
@ -194,8 +195,8 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
|
|||
|
||||
GUIObjectState* gui_object_state;
|
||||
|
||||
AudioClock* primary_clock;
|
||||
AudioClock* secondary_clock;
|
||||
MainClock* primary_clock;
|
||||
MainClock* secondary_clock;
|
||||
void focus_on_clock ();
|
||||
|
||||
TimeInfoBox* time_info_box;
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@
|
|||
#include "audio_clock.h"
|
||||
#include "actions.h"
|
||||
#include "button_joiner.h"
|
||||
#include "main_clock.h"
|
||||
#include "utils.h"
|
||||
#include "theme_manager.h"
|
||||
#include "midi_tracer.h"
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "gui_thread.h"
|
||||
#include "keyeditor.h"
|
||||
#include "location_ui.h"
|
||||
#include "main_clock.h"
|
||||
#include "midi_tracer.h"
|
||||
#include "mixer_ui.h"
|
||||
#include "public_editor.h"
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@
|
|||
#include "window_proxy.h"
|
||||
#include "global_port_matrix.h"
|
||||
#include "location_ui.h"
|
||||
#include "main_clock.h"
|
||||
|
||||
#include <gtkmm2ext/application.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include "actions.h"
|
||||
#include "gui_thread.h"
|
||||
#include "public_editor.h"
|
||||
#include "main_clock.h"
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -57,20 +57,23 @@ static const gchar* _automation_mode_strings[] = {
|
|||
self = [ super init ];
|
||||
|
||||
if (self) {
|
||||
plugin_ui = apluginui;
|
||||
cocoa_parent = cp;
|
||||
plugin_ui = apluginui;
|
||||
top_level_parent = tlp;
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(cocoaParentActivationHandler:)
|
||||
name:NSWindowDidBecomeMainNotification
|
||||
object:nil];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(cocoaParentBecameKeyHandler:)
|
||||
name:NSWindowDidBecomeKeyNotification
|
||||
object:nil];
|
||||
}
|
||||
|
||||
if (cp) {
|
||||
cocoa_parent = cp;
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(cocoaParentActivationHandler:)
|
||||
name:NSWindowDidBecomeMainNotification
|
||||
object:nil];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(cocoaParentBecameKeyHandler:)
|
||||
name:NSWindowDidBecomeKeyNotification
|
||||
object:nil];
|
||||
}
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
|
@ -103,7 +106,7 @@ static const gchar* _automation_mode_strings[] = {
|
|||
|
||||
- (void)auViewResized:(NSNotification *)notification;
|
||||
{
|
||||
(void) notification;
|
||||
(void) notification; // stop complaints about unusued argument
|
||||
plugin_ui->cocoa_view_resized();
|
||||
}
|
||||
|
||||
|
|
@ -192,11 +195,13 @@ AUPluginUI::AUPluginUI (boost::shared_ptr<PluginInsert> insert)
|
|||
|
||||
AUPluginUI::~AUPluginUI ()
|
||||
{
|
||||
if (_notify) {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:_notify];
|
||||
}
|
||||
|
||||
if (cocoa_parent) {
|
||||
NSWindow* win = get_nswindow();
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:_notify];
|
||||
[win removeChildWindow:cocoa_parent];
|
||||
|
||||
}
|
||||
|
||||
#ifdef WITH_CARBON
|
||||
|
|
@ -302,6 +307,7 @@ AUPluginUI::create_cocoa_view ()
|
|||
string_compose ( "based on %1, there are %2 cocoa UI classes\n", dataSize, numberOfClasses));
|
||||
|
||||
cocoaViewInfo = (AudioUnitCocoaViewInfo *)malloc(dataSize);
|
||||
|
||||
if(AudioUnitGetProperty(*au->get_au(),
|
||||
kAudioUnitProperty_CocoaUI,
|
||||
kAudioUnitScope_Global,
|
||||
|
|
@ -315,8 +321,8 @@ AUPluginUI::create_cocoa_view ()
|
|||
factoryClassName = (NSString *)cocoaViewInfo->mCocoaAUViewClass[0];
|
||||
|
||||
DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("the factory name is %1 bundle is %2\n",
|
||||
factoryClassName, CocoaViewBundlePath));
|
||||
|
||||
[factoryClassName UTF8String], CocoaViewBundlePath));
|
||||
|
||||
} else {
|
||||
|
||||
DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("No cocoaUI property cocoaViewInfo = %1\n", cocoaViewInfo));
|
||||
|
|
@ -328,8 +334,6 @@ AUPluginUI::create_cocoa_view ()
|
|||
}
|
||||
}
|
||||
|
||||
NSRect crect = { { 0, 0 }, { 1, 1} };
|
||||
|
||||
// [A] Show custom UI if view has it
|
||||
|
||||
if (CocoaViewBundlePath && factoryClassName) {
|
||||
|
|
@ -354,8 +358,8 @@ AUPluginUI::create_cocoa_view ()
|
|||
return -1;
|
||||
}
|
||||
// make a factory
|
||||
id factoryInstance = [[[factoryClass alloc] init] autorelease];
|
||||
if (factoryInstance == nil) {
|
||||
id factory = [[[factoryClass alloc] init] autorelease];
|
||||
if (factory == nil) {
|
||||
error << _("AUPluginUI: Could not create an instance of the AU view factory") << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -363,7 +367,7 @@ AUPluginUI::create_cocoa_view ()
|
|||
DEBUG_TRACE (DEBUG::AudioUnits, "got a factory instance\n");
|
||||
|
||||
// make a view
|
||||
au_view = [factoryInstance uiViewForAudioUnit:*au->get_au() withSize:crect.size];
|
||||
au_view = [factory uiViewForAudioUnit:*au->get_au() withSize:NSZeroSize];
|
||||
|
||||
DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("view created @ %1\n", au_view));
|
||||
|
||||
|
|
@ -389,24 +393,10 @@ AUPluginUI::create_cocoa_view ()
|
|||
[(AUGenericView *)au_view setShowsExpertParameters:YES];
|
||||
}
|
||||
|
||||
// watch for size changes of the view
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:_notify
|
||||
selector:@selector(auViewResized:) name:NSViewBoundsDidChangeNotification
|
||||
object:au_view];
|
||||
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:_notify
|
||||
selector:@selector(auViewResized:) name:NSViewFrameDidChangeNotification
|
||||
object:au_view];
|
||||
|
||||
// Get the size of the new AU View's frame
|
||||
// Get the initial size of the new AU View's frame
|
||||
|
||||
NSRect packFrame;
|
||||
packFrame = [au_view frame];
|
||||
prefwidth = packFrame.size.width;
|
||||
prefheight = packFrame.size.height;
|
||||
low_box.set_size_request (prefwidth, prefheight);
|
||||
NSRect rect = [au_view frame];
|
||||
low_box.set_size_request (rect.size.width, rect.size.height);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -414,10 +404,35 @@ AUPluginUI::create_cocoa_view ()
|
|||
void
|
||||
AUPluginUI::cocoa_view_resized ()
|
||||
{
|
||||
NSRect packFrame = [au_view frame];
|
||||
prefwidth = packFrame.size.width;
|
||||
prefheight = packFrame.size.height;
|
||||
low_box.set_size_request (prefwidth, prefheight);
|
||||
GtkRequisition topsize = top_box.size_request ();
|
||||
NSWindow* window = get_nswindow ();
|
||||
NSSize oldContentSize= [window contentRectForFrameRect:[window frame]].size;
|
||||
NSSize newContentSize= [au_view frame].size;
|
||||
NSRect windowFrame= [window frame];
|
||||
|
||||
oldContentSize.height -= topsize.height;
|
||||
|
||||
float dy = oldContentSize.height - newContentSize.height;
|
||||
float dx = oldContentSize.width - newContentSize.width;
|
||||
|
||||
windowFrame.origin.y += dy;
|
||||
windowFrame.origin.x += dx;
|
||||
windowFrame.size.height -= dy;
|
||||
windowFrame.size.width -= dx;
|
||||
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:_notify
|
||||
name:NSViewFrameDidChangeNotification
|
||||
object:au_view];
|
||||
|
||||
NSUInteger old_auto_resize = [au_view autoresizingMask];
|
||||
|
||||
[au_view setAutoresizingMask:NSViewNotSizable];
|
||||
[window setFrame:windowFrame display:YES];
|
||||
[au_view setAutoresizingMask:old_auto_resize];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:_notify
|
||||
selector:@selector(auViewResized:) name:NSViewFrameDidChangeNotification
|
||||
object:au_view];
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -597,7 +612,15 @@ AUPluginUI::parent_cocoa_window ()
|
|||
NSPoint origin = { 0, a.height };
|
||||
|
||||
[au_view setFrameOrigin:origin];
|
||||
[view addSubview:au_view];
|
||||
[view addSubview:au_view positioned:NSWindowBelow relativeTo:nil];
|
||||
|
||||
// watch for size changes of the view
|
||||
|
||||
_notify = [ [NotificationObject alloc] initWithPluginUI:this andCocoaParent:nil andTopLevelParent:win ];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:_notify
|
||||
selector:@selector(auViewResized:) name:NSViewFrameDidChangeNotification
|
||||
object:au_view];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,8 @@ const double AudioClock::x_leading_padding = 6.0;
|
|||
|
||||
AudioClock::AudioClock (const string& clock_name, bool transient, const string& widget_name,
|
||||
bool allow_edit, bool follows_playhead, bool duration, bool with_info)
|
||||
: _name (clock_name)
|
||||
: ops_menu (0)
|
||||
, _name (clock_name)
|
||||
, is_transient (transient)
|
||||
, is_duration (duration)
|
||||
, editable (allow_edit)
|
||||
|
|
@ -71,7 +72,6 @@ AudioClock::AudioClock (const string& clock_name, bool transient, const string&
|
|||
, layout_x_offset (0)
|
||||
, em_width (0)
|
||||
, _edit_by_click_field (false)
|
||||
, ops_menu (0)
|
||||
, editing_attr (0)
|
||||
, foreground_attr (0)
|
||||
, first_height (0)
|
||||
|
|
|
|||
|
|
@ -87,6 +87,9 @@ class AudioClock : public CairoWidget, public ARDOUR::SessionHandlePtr
|
|||
protected:
|
||||
void render (cairo_t*);
|
||||
|
||||
virtual void build_ops_menu ();
|
||||
Gtk::Menu *ops_menu;
|
||||
|
||||
private:
|
||||
Mode _mode;
|
||||
std::string _name;
|
||||
|
|
@ -101,8 +104,6 @@ class AudioClock : public CairoWidget, public ARDOUR::SessionHandlePtr
|
|||
int em_width;
|
||||
bool _edit_by_click_field;
|
||||
|
||||
Gtk::Menu *ops_menu;
|
||||
|
||||
Glib::RefPtr<Pango::Layout> _layout;
|
||||
Glib::RefPtr<Pango::Layout> _left_layout;
|
||||
Glib::RefPtr<Pango::Layout> _right_layout;
|
||||
|
|
@ -197,8 +198,6 @@ class AudioClock : public CairoWidget, public ARDOUR::SessionHandlePtr
|
|||
framepos_t frames_from_minsec_string (const std::string&) const;
|
||||
framepos_t frames_from_audioframes_string (const std::string&) const;
|
||||
|
||||
void build_ops_menu ();
|
||||
|
||||
void session_configuration_changed (std::string);
|
||||
|
||||
Field index_to_field () const;
|
||||
|
|
|
|||
|
|
@ -199,13 +199,8 @@ AudioRegionView::init (Gdk::Color const & basic_color, bool wfd)
|
|||
if (!Profile->get_sae()) {
|
||||
gain_line.reset (new AudioRegionGainLine (line_name, *this, *group, audio_region()->envelope()));
|
||||
}
|
||||
|
||||
if (Config->get_show_region_gain()) {
|
||||
gain_line->show ();
|
||||
} else {
|
||||
gain_line->hide ();
|
||||
}
|
||||
|
||||
|
||||
update_envelope_visibility ();
|
||||
gain_line->reset ();
|
||||
|
||||
set_height (trackview.current_height());
|
||||
|
|
@ -499,9 +494,7 @@ AudioRegionView::set_height (gdouble height)
|
|||
if ((height/wcnt) < NAME_HIGHLIGHT_THRESH) {
|
||||
gain_line->hide ();
|
||||
} else {
|
||||
if (Config->get_show_region_gain ()) {
|
||||
gain_line->show ();
|
||||
}
|
||||
update_envelope_visibility ();
|
||||
}
|
||||
|
||||
gain_line->set_height ((uint32_t) rint (height - NAME_HIGHLIGHT_SIZE) - 2);
|
||||
|
|
@ -663,7 +656,8 @@ AudioRegionView::reset_fade_out_shape ()
|
|||
void
|
||||
AudioRegionView::reset_fade_out_shape_width (framecnt_t width)
|
||||
{
|
||||
if (dragging()) {
|
||||
if (dragging() && audio_region()->fade_out_is_xfade()) {
|
||||
/* we hide xfades while dragging regions */
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -857,20 +851,20 @@ AudioRegionView::temporarily_hide_envelope ()
|
|||
void
|
||||
AudioRegionView::unhide_envelope ()
|
||||
{
|
||||
if (gain_line) {
|
||||
gain_line->show ();
|
||||
}
|
||||
update_envelope_visibility ();
|
||||
}
|
||||
|
||||
void
|
||||
AudioRegionView::set_envelope_visible (bool yn)
|
||||
AudioRegionView::update_envelope_visibility ()
|
||||
{
|
||||
if (gain_line) {
|
||||
if (yn) {
|
||||
gain_line->show ();
|
||||
} else {
|
||||
gain_line->hide ();
|
||||
}
|
||||
if (!gain_line) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Config->get_show_region_gain() || trackview.editor().current_mouse_mode() == Editing::MouseGain) {
|
||||
gain_line->add_visibility (AutomationLine::Line);
|
||||
} else {
|
||||
gain_line->hide ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1035,7 +1029,7 @@ AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev)
|
|||
|
||||
/* don't create points that can't be seen */
|
||||
|
||||
set_envelope_visible (true);
|
||||
update_envelope_visibility ();
|
||||
|
||||
x = ev->button.x;
|
||||
y = ev->button.y;
|
||||
|
|
@ -1222,9 +1216,9 @@ AudioRegionView::entered (bool internal_editing)
|
|||
{
|
||||
trackview.editor().set_current_trimmable (_region);
|
||||
trackview.editor().set_current_movable (_region);
|
||||
|
||||
if (gain_line && Config->get_show_region_gain ()) {
|
||||
gain_line->show_all_control_points ();
|
||||
|
||||
if (gain_line && trackview.editor().current_mouse_mode() == Editing::MouseGain) {
|
||||
gain_line->add_visibility (AutomationLine::ControlPoints);
|
||||
}
|
||||
|
||||
if (fade_in_handle && !internal_editing) {
|
||||
|
|
@ -1239,8 +1233,8 @@ AudioRegionView::exited ()
|
|||
trackview.editor().set_current_trimmable (boost::shared_ptr<Trimmable>());
|
||||
trackview.editor().set_current_movable (boost::shared_ptr<Movable>());
|
||||
|
||||
if (gain_line) {
|
||||
gain_line->hide_all_but_selected_control_points ();
|
||||
if (gain_line && trackview.editor().current_mouse_mode() == Editing::MouseGain) {
|
||||
gain_line->remove_visibility (AutomationLine::ControlPoints);
|
||||
}
|
||||
|
||||
if (fade_in_handle) {
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ class AudioRegionView : public RegionView
|
|||
void temporarily_hide_envelope (); ///< Dangerous!
|
||||
void unhide_envelope (); ///< Dangerous!
|
||||
|
||||
void set_envelope_visible (bool);
|
||||
void update_envelope_visibility ();
|
||||
void set_waveform_visible (bool yn);
|
||||
void set_waveform_shape (ARDOUR::WaveformShape);
|
||||
void set_waveform_scale (ARDOUR::WaveformScale);
|
||||
|
|
@ -198,6 +198,8 @@ class AudioRegionView : public RegionView
|
|||
|
||||
void transients_changed();
|
||||
|
||||
AutomationLine::VisibleAspects automation_line_visibility () const;
|
||||
|
||||
private:
|
||||
void setup_fade_handle_positions ();
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@
|
|||
#include "time_axis_view.h"
|
||||
#include "point_selection.h"
|
||||
#include "automation_time_axis.h"
|
||||
#include "public_editor.h"
|
||||
|
||||
#include "ardour/event_type_map.h"
|
||||
#include "ardour/session.h"
|
||||
|
|
@ -77,11 +76,11 @@ AutomationLine::AutomationLine (const string& name, TimeAxisView& tv, ArdourCanv
|
|||
_our_time_converter = true;
|
||||
}
|
||||
|
||||
points_visible = false;
|
||||
_visible = Line;
|
||||
|
||||
update_pending = false;
|
||||
_uses_gain_mapping = false;
|
||||
no_draw = false;
|
||||
_visible = true;
|
||||
_is_boolean = false;
|
||||
terminal_points_can_slide = true;
|
||||
_height = 0;
|
||||
|
|
@ -136,27 +135,36 @@ AutomationLine::queue_reset ()
|
|||
void
|
||||
AutomationLine::show ()
|
||||
{
|
||||
if (alist->interpolation() != AutomationList::Discrete) {
|
||||
line->show();
|
||||
if (_visible & Line) {
|
||||
if (alist->interpolation() != AutomationList::Discrete) {
|
||||
line->show();
|
||||
} else {
|
||||
line->hide ();
|
||||
}
|
||||
} else {
|
||||
line->hide();
|
||||
}
|
||||
|
||||
if (points_visible) {
|
||||
if (_visible & ControlPoints) {
|
||||
for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) {
|
||||
(*i)->set_visible (true);
|
||||
(*i)->show ();
|
||||
}
|
||||
} else if (_visible & SelectedControlPoints) {
|
||||
for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) {
|
||||
(*i)->set_visible ((*i)->get_selected());
|
||||
}
|
||||
} else {
|
||||
for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) {
|
||||
(*i)->set_visible (false);
|
||||
}
|
||||
}
|
||||
|
||||
_visible = true;
|
||||
}
|
||||
|
||||
void
|
||||
AutomationLine::hide ()
|
||||
{
|
||||
line->hide();
|
||||
for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) {
|
||||
(*i)->hide();
|
||||
}
|
||||
_visible = false;
|
||||
set_visibility (VisibleAspects (0));
|
||||
}
|
||||
|
||||
double
|
||||
|
|
@ -238,7 +246,7 @@ AutomationLine::modify_point_y (ControlPoint& cp, double y)
|
|||
y = min (1.0, y);
|
||||
y = _height - (y * _height);
|
||||
|
||||
double const x = trackview.editor().frame_to_unit (_time_converter->to((*cp.model())->when) - _offset);
|
||||
double const x = trackview.editor().frame_to_unit_unrounded (_time_converter->to((*cp.model())->when) - _offset);
|
||||
|
||||
trackview.editor().session()->begin_reversible_command (_("automation event move"));
|
||||
trackview.editor().session()->add_command (
|
||||
|
|
@ -457,7 +465,7 @@ AutomationLine::start_drag_common (double x, float fraction)
|
|||
* @return x position and y fraction that were actually used (once clamped).
|
||||
*/
|
||||
pair<double, float>
|
||||
AutomationLine::drag_motion (double x, float fraction, bool ignore_x, bool with_push)
|
||||
AutomationLine::drag_motion (double const x, float fraction, bool ignore_x, bool with_push)
|
||||
{
|
||||
/* setup the points that are to be moved this time round */
|
||||
list<ControlPoint*> points = _drag_points;
|
||||
|
|
@ -469,49 +477,51 @@ AutomationLine::drag_motion (double x, float fraction, bool ignore_x, bool with_
|
|||
double dx = ignore_x ? 0 : (x - _drag_x);
|
||||
double dy = fraction - _last_drag_fraction;
|
||||
|
||||
/* find x limits */
|
||||
ControlPoint* before = 0;
|
||||
ControlPoint* after = 0;
|
||||
|
||||
for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) {
|
||||
if ((*i)->get_x() < points.front()->get_x()) {
|
||||
before = *i;
|
||||
}
|
||||
if ((*i)->get_x() > points.back()->get_x() && after == 0) {
|
||||
after = *i;
|
||||
}
|
||||
}
|
||||
|
||||
double const before_x = before ? before->get_x() : 0;
|
||||
double const after_x = after ? after->get_x() : DBL_MAX;
|
||||
|
||||
/* clamp x */
|
||||
for (list<ControlPoint*>::iterator i = points.begin(); i != points.end(); ++i) {
|
||||
/* Find the points that aren't being moved before and after
|
||||
this one on the control_points list
|
||||
*/
|
||||
|
||||
if ((*i)->can_slide() && !ignore_x) {
|
||||
ControlPoint* before = 0;
|
||||
ControlPoint* after = 0;
|
||||
|
||||
/* clamp min x */
|
||||
double const a = (*i)->get_x() + dx;
|
||||
double const b = before_x + 1;
|
||||
if (a < b) {
|
||||
dx += b - a;
|
||||
ControlPoint* last = 0;
|
||||
for (vector<ControlPoint*>::iterator j = control_points.begin(); j != control_points.end(); ++j) {
|
||||
|
||||
if (*j == *i) {
|
||||
|
||||
before = last;
|
||||
|
||||
vector<ControlPoint*>::iterator k = j;
|
||||
|
||||
/* Next point */
|
||||
++k;
|
||||
|
||||
/* Now move past any points that are being moved this time */
|
||||
while (find (points.begin(), points.end(), *k) != points.end() && k != control_points.end ()) {
|
||||
++k;
|
||||
}
|
||||
|
||||
if (k != control_points.end()) {
|
||||
after = *k;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* clamp max x */
|
||||
if (after) {
|
||||
|
||||
if (after_x - before_x < 2) {
|
||||
/* after and before are very close, so just leave this alone */
|
||||
dx = 0;
|
||||
} else {
|
||||
double const a = (*i)->get_x() + dx;
|
||||
double const b = after_x - 1;
|
||||
if (a > b) {
|
||||
dx -= a - b;
|
||||
}
|
||||
}
|
||||
if (find (points.begin(), points.end(), *j) == points.end ()) {
|
||||
/* This point isn't being moved, so it's the `last' point we've seen */
|
||||
last = *j;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clamp dx for this point */
|
||||
double const before_x = before ? before->get_x() : 0;
|
||||
double const after_x = after ? after->get_x() : DBL_MAX;
|
||||
|
||||
double tx = (*i)->get_x() + dx;
|
||||
tx = max (tx, before_x);
|
||||
tx = min (tx, after_x);
|
||||
dx = tx - (*i)->get_x ();
|
||||
}
|
||||
|
||||
/* clamp y */
|
||||
|
|
@ -527,7 +537,7 @@ AutomationLine::drag_motion (double x, float fraction, bool ignore_x, bool with_
|
|||
|
||||
pair<double, float> const clamped (_drag_x + dx, _last_drag_fraction + dy);
|
||||
_drag_distance += dx;
|
||||
_drag_x = x;
|
||||
_drag_x += dx;
|
||||
_last_drag_fraction = fraction;
|
||||
|
||||
for (list<ControlPoint*>::iterator i = _drag_points.begin(); i != _drag_points.end(); ++i) {
|
||||
|
|
@ -548,7 +558,9 @@ AutomationLine::drag_motion (double x, float fraction, bool ignore_x, bool with_
|
|||
}
|
||||
|
||||
_drag_had_movement = true;
|
||||
did_push = with_push;
|
||||
if (with_push) {
|
||||
did_push = with_push;
|
||||
}
|
||||
|
||||
return clamped;
|
||||
}
|
||||
|
|
@ -597,7 +609,7 @@ AutomationLine::sync_model_with_view_point (ControlPoint& cp, framecnt_t distanc
|
|||
|
||||
/* if xval has not changed, set it directly from the model to avoid rounding errors */
|
||||
|
||||
if (view_x == trackview.editor().frame_to_unit (_time_converter->to ((*cp.model())->when)) - _offset) {
|
||||
if (view_x == trackview.editor().frame_to_unit_unrounded (_time_converter->to ((*cp.model())->when)) - _offset) {
|
||||
view_x = (*cp.model())->when - _offset;
|
||||
} else {
|
||||
view_x = trackview.editor().unit_to_frame (view_x);
|
||||
|
|
@ -609,11 +621,6 @@ AutomationLine::sync_model_with_view_point (ControlPoint& cp, framecnt_t distanc
|
|||
view_to_model_coord_y (view_y);
|
||||
|
||||
alist->modify (cp.model(), view_x, view_y);
|
||||
|
||||
if (did_push) {
|
||||
/* move all points after cp by the same distance */
|
||||
alist->slide (cp.model()++, _time_converter->from (distance));
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -623,7 +630,7 @@ AutomationLine::control_points_adjacent (double xval, uint32_t & before, uint32_
|
|||
ControlPoint *acp = 0;
|
||||
double unit_xval;
|
||||
|
||||
unit_xval = trackview.editor().frame_to_unit (xval);
|
||||
unit_xval = trackview.editor().frame_to_unit_unrounded (xval);
|
||||
|
||||
for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) {
|
||||
|
||||
|
|
@ -807,7 +814,7 @@ AutomationLine::reset_callback (const Evoral::ControlList& events)
|
|||
* zoom and scroll into account).
|
||||
*/
|
||||
|
||||
tx = trackview.editor().frame_to_unit (tx);
|
||||
tx = trackview.editor().frame_to_unit_unrounded (tx);
|
||||
|
||||
/* convert from canonical view height (0..1.0) to actual
|
||||
* height coordinates (using X11's top-left rooted system)
|
||||
|
|
@ -896,44 +903,31 @@ AutomationLine::set_list (boost::shared_ptr<ARDOUR::AutomationList> list)
|
|||
}
|
||||
|
||||
void
|
||||
AutomationLine::show_all_control_points ()
|
||||
AutomationLine::add_visibility (VisibleAspects va)
|
||||
{
|
||||
if (_is_boolean) {
|
||||
// show the line but don't allow any control points
|
||||
return;
|
||||
}
|
||||
|
||||
points_visible = true;
|
||||
|
||||
for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) {
|
||||
if (!(*i)->visible()) {
|
||||
(*i)->show ();
|
||||
(*i)->set_visible (true);
|
||||
}
|
||||
}
|
||||
_visible = VisibleAspects (_visible | va);
|
||||
show ();
|
||||
}
|
||||
|
||||
void
|
||||
AutomationLine::hide_all_but_selected_control_points ()
|
||||
AutomationLine::set_visibility (VisibleAspects va)
|
||||
{
|
||||
if (alist->interpolation() == AutomationList::Discrete) {
|
||||
return;
|
||||
}
|
||||
_visible = va;
|
||||
show ();
|
||||
}
|
||||
|
||||
points_visible = false;
|
||||
|
||||
for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) {
|
||||
if (!(*i)->get_selected()) {
|
||||
(*i)->set_visible (false);
|
||||
}
|
||||
}
|
||||
void
|
||||
AutomationLine::remove_visibility (VisibleAspects va)
|
||||
{
|
||||
_visible = VisibleAspects (_visible & ~va);
|
||||
show ();
|
||||
}
|
||||
|
||||
void
|
||||
AutomationLine::track_entered()
|
||||
{
|
||||
if (alist->interpolation() != AutomationList::Discrete) {
|
||||
show_all_control_points();
|
||||
add_visibility (ControlPoints);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -941,7 +935,7 @@ void
|
|||
AutomationLine::track_exited()
|
||||
{
|
||||
if (alist->interpolation() != AutomationList::Discrete) {
|
||||
hide_all_but_selected_control_points();
|
||||
remove_visibility (ControlPoints);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1012,11 +1006,10 @@ void
|
|||
AutomationLine::interpolation_changed (AutomationList::InterpolationStyle style)
|
||||
{
|
||||
if (style == AutomationList::Discrete) {
|
||||
show_all_control_points();
|
||||
set_visibility (ControlPoints);
|
||||
line->hide();
|
||||
} else {
|
||||
hide_all_but_selected_control_points();
|
||||
line->show();
|
||||
set_visibility (Line);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1060,13 +1053,11 @@ AutomationLine::add_visible_control_point (uint32_t view_index, uint32_t pi, dou
|
|||
|
||||
/* finally, control visibility */
|
||||
|
||||
if (_visible && points_visible) {
|
||||
if (_visible & ControlPoints) {
|
||||
control_points[view_index]->show ();
|
||||
control_points[view_index]->set_visible (true);
|
||||
} else {
|
||||
if (!points_visible) {
|
||||
control_points[view_index]->set_visible (false);
|
||||
}
|
||||
control_points[view_index]->set_visible (false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -57,6 +57,12 @@ namespace Gnome {
|
|||
class AutomationLine : public sigc::trackable, public PBD::StatefulDestructible
|
||||
{
|
||||
public:
|
||||
enum VisibleAspects {
|
||||
Line = 0x1,
|
||||
ControlPoints = 0x2,
|
||||
SelectedControlPoints = 0x4
|
||||
};
|
||||
|
||||
AutomationLine (const std::string& name, TimeAxisView&, ArdourCanvas::Group&,
|
||||
boost::shared_ptr<ARDOUR::AutomationList>,
|
||||
Evoral::TimeConverter<double, ARDOUR::framepos_t>* converter = 0);
|
||||
|
|
@ -85,17 +91,20 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulDestructible
|
|||
uint32_t npoints() const { return control_points.size(); }
|
||||
|
||||
std::string name() const { return _name; }
|
||||
bool visible() const { return _visible; }
|
||||
bool visible() const { return _visible != VisibleAspects(0); }
|
||||
guint32 height() const { return _height; }
|
||||
|
||||
void set_line_color (uint32_t);
|
||||
uint32_t get_line_color() const { return _line_color; }
|
||||
|
||||
void show ();
|
||||
void hide ();
|
||||
void set_height (guint32);
|
||||
void set_uses_gain_mapping (bool yn);
|
||||
bool get_uses_gain_mapping () const { return _uses_gain_mapping; }
|
||||
void set_visibility (VisibleAspects);
|
||||
void add_visibility (VisibleAspects);
|
||||
void remove_visibility (VisibleAspects);
|
||||
|
||||
void hide ();
|
||||
void set_height (guint32);
|
||||
void set_uses_gain_mapping (bool yn);
|
||||
bool get_uses_gain_mapping () const { return _uses_gain_mapping; }
|
||||
|
||||
TimeAxisView& trackview;
|
||||
|
||||
|
|
@ -113,9 +122,6 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulDestructible
|
|||
void set_list(boost::shared_ptr<ARDOUR::AutomationList> list);
|
||||
boost::shared_ptr<ARDOUR::AutomationList> the_list() const { return alist; }
|
||||
|
||||
void show_all_control_points ();
|
||||
void hide_all_but_selected_control_points ();
|
||||
|
||||
void track_entered();
|
||||
void track_exited();
|
||||
|
||||
|
|
@ -157,13 +163,14 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulDestructible
|
|||
/** true if _time_converter belongs to us (ie we should delete it on destruction) */
|
||||
bool _our_time_converter;
|
||||
|
||||
bool _visible : 1;
|
||||
VisibleAspects _visible;
|
||||
|
||||
bool _uses_gain_mapping : 1;
|
||||
bool terminal_points_can_slide : 1;
|
||||
bool update_pending : 1;
|
||||
bool no_draw : 1;
|
||||
bool _is_boolean : 1;
|
||||
bool points_visible : 1;
|
||||
/** true if we did a push at any point during the current drag */
|
||||
bool did_push;
|
||||
|
||||
ArdourCanvas::Group& _parent_group;
|
||||
|
|
@ -195,6 +202,7 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulDestructible
|
|||
*/
|
||||
ARDOUR::framecnt_t _offset;
|
||||
|
||||
void show ();
|
||||
void reset_line_coords (ControlPoint&);
|
||||
void add_visible_control_point (uint32_t, uint32_t, double, double, ARDOUR::AutomationList::iterator, uint32_t);
|
||||
double control_point_box_size ();
|
||||
|
|
|
|||
|
|
@ -89,8 +89,7 @@ AutomationRegionView::create_line (boost::shared_ptr<ARDOUR::AutomationList> lis
|
|||
&_source_relative_time_converter));
|
||||
_line->set_colors();
|
||||
_line->set_height ((uint32_t)rint(trackview.current_height() - NAME_HIGHLIGHT_SIZE));
|
||||
_line->show();
|
||||
_line->show_all_control_points();
|
||||
_line->set_visibility (AutomationLine::VisibleAspects (AutomationLine::Line|AutomationLine::ControlPoints));
|
||||
_line->set_maximum_time (_region->length());
|
||||
_line->set_offset (_region->start ());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -730,7 +730,7 @@ AutomationTimeAxisView::add_line (boost::shared_ptr<AutomationLine> line)
|
|||
/* pick up the current state */
|
||||
automation_state_changed ();
|
||||
|
||||
line->show();
|
||||
line->add_visibility (AutomationLine::Line);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ class AutomationTimeAxisView : public TimeAxisView {
|
|||
void get_selectables (ARDOUR::framepos_t start, ARDOUR::framepos_t end, double top, double bot, std::list<Selectable *>&);
|
||||
void get_inverted_selectables (Selection&, std::list<Selectable*>& results);
|
||||
|
||||
void show_timestretch (framepos_t /*start*/, framepos_t /*end*/) {}
|
||||
void show_timestretch (framepos_t /*start*/, framepos_t /*end*/, int /*layers*/, int /*layer*/) {}
|
||||
void hide_timestretch () {}
|
||||
|
||||
/* editing operations */
|
||||
|
|
|
|||
|
|
@ -213,6 +213,9 @@ CanvasPatchChange::on_event (GdkEvent* ev)
|
|||
_region.patch_left (this);
|
||||
break;
|
||||
|
||||
case GDK_BUTTON_RELEASE:
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -281,6 +281,7 @@ Editor::Editor ()
|
|||
|
||||
, _region_selection_change_updates_region_list (true)
|
||||
, _following_mixer_selection (false)
|
||||
, _control_point_toggled_on_press (false)
|
||||
{
|
||||
constructed = false;
|
||||
|
||||
|
|
@ -4526,16 +4527,15 @@ Editor::get_regions_from_selection ()
|
|||
* the edit point is `mouse' and the mouse is over an unselected
|
||||
* region. In this case, start with just that region.
|
||||
*
|
||||
* Then, make an initial track list of the tracks that these
|
||||
* regions are on, and if the edit point is not `mouse', add the
|
||||
* selected tracks.
|
||||
* Then, add equivalent regions in active edit groups to the region list.
|
||||
*
|
||||
* Look at this track list and add any other tracks that are on the
|
||||
* same active edit-enabled route group as one of the initial tracks.
|
||||
* Then, search the list of selected tracks to find any selected tracks which
|
||||
* do not contain regions already in the region list. If there are no selected
|
||||
* tracks and 'No Selection = All Tracks' is active, search all tracks rather
|
||||
* than just the selected.
|
||||
*
|
||||
* Finally take the initial region list and add any regions that are
|
||||
* under the edit point on one of the tracks on the track list to get
|
||||
* the returned region list.
|
||||
* Add any regions that are under the edit point on these tracks to get the
|
||||
* returned region list.
|
||||
*
|
||||
* The rationale here is that the mouse edit point is special in that
|
||||
* its position describes both a time and a track; the other edit
|
||||
|
|
@ -4563,22 +4563,40 @@ Editor::get_regions_from_selection_and_edit_point ()
|
|||
tracks = selection->tracks;
|
||||
}
|
||||
|
||||
/* Add any other tracks that have regions that are in the same
|
||||
/* Add any other regions that are in the same
|
||||
edit-activated route group as one of our regions.
|
||||
*/
|
||||
for (RegionSelection::iterator i = regions.begin (); i != regions.end(); ++i) {
|
||||
regions = get_equivalent_regions (regions, ARDOUR::Properties::edit.property_id);
|
||||
framepos_t const where = get_preferred_edit_position ();
|
||||
|
||||
RouteGroup* g = (*i)->get_time_axis_view().route_group ();
|
||||
|
||||
if (g && g->is_active() && g->is_edit()) {
|
||||
tracks.add (axis_views_from_routes (g->route_list()));
|
||||
}
|
||||
if (_route_groups->all_group_active_button().get_active() && tracks.empty()) {
|
||||
/* tracks is empty (no track selected), and 'No Selection = All Tracks'
|
||||
* is enabled, so consider all tracks
|
||||
*/
|
||||
tracks = track_views;
|
||||
}
|
||||
|
||||
if (!tracks.empty()) {
|
||||
/* now find regions that are at the edit position on those tracks */
|
||||
framepos_t const where = get_preferred_edit_position ();
|
||||
get_regions_at (regions, where, tracks);
|
||||
/* now search the selected tracks for tracks which don't
|
||||
already contain regions to be acted upon, and get regions at
|
||||
the edit point on those tracks too.
|
||||
*/
|
||||
TrackViewList tracks_without_relevant_regions;
|
||||
|
||||
for (TrackViewList::iterator t = tracks.begin (); t != tracks.end (); ++t) {
|
||||
if (!regions.involves (**t)) {
|
||||
/* there are no equivalent regions on this track */
|
||||
tracks_without_relevant_regions.push_back (*t);
|
||||
}
|
||||
}
|
||||
|
||||
if (!tracks_without_relevant_regions.empty()) {
|
||||
/* there are some selected tracks with neither selected
|
||||
* regions or their equivalents: act upon all regions in
|
||||
* those tracks
|
||||
*/
|
||||
get_regions_at (regions, where, tracks_without_relevant_regions);
|
||||
}
|
||||
}
|
||||
|
||||
return regions;
|
||||
|
|
|
|||
|
|
@ -239,6 +239,10 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
|||
return rint ((double) frame / (double) frames_per_unit);
|
||||
}
|
||||
|
||||
double frame_to_unit_unrounded (framepos_t frame) const {
|
||||
return frame / frames_per_unit;
|
||||
}
|
||||
|
||||
double frame_to_unit (double frame) const {
|
||||
return rint (frame / frames_per_unit);
|
||||
}
|
||||
|
|
@ -1951,8 +1955,8 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
|||
gint left_automation_track ();
|
||||
|
||||
void reset_canvas_action_sensitivity (bool);
|
||||
void set_gain_envelope_visibility (bool);
|
||||
void set_region_gain_visibility (RegionView*, bool);
|
||||
void set_gain_envelope_visibility ();
|
||||
void set_region_gain_visibility (RegionView*);
|
||||
void toggle_gain_envelope_active ();
|
||||
void reset_region_gain_envelopes ();
|
||||
|
||||
|
|
@ -2092,6 +2096,9 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
|||
|
||||
void toggle_sound_midi_notes ();
|
||||
|
||||
/** Flag for a bit of a hack wrt control point selection; see set_selected_control_point_from_click */
|
||||
bool _control_point_toggled_on_press;
|
||||
|
||||
friend class Drag;
|
||||
friend class RegionDrag;
|
||||
friend class RegionMoveDrag;
|
||||
|
|
|
|||
|
|
@ -1483,7 +1483,7 @@ Editor::parameter_changed (std::string p)
|
|||
}
|
||||
}
|
||||
} else if (p == "show-region-gain") {
|
||||
set_gain_envelope_visibility (Config->get_show_region_gain ());
|
||||
set_gain_envelope_visibility ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2818,6 +2818,10 @@ ControlPointDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/)
|
|||
event->button.x + 10, event->button.y + 10);
|
||||
|
||||
_editor->verbose_cursor()->show ();
|
||||
|
||||
if (!_point->can_slide ()) {
|
||||
_x_constrained = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -2871,7 +2875,7 @@ ControlPointDrag::motion (GdkEvent* event, bool)
|
|||
|
||||
bool const push = Keyboard::modifier_state_contains (event->button.state, Keyboard::PrimaryModifier);
|
||||
|
||||
_point->line().drag_motion (_editor->frame_to_unit (cx_frames), fraction, false, push);
|
||||
_point->line().drag_motion (_editor->frame_to_unit_unrounded (cx_frames), fraction, false, push);
|
||||
|
||||
_editor->verbose_cursor()->set_text (_point->line().get_verbose_cursor_string (fraction));
|
||||
}
|
||||
|
|
@ -3245,11 +3249,16 @@ void
|
|||
TimeFXDrag::motion (GdkEvent* event, bool)
|
||||
{
|
||||
RegionView* rv = _primary;
|
||||
StreamView* cv = rv->get_time_axis_view().view ();
|
||||
|
||||
pair<TimeAxisView*, double> const tv = _editor->trackview_by_y_position (grab_y());
|
||||
int layer = tv.first->layer_display() == Overlaid ? 0 : tv.second;
|
||||
int layers = tv.first->layer_display() == Overlaid ? 1 : cv->layers();
|
||||
|
||||
framepos_t const pf = adjusted_current_frame (event);
|
||||
|
||||
if (pf > rv->region()->position()) {
|
||||
rv->get_time_axis_view().show_timestretch (rv->region()->position(), pf);
|
||||
rv->get_time_axis_view().show_timestretch (rv->region()->position(), pf, layers, layer);
|
||||
}
|
||||
|
||||
show_verbose_cursor_time (pf);
|
||||
|
|
|
|||
|
|
@ -247,61 +247,38 @@ Editor::set_current_movable (boost::shared_ptr<Movable> m)
|
|||
void
|
||||
Editor::set_canvas_cursor ()
|
||||
{
|
||||
if (_internal_editing) {
|
||||
switch (mouse_mode) {
|
||||
case MouseRange:
|
||||
current_canvas_cursor = _cursors->selector;
|
||||
break;
|
||||
|
||||
switch (mouse_mode) {
|
||||
case MouseDraw:
|
||||
current_canvas_cursor = _cursors->midi_pencil;
|
||||
break;
|
||||
case MouseObject:
|
||||
current_canvas_cursor = which_grabber_cursor();
|
||||
break;
|
||||
|
||||
case MouseObject:
|
||||
current_canvas_cursor = which_grabber_cursor();
|
||||
break;
|
||||
case MouseDraw:
|
||||
current_canvas_cursor = _cursors->midi_pencil;
|
||||
break;
|
||||
|
||||
case MouseTimeFX:
|
||||
current_canvas_cursor = _cursors->midi_resize;
|
||||
break;
|
||||
case MouseGain:
|
||||
current_canvas_cursor = _cursors->cross_hair;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
case MouseZoom:
|
||||
if (Keyboard::the_keyboard().key_is_down (GDK_Control_L)) {
|
||||
current_canvas_cursor = _cursors->zoom_out;
|
||||
} else {
|
||||
current_canvas_cursor = _cursors->zoom_in;
|
||||
}
|
||||
break;
|
||||
|
||||
} else {
|
||||
case MouseTimeFX:
|
||||
current_canvas_cursor = _cursors->time_fx; // just use playhead
|
||||
break;
|
||||
|
||||
switch (mouse_mode) {
|
||||
case MouseRange:
|
||||
current_canvas_cursor = _cursors->selector;
|
||||
break;
|
||||
|
||||
case MouseObject:
|
||||
current_canvas_cursor = which_grabber_cursor();
|
||||
break;
|
||||
|
||||
case MouseDraw:
|
||||
/* shouldn't be possible, but just cover it anyway ... */
|
||||
current_canvas_cursor = _cursors->midi_pencil;
|
||||
break;
|
||||
|
||||
case MouseGain:
|
||||
current_canvas_cursor = _cursors->cross_hair;
|
||||
break;
|
||||
|
||||
case MouseZoom:
|
||||
if (Keyboard::the_keyboard().key_is_down (GDK_Control_L)) {
|
||||
current_canvas_cursor = _cursors->zoom_out;
|
||||
} else {
|
||||
current_canvas_cursor = _cursors->zoom_in;
|
||||
}
|
||||
break;
|
||||
|
||||
case MouseTimeFX:
|
||||
current_canvas_cursor = _cursors->time_fx; // just use playhead
|
||||
break;
|
||||
|
||||
case MouseAudition:
|
||||
current_canvas_cursor = _cursors->speaker;
|
||||
break;
|
||||
}
|
||||
case MouseAudition:
|
||||
current_canvas_cursor = _cursors->speaker;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (_join_object_range_state) {
|
||||
|
|
@ -473,6 +450,7 @@ Editor::mouse_mode_toggled (MouseMode m)
|
|||
}
|
||||
|
||||
set_canvas_cursor ();
|
||||
set_gain_envelope_visibility ();
|
||||
|
||||
MouseModeChanged (); /* EMIT SIGNAL */
|
||||
}
|
||||
|
|
@ -583,7 +561,7 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
|
|||
(mouse_mode != MouseRange) &&
|
||||
(mouse_mode != MouseDraw)) ||
|
||||
((event->type != GDK_BUTTON_PRESS && event->type != GDK_BUTTON_RELEASE) || event->button.button > 3) ||
|
||||
internal_editing()) {
|
||||
(internal_editing() && mouse_mode != MouseTimeFX)) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -1157,8 +1135,8 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
|
|||
/* drag notes if we're in internal edit mode */
|
||||
_drags->set (new NoteResizeDrag (this, item), event, current_canvas_cursor);
|
||||
return true;
|
||||
} else if ((!internal_editing() || dynamic_cast<AudioRegionView*> (clicked_regionview)) && clicked_regionview) {
|
||||
/* do time-FX if we're not in internal edit mode, or we are but we clicked on an audio region */
|
||||
} else if (clicked_regionview) {
|
||||
/* do time-FX */
|
||||
_drags->set (new TimeFXDrag (this, item, clicked_regionview, selection->regions.by_layer()), event);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1369,6 +1369,13 @@ Editor::temporal_zoom (gdouble fpu)
|
|||
}
|
||||
|
||||
nfpu = fpu;
|
||||
|
||||
// Imposing an arbitrary limit to zoom out as too much zoom out produces
|
||||
// segfaults for lack of memory. If somebody decides this is not high enough I
|
||||
// believe it can be raisen to higher values but some limit must be in place.
|
||||
if (nfpu > 8e+08) {
|
||||
nfpu = 8e+08;
|
||||
}
|
||||
|
||||
new_page_size = (framepos_t) floor (_canvas_width * nfpu);
|
||||
half_page_size = new_page_size / 2;
|
||||
|
|
@ -4720,8 +4727,14 @@ Editor::insert_patch_change (bool from_context)
|
|||
|
||||
const framepos_t p = get_preferred_edit_position (false, from_context);
|
||||
|
||||
/* XXX: bit of a hack; use the MIDNAM from the first selected region;
|
||||
there may be more than one, but the PatchChangeDialog can only offer
|
||||
one set of patch menus.
|
||||
*/
|
||||
MidiRegionView* first = dynamic_cast<MidiRegionView*> (rs.front ());
|
||||
|
||||
Evoral::PatchChange<Evoral::MusicalTime> empty (0, 0, 0, 0);
|
||||
PatchChangeDialog d (0, _session, empty, Gtk::Stock::ADD);
|
||||
PatchChangeDialog d (0, _session, empty, first->model_name(), first->custom_device_mode(), Gtk::Stock::ADD);
|
||||
|
||||
if (d.run() == RESPONSE_CANCEL) {
|
||||
return;
|
||||
|
|
@ -4851,16 +4864,16 @@ Editor::reset_region_gain_envelopes ()
|
|||
}
|
||||
|
||||
void
|
||||
Editor::set_region_gain_visibility (RegionView* rv, bool yn)
|
||||
Editor::set_region_gain_visibility (RegionView* rv)
|
||||
{
|
||||
AudioRegionView* arv = dynamic_cast<AudioRegionView*> (rv);
|
||||
if (arv) {
|
||||
arv->set_envelope_visible (yn);
|
||||
arv->update_envelope_visibility();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editor::set_gain_envelope_visibility (bool yn)
|
||||
Editor::set_gain_envelope_visibility ()
|
||||
{
|
||||
if (!_session) {
|
||||
return;
|
||||
|
|
@ -4869,7 +4882,7 @@ Editor::set_gain_envelope_visibility (bool yn)
|
|||
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
|
||||
AudioTimeAxisView* v = dynamic_cast<AudioTimeAxisView*>(*i);
|
||||
if (v) {
|
||||
v->audio_view()->foreach_regionview (sigc::bind (sigc::mem_fun (this, &Editor::set_region_gain_visibility), yn));
|
||||
v->audio_view()->foreach_regionview (sigc::mem_fun (this, &Editor::set_region_gain_visibility));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5916,6 +5929,10 @@ Editor::split_region_at_points (boost::shared_ptr<Region> r, AnalysisFeatureList
|
|||
plist.add (ARDOUR::Properties::layer, 0);
|
||||
|
||||
boost::shared_ptr<Region> nr = RegionFactory::create (r->sources(), plist, false);
|
||||
/* because we set annouce to false, manually add the new region to the
|
||||
RegionFactory map
|
||||
*/
|
||||
RegionFactory::map_add (nr);
|
||||
|
||||
pl->add_region (nr, r->position() + pos);
|
||||
|
||||
|
|
@ -5940,6 +5957,10 @@ Editor::split_region_at_points (boost::shared_ptr<Region> r, AnalysisFeatureList
|
|||
plist.add (ARDOUR::Properties::layer, 0);
|
||||
|
||||
boost::shared_ptr<Region> nr = RegionFactory::create (r->sources(), plist, false);
|
||||
/* because we set annouce to false, manually add the new region to the
|
||||
RegionFactory map
|
||||
*/
|
||||
RegionFactory::map_add (nr);
|
||||
pl->add_region (nr, r->position() + pos);
|
||||
|
||||
if (select_new) {
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@
|
|||
#include "utils.h"
|
||||
#include "editor_regions.h"
|
||||
#include "editor_drag.h"
|
||||
#include "main_clock.h"
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -318,19 +318,39 @@ Editor::set_selected_control_point_from_click (bool press, Selection::Operation
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!press) {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (op) {
|
||||
case Selection::Set:
|
||||
selection->set (clicked_control_point);
|
||||
if (press) {
|
||||
selection->set (clicked_control_point);
|
||||
}
|
||||
break;
|
||||
case Selection::Add:
|
||||
selection->add (clicked_control_point);
|
||||
if (press) {
|
||||
selection->add (clicked_control_point);
|
||||
}
|
||||
break;
|
||||
case Selection::Toggle:
|
||||
selection->toggle (clicked_control_point);
|
||||
/* This is a bit of a hack; if we Primary-Click-Drag a control
|
||||
point (for push drag) we want the point we clicked on to be
|
||||
selected, otherwise we end up confusingly dragging an
|
||||
unselected point. So here we ensure that the point is selected
|
||||
after the press, and if we subsequently get a release (meaning no
|
||||
drag occurred) we set things up so that the toggle has happened.
|
||||
*/
|
||||
if (press && !selection->selected (clicked_control_point)) {
|
||||
/* This is the button press, and the control point is not selected; make it so,
|
||||
in case this press leads to a drag. Also note that having done this, we don't
|
||||
need to toggle again on release.
|
||||
*/
|
||||
selection->toggle (clicked_control_point);
|
||||
_control_point_toggled_on_press = true;
|
||||
} else if (!press && !_control_point_toggled_on_press) {
|
||||
/* This is the release, and the point wasn't toggled on the press, so do it now */
|
||||
selection->toggle (clicked_control_point);
|
||||
} else {
|
||||
/* Reset our flag */
|
||||
_control_point_toggled_on_press = false;
|
||||
}
|
||||
break;
|
||||
case Selection::Extend:
|
||||
/* XXX */
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ sigc::signal<void,RouteGroup*> GainMeterBase::ResetGroupPeakDisplays;
|
|||
|
||||
GainMeter::MetricPatterns GainMeter::metric_patterns;
|
||||
Glib::RefPtr<Gdk::Pixbuf> GainMeter::slider;
|
||||
Glib::RefPtr<Gdk::Pixbuf> GainMeter::slider_desensitised;
|
||||
|
||||
|
||||
void
|
||||
|
|
@ -70,10 +71,15 @@ GainMeter::setup_slider_pix ()
|
|||
if ((slider = ::get_icon ("fader_belt")) == 0) {
|
||||
throw failed_constructor();
|
||||
}
|
||||
|
||||
if ((slider_desensitised = ::get_icon ("fader_belt_desensitised")) == 0) {
|
||||
throw failed_constructor();
|
||||
}
|
||||
}
|
||||
|
||||
GainMeterBase::GainMeterBase (Session* s,
|
||||
const Glib::RefPtr<Gdk::Pixbuf>& pix,
|
||||
const Glib::RefPtr<Gdk::Pixbuf>& pix_desensitised,
|
||||
bool horizontal,
|
||||
int fader_length)
|
||||
: gain_adjustment (gain_to_slider_position_with_max (1.0, Config->get_max_gain()), 0.0, 1.0, 0.01, 0.1)
|
||||
|
|
@ -95,11 +101,13 @@ GainMeterBase::GainMeterBase (Session* s,
|
|||
|
||||
if (horizontal) {
|
||||
gain_slider = manage (new HSliderController (pix,
|
||||
pix_desensitised,
|
||||
&gain_adjustment,
|
||||
fader_length,
|
||||
false));
|
||||
} else {
|
||||
gain_slider = manage (new VSliderController (pix,
|
||||
pix_desensitised,
|
||||
&gain_adjustment,
|
||||
fader_length,
|
||||
false));
|
||||
|
|
@ -839,7 +847,7 @@ GainMeterBase::on_theme_changed()
|
|||
}
|
||||
|
||||
GainMeter::GainMeter (Session* s, int fader_length)
|
||||
: GainMeterBase (s, slider, false, fader_length)
|
||||
: GainMeterBase (s, slider, slider_desensitised, false, fader_length)
|
||||
, gain_display_box(true, 0)
|
||||
, hbox(true, 2)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ namespace Gtk {
|
|||
class GainMeterBase : virtual public sigc::trackable, ARDOUR::SessionHandlePtr
|
||||
{
|
||||
public:
|
||||
GainMeterBase (ARDOUR::Session*, const Glib::RefPtr<Gdk::Pixbuf>& pix,
|
||||
GainMeterBase (ARDOUR::Session*, const Glib::RefPtr<Gdk::Pixbuf>&, const Glib::RefPtr<Gdk::Pixbuf> &,
|
||||
bool horizontal, int);
|
||||
virtual ~GainMeterBase ();
|
||||
|
||||
|
|
@ -231,6 +231,7 @@ class GainMeter : public GainMeterBase, public Gtk::VBox
|
|||
std::vector<ARDOUR::DataType> _types;
|
||||
|
||||
static Glib::RefPtr<Gdk::Pixbuf> slider;
|
||||
static Glib::RefPtr<Gdk::Pixbuf> slider_desensitised;
|
||||
};
|
||||
|
||||
#endif /* __ardour_gtk_gain_meter_h__ */
|
||||
|
|
|
|||
BIN
gtk2_ardour/icons/fader_belt_desensitised.png
Normal file
BIN
gtk2_ardour/icons/fader_belt_desensitised.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.9 KiB |
BIN
gtk2_ardour/icons/fader_belt_h_desensitised.png
Normal file
BIN
gtk2_ardour/icons/fader_belt_h_desensitised.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
BIN
gtk2_ardour/icons/fader_belt_h_thin_desensitised.png
Normal file
BIN
gtk2_ardour/icons/fader_belt_h_thin_desensitised.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 929 B |
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2001-2007 Paul Davis
|
||||
Copyright (C) 2001-2012 Paul Davis
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -141,35 +141,14 @@ fixup_bundle_environment (int, char* [])
|
|||
|
||||
_NSGetExecutablePath (execpath, &pathsz);
|
||||
|
||||
std::string dir_path = Glib::path_get_dirname (execpath);
|
||||
std::string path;
|
||||
const char *cstr = getenv ("PATH");
|
||||
std::string exec_dir = Glib::path_get_dirname (execpath);
|
||||
std::string bundle_dir;
|
||||
std::string userconfigdir = user_config_directory().to_string();
|
||||
|
||||
/* ensure that we find any bundled executables (e.g. JACK),
|
||||
and find them before any instances of the same name
|
||||
elsewhere in PATH
|
||||
*/
|
||||
bundle_dir = Glib::path_get_dirname (exec_dir);
|
||||
|
||||
path = dir_path;
|
||||
|
||||
/* JACK is often in /usr/local/bin and since Info.plist refuses to
|
||||
set PATH, we have to force this in order to discover a running
|
||||
instance of JACK ...
|
||||
*/
|
||||
|
||||
path += ':';
|
||||
path += "/usr/local/bin";
|
||||
|
||||
if (cstr) {
|
||||
path += ':';
|
||||
path += cstr;
|
||||
}
|
||||
setenv ("PATH", path.c_str(), 1);
|
||||
|
||||
export_search_path (dir_path, "ARDOUR_DLL_PATH", "/../lib");
|
||||
|
||||
path += dir_path;
|
||||
path += "/../Resources";
|
||||
export_search_path (bundle_dir, "ARDOUR_DLL_PATH", "/lib");
|
||||
|
||||
/* inside an OS X .app bundle, there is no difference
|
||||
between DATA and CONFIG locations, since OS X doesn't
|
||||
|
|
@ -177,17 +156,13 @@ fixup_bundle_environment (int, char* [])
|
|||
machine-independent shared data.
|
||||
*/
|
||||
|
||||
export_search_path (dir_path, "ARDOUR_DATA_PATH", "/../Resources");
|
||||
export_search_path (dir_path, "ARDOUR_CONFIG_PATH", "/../Resources");
|
||||
export_search_path (dir_path, "ARDOUR_INSTANT_XML_PATH", "/../Resources");
|
||||
|
||||
export_search_path (dir_path, "LADSPA_PATH", "/../Plugins");
|
||||
export_search_path (dir_path, "VAMP_PATH", "/../lib");
|
||||
export_search_path (dir_path, "SUIL_MODULE_DIR", "/../lib");
|
||||
|
||||
path = dir_path;
|
||||
path += "/../lib/clearlooks";
|
||||
setenv ("GTK_PATH", path.c_str(), 1);
|
||||
export_search_path (bundle_dir, "ARDOUR_DATA_PATH", "/Resources");
|
||||
export_search_path (bundle_dir, "ARDOUR_CONFIG_PATH", "/Resources");
|
||||
export_search_path (bundle_dir, "ARDOUR_INSTANT_XML_PATH", "/Resources");
|
||||
export_search_path (bundle_dir, "LADSPA_PATH", "/Plugins");
|
||||
export_search_path (bundle_dir, "VAMP_PATH", "/lib");
|
||||
export_search_path (bundle_dir, "SUIL_MODULE_DIR", "/lib");
|
||||
export_search_path (bundle_dir, "GTK_PATH", "/lib/clearlooks");
|
||||
|
||||
/* unset GTK_RC_FILES so that we only load the RC files that we define
|
||||
*/
|
||||
|
|
@ -195,12 +170,7 @@ fixup_bundle_environment (int, char* [])
|
|||
unsetenv ("GTK_RC_FILES");
|
||||
|
||||
if (!ARDOUR::translations_are_disabled ()) {
|
||||
|
||||
path = dir_path;
|
||||
path += "/../Resources/locale";
|
||||
|
||||
localedir = strdup (path.c_str());
|
||||
setenv ("GTK_LOCALEDIR", localedir, 1);
|
||||
export_search_path (bundle_dir, "GTK_LOCALEDIR", "/Resources/locale");
|
||||
}
|
||||
|
||||
/* write a pango.rc file and tell pango to use it. we'd love
|
||||
|
|
@ -211,62 +181,35 @@ fixup_bundle_environment (int, char* [])
|
|||
actually exists ...
|
||||
*/
|
||||
|
||||
try {
|
||||
sys::create_directories (user_config_directory ());
|
||||
}
|
||||
catch (const sys::filesystem_error& ex) {
|
||||
error << _("Could not create user configuration directory") << endmsg;
|
||||
}
|
||||
|
||||
sys::path pangopath = user_config_directory();
|
||||
pangopath /= "pango.rc";
|
||||
path = pangopath.to_string();
|
||||
if (g_mkdir_with_parents (userconfigdir.c_str(), 0755) < 0) {
|
||||
error << string_compose (_("cannot create user ardour folder %1 (%2)"), userconfigdir, strerror (errno))
|
||||
<< endmsg;
|
||||
return;
|
||||
}
|
||||
|
||||
path = Glib::build_filename (userconfigdir, "pango.rc");
|
||||
std::ofstream pangorc (path.c_str());
|
||||
if (!pangorc) {
|
||||
error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
|
||||
return;
|
||||
} else {
|
||||
pangorc << "[Pango]\nModuleFiles=";
|
||||
|
||||
pangopath = dir_path;
|
||||
pangopath /= "..";
|
||||
pangopath /= "Resources";
|
||||
pangopath /= "pango.modules";
|
||||
|
||||
pangorc << pangopath.to_string() << endl;
|
||||
|
||||
pangorc << "[Pango]\nModuleFiles="
|
||||
<< Glib::build_filename (bundle_dir, "Resources/pango.modules")
|
||||
<< endl;
|
||||
pangorc.close ();
|
||||
|
||||
setenv ("PANGO_RC_FILE", path.c_str(), 1);
|
||||
}
|
||||
|
||||
// gettext charset aliases
|
||||
// gettext charset aliases XXX do we really need this, since the path
|
||||
// is totally wrong?
|
||||
|
||||
setenv ("CHARSETALIASDIR", path.c_str(), 1);
|
||||
|
||||
// font config
|
||||
|
||||
path = dir_path;
|
||||
path += "/../Resources/fonts.conf";
|
||||
|
||||
setenv ("FONTCONFIG_FILE", path.c_str(), 1);
|
||||
setenv ("FONTCONFIG_FILE", Glib::build_filename (bundle_dir, "Resources/fonts.conf").c_str(), 1);
|
||||
|
||||
// GDK Pixbuf loader module file
|
||||
|
||||
path = dir_path;
|
||||
path += "/../Resources/gdk-pixbuf.loaders";
|
||||
|
||||
setenv ("GDK_PIXBUF_MODULE_FILE", path.c_str(), 1);
|
||||
|
||||
if (getenv ("ARDOUR_WITH_JACK")) {
|
||||
// JACK driver dir
|
||||
|
||||
path = dir_path;
|
||||
path += "/../lib";
|
||||
|
||||
setenv ("JACK_DRIVER_DIR", path.c_str(), 1);
|
||||
}
|
||||
setenv ("GDK_PIXBUF_MODULE_FILE", Glib::build_filename (bundle_dir, "Resources/gdk-pixbuf.loaders").c_str(), 1);
|
||||
}
|
||||
|
||||
#else
|
||||
|
|
@ -284,9 +227,9 @@ fixup_bundle_environment (int /*argc*/, char* argv[])
|
|||
|
||||
EnvironmentalProtectionAgency::set_global_epa (new EnvironmentalProtectionAgency (true, "PREBUNDLE_ENV"));
|
||||
|
||||
Glib::ustring dir_path = Glib::path_get_dirname (Glib::path_get_dirname (argv[0]));
|
||||
Glib::ustring path;
|
||||
Glib::ustring userconfigdir = user_config_directory().to_string();
|
||||
std::string path;
|
||||
std::string dir_path = Glib::path_get_dirname (Glib::path_get_dirname (argv[0]));
|
||||
std::string userconfigdir = user_config_directory().to_string();
|
||||
|
||||
/* note that this function is POSIX/Linux specific, so using / as
|
||||
a dir separator in this context is just fine.
|
||||
|
|
@ -296,14 +239,11 @@ fixup_bundle_environment (int /*argc*/, char* argv[])
|
|||
export_search_path (dir_path, "ARDOUR_CONFIG_PATH", "/etc");
|
||||
export_search_path (dir_path, "ARDOUR_INSTANT_XML_PATH", "/share");
|
||||
export_search_path (dir_path, "ARDOUR_DATA_PATH", "/share");
|
||||
|
||||
export_search_path (dir_path, "LADSPA_PATH", "/../plugins");
|
||||
export_search_path (dir_path, "LADSPA_PATH", "/plugins");
|
||||
export_search_path (dir_path, "VAMP_PATH", "/lib");
|
||||
export_search_path (dir_path, "SUIL_MODULE_DIR", "/lib");
|
||||
|
||||
path = dir_path;
|
||||
path += "/lib/clearlooks";
|
||||
setenv ("GTK_PATH", path.c_str(), 1);
|
||||
export_search_path (dir_path, "GTK_PATH", "/lib/clearlooks");
|
||||
|
||||
/* unset GTK_RC_FILES so that we only load the RC files that we define
|
||||
*/
|
||||
|
|
@ -311,11 +251,7 @@ fixup_bundle_environment (int /*argc*/, char* argv[])
|
|||
unsetenv ("GTK_RC_FILES");
|
||||
|
||||
if (!ARDOUR::translations_are_disabled ()) {
|
||||
path = dir_path;
|
||||
path += "/share/locale";
|
||||
|
||||
localedir = strdup (path.c_str());
|
||||
setenv ("GTK_LOCALEDIR", localedir, 1);
|
||||
export_search_path (dir_path, "GTK_LOCALEDIR", "/share/locale");
|
||||
}
|
||||
|
||||
/* Tell fontconfig where to find fonts.conf. Use the system version
|
||||
|
|
@ -330,8 +266,7 @@ fixup_bundle_environment (int /*argc*/, char* argv[])
|
|||
|
||||
path = Glib::build_filename (dir_path, "etc/fonts/fonts.conf");
|
||||
setenv ("FONTCONFIG_FILE", path.c_str(), 1);
|
||||
path = Glib::build_filename (dir_path, "etc/fonts");
|
||||
setenv ("FONTCONFIG_PATH", "/etc/fonts", 1);
|
||||
export_search_path (dir_path, "FONTCONFIG_PATH", "/etc/fonts");
|
||||
}
|
||||
|
||||
/* write a pango.rc file and tell pango to use it. we'd love
|
||||
|
|
@ -348,18 +283,14 @@ fixup_bundle_environment (int /*argc*/, char* argv[])
|
|||
return;
|
||||
}
|
||||
|
||||
Glib::ustring mpath;
|
||||
|
||||
path = Glib::build_filename (userconfigdir, "pango.rc");
|
||||
|
||||
std::ofstream pangorc (path.c_str());
|
||||
if (!pangorc) {
|
||||
error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
|
||||
} else {
|
||||
mpath = Glib::build_filename (userconfigdir, "pango.modules");
|
||||
|
||||
pangorc << "[Pango]\nModuleFiles=";
|
||||
pangorc << mpath << endl;
|
||||
pangorc << "[Pango]\nModuleFiles="
|
||||
<< Glib::build_filename (userconfigdir, "pango.modules")
|
||||
<< endl;
|
||||
pangorc.close ();
|
||||
}
|
||||
|
||||
|
|
@ -369,8 +300,7 @@ fixup_bundle_environment (int /*argc*/, char* argv[])
|
|||
to specify where it lives.
|
||||
*/
|
||||
|
||||
mpath = Glib::build_filename (userconfigdir, "gdk-pixbuf.loaders");
|
||||
setenv ("GDK_PIXBUF_MODULE_FILE", mpath.c_str(), 1);
|
||||
setenv ("GDK_PIXBUF_MODULE_FILE", Glib::build_filename (userconfigdir, "gdk-pixbuf.loaders").c_str(), 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -423,10 +353,6 @@ sigpipe_handler (int /*signal*/)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_LV2
|
||||
void close_external_ui_windows();
|
||||
#endif
|
||||
|
||||
#ifdef WINDOWS_VST_SUPPORT
|
||||
|
||||
extern int windows_vst_gui_init (int* argc, char** argv[]);
|
||||
|
|
@ -534,9 +460,6 @@ int main (int argc, char *argv[])
|
|||
ARDOUR::cleanup ();
|
||||
pthread_cancel_all ();
|
||||
|
||||
#ifdef HAVE_LV2
|
||||
close_external_ui_windows();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#ifdef WINDOWS_VST_SUPPORT
|
||||
|
|
|
|||
68
gtk2_ardour/main_clock.cc
Normal file
68
gtk2_ardour/main_clock.cc
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
Copyright (C) 2012 Paul Davis
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
#include "ardour/rc_configuration.h"
|
||||
#include "main_clock.h"
|
||||
#include "i18n.h"
|
||||
|
||||
using namespace Gtk;
|
||||
|
||||
MainClock::MainClock (
|
||||
const std::string& clock_name,
|
||||
bool is_transient,
|
||||
const std::string& widget_name,
|
||||
bool editable,
|
||||
bool follows_playhead,
|
||||
bool primary,
|
||||
bool duration,
|
||||
bool with_info
|
||||
)
|
||||
: AudioClock (clock_name, is_transient, widget_name, editable, follows_playhead, duration, with_info)
|
||||
, _primary (primary)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
MainClock::build_ops_menu ()
|
||||
{
|
||||
using namespace Menu_Helpers;
|
||||
|
||||
AudioClock::build_ops_menu ();
|
||||
|
||||
MenuList& ops_items = ops_menu->items();
|
||||
ops_items.push_back (SeparatorElem ());
|
||||
ops_items.push_back (CheckMenuElem (_("Display delta to edit cursor"), sigc::mem_fun (*this, &MainClock::display_delta_to_edit_cursor)));
|
||||
CheckMenuItem* c = dynamic_cast<CheckMenuItem *> (&ops_items.back());
|
||||
if (_primary) {
|
||||
c->set_active (ARDOUR::Config->get_primary_clock_delta_edit_cursor ());
|
||||
} else {
|
||||
c->set_active (ARDOUR::Config->get_secondary_clock_delta_edit_cursor ());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MainClock::display_delta_to_edit_cursor ()
|
||||
{
|
||||
if (_primary) {
|
||||
ARDOUR::Config->set_primary_clock_delta_edit_cursor (!ARDOUR::Config->get_primary_clock_delta_edit_cursor ());
|
||||
} else {
|
||||
ARDOUR::Config->set_secondary_clock_delta_edit_cursor (!ARDOUR::Config->get_secondary_clock_delta_edit_cursor ());
|
||||
}
|
||||
}
|
||||
33
gtk2_ardour/main_clock.h
Normal file
33
gtk2_ardour/main_clock.h
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
Copyright (C) 2012 Paul Davis
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
#include "audio_clock.h"
|
||||
|
||||
/** A simple subclass of AudioClock that adds the `display delta to edit cursor' option to its context menu */
|
||||
class MainClock : public AudioClock
|
||||
{
|
||||
public:
|
||||
MainClock (const std::string &, bool, const std::string &, bool, bool, bool primary, bool duration = false, bool with_info = false);
|
||||
|
||||
private:
|
||||
|
||||
void build_ops_menu ();
|
||||
void display_delta_to_edit_cursor ();
|
||||
bool _primary;
|
||||
};
|
||||
|
|
@ -113,6 +113,10 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &
|
|||
_note_group->raise_to_top();
|
||||
PublicEditor::DropDownKeys.connect (sigc::mem_fun (*this, &MidiRegionView::drop_down_keys));
|
||||
|
||||
/* Look up MIDNAM details from our MidiTimeAxisView */
|
||||
MidiTimeAxisView& mtv = dynamic_cast<MidiTimeAxisView&> (tv);
|
||||
midi_patch_settings_changed (mtv.midi_patch_model (), mtv.midi_patch_custom_device_node ());
|
||||
|
||||
Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&MidiRegionView::parameter_changed, this, _1), gui_context());
|
||||
connect_to_diskstream ();
|
||||
|
||||
|
|
@ -149,6 +153,10 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &
|
|||
_note_group->raise_to_top();
|
||||
PublicEditor::DropDownKeys.connect (sigc::mem_fun (*this, &MidiRegionView::drop_down_keys));
|
||||
|
||||
/* Look up MIDNAM details from our MidiTimeAxisView */
|
||||
MidiTimeAxisView& mtv = dynamic_cast<MidiTimeAxisView&> (tv);
|
||||
midi_patch_settings_changed (mtv.midi_patch_model (), mtv.midi_patch_custom_device_node ());
|
||||
|
||||
connect_to_diskstream ();
|
||||
|
||||
SelectionCleared.connect (_selection_cleared_connection, invalidator (*this), boost::bind (&MidiRegionView::selection_cleared, this, _1), gui_context ());
|
||||
|
|
@ -327,7 +335,10 @@ MidiRegionView::canvas_event(GdkEvent* ev)
|
|||
return trackview.editor().toggle_internal_editing_from_double_click (ev);
|
||||
}
|
||||
|
||||
if (!trackview.editor().internal_editing()) {
|
||||
if ((!trackview.editor().internal_editing() && trackview.editor().current_mouse_mode() != MouseGain) ||
|
||||
(trackview.editor().current_mouse_mode() == MouseTimeFX) ||
|
||||
(trackview.editor().current_mouse_mode() == MouseZoom)) {
|
||||
// handle non-draw modes elsewhere
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -388,6 +399,13 @@ MidiRegionView::enter_notify (GdkEventCrossing* ev)
|
|||
group->grab_focus();
|
||||
}
|
||||
|
||||
// if current operation is non-operational in a midi region, change the cursor to so indicate
|
||||
if (trackview.editor().current_mouse_mode() == MouseGain) {
|
||||
Editor* editor = dynamic_cast<Editor *> (&trackview.editor());
|
||||
pre_enter_cursor = editor->get_canvas_cursor();
|
||||
editor->set_canvas_cursor(editor->cursors()->timebar);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -399,6 +417,11 @@ MidiRegionView::leave_notify (GdkEventCrossing*)
|
|||
trackview.editor().verbose_cursor()->hide ();
|
||||
remove_ghost_note ();
|
||||
|
||||
if (pre_enter_cursor) {
|
||||
Editor* editor = dynamic_cast<Editor *> (&trackview.editor());
|
||||
editor->set_canvas_cursor(pre_enter_cursor);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -596,8 +619,8 @@ MidiRegionView::motion (GdkEventMotion* ev)
|
|||
editor.verbose_cursor()->hide ();
|
||||
return true;
|
||||
} else if (m == MouseObject) {
|
||||
|
||||
editor.drags()->set (new MidiRubberbandSelectDrag (dynamic_cast<Editor *> (&editor), this), (GdkEvent *) ev);
|
||||
clear_selection ();
|
||||
_mouse_state = SelectRectDragging;
|
||||
return true;
|
||||
} else if (m == MouseRange) {
|
||||
|
|
@ -1939,9 +1962,7 @@ MidiRegionView::delete_note (boost::shared_ptr<NoteType> n)
|
|||
void
|
||||
MidiRegionView::clear_selection_except (ArdourCanvas::CanvasNoteEvent* ev, bool signal)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
for (Selection::iterator i = _selection.begin(); i != _selection.end(); ) {
|
||||
for (Selection::iterator i = _selection.begin(); i != _selection.end(); ) {
|
||||
if ((*i) != ev) {
|
||||
Selection::iterator tmp = i;
|
||||
++tmp;
|
||||
|
|
@ -1949,7 +1970,6 @@ MidiRegionView::clear_selection_except (ArdourCanvas::CanvasNoteEvent* ev, bool
|
|||
(*i)->set_selected (false);
|
||||
(*i)->hide_velocity ();
|
||||
_selection.erase (i);
|
||||
changed = true;
|
||||
|
||||
i = tmp;
|
||||
} else {
|
||||
|
|
@ -1961,7 +1981,7 @@ MidiRegionView::clear_selection_except (ArdourCanvas::CanvasNoteEvent* ev, bool
|
|||
selection.
|
||||
*/
|
||||
|
||||
if (changed && signal) {
|
||||
if (signal) {
|
||||
SelectionCleared (this); /* EMIT SIGNAL */
|
||||
}
|
||||
}
|
||||
|
|
@ -3628,7 +3648,7 @@ MidiRegionView::trim_front_ending ()
|
|||
void
|
||||
MidiRegionView::edit_patch_change (ArdourCanvas::CanvasPatchChange* pc)
|
||||
{
|
||||
PatchChangeDialog d (&_source_relative_time_converter, trackview.session(), *pc->patch (), Gtk::Stock::APPLY);
|
||||
PatchChangeDialog d (&_source_relative_time_converter, trackview.session(), *pc->patch (), _model_name, _custom_device_mode, Gtk::Stock::APPLY);
|
||||
if (d.run () != Gtk::RESPONSE_ACCEPT) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -292,6 +292,16 @@ public:
|
|||
void trim_front_ending ();
|
||||
|
||||
void create_note_at (framepos_t, double, double, bool);
|
||||
|
||||
void clear_selection (bool signal = true) { clear_selection_except (0, signal); }
|
||||
|
||||
std::string model_name () const {
|
||||
return _model_name;
|
||||
}
|
||||
|
||||
std::string custom_device_mode () const {
|
||||
return _custom_device_mode;
|
||||
}
|
||||
|
||||
protected:
|
||||
/** Allows derived types to specify their visibility requirements
|
||||
|
|
@ -318,7 +328,10 @@ private:
|
|||
friend class MidiRubberbandSelectDrag;
|
||||
friend class MidiVerticalSelectDrag;
|
||||
|
||||
/** Emitted when the selection has been cleared in one MidiRegionView */
|
||||
/** Emitted when the selection has been cleared in one MidiRegionView,
|
||||
* with the expectation that others will clear their selections in
|
||||
* sympathy.
|
||||
*/
|
||||
static PBD::Signal1<void, MidiRegionView*> SelectionCleared;
|
||||
PBD::ScopedConnection _selection_cleared_connection;
|
||||
void selection_cleared (MidiRegionView *);
|
||||
|
|
@ -353,7 +366,6 @@ private:
|
|||
ARDOUR::MidiModel::TimeType end_delta);
|
||||
|
||||
void clear_selection_except (ArdourCanvas::CanvasNoteEvent* ev, bool signal = true);
|
||||
void clear_selection (bool signal = true) { clear_selection_except (0, signal); }
|
||||
void update_drag_selection (double last_x, double x, double last_y, double y, bool extend);
|
||||
void update_vertical_drag_selection (double last_y, double y, bool extend);
|
||||
|
||||
|
|
|
|||
|
|
@ -647,3 +647,14 @@ MidiStreamView::resume_updates ()
|
|||
draw_note_lines ();
|
||||
apply_note_range_to_regions ();
|
||||
}
|
||||
|
||||
void
|
||||
MidiStreamView::leave_internal_edit_mode ()
|
||||
{
|
||||
StreamView::leave_internal_edit_mode ();
|
||||
for (RegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) {
|
||||
MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (*i);
|
||||
assert (mrv);
|
||||
mrv->clear_selection ();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,6 +76,8 @@ class MidiStreamView : public StreamView
|
|||
|
||||
void redisplay_track ();
|
||||
|
||||
void leave_internal_edit_mode ();
|
||||
|
||||
inline double contents_height() const
|
||||
{ return (child_height() - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE - 2); }
|
||||
|
||||
|
|
|
|||
|
|
@ -199,14 +199,14 @@ MidiTimeAxisView::set_route (boost::shared_ptr<Route> rt)
|
|||
_model_selector.append_text(m->c_str());
|
||||
}
|
||||
|
||||
|
||||
_model_selector.signal_changed().connect(sigc::mem_fun(*this, &MidiTimeAxisView::model_changed));
|
||||
|
||||
_custom_device_mode_selector.signal_changed().connect(
|
||||
sigc::mem_fun(*this, &MidiTimeAxisView::custom_device_mode_changed));
|
||||
|
||||
// TODO: persist the choice
|
||||
// this initializes the comboboxes and sends out the signal
|
||||
_model_selector.set_active(0);
|
||||
_model_selector.set_active_text (gui_property (X_("midnam-model-name")));
|
||||
_custom_device_mode_selector.set_active_text (gui_property (X_("midnam-custom-device-mode")));
|
||||
|
||||
midi_controls_hbox->pack_start(_channel_selector, true, false);
|
||||
if (!patch_manager.all_models().empty()) {
|
||||
|
|
@ -317,12 +317,15 @@ MidiTimeAxisView::model_changed()
|
|||
}
|
||||
|
||||
_custom_device_mode_selector.set_active(0);
|
||||
|
||||
set_gui_property (X_("midnam-model-name"), midi_patch_model ());
|
||||
}
|
||||
|
||||
void MidiTimeAxisView::custom_device_mode_changed()
|
||||
void
|
||||
MidiTimeAxisView::custom_device_mode_changed()
|
||||
{
|
||||
_midi_patch_settings_changed.emit(_model_selector.get_active_text(),
|
||||
_custom_device_mode_selector.get_active_text());
|
||||
_midi_patch_settings_changed.emit (midi_patch_model (), midi_patch_custom_device_node ());
|
||||
set_gui_property (X_("midnam-custom-device-mode"), midi_patch_custom_device_node ());
|
||||
}
|
||||
|
||||
MidiStreamView*
|
||||
|
|
@ -1203,3 +1206,15 @@ MidiTimeAxisView::note_range_changed ()
|
|||
set_gui_property ("note-range-min", (int) midi_view()->lowest_note ());
|
||||
set_gui_property ("note-range-max", (int) midi_view()->highest_note ());
|
||||
}
|
||||
|
||||
string
|
||||
MidiTimeAxisView::midi_patch_model () const
|
||||
{
|
||||
return _model_selector.get_active_text ();
|
||||
}
|
||||
|
||||
string
|
||||
MidiTimeAxisView::midi_patch_custom_device_node () const
|
||||
{
|
||||
return _custom_device_mode_selector.get_active_text ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,6 +102,9 @@ class MidiTimeAxisView : public RouteTimeAxisView
|
|||
|
||||
uint8_t get_channel_for_add () const;
|
||||
|
||||
std::string midi_patch_model () const;
|
||||
std::string midi_patch_custom_device_node () const;
|
||||
|
||||
protected:
|
||||
void start_step_editing ();
|
||||
void stop_step_editing ();
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ MouseCursors::MouseCursors ()
|
|||
|
||||
{
|
||||
RefPtr<Pixbuf> p (::get_icon ("zoom_in_cursor"));
|
||||
zoom_in = new Cursor (Display::get_default(), p, 5, 5);
|
||||
zoom_in = new Cursor (Display::get_default(), p, 10, 5);
|
||||
}
|
||||
|
||||
{
|
||||
|
|
@ -49,7 +49,7 @@ MouseCursors::MouseCursors ()
|
|||
{
|
||||
RefPtr<Bitmap> source = Bitmap::create ((char const *) speaker_cursor_bits, speaker_cursor_width, speaker_cursor_height);
|
||||
RefPtr<Bitmap> mask = Bitmap::create ((char const *) speaker_cursor_mask_bits, speaker_cursor_width, speaker_cursor_height);
|
||||
speaker = new Cursor (source, mask, ffg, fbg, speaker_cursor_x_hot, speaker_cursor_y_hot);
|
||||
speaker = new Cursor (source, mask, ffg, fbg, speaker_cursor_width >> 1, speaker_cursor_height >> 1);
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
|||
|
|
@ -176,7 +176,13 @@ FaderOption::FaderOption (string const & i, string const & n, sigc::slot<gain_t>
|
|||
throw failed_constructor ();
|
||||
}
|
||||
|
||||
_pix_desensitised = ::get_icon (X_("fader_belt_h_desensitised"));
|
||||
if (_pix_desensitised == 0) {
|
||||
throw failed_constructor ();
|
||||
}
|
||||
|
||||
_db_slider = manage (new HSliderController (_pix,
|
||||
_pix_desensitised,
|
||||
&_db_adjustment,
|
||||
115,
|
||||
false));
|
||||
|
|
|
|||
|
|
@ -362,6 +362,7 @@ private:
|
|||
Gtk::Adjustment _db_adjustment;
|
||||
Gtkmm2ext::HSliderController* _db_slider;
|
||||
Glib::RefPtr<Gdk::Pixbuf> _pix;
|
||||
Glib::RefPtr<Gdk::Pixbuf> _pix_desensitised;
|
||||
Gtk::Entry _db_display;
|
||||
Gtk::Label _label;
|
||||
Gtk::HBox _box;
|
||||
|
|
|
|||
|
|
@ -20,10 +20,13 @@
|
|||
|
||||
#include <gtkmm/stock.h>
|
||||
#include <gtkmm/table.h>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include "ardour/midi_patch_manager.h"
|
||||
#include "ardour/beats_frames_converter.h"
|
||||
#include "patch_change_dialog.h"
|
||||
#include "i18n.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace Gtk;
|
||||
|
||||
/** @param tc If non-0, a time converter for this patch change. If 0, time control will be desensitized */
|
||||
|
|
@ -31,14 +34,19 @@ PatchChangeDialog::PatchChangeDialog (
|
|||
const ARDOUR::BeatsFramesConverter* tc,
|
||||
ARDOUR::Session* session,
|
||||
Evoral::PatchChange<Evoral::MusicalTime> const & patch,
|
||||
string const & model_name,
|
||||
string const & custom_device_node,
|
||||
const Gtk::BuiltinStockID& ok
|
||||
)
|
||||
: ArdourDialog (_("Patch Change"), true)
|
||||
, _time_converter (tc)
|
||||
, _model_name (model_name)
|
||||
, _custom_device_mode (custom_device_node)
|
||||
, _time (X_("patchchangetime"), true, "", true, false)
|
||||
, _channel (*manage (new Adjustment (1, 1, 16, 1, 4)))
|
||||
, _program (*manage (new Adjustment (1, 1, 128, 1, 16)))
|
||||
, _bank (*manage (new Adjustment (1, 1, 16384, 1, 64)))
|
||||
, _ignore_signals (false)
|
||||
{
|
||||
Table* t = manage (new Table (4, 2));
|
||||
Label* l;
|
||||
|
|
@ -58,13 +66,30 @@ PatchChangeDialog::PatchChangeDialog (
|
|||
_time.set (_time_converter->to (patch.time ()), true);
|
||||
}
|
||||
|
||||
l = manage (new Label (_("Patch Bank")));
|
||||
l->set_alignment (0, 0.5);
|
||||
t->attach (*l, 0, 1, r, r + 1);
|
||||
t->attach (_bank_combo, 1, 2, r, r + 1);
|
||||
++r;
|
||||
|
||||
_bank_combo.signal_changed().connect (sigc::mem_fun (*this, &PatchChangeDialog::bank_combo_changed));
|
||||
|
||||
l = manage (new Label (_("Patch")));
|
||||
l->set_alignment (0, 0.5);
|
||||
t->attach (*l, 0, 1, r, r + 1);
|
||||
t->attach (_patch_combo, 1, 2, r, r + 1);
|
||||
++r;
|
||||
|
||||
_patch_combo.signal_changed().connect (sigc::mem_fun (*this, &PatchChangeDialog::patch_combo_changed));
|
||||
|
||||
l = manage (new Label (_("Channel")));
|
||||
l->set_alignment (0, 0.5);
|
||||
t->attach (*l, 0, 1, r, r + 1);
|
||||
t->attach (_channel, 1, 2, r, r + 1);
|
||||
++r;
|
||||
|
||||
|
||||
_channel.set_value (patch.channel() + 1);
|
||||
_channel.signal_changed().connect (sigc::mem_fun (*this, &PatchChangeDialog::channel_changed));
|
||||
|
||||
l = manage (new Label (_("Program")));
|
||||
l->set_alignment (0, 0.5);
|
||||
|
|
@ -73,6 +98,7 @@ PatchChangeDialog::PatchChangeDialog (
|
|||
++r;
|
||||
|
||||
_program.set_value (patch.program () + 1);
|
||||
_program.signal_changed().connect (sigc::mem_fun (*this, &PatchChangeDialog::program_changed));
|
||||
|
||||
l = manage (new Label (_("Bank")));
|
||||
l->set_alignment (0, 0.5);
|
||||
|
|
@ -81,6 +107,7 @@ PatchChangeDialog::PatchChangeDialog (
|
|||
++r;
|
||||
|
||||
_bank.set_value (patch.bank() + 1);
|
||||
_bank.signal_changed().connect (sigc::mem_fun (*this, &PatchChangeDialog::bank_changed));
|
||||
|
||||
get_vbox()->add (*t);
|
||||
|
||||
|
|
@ -88,6 +115,10 @@ PatchChangeDialog::PatchChangeDialog (
|
|||
add_button (ok, RESPONSE_ACCEPT);
|
||||
set_default_response (RESPONSE_ACCEPT);
|
||||
|
||||
fill_bank_combo ();
|
||||
set_active_bank_combo ();
|
||||
bank_combo_changed ();
|
||||
|
||||
show_all ();
|
||||
}
|
||||
|
||||
|
|
@ -107,3 +138,210 @@ PatchChangeDialog::patch () const
|
|||
_bank.get_value_as_int() - 1
|
||||
);
|
||||
}
|
||||
|
||||
/** Fill the bank_combo according to the current _channel */
|
||||
void
|
||||
PatchChangeDialog::fill_bank_combo ()
|
||||
{
|
||||
MIDI::Name::ChannelNameSet::PatchBanks const * banks = get_banks ();
|
||||
if (banks == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (MIDI::Name::ChannelNameSet::PatchBanks::const_iterator i = banks->begin(); i != banks->end(); ++i) {
|
||||
string n = (*i)->name ();
|
||||
boost::replace_all (n, "_", " ");
|
||||
_bank_combo.append_text (n);
|
||||
}
|
||||
}
|
||||
|
||||
/** Set the active value of the bank_combo, and _current_patch_bank, from the contents of _bank */
|
||||
void
|
||||
PatchChangeDialog::set_active_bank_combo ()
|
||||
{
|
||||
_current_patch_bank.reset ();
|
||||
|
||||
MIDI::Name::ChannelNameSet::PatchBanks const * banks = get_banks ();
|
||||
if (banks == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (MIDI::Name::ChannelNameSet::PatchBanks::const_iterator i = banks->begin(); i != banks->end(); ++i) {
|
||||
string n = (*i)->name ();
|
||||
boost::replace_all (n, "_", " ");
|
||||
|
||||
MIDI::Name::PatchPrimaryKey const * key = (*i)->patch_primary_key ();
|
||||
if (key && ((key->msb << 7) | key->lsb) == _bank.get_value () - 1) {
|
||||
_current_patch_bank = *i;
|
||||
_ignore_signals = true;
|
||||
_bank_combo.set_active_text (n);
|
||||
_ignore_signals = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_ignore_signals = true;
|
||||
_bank_combo.set_active (-1);
|
||||
_ignore_signals = false;
|
||||
}
|
||||
|
||||
/** Update _current_patch_bank and reflect the current value of
|
||||
* bank_combo in the rest of the dialog.
|
||||
*/
|
||||
void
|
||||
PatchChangeDialog::bank_combo_changed ()
|
||||
{
|
||||
if (_ignore_signals) {
|
||||
return;
|
||||
}
|
||||
|
||||
_current_patch_bank.reset ();
|
||||
|
||||
MIDI::Name::ChannelNameSet::PatchBanks const * banks = get_banks ();
|
||||
if (banks == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (MIDI::Name::ChannelNameSet::PatchBanks::const_iterator i = banks->begin(); i != banks->end(); ++i) {
|
||||
string n = (*i)->name ();
|
||||
boost::replace_all (n, "_", " ");
|
||||
if (n == _bank_combo.get_active_text()) {
|
||||
_current_patch_bank = *i;
|
||||
}
|
||||
}
|
||||
|
||||
if (_current_patch_bank == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reflect */
|
||||
|
||||
fill_patch_combo ();
|
||||
set_active_patch_combo ();
|
||||
|
||||
MIDI::Name::PatchPrimaryKey const * key = _current_patch_bank->patch_primary_key ();
|
||||
if (key) {
|
||||
_ignore_signals = true;
|
||||
_bank.set_value (((key->msb << 7) | key->lsb) + 1);
|
||||
_ignore_signals = false;
|
||||
}
|
||||
}
|
||||
|
||||
/** Fill the contents of the patch combo */
|
||||
void
|
||||
PatchChangeDialog::fill_patch_combo ()
|
||||
{
|
||||
_patch_combo.clear ();
|
||||
|
||||
if (_current_patch_bank == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const MIDI::Name::PatchBank::PatchNameList& patches = _current_patch_bank->patch_name_list ();
|
||||
for (MIDI::Name::PatchBank::PatchNameList::const_iterator j = patches.begin(); j != patches.end(); ++j) {
|
||||
string n = (*j)->name ();
|
||||
boost::replace_all (n, "_", " ");
|
||||
_patch_combo.append_text (n);
|
||||
}
|
||||
}
|
||||
|
||||
/** Set the active value of the patch combo from the value of the _program entry */
|
||||
void
|
||||
PatchChangeDialog::set_active_patch_combo ()
|
||||
{
|
||||
if (_ignore_signals) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_current_patch_bank == 0) {
|
||||
_ignore_signals = true;
|
||||
_patch_combo.set_active (-1);
|
||||
_ignore_signals = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const MIDI::Name::PatchBank::PatchNameList& patches = _current_patch_bank->patch_name_list ();
|
||||
for (MIDI::Name::PatchBank::PatchNameList::const_iterator j = patches.begin(); j != patches.end(); ++j) {
|
||||
string n = (*j)->name ();
|
||||
boost::replace_all (n, "_", " ");
|
||||
|
||||
MIDI::Name::PatchPrimaryKey const & key = (*j)->patch_primary_key ();
|
||||
if (key.program_number == _program.get_value() - 1) {
|
||||
_ignore_signals = true;
|
||||
_patch_combo.set_active_text (n);
|
||||
_ignore_signals = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_ignore_signals = true;
|
||||
_patch_combo.set_active (-1);
|
||||
_ignore_signals = false;
|
||||
}
|
||||
|
||||
/** Set _program from the current state of _patch_combo */
|
||||
void
|
||||
PatchChangeDialog::patch_combo_changed ()
|
||||
{
|
||||
if (_ignore_signals || _current_patch_bank == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const MIDI::Name::PatchBank::PatchNameList& patches = _current_patch_bank->patch_name_list ();
|
||||
for (MIDI::Name::PatchBank::PatchNameList::const_iterator j = patches.begin(); j != patches.end(); ++j) {
|
||||
string n = (*j)->name ();
|
||||
boost::replace_all (n, "_", " ");
|
||||
if (n == _patch_combo.get_active_text ()) {
|
||||
MIDI::Name::PatchPrimaryKey const & key = (*j)->patch_primary_key ();
|
||||
_ignore_signals = true;
|
||||
_program.set_value (key.program_number + 1);
|
||||
_ignore_signals = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PatchChangeDialog::channel_changed ()
|
||||
{
|
||||
fill_bank_combo ();
|
||||
set_active_bank_combo ();
|
||||
fill_patch_combo ();
|
||||
set_active_patch_combo ();
|
||||
}
|
||||
|
||||
void
|
||||
PatchChangeDialog::program_changed ()
|
||||
{
|
||||
if (_ignore_signals) {
|
||||
return;
|
||||
}
|
||||
|
||||
set_active_patch_combo ();
|
||||
}
|
||||
|
||||
void
|
||||
PatchChangeDialog::bank_changed ()
|
||||
{
|
||||
if (_ignore_signals) {
|
||||
return;
|
||||
}
|
||||
|
||||
set_active_bank_combo ();
|
||||
fill_patch_combo ();
|
||||
set_active_patch_combo ();
|
||||
}
|
||||
|
||||
MIDI::Name::ChannelNameSet::PatchBanks const *
|
||||
PatchChangeDialog::get_banks ()
|
||||
{
|
||||
MIDI::Name::MidiPatchManager& mpm = MIDI::Name::MidiPatchManager::instance ();
|
||||
boost::shared_ptr<MIDI::Name::ChannelNameSet> channel_name_set = mpm.find_channel_name_set (
|
||||
_model_name, _custom_device_mode, _channel.get_value_as_int() - 1
|
||||
);
|
||||
|
||||
if (!channel_name_set) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return &channel_name_set->patch_banks ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
*/
|
||||
|
||||
#include <gtkmm/spinbutton.h>
|
||||
#include <gtkmm/comboboxtext.h>
|
||||
#include "midi++/midnam_patch.h"
|
||||
#include "evoral/PatchChange.hpp"
|
||||
#include "ardour_dialog.h"
|
||||
#include "audio_clock.h"
|
||||
|
|
@ -28,6 +30,12 @@ namespace ARDOUR {
|
|||
class Session;
|
||||
}
|
||||
|
||||
namespace MIDI {
|
||||
namespace Name {
|
||||
class PatchBank;
|
||||
}
|
||||
}
|
||||
|
||||
class PatchChangeDialog : public ArdourDialog
|
||||
{
|
||||
public:
|
||||
|
|
@ -35,15 +43,36 @@ public:
|
|||
const ARDOUR::BeatsFramesConverter *,
|
||||
ARDOUR::Session *,
|
||||
Evoral::PatchChange<Evoral::MusicalTime> const &,
|
||||
std::string const &,
|
||||
std::string const &,
|
||||
const Gtk::BuiltinStockID &
|
||||
);
|
||||
|
||||
Evoral::PatchChange<Evoral::MusicalTime> patch () const;
|
||||
|
||||
private:
|
||||
void fill_bank_combo ();
|
||||
void set_active_bank_combo ();
|
||||
void fill_patch_combo ();
|
||||
void set_active_patch_combo ();
|
||||
void bank_combo_changed ();
|
||||
void patch_combo_changed ();
|
||||
void channel_changed ();
|
||||
void bank_changed ();
|
||||
void program_changed ();
|
||||
|
||||
MIDI::Name::ChannelNameSet::PatchBanks const * get_banks ();
|
||||
|
||||
const ARDOUR::BeatsFramesConverter* _time_converter;
|
||||
std::string _model_name;
|
||||
std::string _custom_device_mode;
|
||||
AudioClock _time;
|
||||
Gtk::SpinButton _channel;
|
||||
Gtk::SpinButton _program;
|
||||
Gtk::SpinButton _bank;
|
||||
Gtk::ComboBoxText _bank_combo;
|
||||
Gtk::ComboBoxText _patch_combo;
|
||||
|
||||
boost::shared_ptr<MIDI::Name::PatchBank> _current_patch_bank;
|
||||
bool _ignore_signals;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ PlaylistSelector::PlaylistSelector ()
|
|||
|
||||
get_vbox()->pack_start (scroller);
|
||||
|
||||
Button* b = add_button (_("close"), RESPONSE_CANCEL);
|
||||
Button* b = add_button (_("Close"), RESPONSE_CANCEL);
|
||||
b->signal_clicked().connect (sigc::mem_fun(*this, &PlaylistSelector::close_button_click));
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ RefPtr<Action> ProcessorBox::rename_action;
|
|||
RefPtr<Action> ProcessorBox::edit_action;
|
||||
RefPtr<Action> ProcessorBox::edit_generic_action;
|
||||
Glib::RefPtr<Gdk::Pixbuf> ProcessorEntry::_slider_pixbuf;
|
||||
Glib::RefPtr<Gdk::Pixbuf> ProcessorEntry::_slider_pixbuf_desensitised;
|
||||
|
||||
ProcessorEntry::ProcessorEntry (ProcessorBox* parent, boost::shared_ptr<Processor> p, Width w)
|
||||
: _button (ArdourButton::led_default_elements)
|
||||
|
|
@ -121,7 +122,13 @@ ProcessorEntry::ProcessorEntry (ProcessorBox* parent, boost::shared_ptr<Processo
|
|||
set<Evoral::Parameter> p = _processor->what_can_be_automated ();
|
||||
for (set<Evoral::Parameter>::iterator i = p.begin(); i != p.end(); ++i) {
|
||||
|
||||
Control* c = new Control (_slider_pixbuf, _processor->automation_control (*i), _processor->describe_parameter (*i));
|
||||
Control* c = new Control (
|
||||
_slider_pixbuf,
|
||||
_slider_pixbuf_desensitised,
|
||||
_processor->automation_control (*i),
|
||||
_processor->describe_parameter (*i)
|
||||
);
|
||||
|
||||
_controls.push_back (c);
|
||||
|
||||
if (boost::dynamic_pointer_cast<Amp> (_processor) == 0) {
|
||||
|
|
@ -301,6 +308,8 @@ ProcessorEntry::setup_slider_pix ()
|
|||
{
|
||||
_slider_pixbuf = ::get_icon ("fader_belt_h_thin");
|
||||
assert (_slider_pixbuf);
|
||||
_slider_pixbuf_desensitised = ::get_icon ("fader_belt_h_thin_desensitised");
|
||||
assert (_slider_pixbuf_desensitised);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -398,10 +407,10 @@ ProcessorEntry::toggle_control_visibility (Control* c)
|
|||
_parent->update_gui_object_state (this);
|
||||
}
|
||||
|
||||
ProcessorEntry::Control::Control (Glib::RefPtr<Gdk::Pixbuf> s, boost::shared_ptr<AutomationControl> c, string const & n)
|
||||
ProcessorEntry::Control::Control (Glib::RefPtr<Gdk::Pixbuf> s, Glib::RefPtr<Gdk::Pixbuf> sd, boost::shared_ptr<AutomationControl> c, string const & n)
|
||||
: _control (c)
|
||||
, _adjustment (gain_to_slider_position_with_max (1.0, Config->get_max_gain()), 0, 1, 0.01, 0.1)
|
||||
, _slider (s, &_adjustment, 0, false)
|
||||
, _slider (s, sd, &_adjustment, 0, false)
|
||||
, _button (ArdourButton::Element (ArdourButton::Text | ArdourButton::Indicator))
|
||||
, _ignore_ui_adjustment (false)
|
||||
, _visible (false)
|
||||
|
|
|
|||
|
|
@ -140,6 +140,7 @@ protected:
|
|||
virtual void setup_visuals ();
|
||||
|
||||
static Glib::RefPtr<Gdk::Pixbuf> _slider_pixbuf;
|
||||
static Glib::RefPtr<Gdk::Pixbuf> _slider_pixbuf_desensitised;
|
||||
|
||||
private:
|
||||
void led_clicked();
|
||||
|
|
@ -157,7 +158,7 @@ private:
|
|||
|
||||
class Control {
|
||||
public:
|
||||
Control (Glib::RefPtr<Gdk::Pixbuf>, boost::shared_ptr<ARDOUR::AutomationControl>, std::string const &);
|
||||
Control (Glib::RefPtr<Gdk::Pixbuf>, Glib::RefPtr<Gdk::Pixbuf>, boost::shared_ptr<ARDOUR::AutomationControl>, std::string const &);
|
||||
|
||||
void set_pixel_width (int);
|
||||
void set_visible (bool);
|
||||
|
|
|
|||
|
|
@ -202,6 +202,7 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible {
|
|||
virtual framepos_t unit_to_frame (double unit) const = 0;
|
||||
virtual double frame_to_unit (framepos_t frame) const = 0;
|
||||
virtual double frame_to_unit (double frame) const = 0;
|
||||
virtual double frame_to_unit_unrounded (framepos_t frame) const = 0;
|
||||
virtual framepos_t pixel_to_frame (double pixel) const = 0;
|
||||
virtual gulong frame_to_pixel (framepos_t frame) const = 0;
|
||||
virtual Selection& get_selection () const = 0;
|
||||
|
|
|
|||
|
|
@ -1005,22 +1005,6 @@ RCOptionEditor::RCOptionEditor ()
|
|||
sigc::mem_fun (*_rc_config, &RCConfiguration::set_seamless_loop)
|
||||
));
|
||||
|
||||
add_option (_("Transport"),
|
||||
new BoolOption (
|
||||
"primary-clock-delta-edit-cursor",
|
||||
_("Primary clock delta to edit cursor"),
|
||||
sigc::mem_fun (*_rc_config, &RCConfiguration::get_primary_clock_delta_edit_cursor),
|
||||
sigc::mem_fun (*_rc_config, &RCConfiguration::set_primary_clock_delta_edit_cursor)
|
||||
));
|
||||
|
||||
add_option (_("Transport"),
|
||||
new BoolOption (
|
||||
"secondary-clock-delta-edit-cursor",
|
||||
_("Secondary clock delta to edit cursor"),
|
||||
sigc::mem_fun (*_rc_config, &RCConfiguration::get_secondary_clock_delta_edit_cursor),
|
||||
sigc::mem_fun (*_rc_config, &RCConfiguration::set_secondary_clock_delta_edit_cursor)
|
||||
));
|
||||
|
||||
add_option (_("Transport"),
|
||||
new BoolOption (
|
||||
"disable-disarm-during-roll",
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ using namespace std;
|
|||
using std::list;
|
||||
|
||||
Glib::RefPtr<Gdk::Pixbuf> RouteTimeAxisView::slider;
|
||||
Glib::RefPtr<Gdk::Pixbuf> RouteTimeAxisView::slider_desensitised;
|
||||
|
||||
void
|
||||
RouteTimeAxisView::setup_slider_pix ()
|
||||
|
|
@ -93,6 +94,10 @@ RouteTimeAxisView::setup_slider_pix ()
|
|||
if ((slider = ::get_icon ("fader_belt_h")) == 0) {
|
||||
throw failed_constructor ();
|
||||
}
|
||||
|
||||
if ((slider_desensitised = ::get_icon ("fader_belt_h_desensitised")) == 0) {
|
||||
throw failed_constructor ();
|
||||
}
|
||||
}
|
||||
|
||||
RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session* sess, Canvas& canvas)
|
||||
|
|
@ -112,7 +117,7 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session* sess, Canvas& c
|
|||
, playlist_action_menu (0)
|
||||
, mode_menu (0)
|
||||
, color_mode_menu (0)
|
||||
, gm (sess, slider, true, 115)
|
||||
, gm (sess, slider, slider_desensitised, true, 115)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -124,6 +129,7 @@ RouteTimeAxisView::set_route (boost::shared_ptr<Route> rt)
|
|||
gm.set_controls (_route, _route->shared_peak_meter(), _route->amp());
|
||||
gm.get_level_meter().set_no_show_all();
|
||||
gm.get_level_meter().setup_meters(50);
|
||||
gm.update_gain_sensitive ();
|
||||
|
||||
string str = gui_property ("height");
|
||||
if (!str.empty()) {
|
||||
|
|
@ -757,13 +763,9 @@ RouteTimeAxisView::set_track_mode (TrackMode mode, bool apply_to_selection)
|
|||
}
|
||||
|
||||
void
|
||||
RouteTimeAxisView::show_timestretch (framepos_t start, framepos_t end)
|
||||
RouteTimeAxisView::show_timestretch (framepos_t start, framepos_t end, int layers, int layer)
|
||||
{
|
||||
double x1;
|
||||
double x2;
|
||||
double y2;
|
||||
|
||||
TimeAxisView::show_timestretch (start, end);
|
||||
TimeAxisView::show_timestretch (start, end, layers, layer);
|
||||
|
||||
hide_timestretch ();
|
||||
|
||||
|
|
@ -802,14 +804,13 @@ RouteTimeAxisView::show_timestretch (framepos_t start, framepos_t end)
|
|||
timestretch_rect->show ();
|
||||
timestretch_rect->raise_to_top ();
|
||||
|
||||
x1 = start / _editor.get_current_zoom();
|
||||
x2 = (end - 1) / _editor.get_current_zoom();
|
||||
y2 = current_height() - 2;
|
||||
double const x1 = start / _editor.get_current_zoom();
|
||||
double const x2 = (end - 1) / _editor.get_current_zoom();
|
||||
|
||||
timestretch_rect->property_x1() = x1;
|
||||
timestretch_rect->property_y1() = 1.0;
|
||||
timestretch_rect->property_y1() = current_height() * (layers - layer - 1) / layers;
|
||||
timestretch_rect->property_x2() = x2;
|
||||
timestretch_rect->property_y2() = y2;
|
||||
timestretch_rect->property_y2() = current_height() * (layers - layer) / layers;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ public:
|
|||
|
||||
void set_samples_per_unit (double);
|
||||
void set_height (uint32_t h);
|
||||
void show_timestretch (framepos_t start, framepos_t end);
|
||||
void show_timestretch (framepos_t start, framepos_t end, int layers, int layer);
|
||||
void hide_timestretch ();
|
||||
void selection_click (GdkEventButton*);
|
||||
void set_selected_points (PointSelection&);
|
||||
|
|
@ -296,6 +296,7 @@ protected:
|
|||
GainMeterBase gm;
|
||||
|
||||
static Glib::RefPtr<Gdk::Pixbuf> slider;
|
||||
static Glib::RefPtr<Gdk::Pixbuf> slider_desensitised;
|
||||
|
||||
XMLNode* underlay_xml_node;
|
||||
bool set_underlay_state();
|
||||
|
|
|
|||
|
|
@ -861,6 +861,12 @@ Selection::selected (RegionView* rv)
|
|||
return find (regions.begin(), regions.end(), rv) != regions.end();
|
||||
}
|
||||
|
||||
bool
|
||||
Selection::selected (ControlPoint* cp)
|
||||
{
|
||||
return find (points.begin(), points.end(), cp) != points.end();
|
||||
}
|
||||
|
||||
bool
|
||||
Selection::empty (bool internal_selection)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ class Selection : public sigc::trackable, public PBD::ScopedConnectionList
|
|||
bool selected (TimeAxisView*);
|
||||
bool selected (RegionView*);
|
||||
bool selected (Marker*);
|
||||
bool selected (ControlPoint*);
|
||||
|
||||
void set (std::list<Selectable*> const &);
|
||||
void add (std::list<Selectable*> const &);
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@
|
|||
#include "editing.h"
|
||||
#include "utils.h"
|
||||
#include "gain_meter.h"
|
||||
#include "main_clock.h"
|
||||
|
||||
#ifdef FREESOUND
|
||||
#include "sfdb_freesound_mootcher.h"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,22 @@
|
|||
/*
|
||||
Copyright (C) 2008 Paul Davis
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "pbd/failed_constructor.h"
|
||||
|
|
@ -20,6 +39,8 @@ Splash* Splash::the_splash = 0;
|
|||
|
||||
Splash::Splash ()
|
||||
{
|
||||
assert (the_splash == 0);
|
||||
|
||||
sys::path splash_file;
|
||||
|
||||
if (!find_file_in_search_path (ardour_data_search_path(), "splash.png", splash_file)) {
|
||||
|
|
@ -59,6 +80,11 @@ Splash::Splash ()
|
|||
ARDOUR::BootMessage.connect (msg_connection, invalidator (*this), boost::bind (&Splash::boot_message, this, _1), gui_context());
|
||||
}
|
||||
|
||||
Splash::~Splash ()
|
||||
{
|
||||
the_splash = 0;
|
||||
}
|
||||
|
||||
void
|
||||
Splash::pop_back_for (Gtk::Window& win)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ class Splash : public Gtk::Window
|
|||
{
|
||||
public:
|
||||
Splash ();
|
||||
~Splash () {}
|
||||
~Splash ();
|
||||
|
||||
static Splash* instance() { return the_splash; }
|
||||
|
||||
|
|
|
|||
|
|
@ -476,35 +476,67 @@ StereoPanner::on_motion_notify_event (GdkEventMotion* ev)
|
|||
if (dragging_left) {
|
||||
delta = -delta;
|
||||
}
|
||||
|
||||
|
||||
if (dragging_left || dragging_right) {
|
||||
|
||||
/* maintain position as invariant as we change the width */
|
||||
if (Keyboard::modifier_state_contains (ev->state, Keyboard::SecondaryModifier)) {
|
||||
|
||||
/* change width and position in a way that keeps the
|
||||
* other side in the same place
|
||||
*/
|
||||
|
||||
/* create a detent close to the center */
|
||||
_panner->freeze ();
|
||||
|
||||
double pv = position_control->get_value();
|
||||
|
||||
if (!detented && fabs (current_width) < 0.02) {
|
||||
detented = true;
|
||||
/* snap to zero */
|
||||
width_control->set_value (0);
|
||||
}
|
||||
|
||||
if (detented) {
|
||||
|
||||
accumulated_delta += delta;
|
||||
|
||||
/* have we pulled far enough to escape ? */
|
||||
|
||||
if (fabs (accumulated_delta) >= 0.025) {
|
||||
width_control->set_value (current_width + accumulated_delta);
|
||||
detented = false;
|
||||
accumulated_delta = false;
|
||||
if (dragging_left) {
|
||||
position_control->set_value (pv - delta);
|
||||
} else {
|
||||
position_control->set_value (pv + delta);
|
||||
}
|
||||
|
||||
if (delta > 0.0) {
|
||||
/* delta is positive, so we're about to
|
||||
increase the width. But we need to increase it
|
||||
by twice the required value so that the
|
||||
other side remains in place when we set
|
||||
the position as well.
|
||||
*/
|
||||
width_control->set_value (current_width + (delta * 2.0));
|
||||
} else {
|
||||
width_control->set_value (current_width + delta);
|
||||
}
|
||||
|
||||
_panner->thaw ();
|
||||
|
||||
} else {
|
||||
/* width needs to change by 2 * delta because both L & R move */
|
||||
width_control->set_value (current_width + delta * 2);
|
||||
|
||||
/* maintain position as invariant as we change the width */
|
||||
|
||||
/* create a detent close to the center */
|
||||
|
||||
if (!detented && fabs (current_width) < 0.02) {
|
||||
detented = true;
|
||||
/* snap to zero */
|
||||
width_control->set_value (0);
|
||||
}
|
||||
|
||||
if (detented) {
|
||||
|
||||
accumulated_delta += delta;
|
||||
|
||||
/* have we pulled far enough to escape ? */
|
||||
|
||||
if (fabs (accumulated_delta) >= 0.025) {
|
||||
width_control->set_value (current_width + accumulated_delta);
|
||||
detented = false;
|
||||
accumulated_delta = false;
|
||||
}
|
||||
|
||||
} else {
|
||||
/* width needs to change by 2 * delta because both L & R move */
|
||||
width_control->set_value (current_width + (delta * 2.0));
|
||||
}
|
||||
}
|
||||
|
||||
} else if (dragging_position) {
|
||||
|
|
|
|||
|
|
@ -764,10 +764,10 @@ TimeAxisView::set_samples_per_unit (double spu)
|
|||
}
|
||||
|
||||
void
|
||||
TimeAxisView::show_timestretch (framepos_t start, framepos_t end)
|
||||
TimeAxisView::show_timestretch (framepos_t start, framepos_t end, int layers, int layer)
|
||||
{
|
||||
for (Children::iterator i = children.begin(); i != children.end(); ++i) {
|
||||
(*i)->show_timestretch (start, end);
|
||||
(*i)->show_timestretch (start, end, layers, layer);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ class TimeAxisView : public virtual AxisView
|
|||
virtual void show_selection (TimeSelection&);
|
||||
virtual void hide_selection ();
|
||||
virtual void reshow_selection (TimeSelection&);
|
||||
virtual void show_timestretch (framepos_t start, framepos_t end);
|
||||
virtual void show_timestretch (framepos_t start, framepos_t end, int layers, int layer);
|
||||
virtual void hide_timestretch ();
|
||||
|
||||
/* editing operations */
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include "audio_clock.h"
|
||||
#include "editor.h"
|
||||
#include "editor_drag.h"
|
||||
#include "main_clock.h"
|
||||
#include "utils.h"
|
||||
#include "verbose_cursor.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -409,7 +409,7 @@ VisualTimeAxis::name_entry_key_release_handler(GdkEventKey* ev)
|
|||
// Super class methods not handled by VisualTimeAxis
|
||||
|
||||
void
|
||||
VisualTimeAxis::show_timestretch (framepos_t start, framepos_t end)
|
||||
VisualTimeAxis::show_timestretch (framepos_t start, framepos_t end, int layers, int layer)
|
||||
{
|
||||
// Not handled by purely visual TimeAxis
|
||||
}
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@ class VisualTimeAxis : public TimeAxisView
|
|||
*
|
||||
* @todo should VisualTimeAxis handle this?
|
||||
*/
|
||||
void show_timestretch (nframes_t start, nframes_t end);
|
||||
void show_timestretch (nframes_t start, nframes_t end, int layers, int layer);
|
||||
|
||||
/**
|
||||
* Not handle by purely visual TimeAxis
|
||||
|
|
|
|||
|
|
@ -133,6 +133,7 @@ gtk2_ardour_sources = [
|
|||
'lineset.cc',
|
||||
'location_ui.cc',
|
||||
'main.cc',
|
||||
'main_clock.cc',
|
||||
'marker.cc',
|
||||
'midi_automation_line.cc',
|
||||
'midi_channel_dialog.cc',
|
||||
|
|
|
|||
|
|
@ -173,6 +173,7 @@ public:
|
|||
|
||||
void prepare () { _written = false; _silent = false; }
|
||||
bool written() const { return _written; }
|
||||
void set_written(bool w) { _written = w; }
|
||||
|
||||
private:
|
||||
bool _owns_data;
|
||||
|
|
|
|||
|
|
@ -59,7 +59,8 @@ private:
|
|||
int set_state (const XMLNode&, int version);
|
||||
void dump () const;
|
||||
bool region_changed (const PBD::PropertyChange&, boost::shared_ptr<Region>);
|
||||
void source_offset_changed (boost::shared_ptr<AudioRegion> region);
|
||||
void source_offset_changed (boost::shared_ptr<AudioRegion>);
|
||||
void load_legacy_crossfades (const XMLNode&, int version);
|
||||
};
|
||||
|
||||
} /* namespace ARDOUR */
|
||||
|
|
|
|||
|
|
@ -94,6 +94,11 @@ class AudioRegion : public Region
|
|||
bool fade_out_is_xfade() const { return _fade_out_is_xfade; }
|
||||
void set_fade_out_is_xfade (bool yn);
|
||||
|
||||
bool fade_in_is_short() const { return _fade_in_is_short; }
|
||||
void set_fade_in_is_short (bool yn);
|
||||
bool fade_out_is_short() const { return _fade_out_is_short; }
|
||||
void set_fade_out_is_short (bool yn);
|
||||
|
||||
boost::shared_ptr<AutomationList> fade_in() { return _fade_in; }
|
||||
boost::shared_ptr<AutomationList> inverse_fade_in() { return _inverse_fade_in; }
|
||||
boost::shared_ptr<AutomationList> fade_out() { return _fade_out; }
|
||||
|
|
@ -199,6 +204,10 @@ class AudioRegion : public Region
|
|||
PBD::Property<bool> _fade_out_active;
|
||||
/** linear gain to apply to the whole region */
|
||||
PBD::Property<gain_t> _scale_amplitude;
|
||||
PBD::Property<bool> _fade_in_is_xfade;
|
||||
PBD::Property<bool> _fade_out_is_xfade;
|
||||
PBD::Property<bool> _fade_in_is_short;
|
||||
PBD::Property<bool> _fade_out_is_short;
|
||||
|
||||
void register_properties ();
|
||||
void post_set (const PBD::PropertyChange&);
|
||||
|
|
@ -231,11 +240,6 @@ class AudioRegion : public Region
|
|||
boost::shared_ptr<AutomationList> _envelope;
|
||||
uint32_t _fade_in_suspended;
|
||||
uint32_t _fade_out_suspended;
|
||||
/* This is not a Property because its not subject to user control,
|
||||
or undo/redo. XXX this may prove to be a mistake.
|
||||
*/
|
||||
bool _fade_in_is_xfade;
|
||||
bool _fade_out_is_xfade;
|
||||
|
||||
boost::shared_ptr<ARDOUR::Region> get_single_other_xfade_region (bool start) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -104,10 +104,7 @@ class LV2Plugin : public ARDOUR::Plugin, public ARDOUR::Workee
|
|||
boost::shared_ptr<Plugin::ScalePoints>
|
||||
get_scale_points(uint32_t port_index) const;
|
||||
|
||||
/// Return the URID of midi:MidiEvent
|
||||
static uint32_t midi_event_type (bool event_api) {
|
||||
return event_api ? _midi_event_type_ev : _midi_event_type;
|
||||
}
|
||||
static uint32_t midi_event_type() { return _midi_event_type; }
|
||||
|
||||
void set_insert_info(const PluginInsert* insert);
|
||||
|
||||
|
|
@ -140,7 +137,6 @@ class LV2Plugin : public ARDOUR::Plugin, public ARDOUR::Workee
|
|||
|
||||
static URIMap _uri_map;
|
||||
|
||||
static uint32_t _midi_event_type_ev;
|
||||
static uint32_t _midi_event_type;
|
||||
static uint32_t _chunk_type;
|
||||
static uint32_t _sequence_type;
|
||||
|
|
|
|||
|
|
@ -27,11 +27,11 @@ public:
|
|||
MTDM ();
|
||||
|
||||
int process (size_t len, float *inp, float *out);
|
||||
int resolve (void);
|
||||
void invert (void) { _inv ^= 1; }
|
||||
int inv (void) { return _inv; }
|
||||
double del (void) { return _del; }
|
||||
double err (void) { return _err; }
|
||||
int resolve ();
|
||||
void invert () { _inv ^= 1; }
|
||||
int inv () { return _inv; }
|
||||
double del () { return _del; }
|
||||
double err () { return _err; }
|
||||
|
||||
private:
|
||||
class Freq {
|
||||
|
|
|
|||
|
|
@ -151,6 +151,9 @@ public:
|
|||
return fabs (a.azi - b.azi) < 1.0;
|
||||
}
|
||||
|
||||
virtual void freeze ();
|
||||
virtual void thaw ();
|
||||
|
||||
protected:
|
||||
boost::shared_ptr<Pannable> _pannable;
|
||||
|
||||
|
|
@ -158,6 +161,8 @@ protected:
|
|||
virtual void distribute_one_automated (AudioBuffer&, BufferSet& obufs,
|
||||
framepos_t start, framepos_t end, pframes_t nframes,
|
||||
pan_t** buffers, uint32_t which) = 0;
|
||||
|
||||
int32_t _frozen;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -31,9 +31,6 @@
|
|||
#include <sys/stat.h>
|
||||
|
||||
#include <glib.h>
|
||||
#ifdef HAVE_GLIB_THREADS_RECMUTEX
|
||||
#include <glibmm/threads.h>
|
||||
#endif
|
||||
|
||||
#include "pbd/undo.h"
|
||||
#include "pbd/stateful.h"
|
||||
|
|
@ -121,6 +118,7 @@ public:
|
|||
bool hidden() const { return _hidden; }
|
||||
bool empty() const;
|
||||
uint32_t n_regions() const;
|
||||
bool all_regions_empty() const;
|
||||
std::pair<framepos_t, framepos_t> get_extent () const;
|
||||
layer_t top_layer() const;
|
||||
|
||||
|
|
@ -228,6 +226,8 @@ public:
|
|||
uint64_t highest_layering_index () const;
|
||||
|
||||
void set_layer (boost::shared_ptr<Region>, double);
|
||||
|
||||
void set_capture_insertion_in_progress (bool yn);
|
||||
|
||||
protected:
|
||||
friend class Session;
|
||||
|
|
@ -294,6 +294,7 @@ public:
|
|||
bool in_flush;
|
||||
bool in_partition;
|
||||
bool _frozen;
|
||||
bool _capture_insertion_underway;
|
||||
uint32_t subcnt;
|
||||
PBD::ID _orig_track_id;
|
||||
bool auto_partition;
|
||||
|
|
|
|||
|
|
@ -111,6 +111,13 @@ public:
|
|||
|
||||
static void add_compound_association (boost::shared_ptr<Region>, boost::shared_ptr<Region>);
|
||||
|
||||
/* exposed because there may be cases where regions are created with
|
||||
* announce=false but they still need to be in the map soon after
|
||||
* creation.
|
||||
*/
|
||||
|
||||
static void map_add (boost::shared_ptr<Region>);
|
||||
|
||||
private:
|
||||
|
||||
static void region_changed (PBD::PropertyChange const &, boost::weak_ptr<Region>);
|
||||
|
|
@ -118,7 +125,6 @@ public:
|
|||
static Glib::StaticMutex region_map_lock;
|
||||
|
||||
static RegionMap region_map;
|
||||
static void map_add (boost::shared_ptr<Region>);
|
||||
|
||||
static Glib::StaticMutex region_name_map_lock;
|
||||
|
||||
|
|
|
|||
|
|
@ -30,8 +30,10 @@
|
|||
|
||||
namespace ARDOUR {
|
||||
|
||||
|
||||
/** Implementation of the LV2 uri-map and urid extensions.
|
||||
*
|
||||
* This just uses a pair of std::map and is not so great in the space overhead
|
||||
* department, but it's fast enough and not really performance critical anyway.
|
||||
*/
|
||||
class URIMap : public boost::noncopyable {
|
||||
public:
|
||||
|
|
@ -44,26 +46,15 @@ public:
|
|||
LV2_URID_Map* urid_map() { return &_urid_map_feature_data; }
|
||||
LV2_URID_Unmap* urid_unmap() { return &_urid_unmap_feature_data; }
|
||||
|
||||
uint32_t uri_to_id(const char* map, const char* uri);
|
||||
|
||||
const char* id_to_uri(const char* map, uint32_t id);
|
||||
uint32_t uri_to_id(const char* uri);
|
||||
const char* id_to_uri(uint32_t id) const;
|
||||
|
||||
private:
|
||||
static uint32_t uri_map_uri_to_id(LV2_URI_Map_Callback_Data callback_data,
|
||||
const char* map,
|
||||
const char* uri);
|
||||
typedef std::map<const std::string, uint32_t> Map;
|
||||
typedef std::map<uint32_t, const std::string> Unmap;
|
||||
|
||||
static LV2_URID urid_map(LV2_URID_Map_Handle handle,
|
||||
const char* uri);
|
||||
|
||||
static const char* urid_unmap(LV2_URID_Unmap_Handle handle,
|
||||
LV2_URID urid);
|
||||
|
||||
typedef std::map<uint16_t, uint32_t> EventToGlobal;
|
||||
typedef std::map<uint32_t, uint16_t> GlobalToEvent;
|
||||
|
||||
EventToGlobal _event_to_global;
|
||||
GlobalToEvent _global_to_event;
|
||||
Map _map;
|
||||
Unmap _unmap;
|
||||
|
||||
LV2_Feature _uri_map_feature;
|
||||
LV2_URI_Map_Feature _uri_map_feature_data;
|
||||
|
|
@ -73,7 +64,6 @@ private:
|
|||
LV2_URID_Unmap _urid_unmap_feature_data;
|
||||
};
|
||||
|
||||
|
||||
} // namespace ARDOUR
|
||||
|
||||
#endif // __ardour_uri_map_h__
|
||||
|
|
|
|||
|
|
@ -61,7 +61,6 @@ std::string path_expand (std::string); /* single file path */
|
|||
std::string search_path_expand (std::string); /* colon-separated search path */
|
||||
std::string region_name_from_path (std::string path, bool strip_channels, bool add_channel_suffix = false, uint32_t total = 0, uint32_t this_one = 0);
|
||||
bool path_is_paired (std::string path, std::string& pair_base);
|
||||
bool inodes_same (const std::string &, const std::string &);
|
||||
|
||||
void compute_equal_power_fades (ARDOUR::framecnt_t nframes, float* in, float* out);
|
||||
|
||||
|
|
|
|||
|
|
@ -1476,6 +1476,7 @@ AudioDiskstream::transport_stopped_wallclock (struct tm& when, time_t twhen, boo
|
|||
// cerr << _name << ": there are " << capture_info.size() << " capture_info records\n";
|
||||
|
||||
_playlist->clear_changes ();
|
||||
_playlist->set_capture_insertion_in_progress (true);
|
||||
_playlist->freeze ();
|
||||
|
||||
for (buffer_position = c->front()->write_source->last_capture_start_frame(), ci = capture_info.begin(); ci != capture_info.end(); ++ci) {
|
||||
|
|
@ -1514,6 +1515,7 @@ AudioDiskstream::transport_stopped_wallclock (struct tm& when, time_t twhen, boo
|
|||
}
|
||||
|
||||
_playlist->thaw ();
|
||||
_playlist->set_capture_insertion_in_progress (false);
|
||||
_session.add_command (new StatefulDiffCommand (_playlist));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -49,6 +49,8 @@ AudioPlaylist::AudioPlaylist (Session& session, const XMLNode& node, bool hidden
|
|||
in_set_state--;
|
||||
|
||||
relayer ();
|
||||
|
||||
load_legacy_crossfades (node, Stateful::loading_state_version);
|
||||
}
|
||||
|
||||
AudioPlaylist::AudioPlaylist (Session& session, string name, bool hidden)
|
||||
|
|
@ -200,7 +202,7 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, fr
|
|||
|
||||
/* This will be a list of the bits of regions that we need to read */
|
||||
list<Segment> to_do;
|
||||
|
||||
|
||||
/* Now go through the `all' list filling in `to_do' and `done' */
|
||||
for (RegionList::iterator i = all->begin(); i != all->end(); ++i) {
|
||||
boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (*i);
|
||||
|
|
@ -213,6 +215,7 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, fr
|
|||
region_range.to = min (region_range.to, start + cnt - 1);
|
||||
|
||||
/* ... and then remove the bits that are already done */
|
||||
|
||||
Evoral::RangeList<framepos_t> region_to_do = Evoral::subtract (region_range, done);
|
||||
|
||||
/* Read those bits, adding their bodies (the parts between end-of-fade-in
|
||||
|
|
@ -239,6 +242,10 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, fr
|
|||
|
||||
/* Now go backwards through the to_do list doing the actual reads */
|
||||
for (list<Segment>::reverse_iterator i = to_do.rbegin(); i != to_do.rend(); ++i) {
|
||||
DEBUG_TRACE (DEBUG::AudioPlayback, string_compose ("\tPlaylist %1 read %2 @ %3 for %4, channel %5, buf @ %6 offset %7\n",
|
||||
name(), i->region->name(), i->range.from,
|
||||
i->range.to - i->range.from + 1, (int) chan_n,
|
||||
buf, i->range.from - start));
|
||||
i->region->read_at (buf + i->range.from - start, mixdown_buffer, gain_buffer, i->range.from, i->range.to - i->range.from + 1, chan_n);
|
||||
}
|
||||
|
||||
|
|
@ -313,35 +320,51 @@ AudioPlaylist::check_crossfades (Evoral::Range<framepos_t> range)
|
|||
|
||||
/* Top's fade-in will cause an implicit fade-out of bottom */
|
||||
|
||||
framecnt_t len = 0;
|
||||
switch (_session.config.get_xfade_model()) {
|
||||
case FullCrossfade:
|
||||
len = bottom->last_frame () - top->first_frame ();
|
||||
break;
|
||||
case ShortCrossfade:
|
||||
len = _session.config.get_short_xfade_seconds() * _session.frame_rate();
|
||||
break;
|
||||
}
|
||||
|
||||
top->set_fade_in_active (true);
|
||||
top->set_fade_in_is_xfade (true);
|
||||
if (top->fade_in_is_xfade() && top->fade_in_is_short()) {
|
||||
|
||||
/* XXX may 2012: -3dB and -6dB curves
|
||||
* are the same right now
|
||||
*/
|
||||
/* its already an xfade. if its
|
||||
* really short, leave it
|
||||
* alone.
|
||||
*/
|
||||
|
||||
switch (_session.config.get_xfade_choice ()) {
|
||||
case ConstantPowerMinus3dB:
|
||||
top->set_fade_in (FadeConstantPower, len);
|
||||
break;
|
||||
case ConstantPowerMinus6dB:
|
||||
top->set_fade_in (FadeConstantPower, len);
|
||||
break;
|
||||
case RegionFades:
|
||||
top->set_fade_in_length (len);
|
||||
break;
|
||||
} else {
|
||||
framecnt_t len = 0;
|
||||
|
||||
if (_capture_insertion_underway) {
|
||||
len = _session.config.get_short_xfade_seconds() * _session.frame_rate();
|
||||
} else {
|
||||
switch (_session.config.get_xfade_model()) {
|
||||
case FullCrossfade:
|
||||
len = bottom->last_frame () - top->first_frame ();
|
||||
top->set_fade_in_is_short (false);
|
||||
break;
|
||||
case ShortCrossfade:
|
||||
len = _session.config.get_short_xfade_seconds() * _session.frame_rate();
|
||||
top->set_fade_in_is_short (true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
top->set_fade_in_active (true);
|
||||
top->set_fade_in_is_xfade (true);
|
||||
|
||||
/* XXX may 2012: -3dB and -6dB curves
|
||||
* are the same right now
|
||||
*/
|
||||
|
||||
switch (_session.config.get_xfade_choice ()) {
|
||||
case ConstantPowerMinus3dB:
|
||||
top->set_fade_in (FadeConstantPower, len);
|
||||
break;
|
||||
case ConstantPowerMinus6dB:
|
||||
top->set_fade_in (FadeConstantPower, len);
|
||||
break;
|
||||
case RegionFades:
|
||||
top->set_fade_in_length (len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
done_start.insert (top);
|
||||
}
|
||||
|
||||
|
|
@ -356,29 +379,44 @@ AudioPlaylist::check_crossfades (Evoral::Range<framepos_t> range)
|
|||
if (done_end.find (top) == done_end.end() && done_start.find (bottom) == done_start.end ()) {
|
||||
/* Top's fade-out will cause an implicit fade-in of bottom */
|
||||
|
||||
framecnt_t len = 0;
|
||||
switch (_session.config.get_xfade_model()) {
|
||||
case FullCrossfade:
|
||||
len = top->last_frame () - bottom->first_frame ();
|
||||
break;
|
||||
case ShortCrossfade:
|
||||
len = _session.config.get_short_xfade_seconds() * _session.frame_rate();
|
||||
break;
|
||||
}
|
||||
|
||||
top->set_fade_out_active (true);
|
||||
top->set_fade_out_is_xfade (true);
|
||||
if (top->fade_out_is_xfade() && top->fade_out_is_short()) {
|
||||
|
||||
switch (_session.config.get_xfade_choice ()) {
|
||||
case ConstantPowerMinus3dB:
|
||||
top->set_fade_out (FadeConstantPower, len);
|
||||
break;
|
||||
case ConstantPowerMinus6dB:
|
||||
top->set_fade_out (FadeConstantPower, len);
|
||||
break;
|
||||
case RegionFades:
|
||||
top->set_fade_out_length (len);
|
||||
break;
|
||||
/* its already an xfade. if its
|
||||
* really short, leave it
|
||||
* alone.
|
||||
*/
|
||||
|
||||
} else {
|
||||
framecnt_t len = 0;
|
||||
|
||||
if (_capture_insertion_underway) {
|
||||
len = _session.config.get_short_xfade_seconds() * _session.frame_rate();
|
||||
} else {
|
||||
switch (_session.config.get_xfade_model()) {
|
||||
case FullCrossfade:
|
||||
len = top->last_frame () - bottom->first_frame ();
|
||||
break;
|
||||
case ShortCrossfade:
|
||||
len = _session.config.get_short_xfade_seconds() * _session.frame_rate();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
top->set_fade_out_active (true);
|
||||
top->set_fade_out_is_xfade (true);
|
||||
|
||||
switch (_session.config.get_xfade_choice ()) {
|
||||
case ConstantPowerMinus3dB:
|
||||
top->set_fade_out (FadeConstantPower, len);
|
||||
break;
|
||||
case ConstantPowerMinus6dB:
|
||||
top->set_fade_out (FadeConstantPower, len);
|
||||
break;
|
||||
case RegionFades:
|
||||
top->set_fade_out_length (len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
done_end.insert (top);
|
||||
|
|
@ -390,14 +428,18 @@ AudioPlaylist::check_crossfades (Evoral::Range<framepos_t> range)
|
|||
for (RegionList::iterator i = starts->begin(); i != starts->end(); ++i) {
|
||||
if (done_start.find (*i) == done_start.end()) {
|
||||
boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (*i);
|
||||
r->set_default_fade_in ();
|
||||
if (r->fade_in_is_xfade()) {
|
||||
r->set_default_fade_in ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (RegionList::iterator i = ends->begin(); i != ends->end(); ++i) {
|
||||
if (done_end.find (*i) == done_end.end()) {
|
||||
boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (*i);
|
||||
r->set_default_fade_out ();
|
||||
if (r->fade_out_is_xfade()) {
|
||||
r->set_default_fade_out ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -621,11 +663,12 @@ AudioPlaylist::pre_uncombine (vector<boost::shared_ptr<Region> >& originals, boo
|
|||
int
|
||||
AudioPlaylist::set_state (const XMLNode& node, int version)
|
||||
{
|
||||
int const r = Playlist::set_state (node, version);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
return Playlist::set_state (node, version);
|
||||
}
|
||||
|
||||
void
|
||||
AudioPlaylist::load_legacy_crossfades (const XMLNode& node, int version)
|
||||
{
|
||||
/* Read legacy Crossfade nodes and set up region fades accordingly */
|
||||
|
||||
XMLNodeList children = node.children ();
|
||||
|
|
@ -634,36 +677,97 @@ AudioPlaylist::set_state (const XMLNode& node, int version)
|
|||
|
||||
XMLProperty* p = (*i)->property (X_("active"));
|
||||
assert (p);
|
||||
|
||||
if (!string_is_affirmative (p->value())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((p = (*i)->property (X_("in"))) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
p = (*i)->property (X_("in"));
|
||||
assert (p);
|
||||
boost::shared_ptr<Region> in = region_by_id (PBD::ID (p->value ()));
|
||||
assert (in);
|
||||
|
||||
if (!in) {
|
||||
warning << string_compose (_("Legacy crossfade involved an incoming region not present in playlist \"%1\" - crossfade discarded"),
|
||||
name())
|
||||
<< endmsg;
|
||||
continue;
|
||||
}
|
||||
|
||||
boost::shared_ptr<AudioRegion> in_a = boost::dynamic_pointer_cast<AudioRegion> (in);
|
||||
assert (in_a);
|
||||
|
||||
p = (*i)->property (X_("out"));
|
||||
assert (p);
|
||||
if ((p = (*i)->property (X_("out"))) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
boost::shared_ptr<Region> out = region_by_id (PBD::ID (p->value ()));
|
||||
assert (out);
|
||||
|
||||
if (!out) {
|
||||
warning << string_compose (_("Legacy crossfade involved an outgoing region not present in playlist \"%1\" - crossfade discarded"),
|
||||
name())
|
||||
<< endmsg;
|
||||
continue;
|
||||
}
|
||||
|
||||
boost::shared_ptr<AudioRegion> out_a = boost::dynamic_pointer_cast<AudioRegion> (out);
|
||||
assert (out_a);
|
||||
|
||||
XMLNodeList c = (*i)->children ();
|
||||
for (XMLNodeConstIterator j = c.begin(); j != c.end(); ++j) {
|
||||
if ((*j)->name() == X_("FadeIn")) {
|
||||
in_a->fade_in()->set_state (**j, version);
|
||||
in_a->set_fade_in_active (true);
|
||||
} else if ((*j)->name() == X_("FadeOut")) {
|
||||
out_a->fade_out()->set_state (**j, version);
|
||||
out_a->set_fade_out_active (true);
|
||||
/* now decide whether to add a fade in or fade out
|
||||
* xfade and to which region
|
||||
*/
|
||||
|
||||
if (in->layer() <= out->layer()) {
|
||||
|
||||
/* incoming region is below the outgoing one,
|
||||
* so apply a fade out to the outgoing one
|
||||
*/
|
||||
|
||||
const XMLNodeList c = (*i)->children ();
|
||||
|
||||
for (XMLNodeConstIterator j = c.begin(); j != c.end(); ++j) {
|
||||
if ((*j)->name() == X_("FadeOut")) {
|
||||
out_a->fade_out()->set_state (**j, version);
|
||||
} else if ((*j)->name() == X_("FadeIn")) {
|
||||
out_a->inverse_fade_out()->set_state (**j, version);
|
||||
}
|
||||
}
|
||||
|
||||
if ((p = (*i)->property ("follow-overlap")) != 0) {
|
||||
out_a->set_fade_out_is_short (!string_is_affirmative (p->value()));
|
||||
} else {
|
||||
out_a->set_fade_out_is_short (false);
|
||||
}
|
||||
|
||||
out_a->set_fade_out_is_xfade (true);
|
||||
out_a->set_fade_out_active (true);
|
||||
|
||||
} else {
|
||||
|
||||
/* apply a fade in to the incoming region,
|
||||
* since its above the outgoing one
|
||||
*/
|
||||
|
||||
const XMLNodeList c = (*i)->children ();
|
||||
|
||||
for (XMLNodeConstIterator j = c.begin(); j != c.end(); ++j) {
|
||||
if ((*j)->name() == X_("FadeIn")) {
|
||||
in_a->fade_in()->set_state (**j, version);
|
||||
} else if ((*j)->name() == X_("FadeOut")) {
|
||||
in_a->inverse_fade_in()->set_state (**j, version);
|
||||
}
|
||||
}
|
||||
|
||||
if ((p = (*i)->property ("follow-overlap")) != 0) {
|
||||
in_a->set_fade_in_is_short (!string_is_affirmative (p->value()));
|
||||
} else {
|
||||
in_a->set_fade_in_is_short (false);
|
||||
}
|
||||
|
||||
in_a->set_fade_in_is_xfade (true);
|
||||
in_a->set_fade_in_active (true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,6 +61,10 @@ namespace ARDOUR {
|
|||
PBD::PropertyDescriptor<bool> fade_in_active;
|
||||
PBD::PropertyDescriptor<bool> fade_out_active;
|
||||
PBD::PropertyDescriptor<float> scale_amplitude;
|
||||
PBD::PropertyDescriptor<bool> fade_out_is_xfade;
|
||||
PBD::PropertyDescriptor<bool> fade_out_is_short;
|
||||
PBD::PropertyDescriptor<bool> fade_in_is_xfade;
|
||||
PBD::PropertyDescriptor<bool> fade_in_is_short;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -74,14 +78,14 @@ reverse_curve (boost::shared_ptr<Evoral::ControlList> dst, boost::shared_ptr<con
|
|||
size_t len = src->back()->when;
|
||||
|
||||
for (Evoral::ControlList::const_iterator it = src->begin(); it!=src->end(); it++) {
|
||||
dst->add ( len - (*it)->when, (*it)->value );
|
||||
dst->add (len - (*it)->when, (*it)->value);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
generate_inverse_power_curve (boost::shared_ptr<Evoral::ControlList> dst, boost::shared_ptr<const Evoral::ControlList> src)
|
||||
{
|
||||
//calc inverse curve using sum of squares
|
||||
// calc inverse curve using sum of squares
|
||||
for (Evoral::ControlList::const_iterator it = src->begin(); it!=src->end(); ++it ) {
|
||||
float value = (*it)->value;
|
||||
value = 1 - powf(value,2);
|
||||
|
|
@ -90,18 +94,6 @@ generate_inverse_power_curve (boost::shared_ptr<Evoral::ControlList> dst, boost:
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
static void
|
||||
generate_inverse_coefficient_curve (boost::shared_ptr<Evoral::ControlList> dst, boost::shared_ptr<const Evoral::ControlList> src)
|
||||
{
|
||||
//calc inverse gain coefficient curve
|
||||
for (Evoral::ControlList::const_iterator it = src->begin(); it!=src->end(); ++it ) {
|
||||
float value = 1.0 - (*it)->value;
|
||||
dst->fast_simple_add ( (*it)->when, value );
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
static void
|
||||
generate_db_fade (boost::shared_ptr<Evoral::ControlList> dst, double len, int num_steps, float dB_drop)
|
||||
{
|
||||
|
|
@ -164,6 +156,14 @@ AudioRegion::make_property_quarks ()
|
|||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade-out-active = %1\n", Properties::fade_out_active.property_id));
|
||||
Properties::scale_amplitude.property_id = g_quark_from_static_string (X_("scale-amplitude"));
|
||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for scale-amplitude = %1\n", Properties::scale_amplitude.property_id));
|
||||
Properties::fade_out_is_xfade.property_id = g_quark_from_static_string (X_("fade-out-is-xfade"));
|
||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade-out-is-xfade = %1\n", Properties::fade_out_is_xfade.property_id));
|
||||
Properties::fade_out_is_short.property_id = g_quark_from_static_string (X_("fade-out-is-short"));
|
||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade-out-is-short = %1\n", Properties::fade_out_is_short.property_id));
|
||||
Properties::fade_in_is_xfade.property_id = g_quark_from_static_string (X_("fade-in-is-xfade"));
|
||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade-in-is-xfade = %1\n", Properties::fade_in_is_xfade.property_id));
|
||||
Properties::fade_in_is_short.property_id = g_quark_from_static_string (X_("fade-in-is-short"));
|
||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade-in-is-short = %1\n", Properties::fade_in_is_short.property_id));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -177,6 +177,10 @@ AudioRegion::register_properties ()
|
|||
add_property (_fade_in_active);
|
||||
add_property (_fade_out_active);
|
||||
add_property (_scale_amplitude);
|
||||
add_property (_fade_out_is_xfade);
|
||||
add_property (_fade_out_is_short);
|
||||
add_property (_fade_in_is_xfade);
|
||||
add_property (_fade_in_is_short);
|
||||
}
|
||||
|
||||
#define AUDIOREGION_STATE_DEFAULT \
|
||||
|
|
@ -185,7 +189,11 @@ AudioRegion::register_properties ()
|
|||
, _default_fade_out (Properties::default_fade_out, true) \
|
||||
, _fade_in_active (Properties::fade_in_active, true) \
|
||||
, _fade_out_active (Properties::fade_out_active, true) \
|
||||
, _scale_amplitude (Properties::scale_amplitude, 1.0)
|
||||
, _scale_amplitude (Properties::scale_amplitude, 1.0) \
|
||||
, _fade_in_is_xfade (Properties::fade_in_is_xfade, false) \
|
||||
, _fade_out_is_xfade (Properties::fade_out_is_xfade, false) \
|
||||
, _fade_in_is_short (Properties::fade_in_is_short, false) \
|
||||
, _fade_out_is_short (Properties::fade_out_is_short, false)
|
||||
|
||||
#define AUDIOREGION_COPY_STATE(other) \
|
||||
_envelope_active (Properties::envelope_active, other->_envelope_active) \
|
||||
|
|
@ -193,7 +201,11 @@ AudioRegion::register_properties ()
|
|||
, _default_fade_out (Properties::default_fade_out, other->_default_fade_out) \
|
||||
, _fade_in_active (Properties::fade_in_active, other->_fade_in_active) \
|
||||
, _fade_out_active (Properties::fade_out_active, other->_fade_out_active) \
|
||||
, _scale_amplitude (Properties::scale_amplitude, other->_scale_amplitude)
|
||||
, _scale_amplitude (Properties::scale_amplitude, other->_scale_amplitude) \
|
||||
, _fade_in_is_xfade (Properties::fade_in_is_xfade, other->_fade_in_is_xfade) \
|
||||
, _fade_out_is_xfade (Properties::fade_out_is_xfade, other->_fade_out_is_xfade) \
|
||||
, _fade_in_is_short (Properties::fade_in_is_short, other->_fade_in_is_short) \
|
||||
, _fade_out_is_short (Properties::fade_out_is_short, other->_fade_out_is_short)
|
||||
/* a Session will reset these to its chosen defaults by calling AudioRegion::set_default_fade() */
|
||||
|
||||
void
|
||||
|
|
@ -223,8 +235,6 @@ AudioRegion::AudioRegion (Session& s, framepos_t start, framecnt_t len, std::str
|
|||
, _envelope (new AutomationList(Evoral::Parameter(EnvelopeAutomation)))
|
||||
, _fade_in_suspended (0)
|
||||
, _fade_out_suspended (0)
|
||||
, _fade_in_is_xfade (false)
|
||||
, _fade_out_is_xfade (false)
|
||||
{
|
||||
init ();
|
||||
assert (_sources.size() == _master_sources.size());
|
||||
|
|
@ -242,8 +252,6 @@ AudioRegion::AudioRegion (const SourceList& srcs)
|
|||
, _envelope (new AutomationList(Evoral::Parameter(EnvelopeAutomation)))
|
||||
, _fade_in_suspended (0)
|
||||
, _fade_out_suspended (0)
|
||||
, _fade_in_is_xfade (false)
|
||||
, _fade_out_is_xfade (false)
|
||||
{
|
||||
init ();
|
||||
assert (_sources.size() == _master_sources.size());
|
||||
|
|
@ -263,8 +271,6 @@ AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other)
|
|||
, _envelope (new AutomationList (*other->_envelope, 0, other->_length))
|
||||
, _fade_in_suspended (0)
|
||||
, _fade_out_suspended (0)
|
||||
, _fade_in_is_xfade (false)
|
||||
, _fade_out_is_xfade (false)
|
||||
{
|
||||
/* don't use init here, because we got fade in/out from the other region
|
||||
*/
|
||||
|
|
@ -291,8 +297,6 @@ AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, framecnt_t
|
|||
, _envelope (new AutomationList (*other->_envelope, offset, other->_length))
|
||||
, _fade_in_suspended (0)
|
||||
, _fade_out_suspended (0)
|
||||
, _fade_in_is_xfade (false)
|
||||
, _fade_out_is_xfade (false)
|
||||
{
|
||||
/* don't use init here, because we got fade in/out from the other region
|
||||
*/
|
||||
|
|
@ -316,8 +320,6 @@ AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, const Sour
|
|||
, _envelope (new AutomationList (*other->_envelope))
|
||||
, _fade_in_suspended (0)
|
||||
, _fade_out_suspended (0)
|
||||
, _fade_in_is_xfade (false)
|
||||
, _fade_out_is_xfade (false)
|
||||
{
|
||||
/* make-a-sort-of-copy-with-different-sources constructor (used by audio filter) */
|
||||
|
||||
|
|
@ -341,8 +343,6 @@ AudioRegion::AudioRegion (SourceList& srcs)
|
|||
, _envelope (new AutomationList(Evoral::Parameter(EnvelopeAutomation)))
|
||||
, _fade_in_suspended (0)
|
||||
, _fade_out_suspended (0)
|
||||
, _fade_in_is_xfade (false)
|
||||
, _fade_out_is_xfade (false)
|
||||
{
|
||||
init ();
|
||||
|
||||
|
|
@ -524,7 +524,7 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
|
|||
|
||||
/* COMPUTE DETAILS OF ANY FADES INVOLVED IN THIS READ */
|
||||
|
||||
/* Amount of fade in that we are dealing with in this read */
|
||||
/* Amount (length) of fade in that we are dealing with in this read */
|
||||
framecnt_t fade_in_limit = 0;
|
||||
|
||||
/* Offset from buf / mixdown_buffer of the start
|
||||
|
|
@ -532,7 +532,7 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
|
|||
*/
|
||||
frameoffset_t fade_out_offset = 0;
|
||||
|
||||
/* Amount of fade in that we are dealing with in this read */
|
||||
/* Amount (length) of fade out that we are dealing with in this read */
|
||||
framecnt_t fade_out_limit = 0;
|
||||
|
||||
framecnt_t fade_interval_start = 0;
|
||||
|
|
@ -542,7 +542,7 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
|
|||
if (_fade_in_active && _session.config.get_use_region_fades()) {
|
||||
|
||||
framecnt_t fade_in_length = (framecnt_t) _fade_in->back()->when;
|
||||
|
||||
|
||||
/* see if this read is within the fade in */
|
||||
|
||||
if (internal_offset < fade_in_length) {
|
||||
|
|
@ -611,7 +611,6 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
|
|||
apply_gain_to_buffer (mixdown_buffer, to_read, _scale_amplitude);
|
||||
}
|
||||
|
||||
|
||||
/* APPLY FADES TO THE DATA IN mixdown_buffer AND MIX THE RESULTS INTO
|
||||
* buf. The key things to realize here: (1) the fade being applied is
|
||||
* (as of April 26th 2012) just the inverse of the fade in curve (2)
|
||||
|
|
@ -623,6 +622,7 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
|
|||
|
||||
if (opaque()) {
|
||||
if (_inverse_fade_in) {
|
||||
|
||||
|
||||
/* explicit inverse fade in curve (e.g. for constant
|
||||
* power), so we have to fetch it.
|
||||
|
|
@ -671,7 +671,7 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
|
|||
|
||||
_inverse_fade_out->curve().get_vector (curve_offset, curve_offset + fade_out_limit, gain_buffer, fade_out_limit);
|
||||
|
||||
/* Fade the data from lower levels out */
|
||||
/* Fade the data from lower levels in */
|
||||
for (framecnt_t n = 0, m = fade_out_offset; n < fade_out_limit; ++n, ++m) {
|
||||
buf[m] *= gain_buffer[n];
|
||||
}
|
||||
|
|
@ -682,7 +682,8 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
|
|||
|
||||
} else {
|
||||
|
||||
/* no explicit inverse fade out, so just use (1 - fade
|
||||
/* no explicit inverse fade out (which is
|
||||
* actually a fade in), so just use (1 - fade
|
||||
* out) for the fade in of lower layers
|
||||
*/
|
||||
|
||||
|
|
@ -696,12 +697,13 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
|
|||
_fade_out->curve().get_vector (curve_offset, curve_offset + fade_out_limit, gain_buffer, fade_out_limit);
|
||||
}
|
||||
|
||||
/* Mix our newly-read data out, with the fade */
|
||||
/* Mix our newly-read data with whatever was already there,
|
||||
with the fade out applied to our data.
|
||||
*/
|
||||
for (framecnt_t n = 0, m = fade_out_offset; n < fade_out_limit; ++n, ++m) {
|
||||
buf[m] += mixdown_buffer[m] * gain_buffer[n];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* MIX OR COPY THE REGION BODY FROM mixdown_buffer INTO buf */
|
||||
|
||||
|
|
@ -806,7 +808,6 @@ AudioRegion::state ()
|
|||
}
|
||||
|
||||
child = node.add_child (X_("FadeIn"));
|
||||
child->add_property ("is-xfade", (_fade_in_is_xfade ? "yes" : "no"));
|
||||
|
||||
if (_default_fade_in) {
|
||||
child->add_property ("default", "yes");
|
||||
|
|
@ -820,7 +821,6 @@ AudioRegion::state ()
|
|||
}
|
||||
|
||||
child = node.add_child (X_("FadeOut"));
|
||||
child->add_property ("is-xfade", (_fade_out_is_xfade ? "yes" : "no"));
|
||||
|
||||
if (_default_fade_out) {
|
||||
child->add_property ("default", "yes");
|
||||
|
|
@ -899,12 +899,6 @@ AudioRegion::_set_state (const XMLNode& node, int version, PropertyChange& what_
|
|||
}
|
||||
}
|
||||
|
||||
if ((prop = child->property ("is-xfade")) != 0) {
|
||||
_fade_in_is_xfade = string_is_affirmative (prop->value());
|
||||
} else {
|
||||
_fade_in_is_xfade = false;
|
||||
}
|
||||
|
||||
if ((prop = child->property ("active")) != 0) {
|
||||
if (string_is_affirmative (prop->value())) {
|
||||
set_fade_in_active (true);
|
||||
|
|
@ -913,6 +907,12 @@ AudioRegion::_set_state (const XMLNode& node, int version, PropertyChange& what_
|
|||
}
|
||||
}
|
||||
|
||||
/* legacy a3 */
|
||||
|
||||
if ((prop = child->property ("is-xfade")) != 0) {
|
||||
_fade_in_is_xfade = string_is_affirmative (prop->value());
|
||||
}
|
||||
|
||||
} else if (child->name() == "FadeOut") {
|
||||
|
||||
_fade_out->clear ();
|
||||
|
|
@ -925,14 +925,8 @@ AudioRegion::_set_state (const XMLNode& node, int version, PropertyChange& what_
|
|||
_fade_out->set_state (*grandchild, version);
|
||||
}
|
||||
}
|
||||
|
||||
if ((prop = child->property ("is-xfade")) != 0) {
|
||||
_fade_out_is_xfade = string_is_affirmative (prop->value());
|
||||
} else {
|
||||
_fade_out_is_xfade = false;
|
||||
}
|
||||
|
||||
if ((prop = child->property ("active")) != 0) {
|
||||
|
||||
if ((prop = child->property ("active")) != 0) {
|
||||
if (string_is_affirmative (prop->value())) {
|
||||
set_fade_out_active (true);
|
||||
} else {
|
||||
|
|
@ -940,6 +934,12 @@ AudioRegion::_set_state (const XMLNode& node, int version, PropertyChange& what_
|
|||
}
|
||||
}
|
||||
|
||||
/* legacy a3 */
|
||||
|
||||
if ((prop = child->property ("is-xfade")) != 0) {
|
||||
_fade_out_is_xfade = string_is_affirmative (prop->value());
|
||||
}
|
||||
|
||||
} else if (child->name() == "InvFadeIn") {
|
||||
XMLNode* grandchild = child->child ("AutomationList");
|
||||
if (grandchild) {
|
||||
|
|
@ -1163,7 +1163,7 @@ AudioRegion::set_fade_in_length (framecnt_t len)
|
|||
|
||||
if (_session.config.get_xfade_model() == FullCrossfade &&
|
||||
_session.config.get_auto_xfade() &&
|
||||
_fade_in_is_xfade) {
|
||||
_fade_in_is_xfade && !_fade_in_is_short) {
|
||||
|
||||
/* trim a single other region below us to the new start
|
||||
of the fade.
|
||||
|
|
@ -1202,7 +1202,7 @@ AudioRegion::set_fade_out_length (framecnt_t len)
|
|||
|
||||
if (_session.config.get_xfade_model() == FullCrossfade &&
|
||||
_session.config.get_auto_xfade() &&
|
||||
_fade_out_is_xfade) {
|
||||
_fade_out_is_xfade && !_fade_out_is_short) {
|
||||
|
||||
/* trim a single other region below us to the new start
|
||||
of the fade.
|
||||
|
|
@ -1256,6 +1256,7 @@ AudioRegion::set_default_fade_in ()
|
|||
{
|
||||
_fade_in_suspended = 0;
|
||||
_fade_in_is_xfade = false;
|
||||
_fade_in_is_short = true;
|
||||
set_fade_in (FadeLinear, 64);
|
||||
}
|
||||
|
||||
|
|
@ -1264,6 +1265,7 @@ AudioRegion::set_default_fade_out ()
|
|||
{
|
||||
_fade_out_suspended = 0;
|
||||
_fade_out_is_xfade = false;
|
||||
_fade_out_is_short = true;
|
||||
set_fade_out (FadeLinear, 64);
|
||||
}
|
||||
|
||||
|
|
@ -1835,13 +1837,46 @@ AudioRegion::body_range () const
|
|||
void
|
||||
AudioRegion::set_fade_in_is_xfade (bool yn)
|
||||
{
|
||||
if (yn == _fade_in_is_xfade) {
|
||||
return;
|
||||
}
|
||||
|
||||
_fade_in_is_xfade = yn;
|
||||
send_change (PropertyChange (Properties::fade_in_is_xfade));
|
||||
}
|
||||
|
||||
void
|
||||
AudioRegion::set_fade_out_is_xfade (bool yn)
|
||||
{
|
||||
if (yn == _fade_out_is_xfade) {
|
||||
return;
|
||||
}
|
||||
|
||||
_fade_out_is_xfade = yn;
|
||||
send_change (PropertyChange (Properties::fade_out_is_xfade));
|
||||
}
|
||||
|
||||
void
|
||||
AudioRegion::set_fade_in_is_short (bool yn)
|
||||
{
|
||||
if (yn == _fade_in_is_short) {
|
||||
return;
|
||||
}
|
||||
|
||||
_fade_in_is_short = yn;
|
||||
send_change (PropertyChange (Properties::fade_in_is_short));
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
AudioRegion::set_fade_out_is_short (bool yn)
|
||||
{
|
||||
if (yn == _fade_out_is_short) {
|
||||
return;
|
||||
}
|
||||
|
||||
_fade_out_is_short = yn;
|
||||
send_change (PropertyChange (Properties::fade_out_is_short));
|
||||
}
|
||||
|
||||
boost::shared_ptr<Region>
|
||||
|
|
|
|||
|
|
@ -269,7 +269,7 @@ BufferSet::get_lv2_midi(bool input, size_t i, bool old_api)
|
|||
mbuf.size(), (void*) mbuf.data()));
|
||||
|
||||
LV2_Evbuf_Iterator i = lv2_evbuf_begin(evbuf);
|
||||
const uint32_t type = LV2Plugin::midi_event_type(old_api);
|
||||
const uint32_t type = LV2Plugin::midi_event_type();
|
||||
for (MidiBuffer::iterator e = mbuf.begin(); e != mbuf.end(); ++e) {
|
||||
const Evoral::MIDIEvent<framepos_t> ev(*e, false);
|
||||
#ifndef NDEBUG
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include "pbd/strsplit.h"
|
||||
#include "pbd/shortpath.h"
|
||||
#include "pbd/enumwriter.h"
|
||||
#include "pbd/filesystem.h"
|
||||
|
||||
#include <glibmm/miscutils.h>
|
||||
#include <glibmm/fileutils.h>
|
||||
|
|
@ -122,11 +123,7 @@ FileSource::init (const string& pathstr, bool must_exist)
|
|||
}
|
||||
|
||||
set_within_session_from_path (_path);
|
||||
|
||||
if (!within_session()) {
|
||||
_session.ensure_search_path_includes (Glib::path_get_dirname (_path), _type);
|
||||
}
|
||||
|
||||
|
||||
_name = Glib::path_get_basename (_path);
|
||||
|
||||
if (_file_is_new && must_exist) {
|
||||
|
|
@ -281,7 +278,7 @@ FileSource::find (Session& s, DataType type, const string& path, bool must_exist
|
|||
++j;
|
||||
|
||||
while (j != hits.end()) {
|
||||
if (inodes_same (*i, *j)) {
|
||||
if (PBD::sys::inodes_same (*i, *j)) {
|
||||
/* *i and *j are the same file; break out of the loop early */
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,20 +68,16 @@ using namespace ARDOUR;
|
|||
using namespace PBD;
|
||||
|
||||
URIMap LV2Plugin::_uri_map;
|
||||
uint32_t LV2Plugin::_midi_event_type_ev = _uri_map.uri_to_id(
|
||||
"http://lv2plug.in/ns/ext/event",
|
||||
"http://lv2plug.in/ns/ext/midi#MidiEvent");
|
||||
uint32_t LV2Plugin::_midi_event_type = _uri_map.uri_to_id(
|
||||
NULL,
|
||||
"http://lv2plug.in/ns/ext/midi#MidiEvent");
|
||||
uint32_t LV2Plugin::_chunk_type = _uri_map.uri_to_id(
|
||||
NULL, LV2_ATOM__Chunk);
|
||||
LV2_ATOM__Chunk);
|
||||
uint32_t LV2Plugin::_sequence_type = _uri_map.uri_to_id(
|
||||
NULL, LV2_ATOM__Sequence);
|
||||
LV2_ATOM__Sequence);
|
||||
uint32_t LV2Plugin::_event_transfer_type = _uri_map.uri_to_id(
|
||||
NULL, LV2_ATOM__eventTransfer);
|
||||
LV2_ATOM__eventTransfer);
|
||||
uint32_t LV2Plugin::_path_type = _uri_map.uri_to_id(
|
||||
NULL, LV2_ATOM__Path);
|
||||
LV2_ATOM__Path);
|
||||
|
||||
class LV2World : boost::noncopyable {
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
#include "ardour/mtdm.h"
|
||||
|
||||
MTDM::MTDM (void)
|
||||
MTDM::MTDM ()
|
||||
: _cnt (0)
|
||||
, _inv (0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ using namespace std;
|
|||
using namespace ARDOUR;
|
||||
|
||||
Panner::Panner (boost::shared_ptr<Pannable> p)
|
||||
: _frozen (0)
|
||||
{
|
||||
// boost_debug_shared_ptr_mark_interesting (this, "panner");
|
||||
_pannable = p;
|
||||
|
|
@ -118,3 +119,17 @@ Panner::set_state (XMLNode const &, int)
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Panner::freeze ()
|
||||
{
|
||||
_frozen++;
|
||||
}
|
||||
|
||||
void
|
||||
Panner::thaw ()
|
||||
{
|
||||
if (_frozen > 0.0) {
|
||||
_frozen--;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,9 +47,9 @@ using namespace ARDOUR;
|
|||
using namespace PBD;
|
||||
|
||||
namespace ARDOUR {
|
||||
namespace Properties {
|
||||
PBD::PropertyDescriptor<bool> regions;
|
||||
}
|
||||
namespace Properties {
|
||||
PBD::PropertyDescriptor<bool> regions;
|
||||
}
|
||||
}
|
||||
|
||||
struct ShowMeTheList {
|
||||
|
|
@ -311,6 +311,7 @@ Playlist::init (bool hide)
|
|||
in_partition = false;
|
||||
subcnt = 0;
|
||||
_frozen = false;
|
||||
_capture_insertion_underway = false;
|
||||
_combine_ops = 0;
|
||||
|
||||
_session.history().BeginUndoRedo.connect_same_thread (*this, boost::bind (&Playlist::begin_undo, this));
|
||||
|
|
@ -2179,6 +2180,16 @@ Playlist::n_regions() const
|
|||
return regions.size();
|
||||
}
|
||||
|
||||
/** @return true if the all_regions list is empty, ie this playlist
|
||||
* has never had a region added to it.
|
||||
*/
|
||||
bool
|
||||
Playlist::all_regions_empty() const
|
||||
{
|
||||
RegionReadLock rl (const_cast<Playlist *> (this));
|
||||
return all_regions.empty();
|
||||
}
|
||||
|
||||
pair<framepos_t, framepos_t>
|
||||
Playlist::get_extent () const
|
||||
{
|
||||
|
|
@ -3124,3 +3135,9 @@ restart:
|
|||
check_crossfades (*i);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Playlist::set_capture_insertion_in_progress (bool yn)
|
||||
{
|
||||
_capture_insertion_underway = yn;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,10 +62,7 @@ PortInsert::~PortInsert ()
|
|||
void
|
||||
PortInsert::start_latency_detection ()
|
||||
{
|
||||
if (_mtdm != 0) {
|
||||
delete _mtdm;
|
||||
}
|
||||
|
||||
delete _mtdm;
|
||||
_mtdm = new MTDM;
|
||||
_latency_flush_frames = false;
|
||||
_latency_detect = true;
|
||||
|
|
@ -118,8 +115,9 @@ PortInsert::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame,
|
|||
Sample* out = outbuf.data();
|
||||
|
||||
_mtdm->process (nframes, in, out);
|
||||
|
||||
|
||||
outbuf.set_is_silent (false);
|
||||
outbuf.set_written (true);
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -75,11 +75,10 @@ RegionFactory::create (boost::shared_ptr<const Region> region, bool announce)
|
|||
if (ret->session().config.get_glue_new_regions_to_bars_and_beats ()) {
|
||||
ret->set_position_lock_style (MusicTime);
|
||||
}
|
||||
|
||||
map_add (ret);
|
||||
|
||||
/* pure copy constructor - no property list */
|
||||
if (announce) {
|
||||
map_add (ret);
|
||||
CheckNewRegion (ret);
|
||||
}
|
||||
}
|
||||
|
|
@ -119,9 +118,8 @@ RegionFactory::create (boost::shared_ptr<Region> region, const PropertyList& pli
|
|||
ret->set_position_lock_style (MusicTime);
|
||||
}
|
||||
|
||||
map_add (ret);
|
||||
|
||||
if (announce) {
|
||||
map_add (ret);
|
||||
CheckNewRegion (ret);
|
||||
}
|
||||
}
|
||||
|
|
@ -161,9 +159,8 @@ RegionFactory::create (boost::shared_ptr<Region> region, frameoffset_t offset, c
|
|||
ret->set_position_lock_style (MusicTime);
|
||||
}
|
||||
|
||||
map_add (ret);
|
||||
|
||||
if (announce) {
|
||||
map_add (ret);
|
||||
CheckNewRegion (ret);
|
||||
}
|
||||
}
|
||||
|
|
@ -203,9 +200,8 @@ RegionFactory::create (boost::shared_ptr<Region> region, const SourceList& srcs,
|
|||
ret->set_position_lock_style (MusicTime);
|
||||
}
|
||||
|
||||
map_add (ret);
|
||||
|
||||
if (announce) {
|
||||
map_add (ret);
|
||||
CheckNewRegion (ret);
|
||||
}
|
||||
}
|
||||
|
|
@ -248,9 +244,8 @@ RegionFactory::create (const SourceList& srcs, const PropertyList& plist, bool a
|
|||
ret->set_position_lock_style (MusicTime);
|
||||
}
|
||||
|
||||
map_add (ret);
|
||||
|
||||
if (announce) {
|
||||
map_add (ret);
|
||||
CheckNewRegion (ret);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2952,6 +2952,14 @@ Session::add_source (boost::shared_ptr<Source> source)
|
|||
|
||||
/* yay, new source */
|
||||
|
||||
boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (source);
|
||||
|
||||
if (fs) {
|
||||
if (!fs->within_session()) {
|
||||
ensure_search_path_includes (Glib::path_get_dirname (fs->path()), fs->type());
|
||||
}
|
||||
}
|
||||
|
||||
set_dirty();
|
||||
|
||||
boost::shared_ptr<AudioFileSource> afs;
|
||||
|
|
@ -4470,7 +4478,7 @@ Session::ensure_search_path_includes (const string& path, DataType type)
|
|||
search_path = config.get_midi_search_path ();
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
split (search_path, dirs, ':');
|
||||
|
||||
for (vector<string>::iterator i = dirs.begin(); i != dirs.end(); ++i) {
|
||||
|
|
@ -4480,7 +4488,7 @@ Session::ensure_search_path_includes (const string& path, DataType type)
|
|||
|
||||
On Windows, I think we could just do if (*i == path) here.
|
||||
*/
|
||||
if (inodes_same (*i, path)) {
|
||||
if (PBD::sys::inodes_same (*i, path)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -428,7 +428,7 @@ bool
|
|||
Session::path_is_within_session (const std::string& path)
|
||||
{
|
||||
for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
|
||||
if (path.find ((*i).path) == 0) {
|
||||
if (PBD::sys::path_is_within (i->path, path)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
29
libs/ardour/test/mtdm_test.cc
Normal file
29
libs/ardour/test/mtdm_test.cc
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#include <cstring>
|
||||
#include <cmath>
|
||||
#include "ardour/mtdm.h"
|
||||
#include "mtdm_test.h"
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION (MTDMTest);
|
||||
|
||||
using namespace std;
|
||||
|
||||
void
|
||||
MTDMTest::basicTest ()
|
||||
{
|
||||
float in[256];
|
||||
float out[256];
|
||||
|
||||
memset (in, 0, 256 * sizeof (float));
|
||||
MTDM* mtdm = new MTDM;
|
||||
mtdm->process (256, in, out);
|
||||
memcpy (in, out, 256 * sizeof (float));
|
||||
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
mtdm->process (256, in, out);
|
||||
memcpy (in, out, 256 * sizeof (float));
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL (0, mtdm->resolve ());
|
||||
CPPUNIT_ASSERT (mtdm->err() < 1);
|
||||
CPPUNIT_ASSERT_EQUAL (256.0, rint (mtdm->del()));
|
||||
}
|
||||
}
|
||||
17
libs/ardour/test/mtdm_test.h
Normal file
17
libs/ardour/test/mtdm_test.h
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#include <sigc++/sigc++.h>
|
||||
#include <cppunit/TestFixture.h>
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
|
||||
class MTDMTest : public CppUnit::TestFixture
|
||||
{
|
||||
CPPUNIT_TEST_SUITE (MTDMTest);
|
||||
CPPUNIT_TEST (basicTest);
|
||||
CPPUNIT_TEST_SUITE_END ();
|
||||
|
||||
public:
|
||||
void setUp () {}
|
||||
void tearDown () {}
|
||||
|
||||
void basicTest ();
|
||||
};
|
||||
|
||||
|
|
@ -329,7 +329,15 @@ Track::set_name (const string& str)
|
|||
return false;
|
||||
}
|
||||
|
||||
_diskstream->set_name (str);
|
||||
if (_diskstream->playlist()->all_regions_empty ()) {
|
||||
/* Only rename the diskstream (and therefore the playlist) if
|
||||
the playlist has never had a region added to it. Otherwise
|
||||
people can get confused if, say, they have notes about a
|
||||
playlist with a given name and then it changes (see mantis
|
||||
#4759).
|
||||
*/
|
||||
_diskstream->set_name (str);
|
||||
}
|
||||
|
||||
/* save state so that the statefile fully reflects any filename changes */
|
||||
|
||||
|
|
|
|||
|
|
@ -18,112 +18,94 @@
|
|||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "pbd/error.h"
|
||||
|
||||
#include "ardour/uri_map.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace ARDOUR {
|
||||
|
||||
static uint32_t
|
||||
c_uri_map_uri_to_id(LV2_URI_Map_Callback_Data callback_data,
|
||||
const char* map,
|
||||
const char* uri)
|
||||
{
|
||||
URIMap* const me = (URIMap*)callback_data;
|
||||
const uint32_t id = me->uri_to_id(uri);
|
||||
|
||||
/* The event context with the uri-map extension guarantees a value in the
|
||||
range of uint16_t. Ardour used to map to a separate range to achieve
|
||||
this, but unfortunately some plugins are broken and use the incorrect
|
||||
context. To compensate, we simply use the same context for everything
|
||||
and hope that anything in the event context gets mapped before
|
||||
UINT16_MAX is reached (which will be fine unless something seriously
|
||||
weird is going on). If this fails there is nothing we can do, die.
|
||||
*/
|
||||
assert(!map || strcmp(map, "http://lv2plug.in/ns/ext/event")
|
||||
|| id < UINT16_MAX);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
static LV2_URID
|
||||
c_urid_map(LV2_URID_Map_Handle handle,
|
||||
const char* uri)
|
||||
{
|
||||
URIMap* const me = (URIMap*)handle;
|
||||
return me->uri_to_id(uri);
|
||||
}
|
||||
|
||||
static const char*
|
||||
c_urid_unmap(LV2_URID_Unmap_Handle handle,
|
||||
LV2_URID urid)
|
||||
{
|
||||
URIMap* const me = (URIMap*)handle;
|
||||
return me->id_to_uri(urid);
|
||||
}
|
||||
|
||||
URIMap::URIMap()
|
||||
{
|
||||
_uri_map_feature_data.uri_to_id = &URIMap::uri_map_uri_to_id;
|
||||
_uri_map_feature_data.uri_to_id = c_uri_map_uri_to_id;
|
||||
_uri_map_feature_data.callback_data = this;
|
||||
_uri_map_feature.URI = LV2_URI_MAP_URI;
|
||||
_uri_map_feature.data = &_uri_map_feature_data;
|
||||
|
||||
_urid_map_feature_data.map = &URIMap::urid_map;
|
||||
_urid_map_feature_data.map = c_urid_map;
|
||||
_urid_map_feature_data.handle = this;
|
||||
_urid_map_feature.URI = LV2_URID_MAP_URI;
|
||||
_urid_map_feature.data = &_urid_map_feature_data;
|
||||
|
||||
_urid_unmap_feature_data.unmap = &URIMap::urid_unmap;
|
||||
_urid_unmap_feature_data.unmap = c_urid_unmap;
|
||||
_urid_unmap_feature_data.handle = this;
|
||||
_urid_unmap_feature.URI = LV2_URID_UNMAP_URI;
|
||||
_urid_unmap_feature.data = &_urid_unmap_feature_data;
|
||||
}
|
||||
|
||||
|
||||
uint32_t
|
||||
URIMap::uri_to_id(const char* map,
|
||||
const char* uri)
|
||||
URIMap::uri_to_id(const char* uri)
|
||||
{
|
||||
const uint32_t id = static_cast<uint32_t>(g_quark_from_string(uri));
|
||||
if (map && !strcmp(map, "http://lv2plug.in/ns/ext/event")) {
|
||||
GlobalToEvent::iterator i = _global_to_event.find(id);
|
||||
if (i != _global_to_event.end()) {
|
||||
return i->second;
|
||||
} else {
|
||||
if (_global_to_event.size() + 1 > UINT16_MAX) {
|
||||
PBD::error << "Event URI " << uri << " ID out of range." << endl;
|
||||
return 0;
|
||||
}
|
||||
const uint16_t ev_id = _global_to_event.size() + 1;
|
||||
assert(_event_to_global.find(ev_id) == _event_to_global.end());
|
||||
_global_to_event.insert(make_pair(id, ev_id));
|
||||
_event_to_global.insert(make_pair(ev_id, id));
|
||||
return ev_id;
|
||||
}
|
||||
} else {
|
||||
return id;
|
||||
const std::string urimm(uri);
|
||||
const Map::const_iterator i = _map.find(urimm);
|
||||
if (i != _map.end()) {
|
||||
return i->second;
|
||||
}
|
||||
const uint32_t id = _map.size() + 1;
|
||||
_map.insert(std::make_pair(urimm, id));
|
||||
_unmap.insert(std::make_pair(id, urimm));
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
URIMap::id_to_uri(const char* map,
|
||||
const uint32_t id)
|
||||
URIMap::id_to_uri(const uint32_t id) const
|
||||
{
|
||||
if (map && !strcmp(map, "http://lv2plug.in/ns/ext/event")) {
|
||||
EventToGlobal::iterator i = _event_to_global.find(id);
|
||||
if (i == _event_to_global.end()) {
|
||||
PBD::error << "Failed to unmap event URI " << id << endl;
|
||||
return NULL;
|
||||
}
|
||||
return g_quark_to_string(i->second);
|
||||
} else {
|
||||
return g_quark_to_string(id);
|
||||
}
|
||||
|
||||
const Unmap::const_iterator i = _unmap.find(id);
|
||||
return (i != _unmap.end()) ? i->second.c_str() : NULL;
|
||||
}
|
||||
|
||||
|
||||
uint32_t
|
||||
URIMap::uri_map_uri_to_id(LV2_URI_Map_Callback_Data callback_data,
|
||||
const char* map,
|
||||
const char* uri)
|
||||
{
|
||||
URIMap* const me = (URIMap*)callback_data;
|
||||
return me->uri_to_id(map, uri);
|
||||
}
|
||||
|
||||
|
||||
LV2_URID
|
||||
URIMap::urid_map(LV2_URID_Map_Handle handle,
|
||||
const char* uri)
|
||||
{
|
||||
URIMap* const me = (URIMap*)handle;
|
||||
return me->uri_to_id(NULL, uri);
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
URIMap::urid_unmap(LV2_URID_Unmap_Handle handle,
|
||||
LV2_URID urid)
|
||||
{
|
||||
URIMap* const me = (URIMap*)handle;
|
||||
return me->id_to_uri(NULL, urid);
|
||||
}
|
||||
|
||||
|
||||
} // namespace ARDOUR
|
||||
|
||||
|
|
|
|||
|
|
@ -120,46 +120,6 @@ bump_name_once (const std::string& name, char delimiter)
|
|||
|
||||
}
|
||||
|
||||
bool
|
||||
could_be_a_valid_path (const string& path)
|
||||
{
|
||||
vector<string> posix_dirs;
|
||||
vector<string> dos_dirs;
|
||||
string testpath;
|
||||
|
||||
split (path, posix_dirs, '/');
|
||||
split (path, dos_dirs, '\\');
|
||||
|
||||
/* remove the last component of each */
|
||||
|
||||
posix_dirs.erase (--posix_dirs.end());
|
||||
dos_dirs.erase (--dos_dirs.end());
|
||||
|
||||
if (G_DIR_SEPARATOR == '/') {
|
||||
for (vector<string>::iterator x = posix_dirs.begin(); x != posix_dirs.end(); ++x) {
|
||||
testpath = Glib::build_filename (testpath, *x);
|
||||
cerr << "Testing " << testpath << endl;
|
||||
if (!Glib::file_test (testpath, Glib::FILE_TEST_IS_DIR|Glib::FILE_TEST_EXISTS)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (G_DIR_SEPARATOR == '\\') {
|
||||
testpath = "";
|
||||
for (vector<string>::iterator x = dos_dirs.begin(); x != dos_dirs.end(); ++x) {
|
||||
testpath = Glib::build_filename (testpath, *x);
|
||||
cerr << "Testing " << testpath << endl;
|
||||
if (!Glib::file_test (testpath, Glib::FILE_TEST_IS_DIR|Glib::FILE_TEST_EXISTS)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
XMLNode *
|
||||
find_named_node (const XMLNode& node, string name)
|
||||
{
|
||||
|
|
@ -745,18 +705,6 @@ double slider_position_to_gain_with_max (double g, double max_gain)
|
|||
return slider_position_to_gain (g * max_gain/2.0);
|
||||
}
|
||||
|
||||
/** @return true if files a and b have the same inode */
|
||||
bool
|
||||
inodes_same (const string& a, const string& b)
|
||||
{
|
||||
struct stat bA;
|
||||
int const rA = stat (a.c_str(), &bA);
|
||||
struct stat bB;
|
||||
int const rB = stat (b.c_str(), &bB);
|
||||
|
||||
return (rA == 0 && rB == 0 && bA.st_ino == bB.st_ino);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
void c_stacktrace() { stacktrace (cerr); }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -259,11 +259,19 @@ def configure(conf):
|
|||
autowaf.check_pkg(conf, 'sigc++-2.0', uselib_store='SIGCPP',
|
||||
atleast_version='2.0')
|
||||
if Options.options.lv2:
|
||||
autowaf.check_pkg(conf, 'lv2', uselib_store='LV2',
|
||||
atleast_version='1.0.0', mandatory=True)
|
||||
autowaf.check_pkg(conf, 'serd-0', uselib_store='SERD',
|
||||
atleast_version='0.14.0', mandatory=True)
|
||||
autowaf.check_pkg(conf, 'sord-0', uselib_store='SORD',
|
||||
atleast_version='0.8.0', mandatory=True)
|
||||
autowaf.check_pkg(conf, 'sratom-0', uselib_store='SRATOM',
|
||||
atleast_version='0.2.0', mandatory=True)
|
||||
autowaf.check_pkg(conf, 'lilv-0', uselib_store='LILV',
|
||||
atleast_version='0.14.0', mandatory=False)
|
||||
if conf.is_defined('HAVE_LILV'):
|
||||
autowaf.check_pkg(conf, 'suil-0', uselib_store='SUIL',
|
||||
atleast_version='0.6.0', mandatory=False)
|
||||
atleast_version='0.14.0', mandatory=True)
|
||||
autowaf.check_pkg(conf, 'suil-0', uselib_store='SUIL',
|
||||
atleast_version='0.6.0', mandatory=False)
|
||||
conf.define ('LV2_SUPPORT', 1)
|
||||
|
||||
# autowaf.check_pkg(conf, 'soundtouch-1.0', uselib_store='SOUNDTOUCH',
|
||||
# mandatory=False)
|
||||
|
|
@ -335,9 +343,6 @@ int main(int argc, char **argv) {
|
|||
if ogg_supported():
|
||||
conf.define ('HAVE_OGG', 1)
|
||||
|
||||
if Options.options.lv2 and conf.is_defined('HAVE_LILV'):
|
||||
conf.define ('LV2_SUPPORT', 1)
|
||||
|
||||
conf.write_config_header('libardour-config.h', remove=False)
|
||||
|
||||
# Boost headers
|
||||
|
|
@ -437,6 +442,7 @@ def build(bld):
|
|||
test/playlist_layering_test.cc
|
||||
test/playlist_read_test.cc
|
||||
test/control_surfaces_test.cc
|
||||
test/mtdm_test.cc
|
||||
test/testrunner.cc
|
||||
'''.split()
|
||||
|
||||
|
|
|
|||
|
|
@ -106,6 +106,10 @@ public:
|
|||
void set_parameter(const Parameter& p) { _parameter = p; }
|
||||
|
||||
EventList::size_type size() const { return _events.size(); }
|
||||
double length() const {
|
||||
Glib::Mutex::Lock lm (_lock);
|
||||
return _events.empty() ? 0.0 : _events.back()->when;
|
||||
}
|
||||
bool empty() const { return _events.empty(); }
|
||||
|
||||
void reset_default (double val) {
|
||||
|
|
|
|||
|
|
@ -139,7 +139,6 @@ public:
|
|||
return _list.empty ();
|
||||
}
|
||||
|
||||
private:
|
||||
void coalesce () {
|
||||
if (!_dirty) {
|
||||
return;
|
||||
|
|
@ -164,6 +163,8 @@ private:
|
|||
|
||||
_dirty = false;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
List _list;
|
||||
bool _dirty;
|
||||
|
|
@ -178,37 +179,71 @@ struct RangeMove {
|
|||
T to; ///< new start of the range
|
||||
};
|
||||
|
||||
/** Subtract the ranges in `sub' from that in `range',
|
||||
* returning the result.
|
||||
*/
|
||||
template<typename T>
|
||||
RangeList<T> subtract (Range<T> range, RangeList<T> sub)
|
||||
{
|
||||
/* Start with the input range */
|
||||
RangeList<T> result;
|
||||
result.add (range);
|
||||
|
||||
if (sub.empty ()) {
|
||||
result.add (range);
|
||||
return result;
|
||||
}
|
||||
|
||||
T x = range.from;
|
||||
|
||||
typename RangeList<T>::List s = sub.get ();
|
||||
|
||||
/* The basic idea here is to keep a list of the result ranges, and subtract
|
||||
the bits of `sub' from them one by one.
|
||||
*/
|
||||
|
||||
for (typename RangeList<T>::List::const_iterator i = s.begin(); i != s.end(); ++i) {
|
||||
|
||||
if (coverage (range.from, range.to, i->from, i->to) == OverlapNone) {
|
||||
continue;
|
||||
/* Here's where we'll put the new current result after subtracting *i from it */
|
||||
RangeList<T> new_result;
|
||||
|
||||
typename RangeList<T>::List r = result.get ();
|
||||
|
||||
/* Work on all parts of the current result using this range *i */
|
||||
for (typename RangeList<T>::List::const_iterator j = r.begin(); j != r.end(); ++j) {
|
||||
|
||||
switch (coverage (j->from, j->to, i->from, i->to)) {
|
||||
case OverlapNone:
|
||||
/* The thing we're subtracting does not overlap this bit of the result,
|
||||
so pass it through.
|
||||
*/
|
||||
new_result.add (*j);
|
||||
break;
|
||||
case OverlapInternal:
|
||||
/* Internal overlap of the thing we're subtracting from this bit of the result,
|
||||
so we might end up with two bits left over.
|
||||
*/
|
||||
if (j->from < (i->from - 1)) {
|
||||
new_result.add (Range<T> (j->from, i->from - 1));
|
||||
}
|
||||
if (j->to != i->to) {
|
||||
new_result.add (Range<T> (i->to, j->to));
|
||||
}
|
||||
break;
|
||||
case OverlapStart:
|
||||
/* The bit we're subtracting overlaps the start of the bit of the result */
|
||||
new_result.add (Range<T> (i->to, j->to - 1));
|
||||
break;
|
||||
case OverlapEnd:
|
||||
/* The bit we're subtracting overlaps the end of the bit of the result */
|
||||
new_result.add (Range<T> (j->from, i->from - 1));
|
||||
break;
|
||||
case OverlapExternal:
|
||||
/* total overlap of the bit we're subtracting with the result bit, so the
|
||||
result bit is completely removed; do nothing */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Range<T> clamped (std::max (range.from, i->from), std::min (range.to, i->to));
|
||||
|
||||
if (clamped.from != x) {
|
||||
result.add (Range<T> (x, clamped.from - 1));
|
||||
}
|
||||
|
||||
x = clamped.to;
|
||||
}
|
||||
|
||||
if (s.back().to < range.to) {
|
||||
result.add (Range<T> (x, range.to));
|
||||
new_result.coalesce ();
|
||||
result = new_result;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include "RangeTest.hpp"
|
||||
#include "evoral/Range.hpp"
|
||||
#include <stdlib.h>
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION (RangeTest);
|
||||
|
||||
|
|
@ -24,6 +25,7 @@ RangeTest::coalesceTest ()
|
|||
CPPUNIT_ASSERT_EQUAL (8, i->to);
|
||||
}
|
||||
|
||||
/* Basic subtraction of a few smaller ranges from a larger one */
|
||||
void
|
||||
RangeTest::subtractTest1 ()
|
||||
{
|
||||
|
|
@ -51,6 +53,7 @@ RangeTest::subtractTest1 ()
|
|||
CPPUNIT_ASSERT_EQUAL (10, i->to);
|
||||
}
|
||||
|
||||
/* Test subtraction of a range B from a range A, where A and B do not overlap */
|
||||
void
|
||||
RangeTest::subtractTest2 ()
|
||||
{
|
||||
|
|
@ -69,6 +72,7 @@ RangeTest::subtractTest2 ()
|
|||
CPPUNIT_ASSERT_EQUAL (10, i->to);
|
||||
}
|
||||
|
||||
/* Test subtraction of B from A, where B entirely overlaps A */
|
||||
void
|
||||
RangeTest::subtractTest3 ()
|
||||
{
|
||||
|
|
@ -82,3 +86,62 @@ RangeTest::subtractTest3 ()
|
|||
RangeList<int>::List s = sheila.get ();
|
||||
CPPUNIT_ASSERT_EQUAL (size_t (0), s.size ());
|
||||
}
|
||||
|
||||
/* A bit like subtractTest1, except some of the ranges
|
||||
we are subtracting overlap.
|
||||
*/
|
||||
void
|
||||
RangeTest::subtractTest4 ()
|
||||
{
|
||||
Range<int> fred (0, 10);
|
||||
|
||||
RangeList<int> jim;
|
||||
jim.add (Range<int> (2, 4));
|
||||
jim.add (Range<int> (7, 8));
|
||||
jim.add (Range<int> (8, 9));
|
||||
|
||||
RangeList<int> sheila = subtract (fred, jim);
|
||||
|
||||
RangeList<int>::List s = sheila.get ();
|
||||
CPPUNIT_ASSERT_EQUAL (size_t (3), s.size ());
|
||||
|
||||
RangeList<int>::List::iterator i = s.begin ();
|
||||
CPPUNIT_ASSERT_EQUAL (0, i->from);
|
||||
CPPUNIT_ASSERT_EQUAL (1, i->to);
|
||||
|
||||
++i;
|
||||
CPPUNIT_ASSERT_EQUAL (4, i->from);
|
||||
CPPUNIT_ASSERT_EQUAL (6, i->to);
|
||||
|
||||
++i;
|
||||
CPPUNIT_ASSERT_EQUAL (9, i->from);
|
||||
CPPUNIT_ASSERT_EQUAL (10, i->to);
|
||||
}
|
||||
|
||||
/* A bit like subtractTest1, except some of the ranges
|
||||
we are subtracting overlap the start / end of the
|
||||
initial range.
|
||||
*/
|
||||
void
|
||||
RangeTest::subtractTest5 ()
|
||||
{
|
||||
Range<int> fred (1, 12);
|
||||
|
||||
RangeList<int> jim;
|
||||
jim.add (Range<int> (0, 4));
|
||||
jim.add (Range<int> (6, 7));
|
||||
jim.add (Range<int> (9, 42));
|
||||
|
||||
RangeList<int> sheila = subtract (fred, jim);
|
||||
|
||||
RangeList<int>::List s = sheila.get ();
|
||||
CPPUNIT_ASSERT_EQUAL (size_t (2), s.size ());
|
||||
|
||||
RangeList<int>::List::iterator i = s.begin ();
|
||||
CPPUNIT_ASSERT_EQUAL (4, i->from);
|
||||
CPPUNIT_ASSERT_EQUAL (5, i->to);
|
||||
|
||||
++i;
|
||||
CPPUNIT_ASSERT_EQUAL (7, i->from);
|
||||
CPPUNIT_ASSERT_EQUAL (8, i->to);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,10 @@ class RangeTest : public CppUnit::TestFixture
|
|||
CPPUNIT_TEST_SUITE (RangeTest);
|
||||
CPPUNIT_TEST (coalesceTest);
|
||||
CPPUNIT_TEST (subtractTest1);
|
||||
CPPUNIT_TEST (subtractTest2);
|
||||
CPPUNIT_TEST (subtractTest3);
|
||||
CPPUNIT_TEST (subtractTest4);
|
||||
CPPUNIT_TEST (subtractTest5);
|
||||
CPPUNIT_TEST_SUITE_END ();
|
||||
|
||||
public:
|
||||
|
|
@ -14,6 +17,8 @@ public:
|
|||
void subtractTest1 ();
|
||||
void subtractTest2 ();
|
||||
void subtractTest3 ();
|
||||
void subtractTest4 ();
|
||||
void subtractTest5 ();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,8 @@ class Keyboard : public sigc::trackable, PBD::Stateful
|
|||
static uint32_t Level4Modifier;
|
||||
static uint32_t CopyModifier;
|
||||
static uint32_t RangeSelectModifier;
|
||||
static uint32_t GainFineScaleModifier;
|
||||
static uint32_t GainExtraFineScaleModifier;
|
||||
|
||||
static const char* primary_modifier_name ();
|
||||
static const char* secondary_modifier_name ();
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ namespace Gtkmm2ext {
|
|||
class PixFader : public Gtk::DrawingArea
|
||||
{
|
||||
public:
|
||||
PixFader (Glib::RefPtr<Gdk::Pixbuf> belt_image, Gtk::Adjustment& adjustment, int orientation, int);
|
||||
PixFader (Glib::RefPtr<Gdk::Pixbuf>, Glib::RefPtr<Gdk::Pixbuf>, Gtk::Adjustment& adjustment, int orientation, int);
|
||||
virtual ~PixFader ();
|
||||
|
||||
void set_fader_length (int);
|
||||
|
|
@ -58,10 +58,17 @@ class PixFader : public Gtk::DrawingArea
|
|||
HORIZ=2,
|
||||
};
|
||||
|
||||
private:
|
||||
Cairo::RefPtr<Cairo::Context> belt_context;
|
||||
Cairo::RefPtr<Cairo::ImageSurface> belt_surface;
|
||||
Glib::RefPtr<Gdk::Pixbuf> pixbuf;
|
||||
private:
|
||||
|
||||
enum State {
|
||||
NORMAL,
|
||||
DESENSITISED,
|
||||
STATES
|
||||
};
|
||||
|
||||
Cairo::RefPtr<Cairo::Context> belt_context[STATES];
|
||||
Cairo::RefPtr<Cairo::ImageSurface> belt_surface[STATES];
|
||||
Glib::RefPtr<Gdk::Pixbuf> pixbuf[STATES];
|
||||
int span, girth;
|
||||
int _orien;
|
||||
float left_r;
|
||||
|
|
@ -85,9 +92,6 @@ class PixFader : public Gtk::DrawingArea
|
|||
int display_span ();
|
||||
void set_adjustment_from_event (GdkEventButton *);
|
||||
void update_unity_position ();
|
||||
|
||||
static int fine_scale_modifier;
|
||||
static int extra_fine_scale_modifier;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ namespace Gtkmm2ext {
|
|||
class SliderController : public Gtkmm2ext::PixFader
|
||||
{
|
||||
public:
|
||||
SliderController (Glib::RefPtr<Gdk::Pixbuf> image, Gtk::Adjustment* adj, int orientation, int);
|
||||
SliderController (Glib::RefPtr<Gdk::Pixbuf>, Glib::RefPtr<Gdk::Pixbuf>, Gtk::Adjustment* adj, int orientation, int);
|
||||
|
||||
virtual ~SliderController () {}
|
||||
|
||||
|
|
@ -66,6 +66,7 @@ class VSliderController : public SliderController
|
|||
{
|
||||
public:
|
||||
VSliderController (Glib::RefPtr<Gdk::Pixbuf> image,
|
||||
Glib::RefPtr<Gdk::Pixbuf> image_desensitised,
|
||||
Gtk::Adjustment *adj, int,
|
||||
bool with_numeric = true);
|
||||
};
|
||||
|
|
@ -74,6 +75,7 @@ class HSliderController : public SliderController
|
|||
{
|
||||
public:
|
||||
HSliderController (Glib::RefPtr<Gdk::Pixbuf> image,
|
||||
Glib::RefPtr<Gdk::Pixbuf> image_desensitised,
|
||||
Gtk::Adjustment *adj, int,
|
||||
bool with_numeric = true);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -58,9 +58,9 @@ guint Keyboard::snap_mod = GDK_MOD3_MASK;
|
|||
#ifdef GTKOSX
|
||||
|
||||
uint Keyboard::PrimaryModifier = GDK_MOD2_MASK; // Command
|
||||
guint Keyboard::SecondaryModifier = GDK_CONTROL_MASK; // Alt/Option
|
||||
guint Keyboard::SecondaryModifier = GDK_CONTROL_MASK; // Control
|
||||
guint Keyboard::TertiaryModifier = GDK_SHIFT_MASK; // Shift
|
||||
guint Keyboard::Level4Modifier = GDK_MOD1_MASK; // Control
|
||||
guint Keyboard::Level4Modifier = GDK_MOD1_MASK; // Alt/Option
|
||||
guint Keyboard::CopyModifier = GDK_CONTROL_MASK; // Control
|
||||
guint Keyboard::RangeSelectModifier = GDK_SHIFT_MASK;
|
||||
guint Keyboard::button2_modifiers = Keyboard::SecondaryModifier|Keyboard::Level4Modifier;
|
||||
|
|
@ -91,6 +91,9 @@ const char* Keyboard::rangeselect_modifier_name() { return S_("Key|Shift"); }
|
|||
|
||||
#endif
|
||||
|
||||
guint Keyboard::GainFineScaleModifier = Keyboard::PrimaryModifier;
|
||||
guint Keyboard::GainExtraFineScaleModifier = Keyboard::SecondaryModifier;
|
||||
|
||||
Keyboard* Keyboard::_the_keyboard = 0;
|
||||
Gtk::Window* Keyboard::current_window = 0;
|
||||
bool Keyboard::_some_magic_widget_has_focus = false;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue