diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2009-08-10 19:29:29 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2009-08-10 19:29:29 +0000 |
commit | 0bf3eb77591afc4aa8d0d6b5efa72273f02b109e (patch) | |
tree | ca49bb8ef0ef1ffd6df3adaa3c835b35cf6f2f16 | |
parent | 7f9aea14e926a58f86ffdc788e4873dcf41a6d2c (diff) |
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
-rw-r--r-- | gtk2_ardour/canvas-note-event.cc | 16 | ||||
-rw-r--r-- | gtk2_ardour/canvas-note-event.h | 5 | ||||
-rw-r--r-- | gtk2_ardour/editor.h | 1 | ||||
-rw-r--r-- | gtk2_ardour/editor_ops.cc | 122 | ||||
-rw-r--r-- | gtk2_ardour/midi_region_view.cc | 155 | ||||
-rw-r--r-- | gtk2_ardour/midi_region_view.h | 11 | ||||
-rw-r--r-- | gtk2_ardour/selection.cc | 68 | ||||
-rw-r--r-- | gtk2_ardour/selection.h | 10 | ||||
-rw-r--r-- | libs/ardour/ardour/io_processor.h | 2 | ||||
-rw-r--r-- | libs/ardour/io.cc | 10 | ||||
-rw-r--r-- | libs/ardour/io_processor.cc | 12 | ||||
-rw-r--r-- | libs/ardour/processor.cc | 2 | ||||
-rw-r--r-- | libs/ardour/route.cc | 2 |
13 files changed, 279 insertions, 137 deletions
diff --git a/gtk2_ardour/canvas-note-event.cc b/gtk2_ardour/canvas-note-event.cc index 74632d7ddf..52e7ac5eef 100644 --- a/gtk2_ardour/canvas-note-event.cc +++ b/gtk2_ardour/canvas-note-event.cc @@ -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); diff --git a/gtk2_ardour/canvas-note-event.h b/gtk2_ardour/canvas-note-event.h index 86f7312d17..305988667d 100644 --- a/gtk2_ardour/canvas-note-event.h +++ b/gtk2_ardour/canvas-note-event.h @@ -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, diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 2a1875d17d..758772598c 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -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); diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index 55382bbaca..0a7543b214 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -3906,69 +3906,82 @@ Editor::cut_copy (CutCopyOp op) return; } - RegionSelection rs; - - /* we only want to cut regions if some are selected */ + if (internal_editing()) { - if (!selection->regions.empty()) { - get_regions_for_action (rs); - } - - switch (current_mouse_mode()) { - case MouseObject: - if (!rs.empty() || !selection->points.empty()) { + switch (current_mouse_mode()) { + case MouseObject: + case MouseRange: + cut_copy_midi (op); + break; + default: + break; + } + + } else { + + 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")); + begin_reversible_command (opname + _(" objects")); - if (!rs.empty()) { - cut_copy_regions (op, rs); + if (!rs.empty()) { + cut_copy_regions (op, rs); - if (op == Cut) { - selection->clear_regions (); + if (op == Cut) { + selection->clear_regions (); + } } - } - if (!selection->points.empty()) { - cut_copy_points (op); + if (!selection->points.empty()) { + cut_copy_points (op); - if (op == Cut) { - selection->clear_points (); + 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 + 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; + 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; + break; - default: - 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; diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index aa964749ff..9b9be486a3 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -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); + } - _selection.clear(); - _selection.insert(ev); + i = tmp; + } - 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(); +} + diff --git a/gtk2_ardour/midi_region_view.h b/gtk2_ardour/midi_region_view.h index 3df4001ab4..01d5a305cb 100644 --- a/gtk2_ardour/midi_region_view.h +++ b/gtk2_ardour/midi_region_view.h @@ -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. */ diff --git a/gtk2_ardour/selection.cc b/gtk2_ardour/selection.cc index cbe5975e87..be7552b0bd 100644 --- a/gtk2_ardour/selection.cc +++ b/gtk2_ardour/selection.cc @@ -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 @@ -110,6 +113,15 @@ Selection::clear_tracks () } void +Selection::clear_midi () +{ + if (!midi.empty()) { + midi.clear (); + MidiChanged (); + } +} + +void Selection::clear_time () { time.track = 0; @@ -208,6 +220,20 @@ Selection::toggle (RegionView* r) } 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) { RegionSelection::iterator i; @@ -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) @@ -543,6 +602,13 @@ Selection::set (const RegionSelection& rs) } void +Selection::set (MidiRegionView* mrv) +{ + clear_midi (); + add (mrv); +} + +void Selection::set (RegionView* r, bool also_clear_tracks) { clear_regions (); diff --git a/gtk2_ardour/selection.h b/gtk2_ardour/selection.h index 6107e2970a..9278935e31 100644 --- a/gtk2_ardour/selection.h +++ b/gtk2_ardour/selection.h @@ -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)); diff --git a/libs/ardour/ardour/io_processor.h b/libs/ardour/ardour/io_processor.h index ff985c6e79..d591962733 100644 --- a/libs/ardour/ardour/io_processor.h +++ b/libs/ardour/ardour/io_processor.h @@ -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; diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc index 7a97ce0d6b..2749b9f405 100644 --- a/libs/ardour/io.cc +++ b/libs/ardour/io.cc @@ -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 diff --git a/libs/ardour/io_processor.cc b/libs/ardour/io_processor.cc index 708820cdca..505d33a1b0 100644 --- a/libs/ardour/io_processor.cc +++ b/libs/ardour/io_processor.cc @@ -221,18 +221,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 { return _output ? _output->n_ports() : ChanCount::ZERO; diff --git a/libs/ardour/processor.cc b/libs/ardour/processor.cc index 04706c0c2d..101bc29ab4 100644 --- a/libs/ardour/processor.cc +++ b/libs/ardour/processor.cc @@ -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; diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 9895cf1e18..989cecdd6b 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -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()); |