first part of MIDI cut/copy/paste ; fix for input/output_streams of an IOProcessor being reported in a misleading way; in/out translation fix from 2.X, sort of

git-svn-id: svn://localhost/ardour2/branches/3.0@5510 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2009-08-10 19:29:29 +00:00
parent 7f9aea14e9
commit 0bf3eb7759
13 changed files with 286 additions and 144 deletions

View File

@ -242,20 +242,6 @@ CanvasNoteEvent::on_event(GdkEvent* ev)
return false;
}
case GDK_KEY_PRESS:
if (_note && ev->key.keyval == GDK_Delete) {
selected(true);
_region.start_delta_command();
_region.command_remove_note(this);
}
break;
case GDK_KEY_RELEASE:
if (ev->key.keyval == GDK_Delete) {
_region.apply_command();
}
break;
case GDK_ENTER_NOTIFY:
_region.note_entered(this);
//_item->grab_focus();
@ -342,7 +328,7 @@ CanvasNoteEvent::on_event(GdkEvent* ev)
break;
case GDK_BUTTON_RELEASE:
select_mod = (ev->motion.state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK));
select_mod = (ev->motion.state & (Keyboard::PrimaryModifier | Keyboard::SecondaryModifier));
event_x = ev->button.x;
event_y = ev->button.y;
_item->property_parent().get_value()->w2i(event_x, event_y);

View File

