mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-23 15:16:25 +01:00
fix dragging that involves locked regions; auto-rebinding patch for people to experiment with (probably needs a little work)
git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@3164 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
aa06f1f9f8
commit
fec2a96cec
26 changed files with 397 additions and 91 deletions
|
|
@ -364,6 +364,8 @@
|
||||||
<menuitem action='RemoteUserDefined'/>
|
<menuitem action='RemoteUserDefined'/>
|
||||||
<menuitem action='RemoteMixerDefined'/>
|
<menuitem action='RemoteMixerDefined'/>
|
||||||
<menuitem action='RemoteEditorDefined'/>
|
<menuitem action='RemoteEditorDefined'/>
|
||||||
|
<separator/>
|
||||||
|
<menuitem action='AutoRebinding'/>
|
||||||
</menu>
|
</menu>
|
||||||
<menu action='Monitoring'>
|
<menu action='Monitoring'>
|
||||||
<menuitem action='UseHardwareMonitoring'/>
|
<menuitem action='UseHardwareMonitoring'/>
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@
|
||||||
#include "engine_dialog.h"
|
#include "engine_dialog.h"
|
||||||
#include "editor.h"
|
#include "editor.h"
|
||||||
#include "actions.h"
|
#include "actions.h"
|
||||||
|
#include "mixer_ui.h"
|
||||||
|
|
||||||
#ifdef GTKOSX
|
#ifdef GTKOSX
|
||||||
#include <gtkmm2ext/sync-menu.h>
|
#include <gtkmm2ext/sync-menu.h>
|
||||||
|
|
@ -573,6 +574,10 @@ ARDOUR_UI::install_actions ()
|
||||||
act = ActionManager::register_radio_action (option_actions, remote_group, X_("RemoteEditorDefined"), _("Remote ID follows order of Editor"), hide_return (bind (mem_fun (*this, &ARDOUR_UI::set_remote_model), EditorOrdered)));
|
act = ActionManager::register_radio_action (option_actions, remote_group, X_("RemoteEditorDefined"), _("Remote ID follows order of Editor"), hide_return (bind (mem_fun (*this, &ARDOUR_UI::set_remote_model), EditorOrdered)));
|
||||||
ActionManager::session_sensitive_actions.push_back (act);
|
ActionManager::session_sensitive_actions.push_back (act);
|
||||||
|
|
||||||
|
act = ActionManager::register_toggle_action (option_actions, X_("AutoRebinding"), _("Auto Rebind Controls"), mem_fun (*(this->mixer), &Mixer_UI::toggle_auto_rebinding));
|
||||||
|
ActionManager::session_sensitive_actions.push_back (act);
|
||||||
|
|
||||||
|
|
||||||
ActionManager::add_action_group (shuttle_actions);
|
ActionManager::add_action_group (shuttle_actions);
|
||||||
ActionManager::add_action_group (option_actions);
|
ActionManager::add_action_group (option_actions);
|
||||||
ActionManager::add_action_group (jack_actions);
|
ActionManager::add_action_group (jack_actions);
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,28 @@ AudioRegionView::AudioRegionView (const AudioRegionView& other)
|
||||||
init (c, true);
|
init (c, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AudioRegionView::AudioRegionView (const AudioRegionView& other, boost::shared_ptr<AudioRegion> other_region)
|
||||||
|
: RegionView (other, boost::shared_ptr<Region> (other_region))
|
||||||
|
, zero_line(0)
|
||||||
|
, fade_in_shape(0)
|
||||||
|
, fade_out_shape(0)
|
||||||
|
, fade_in_handle(0)
|
||||||
|
, fade_out_handle(0)
|
||||||
|
, gain_line(0)
|
||||||
|
, _amplitude_above_axis(1.0)
|
||||||
|
, _flags(0)
|
||||||
|
, fade_color(0)
|
||||||
|
|
||||||
|
{
|
||||||
|
Gdk::Color c;
|
||||||
|
int r,g,b,a;
|
||||||
|
|
||||||
|
UINT_TO_RGBA (other.fill_color, &r, &g, &b, &a);
|
||||||
|
c.set_rgb_p (r/255.0, g/255.0, b/255.0);
|
||||||
|
|
||||||
|
init (c, true);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AudioRegionView::init (Gdk::Color& basic_color, bool wfd)
|
AudioRegionView::init (Gdk::Color& basic_color, bool wfd)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ class AudioRegionView : public RegionView
|
||||||
Gdk::Color& basic_color);
|
Gdk::Color& basic_color);
|
||||||
|
|
||||||
AudioRegionView (const AudioRegionView& other);
|
AudioRegionView (const AudioRegionView& other);
|
||||||
|
AudioRegionView (const AudioRegionView& other, boost::shared_ptr<ARDOUR::AudioRegion>);
|
||||||
|
|
||||||
~AudioRegionView ();
|
~AudioRegionView ();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,8 @@ struct DragInfo {
|
||||||
double last_pointer_y;
|
double last_pointer_y;
|
||||||
void (Editor::*motion_callback)(ArdourCanvas::Item*, GdkEvent*);
|
void (Editor::*motion_callback)(ArdourCanvas::Item*, GdkEvent*);
|
||||||
void (Editor::*finished_callback)(ArdourCanvas::Item*, GdkEvent*);
|
void (Editor::*finished_callback)(ArdourCanvas::Item*, GdkEvent*);
|
||||||
TimeAxisView* last_trackview;
|
TimeAxisView* source_trackview;
|
||||||
|
TimeAxisView* dest_trackview;
|
||||||
bool x_constrained;
|
bool x_constrained;
|
||||||
bool y_constrained;
|
bool y_constrained;
|
||||||
bool copy;
|
bool copy;
|
||||||
|
|
|
||||||
|
|
@ -430,7 +430,8 @@ Editor::start_imageframe_grab(ArdourCanvas::Item* item, GdkEvent* event)
|
||||||
drag_info.finished_callback = &Editor::timeaxis_item_drag_finished_callback;
|
drag_info.finished_callback = &Editor::timeaxis_item_drag_finished_callback;
|
||||||
drag_info.last_frame_position = ifv->get_position() ;
|
drag_info.last_frame_position = ifv->get_position() ;
|
||||||
|
|
||||||
drag_info.last_trackview = &ifv->get_time_axis_view() ;
|
drag_info.source_trackview = &ifv->get_time_axis_view() ;
|
||||||
|
drag_info.dest_trackview = drag_info.source_trackview;
|
||||||
|
|
||||||
/* this is subtle. raising the regionview itself won't help,
|
/* this is subtle. raising the regionview itself won't help,
|
||||||
because raise_to_top() just puts the item on the top of
|
because raise_to_top() just puts the item on the top of
|
||||||
|
|
@ -442,7 +443,7 @@ Editor::start_imageframe_grab(ArdourCanvas::Item* item, GdkEvent* event)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
drag_info.item->raise_to_top();
|
drag_info.item->raise_to_top();
|
||||||
drag_info.last_trackview->canvas_display->raise_to_top();
|
drag_info.source_trackview->canvas_display->raise_to_top();
|
||||||
//time_line_group->raise_to_top();
|
//time_line_group->raise_to_top();
|
||||||
cursor_group->raise_to_top ();
|
cursor_group->raise_to_top ();
|
||||||
|
|
||||||
|
|
@ -463,7 +464,8 @@ Editor::start_markerview_grab(ArdourCanvas::Item* item, GdkEvent* event)
|
||||||
drag_info.finished_callback = &Editor::timeaxis_item_drag_finished_callback;
|
drag_info.finished_callback = &Editor::timeaxis_item_drag_finished_callback;
|
||||||
drag_info.last_frame_position = mv->get_position() ;
|
drag_info.last_frame_position = mv->get_position() ;
|
||||||
|
|
||||||
drag_info.last_trackview = &mv->get_time_axis_view() ;
|
drag_info.source_trackview = &mv->get_time_axis_view() ;
|
||||||
|
drag_info.dest_trackview = drag_info.source_trackview;
|
||||||
|
|
||||||
/* this is subtle. raising the regionview itself won't help,
|
/* this is subtle. raising the regionview itself won't help,
|
||||||
because raise_to_top() just puts the item on the top of
|
because raise_to_top() just puts the item on the top of
|
||||||
|
|
@ -475,7 +477,7 @@ Editor::start_markerview_grab(ArdourCanvas::Item* item, GdkEvent* event)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
drag_info.item->raise_to_top();
|
drag_info.item->raise_to_top();
|
||||||
drag_info.last_trackview->canvas_display->raise_to_top();
|
drag_info.source_trackview->canvas_display->raise_to_top();
|
||||||
//time_line_group->raise_to_top();
|
//time_line_group->raise_to_top();
|
||||||
cursor_group->raise_to_top ();
|
cursor_group->raise_to_top ();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1846,7 +1846,8 @@ Editor::end_grab (ArdourCanvas::Item* item, GdkEvent* event)
|
||||||
drag_info.copy = false;
|
drag_info.copy = false;
|
||||||
drag_info.motion_callback = 0;
|
drag_info.motion_callback = 0;
|
||||||
drag_info.finished_callback = 0;
|
drag_info.finished_callback = 0;
|
||||||
drag_info.last_trackview = 0;
|
drag_info.dest_trackview = 0;
|
||||||
|
drag_info.source_trackview = 0;
|
||||||
drag_info.last_frame_position = 0;
|
drag_info.last_frame_position = 0;
|
||||||
drag_info.grab_frame = 0;
|
drag_info.grab_frame = 0;
|
||||||
drag_info.last_pointer_frame = 0;
|
drag_info.last_pointer_frame = 0;
|
||||||
|
|
@ -2944,7 +2945,8 @@ Editor::start_region_grab (ArdourCanvas::Item* item, GdkEvent* event)
|
||||||
|
|
||||||
drag_info.last_frame_position = (nframes_t) (clicked_regionview->region()->position() / speed);
|
drag_info.last_frame_position = (nframes_t) (clicked_regionview->region()->position() / speed);
|
||||||
drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
|
drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
|
||||||
drag_info.last_trackview = &clicked_regionview->get_time_axis_view();
|
drag_info.source_trackview = &clicked_regionview->get_time_axis_view();
|
||||||
|
drag_info.dest_trackview = drag_info.source_trackview;
|
||||||
// we want a move threshold
|
// we want a move threshold
|
||||||
drag_info.want_move_threshold = true;
|
drag_info.want_move_threshold = true;
|
||||||
|
|
||||||
|
|
@ -2974,7 +2976,8 @@ Editor::start_region_copy_grab (ArdourCanvas::Item* item, GdkEvent* event)
|
||||||
speed = atv->get_diskstream()->speed();
|
speed = atv->get_diskstream()->speed();
|
||||||
}
|
}
|
||||||
|
|
||||||
drag_info.last_trackview = &clicked_regionview->get_time_axis_view();
|
drag_info.source_trackview = &clicked_regionview->get_time_axis_view();
|
||||||
|
drag_info.dest_trackview = drag_info.source_trackview;
|
||||||
drag_info.last_frame_position = (nframes_t) (clicked_regionview->region()->position() / speed);
|
drag_info.last_frame_position = (nframes_t) (clicked_regionview->region()->position() / speed);
|
||||||
drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
|
drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
|
||||||
// we want a move threshold
|
// we want a move threshold
|
||||||
|
|
@ -3009,7 +3012,8 @@ Editor::start_region_brush_grab (ArdourCanvas::Item* item, GdkEvent* event)
|
||||||
|
|
||||||
drag_info.last_frame_position = (nframes_t) (clicked_regionview->region()->position() / speed);
|
drag_info.last_frame_position = (nframes_t) (clicked_regionview->region()->position() / speed);
|
||||||
drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
|
drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
|
||||||
drag_info.last_trackview = &clicked_regionview->get_time_axis_view();
|
drag_info.source_trackview = &clicked_regionview->get_time_axis_view();
|
||||||
|
drag_info.dest_trackview = drag_info.source_trackview;
|
||||||
// we want a move threshold
|
// we want a move threshold
|
||||||
drag_info.want_move_threshold = true;
|
drag_info.want_move_threshold = true;
|
||||||
drag_info.brushing = true;
|
drag_info.brushing = true;
|
||||||
|
|
@ -3024,7 +3028,7 @@ Editor::possibly_copy_regions_during_grab (GdkEvent* event)
|
||||||
|
|
||||||
drag_info.want_move_threshold = false; // don't copy again
|
drag_info.want_move_threshold = false; // don't copy again
|
||||||
|
|
||||||
/* duplicate the region(s) */
|
/* duplicate the regionview(s) and region(s) */
|
||||||
|
|
||||||
vector<RegionView*> new_regionviews;
|
vector<RegionView*> new_regionviews;
|
||||||
|
|
||||||
|
|
@ -3032,7 +3036,7 @@ Editor::possibly_copy_regions_during_grab (GdkEvent* event)
|
||||||
RegionView* rv;
|
RegionView* rv;
|
||||||
RegionView* nrv;
|
RegionView* nrv;
|
||||||
AudioRegionView* arv;
|
AudioRegionView* arv;
|
||||||
|
|
||||||
rv = (*i);
|
rv = (*i);
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -3040,8 +3044,12 @@ Editor::possibly_copy_regions_during_grab (GdkEvent* event)
|
||||||
/* XXX handle MIDI here */
|
/* XXX handle MIDI here */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const boost::shared_ptr<const Region> original = arv->region();
|
||||||
|
boost::shared_ptr<Region> region_copy = RegionFactory::create (original);
|
||||||
|
boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (region_copy);
|
||||||
|
|
||||||
nrv = new AudioRegionView (*arv);
|
nrv = new AudioRegionView (*arv, ar);
|
||||||
nrv->get_canvas_group()->show ();
|
nrv->get_canvas_group()->show ();
|
||||||
|
|
||||||
new_regionviews.push_back (nrv);
|
new_regionviews.push_back (nrv);
|
||||||
|
|
@ -3178,7 +3186,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
original_pointer_order = drag_info.last_trackview->order;
|
original_pointer_order = drag_info.dest_trackview->order;
|
||||||
|
|
||||||
/************************************************************
|
/************************************************************
|
||||||
Y-Delta Computation
|
Y-Delta Computation
|
||||||
|
|
@ -3190,7 +3198,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
||||||
goto y_axis_done;
|
goto y_axis_done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((pointer_y_span = (drag_info.last_trackview->order - tv->order)) != 0) {
|
if ((pointer_y_span = (drag_info.dest_trackview->order - tv->order)) != 0) {
|
||||||
|
|
||||||
int32_t children = 0, numtracks = 0;
|
int32_t children = 0, numtracks = 0;
|
||||||
// XXX hard coding track limit, oh my, so very very bad
|
// XXX hard coding track limit, oh my, so very very bad
|
||||||
|
|
@ -3234,16 +3242,16 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
||||||
/* find the actual span according to the canvas */
|
/* find the actual span according to the canvas */
|
||||||
|
|
||||||
canvas_pointer_y_span = pointer_y_span;
|
canvas_pointer_y_span = pointer_y_span;
|
||||||
if (drag_info.last_trackview->order >= tv->order) {
|
if (drag_info.dest_trackview->order >= tv->order) {
|
||||||
int32_t y;
|
int32_t y;
|
||||||
for (y = tv->order; y < drag_info.last_trackview->order; y++) {
|
for (y = tv->order; y < drag_info.dest_trackview->order; y++) {
|
||||||
if (height_list[y] == 0 ) {
|
if (height_list[y] == 0 ) {
|
||||||
canvas_pointer_y_span--;
|
canvas_pointer_y_span--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int32_t y;
|
int32_t y;
|
||||||
for (y = drag_info.last_trackview->order;y <= tv->order; y++) {
|
for (y = drag_info.dest_trackview->order;y <= tv->order; y++) {
|
||||||
if ( height_list[y] == 0 ) {
|
if ( height_list[y] == 0 ) {
|
||||||
canvas_pointer_y_span++;
|
canvas_pointer_y_span++;
|
||||||
}
|
}
|
||||||
|
|
@ -3255,6 +3263,10 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
||||||
double ix1, ix2, iy1, iy2;
|
double ix1, ix2, iy1, iy2;
|
||||||
int32_t n = 0;
|
int32_t n = 0;
|
||||||
|
|
||||||
|
if (rv2->region()->locked()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
rv2->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
|
rv2->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
|
||||||
rv2->get_canvas_group()->i2w (ix1, iy1);
|
rv2->get_canvas_group()->i2w (ix1, iy1);
|
||||||
TimeAxisView* tvp2 = trackview_by_y_position (iy1);
|
TimeAxisView* tvp2 = trackview_by_y_position (iy1);
|
||||||
|
|
@ -3326,13 +3338,13 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (drag_info.last_trackview == tv) {
|
} else if (drag_info.dest_trackview == tv) {
|
||||||
clamp_y_axis = true;
|
clamp_y_axis = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
y_axis_done:
|
y_axis_done:
|
||||||
if (!clamp_y_axis) {
|
if (!clamp_y_axis) {
|
||||||
drag_info.last_trackview = tv;
|
drag_info.dest_trackview = tv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************
|
/************************************************************
|
||||||
|
|
@ -3465,6 +3477,10 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
||||||
double ix1, ix2, iy1, iy2;
|
double ix1, ix2, iy1, iy2;
|
||||||
int32_t temp_pointer_y_span = pointer_y_span;
|
int32_t temp_pointer_y_span = pointer_y_span;
|
||||||
|
|
||||||
|
if (rv->region()->locked()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* get item BBox, which will be relative to parent. so we have
|
/* get item BBox, which will be relative to parent. so we have
|
||||||
to query on a child, then convert to world coordinates using
|
to query on a child, then convert to world coordinates using
|
||||||
the parent.
|
the parent.
|
||||||
|
|
@ -3502,6 +3518,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
||||||
y_delta -= (*j);
|
y_delta -= (*j);
|
||||||
temp_pointer_y_span--;
|
temp_pointer_y_span--;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (temp_pointer_y_span < 0) {
|
while (temp_pointer_y_span < 0) {
|
||||||
y_delta += (*j);
|
y_delta += (*j);
|
||||||
if (x != original_pointer_order) {
|
if (x != original_pointer_order) {
|
||||||
|
|
@ -3532,7 +3549,8 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
||||||
x++;
|
x++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* prevent the regionview from being moved to before
|
/* prevent the regionview from being moved to before
|
||||||
the zero position on the canvas.
|
the zero position on the canvas.
|
||||||
*/
|
*/
|
||||||
|
|
@ -3597,6 +3615,10 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
|
||||||
bool regionview_y_movement;
|
bool regionview_y_movement;
|
||||||
bool regionview_x_movement;
|
bool regionview_x_movement;
|
||||||
vector<RegionView*> copies;
|
vector<RegionView*> copies;
|
||||||
|
RouteTimeAxisView* tvp1;
|
||||||
|
boost::shared_ptr<Diskstream> ds;
|
||||||
|
boost::shared_ptr<Playlist> from_playlist;
|
||||||
|
bool axis_motion;
|
||||||
|
|
||||||
/* first_move is set to false if the regionview has been moved in the
|
/* first_move is set to false if the regionview has been moved in the
|
||||||
motion handler.
|
motion handler.
|
||||||
|
|
@ -3632,19 +3654,40 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* get the playlist where this drag started. we can't use rv->region()->playlist()
|
||||||
|
because we may have copied the region and it has not been attached to a playlist.
|
||||||
|
*/
|
||||||
|
|
||||||
|
assert ((tvp1 = dynamic_cast<RouteTimeAxisView*> (drag_info.source_trackview)));
|
||||||
|
assert ((ds = tvp1->get_diskstream()));
|
||||||
|
assert ((from_playlist = ds->playlist()));
|
||||||
|
|
||||||
/* adjust for track speed */
|
/* adjust for track speed */
|
||||||
speed = 1.0;
|
speed = 1.0;
|
||||||
|
|
||||||
atv = dynamic_cast<AudioTimeAxisView*> (drag_info.last_trackview);
|
atv = dynamic_cast<AudioTimeAxisView*> (drag_info.dest_trackview);
|
||||||
|
|
||||||
if (atv && atv->get_diskstream()) {
|
if (atv && atv->get_diskstream()) {
|
||||||
speed = atv->get_diskstream()->speed();
|
speed = atv->get_diskstream()->speed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check all regions for motion because some might have been locked */
|
||||||
|
|
||||||
regionview_x_movement = (drag_info.last_frame_position != (nframes_t) (rv->region()->position()/speed));
|
regionview_x_movement = false;
|
||||||
regionview_y_movement = (drag_info.last_trackview != &rv->get_time_axis_view());
|
regionview_y_movement = false;
|
||||||
|
|
||||||
|
for (list<RegionView*>::const_iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
|
||||||
|
if (drag_info.last_frame_position != (nframes_t) ((*i)->region()->position()/speed)) {
|
||||||
|
regionview_x_movement = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (drag_info.dest_trackview != &(*i)->get_time_axis_view()) {
|
||||||
|
regionview_y_movement = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//printf ("last_frame: %s position is %lu %g\n", rv->get_time_axis_view().name().c_str(), drag_info.last_frame_position, speed);
|
//printf ("last_frame: %s position is %lu %g\n", rv->get_time_axis_view().name().c_str(), drag_info.last_frame_position, speed);
|
||||||
//printf ("last_rackview: %s \n", drag_info.last_trackview->name().c_str());
|
//printf ("last_rackview: %s \n", drag_info.dest_trackview->name().c_str());
|
||||||
|
|
||||||
char* op_string;
|
char* op_string;
|
||||||
|
|
||||||
|
|
@ -3673,19 +3716,29 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
|
||||||
for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ) {
|
for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ) {
|
||||||
|
|
||||||
RegionView* rv = (*i);
|
RegionView* rv = (*i);
|
||||||
|
|
||||||
|
if (rv->region()->locked()) {
|
||||||
|
++i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
double ix1, ix2, iy1, iy2;
|
double ix1, ix2, iy1, iy2;
|
||||||
|
|
||||||
rv->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
|
rv->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
|
||||||
rv->get_canvas_group()->i2w (ix1, iy1);
|
rv->get_canvas_group()->i2w (ix1, iy1);
|
||||||
TimeAxisView* tvp2 = trackview_by_y_position (iy1);
|
TimeAxisView* tvp2 = trackview_by_y_position (iy1);
|
||||||
AudioTimeAxisView* atv2 = dynamic_cast<AudioTimeAxisView*>(tvp2);
|
AudioTimeAxisView* atv2 = dynamic_cast<AudioTimeAxisView*>(tvp2);
|
||||||
|
|
||||||
boost::shared_ptr<Playlist> from_playlist = rv->region()->playlist();
|
|
||||||
boost::shared_ptr<Playlist> to_playlist = atv2->playlist();
|
boost::shared_ptr<Playlist> to_playlist = atv2->playlist();
|
||||||
|
|
||||||
where = (nframes_t) (unit_to_frame (ix1) * speed);
|
where = (nframes_t) (unit_to_frame (ix1) * speed);
|
||||||
boost::shared_ptr<Region> new_region (RegionFactory::create (rv->region()));
|
boost::shared_ptr<Region> new_region;
|
||||||
|
|
||||||
|
if (drag_info.copy) {
|
||||||
|
/* we already made a copy */
|
||||||
|
new_region = rv->region();
|
||||||
|
} else {
|
||||||
|
new_region = RegionFactory::create (rv->region());
|
||||||
|
}
|
||||||
|
|
||||||
/* undo the previous hide_dependent_views so that xfades don't
|
/* undo the previous hide_dependent_views so that xfades don't
|
||||||
disappear on copying regions
|
disappear on copying regions
|
||||||
|
|
@ -3797,31 +3850,21 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
|
||||||
where = rv->region()->position();
|
where = rv->region()->position();
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<Playlist> to_playlist = rv->region()->playlist();
|
|
||||||
|
|
||||||
assert (to_playlist);
|
|
||||||
|
|
||||||
/* add the undo */
|
/* add the undo */
|
||||||
|
|
||||||
session->add_command (new MementoCommand<Playlist>(*to_playlist, &to_playlist->get_state(), 0));
|
session->add_command (new MementoCommand<Playlist>(*from_playlist, &from_playlist->get_state(), 0));
|
||||||
|
|
||||||
if (drag_info.copy) {
|
if (drag_info.copy) {
|
||||||
|
|
||||||
boost::shared_ptr<Region> newregion;
|
/* we already made a copy of the region */
|
||||||
boost::shared_ptr<Region> ar;
|
|
||||||
|
|
||||||
if ((ar = boost::dynamic_pointer_cast<AudioRegion>(rv->region())) != 0) {
|
boost::shared_ptr<Region> newregion = rv->region();
|
||||||
newregion = RegionFactory::create (ar);
|
|
||||||
} else {
|
|
||||||
/* XXX MIDI HERE drobilla */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* add it */
|
/* add it */
|
||||||
|
|
||||||
latest_regionviews.clear ();
|
latest_regionviews.clear ();
|
||||||
sigc::connection c = atv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
|
sigc::connection c = atv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
|
||||||
to_playlist->add_region (newregion, (nframes_t) (where * atv->get_diskstream()->speed()));
|
from_playlist->add_region (newregion, (nframes_t) (where * atv->get_diskstream()->speed()));
|
||||||
c.disconnect ();
|
c.disconnect ();
|
||||||
|
|
||||||
if (!latest_regionviews.empty()) {
|
if (!latest_regionviews.empty()) {
|
||||||
|
|
@ -3844,7 +3887,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
|
||||||
|
|
||||||
/* add the redo */
|
/* add the redo */
|
||||||
|
|
||||||
session->add_command (new MementoCommand<Playlist>(*to_playlist, 0, &to_playlist->get_state()));
|
session->add_command (new MementoCommand<Playlist>(*from_playlist, 0, &from_playlist->get_state()));
|
||||||
|
|
||||||
if (drag_info.copy) {
|
if (drag_info.copy) {
|
||||||
copies.push_back (rv);
|
copies.push_back (rv);
|
||||||
|
|
@ -4109,7 +4152,8 @@ Editor::start_selection_grab (ArdourCanvas::Item* item, GdkEvent* event)
|
||||||
|
|
||||||
start_grab (event);
|
start_grab (event);
|
||||||
|
|
||||||
drag_info.last_trackview = clicked_trackview;
|
drag_info.source_trackview = clicked_trackview;
|
||||||
|
drag_info.dest_trackview = drag_info.source_trackview;
|
||||||
drag_info.last_frame_position = latest_regionviews.front()->region()->position();
|
drag_info.last_frame_position = latest_regionviews.front()->region()->position();
|
||||||
drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
|
drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,7 @@ class GainMeter : public Gtk::VBox
|
||||||
|
|
||||||
void set_meter_strip_name (const char * name);
|
void set_meter_strip_name (const char * name);
|
||||||
void set_fader_name (const char * name);
|
void set_fader_name (const char * name);
|
||||||
|
PBD::Controllable& get_controllable() { return _io->gain_control(); }
|
||||||
|
|
||||||
void clear_meters ();
|
void clear_meters ();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -223,6 +223,8 @@ Mixer_UI::Mixer_UI ()
|
||||||
signal_configure_event().connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
|
signal_configure_event().connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
|
||||||
|
|
||||||
_selection.RoutesChanged.connect (mem_fun(*this, &Mixer_UI::follow_strip_selection));
|
_selection.RoutesChanged.connect (mem_fun(*this, &Mixer_UI::follow_strip_selection));
|
||||||
|
|
||||||
|
auto_rebinding = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Mixer_UI::~Mixer_UI ()
|
Mixer_UI::~Mixer_UI ()
|
||||||
|
|
@ -712,8 +714,97 @@ Mixer_UI::redisplay_track_list ()
|
||||||
Route::SyncOrderKeys (); // EMIT SIGNAL
|
Route::SyncOrderKeys (); // EMIT SIGNAL
|
||||||
ignore_sync = false;
|
ignore_sync = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rebind all of the midi controls automatically
|
||||||
|
|
||||||
|
if (auto_rebinding)
|
||||||
|
auto_rebind_midi_controls ();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Mixer_UI::set_auto_rebinding( bool val )
|
||||||
|
{
|
||||||
|
if( val == TRUE )
|
||||||
|
{
|
||||||
|
auto_rebinding = TRUE;
|
||||||
|
Session::AutoBindingOff();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto_rebinding = FALSE;
|
||||||
|
Session::AutoBindingOn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Mixer_UI::toggle_auto_rebinding()
|
||||||
|
{
|
||||||
|
if (auto_rebinding)
|
||||||
|
{
|
||||||
|
set_auto_rebinding( FALSE );
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
set_auto_rebinding( TRUE );
|
||||||
|
}
|
||||||
|
|
||||||
|
auto_rebind_midi_controls();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Mixer_UI::auto_rebind_midi_controls ()
|
||||||
|
{
|
||||||
|
TreeModel::Children rows = track_model->children();
|
||||||
|
TreeModel::Children::iterator i;
|
||||||
|
int pos;
|
||||||
|
|
||||||
|
// Create bindings for all visible strips and remove those that are not visible
|
||||||
|
pos = 1; // 0 is reserved for the master strip
|
||||||
|
for (i = rows.begin(); i != rows.end(); ++i) {
|
||||||
|
MixerStrip* strip = (*i)[track_columns.strip];
|
||||||
|
|
||||||
|
if ( (*i)[track_columns.visible] == true ) { // add bindings for
|
||||||
|
// make the actual binding
|
||||||
|
//cout<<"Auto Binding: Visible Strip Found: "<<strip->name()<<endl;
|
||||||
|
|
||||||
|
int controlValue = pos;
|
||||||
|
if( strip->route()->master() ) {
|
||||||
|
controlValue = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
PBD::Controllable::CreateBinding ( strip->solo_button->get_controllable(), controlValue, 0);
|
||||||
|
PBD::Controllable::CreateBinding ( strip->mute_button->get_controllable(), controlValue, 1);
|
||||||
|
|
||||||
|
if( strip->is_audio_track() ) {
|
||||||
|
PBD::Controllable::CreateBinding ( strip->rec_enable_button->get_controllable(), controlValue, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
PBD::Controllable::CreateBinding ( &(strip->gpm.get_controllable()), controlValue, 3);
|
||||||
|
PBD::Controllable::CreateBinding ( strip->panners.get_controllable(), controlValue, 4);
|
||||||
|
|
||||||
|
}
|
||||||
|
else { // Remove any existing binding
|
||||||
|
PBD::Controllable::DeleteBinding ( strip->solo_button->get_controllable() );
|
||||||
|
PBD::Controllable::DeleteBinding ( strip->mute_button->get_controllable() );
|
||||||
|
|
||||||
|
if( strip->is_audio_track() ) {
|
||||||
|
PBD::Controllable::DeleteBinding ( strip->rec_enable_button->get_controllable() );
|
||||||
|
}
|
||||||
|
|
||||||
|
PBD::Controllable::DeleteBinding ( &(strip->gpm.get_controllable()) );
|
||||||
|
PBD::Controllable::DeleteBinding ( strip->panners.get_controllable() ); // This only takes the first panner if there are multiples...
|
||||||
|
}
|
||||||
|
|
||||||
|
} // for
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct SignalOrderRouteSorter {
|
struct SignalOrderRouteSorter {
|
||||||
bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
|
bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
|
||||||
/* use of ">" forces the correct sort order */
|
/* use of ">" forces the correct sort order */
|
||||||
|
|
@ -1069,6 +1160,7 @@ Mixer_UI::mix_group_row_change (const Gtk::TreeModel::Path& path,const Gtk::Tree
|
||||||
if (name != group->name()) {
|
if (name != group->name()) {
|
||||||
group->set_name (name);
|
group->set_name (name);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,8 @@ class Mixer_UI : public Gtk::Window
|
||||||
void hide_strip (MixerStrip *);
|
void hide_strip (MixerStrip *);
|
||||||
|
|
||||||
void ensure_float (Gtk::Window&);
|
void ensure_float (Gtk::Window&);
|
||||||
|
void toggle_auto_rebinding ();
|
||||||
|
void set_auto_rebinding(bool);
|
||||||
|
|
||||||
RouteRedirectSelection& selection() { return _selection; }
|
RouteRedirectSelection& selection() { return _selection; }
|
||||||
|
|
||||||
|
|
@ -129,6 +131,9 @@ class Mixer_UI : public Gtk::Window
|
||||||
void unselect_all_audiobus_strips ();
|
void unselect_all_audiobus_strips ();
|
||||||
void select_all_audiobus_strips ();
|
void select_all_audiobus_strips ();
|
||||||
|
|
||||||
|
void auto_rebind_midi_controls ();
|
||||||
|
bool auto_rebinding;
|
||||||
|
|
||||||
void strip_select_op (bool audiotrack, bool select);
|
void strip_select_op (bool audiotrack, bool select);
|
||||||
void select_strip_op (MixerStrip*, bool select);
|
void select_strip_op (MixerStrip*, bool select);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -152,6 +152,12 @@ PannerUI::PannerUI (boost::shared_ptr<IO> io, Session& s)
|
||||||
pan_automation_state_changed ();
|
pan_automation_state_changed ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PBD::Controllable*
|
||||||
|
PannerUI::get_controllable()
|
||||||
|
{
|
||||||
|
return pan_bars[0]->get_controllable();
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
PannerUI::panning_link_button_press (GdkEventButton* ev)
|
PannerUI::panning_link_button_press (GdkEventButton* ev)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -68,9 +68,11 @@ class PannerUI : public Gtk::HBox
|
||||||
void effective_pan_display ();
|
void effective_pan_display ();
|
||||||
|
|
||||||
void set_meter_strip_name (string name);
|
void set_meter_strip_name (string name);
|
||||||
|
PBD::Controllable* get_controllable();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class MixerStrip;
|
friend class MixerStrip;
|
||||||
|
|
||||||
boost::shared_ptr<ARDOUR::IO> _io;
|
boost::shared_ptr<ARDOUR::IO> _io;
|
||||||
ARDOUR::Session& _session;
|
ARDOUR::Session& _session;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,23 @@ RegionView::RegionView (const RegionView& other)
|
||||||
_height = other._height;
|
_height = other._height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RegionView::RegionView (const RegionView& other, boost::shared_ptr<Region> other_region)
|
||||||
|
: TimeAxisViewItem (other)
|
||||||
|
{
|
||||||
|
/* this is a pseudo-copy constructor used when dragging regions
|
||||||
|
around on the canvas.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* derived concrete type will call init () */
|
||||||
|
|
||||||
|
_region = other_region;
|
||||||
|
editor = other.editor;
|
||||||
|
current_visible_sync_position = other.current_visible_sync_position;
|
||||||
|
valid = false;
|
||||||
|
_pixel_width = other._pixel_width;
|
||||||
|
_height = other._height;
|
||||||
|
}
|
||||||
|
|
||||||
RegionView::RegionView (ArdourCanvas::Group* parent,
|
RegionView::RegionView (ArdourCanvas::Group* parent,
|
||||||
TimeAxisView& tv,
|
TimeAxisView& tv,
|
||||||
boost::shared_ptr<ARDOUR::Region> r,
|
boost::shared_ptr<ARDOUR::Region> r,
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ class RegionView : public TimeAxisViewItem
|
||||||
Gdk::Color& basic_color);
|
Gdk::Color& basic_color);
|
||||||
|
|
||||||
RegionView (const RegionView& other);
|
RegionView (const RegionView& other);
|
||||||
|
RegionView (const RegionView& other, boost::shared_ptr<ARDOUR::Region> other_region);
|
||||||
|
|
||||||
~RegionView ();
|
~RegionView ();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,12 @@ class RegionFactory {
|
||||||
|
|
||||||
static sigc::signal<void,boost::shared_ptr<Region> > CheckNewRegion;
|
static sigc::signal<void,boost::shared_ptr<Region> > CheckNewRegion;
|
||||||
|
|
||||||
|
static boost::shared_ptr<Region> create (boost::shared_ptr<const Region>);
|
||||||
|
|
||||||
|
/* note: both of the first two should use const shared_ptr as well, but
|
||||||
|
gcc 4.1 doesn't seem to be able to disambiguate them if they do.
|
||||||
|
*/
|
||||||
|
|
||||||
static boost::shared_ptr<Region> create (boost::shared_ptr<Region>, nframes_t start,
|
static boost::shared_ptr<Region> create (boost::shared_ptr<Region>, nframes_t start,
|
||||||
nframes_t length, std::string name,
|
nframes_t length, std::string name,
|
||||||
layer_t = 0, Region::Flag flags = Region::DefaultFlags, bool announce = true);
|
layer_t = 0, Region::Flag flags = Region::DefaultFlags, bool announce = true);
|
||||||
|
|
@ -50,7 +56,6 @@ class RegionFactory {
|
||||||
layer_t = 0, Region::Flag flags = Region::DefaultFlags, bool announce = true);
|
layer_t = 0, Region::Flag flags = Region::DefaultFlags, bool announce = true);
|
||||||
static boost::shared_ptr<Region> create (boost::shared_ptr<Source>, nframes_t start, nframes_t length, const string& name, layer_t = 0, Region::Flag flags = Region::DefaultFlags, bool announce = true);
|
static boost::shared_ptr<Region> create (boost::shared_ptr<Source>, nframes_t start, nframes_t length, const string& name, layer_t = 0, Region::Flag flags = Region::DefaultFlags, bool announce = true);
|
||||||
static boost::shared_ptr<Region> create (const SourceList &, nframes_t start, nframes_t length, const string& name, layer_t = 0, Region::Flag flags = Region::DefaultFlags, bool announce = true);
|
static boost::shared_ptr<Region> create (const SourceList &, nframes_t start, nframes_t length, const string& name, layer_t = 0, Region::Flag flags = Region::DefaultFlags, bool announce = true);
|
||||||
static boost::shared_ptr<Region> create (boost::shared_ptr<Region>);
|
|
||||||
static boost::shared_ptr<Region> create (Session&, XMLNode&, bool);
|
static boost::shared_ptr<Region> create (Session&, XMLNode&, bool);
|
||||||
static boost::shared_ptr<Region> create (SourceList &, const XMLNode&);
|
static boost::shared_ptr<Region> create (SourceList &, const XMLNode&);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -249,6 +249,9 @@ class Session : public PBD::StatefulDestructible
|
||||||
bool deletion_in_progress() const { return _state_of_the_state & Deletion; }
|
bool deletion_in_progress() const { return _state_of_the_state & Deletion; }
|
||||||
sigc::signal<void> DirtyChanged;
|
sigc::signal<void> DirtyChanged;
|
||||||
|
|
||||||
|
static sigc::signal<void> AutoBindingOn;
|
||||||
|
static sigc::signal<void> AutoBindingOff;
|
||||||
|
|
||||||
std::string sound_dir (bool with_path = true) const;
|
std::string sound_dir (bool with_path = true) const;
|
||||||
std::string peak_dir () const;
|
std::string peak_dir () const;
|
||||||
std::string dead_sound_dir () const;
|
std::string dead_sound_dir () const;
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,8 @@ sigc::signal<void,boost::shared_ptr<Region> > RegionFactory::CheckNewRegion;
|
||||||
|
|
||||||
boost::shared_ptr<Region>
|
boost::shared_ptr<Region>
|
||||||
RegionFactory::create (boost::shared_ptr<Region> region, nframes_t start,
|
RegionFactory::create (boost::shared_ptr<Region> region, nframes_t start,
|
||||||
nframes_t length, std::string name,
|
nframes_t length, std::string name,
|
||||||
layer_t layer, Region::Flag flags, bool announce)
|
layer_t layer, Region::Flag flags, bool announce)
|
||||||
{
|
{
|
||||||
boost::shared_ptr<const AudioRegion> other;
|
boost::shared_ptr<const AudioRegion> other;
|
||||||
|
|
||||||
|
|
@ -57,11 +57,11 @@ RegionFactory::create (boost::shared_ptr<Region> region, nframes_t start,
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<Region>
|
boost::shared_ptr<Region>
|
||||||
RegionFactory::create (boost::shared_ptr<Region> region)
|
RegionFactory::create (boost::shared_ptr<const Region> region)
|
||||||
{
|
{
|
||||||
boost::shared_ptr<AudioRegion> other;
|
boost::shared_ptr<const AudioRegion> other;
|
||||||
|
|
||||||
if ((other = boost::dynamic_pointer_cast<AudioRegion>(region)) != 0) {
|
if ((other = boost::dynamic_pointer_cast<const AudioRegion>(region)) != 0) {
|
||||||
boost::shared_ptr<Region> ret (new AudioRegion (other));
|
boost::shared_ptr<Region> ret (new AudioRegion (other));
|
||||||
/* pure copy constructor - no CheckNewRegion emitted */
|
/* pure copy constructor - no CheckNewRegion emitted */
|
||||||
return ret;
|
return ret;
|
||||||
|
|
@ -75,8 +75,8 @@ RegionFactory::create (boost::shared_ptr<Region> region)
|
||||||
|
|
||||||
boost::shared_ptr<Region>
|
boost::shared_ptr<Region>
|
||||||
RegionFactory::create (boost::shared_ptr<AudioRegion> region, nframes_t start,
|
RegionFactory::create (boost::shared_ptr<AudioRegion> region, nframes_t start,
|
||||||
nframes_t length, std::string name,
|
nframes_t length, std::string name,
|
||||||
layer_t layer, Region::Flag flags, bool announce)
|
layer_t layer, Region::Flag flags, bool announce)
|
||||||
{
|
{
|
||||||
return create (boost::static_pointer_cast<Region> (region), start, length, name, layer, flags, announce);
|
return create (boost::static_pointer_cast<Region> (region), start, length, name, layer, flags, announce);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,10 @@ sigc::signal<void> Session::SMPTEOffsetChanged;
|
||||||
sigc::signal<void> Session::StartTimeChanged;
|
sigc::signal<void> Session::StartTimeChanged;
|
||||||
sigc::signal<void> Session::EndTimeChanged;
|
sigc::signal<void> Session::EndTimeChanged;
|
||||||
|
|
||||||
|
sigc::signal<void> Session::AutoBindingOn;
|
||||||
|
sigc::signal<void> Session::AutoBindingOff;
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
Session::find_session (string str, string& path, string& snapshot, bool& isnew)
|
Session::find_session (string str, string& path, string& snapshot, bool& isnew)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,7 @@ class BarController : public Gtk::Frame
|
||||||
/* export this to allow direct connection to button events */
|
/* export this to allow direct connection to button events */
|
||||||
|
|
||||||
Gtk::Widget& event_widget() { return darea; }
|
Gtk::Widget& event_widget() { return darea; }
|
||||||
|
PBD::Controllable* get_controllable() { return binding_proxy.get_controllable(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Gtk::Adjustment& adjustment;
|
Gtk::Adjustment& adjustment;
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,8 @@ class BindableToggleButton : public Gtkmm2ext::StatefulToggleButton
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PBD::Controllable* get_controllable() { return binding_proxy.get_controllable(); }
|
||||||
private:
|
private:
|
||||||
BindingProxy binding_proxy;
|
BindingProxy binding_proxy;
|
||||||
};
|
};
|
||||||
|
|
@ -71,6 +72,8 @@ class BindableButton : public Gtkmm2ext::StatefulButton
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PBD::Controllable* get_controllable() { return binding_proxy.get_controllable(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BindingProxy binding_proxy;
|
BindingProxy binding_proxy;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ class BindingProxy : public sigc::trackable
|
||||||
|
|
||||||
bool button_press_handler (GdkEventButton *);
|
bool button_press_handler (GdkEventButton *);
|
||||||
|
|
||||||
|
PBD::Controllable* get_controllable() { return &controllable; }
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
Gtkmm2ext::PopUp* prompter;
|
Gtkmm2ext::PopUp* prompter;
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,8 @@ using namespace PBD;
|
||||||
sigc::signal<void,Controllable*> Controllable::Destroyed;
|
sigc::signal<void,Controllable*> Controllable::Destroyed;
|
||||||
sigc::signal<bool,Controllable*> Controllable::StartLearning;
|
sigc::signal<bool,Controllable*> Controllable::StartLearning;
|
||||||
sigc::signal<void,Controllable*> Controllable::StopLearning;
|
sigc::signal<void,Controllable*> Controllable::StopLearning;
|
||||||
|
sigc::signal<void,Controllable*,int,int> Controllable::CreateBinding;
|
||||||
|
sigc::signal<void,Controllable*> Controllable::DeleteBinding;
|
||||||
|
|
||||||
Glib::Mutex* Controllable::registry_lock = 0;
|
Glib::Mutex* Controllable::registry_lock = 0;
|
||||||
Controllable::Controllables Controllable::registry;
|
Controllable::Controllables Controllable::registry;
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,8 @@ class Controllable : public PBD::StatefulDestructible {
|
||||||
virtual bool can_send_feedback() const { return true; }
|
virtual bool can_send_feedback() const { return true; }
|
||||||
|
|
||||||
sigc::signal<void> LearningFinished;
|
sigc::signal<void> LearningFinished;
|
||||||
|
static sigc::signal<void,PBD::Controllable*,int,int> CreateBinding;
|
||||||
|
static sigc::signal<void,PBD::Controllable*> DeleteBinding;
|
||||||
|
|
||||||
static sigc::signal<bool,PBD::Controllable*> StartLearning;
|
static sigc::signal<bool,PBD::Controllable*> StartLearning;
|
||||||
static sigc::signal<void,PBD::Controllable*> StopLearning;
|
static sigc::signal<void,PBD::Controllable*> StopLearning;
|
||||||
|
|
|
||||||
|
|
@ -56,9 +56,17 @@ GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
|
||||||
_feedback_interval = 10000; // microseconds
|
_feedback_interval = 10000; // microseconds
|
||||||
last_feedback_time = 0;
|
last_feedback_time = 0;
|
||||||
|
|
||||||
|
auto_binding = FALSE;
|
||||||
|
|
||||||
Controllable::StartLearning.connect (mem_fun (*this, &GenericMidiControlProtocol::start_learning));
|
Controllable::StartLearning.connect (mem_fun (*this, &GenericMidiControlProtocol::start_learning));
|
||||||
Controllable::StopLearning.connect (mem_fun (*this, &GenericMidiControlProtocol::stop_learning));
|
Controllable::StopLearning.connect (mem_fun (*this, &GenericMidiControlProtocol::stop_learning));
|
||||||
Session::SendFeedback.connect (mem_fun (*this, &GenericMidiControlProtocol::send_feedback));
|
Session::SendFeedback.connect (mem_fun (*this, &GenericMidiControlProtocol::send_feedback));
|
||||||
|
|
||||||
|
Controllable::CreateBinding.connect (mem_fun (*this, &GenericMidiControlProtocol::create_binding));
|
||||||
|
Controllable::DeleteBinding.connect (mem_fun (*this, &GenericMidiControlProtocol::delete_binding));
|
||||||
|
|
||||||
|
Session::AutoBindingOn.connect (mem_fun (*this, &GenericMidiControlProtocol::auto_binding_on));
|
||||||
|
Session::AutoBindingOff.connect (mem_fun (*this, &GenericMidiControlProtocol::auto_binding_off));
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericMidiControlProtocol::~GenericMidiControlProtocol ()
|
GenericMidiControlProtocol::~GenericMidiControlProtocol ()
|
||||||
|
|
@ -225,6 +233,71 @@ GenericMidiControlProtocol::stop_learning (Controllable* c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GenericMidiControlProtocol::delete_binding ( PBD::Controllable* control )
|
||||||
|
{
|
||||||
|
if( control != 0 ) {
|
||||||
|
Glib::Mutex::Lock lm2 (controllables_lock);
|
||||||
|
|
||||||
|
for( MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end(); ++iter) {
|
||||||
|
MIDIControllable* existingBinding = (*iter);
|
||||||
|
|
||||||
|
if( control == &(existingBinding->get_controllable()) ) {
|
||||||
|
delete existingBinding;
|
||||||
|
controllables.erase (iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end for midi controllables
|
||||||
|
} // end null check
|
||||||
|
}
|
||||||
|
void
|
||||||
|
GenericMidiControlProtocol::create_binding (PBD::Controllable* control, int pos, int control_number)
|
||||||
|
{
|
||||||
|
if( control != NULL ) {
|
||||||
|
Glib::Mutex::Lock lm2 (controllables_lock);
|
||||||
|
|
||||||
|
MIDI::channel_t channel = (pos & 0xf);
|
||||||
|
MIDI::byte value = control_number;
|
||||||
|
|
||||||
|
// Create a MIDIControllable::
|
||||||
|
MIDIControllable* mc = new MIDIControllable (*_port, *control);
|
||||||
|
|
||||||
|
// Remove any old binding for this midi channel/type/value pair
|
||||||
|
// Note: can't use delete_binding() here because we don't know the specific controllable we want to remove, only the midi information
|
||||||
|
for( MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end(); ++iter) {
|
||||||
|
MIDIControllable* existingBinding = (*iter);
|
||||||
|
|
||||||
|
if( (existingBinding->get_control_channel() & 0xf ) == channel &&
|
||||||
|
existingBinding->get_control_additional() == value &&
|
||||||
|
(existingBinding->get_control_type() & 0xf0 ) == MIDI::controller ) {
|
||||||
|
|
||||||
|
delete existingBinding;
|
||||||
|
controllables.erase (iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end for midi controllables
|
||||||
|
|
||||||
|
|
||||||
|
// Update the MIDI Controllable based on the the pos param
|
||||||
|
// Here is where a table lookup for user mappings could go; for now we'll just wing it...
|
||||||
|
mc->bind_midi( channel, MIDI::controller, value );
|
||||||
|
|
||||||
|
controllables.insert (mc);
|
||||||
|
} // end null test
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GenericMidiControlProtocol::auto_binding_on()
|
||||||
|
{
|
||||||
|
auto_binding = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GenericMidiControlProtocol::auto_binding_off()
|
||||||
|
{
|
||||||
|
auto_binding = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
XMLNode&
|
XMLNode&
|
||||||
GenericMidiControlProtocol::get_state ()
|
GenericMidiControlProtocol::get_state ()
|
||||||
{
|
{
|
||||||
|
|
@ -269,46 +342,47 @@ GenericMidiControlProtocol::set_state (const XMLNode& node)
|
||||||
_feedback_interval = 10000;
|
_feedback_interval = 10000;
|
||||||
}
|
}
|
||||||
|
|
||||||
Controllable* c;
|
// Are we using the autobinding feature? If so skip this part
|
||||||
|
if ( !auto_binding ) {
|
||||||
{
|
|
||||||
Glib::Mutex::Lock lm (pending_lock);
|
Controllable* c;
|
||||||
pending_controllables.clear ();
|
|
||||||
}
|
{
|
||||||
|
Glib::Mutex::Lock lm (pending_lock);
|
||||||
Glib::Mutex::Lock lm2 (controllables_lock);
|
pending_controllables.clear ();
|
||||||
|
}
|
||||||
controllables.clear ();
|
|
||||||
|
Glib::Mutex::Lock lm2 (controllables_lock);
|
||||||
nlist = node.children(); // "controls"
|
controllables.clear ();
|
||||||
|
nlist = node.children(); // "controls"
|
||||||
if (nlist.empty()) {
|
|
||||||
return 0;
|
if (nlist.empty()) {
|
||||||
}
|
return 0;
|
||||||
|
}
|
||||||
nlist = nlist.front()->children ();
|
|
||||||
|
nlist = nlist.front()->children ();
|
||||||
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
|
||||||
|
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
||||||
if ((prop = (*niter)->property ("id")) != 0) {
|
|
||||||
|
|
||||||
ID id = prop->value ();
|
if ((prop = (*niter)->property ("id")) != 0) {
|
||||||
|
|
||||||
c = Controllable::by_id (id);
|
ID id = prop->value ();
|
||||||
|
c = session->controllable_by_id (id);
|
||||||
if (c) {
|
|
||||||
MIDIControllable* mc = new MIDIControllable (*_port, *c);
|
|
||||||
if (mc->set_state (**niter) == 0) {
|
|
||||||
controllables.insert (mc);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
if (c) {
|
||||||
warning << string_compose (_("Generic MIDI control: controllable %1 not found (ignored)"), id)
|
MIDIControllable* mc = new MIDIControllable (*_port, *c);
|
||||||
<< endmsg;
|
if (mc->set_state (**niter) == 0) {
|
||||||
|
controllables.insert (mc);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
warning << string_compose (_("Generic MIDI control: controllable %1 not found in session (ignored)"),
|
||||||
|
id)
|
||||||
|
<< endmsg;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} // end autobinding check
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol {
|
||||||
ARDOUR::microseconds_t last_feedback_time;
|
ARDOUR::microseconds_t last_feedback_time;
|
||||||
|
|
||||||
bool do_feedback;
|
bool do_feedback;
|
||||||
|
bool auto_binding;
|
||||||
void _send_feedback ();
|
void _send_feedback ();
|
||||||
void send_feedback ();
|
void send_feedback ();
|
||||||
|
|
||||||
|
|
@ -59,6 +60,13 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol {
|
||||||
void stop_learning (PBD::Controllable*);
|
void stop_learning (PBD::Controllable*);
|
||||||
|
|
||||||
void learning_stopped (MIDIControllable*);
|
void learning_stopped (MIDIControllable*);
|
||||||
|
|
||||||
|
void create_binding (PBD::Controllable*, int, int);
|
||||||
|
void delete_binding (PBD::Controllable*);
|
||||||
|
|
||||||
|
void auto_binding_on();
|
||||||
|
void auto_binding_off();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* ardour_generic_midi_control_protocol_h */
|
#endif /* ardour_generic_midi_control_protocol_h */
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,10 @@ class MIDIControllable : public Stateful
|
||||||
XMLNode& get_state (void);
|
XMLNode& get_state (void);
|
||||||
int set_state (const XMLNode&);
|
int set_state (const XMLNode&);
|
||||||
|
|
||||||
|
void bind_midi (MIDI::channel_t, MIDI::eventType, MIDI::byte);
|
||||||
|
MIDI::channel_t get_control_channel () { return control_channel; }
|
||||||
|
MIDI::eventType get_control_type () { return control_type; }
|
||||||
|
MIDI::byte get_control_additional () { return control_additional; }
|
||||||
private:
|
private:
|
||||||
PBD::Controllable& controllable;
|
PBD::Controllable& controllable;
|
||||||
MIDI::Port& _port;
|
MIDI::Port& _port;
|
||||||
|
|
@ -86,8 +90,6 @@ class MIDIControllable : public Stateful
|
||||||
void midi_sense_controller (MIDI::Parser &, MIDI::EventTwoBytes *);
|
void midi_sense_controller (MIDI::Parser &, MIDI::EventTwoBytes *);
|
||||||
void midi_sense_program_change (MIDI::Parser &, MIDI::byte);
|
void midi_sense_program_change (MIDI::Parser &, MIDI::byte);
|
||||||
void midi_sense_pitchbend (MIDI::Parser &, MIDI::pitchbend_t);
|
void midi_sense_pitchbend (MIDI::Parser &, MIDI::pitchbend_t);
|
||||||
|
|
||||||
void bind_midi (MIDI::channel_t, MIDI::eventType, MIDI::byte);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __gm_midicontrollable_h__
|
#endif // __gm_midicontrollable_h__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue