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:
Paul Davis 2012-06-02 16:21:08 +00:00
parent 4f9eb9862c
commit 8e1db53556
131 changed files with 2056 additions and 996 deletions

View file

@ -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

View file

@ -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;

View file

@ -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"

View file

@ -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"

View file

@ -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>

View file

@ -38,6 +38,7 @@
#include "actions.h"
#include "gui_thread.h"
#include "public_editor.h"
#include "main_clock.h"
#include "i18n.h"

View file

@ -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;
}

View file

@ -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)

View file

@ -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;

View file

@ -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) {

View file

@ -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 ();

View file

@ -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);
}
}

View file

@ -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 ();

View file

@ -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 ());
}

View file

@ -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

View file

@ -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 */

View file

@ -213,6 +213,9 @@ CanvasPatchChange::on_event (GdkEvent* ev)
_region.patch_left (this);
break;
case GDK_BUTTON_RELEASE:
return true;
default:
break;
}

View file

@ -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;

View file

@ -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;

View file

@ -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 ();
}
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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) {

View file

@ -47,6 +47,7 @@
#include "utils.h"
#include "editor_regions.h"
#include "editor_drag.h"
#include "main_clock.h"
#include "i18n.h"

View file

@ -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 */

View file

@ -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)
{

View file

@ -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__ */

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 929 B

View file

@ -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
View 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
View 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;
};

View file

@ -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;
}

View file

@ -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);

View file

@ -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 ();
}
}

View file

@ -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); }

View file

@ -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 ();
}

View file

@ -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 ();

View file

@ -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);
}
{

View file

@ -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));

View file

@ -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;

View file

@ -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 ();
}

View file

@ -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;
};

View file

@ -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));
}

View file

@ -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)

View file

@ -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);

View file

@ -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;

View file

@ -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",

View file

@ -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

View file

@ -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();

View file

@ -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)
{

View file

@ -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 &);

View file

@ -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"

View file

@ -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)
{

View file

@ -34,7 +34,7 @@ class Splash : public Gtk::Window
{
public:
Splash ();
~Splash () {}
~Splash ();
static Splash* instance() { return the_splash; }

View file

@ -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) {

View file

@ -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);
}
}

View file

@ -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 */

View file

@ -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"

View file

@ -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
}

View file

@ -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

View file

@ -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',

View file

@ -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;

View file

@ -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 */

View file

@ -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;

View file

@ -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;

View file

@ -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 {

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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__

View file

@ -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);

View file

@ -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));
}

View file

@ -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;
}

View file

@ -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>

View file

@ -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

View file

@ -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;
}

View file

@ -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:

View file

@ -20,7 +20,7 @@
#include "ardour/mtdm.h"
MTDM::MTDM (void)
MTDM::MTDM ()
: _cnt (0)
, _inv (0)
{

View file

@ -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--;
}
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View 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()));
}
}

View 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 ();
};

View file

@ -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 */

View file

@ -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

View file

@ -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); }
}

View file

@ -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()

View file

@ -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) {

View file

@ -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;

View file

@ -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);
}

View file

@ -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 ();
};

View file

@ -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 ();

View file

@ -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;
};

View file

@ -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);
};

View file

@ -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