@ -24,6 +24,8 @@
#include <libgnomecanvasmm/text.h>
#include <libgnomecanvasmm/widget.h>
#include "ardour/midi_model.h"
#include "rgb_macros.h"
#include "ardour_ui.h"
#include "ui_config.h"
@ -51,7 +53,8 @@ namespace Canvas {
*/
class CanvasNoteEvent : virtual public sigc::trackable, public InteractiveItem {
public:
typedef Evoral::Note<double> NoteType;
typedef Evoral::Note<ARDOUR::MidiModel::TimeType> NoteType;
CanvasNoteEvent(
MidiRegionView& region,
Item* item,

View File

@ -1025,6 +1025,7 @@ class Editor : public PublicEditor
void cut_copy_points (Editing::CutCopyOp);
void cut_copy_regions (Editing::CutCopyOp, RegionSelection&);
void cut_copy_ranges (Editing::CutCopyOp);
void cut_copy_midi (Editing::CutCopyOp);
void mouse_paste ();
void paste_internal (nframes64_t position, float times);

View File

@ -3906,69 +3906,82 @@ Editor::cut_copy (CutCopyOp op)
return;
}
RegionSelection rs;
if (internal_editing()) {
/* we only want to cut regions if some are selected */
if (!selection->regions.empty()) {
get_regions_for_action (rs);
}
switch (current_mouse_mode()) {
case MouseObject:
if (!rs.empty() || !selection->points.empty()) {
begin_reversible_command (opname + _(" objects"));
if (!rs.empty()) {
cut_copy_regions (op, rs);
if (op == Cut) {
selection->clear_regions ();
}
}
if (!selection->points.empty()) {
cut_copy_points (op);
if (op == Cut) {
selection->clear_points ();
}
}
commit_reversible_command ();
break; // terminate case statement here
}
if (!selection->time.empty()) {
/* don't cause suprises */
switch (current_mouse_mode()) {
case MouseObject:
case MouseRange:
cut_copy_midi (op);
break;
default:
break;
}
// fall thru if there was nothing selected
} else {
case MouseRange:
if (selection->time.empty()) {
nframes64_t start, end;
if (!get_edit_op_range (start, end)) {
return;
RegionSelection rs;
/* we only want to cut regions if some are selected */
if (!selection->regions.empty()) {
get_regions_for_action (rs);
}
switch (current_mouse_mode()) {
case MouseObject:
if (!rs.empty() || !selection->points.empty()) {
begin_reversible_command (opname + _(" objects"));
if (!rs.empty()) {
cut_copy_regions (op, rs);
if (op == Cut) {
selection->clear_regions ();
}
}
if (!selection->points.empty()) {
cut_copy_points (op);
if (op == Cut) {
selection->clear_points ();
}
}
commit_reversible_command ();
break; // terminate case statement here
}
if (!selection->time.empty()) {
/* don't cause suprises */
break;
}
// fall thru if there was nothing selected
case MouseRange:
if (selection->time.empty()) {
nframes64_t start, end;
if (!get_edit_op_range (start, end)) {
return;
}
selection->set ((TimeAxisView*) 0, start, end);
}
selection->set ((TimeAxisView*) 0, start, end);
}
begin_reversible_command (opname + _(" range"));
cut_copy_ranges (op);
commit_reversible_command ();
begin_reversible_command (opname + _(" range"));
cut_copy_ranges (op);
commit_reversible_command ();
if (op == Cut) {
selection->clear_time ();
if (op == Cut) {
selection->clear_time ();
}
break;
default:
break;
}
break;
default:
break;
}
if (op == Cut || op == Clear) {
break_drag ();
delete _drag;
@ -3992,6 +4005,20 @@ Editor::cut_copy_points (CutCopyOp op)
}
}
/** Cut, copy or clear selected automation points.
* @param op Operation (Cut, Copy or Clear)
*/
void
Editor::cut_copy_midi (CutCopyOp op)
{
cerr << "CCM: there are " << selection->midi.size() << " MRV's to work on\n";
for (MidiSelection::iterator i = selection->midi.begin(); i != selection->midi.end(); ++i) {
MidiRegionView* mrv = *i;
mrv->cut_copy_clear (op);
}
}
struct PlaylistState {
boost::shared_ptr<Playlist> playlist;
XMLNode* before;
@ -4307,7 +4334,6 @@ Editor::paste_internal (nframes64_t position, float times)
/* get everything in the correct order */
if (!selection->tracks.empty()) {
sort_track_selection ();
ts = selection->tracks;

View File

@ -39,23 +39,24 @@
#include "evoral/Parameter.hpp"
#include "evoral/Control.hpp"
#include "streamview.h"
#include "midi_region_view.h"
#include "midi_streamview.h"
#include "midi_time_axis.h"
#include "simpleline.h"
#include "automation_region_view.h"
#include "automation_time_axis.h"
#include "canvas-hit.h"
#include "canvas-note.h"
#include "canvas-program-change.h"
#include "public_editor.h"
#include "ghostregion.h"
#include "midi_time_axis.h"
#include "automation_time_axis.h"
#include "automation_region_view.h"
#include "utils.h"
#include "midi_util.h"
#include "gui_thread.h"
#include "keyboard.h"
#include "midi_region_view.h"
#include "midi_streamview.h"
#include "midi_time_axis.h"
#include "midi_time_axis.h"
#include "midi_util.h"
#include "public_editor.h"
#include "selection.h"
#include "simpleline.h"
#include "streamview.h"
#include "utils.h"
#include "i18n.h"
@ -659,12 +660,12 @@ MidiRegionView::~MidiRegionView ()
}
_selection.clear();
_cut_buffer.clear ();
clear_events();
delete _note_group;
delete _delta_command;
}
void
MidiRegionView::region_resized (Change what_changed)
{
@ -1162,34 +1163,32 @@ MidiRegionView::clear_selection_except(ArdourCanvas::CanvasNoteEvent* ev)
void
MidiRegionView::unique_select(ArdourCanvas::CanvasNoteEvent* ev)
{
for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) {
for (Selection::iterator i = _selection.begin(); i != _selection.end(); ) {
Selection::iterator tmp = i;
++tmp;
if ((*i) != ev) {
(*i)->selected(false);
(*i)->hide_velocity();
}
remove_from_selection (*i);
}
i = tmp;
}
_selection.clear();
_selection.insert(ev);
if ( ! ev->selected()) {
ev->selected(true);
if (!ev->selected()) {
add_to_selection (ev);
}
}
void
MidiRegionView::note_selected(ArdourCanvas::CanvasNoteEvent* ev, bool add)
{
if ( ! add) {
if (!add) {
clear_selection_except(ev);
}
if (_selection.insert(ev).second) {
play_midi_note(ev->note());
}
if ( ! ev->selected()) {
ev->selected(true);
if (!ev->selected()) {
add_to_selection (ev);
}
}
@ -1197,15 +1196,11 @@ MidiRegionView::note_selected(ArdourCanvas::CanvasNoteEvent* ev, bool add)
void
MidiRegionView::note_deselected(ArdourCanvas::CanvasNoteEvent* ev, bool add)
{
if ( ! add) {
if (!add) {
clear_selection_except(ev);
}
_selection.erase(ev);
if (ev->selected()) {
ev->selected(false);
}
remove_from_selection (ev);
}
@ -1230,17 +1225,12 @@ MidiRegionView::update_drag_selection(double x1, double x2, double y1, double y2
assert((*i)->x1() >= last_x1);
last_x1 = (*i)->x1();
#endif
// Inside rectangle
if ((*i)->x1() >= x1 && (*i)->x1() <= x2 && (*i)->y1() >= last_y && (*i)->y1() <= y) {
if (!(*i)->selected()) {
(*i)->selected(true);
_selection.insert(*i);
play_midi_note((*i)->note());
}
// Not inside rectangle
// Inside rectangle
add_to_selection (*i);
} else if ((*i)->selected()) {
(*i)->selected(false);
_selection.erase(*i);
// Not inside rectangle
remove_from_selection (*i);
}
}
} else {
@ -1250,22 +1240,54 @@ MidiRegionView::update_drag_selection(double x1, double x2, double y1, double y2
assert((*i)->x1() >= last_x1);
last_x1 = (*i)->x1();
#endif
// Inside rectangle
if ((*i)->x2() <= x1 && (*i)->x2() >= x2 && (*i)->y1() >= last_y && (*i)->y1() <= y) {
if (!(*i)->selected()) {
(*i)->selected(true);
_selection.insert(*i);
play_midi_note((*i)->note());
}
// Not inside rectangle
// Inside rectangle
add_to_selection (*i);
} else if ((*i)->selected()) {
(*i)->selected(false);
_selection.erase(*i);
// Not inside rectangle
remove_from_selection (*i);
}
}
}
}
void
MidiRegionView::remove_from_selection (CanvasNoteEvent* ev)
{
Selection::iterator i = _selection.find (ev);
if (i != _selection.end()) {
_selection.erase (i);
}
ev->selected (false);
ev->hide_velocity ();
if (_selection.empty()) {
PublicEditor& editor (trackview.editor());
editor.get_selection().remove (this);
}
}
void
MidiRegionView::add_to_selection (CanvasNoteEvent* ev)
{
bool add_mrv_selection = false;
if (_selection.empty()) {
add_mrv_selection = true;
}
if (_selection.insert (ev).second) {
ev->selected (true);
play_midi_note ((ev)->note());
}
if (add_mrv_selection) {
PublicEditor& editor (trackview.editor());
editor.get_selection().add (this);
}
}
void
MidiRegionView::move_selection(double dx, double dy)
@ -1275,7 +1297,6 @@ MidiRegionView::move_selection(double dx, double dy)
}
}
void
MidiRegionView::note_dropped(CanvasNoteEvent* ev, double dt, uint8_t dnote)
{
@ -1641,3 +1662,31 @@ MidiRegionView::midi_patch_settings_changed(std::string model, std::string custo
redisplay_model();
}
void
MidiRegionView::cut_copy_clear (Editing::CutCopyOp op)
{
if (_selection.empty()) {
return;
}
_cut_buffer.clear ();
start_delta_command();
for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) {
switch (op) {
case Copy:
_cut_buffer.push_back (NoteType (*((*i)->note().get())));
break;
case Cut:
_cut_buffer.push_back (NoteType (*(*i)->note().get()));
command_remove_note (*i);
break;
case Clear:
break;
}
}
apply_command();
}

View File

@ -30,6 +30,7 @@
#include "ardour/diskstream.h"
#include "ardour/types.h"
#include "editing.h"
#include "region_view.h"
#include "midi_time_axis.h"
#include "time_axis_view_item.h"
@ -97,6 +98,8 @@ class MidiRegionView : public RegionView
void add_note(const boost::shared_ptr<NoteType> note);
void resolve_note(uint8_t note_num, double end_time);
void cut_copy_clear (Editing::CutCopyOp);
struct PCEvent {
PCEvent(double a_time, uint8_t a_value, uint8_t a_channel)
@ -171,7 +174,7 @@ class MidiRegionView : public RegionView
void note_deselected(ArdourCanvas::CanvasNoteEvent* ev, bool add);
void delete_selection();
size_t selection_size() { return _selection.size(); }
void move_selection(double dx, double dy);
void note_dropped(ArdourCanvas::CanvasNoteEvent* ev, double d_pixels, uint8_t d_note);
@ -297,6 +300,9 @@ class MidiRegionView : public RegionView
void clear_selection() { clear_selection_except(NULL); }
void update_drag_selection(double last_x, double x, double last_y, double y);
void add_to_selection (ArdourCanvas::CanvasNoteEvent*);
void remove_from_selection (ArdourCanvas::CanvasNoteEvent*);
int8_t _force_channel;
uint16_t _last_channel_selection;
double _default_note_length;
@ -327,6 +333,9 @@ class MidiRegionView : public RegionView
typedef std::set<ArdourCanvas::CanvasNoteEvent*> Selection;
/// Currently selected CanvasNoteEvents
Selection _selection;
/// the cut buffer for this region view
typedef std::list<NoteType> CutBuffer;
CutBuffer _cut_buffer;
/** New notes (created in the current command) which should be selected
* when they appear after the command is applied. */

View File

@ -53,6 +53,7 @@ Selection::operator= (const Selection& other)
tracks = other.tracks;
time = other.time;
lines = other.lines;
midi = other.midi;
}
return *this;
}
@ -66,7 +67,8 @@ operator== (const Selection& a, const Selection& b)
a.time.group == b.time.group &&
a.time == b.time &&
a.lines == b.lines &&
a.playlists == b.playlists;
a.playlists == b.playlists &&
a.midi == b.midi;
}
/** Clear everything from the Selection */
@ -79,6 +81,7 @@ Selection::clear ()
clear_lines();
clear_time ();
clear_playlists ();
clear_midi ();
}
void
@ -109,6 +112,15 @@ Selection::clear_tracks ()
}
}
void
Selection::clear_midi ()
{
if (!midi.empty()) {
midi.clear ();
MidiChanged ();
}
}
void
Selection::clear_time ()
{
@ -207,6 +219,20 @@ Selection::toggle (RegionView* r)
RegionsChanged ();
}
void
Selection::toggle (MidiRegionView* mrv)
{
MidiSelection::iterator i;
if ((i = find (midi.begin(), midi.end(), mrv)) == midi.end()) {
add (mrv);
} else {
midi.erase (i);
}
MidiChanged ();
}
void
Selection::toggle (vector<RegionView*>& r)
{
@ -349,6 +375,21 @@ Selection::add (RegionView* r)
}
}
void
Selection::add (MidiRegionView* mrv)
{
if (find (midi.begin(), midi.end(), mrv) == midi.end()) {
midi.push_back (mrv);
/* XXX should we do this? */
#if 0
if (Config->get_link_region_and_track_selection()) {
add (&mrv->get_trackview());
}
#endif
MidiChanged ();
}
}
long
Selection::add (nframes_t start, nframes_t end)
{
@ -473,6 +514,24 @@ Selection::remove (RegionView* r)
}
}
void
Selection::remove (MidiRegionView* mrv)
{
MidiSelection::iterator x;
if ((x = find (midi.begin(), midi.end(), mrv)) != midi.end()) {
midi.erase (x);
MidiChanged ();
}
#if 0
/* XXX fix this up ? */
if (Config->get_link_region_and_track_selection() && !regions.involves (r->get_trackview())) {
remove (&r->get_trackview());
}
#endif
}
void
Selection::remove (uint32_t selection_id)
@ -542,6 +601,13 @@ Selection::set (const RegionSelection& rs)
RegionsChanged(); /* EMIT SIGNAL */
}
void
Selection::set (MidiRegionView* mrv)
{
clear_midi ();
add (mrv);
}
void
Selection::set (RegionView* r, bool also_clear_tracks)
{

View File

@ -33,11 +33,13 @@
#include "processor_selection.h"
#include "point_selection.h"
#include "marker_selection.h"
#include "midi_selection.h"
class TimeAxisView;
class RegionView;
class Selectable;
class PublicEditor;
class MidiRegionView;
namespace ARDOUR {
class Region;
@ -77,6 +79,7 @@ class Selection : public sigc::trackable
PlaylistSelection playlists;
PointSelection points;
MarkerSelection markers;
MidiSelection midi;
Selection (PublicEditor const * e) : editor (e), next_time_id (0) {
clear();
@ -91,6 +94,7 @@ class Selection : public sigc::trackable
sigc::signal<void> PlaylistsChanged;
sigc::signal<void> PointsChanged;
sigc::signal<void> MarkersChanged;
sigc::signal<void> MidiChanged;
void clear ();
bool empty();
@ -108,6 +112,7 @@ class Selection : public sigc::trackable
void set (TimeAxisView*);
void set (const std::list<TimeAxisView*>&);
void set (RegionView*, bool also_clear_tracks = true);
void set (MidiRegionView*);
void set (std::vector<RegionView*>&);
long set (TimeAxisView*, nframes_t, nframes_t);
void set (boost::shared_ptr<Evoral::ControlList>);
@ -120,6 +125,7 @@ class Selection : public sigc::trackable
void toggle (TimeAxisView*);
void toggle (const std::list<TimeAxisView*>&);
void toggle (RegionView*);
void toggle (MidiRegionView*);
void toggle (std::vector<RegionView*>&);
long toggle (nframes_t, nframes_t);
void toggle (ARDOUR::AutomationList*);
@ -131,6 +137,7 @@ class Selection : public sigc::trackable
void add (TimeAxisView*);
void add (const std::list<TimeAxisView*>&);
void add (RegionView*);
void add (MidiRegionView*);
void add (std::vector<RegionView*>&);
long add (nframes_t, nframes_t);
void add (boost::shared_ptr<Evoral::ControlList>);
@ -139,10 +146,10 @@ class Selection : public sigc::trackable
void add (Marker*);
void add (const std::list<Marker*>&);
void add (const RegionSelection&);
void remove (TimeAxisView*);
void remove (const std::list<TimeAxisView*>&);
void remove (RegionView*);
void remove (MidiRegionView*);
void remove (uint32_t selection_id);
void remove (nframes_t, nframes_t);
void remove (boost::shared_ptr<ARDOUR::AutomationList>);
@ -160,6 +167,7 @@ class Selection : public sigc::trackable
void clear_playlists ();
void clear_points ();
void clear_markers ();
void clear_midi ();
void foreach_region (void (ARDOUR::Region::*method)(void));
void foreach_regionview (void (RegionView::*method)(void));

View File

@ -53,8 +53,6 @@ class IOProcessor : public Processor
bool set_name (const std::string& str);
virtual ChanCount output_streams() const;
virtual ChanCount input_streams () const;
virtual ChanCount natural_output_streams() const;
virtual ChanCount natural_input_streams () const;

View File

@ -1061,10 +1061,16 @@ IO::build_legal_port_name (DataType type)
throw unknown_type();
}
/* note that if "in" or "out" are translated it will break a session
across locale switches because a port's connection list will
show (old) translated names, but the current port name will
use the (new) translated name.
*/
if (_direction == Input) {
suffix += _("_in");
suffix += X_("_in");
} else {
suffix += _("_out");
suffix += X_("_out");
}
// allow up to 4 digits for the output port number, plus the slash, suffix and extra space

View File

@ -220,18 +220,6 @@ IOProcessor::silence (nframes_t nframes)
}
}
ChanCount
IOProcessor::output_streams() const
{
return _output ? _output->n_ports() : ChanCount::ZERO;
}
ChanCount
IOProcessor::input_streams () const
{
return _input ? _input->n_ports() : ChanCount::ZERO;
}
ChanCount
IOProcessor::natural_output_streams() const
{

View File

@ -232,6 +232,8 @@ Processor::configure_io (ChanCount in, ChanCount out)
_configured_output = out;
_configured = true;
std::cerr << "******* CONF IN for " << _name << " set to " << in << std::endl;
ConfigurationChanged.emit (in, out);
return true;

View File

@ -422,7 +422,7 @@ Route::process_output_buffers (BufferSet& bufs,
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
if (bufs.count() != (*i)->input_streams()) {
cerr << _name << " bufs = " << bufs.count()
<< " input = " << (*i)->input_streams()
<< " input for " << (*i)->name() << " = " << (*i)->input_streams()
<< endl;
}
assert (bufs.count() == (*i)->input_streams());