diff options
73 files changed, 6085 insertions, 4006 deletions
diff --git a/ardour.dox b/ardour.dox index a72ecbc588..2ad51340df 100644 --- a/ardour.dox +++ b/ardour.dox @@ -459,7 +459,8 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = libs/pbd libs/midi++2 libs/ardour libs/gtkmm2ext gtk2_ardour +#INPUT = libs/pbd libs/midi++2 libs/ardour libs/gtkmm2ext gtk2_ardour +INPUT = libs/ardour gtk2_ardour # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp diff --git a/gtk2_ardour/SConscript b/gtk2_ardour/SConscript index 68e07ebd22..15bff16562 100644 --- a/gtk2_ardour/SConscript +++ b/gtk2_ardour/SConscript @@ -76,10 +76,13 @@ ardour_ui_mixer.cc ardour_ui_options.cc audio_clock.cc audio_time_axis.cc +audio_region_editor.cc automation_gain_line.cc automation_line.cc automation_pan_line.cc automation_time_axis.cc +midi_time_axis.cc +midi_streamview.cc axis_view.cc canvas-imageframe.c canvas-simpleline.c @@ -159,10 +162,11 @@ public_editor.cc redirect_automation_line.cc redirect_automation_time_axis.cc redirect_box.cc -region_editor.cc region_gain_line.cc region_selection.cc regionview.cc +audio_regionview.cc +taperegionview.cc route_params_ui.cc route_redirect_selection.cc route_ui.cc @@ -170,10 +174,11 @@ selection.cc sfdb_ui.cc send_ui.cc streamview.cc -taperegionview.cc +audio_streamview.cc tempo_dialog.cc time_axis_view.cc time_axis_view_item.cc +route_time_axis.cc time_selection.cc utils.cc version.cc diff --git a/gtk2_ardour/analysis_window.cc b/gtk2_ardour/analysis_window.cc index 44d40f7ec8..9d9e928312 100644 --- a/gtk2_ardour/analysis_window.cc +++ b/gtk2_ardour/analysis_window.cc @@ -35,7 +35,7 @@ #include "time_axis_view.h" #include "public_editor.h" #include "selection.h" -#include "regionview.h" +#include "audio_regionview.h" #include "i18n.h" @@ -225,7 +225,7 @@ AnalysisWindow::analyze_data (Gtk::Button *button) Selection s = PublicEditor::instance().get_selection(); TimeSelection ts = s.time; - AudioRegionSelection ars = s.audio_regions; + RegionSelection ars = s.regions; for (TrackSelection::iterator i = s.tracks.begin(); i != s.tracks.end(); ++i) { @@ -279,24 +279,29 @@ AnalysisWindow::analyze_data (Gtk::Button *button) TimeAxisView *current_axis = (*i); - for (std::set<AudioRegionView *>::iterator j = ars.begin(); j != ars.end(); ++j) { + for (std::set<RegionView *>::iterator j = ars.begin(); j != ars.end(); ++j) { + // Check that the region is actually audio (so we can analyze it) + AudioRegionView* arv = dynamic_cast<AudioRegionView*>(*j); + if (!arv) + continue; + // Check that the region really is selected on _this_ track/solo - if ( &(*j)->get_time_axis_view() != current_axis) + if ( &arv->get_time_axis_view() != current_axis) continue; -// cerr << " - " << (*j)->region.name() << ": " << (*j)->region.length() << " samples starting at " << (*j)->region.position() << endl; +// cerr << " - " << (*j)->region().name() << ": " << (*j)->region().length() << " samples starting at " << (*j)->region().position() << endl; jack_nframes_t i = 0; int n; - while ( i < (*j)->region.length() ) { + while ( i < arv->region().length() ) { // TODO: What about stereo+ channels? composite all to one, I guess n = fft_graph.windowSize(); - if (i + n >= (*j)->region.length() ) { - n = (*j)->region.length() - i; + if (i + n >= arv->region().length() ) { + n = arv->region().length() - i; } - - n = (*j)->region.read_at(buf, mixbuf, gain, work, (*j)->region.position() + i, n); + + n = arv->audio_region().read_at(buf, mixbuf, gain, work, arv->region().position() + i, n); if ( n < fft_graph.windowSize()) { for (int j = n; j < fft_graph.windowSize(); j++) { diff --git a/gtk2_ardour/ardour.colors b/gtk2_ardour/ardour.colors index 50f9460b3c..aa87f2de9d 100644 --- a/gtk2_ardour/ardour.colors +++ b/gtk2_ardour/ardour.colors @@ -2,12 +2,12 @@ cWaveForm 0.0 0.0 0.0 0.80 cMutedWaveForm 0.35 0.35 0.35 1.0 cSelectedFrameBase 0.0 0.57 0.66 0.5 cFrameBase 0.0 0.76 0.75 0.5 -cAudioTrackBase 0.75 0.75 0.85 0.41 cAudioTrackOutline 0.00 0.00 0.00 1.00 -cAudioBusBase 0.75 0.80 0.75 0.41 -cMidiTrackBase 0.85 0.75 0.75 0.41 +cAudioTrackBase 0.80 0.80 1.0 0.5 +cAudioBusBase 0.65 0.65 0.75 0.41 cMidiTrackOutline 0.00 0.00 0.00 1.00 -cMidiBusBase 0.80 0.75 0.75 0.41 +cMidiTrackBase 1.0 0.85 0.85 0.5 +cMidiBusBase 0.75 0.65 0.65 0.41 cMeterBar 0.40 0.40 0.40 1.0 cTempoBar 0.45 0.45 0.45 1.0 cMarkerBar 0.50 0.50 0.50 1.0 diff --git a/gtk2_ardour/ardour2_ui.rc b/gtk2_ardour/ardour2_ui.rc index e43013a98e..6945ea1338 100644 --- a/gtk2_ardour/ardour2_ui.rc +++ b/gtk2_ardour/ardour2_ui.rc @@ -501,44 +501,44 @@ style "editor_time_ruler" = "small_text" bg[NORMAL] = { 0.09, 0.09, 0.09 } } +style "audio_bus_base" +{ + font_name = "sans 6" + fg[NORMAL] = { 0.77, 0.77, 0.72 } + fg[NORMAL] = { 0.7, 0.8, 0.2 } + bg[NORMAL] = { 0.20, 0.20, 0.26 } +} + style "audio_track_base" = "default_base" { font_name = "sans 6" fg[NORMAL] = { 0.77, 0.77, 0.72 } - bg[NORMAL] = { 0.18, 0.18, 0.22 } + bg[NORMAL] = { 0.32, 0.32, 0.45 } bg[ACTIVE] = { 0.20, 0.20, 0.20 } bg[PRELIGHT] = { 0.20, 0.20, 0.20 } bg[INSENSITIVE] = { 0.20, 0.20, 0.20 } bg[SELECTED] = { 0.20, 0.20, 0.20 } } -style "audio_bus_base" +style "midi_bus_base" { font_name = "sans 6" fg[NORMAL] = { 0.77, 0.77, 0.72 } - fg[NORMAL] = { 0.7, 0.8, 0.2 } - bg[NORMAL] = {0, 0.40, 0.36 } + fg[NORMAL] = { 0.8, 0.7, 0.2 } + bg[NORMAL] = { 0.26, 0.20, 0.20 } } style "midi_track_base" = "default_base" { font_name = "sans 6" fg[NORMAL] = { 0.77, 0.77, 0.72 } - bg[NORMAL] = { 0.22, 0.18, 0.18 } + bg[NORMAL] = { 0.48, 0.30, 0.32 } bg[ACTIVE] = { 0.20, 0.20, 0.20 } bg[PRELIGHT] = { 0.20, 0.20, 0.20 } bg[INSENSITIVE] = { 0.20, 0.20, 0.20 } bg[SELECTED] = { 0.20, 0.20, 0.20 } } -style "midi_bus_base" -{ - font_name = "sans 6" - fg[NORMAL] = { 0.77, 0.77, 0.72 } - fg[NORMAL] = { 0.8, 0.7, 0.2 } - bg[NORMAL] = {0.40, 0.36, 0.00 } -} - style "track_name_display" { font_name = "sans medium 8" @@ -1028,13 +1028,20 @@ widget "*BBTRuler" style "editor_time_ruler" widget "*FramesRuler" style "editor_time_ruler" widget "*MinSecRuler" style "editor_time_ruler" widget "*BaseFrame" style "base_frame" -widget "*BusControlsBaseUnselected" style "audio_bus_base" +widget "*AudioBusControlsBaseUnselected" style "audio_bus_base" +widget "*AudioBusControlsBaseInactiveUnselected" style "track_controls_inactive" +widget "*AudioBusControlsBaseInactiveSelected" style "track_controls_inactive" +widget "*AudioBusControlsBaseSelected" style "edit_controls_base_selected" widget "*AudioTimeAxisViewControlsBaseUnselected" style "audio_track_base" widget "*AudioTrackStripBase" style "audio_track_base" widget "*AudioTrackControlsBaseUnselected" style "audio_track_base" widget "*AudioTrackFader" style "audio_track_base" widget "*AudioBusStripBase" style "audio_bus_base" widget "*AudioBusFader" style "audio_bus_base" +widget "*MidiBusControlsBaseUnselected" style "midi_bus_base" +widget "*MidiBusControlsBaseInactiveUnselected" style "track_controls_inactive" +widget "*MidiBusControlsBaseInactiveSelected" style "track_controls_inactive" +widget "*MidiBusControlsBaseSelected" style "edit_controls_base_selected" widget "*MidiTimeAxisViewControlsBaseUnselected" style "midi_track_base" widget "*MidiTrackStripBase" style "midi_track_base" widget "*MidiTrackControlsBaseUnselected" style "midi_track_base" @@ -1065,15 +1072,12 @@ widget "*MouseModeButton" style "default_buttons_menus" widget "*MouseModeButton*" style "default_buttons_menus" widget "*EditorMainCanvas" style "main_canvas_area" widget "*AudioTrackControlsBaseInactiveUnselected" style "track_controls_inactive" -widget "*BusControlsBaseInactiveUnselected" style "track_controls_inactive" widget "*AutomationTrackControlsBaseInactiveUnselected" style "track_controls_inactive" widget "*AudioTrackControlsBaseInactiveSelected" style "track_controls_inactive" -widget "*BusControlsBaseInactiveSelected" style "track_controls_inactive" widget "*AutomationTrackControlsBaseInactiveSelected" style "track_controls_inactive" widget "*AudioTrackStripBaseInactive" style "track_controls_inactive" widget "*AudioBusStripBaseInactive" style "track_controls_inactive" widget "*AudioTrackControlsBaseSelected" style "edit_controls_base_selected" -widget "*BusControlsBaseSelected" style "edit_controls_base_selected" widget "*AutomationTrackControlsBase" style "automation_track_controls_base" widget "*AutomationTrackControlsBaseSelected" style "edit_controls_base_selected" /*widget "*EditorMenuBar*" style "black_mackie_menu_bar" diff --git a/gtk2_ardour/region_editor.cc b/gtk2_ardour/audio_region_editor.cc index 413ff01753..b3e2edb126 100644 --- a/gtk2_ardour/region_editor.cc +++ b/gtk2_ardour/audio_region_editor.cc @@ -24,8 +24,8 @@ #include <gtkmm2ext/stop_signal.h> #include <cmath> -#include "region_editor.h" -#include "regionview.h" +#include "audio_region_editor.h" +#include "audio_regionview.h" #include "ardour_ui.h" #include "utils.h" #include "gui_thread.h" @@ -37,9 +37,8 @@ using namespace PBD; using namespace sigc; using namespace std; -AudioRegionEditor::AudioRegionEditor (Session&s, AudioRegion& r, AudioRegionView& rv) - : ArdourDialog ("audio region editor"), - _session (s), +AudioRegionEditor::AudioRegionEditor (Session& s, AudioRegion& r, AudioRegionView& rv) + : RegionEditor (s), _region (r), _region_view (rv), name_label (_("NAME:")), diff --git a/gtk2_ardour/audio_region_editor.h b/gtk2_ardour/audio_region_editor.h new file mode 100644 index 0000000000..38cd920e5e --- /dev/null +++ b/gtk2_ardour/audio_region_editor.h @@ -0,0 +1,186 @@ +/* + Copyright (C) 2001 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __gtk_ardour_audio_region_edit_h__ +#define __gtk_ardour_audio_region_edit_h__ + +#include <map> + +#include <gtkmm/label.h> +#include <gtkmm/entry.h> +#include <gtkmm/box.h> +#include <gtkmm/togglebutton.h> +#include <gtkmm/button.h> +#include <gtkmm/arrow.h> +#include <gtkmm/frame.h> +#include <gtkmm/table.h> +#include <gtkmm/alignment.h> +#include <gtkmm/adjustment.h> +#include <gtkmm/separator.h> +#include <gtkmm/spinbutton.h> + +#include <libgnomecanvas/libgnomecanvas.h> +#include <sigc++/signal.h> + +#include "audio_clock.h" +#include "ardour_dialog.h" +#include "region_editor.h" + +namespace ARDOUR { + class AudioRegion; + class Session; +} + +class AudioRegionView; + +class AudioRegionEditor : public RegionEditor +{ + public: + AudioRegionEditor (ARDOUR::Session&, ARDOUR::AudioRegion&, AudioRegionView& rv); + ~AudioRegionEditor (); + + private: + ARDOUR::AudioRegion& _region; + AudioRegionView& _region_view; + + void connect_editor_events (); + + Gtk::Label name_label; + Gtk::Entry name_entry; + Gtk::HBox name_hbox; + + Gtk::HBox top_row_hbox; + Gtk::HBox top_row_button_hbox; + + Gtk::ToggleButton lock_button; + Gtk::ToggleButton mute_button; + Gtk::ToggleButton opaque_button; + Gtk::ToggleButton envelope_active_button; + Gtk::ToggleButton envelope_view_button; + + Gtk::Button raise_button; + Gtk::Arrow raise_arrow; + Gtk::Button lower_button; + Gtk::Arrow lower_arrow; + Gtk::Frame layer_frame; + Gtk::Label layer_value_label; + Gtk::Label layer_label; + Gtk::HBox layer_hbox; + + Gtk::ToggleButton audition_button; + + Gtk::HBox lower_hbox; + + Gtk::Table time_table; + + Gtk::Label start_label; + Gtk::Label end_label; + Gtk::Label length_label; + Gtk::Alignment start_alignment; + Gtk::Alignment end_alignment; + Gtk::Alignment length_alignment; + + AudioClock start_clock; + AudioClock end_clock; + AudioClock length_clock; + AudioClock sync_offset_clock; + + Gtk::Table envelope_loop_table; + Gtk::Button loop_button; + Gtk::Label loop_label; + Gtk::Label envelope_label; + + Gtk::Table fade_in_table; + Gtk::Label fade_in_label; + Gtk::Alignment fade_in_label_align; + Gtk::Label fade_in_active_button_label; + Gtk::ToggleButton fade_in_active_button; + Gtk::Label fade_in_length_label; + + Gtk::Adjustment fade_in_length_adjustment; + Gtk::SpinButton fade_in_length_spinner; + + Gtk::Table fade_out_table; + Gtk::Label fade_out_label; + Gtk::Alignment fade_out_label_align; + Gtk::Label fade_out_active_button_label; + Gtk::ToggleButton fade_out_active_button; + Gtk::Label fade_out_length_label; + + Gtk::Adjustment fade_out_length_adjustment; + Gtk::SpinButton fade_out_length_spinner; + + Gtk::HSeparator sep3; + Gtk::VSeparator sep1; + Gtk::VSeparator sep2; + + void region_changed (ARDOUR::Change); + void bounds_changed (ARDOUR::Change); + void name_changed (); + void opacity_changed (); + void mute_changed (); + void envelope_active_changed (); + void lock_changed (); + void layer_changed (); + + void fade_in_length_adjustment_changed (); + void fade_out_length_adjustment_changed (); + void fade_in_changed (); + void fade_out_changed (); + void audition_state_changed (bool); + + void activation (); + + void name_entry_changed (); + void start_clock_changed (); + void end_clock_changed (); + void length_clock_changed (); + + gint envelope_active_button_press (GdkEventButton *); + gint envelope_active_button_release (GdkEventButton *); + + void audition_button_toggled (); + void envelope_view_button_toggled (); + void lock_button_clicked (); + void mute_button_clicked (); + void opaque_button_clicked (); + void raise_button_clicked (); + void lower_button_clicked (); + + void fade_in_active_toggled (); + void fade_out_active_toggled (); + void fade_in_active_changed (); + void fade_out_active_changed (); + + void fade_in_realized (); + void fade_out_realized (); + + void start_editing_fade_in (); + void start_editing_fade_out (); + void stop_editing_fade_in (); + void stop_editing_fade_out (); + + gint bpressed (GdkEventButton* ev, Gtk::SpinButton* but, void (AudioRegionEditor::*pmf)()); + gint breleased (GdkEventButton* ev, Gtk::SpinButton* but, void (AudioRegionEditor::*pmf)()); + + bool spin_arrow_grab; +}; + +#endif /* __gtk_ardour_audio_region_edit_h__ */ diff --git a/gtk2_ardour/audio_regionview.cc b/gtk2_ardour/audio_regionview.cc new file mode 100644 index 0000000000..125654c35c --- /dev/null +++ b/gtk2_ardour/audio_regionview.cc @@ -0,0 +1,1351 @@ +/* + Copyright (C) 2001 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: regionview.cc 682 2006-07-14 03:43:32Z drobilla $ +*/ + +#include <cmath> +#include <algorithm> + +#include <gtkmm.h> + +#include <gtkmm2ext/gtk_ui.h> + +#include <ardour/playlist.h> +#include <ardour/audioregion.h> +#include <ardour/audiosource.h> +#include <ardour/audio_diskstream.h> + +#include "streamview.h" +#include "audio_regionview.h" +#include "audio_time_axis.h" +#include "simplerect.h" +#include "simpleline.h" +#include "waveview.h" +#include "public_editor.h" +#include "audio_region_editor.h" +#include "region_gain_line.h" +#include "ghostregion.h" +#include "audio_time_axis.h" +#include "utils.h" +#include "rgb_macros.h" +#include "gui_thread.h" + +#include "i18n.h" + +using namespace sigc; +using namespace ARDOUR; +using namespace PBD; +using namespace Editing; +using namespace ArdourCanvas; + +static const int32_t sync_mark_width = 9; + +AudioRegionView::AudioRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &tv, AudioRegion& r, double spu, + Gdk::Color& basic_color) + : RegionView (parent, tv, r, spu, basic_color) +{ +} + +AudioRegionView::AudioRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &tv, AudioRegion& r, double spu, + Gdk::Color& basic_color, TimeAxisViewItem::Visibility visibility) + : RegionView (parent, tv, r, spu, basic_color, visibility) +{ +} + +void +AudioRegionView::init (Gdk::Color& basic_color, bool wfw) +{ + ArdourCanvas::Points shape; + XMLNode *node; + + editor = 0; + valid = true; + in_destructor = false; + _amplitude_above_axis = 1.0; + zero_line = 0; + wait_for_waves = wfw; + _height = 0; + + _flags = 0; + + if ((node = _region.extra_xml ("GUI")) != 0) { + set_flags (node); + } else { + _flags = WaveformVisible; + store_flags (); + } + + if (trackview.editor.new_regionviews_display_gain()) { + _flags |= EnvelopeVisible; + } + + compute_colors (basic_color); + + create_waves (); + + name_highlight->set_data ("regionview", this); + name_text->set_data ("regionview", this); + + // shape = new ArdourCanvas::Points (); + + /* an equilateral triangle */ + + shape.push_back (Gnome::Art::Point (-((sync_mark_width-1)/2), 1)); + shape.push_back (Gnome::Art::Point ((sync_mark_width - 1)/2, 1)); + shape.push_back (Gnome::Art::Point (0, sync_mark_width - 1)); + shape.push_back (Gnome::Art::Point (-((sync_mark_width-1)/2), 1)); + + sync_mark = new ArdourCanvas::Polygon (*group); + sync_mark->property_points() = shape; + sync_mark->property_fill_color_rgba() = fill_color; + sync_mark->hide(); + + fade_in_shape = new ArdourCanvas::Polygon (*group); + fade_in_shape->property_fill_color_rgba() = fade_color; + fade_in_shape->set_data ("regionview", this); + + fade_out_shape = new ArdourCanvas::Polygon (*group); + fade_out_shape->property_fill_color_rgba() = fade_color; + fade_out_shape->set_data ("regionview", this); + + + { + uint32_t r,g,b,a; + UINT_TO_RGBA(fill_color,&r,&g,&b,&a); + + + fade_in_handle = new ArdourCanvas::SimpleRect (*group); + fade_in_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,0); + fade_in_handle->property_outline_pixels() = 0; + fade_in_handle->property_y1() = 2.0; + fade_in_handle->property_y2() = 7.0; + + fade_in_handle->set_data ("regionview", this); + + fade_out_handle = new ArdourCanvas::SimpleRect (*group); + fade_out_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,0); + fade_out_handle->property_outline_pixels() = 0; + fade_out_handle->property_y1() = 2.0; + fade_out_handle->property_y2() = 7.0; + + fade_out_handle->set_data ("regionview", this); + } + + string foo = _region.name(); + foo += ':'; + foo += "gain"; + + gain_line = new AudioRegionGainLine (foo, trackview.session(), *this, *group, audio_region().envelope()); + + if (!(_flags & EnvelopeVisible)) { + gain_line->hide (); + } else { + gain_line->show (); + } + + reset_width_dependent_items ((double) _region.length() / samples_per_unit); + + gain_line->reset (); + + set_height (trackview.height); + + region_muted (); + region_sync_changed (); + region_resized (BoundsChanged); + set_waveview_data_src(); + region_locked (); + envelope_active_changed (); + fade_in_active_changed (); + fade_out_active_changed (); + + _region.StateChanged.connect (mem_fun(*this, &AudioRegionView::region_changed)); + + group->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_region_view_event), group, this)); + name_highlight->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_region_view_name_highlight_event), name_highlight, this)); + fade_in_shape->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_in_event), fade_in_shape, this)); + fade_in_handle->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_in_handle_event), fade_in_handle, this)); + fade_out_shape->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_out_event), fade_out_shape, this)); + fade_out_handle->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_out_handle_event), fade_out_handle, this)); + + set_colors (); + + ColorChanged.connect (mem_fun (*this, &AudioRegionView::color_handler)); + + /* XXX sync mark drag? */ +} + +AudioRegionView::~AudioRegionView () +{ + in_destructor = true; + + RegionViewGoingAway (this); /* EMIT_SIGNAL */ + + for (vector<GnomeCanvasWaveViewCache *>::iterator cache = wave_caches.begin(); cache != wave_caches.end() ; ++cache) { + gnome_canvas_waveview_cache_destroy (*cache); + } + + /* all waveviews etc will be destroyed when the group is destroyed */ + + for (vector<GhostRegion*>::iterator g = ghosts.begin(); g != ghosts.end(); ++g) { + delete *g; + } + + if (editor) { + delete editor; + } + + if (gain_line) { + delete gain_line; + } +} + +ARDOUR::AudioRegion& +AudioRegionView::audio_region() const +{ + // Guaranteed to succeed + return dynamic_cast<AudioRegion&>(_region); +} + + +gint +AudioRegionView::_lock_toggle (ArdourCanvas::Item* item, GdkEvent* ev, void* arg) +{ + switch (ev->type) { + case GDK_BUTTON_RELEASE: + static_cast<AudioRegionView*>(arg)->lock_toggle (); + return TRUE; + break; + default: + break; + } + return FALSE; +} + +void +AudioRegionView::lock_toggle () +{ + _region.set_locked (!_region.locked()); +} + +void +AudioRegionView::region_changed (Change what_changed) +{ + ENSURE_GUI_THREAD (bind (mem_fun(*this, &AudioRegionView::region_changed), what_changed)); + + if (what_changed & BoundsChanged) { + region_resized (what_changed); + region_sync_changed (); + } + if (what_changed & Region::MuteChanged) { + region_muted (); + } + if (what_changed & Region::OpacityChanged) { + region_opacity (); + } + if (what_changed & ARDOUR::NameChanged) { + region_renamed (); + } + if (what_changed & Region::SyncOffsetChanged) { + region_sync_changed (); + } + if (what_changed & Region::LayerChanged) { + region_layered (); + } + if (what_changed & Region::LockChanged) { + region_locked (); + } + if (what_changed & AudioRegion::ScaleAmplitudeChanged) { + region_scale_amplitude_changed (); + } + if (what_changed & AudioRegion::FadeInChanged) { + fade_in_changed (); + } + if (what_changed & AudioRegion::FadeOutChanged) { + fade_out_changed (); + } + if (what_changed & AudioRegion::FadeInActiveChanged) { + fade_in_active_changed (); + } + if (what_changed & AudioRegion::FadeOutActiveChanged) { + fade_out_active_changed (); + } + if (what_changed & AudioRegion::EnvelopeActiveChanged) { + envelope_active_changed (); + } +} + +void +AudioRegionView::fade_in_changed () +{ + reset_fade_in_shape (); +} + +void +AudioRegionView::fade_out_changed () +{ + reset_fade_out_shape (); +} + +void +AudioRegionView::set_fade_in_active (bool yn) +{ + audio_region().set_fade_in_active (yn); +} + +void +AudioRegionView::set_fade_out_active (bool yn) +{ + audio_region().set_fade_out_active (yn); +} + +void +AudioRegionView::fade_in_active_changed () +{ + uint32_t r,g,b,a; + uint32_t col; + UINT_TO_RGBA(fade_color,&r,&g,&b,&a); + + if (audio_region().fade_in_active()) { + col = RGBA_TO_UINT(r,g,b,120); + fade_in_shape->property_fill_color_rgba() = col; + fade_in_shape->property_width_pixels() = 0; + fade_in_shape->property_outline_color_rgba() = RGBA_TO_UINT(r,g,b,0); + } else { + col = RGBA_TO_UINT(r,g,b,0); + fade_in_shape->property_fill_color_rgba() = col; + fade_in_shape->property_width_pixels() = 1; + fade_in_shape->property_outline_color_rgba() = RGBA_TO_UINT(r,g,b,255); + } +} + +void +AudioRegionView::fade_out_active_changed () +{ + uint32_t r,g,b,a; + uint32_t col; + UINT_TO_RGBA(fade_color,&r,&g,&b,&a); + + if (audio_region().fade_out_active()) { + col = RGBA_TO_UINT(r,g,b,120); + fade_out_shape->property_fill_color_rgba() = col; + fade_out_shape->property_width_pixels() = 0; + fade_out_shape->property_outline_color_rgba() = RGBA_TO_UINT(r,g,b,0); + } else { + col = RGBA_TO_UINT(r,g,b,0); + fade_out_shape->property_fill_color_rgba() = col; + fade_out_shape->property_width_pixels() = 1; + fade_out_shape->property_outline_color_rgba() = RGBA_TO_UINT(r,g,b,255); + } +} + + +void +AudioRegionView::region_scale_amplitude_changed () +{ + ENSURE_GUI_THREAD (mem_fun(*this, &AudioRegionView::region_scale_amplitude_changed)); + + for (uint32_t n = 0; n < waves.size(); ++n) { + // force a reload of the cache + waves[n]->property_data_src() = &_region; + } +} + +void +AudioRegionView::region_locked () +{ + /* name will show locked status */ + region_renamed (); +} + +void +AudioRegionView::region_resized (Change what_changed) +{ + double unit_length; + + if (what_changed & ARDOUR::PositionChanged) { + set_position (_region.position(), 0); + } + + if (what_changed & Change (StartChanged|LengthChanged)) { + + set_duration (_region.length(), 0); + + unit_length = _region.length() / samples_per_unit; + + reset_width_dependent_items (unit_length); + + for (uint32_t n = 0; n < waves.size(); ++n) { + waves[n]->property_region_start() = _region.start(); + } + + for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) { + + (*i)->set_duration (unit_length); + + for (vector<WaveView*>::iterator w = (*i)->waves.begin(); w != (*i)->waves.end(); ++w) { + (*w)->property_region_start() = _region.start(); + } + } + } +} + +void +AudioRegionView::reset_width_dependent_items (double pixel_width) +{ + TimeAxisViewItem::reset_width_dependent_items (pixel_width); + _pixel_width = pixel_width; + + if (zero_line) { + zero_line->property_x2() = pixel_width - 1.0; + } + + if (fade_in_handle) { + if (pixel_width <= 6.0) { + fade_in_handle->hide(); + fade_out_handle->hide(); + } else { + if (_height < 5.0) { + fade_in_handle->hide(); + fade_out_handle->hide(); + } else { + fade_in_handle->show(); + fade_out_handle->show(); + } + } + } + + reset_fade_shapes (); +} + +void +AudioRegionView::region_layered () +{ + RouteTimeAxisView *atv = dynamic_cast<RouteTimeAxisView*> (&get_time_axis_view()); + atv->view()->region_layered (this); +} + +void +AudioRegionView::region_muted () +{ + set_frame_color (); + region_renamed (); + + for (uint32_t n=0; n < waves.size(); ++n) { + if (_region.muted()) { + waves[n]->property_wave_color() = color_map[cMutedWaveForm]; + } else { + waves[n]->property_wave_color() = color_map[cWaveForm]; + } + } +} + + +void +AudioRegionView::set_height (gdouble height) +{ + uint32_t wcnt = waves.size(); + + TimeAxisViewItem::set_height (height - 2); + + _height = height; + + for (uint32_t n=0; n < wcnt; ++n) { + gdouble ht; + + if ((height) <= NAME_HIGHLIGHT_THRESH) { + ht = ((height-2*wcnt) / (double) wcnt); + } else { + ht = (((height-2*wcnt) - NAME_HIGHLIGHT_SIZE) / (double) wcnt); + } + + gdouble yoff = n * (ht+1); + + waves[n]->property_height() = ht; + waves[n]->property_y() = yoff + 2; + } + + if (gain_line) { + if ((height/wcnt) < NAME_HIGHLIGHT_SIZE) { + gain_line->hide (); + } else { + if (_flags & EnvelopeVisible) { + gain_line->show (); + } + } + gain_line->set_height ((uint32_t) rint (height - NAME_HIGHLIGHT_SIZE)); + } + + manage_zero_line (); + reset_fade_shapes (); + + if (name_text) { + name_text->raise_to_top(); + } +} + +void +AudioRegionView::manage_zero_line () +{ + if (!zero_line) { + return; + } + + if (_height >= 100) { + gdouble wave_midpoint = (_height - NAME_HIGHLIGHT_SIZE) / 2.0; + zero_line->property_y1() = wave_midpoint; + zero_line->property_y2() = wave_midpoint; + zero_line->show(); + } else { + zero_line->hide(); + } +} + +void +AudioRegionView::reset_fade_shapes () +{ + reset_fade_in_shape (); + reset_fade_out_shape (); +} + +void +AudioRegionView::reset_fade_in_shape () +{ + reset_fade_in_shape_width ((jack_nframes_t) audio_region().fade_in().back()->when); +} + +void +AudioRegionView::reset_fade_in_shape_width (jack_nframes_t width) +{ + if (fade_in_handle == 0) { + return; + } + + /* smallest size for a fade is 64 frames */ + + width = std::max ((jack_nframes_t) 64, width); + + Points* points; + double pwidth = width / samples_per_unit; + uint32_t npoints = std::min (gdk_screen_width(), (int) pwidth); + double h; + + if (_height < 5) { + fade_in_shape->hide(); + fade_in_handle->hide(); + return; + } + + double handle_center; + handle_center = pwidth; + + if (handle_center > 7.0) { + handle_center -= 3.0; + } else { + handle_center = 3.0; + } + + fade_in_handle->property_x1() = handle_center - 3.0; + fade_in_handle->property_x2() = handle_center + 3.0; + + if (pwidth < 5) { + fade_in_shape->hide(); + return; + } + + fade_in_shape->show(); + + float curve[npoints]; + audio_region().fade_in().get_vector (0, audio_region().fade_in().back()->when, curve, npoints); + + points = get_canvas_points ("fade in shape", npoints+3); + + if (_height > NAME_HIGHLIGHT_THRESH) { + h = _height - NAME_HIGHLIGHT_SIZE; + } else { + h = _height; + } + + /* points *MUST* be in anti-clockwise order */ + + uint32_t pi, pc; + double xdelta = pwidth/npoints; + + for (pi = 0, pc = 0; pc < npoints; ++pc) { + (*points)[pi].set_x(1 + (pc * xdelta)); + (*points)[pi++].set_y(2 + (h - (curve[pc] * h))); + } + + /* fold back */ + + (*points)[pi].set_x(pwidth); + (*points)[pi++].set_y(2); + + (*points)[pi].set_x(1); + (*points)[pi++].set_y(2); + + /* connect the dots ... */ + + (*points)[pi] = (*points)[0]; + + fade_in_shape->property_points() = *points; + delete points; +} + +void +AudioRegionView::reset_fade_out_shape () +{ + reset_fade_out_shape_width ((jack_nframes_t) audio_region().fade_out().back()->when); +} + +void +AudioRegionView::reset_fade_out_shape_width (jack_nframes_t width) +{ + if (fade_out_handle == 0) { + return; + } + + /* smallest size for a fade is 64 frames */ + + width = std::max ((jack_nframes_t) 64, width); + + Points* points; + double pwidth = width / samples_per_unit; + uint32_t npoints = std::min (gdk_screen_width(), (int) pwidth); + double h; + + if (_height < 5) { + fade_out_shape->hide(); + fade_out_handle->hide(); + return; + } + + double handle_center; + handle_center = (_region.length() - width) / samples_per_unit; + + if (handle_center > 7.0) { + handle_center -= 3.0; + } else { + handle_center = 3.0; + } + + fade_out_handle->property_x1() = handle_center - 3.0; + fade_out_handle->property_x2() = handle_center + 3.0; + + /* don't show shape if its too small */ + + if (pwidth < 5) { + fade_out_shape->hide(); + return; + } + + fade_out_shape->show(); + + float curve[npoints]; + audio_region().fade_out().get_vector (0, audio_region().fade_out().back()->when, curve, npoints); + + if (_height > NAME_HIGHLIGHT_THRESH) { + h = _height - NAME_HIGHLIGHT_SIZE; + } else { + h = _height; + } + + /* points *MUST* be in anti-clockwise order */ + + points = get_canvas_points ("fade out shape", npoints+3); + + uint32_t pi, pc; + double xdelta = pwidth/npoints; + + for (pi = 0, pc = 0; pc < npoints; ++pc) { + (*points)[pi].set_x(_pixel_width - 1 - pwidth + (pc*xdelta)); + (*points)[pi++].set_y(2 + (h - (curve[pc] * h))); + } + + /* fold back */ + + (*points)[pi].set_x(_pixel_width); + (*points)[pi++].set_y(h); + + (*points)[pi].set_x(_pixel_width); + (*points)[pi++].set_y(2); + + /* connect the dots ... */ + + (*points)[pi] = (*points)[0]; + + fade_out_shape->property_points() = *points; + delete points; +} + +void +AudioRegionView::set_samples_per_unit (gdouble spu) +{ + TimeAxisViewItem::set_samples_per_unit (spu); + + for (uint32_t n=0; n < waves.size(); ++n) { + waves[n]->property_samples_per_unit() = spu; + } + + for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) { + (*i)->set_samples_per_unit (spu); + (*i)->set_duration (_region.length() / samples_per_unit); + } + + if (gain_line) { + gain_line->reset (); + } + reset_fade_shapes (); + region_sync_changed (); +} + +bool +AudioRegionView::set_duration (jack_nframes_t frames, void *src) +{ + if (!TimeAxisViewItem::set_duration (frames, src)) { + return false; + } + + for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) { + (*i)->set_duration (_region.length() / samples_per_unit); + } + + return true; +} + +void +AudioRegionView::set_amplitude_above_axis (gdouble spp) +{ + for (uint32_t n=0; n < waves.size(); ++n) { + waves[n]->property_amplitude_above_axis() = spp; + } +} + +void +AudioRegionView::compute_colors (Gdk::Color& basic_color) +{ + TimeAxisViewItem::compute_colors (basic_color); + uint32_t r, g, b, a; + + /* gain color computed in envelope_active_changed() */ + + UINT_TO_RGBA (fill_color, &r, &g, &b, &a); + fade_color = RGBA_TO_UINT(r,g,b,120); +} + +void +AudioRegionView::set_colors () +{ + TimeAxisViewItem::set_colors (); + + if (gain_line) { + gain_line->set_line_color (audio_region().envelope_active() ? color_map[cGainLine] : color_map[cGainLineInactive]); + } + + if (sync_mark) { + sync_mark->property_fill_color_rgba() = fill_color; + } + + for (uint32_t n=0; n < waves.size(); ++n) { + if (_region.muted()) { + waves[n]->property_wave_color() = color_map[cMutedWaveForm]; + } else { + waves[n]->property_wave_color() = color_map[cWaveForm]; + } + } +} + +void +AudioRegionView::set_frame_color () +{ + if (_region.opaque()) { + fill_opacity = 180; + } else { + fill_opacity = 100; + } + + TimeAxisViewItem::set_frame_color (); +} + +void +AudioRegionView::show_region_editor () +{ + if (editor == 0) { + editor = new AudioRegionEditor (trackview.session(), audio_region(), *this); + // GTK2FIX : how to ensure float without realizing + // editor->realize (); + // trackview.editor.ensure_float (*editor); + } + + editor->show_all (); + editor->get_window()->raise(); +} + +void +AudioRegionView::hide_region_editor() +{ + if (editor) { + editor->hide_all (); + } +} + +void +AudioRegionView::region_renamed () +{ + string str; + + if (_region.locked()) { + str += '>'; + str += _region.name(); + str += '<'; + } else { + str = _region.name(); + } + + if (audio_region().speed_mismatch (trackview.session().frame_rate())) { + str = string ("*") + str; + } + + if (_region.muted()) { + str = string ("!") + str; + } + + set_item_name (str, this); + set_name_text (str); +} + +void +AudioRegionView::region_sync_changed () +{ + if (sync_mark == 0) { + return; + } + + int sync_dir; + jack_nframes_t sync_offset; + + sync_offset = _region.sync_offset (sync_dir); + + /* this has to handle both a genuine change of position, a change of samples_per_unit, + and a change in the bounds of the _region. + */ + + if (sync_offset == 0) { + + /* no sync mark - its the start of the region */ + + sync_mark->hide(); + + } else { + + if ((sync_dir < 0) || ((sync_dir > 0) && (sync_offset > _region.length()))) { + + /* no sync mark - its out of the bounds of the region */ + + sync_mark->hide(); + + } else { + + /* lets do it */ + + Points points; + + //points = sync_mark->property_points().get_value(); + + double offset = sync_offset / samples_per_unit; + points.push_back (Gnome::Art::Point (offset - ((sync_mark_width-1)/2), 1)); + points.push_back (Gnome::Art::Point (offset + ((sync_mark_width-1)/2), 1)); + points.push_back (Gnome::Art::Point (offset, sync_mark_width - 1)); + points.push_back (Gnome::Art::Point (offset - ((sync_mark_width-1)/2), 1)); + sync_mark->property_points().set_value (points); + sync_mark->show(); + + } + } +} + +void +AudioRegionView::set_waveform_visible (bool yn) +{ + if (((_flags & WaveformVisible) != yn)) { + if (yn) { + for (uint32_t n=0; n < waves.size(); ++n) { + waves[n]->show(); + } + _flags |= WaveformVisible; + } else { + for (uint32_t n=0; n < waves.size(); ++n) { + waves[n]->hide(); + } + _flags &= ~WaveformVisible; + } + store_flags (); + } +} + +void +AudioRegionView::temporarily_hide_envelope () +{ + if (gain_line) { + gain_line->hide (); + } +} + +void +AudioRegionView::unhide_envelope () +{ + if (gain_line && (_flags & EnvelopeVisible)) { + gain_line->show (); + } +} + +void +AudioRegionView::set_envelope_visible (bool yn) +{ + if (gain_line && ((_flags & EnvelopeVisible) != yn)) { + if (yn) { + gain_line->show (); + _flags |= EnvelopeVisible; + } else { + gain_line->hide (); + _flags &= ~EnvelopeVisible; + } + store_flags (); + } +} + +void +AudioRegionView::create_waves () +{ + bool create_zero_line = true; + + RouteTimeAxisView& atv (*(dynamic_cast<RouteTimeAxisView*>(&trackview))); // ick + + if (!atv.get_diskstream()) { + return; + } + + uint32_t nchans = atv.get_diskstream()->n_channels(); + + /* in tmp_waves, set up null pointers for each channel so the vector is allocated */ + for (uint32_t n = 0; n < nchans; ++n) { + tmp_waves.push_back (0); + } + + for (uint32_t n = 0; n < nchans; ++n) { + + if (n >= audio_region().n_channels()) { + break; + } + + wave_caches.push_back (WaveView::create_cache ()); + + if (wait_for_waves) { + if (audio_region().source(n).peaks_ready (bind (mem_fun(*this, &AudioRegionView::peaks_ready_handler), n), peaks_ready_connection)) { + create_one_wave (n, true); + } else { + create_zero_line = false; + } + } else { + create_one_wave (n, true); + } + } + + if (create_zero_line) { + zero_line = new ArdourCanvas::SimpleLine (*group); + zero_line->property_x1() = (gdouble) 1.0; + zero_line->property_x2() = (gdouble) (_region.length() / samples_per_unit) - 1.0; + zero_line->property_color_rgba() = (guint) color_map[cZeroLine]; + manage_zero_line (); + } +} + +void +AudioRegionView::create_one_wave (uint32_t which, bool direct) +{ + RouteTimeAxisView& atv (*(dynamic_cast<RouteTimeAxisView*>(&trackview))); // ick + uint32_t nchans = atv.get_diskstream()->n_channels(); + uint32_t n; + uint32_t nwaves = std::min (nchans, audio_region().n_channels()); + gdouble ht; + + if (trackview.height < NAME_HIGHLIGHT_SIZE) { + ht = ((trackview.height) / (double) nchans); + } else { + ht = ((trackview.height - NAME_HIGHLIGHT_SIZE) / (double) nchans); + } + + gdouble yoff = which * ht; + + WaveView *wave = new WaveView(*group); + + wave->property_data_src() = (gpointer) &_region; + wave->property_cache() = wave_caches[which]; + wave->property_cache_updater() = true; + wave->property_channel() = which; + wave->property_length_function() = (gpointer) region_length_from_c; + wave->property_sourcefile_length_function() = (gpointer) sourcefile_length_from_c; + wave->property_peak_function() = (gpointer) region_read_peaks_from_c; + wave->property_x() = 0.0; + wave->property_y() = yoff; + wave->property_height() = (double) ht; + wave->property_samples_per_unit() = samples_per_unit; + wave->property_amplitude_above_axis() = _amplitude_above_axis; + wave->property_wave_color() = _region.muted() ? color_map[cMutedWaveForm] : color_map[cWaveForm]; + wave->property_region_start() = _region.start(); + + if (!(_flags & WaveformVisible)) { + wave->hide(); + } + + /* note: calling this function is serialized by the lock + held in the peak building thread that signals that + peaks are ready for use *or* by the fact that it is + called one by one from the GUI thread. + */ + + if (which < nchans) { + tmp_waves[which] = wave; + } else { + /* n-channel track, >n-channel source */ + } + + /* see if we're all ready */ + + for (n = 0; n < nchans; ++n) { + if (tmp_waves[n] == 0) { + break; + } + } + + if (n == nwaves && waves.empty()) { + /* all waves are ready */ + tmp_waves.resize(nwaves); + + waves = tmp_waves; + tmp_waves.clear (); + + if (!zero_line) { + zero_line = new ArdourCanvas::SimpleLine (*group); + zero_line->property_x1() = (gdouble) 1.0; + zero_line->property_x2() = (gdouble) (_region.length() / samples_per_unit) - 1.0; + zero_line->property_color_rgba() = (guint) color_map[cZeroLine]; + manage_zero_line (); + } + } +} + +void +AudioRegionView::peaks_ready_handler (uint32_t which) +{ + Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &AudioRegionView::create_one_wave), which, false)); + + if (!waves.empty()) { + /* all waves created, don't hook into peaks ready anymore */ + peaks_ready_connection.disconnect (); + } +} + +void +AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev) +{ + if (gain_line == 0) { + return; + } + + double x, y; + + /* don't create points that can't be seen */ + + set_envelope_visible (true); + + x = ev->button.x; + y = ev->button.y; + + item->w2i (x, y); + + jack_nframes_t fx = trackview.editor.pixel_to_frame (x); + + if (fx > _region.length()) { + return; + } + + /* compute vertical fractional position */ + + y = 1.0 - (y / (trackview.height - NAME_HIGHLIGHT_SIZE)); + + /* map using gain line */ + + gain_line->view_to_model_y (y); + + trackview.session().begin_reversible_command (_("add gain control point")); + trackview.session().add_undo (audio_region().envelope().get_memento()); + + + if (!audio_region().envelope_active()) { + trackview.session().add_undo( bind( mem_fun(audio_region(), &AudioRegion::set_envelope_active), false) ); + audio_region().set_envelope_active(true); + trackview.session().add_redo( bind( mem_fun(audio_region(), &AudioRegion::set_envelope_active), true) ); + } + + audio_region().envelope().add (fx, y); + + trackview.session().add_redo_no_execute (audio_region().envelope().get_memento()); + trackview.session().commit_reversible_command (); +} + +void +AudioRegionView::remove_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev) +{ + ControlPoint *cp = reinterpret_cast<ControlPoint *> (item->get_data ("control_point")); + audio_region().envelope().erase (cp->model); +} + +void +AudioRegionView::store_flags() +{ + XMLNode *node = new XMLNode ("GUI"); + + node->add_property ("waveform-visible", (_flags & WaveformVisible) ? "yes" : "no"); + node->add_property ("envelope-visible", (_flags & EnvelopeVisible) ? "yes" : "no"); + + _region.add_extra_xml (*node); +} + +void +AudioRegionView::set_flags (XMLNode* node) +{ + XMLProperty *prop; + + if ((prop = node->property ("waveform-visible")) != 0) { + if (prop->value() == "yes") { + _flags |= WaveformVisible; + } + } + + if ((prop = node->property ("envelope-visible")) != 0) { + if (prop->value() == "yes") { + _flags |= EnvelopeVisible; + } + } +} + +void +AudioRegionView::set_waveform_shape (WaveformShape shape) +{ + bool yn; + + /* this slightly odd approach is to leave the door open to + other "shapes" such as spectral displays, etc. + */ + + switch (shape) { + case Rectified: + yn = true; + break; + + default: + yn = false; + break; + } + + if (yn != (bool) (_flags & WaveformRectified)) { + for (vector<WaveView *>::iterator wave = waves.begin(); wave != waves.end() ; ++wave) { + (*wave)->property_rectified() = yn; + } + + if (zero_line) { + if (yn) { + zero_line->hide(); + } else { + zero_line->show(); + } + } + + if (yn) { + _flags |= WaveformRectified; + } else { + _flags &= ~WaveformRectified; + } + } +} + +void +AudioRegionView::move (double x_delta, double y_delta) +{ + if (_region.locked() || (x_delta == 0 && y_delta == 0)) { + return; + } + + get_canvas_group()->move (x_delta, y_delta); + + /* note: ghosts never leave their tracks so y_delta for them is always zero */ + + for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) { + (*i)->group->move (x_delta, 0.0); + } +} + +GhostRegion* +AudioRegionView::add_ghost (AutomationTimeAxisView& atv) +{ + RouteTimeAxisView& myatv (*(dynamic_cast<RouteTimeAxisView*>(&trackview))); // ick + double unit_position = _region.position () / samples_per_unit; + GhostRegion* ghost = new GhostRegion (atv, unit_position); + uint32_t nchans; + + nchans = myatv.get_diskstream()->n_channels(); + + for (uint32_t n = 0; n < nchans; ++n) { + + if (n >= audio_region().n_channels()) { + break; + } + + WaveView *wave = new WaveView(*ghost->group); + + wave->property_data_src() = &_region; + wave->property_cache() = wave_caches[n]; + wave->property_cache_updater() = false; + wave->property_channel() = n; + wave->property_length_function() = (gpointer)region_length_from_c; + wave->property_sourcefile_length_function() = (gpointer) sourcefile_length_from_c; + wave->property_peak_function() = (gpointer) region_read_peaks_from_c; + wave->property_x() = 0.0; + wave->property_samples_per_unit() = samples_per_unit; + wave->property_amplitude_above_axis() = _amplitude_above_axis; + wave->property_wave_color() = color_map[cGhostTrackWave]; + wave->property_region_start() = _region.start(); + + ghost->waves.push_back(wave); + } + + ghost->set_height (); + ghost->set_duration (_region.length() / samples_per_unit); + ghosts.push_back (ghost); + + ghost->GoingAway.connect (mem_fun(*this, &AudioRegionView::remove_ghost)); + + return ghost; +} + +void +AudioRegionView::remove_ghost (GhostRegion* ghost) +{ + if (in_destructor) { + return; + } + + for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) { + if (*i == ghost) { + ghosts.erase (i); + break; + } + } +} + +void +AudioRegionView::entered () +{ + if (gain_line && _flags & EnvelopeVisible) { + gain_line->show_all_control_points (); + } + + uint32_t r,g,b,a; + UINT_TO_RGBA(fade_color,&r,&g,&b,&a); + a=255; + + if (fade_in_handle) { + fade_in_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,a); + fade_out_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,a); + } +} + +void +AudioRegionView::exited () +{ + if (gain_line) { + gain_line->hide_all_but_selected_control_points (); + } + + uint32_t r,g,b,a; + UINT_TO_RGBA(fade_color,&r,&g,&b,&a); + a=0; + + if (fade_in_handle) { + fade_in_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,a); + fade_out_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,a); + } +} + +void +AudioRegionView::envelope_active_changed () +{ + if (gain_line) { + gain_line->set_line_color (audio_region().envelope_active() ? color_map[cGainLine] : color_map[cGainLineInactive]); + } +} + +void +AudioRegionView::set_waveview_data_src() +{ + + double unit_length= _region.length() / samples_per_unit; + + for (uint32_t n = 0; n < waves.size(); ++n) { + // TODO: something else to let it know the channel + waves[n]->property_data_src() = &_region; + } + + for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) { + + (*i)->set_duration (unit_length); + + for (vector<WaveView*>::iterator w = (*i)->waves.begin(); w != (*i)->waves.end(); ++w) { + (*w)->property_data_src() = &_region; + } + } + +} + +void +AudioRegionView::color_handler (ColorID id, uint32_t val) +{ + switch (id) { + case cMutedWaveForm: + case cWaveForm: + set_colors (); + break; + + case cGainLineInactive: + case cGainLine: + envelope_active_changed(); + break; + + case cZeroLine: + if (zero_line) { + zero_line->property_color_rgba() = (guint) color_map[cZeroLine]; + } + break; + + case cGhostTrackWave: + break; + + default: + break; + } +} diff --git a/gtk2_ardour/audio_regionview.h b/gtk2_ardour/audio_regionview.h new file mode 100644 index 0000000000..7889f0c8b5 --- /dev/null +++ b/gtk2_ardour/audio_regionview.h @@ -0,0 +1,194 @@ +/* + Copyright (C) 2001-2006 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __gtk_ardour_audio_region_view_h__ +#define __gtk_ardour_audio_region_view_h__ + +#include <vector> + +#include <libgnomecanvasmm.h> +#include <libgnomecanvasmm/polygon.h> +#include <sigc++/signal.h> +#include <ardour/region.h> + +#include "regionview.h" +#include "route_time_axis.h" +#include "time_axis_view_item.h" +#include "automation_line.h" +#include "enums.h" +#include "waveview.h" +#include "canvas.h" +#include "color.h" + +namespace ARDOUR { + class AudioRegion; + class PeakData; +}; + +class AudioTimeAxisView; +class AudioRegionGainLine; +class AudioRegionEditor; +class GhostRegion; +class AutomationTimeAxisView; + +class AudioRegionView : public RegionView +{ + public: + AudioRegionView (ArdourCanvas::Group *, + RouteTimeAxisView&, + ARDOUR::AudioRegion&, + double initial_samples_per_unit, + Gdk::Color& basic_color); + + ~AudioRegionView (); + + virtual void init (Gdk::Color& base_color, bool wait_for_waves); + + ARDOUR::AudioRegion& audio_region() const; + + bool is_valid() const { return valid; } + void set_valid (bool yn) { valid = yn; } + + void set_height (double); + void set_samples_per_unit (double); + bool set_duration (jack_nframes_t, void*); + + void set_amplitude_above_axis (gdouble spp); + + void move (double xdelta, double ydelta); + + void temporarily_hide_envelope (); ///< Dangerous! + void unhide_envelope (); ///< Dangerous! + + void set_envelope_visible (bool); + void set_waveform_visible (bool yn); + void set_waveform_shape (WaveformShape); + + bool waveform_rectified() const { return _flags & WaveformRectified; } + bool waveform_visible() const { return _flags & WaveformVisible; } + bool envelope_visible() const { return _flags & EnvelopeVisible; } + + void show_region_editor (); + void hide_region_editor(); + + void add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *event); + void remove_gain_point_event (ArdourCanvas::Item *item, GdkEvent *event); + + AudioRegionGainLine* get_gain_line() const { return gain_line; } + + void region_changed (ARDOUR::Change); + void envelope_active_changed (); + + GhostRegion* add_ghost (AutomationTimeAxisView&); + void remove_ghost (GhostRegion*); + + void reset_fade_in_shape_width (jack_nframes_t); + void reset_fade_out_shape_width (jack_nframes_t); + void set_fade_in_active (bool); + void set_fade_out_active (bool); + + virtual void entered (); + virtual void exited (); + + protected: + + /* this constructor allows derived types + to specify their visibility requirements + to the TimeAxisViewItem parent class + */ + + AudioRegionView (ArdourCanvas::Group *, + RouteTimeAxisView&, + ARDOUR::AudioRegion&, + double initial_samples_per_unit, + Gdk::Color& basic_color, + TimeAxisViewItem::Visibility); + + enum Flags { + EnvelopeVisible = 0x1, + WaveformVisible = 0x4, + WaveformRectified = 0x8 + }; + + vector<ArdourCanvas::WaveView *> waves; ///< waveviews + vector<ArdourCanvas::WaveView *> tmp_waves; ///< see ::create_waves() + ArdourCanvas::Polygon* sync_mark; ///< polgyon for sync position + ArdourCanvas::Text* no_wave_msg; ///< text + ArdourCanvas::SimpleLine* zero_line; ///< simpleline + ArdourCanvas::Polygon* fade_in_shape; ///< polygon + ArdourCanvas::Polygon* fade_out_shape; ///< polygon + ArdourCanvas::SimpleRect* fade_in_handle; ///< simplerect + ArdourCanvas::SimpleRect* fade_out_handle; ///< simplerect + + AudioRegionGainLine * gain_line; + AudioRegionEditor * editor; + + vector<ControlPoint *> control_points; + double _amplitude_above_axis; + double current_visible_sync_position; + + uint32_t _flags; + uint32_t fade_color; + bool valid; /* see StreamView::redisplay_diskstream() */ + double _pixel_width; + double _height; + bool in_destructor; + bool wait_for_waves; + sigc::connection peaks_ready_connection; + + void reset_fade_shapes (); + void reset_fade_in_shape (); + void reset_fade_out_shape (); + void fade_in_changed (); + void fade_out_changed (); + void fade_in_active_changed (); + void fade_out_active_changed (); + + void region_resized (ARDOUR::Change); + void region_moved (void *); + void region_muted (); + void region_locked (); + void region_layered (); + void region_renamed (); + void region_sync_changed (); + void region_scale_amplitude_changed (); + + static gint _lock_toggle (ArdourCanvas::Item*, GdkEvent*, void*); + void lock_toggle (); + + void create_waves (); + void create_one_wave (uint32_t, bool); + void manage_zero_line (); + void peaks_ready_handler (uint32_t); + void reset_name (gdouble width); + void set_flags (XMLNode *); + void store_flags (); + + void set_colors (); + void compute_colors (Gdk::Color&); + virtual void set_frame_color (); + void reset_width_dependent_items (double pixel_width); + void set_waveview_data_src(); + + vector<GnomeCanvasWaveViewCache*> wave_caches; + vector<GhostRegion*> ghosts; + + void color_handler (ColorID, uint32_t); +}; + +#endif /* __gtk_ardour_audio_region_view_h__ */ diff --git a/gtk2_ardour/audio_streamview.cc b/gtk2_ardour/audio_streamview.cc new file mode 100644 index 0000000000..1e43f1dac1 --- /dev/null +++ b/gtk2_ardour/audio_streamview.cc @@ -0,0 +1,727 @@ +/* + Copyright (C) 2001, 2006 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <cmath> +#include <cassert> + +#include <gtkmm.h> + +#include <gtkmm2ext/gtk_ui.h> + +#include <ardour/audioplaylist.h> +#include <ardour/audioregion.h> +#include <ardour/audiosource.h> +#include <ardour/audio_diskstream.h> +#include <ardour/audio_track.h> +#include <ardour/playlist_templates.h> +#include <ardour/source.h> + +#include "audio_streamview.h" +#include "audio_regionview.h" +#include "taperegionview.h" +#include "audio_time_axis.h" +#include "canvas-waveview.h" +#include "canvas-simplerect.h" +#include "region_selection.h" +#include "selection.h" +#include "public_editor.h" +#include "ardour_ui.h" +#include "crossfade_view.h" +#include "rgb_macros.h" +#include "gui_thread.h" +#include "utils.h" +#include "color.h" + +using namespace ARDOUR; +using namespace PBD; +using namespace Editing; + +AudioStreamView::AudioStreamView (AudioTimeAxisView& tv) + : StreamView (tv) +{ + region_color = _trackview.color(); + crossfades_visible = true; + + if (tv.is_audio_track()) + stream_base_color = color_map[cAudioTrackBase]; + else + stream_base_color = color_map[cAudioBusBase]; + + /* set_position() will position the group */ + + canvas_group = new ArdourCanvas::Group(*_trackview.canvas_display); + + canvas_rect = new ArdourCanvas::SimpleRect (*canvas_group); + canvas_rect->property_x1() = 0.0; + canvas_rect->property_y1() = 0.0; + canvas_rect->property_x2() = 1000000.0; + canvas_rect->property_y2() = (double) tv.height; + canvas_rect->property_outline_color_rgba() = color_map[cAudioTrackOutline]; + canvas_rect->property_outline_what() = (guint32) (0x1|0x2|0x8); // outline ends and bottom + canvas_rect->property_fill_color_rgba() = stream_base_color; + + canvas_rect->signal_event().connect (bind (mem_fun (_trackview.editor, &PublicEditor::canvas_stream_view_event), canvas_rect, &_trackview)); + + _samples_per_unit = _trackview.editor.get_current_zoom(); + _amplitude_above_axis = 1.0; + + if (_trackview.is_audio_track()) { + _trackview.audio_track()->DiskstreamChanged.connect (mem_fun (*this, &AudioStreamView::diskstream_changed)); + _trackview.session().TransportStateChange.connect (mem_fun (*this, &AudioStreamView::transport_changed)); + _trackview.get_diskstream()->RecordEnableChanged.connect (mem_fun (*this, &AudioStreamView::rec_enable_changed)); + _trackview.session().RecordStateChanged.connect (mem_fun (*this, &AudioStreamView::sess_rec_enable_changed)); + } + + rec_updating = false; + rec_active = false; + use_rec_regions = tv.editor.show_waveforms_recording (); + last_rec_peak_frame = 0; + + ColorChanged.connect (mem_fun (*this, &AudioStreamView::color_handler)); +} + +AudioStreamView::~AudioStreamView () +{ + undisplay_diskstream (); + delete canvas_group; +} + +int +AudioStreamView::set_height (gdouble h) +{ + /* limit the values to something sane-ish */ + if (h < 10.0 || h > 1000.0) { + return -1; + } + + StreamView::set_height(h); + + for (CrossfadeViewList::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) { + (*i)->set_height (h); + } + + return 0; +} + +int +AudioStreamView::set_samples_per_unit (gdouble spp) +{ + StreamView::set_samples_per_unit(spp); + + for (CrossfadeViewList::iterator xi = crossfade_views.begin(); xi != crossfade_views.end(); ++xi) { + (*xi)->set_samples_per_unit (spp); + } + + return 0; +} + +int +AudioStreamView::set_amplitude_above_axis (gdouble app) + +{ + RegionViewList::iterator i; + + if (app < 1.0) { + return -1; + } + + _amplitude_above_axis = app; + + for (i = region_views.begin(); i != region_views.end(); ++i) { + AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i); + if (arv) + arv->set_amplitude_above_axis (app); + } + + return 0; +} + +void +AudioStreamView::add_region_view_internal (Region *r, bool wait_for_waves) +{ + ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::add_region_view), r)); + + AudioRegion* region = dynamic_cast<AudioRegion*> (r); + + if (region == 0) { + return; + } + + AudioRegionView *region_view; + list<RegionView *>::iterator i; + + for (i = region_views.begin(); i != region_views.end(); ++i) { + if (&(*i)->region() == r) { + + /* great. we already have a AudioRegionView for this Region. use it again. */ + + (*i)->set_valid (true); + return; + } + } + + switch (_trackview.audio_track()->mode()) { + case Normal: + region_view = new AudioRegionView (canvas_group, _trackview, *region, + _samples_per_unit, region_color); + break; + case Destructive: + region_view = new TapeAudioRegionView (canvas_group, _trackview, *region, + _samples_per_unit, region_color); + break; + } + + region_view->init (region_color, wait_for_waves); + region_view->set_amplitude_above_axis(_amplitude_above_axis); + region_views.push_front (region_view); + + /* follow global waveform setting */ + + region_view->set_waveform_visible(_trackview.editor.show_waveforms()); + + /* catch regionview going away */ + + region->GoingAway.connect (mem_fun (*this, &AudioStreamView::remove_region_view)); + + RegionViewAdded (region_view); +} + +void +AudioStreamView::remove_region_view (Region *r) +{ + ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::remove_region_view), r)); + + StreamView::remove_region_view(r); + + for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end();) { + list<CrossfadeView*>::iterator tmp; + + tmp = i; + ++tmp; + + AudioRegion* ar = dynamic_cast<AudioRegion*>(r); + if (ar && (*i)->crossfade.involves (*ar)) { + delete *i; + crossfade_views.erase (i); + } + + i = tmp; + } +} + +void +AudioStreamView::undisplay_diskstream () +{ + StreamView::undisplay_diskstream(); + + for (CrossfadeViewList::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) { + delete *i; + } + + crossfade_views.clear (); +} + +void +AudioStreamView::playlist_modified () +{ + ENSURE_GUI_THREAD (mem_fun (*this, &AudioStreamView::playlist_modified)); + + StreamView::playlist_modified(); + + /* if the playlist is modified, make sure xfades are on top and all the regionviews are stacked + correctly. + */ + + for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) { + (*i)->get_canvas_group()->raise_to_top(); + } +} + +void +AudioStreamView::playlist_changed (Diskstream *ds) +{ + ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::playlist_changed), ds)); + + StreamView::playlist_changed(ds); + + AudioPlaylist* apl = dynamic_cast<AudioPlaylist*>(ds->playlist()); + if (apl) + playlist_connections.push_back (apl->NewCrossfade.connect (mem_fun (*this, &AudioStreamView::add_crossfade))); +} + +void +AudioStreamView::add_crossfade (Crossfade *crossfade) +{ + AudioRegionView* lview = 0; + AudioRegionView* rview = 0; + + ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::add_crossfade), crossfade)); + + /* first see if we already have a CrossfadeView for this Crossfade */ + + for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) { + if (&(*i)->crossfade == crossfade) { + if (!crossfades_visible) { + (*i)->hide(); + } else { + (*i)->show (); + } + (*i)->set_valid (true); + return; + } + } + + /* create a new one */ + + for (list<RegionView *>::iterator i = region_views.begin(); i != region_views.end(); ++i) { + AudioRegionView* arv = dynamic_cast<AudioRegionView*>(*i); + + if (!lview && arv && &(arv->region()) == &crossfade->out()) { + lview = arv; + } + if (!rview && arv && &(arv->region()) == &crossfade->in()) { + rview = arv; + } + } + + CrossfadeView *cv = new CrossfadeView (_trackview.canvas_display, + _trackview, + *crossfade, + _samples_per_unit, + region_color, + *lview, *rview); + + crossfade->Invalidated.connect (mem_fun (*this, &AudioStreamView::remove_crossfade)); + crossfade_views.push_back (cv); + + if (!crossfades_visible) { + cv->hide (); + } +} + +void +AudioStreamView::remove_crossfade (Crossfade *xfade) +{ + ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::remove_crossfade), xfade)); + + for (list<CrossfadeView*>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) { + if (&(*i)->crossfade == xfade) { + delete *i; + crossfade_views.erase (i); + break; + } + } +} + +void +AudioStreamView::redisplay_diskstream () +{ + list<RegionView *>::iterator i, tmp; + list<CrossfadeView*>::iterator xi, tmpx; + + + for (i = region_views.begin(); i != region_views.end(); ++i) { + (*i)->set_valid (false); + } + + for (xi = crossfade_views.begin(); xi != crossfade_views.end(); ++xi) { + (*xi)->set_valid (false); + if ((*xi)->visible()) { + (*xi)->show (); + } + } + + if (_trackview.is_audio_track()) { + _trackview.get_diskstream()->playlist()->foreach_region (static_cast<StreamView*>(this), &StreamView::add_region_view); + AudioPlaylist* apl = dynamic_cast<AudioPlaylist*>(_trackview.get_diskstream()->playlist()); + if (apl) + apl->foreach_crossfade (this, &AudioStreamView::add_crossfade); + } + + for (i = region_views.begin(); i != region_views.end(); ) { + tmp = i; + tmp++; + + if (!(*i)->is_valid()) { + delete *i; + region_views.erase (i); + } + + i = tmp; + } + + for (xi = crossfade_views.begin(); xi != crossfade_views.end();) { + tmpx = xi; + tmpx++; + + if (!(*xi)->valid()) { + delete *xi; + crossfade_views.erase (xi); + } + + xi = tmpx; + } + + /* now fix layering */ + + playlist_modified (); +} + +void +AudioStreamView::set_show_waveforms (bool yn) +{ + for (list<RegionView *>::iterator i = region_views.begin(); i != region_views.end(); ++i) { + AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i); + if (arv) + arv->set_waveform_visible (yn); + } +} + +void +AudioStreamView::set_waveform_shape (WaveformShape shape) +{ + for (RegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) { + AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i); + if (arv) + arv->set_waveform_shape (shape); + } +} + +void +AudioStreamView::setup_rec_box () +{ + // cerr << _trackview.name() << " streamview SRB\n"; + + if (_trackview.session().transport_rolling()) { + + // cerr << "\trolling\n"; + + if (!rec_active && + _trackview.session().record_status() == Session::Recording && + _trackview.get_diskstream()->record_enabled()) { + + if (_trackview.audio_track()->mode() == Normal && use_rec_regions && rec_regions.size() == rec_rects.size()) { + + /* add a new region, but don't bother if they set use_rec_regions mid-record */ + + AudioRegion::SourceList sources; + + for (list<sigc::connection>::iterator prc = peak_ready_connections.begin(); prc != peak_ready_connections.end(); ++prc) { + (*prc).disconnect(); + } + peak_ready_connections.clear(); + + // FIXME + AudioDiskstream* ads = dynamic_cast<AudioDiskstream*>(_trackview.get_diskstream()); + assert(ads); + + for (uint32_t n=0; n < ads->n_channels(); ++n) { + AudioSource *src = (AudioSource *) ads->write_source (n); + if (src) { + sources.push_back (src); + peak_ready_connections.push_back (src->PeakRangeReady.connect (bind (mem_fun (*this, &AudioStreamView::rec_peak_range_ready), src))); + } + } + + // handle multi + + jack_nframes_t start = 0; + if (rec_regions.size() > 0) { + start = rec_regions.back()->start() + _trackview.get_diskstream()->get_captured_frames(rec_regions.size()-1); + } + + AudioRegion * region = new AudioRegion(sources, start, 1 , "", 0, (Region::Flag)(Region::DefaultFlags | Region::DoNotSaveState), false); + region->set_position (_trackview.session().transport_frame(), this); + rec_regions.push_back (region); + /* catch it if it goes away */ + region->GoingAway.connect (mem_fun (*this, &AudioStreamView::remove_rec_region)); + + /* we add the region later */ + } + + /* start a new rec box */ + + AudioTrack* at; + + at = _trackview.audio_track(); /* we know what it is already */ + AudioDiskstream& ds = at->audio_diskstream(); + jack_nframes_t frame_pos = ds.current_capture_start (); + gdouble xstart = _trackview.editor.frame_to_pixel (frame_pos); + gdouble xend; + uint32_t fill_color; + + switch (_trackview.audio_track()->mode()) { + case Normal: + xend = xstart; + fill_color = color_map[cRecordingRectFill]; + break; + + case Destructive: + xend = xstart + 2; + fill_color = color_map[cRecordingRectFill]; + /* make the recording rect translucent to allow + the user to see the peak data coming in, etc. + */ + fill_color = UINT_RGBA_CHANGE_A (fill_color, 120); + break; + } + + ArdourCanvas::SimpleRect * rec_rect = new Gnome::Canvas::SimpleRect (*canvas_group); + rec_rect->property_x1() = xstart; + rec_rect->property_y1() = 1.0; + rec_rect->property_x2() = xend; + rec_rect->property_y2() = (double) _trackview.height - 1; + rec_rect->property_outline_color_rgba() = color_map[cRecordingRectOutline]; + rec_rect->property_fill_color_rgba() = fill_color; + + RecBoxInfo recbox; + recbox.rectangle = rec_rect; + recbox.start = _trackview.session().transport_frame(); + recbox.length = 0; + + rec_rects.push_back (recbox); + + screen_update_connection.disconnect(); + screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (mem_fun (*this, &AudioStreamView::update_rec_box)); + rec_updating = true; + rec_active = true; + + } else if (rec_active && + (_trackview.session().record_status() != Session::Recording || + !_trackview.get_diskstream()->record_enabled())) { + + screen_update_connection.disconnect(); + rec_active = false; + rec_updating = false; + + } + + } else { + + // cerr << "\tNOT rolling, rec_rects = " << rec_rects.size() << " rec_regions = " << rec_regions.size() << endl; + + if (!rec_rects.empty() || !rec_regions.empty()) { + + /* disconnect rapid update */ + screen_update_connection.disconnect(); + + for (list<sigc::connection>::iterator prc = peak_ready_connections.begin(); prc != peak_ready_connections.end(); ++prc) { + (*prc).disconnect(); + } + peak_ready_connections.clear(); + + rec_updating = false; + rec_active = false; + last_rec_peak_frame = 0; + + /* remove temp regions */ + for (list<Region*>::iterator iter=rec_regions.begin(); iter != rec_regions.end(); ) + { + list<Region*>::iterator tmp; + + tmp = iter; + ++tmp; + + /* this will trigger the remove_region_view */ + delete *iter; + + iter = tmp; + } + + rec_regions.clear(); + + // cerr << "\tclear " << rec_rects.size() << " rec rects\n"; + + + /* transport stopped, clear boxes */ + for (vector<RecBoxInfo>::iterator iter=rec_rects.begin(); iter != rec_rects.end(); ++iter) { + RecBoxInfo &rect = (*iter); + delete rect.rectangle; + } + + rec_rects.clear(); + + } + } +} + +void +AudioStreamView::foreach_crossfadeview (void (CrossfadeView::*pmf)(void)) +{ + for (list<CrossfadeView*>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) { + ((*i)->*pmf) (); + } +} + +void +AudioStreamView::rec_peak_range_ready (jack_nframes_t start, jack_nframes_t cnt, Source * src) +{ + // this is called from the peak building thread + + ENSURE_GUI_THREAD(bind (mem_fun (*this, &AudioStreamView::rec_peak_range_ready), start, cnt, src)); + + if (rec_peak_ready_map.size() == 0 || start+cnt > last_rec_peak_frame) { + last_rec_peak_frame = start + cnt; + } + + rec_peak_ready_map[src] = true; + + if (rec_peak_ready_map.size() == _trackview.get_diskstream()->n_channels()) { + this->update_rec_regions (); + rec_peak_ready_map.clear(); + } +} + +void +AudioStreamView::update_rec_regions () +{ + if (use_rec_regions) { + + uint32_t n = 0; + + for (list<Region*>::iterator iter = rec_regions.begin(); iter != rec_regions.end(); n++) { + + list<Region*>::iterator tmp; + + tmp = iter; + ++tmp; + + if (!canvas_item_visible (rec_rects[n].rectangle)) { + /* rect already hidden, this region is done */ + iter = tmp; + continue; + } + + // FIXME + AudioRegion * region = dynamic_cast<AudioRegion*>(*iter); + assert(region); + + jack_nframes_t origlen = region->length(); + + if (region == rec_regions.back() && rec_active) { + + if (last_rec_peak_frame > region->start()) { + + jack_nframes_t nlen = last_rec_peak_frame - region->start(); + + if (nlen != region->length()) { + + region->freeze (); + region->set_position (_trackview.get_diskstream()->get_capture_start_frame(n), this); + region->set_length (nlen, this); + region->thaw ("updated"); + + if (origlen == 1) { + /* our special initial length */ + add_region_view_internal (region, false); + } + + /* also update rect */ + ArdourCanvas::SimpleRect * rect = rec_rects[n].rectangle; + gdouble xend = _trackview.editor.frame_to_pixel (region->position() + region->length()); + rect->property_x2() = xend; + } + } + + } else { + + jack_nframes_t nlen = _trackview.get_diskstream()->get_captured_frames(n); + + if (nlen != region->length()) { + + if (region->source(0).length() >= region->start() + nlen) { + + region->freeze (); + region->set_position (_trackview.get_diskstream()->get_capture_start_frame(n), this); + region->set_length (nlen, this); + region->thaw ("updated"); + + if (origlen == 1) { + /* our special initial length */ + add_region_view_internal (region, false); + } + + /* also hide rect */ + ArdourCanvas::Item * rect = rec_rects[n].rectangle; + rect->hide(); + + } + } + } + + iter = tmp; + } + } +} + +void +AudioStreamView::show_all_xfades () +{ + foreach_crossfadeview (&CrossfadeView::show); + crossfades_visible = true; +} + +void +AudioStreamView::hide_all_xfades () +{ + foreach_crossfadeview (&CrossfadeView::hide); + crossfades_visible = false; +} + +void +AudioStreamView::hide_xfades_involving (AudioRegionView& rv) +{ + for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) { + if ((*i)->crossfade.involves (rv.audio_region())) { + (*i)->fake_hide (); + } + } +} + +void +AudioStreamView::reveal_xfades_involving (AudioRegionView& rv) +{ + for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) { + if ((*i)->crossfade.involves (rv.audio_region()) && (*i)->visible()) { + (*i)->show (); + } + } +} + +void +AudioStreamView::color_handler (ColorID id, uint32_t val) +{ + switch (id) { + case cAudioTrackBase: + if (_trackview.is_audio_track()) { + canvas_rect->property_fill_color_rgba() = val; + } + break; + case cAudioBusBase: + if (!_trackview.is_audio_track()) { + canvas_rect->property_fill_color_rgba() = val; + } + break; + case cAudioTrackOutline: + canvas_rect->property_outline_color_rgba() = val; + break; + + default: + break; + } +} diff --git a/gtk2_ardour/audio_streamview.h b/gtk2_ardour/audio_streamview.h new file mode 100644 index 0000000000..d05ecd9307 --- /dev/null +++ b/gtk2_ardour/audio_streamview.h @@ -0,0 +1,111 @@ +/* + Copyright (C) 2001, 2006 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __ardour_audio_streamview_h__ +#define __ardour_audio_streamview_h__ + +#include <list> +#include <map> +#include <cmath> + +#include <ardour/location.h> +#include "enums.h" +#include "simplerect.h" +#include "color.h" +#include "streamview.h" + +namespace Gdk { + class Color; +} + +namespace ARDOUR { + class Route; + class Diskstream; + class Crossfade; + class PeakData; + class AudioRegion; + class Source; +} + +class PublicEditor; +class Selectable; +class AudioTimeAxisView; +class AudioRegionView; +class RegionSelection; +class CrossfadeView; +class Selection; + +class AudioStreamView : public StreamView +{ + public: + AudioStreamView (AudioTimeAxisView&); + ~AudioStreamView (); + + void set_waveform_shape (WaveformShape); + + int set_height (gdouble h); + + int set_samples_per_unit (gdouble spp); + + int set_amplitude_above_axis (gdouble app); + gdouble get_amplitude_above_axis () { return _amplitude_above_axis; } + + void set_show_waveforms (bool yn); + void set_show_waveforms_recording (bool yn) { use_rec_regions = yn; } + + void foreach_crossfadeview (void (CrossfadeView::*pmf)(void)); + + void show_all_xfades (); + void hide_all_xfades (); + void hide_xfades_involving (AudioRegionView&); + void reveal_xfades_involving (AudioRegionView&); + + private: + void setup_rec_box (); + void rec_peak_range_ready (jack_nframes_t start, jack_nframes_t cnt, ARDOUR::Source* src); + void update_rec_regions (); + + void add_region_view_internal (ARDOUR::Region*, bool wait_for_waves); + void remove_region_view (ARDOUR::Region* ); + void remove_audio_region_view (ARDOUR::AudioRegion* ); + void remove_audio_rec_region (ARDOUR::AudioRegion*); + + void undisplay_diskstream (); + void redisplay_diskstream (); + void playlist_modified (); + void playlist_changed (ARDOUR::Diskstream *ds); + + bool crossfades_visible; + void add_crossfade (ARDOUR::Crossfade*); + void remove_crossfade (ARDOUR::Crossfade*); + + void color_handler (ColorID id, uint32_t val); + + + typedef list<CrossfadeView*> CrossfadeViewList; + CrossfadeViewList crossfade_views; + + double _amplitude_above_axis; + + list<sigc::connection> peak_ready_connections; + jack_nframes_t last_rec_peak_frame; + map<ARDOUR::Source*, bool> rec_peak_ready_map; + +}; + +#endif /* __ardour_audio_streamview_h__ */ diff --git a/gtk2_ardour/audio_time_axis.cc b/gtk2_ardour/audio_time_axis.cc index ebaf3fdc2c..f6ccfe0084 100644 --- a/gtk2_ardour/audio_time_axis.cc +++ b/gtk2_ardour/audio_time_axis.cc @@ -20,6 +20,7 @@ #include <cstdlib> #include <cmath> +#include <cassert> #include <algorithm> #include <string> @@ -68,11 +69,11 @@ #include "public_editor.h" #include "redirect_automation_line.h" #include "redirect_automation_time_axis.h" -#include "regionview.h" +#include "audio_regionview.h" #include "rgb_macros.h" #include "selection.h" #include "simplerect.h" -#include "streamview.h" +#include "audio_streamview.h" #include "utils.h" #include <ardour/audio_track.h> @@ -81,39 +82,22 @@ using namespace ARDOUR; using namespace PBD; -using namespace LADSPA; using namespace Gtk; using namespace Editing; AudioTimeAxisView::AudioTimeAxisView (PublicEditor& ed, Session& sess, Route& rt, Canvas& canvas) - : AxisView(sess), - RouteUI(rt, sess, _("m"), _("s"), _("r")), // mute, solo, and record - TimeAxisView(sess,ed,(TimeAxisView*) 0, canvas), - parent_canvas (canvas), - button_table (3, 3), - edit_group_button (_("g")), // group - playlist_button (_("p")), - size_button (_("h")), // height - automation_button (_("a")), - visual_button (_("v")) - + : AxisView(sess), // FIXME: won't compile without this, why?? + RouteTimeAxisView(ed, sess, rt, canvas) { - _has_state = true; subplugin_menu.set_name ("ArdourContextMenu"); - playlist_menu = 0; - playlist_action_menu = 0; - automation_action_menu = 0; gain_track = 0; pan_track = 0; - view = 0; - timestretch_rect = 0; waveform_item = 0; pan_automation_item = 0; gain_automation_item = 0; - no_redraw = false; - view = new StreamView (*this); + _view = new AudioStreamView (*this); add_gain_automation_child (); add_pan_automation_child (); @@ -123,166 +107,54 @@ AudioTimeAxisView::AudioTimeAxisView (PublicEditor& ed, Session& sess, Route& rt mute_button->set_active (false); solo_button->set_active (false); - mute_button->set_name ("TrackMuteButton"); - solo_button->set_name ("SoloButton"); - edit_group_button.set_name ("TrackGroupButton"); - playlist_button.set_name ("TrackPlaylistButton"); - automation_button.set_name ("TrackAutomationButton"); - size_button.set_name ("TrackSizeButton"); - visual_button.set_name ("TrackVisualButton"); - hide_button.set_name ("TrackRemoveButton"); - - hide_button.add (*(manage (new Image (get_xpm("small_x.xpm"))))); - - solo_button->signal_button_press_event().connect (mem_fun (*this, &AudioTimeAxisView::select_me), false); - mute_button->signal_button_press_event().connect (mem_fun (*this, &AudioTimeAxisView::select_me), false); - playlist_button.signal_button_press_event().connect (mem_fun (*this, &AudioTimeAxisView::select_me), false); - automation_button.signal_button_press_event().connect (mem_fun (*this, &AudioTimeAxisView::select_me), false); - size_button.signal_button_press_event().connect (mem_fun (*this, &AudioTimeAxisView::select_me), false); - visual_button.signal_button_press_event().connect (mem_fun (*this, &AudioTimeAxisView::select_me), false); - hide_button.signal_button_press_event().connect (mem_fun (*this, &AudioTimeAxisView::select_me), false); - - solo_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::solo_press), false); - solo_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::solo_release), false); - mute_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::mute_press), false); - mute_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::mute_release), false); - edit_group_button.signal_button_release_event().connect (mem_fun(*this, &AudioTimeAxisView::edit_click), false); - playlist_button.signal_clicked().connect (mem_fun(*this, &AudioTimeAxisView::playlist_click)); - automation_button.signal_clicked().connect (mem_fun(*this, &AudioTimeAxisView::automation_click)); - size_button.signal_button_release_event().connect (mem_fun(*this, &AudioTimeAxisView::size_click), false); - visual_button.signal_clicked().connect (mem_fun(*this, &AudioTimeAxisView::visual_click)); - hide_button.signal_clicked().connect (mem_fun(*this, &AudioTimeAxisView::hide_click)); - - // FIXME: hack (pretty colours) if (is_audio_track()) controls_ebox.set_name ("AudioTimeAxisViewControlsBaseUnselected"); - else - controls_ebox.set_name ("MidiTimeAxisViewControlsBaseUnselected"); - - if (is_audio_track()) { - rec_enable_button->set_active (false); - rec_enable_button->set_name ("TrackRecordEnableButton"); - rec_enable_button->signal_button_press_event().connect (mem_fun (*this, &AudioTimeAxisView::select_me), false); - rec_enable_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::rec_enable_press)); - controls_table.attach (*rec_enable_button, 5, 6, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0); - ARDOUR_UI::instance()->tooltips().set_tip(*rec_enable_button, _("Record")); - } - - controls_table.attach (*mute_button, 6, 7, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0); - controls_table.attach (*solo_button, 7, 8, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::FILL|Gtk::EXPAND, 0, 0); - - controls_table.attach (edit_group_button, 6, 7, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0); - - ARDOUR_UI::instance()->tooltips().set_tip(*solo_button,_("Solo")); - ARDOUR_UI::instance()->tooltips().set_tip(*mute_button,_("Mute")); - ARDOUR_UI::instance()->tooltips().set_tip(edit_group_button,_("Edit Group")); - ARDOUR_UI::instance()->tooltips().set_tip(size_button,_("Display Height")); - ARDOUR_UI::instance()->tooltips().set_tip(playlist_button,_("Playlist")); - ARDOUR_UI::instance()->tooltips().set_tip(automation_button, _("Automation")); - ARDOUR_UI::instance()->tooltips().set_tip(visual_button, _("Visual options")); - ARDOUR_UI::instance()->tooltips().set_tip(hide_button, _("Hide this track")); - - label_view (); - - controls_table.attach (hide_button, 0, 1, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND); - controls_table.attach (visual_button, 1, 2, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND); - controls_table.attach (size_button, 2, 3, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND); - controls_table.attach (automation_button, 3, 4, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND); - - if (is_audio_track() && audio_track()->mode() == ARDOUR::Normal) { - controls_table.attach (playlist_button, 5, 6, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND); - } - - /* remove focus from the buttons */ - - automation_button.unset_flags (Gtk::CAN_FOCUS); - solo_button->unset_flags (Gtk::CAN_FOCUS); - mute_button->unset_flags (Gtk::CAN_FOCUS); - edit_group_button.unset_flags (Gtk::CAN_FOCUS); - size_button.unset_flags (Gtk::CAN_FOCUS); - playlist_button.unset_flags (Gtk::CAN_FOCUS); - hide_button.unset_flags (Gtk::CAN_FOCUS); - visual_button.unset_flags (Gtk::CAN_FOCUS); + else // bus + controls_ebox.set_name ("AudioBusControlsBaseUnselected"); /* map current state of the route */ - update_diskstream_display (); - solo_changed(0); - mute_changed(0); redirects_changed (0); reset_redirect_automation_curves (); - y_position = -1; ensure_xml_node (); set_state (*xml_node); - _route.mute_changed.connect (mem_fun(*this, &RouteUI::mute_changed)); - _route.solo_changed.connect (mem_fun(*this, &RouteUI::solo_changed)); _route.redirects_changed.connect (mem_fun(*this, &AudioTimeAxisView::redirects_changed)); - _route.name_changed.connect (mem_fun(*this, &AudioTimeAxisView::route_name_changed)); - _route.solo_safe_changed.connect (mem_fun(*this, &RouteUI::solo_changed)); _route.panner().Changed.connect (mem_fun(*this, &AudioTimeAxisView::update_pans)); if (is_audio_track()) { - /* track */ - - audio_track()->FreezeChange.connect (mem_fun(*this, &AudioTimeAxisView::map_frozen)); - - audio_track()->DiskstreamChanged.connect (mem_fun(*this, &AudioTimeAxisView::diskstream_changed)); - get_diskstream()->SpeedChanged.connect (mem_fun(*this, &AudioTimeAxisView::speed_changed)); - controls_ebox.set_name ("AudioTrackControlsBaseUnselected"); controls_base_selected_name = "AudioTrackControlsBaseSelected"; controls_base_unselected_name = "AudioTrackControlsBaseUnselected"; /* ask for notifications of any new RegionViews */ + _view->RegionViewAdded.connect (mem_fun(*this, &AudioTimeAxisView::region_view_added)); + _view->attach (); - view->AudioRegionViewAdded.connect (mem_fun(*this, &AudioTimeAxisView::region_view_added)); - - view->attach (); + } else { /* bus */ - /* pick up the correct freeze state */ - - map_frozen (); - - } else { - /* bus */ - - controls_ebox.set_name ("BusControlsBaseUnselected"); - controls_base_selected_name = "BusControlsBaseSelected"; - controls_base_unselected_name = "BusControlsBaseUnselected"; + controls_ebox.set_name ("AudioBusControlsBaseUnselected"); + controls_base_selected_name = "AudioBusControlsBaseSelected"; + controls_base_unselected_name = "AudioBusControlsBaseUnselected"; } - - editor.ZoomChanged.connect (mem_fun(*this, &AudioTimeAxisView::reset_samples_per_unit)); - ColorChanged.connect (mem_fun (*this, &AudioTimeAxisView::color_handler)); } AudioTimeAxisView::~AudioTimeAxisView () { - GoingAway (); /* EMIT_SIGNAL */ - - if (playlist_menu) { - delete playlist_menu; - playlist_menu = 0; - } - - if (playlist_action_menu) { - delete playlist_action_menu; - playlist_action_menu = 0; - } - vector_delete (&redirect_automation_curves); for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) { delete *i; } +} - if (view) { - delete view; - view = 0; - } +AudioStreamView* +AudioTimeAxisView::audio_view() +{ + return dynamic_cast<AudioStreamView*>(_view); } guint32 @@ -304,233 +176,6 @@ AudioTimeAxisView::hide () } void -AudioTimeAxisView::set_playlist (AudioPlaylist *newplaylist) -{ - AudioPlaylist *pl; - - modified_connection.disconnect (); - state_changed_connection.disconnect (); - - if ((pl = dynamic_cast<AudioPlaylist*> (playlist())) != 0) { - state_changed_connection = pl->StateChanged.connect (mem_fun(*this, &AudioTimeAxisView::playlist_state_changed)); - modified_connection = pl->Modified.connect (mem_fun(*this, &AudioTimeAxisView::playlist_modified)); - } -} - -void -AudioTimeAxisView::playlist_modified () -{ -} - -gint -AudioTimeAxisView::edit_click (GdkEventButton *ev) -{ - if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) { - _route.set_edit_group (0, this); - return FALSE; - } - - using namespace Menu_Helpers; - - MenuList& items = edit_group_menu.items (); - RadioMenuItem::Group group; - - items.clear (); - items.push_back (RadioMenuElem (group, _("No group"), - bind (mem_fun(*this, &AudioTimeAxisView::set_edit_group_from_menu), (RouteGroup *) 0))); - - if (_route.edit_group() == 0) { - static_cast<RadioMenuItem*>(&items.back())->set_active (); - } - - _session.foreach_edit_group (bind (mem_fun (*this, &AudioTimeAxisView::add_edit_group_menu_item), &group)); - edit_group_menu.popup (ev->button, ev->time); - - return FALSE; -} - -void -AudioTimeAxisView::add_edit_group_menu_item (RouteGroup *eg, RadioMenuItem::Group* group) -{ - using namespace Menu_Helpers; - - MenuList &items = edit_group_menu.items(); - - cerr << "adding edit group called " << eg->name() << endl; - - items.push_back (RadioMenuElem (*group, eg->name(), bind (mem_fun(*this, &AudioTimeAxisView::set_edit_group_from_menu), eg))); - if (_route.edit_group() == eg) { - static_cast<RadioMenuItem*>(&items.back())->set_active (); - } -} - -void -AudioTimeAxisView::set_edit_group_from_menu (RouteGroup *eg) - -{ - _route.set_edit_group (eg, this); -} - -void -AudioTimeAxisView::playlist_state_changed (Change ignored) -{ - // ENSURE_GUI_THREAD (bind (mem_fun(*this, &AudioTimeAxisView::playlist_state_changed), ignored)); - // why are we here ? -} - -void -AudioTimeAxisView::playlist_changed () - -{ - label_view (); - - if (is_audio_track()) { - set_playlist (dynamic_cast<AudioPlaylist*>(get_diskstream()->playlist())); - } -} - -void -AudioTimeAxisView::label_view () -{ - string x = _route.name(); - - if (x != name_entry.get_text()) { - name_entry.set_text (x); - } - - ARDOUR_UI::instance()->tooltips().set_tip (name_entry, x); -} - -void -AudioTimeAxisView::route_name_changed (void *src) -{ - editor.route_name_changed (this); - label_view (); -} - -void -AudioTimeAxisView::take_name_changed (void *src) - -{ - if (src != this) { - label_view (); - } -} - -void -AudioTimeAxisView::playlist_click () -{ - // always build a new action menu - - if (playlist_action_menu == 0) { - playlist_action_menu = new Menu; - playlist_action_menu->set_name ("ArdourContextMenu"); - } - - build_playlist_menu(playlist_action_menu); - - playlist_action_menu->popup (1, 0); -} - -void -AudioTimeAxisView::automation_click () -{ - if (automation_action_menu == 0) { - /* this seems odd, but the automation action - menu is built as part of the display menu. - */ - build_display_menu (); - } - automation_action_menu->popup (1, 0); -} - -void -AudioTimeAxisView::show_timestretch (jack_nframes_t start, jack_nframes_t end) -{ - double x1; - double x2; - double y2; - - TimeAxisView::show_timestretch (start, end); - - hide_timestretch (); - -#if 0 - if (ts.empty()) { - return; - } - - - /* check that the time selection was made in our route, or our edit group. - remember that edit_group() == 0 implies the route is *not* in a edit group. - */ - - if (!(ts.track == this || (ts.group != 0 && ts.group == _route.edit_group()))) { - /* this doesn't apply to us */ - return; - } - - /* ignore it if our edit group is not active */ - - if ((ts.track != this) && _route.edit_group() && !_route.edit_group()->is_active()) { - return; - } -#endif - - if (timestretch_rect == 0) { - timestretch_rect = new SimpleRect (*canvas_display); - timestretch_rect->property_x1() = 0.0; - timestretch_rect->property_y1() = 0.0; - timestretch_rect->property_x2() = 0.0; - timestretch_rect->property_y2() = 0.0; - timestretch_rect->property_fill_color_rgba() = color_map[cTimeStretchFill]; - timestretch_rect->property_outline_color_rgba() = color_map[cTimeStretchOutline]; - } - - timestretch_rect->show (); - timestretch_rect->raise_to_top (); - - x1 = start / editor.get_current_zoom(); - x2 = (end - 1) / editor.get_current_zoom(); - y2 = height - 2; - - timestretch_rect->property_x1() = x1; - timestretch_rect->property_y1() = 1.0; - timestretch_rect->property_x2() = x2; - timestretch_rect->property_y2() = y2; -} - -void -AudioTimeAxisView::hide_timestretch () -{ - TimeAxisView::hide_timestretch (); - - if (timestretch_rect) { - timestretch_rect->hide (); - } -} - -void -AudioTimeAxisView::show_selection (TimeSelection& ts) -{ - -#if 0 - /* ignore it if our edit group is not active or if the selection was started - in some other track or edit group (remember that edit_group() == 0 means - that the track is not in an edit group). - */ - - if (((ts.track != this && !is_child (ts.track)) && _route.edit_group() && !_route.edit_group()->is_active()) || - (!(ts.track == this || is_child (ts.track) || (ts.group != 0 && ts.group == _route.edit_group())))) { - hide_selection (); - return; - } -#endif - - TimeAxisView::show_selection (ts); -} - -void AudioTimeAxisView::set_state (const XMLNode& node) { const XMLProperty *prop; @@ -583,81 +228,6 @@ AudioTimeAxisView::set_state (const XMLNode& node) } void -AudioTimeAxisView::set_height (TrackHeight h) -{ - bool height_changed = (height == 0) || (h != height_style); - - TimeAxisView::set_height (h); - - ensure_xml_node (); - - view->set_height ((double) height); - - switch (height_style) { - case Largest: - xml_node->add_property ("track_height", "largest"); - show_name_entry (); - hide_name_label (); - controls_table.show_all(); - break; - case Large: - xml_node->add_property ("track_height", "large"); - show_name_entry (); - hide_name_label (); - controls_table.show_all(); - break; - case Larger: - xml_node->add_property ("track_height", "larger"); - show_name_entry (); - hide_name_label (); - controls_table.show_all(); - break; - case Normal: - xml_node->add_property ("track_height", "normal"); - show_name_entry (); - hide_name_label (); - controls_table.show_all(); - break; - case Smaller: - xml_node->add_property ("track_height", "smaller"); - controls_table.show_all (); - show_name_entry (); - hide_name_label (); - edit_group_button.hide (); - hide_button.hide (); - visual_button.hide (); - size_button.hide (); - automation_button.hide (); - playlist_button.hide (); - break; - case Small: - xml_node->add_property ("track_height", "small"); - controls_table.hide_all (); - controls_table.show (); - hide_name_entry (); - show_name_label (); - name_label.set_text (_route.name()); - break; - } - - if (height_changed) { - /* only emit the signal if the height really changed */ - _route.gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ - } -} - -void -AudioTimeAxisView::select_track_color () -{ - if (RouteUI::choose_color ()) { - - if (view) { - view->apply_color (_color, StreamView::RegionColor); - } - } -} - -void AudioTimeAxisView::reset_redirect_automation_curves () { for (vector<RedirectAutomationLine*>::iterator i = redirect_automation_curves.begin(); i != redirect_automation_curves.end(); ++i) { @@ -666,28 +236,6 @@ AudioTimeAxisView::reset_redirect_automation_curves () } void -AudioTimeAxisView::reset_samples_per_unit () -{ - set_samples_per_unit (editor.get_current_zoom()); -} - -void -AudioTimeAxisView::set_samples_per_unit (double spu) -{ - double speed = 1.0; - - if (get_diskstream() != 0) { - speed = get_diskstream()->speed(); - } - - if (view) { - view->set_samples_per_unit (spu * speed); - } - - TimeAxisView::set_samples_per_unit (spu * speed); -} - -void AudioTimeAxisView::build_display_menu () { using namespace Menu_Helpers; @@ -801,371 +349,57 @@ AudioTimeAxisView::build_display_menu () } void -AudioTimeAxisView::align_style_changed () -{ - switch (get_diskstream()->alignment_style()) { - case ExistingMaterial: - if (!align_existing_item->get_active()) { - align_existing_item->set_active(); - } - break; - case CaptureTime: - if (!align_capture_item->get_active()) { - align_capture_item->set_active(); - } - break; - } -} - -void -AudioTimeAxisView::set_align_style (AlignStyle style) -{ - get_diskstream()->set_align_style (style); -} - -void -AudioTimeAxisView::rename_current_playlist () -{ - ArdourPrompter prompter (true); - string name; - - AudioPlaylist *pl; - AudioDiskstream *ds; - - if (((ds = dynamic_cast<AudioDiskstream*>(get_diskstream())) == 0) || ds->destructive() - || ((pl = dynamic_cast<AudioPlaylist*>(ds->playlist())) == 0)) { - return; - } - - prompter.set_prompt (_("Name for playlist")); - prompter.set_initial_text (pl->name()); - prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT); - prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false); - - switch (prompter.run ()) { - case Gtk::RESPONSE_ACCEPT: - prompter.get_result (name); - if (name.length()) { - pl->set_name (name); - } - break; - - default: - break; - } -} - -void -AudioTimeAxisView::use_copy_playlist (bool prompt) -{ - AudioPlaylist *pl; - AudioDiskstream *ds; - string name; - - if (((ds = dynamic_cast<AudioDiskstream*>(get_diskstream())) == 0) || ds->destructive() - || ((pl = dynamic_cast<AudioPlaylist*>(ds->playlist())) == 0)) { - return; - } - - name = Playlist::bump_name (pl->name(), _session); - - if (prompt) { - - ArdourPrompter prompter (true); - - prompter.set_prompt (_("Name for Playlist")); - prompter.set_initial_text (name); - prompter.add_button (Gtk::Stock::NEW, Gtk::RESPONSE_ACCEPT); - prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false); - prompter.show_all (); - - switch (prompter.run ()) { - case Gtk::RESPONSE_ACCEPT: - prompter.get_result (name); - break; - - default: - return; - } - } - - if (name.length()) { - ds->use_copy_playlist (); - pl = dynamic_cast<AudioPlaylist*>(ds->playlist()); - pl->set_name (name); - } -} - -void -AudioTimeAxisView::use_new_playlist (bool prompt) -{ - AudioPlaylist *pl; - AudioDiskstream *ds; - string name; - - if (((ds = dynamic_cast<AudioDiskstream*>(get_diskstream())) == 0) || ds->destructive() - || ((pl = dynamic_cast<AudioPlaylist*>(ds->playlist())) == 0)) { - return; - } - - name = Playlist::bump_name (pl->name(), _session); - - if (prompt) { - - ArdourPrompter prompter (true); - - prompter.set_prompt (_("Name for Playlist")); - prompter.set_initial_text (name); - prompter.add_button (Gtk::Stock::NEW, Gtk::RESPONSE_ACCEPT); - prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false); - - switch (prompter.run ()) { - case Gtk::RESPONSE_ACCEPT: - prompter.get_result (name); - break; - - default: - return; - } - } - - if (name.length()) { - ds->use_new_playlist (); - pl = dynamic_cast<AudioPlaylist*>(ds->playlist()); - pl->set_name (name); - } -} - -void -AudioTimeAxisView::clear_playlist () -{ - AudioPlaylist *pl; - AudioDiskstream *ds; - - if ((ds = dynamic_cast<AudioDiskstream*>(get_diskstream())) != 0) { - if ((pl = dynamic_cast<AudioPlaylist*>(ds->playlist())) != 0) { - editor.clear_playlist (*pl); - } - } -} - -void AudioTimeAxisView::toggle_waveforms () { - if (view && waveform_item && !ignore_toggle) { - view->set_show_waveforms (waveform_item->get_active()); + AudioStreamView* asv = audio_view(); + assert(asv); + + if (asv && waveform_item && !ignore_toggle) { + asv->set_show_waveforms (waveform_item->get_active()); } } void AudioTimeAxisView::set_show_waveforms (bool yn) { + AudioStreamView* asv = audio_view(); + assert(asv); + if (waveform_item) { waveform_item->set_active (yn); } else { - view->set_show_waveforms (yn); + asv->set_show_waveforms (yn); } } void AudioTimeAxisView::set_show_waveforms_recording (bool yn) { - if (view) { - view->set_show_waveforms_recording (yn); - } -} - -void -AudioTimeAxisView::set_waveform_shape (WaveformShape shape) -{ - if (view) { - view->set_waveform_shape (shape); - } -} - -void -AudioTimeAxisView::speed_changed () -{ - Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &AudioTimeAxisView::reset_samples_per_unit)); -} - -void -AudioTimeAxisView::diskstream_changed (void *src) -{ - Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &AudioTimeAxisView::update_diskstream_display)); -} - -void -AudioTimeAxisView::update_diskstream_display () -{ - AudioDiskstream *ds; - - if ((ds = dynamic_cast<AudioDiskstream*>(get_diskstream())) != 0) { - set_playlist (dynamic_cast<AudioPlaylist*> (ds->playlist ())); - } - - map_frozen (); -} - -void -AudioTimeAxisView::selection_click (GdkEventButton* ev) -{ - PublicEditor::TrackViewList* tracks = editor.get_valid_views (this, _route.edit_group()); - - switch (Keyboard::selection_type (ev->state)) { - case Selection::Toggle: - /* XXX this is not right */ - editor.get_selection().add (*tracks); - break; - - case Selection::Set: - editor.get_selection().set (*tracks); - break; - - case Selection::Extend: - /* not defined yet */ - break; - } - - delete tracks; -} - -void -AudioTimeAxisView::set_selected_regionviews (AudioRegionSelection& regions) -{ - if (view) { - view->set_selected_regionviews (regions); - } -} - -void -AudioTimeAxisView::set_selected_points (PointSelection& points) -{ - for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) { - (*i)->set_selected_points (points); - } -} - -void -AudioTimeAxisView::get_selectables (jack_nframes_t start, jack_nframes_t end, double top, double bot, list<Selectable*>& results) -{ - double speed = 1.0; - - if (get_diskstream() != 0) { - speed = get_diskstream()->speed(); - } - - jack_nframes_t start_adjusted = session_frame_to_track_frame(start, speed); - jack_nframes_t end_adjusted = session_frame_to_track_frame(end, speed); + AudioStreamView* asv = audio_view(); - if (view && ((top < 0.0 && bot < 0.0)) || touched (top, bot)) { - view->get_selectables (start_adjusted, end_adjusted, results); - } - - /* pick up visible automation tracks */ - - for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) { - if (!(*i)->hidden()) { - (*i)->get_selectables (start_adjusted, end_adjusted, top, bot, results); - } + if (asv) { + asv->set_show_waveforms_recording (yn); } } void -AudioTimeAxisView::get_inverted_selectables (Selection& sel, list<Selectable*>& results) -{ - if (view) { - view->get_inverted_selectables (sel, results); - } - - for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) { - if (!(*i)->hidden()) { - (*i)->get_inverted_selectables (sel, results); - } - } - - return; -} - -RouteGroup* -AudioTimeAxisView::edit_group() const -{ - return _route.edit_group(); -} - -string -AudioTimeAxisView::name() const -{ - return _route.name(); -} - -Playlist * -AudioTimeAxisView::playlist () const +AudioTimeAxisView::set_waveform_shape (WaveformShape shape) { - Diskstream *ds; + AudioStreamView* asv = audio_view(); - if ((ds = get_diskstream()) != 0) { - return ds->playlist(); - } else { - return 0; + if (asv) { + asv->set_waveform_shape (shape); } } void -AudioTimeAxisView::name_entry_changed () -{ - string x; - - x = name_entry.get_text (); - - if (x == _route.name()) { - return; - } - - if (x.length() == 0) { - name_entry.set_text (_route.name()); - return; - } - - strip_whitespace_edges(x); - - if (_session.route_name_unique (x)) { - _route.set_name (x, this); - } else { - ARDOUR_UI::instance()->popup_error (_("a track already exists with that name")); - name_entry.set_text (_route.name()); - } -} - -void -AudioTimeAxisView::visual_click () -{ - popup_display_menu (0); -} - -void -AudioTimeAxisView::hide_click () -{ - editor.hide_track_in_display (*this); -} - -ARDOUR::AudioDiskstream* -AudioTimeAxisView::get_diskstream() const -{ - return dynamic_cast<ARDOUR::AudioDiskstream*>(RouteUI::get_diskstream()); -} - -Region* -AudioTimeAxisView::find_next_region (jack_nframes_t pos, RegionPoint point, int32_t dir) +AudioTimeAxisView::set_selected_regionviews (RegionSelection& regions) { - Diskstream *stream; - Playlist *playlist; + AudioStreamView* asv = audio_view(); - if ((stream = get_diskstream()) != 0 && (playlist = stream->playlist()) != 0) { - return playlist->find_next_region (pos, point, dir); + if (asv) { + asv->set_selected_regionviews (regions); } - - return 0; } void @@ -1395,6 +629,7 @@ AudioTimeAxisView::find_redirect_automation_node (Redirect *redirect, uint32_t w return 0; } +// FIXME: duplicated in midi_time_axis.cc static string legalize_for_xml_node (string str) { @@ -1462,7 +697,7 @@ AudioTimeAxisView::add_redirect_automation_curve (Redirect *redirect, uint32_t w add_child (ran->view); - view->foreach_regionview (bind (mem_fun(*this, &AudioTimeAxisView::add_ghost_to_redirect), ran->view)); + audio_view()->foreach_regionview (bind (mem_fun(*this, &AudioTimeAxisView::add_ghost_to_redirect), ran->view)); redirect->mark_automation_visible (what, true); } @@ -1729,213 +964,65 @@ AudioTimeAxisView::hide_all_automation () _route.gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ } -bool -AudioTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op) -{ - Playlist* what_we_got; - AudioDiskstream* ds = dynamic_cast<AudioDiskstream*>(get_diskstream()); - Playlist* playlist; - bool ret = false; - - if (ds == 0) { - /* route is a bus, not a track */ - return false; - } - - playlist = ds->playlist(); - - - TimeSelection time (selection.time); - float speed = ds->speed(); - if (speed != 1.0f) { - for (TimeSelection::iterator i = time.begin(); i != time.end(); ++i) { - (*i).start = session_frame_to_track_frame((*i).start, speed); - (*i).end = session_frame_to_track_frame((*i).end, speed); - } - } - - switch (op) { - case Cut: - _session.add_undo (playlist->get_memento()); - if ((what_we_got = playlist->cut (time)) != 0) { - editor.get_cut_buffer().add (what_we_got); - _session.add_redo_no_execute (playlist->get_memento()); - ret = true; - } - break; - case Copy: - if ((what_we_got = playlist->copy (time)) != 0) { - editor.get_cut_buffer().add (what_we_got); - } - break; - - case Clear: - _session.add_undo (playlist->get_memento()); - if ((what_we_got = playlist->cut (time)) != 0) { - _session.add_redo_no_execute (playlist->get_memento()); - what_we_got->unref (); - ret = true; - } - break; - } - - return ret; -} - -bool -AudioTimeAxisView::paste (jack_nframes_t pos, float times, Selection& selection, size_t nth) -{ - if (!is_audio_track()) { - return false; - } - - Playlist* playlist = get_diskstream()->playlist(); - PlaylistSelection::iterator p; - - for (p = selection.playlists.begin(); p != selection.playlists.end() && nth; ++p, --nth); - - if (p == selection.playlists.end()) { - return false; - } - - if (get_diskstream()->speed() != 1.0f) - pos = session_frame_to_track_frame(pos, get_diskstream()->speed() ); - - _session.add_undo (playlist->get_memento()); - playlist->paste (**p, pos, times); - _session.add_redo_no_execute (playlist->get_memento()); - - return true; -} - void -AudioTimeAxisView::region_view_added (AudioRegionView* arv) +AudioTimeAxisView::region_view_added (RegionView* rv) { + assert(dynamic_cast<AudioRegionView*>(rv)); + for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) { AutomationTimeAxisView* atv; if ((atv = dynamic_cast<AutomationTimeAxisView*> (*i)) != 0) { - arv->add_ghost (*atv); + rv->add_ghost (*atv); } } } void -AudioTimeAxisView::add_ghost_to_redirect (AudioRegionView* arv, AutomationTimeAxisView* atv) -{ - arv->add_ghost (*atv); -} - -list<TimeAxisView*> -AudioTimeAxisView::get_child_list() +AudioTimeAxisView::add_ghost_to_redirect (RegionView* rv, AutomationTimeAxisView* atv) { - - list<TimeAxisView*>redirect_children; - - for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) { - if (!(*i)->hidden()) { - redirect_children.push_back(*i); - } - } - return redirect_children; -} - - -void -AudioTimeAxisView::build_playlist_menu (Gtk::Menu * menu) -{ - using namespace Menu_Helpers; - - if (!menu || !is_audio_track()) { - return; - } - - MenuList& playlist_items = menu->items(); - menu->set_name ("ArdourContextMenu"); - playlist_items.clear(); - - if (playlist_menu) { - delete playlist_menu; - } - playlist_menu = new Menu; - playlist_menu->set_name ("ArdourContextMenu"); - - playlist_items.push_back (MenuElem (string_compose (_("Current: %1"), get_diskstream()->playlist()->name()))); - playlist_items.push_back (SeparatorElem()); - - playlist_items.push_back (MenuElem (_("Rename"), mem_fun(*this, &AudioTimeAxisView::rename_current_playlist))); - playlist_items.push_back (SeparatorElem()); - - playlist_items.push_back (MenuElem (_("New"), mem_fun(editor, &PublicEditor::new_playlists))); - playlist_items.push_back (MenuElem (_("New Copy"), mem_fun(editor, &PublicEditor::copy_playlists))); - playlist_items.push_back (SeparatorElem()); - playlist_items.push_back (MenuElem (_("Clear Current"), mem_fun(editor, &PublicEditor::clear_playlists))); - playlist_items.push_back (SeparatorElem()); - playlist_items.push_back (MenuElem(_("Select"), mem_fun(*this, &AudioTimeAxisView::show_playlist_selector))); - -} - -void -AudioTimeAxisView::show_playlist_selector () -{ - editor.playlist_selector().show_for (this); -} - - -void -AudioTimeAxisView::map_frozen () -{ - if (!is_audio_track()) { - return; - } - - ENSURE_GUI_THREAD (mem_fun(*this, &AudioTimeAxisView::map_frozen)); - - switch (audio_track()->freeze_state()) { - case AudioTrack::Frozen: - playlist_button.set_sensitive (false); - rec_enable_button->set_sensitive (false); - break; - default: - playlist_button.set_sensitive (true); - rec_enable_button->set_sensitive (true); - break; - } + rv->add_ghost (*atv); } void AudioTimeAxisView::show_all_xfades () { - if (view) { - view->show_all_xfades (); + AudioStreamView* asv = audio_view(); + + if (asv) { + asv->show_all_xfades (); } } void AudioTimeAxisView::hide_all_xfades () { - if (view) { - view->hide_all_xfades (); + AudioStreamView* asv = audio_view(); + + if (asv) { + asv->hide_all_xfades (); } } void AudioTimeAxisView::hide_dependent_views (TimeAxisViewItem& tavi) { + AudioStreamView* asv = audio_view(); AudioRegionView* rv; - if (view && (rv = dynamic_cast<AudioRegionView*>(&tavi)) != 0) { - view->hide_xfades_involving (*rv); + if (asv && (rv = dynamic_cast<AudioRegionView*>(&tavi)) != 0) { + asv->hide_xfades_involving (*rv); } } void AudioTimeAxisView::reveal_dependent_views (TimeAxisViewItem& tavi) { + AudioStreamView* asv = audio_view(); AudioRegionView* rv; - if (view && (rv = dynamic_cast<AudioRegionView*>(&tavi)) != 0) { - view->reveal_xfades_involving (*rv); + if (asv && (rv = dynamic_cast<AudioRegionView*>(&tavi)) != 0) { + asv->reveal_xfades_involving (*rv); } } @@ -1973,24 +1060,3 @@ AudioTimeAxisView::get_child_xml_node (const string & childname) return RouteUI::get_child_xml_node (childname); } -void -AudioTimeAxisView::color_handler (ColorID id, uint32_t val) -{ - switch (id) { - case cTimeStretchOutline: - timestretch_rect->property_outline_color_rgba() = val; - break; - case cTimeStretchFill: - timestretch_rect->property_fill_color_rgba() = val; - break; - default: - break; - } -} - -bool -AudioTimeAxisView::select_me (GdkEventButton* ev) -{ - editor.get_selection().add (this); - return false; -} diff --git a/gtk2_ardour/audio_time_axis.h b/gtk2_ardour/audio_time_axis.h index 89a8a3a0f0..ed7a256812 100644 --- a/gtk2_ardour/audio_time_axis.h +++ b/gtk2_ardour/audio_time_axis.h @@ -18,8 +18,8 @@ $Id$ */ -#ifndef __ardour_trackview_h__ -#define __ardour_trackview_h__ +#ifndef __ardour_audio_time_axis_h__ +#define __ardour_audio_time_axis_h__ #include <gtkmm/table.h> #include <gtkmm/button.h> @@ -38,14 +38,10 @@ #include "ardour_dialog.h" #include "route_ui.h" #include "enums.h" -#include "time_axis_view.h" +#include "route_time_axis.h" #include "canvas.h" #include "color.h" -namespace ALSA { - class MultiChannelDevice; -} - namespace ARDOUR { class Session; class AudioDiskstream; @@ -56,16 +52,12 @@ namespace ARDOUR { class AudioPlaylist; } -namespace LADSPA { - class Manager; - class Plugin; -} - class PublicEditor; class AudioThing; -class StreamView; +class AudioStreamView; class Selection; class Selectable; +class RegionView; class AudioRegionView; class AutomationLine; class AutomationGainLine; @@ -74,171 +66,62 @@ class RedirectAutomationLine; class TimeSelection; class AutomationTimeAxisView; -class AudioTimeAxisView : public RouteUI, public TimeAxisView +class AudioTimeAxisView : public RouteTimeAxisView { public: AudioTimeAxisView (PublicEditor&, ARDOUR::Session&, ARDOUR::Route&, ArdourCanvas::Canvas& canvas); virtual ~AudioTimeAxisView (); + + AudioStreamView* audio_view(); - void show_selection (TimeSelection&); - void automation_control_point_changed (ARDOUR::AutomationType); - - void set_samples_per_unit (double); - void set_height (TimeAxisView::TrackHeight); void set_show_waveforms (bool yn); void set_show_waveforms_recording (bool yn); - void show_timestretch (jack_nframes_t start, jack_nframes_t end); - void hide_timestretch (); - void selection_click (GdkEventButton*); - void set_selected_regionviews (AudioRegionSelection&); - void set_selected_points (PointSelection&); - void get_selectables (jack_nframes_t start, jack_nframes_t end, double top, double bot, list<Selectable *>&); - void get_inverted_selectables (Selection&, list<Selectable*>&); void show_all_xfades (); void hide_all_xfades (); + void set_selected_regionviews (RegionSelection&); void hide_dependent_views (TimeAxisViewItem&); void reveal_dependent_views (TimeAxisViewItem&); - ARDOUR::AudioDiskstream* get_diskstream() const; - - ARDOUR::Region* find_next_region (jack_nframes_t pos, ARDOUR::RegionPoint, int32_t dir); - - string name() const; - - ARDOUR::RouteGroup* edit_group() const; - - void build_playlist_menu (Gtk::Menu *); - ARDOUR::Playlist* playlist() const; - /* overridden from parent to store display state */ guint32 show_at (double y, int& nth, Gtk::VBox *parent); void hide (); - /* need accessors/mutators */ - - StreamView *view; - - /* editing operations */ - - bool cut_copy_clear (Selection&, Editing::CutCopyOp); - bool paste (jack_nframes_t, float times, Selection&, size_t nth); - - list<TimeAxisView*>get_child_list(); - void set_state (const XMLNode&); XMLNode* get_child_xml_node (const string & childname); - /* the editor calls these when mapping an operation across multiple tracks */ - - void use_new_playlist (bool prompt); - void use_copy_playlist (bool prompt); - void clear_playlist (); - private: - friend class StreamView; + friend class AudioStreamView; friend class AudioRegionView; + + void route_active_changed (); - ArdourCanvas::Canvas& parent_canvas; - - bool no_redraw; - AutomationTimeAxisView *gain_track; AutomationTimeAxisView *pan_track; void update_automation_view (ARDOUR::AutomationType); void reset_redirect_automation_curves (); - Gtk::HBox other_button_hbox; - - Gtk::Table button_table; - - Gtk::Button redirect_button; - Gtk::Button edit_group_button; - Gtk::Button playlist_button; - Gtk::Button size_button; - Gtk::Button automation_button; - Gtk::Button hide_button; - Gtk::Button visual_button; - - void route_active_changed (); - - void diskstream_changed (void *src); - void update_diskstream_display (); - - gint edit_click (GdkEventButton *); - // variables to get the context menu // automation buttons correctly initialized bool show_gain_automation; bool show_pan_automation; - void build_redirect_window (); - void redirect_click (); - void redirect_add (); - void redirect_remove (); - void redirect_edit (); - void redirect_relist (); - void redirect_row_selected (gint row, gint col, GdkEvent *ev); - void add_to_redirect_display (ARDOUR::Redirect *); void redirects_changed (void *); - sigc::connection modified_connection; - sigc::connection state_changed_connection; - - void take_name_changed (void *); - void route_name_changed (void *); - void name_entry_changed (); - - void on_area_realize (); - - virtual void label_view (); - - Gtk::Menu edit_group_menu; - - void add_edit_group_menu_item (ARDOUR::RouteGroup *, Gtk::RadioMenuItem::Group*); - void set_edit_group_from_menu (ARDOUR::RouteGroup *); - - void reset_samples_per_unit (); - - void select_track_color(); - - virtual void build_display_menu (); + void build_display_menu (); Gtk::CheckMenuItem* waveform_item; Gtk::RadioMenuItem* traditional_item; Gtk::RadioMenuItem* rectified_item; - Gtk::RadioMenuItem* align_existing_item; - Gtk::RadioMenuItem* align_capture_item; - - void align_style_changed (); - void set_align_style (ARDOUR::AlignStyle); - void toggle_show_waveforms (); void set_waveform_shape (WaveformShape); void toggle_waveforms (); - Gtk::Menu *playlist_menu; - Gtk::Menu *playlist_action_menu; - Gtk::MenuItem *playlist_item; - - /* playlist */ - - void set_playlist (ARDOUR::AudioPlaylist *); - void playlist_click (); - void show_playlist_selector (); - - void playlist_changed (); - void playlist_state_changed (ARDOUR::Change); - void playlist_modified (); - - void add_playlist_to_playlist_menu (ARDOUR::Playlist*); - void rename_current_playlist (); - /* automation stuff */ - Gtk::Menu* automation_action_menu; + Gtk::Menu* automation_action_menu; Gtk::CheckMenuItem* gain_automation_item; Gtk::CheckMenuItem* pan_automation_item; @@ -249,7 +132,7 @@ class AudioTimeAxisView : public RouteUI, public TimeAxisView void show_existing_automation (); struct RedirectAutomationNode { - uint32_t what; + uint32_t what; Gtk::CheckMenuItem* menu_item; AutomationTimeAxisView* view; AudioTimeAxisView& parent; @@ -289,16 +172,6 @@ class AudioTimeAxisView : public RouteUI, public TimeAxisView void add_redirect_automation_curve (ARDOUR::Redirect*, uint32_t); void add_existing_redirect_automation_curves (ARDOUR::Redirect*); - ArdourCanvas::SimpleRect *timestretch_rect; - - void timestretch (jack_nframes_t start, jack_nframes_t end); - - void visual_click (); - void hide_click (); - gint when_displayed (GdkEventAny*); - - void speed_changed (); - void add_gain_automation_child (); void add_pan_automation_child (); void add_parameter_automation_child (); @@ -311,14 +184,9 @@ class AudioTimeAxisView : public RouteUI, public TimeAxisView void update_pans (); - void region_view_added (AudioRegionView*); - void add_ghost_to_redirect (AudioRegionView*, AutomationTimeAxisView*); - - void map_frozen (); - - void color_handler (ColorID, uint32_t); - bool select_me (GdkEventButton*); + void region_view_added (RegionView*); + void add_ghost_to_redirect (RegionView*, AutomationTimeAxisView*); }; -#endif /* __ardour_trackview_h__ */ +#endif /* __ardour_audio_time_axis_h__ */ diff --git a/gtk2_ardour/automation_time_axis.h b/gtk2_ardour/automation_time_axis.h index b4d434610d..80b451730c 100644 --- a/gtk2_ardour/automation_time_axis.h +++ b/gtk2_ardour/automation_time_axis.h @@ -21,7 +21,7 @@ namespace ARDOUR { class PublicEditor; class TimeSelection; -class AudioRegionSelection; +class RegionSelection; class PointSelection; class AutomationLine; class GhostRegion; diff --git a/gtk2_ardour/canvas-waveview.h b/gtk2_ardour/canvas-waveview.h index 97ac91f622..75281f69eb 100644 --- a/gtk2_ardour/canvas-waveview.h +++ b/gtk2_ardour/canvas-waveview.h @@ -80,10 +80,10 @@ struct _GnomeCanvasWaveView void (*gain_curve_function)(void *arg, double start, double end, float* vector, guint32 veclen); void *gain_src; - /* x-axis: samples per canvas unit. */ + /** x-axis: samples per canvas unit. */ double samples_per_unit; - /* y-axis: amplitude_above_axis. + /** y-axis: amplitude_above_axis. * * the default is that an (scaled, normalized -1.0 ... +1.0) amplitude of 1.0 * corresponds to the top of the area assigned to the waveview. @@ -92,8 +92,8 @@ struct _GnomeCanvasWaveView * smaller values will decrease the vertical scale, moving peaks/troughs toward * the middle of the area assigned to the waveview. */ - double amplitude_above_axis; + double x; double y; double height; diff --git a/gtk2_ardour/crossfade_view.cc b/gtk2_ardour/crossfade_view.cc index 350698ec48..bb9ee08861 100644 --- a/gtk2_ardour/crossfade_view.cc +++ b/gtk2_ardour/crossfade_view.cc @@ -29,7 +29,7 @@ #include "rgb_macros.h" #include "audio_time_axis.h" #include "public_editor.h" -#include "regionview.h" +#include "audio_regionview.h" #include "utils.h" #include "canvas_impl.h" @@ -43,7 +43,7 @@ using namespace Canvas; sigc::signal<void,CrossfadeView*> CrossfadeView::GoingAway; CrossfadeView::CrossfadeView (ArdourCanvas::Group *parent, - AudioTimeAxisView &tv, + RouteTimeAxisView &tv, Crossfade& xf, double spu, Gdk::Color& basic_color, @@ -227,7 +227,7 @@ CrossfadeView::set_valid (bool yn) AudioRegionView& CrossfadeView::upper_regionview () const { - if (left_view.region.layer() > right_view.region.layer()) { + if (left_view.region().layer() > right_view.region().layer()) { return left_view; } else { return right_view; diff --git a/gtk2_ardour/crossfade_view.h b/gtk2_ardour/crossfade_view.h index 403edfe297..adbd74b420 100644 --- a/gtk2_ardour/crossfade_view.h +++ b/gtk2_ardour/crossfade_view.h @@ -28,13 +28,13 @@ #include "time_axis_view_item.h" -class AudioTimeAxisView; +class RouteTimeAxisView; class AudioRegionView; struct CrossfadeView : public TimeAxisViewItem { CrossfadeView (ArdourCanvas::Group*, - AudioTimeAxisView&, + RouteTimeAxisView&, ARDOUR::Crossfade&, double initial_samples_per_unit, Gdk::Color& basic_color, diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 22639dc258..c391ba2bf7 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -56,10 +56,10 @@ #include "keyboard.h" #include "marker.h" #include "playlist_selector.h" -#include "regionview.h" +#include "audio_regionview.h" #include "rgb_macros.h" #include "selection.h" -#include "streamview.h" +#include "audio_streamview.h" #include "time_axis_view.h" #include "utils.h" #include "crossfade_view.h" @@ -681,7 +681,7 @@ Editor::Editor (AudioEngine& eng) _playlist_selector = new PlaylistSelector(); _playlist_selector->signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector))); - AudioRegionView::AudioRegionViewGoingAway.connect (mem_fun(*this, &Editor::catch_vanishing_audio_regionview)); + RegionView::RegionViewGoingAway.connect (mem_fun(*this, &Editor::catch_vanishing_regionview)); /* nudge stuff */ @@ -739,7 +739,7 @@ Editor::add_toplevel_controls (Container& cont) } void -Editor::catch_vanishing_audio_regionview (AudioRegionView *rv) +Editor::catch_vanishing_regionview (RegionView *rv) { /* note: the selection will take care of the vanishing audioregionview by itself. @@ -755,7 +755,7 @@ Editor::catch_vanishing_audio_regionview (AudioRegionView *rv) } void -Editor::set_entered_regionview (AudioRegionView* rv) +Editor::set_entered_regionview (RegionView* rv) { if (rv == entered_regionview) { return; @@ -1185,7 +1185,7 @@ Editor::connect_to_session (Session *t) session_connections.push_back (session->TransportStateChange.connect (mem_fun(*this, &Editor::map_transport_state))); session_connections.push_back (session->PositionChanged.connect (mem_fun(*this, &Editor::map_position_change))); - session_connections.push_back (session->RouteAdded.connect (mem_fun(*this, &Editor::handle_new_route_p))); + session_connections.push_back (session->RouteAdded.connect (mem_fun(*this, &Editor::handle_new_route))); session_connections.push_back (session->AudioRegionAdded.connect (mem_fun(*this, &Editor::handle_new_audio_region))); session_connections.push_back (session->AudioRegionRemoved.connect (mem_fun(*this, &Editor::handle_audio_region_removed))); session_connections.push_back (session->DurationChanged.connect (mem_fun(*this, &Editor::handle_new_duration))); @@ -1409,7 +1409,7 @@ Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* i switch (item_type) { case FadeInItem: case FadeInHandleItem: - if (arv->region.fade_in_active()) { + if (arv->audio_region().fade_in_active()) { items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), false))); } else { items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), true))); @@ -1417,16 +1417,16 @@ Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* i items.push_back (SeparatorElem()); - items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Linear))); - items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogB))); - items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Fast))); - items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogA))); - items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Slow))); + items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->audio_region(), &AudioRegion::set_fade_in_shape), AudioRegion::Linear))); + items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->audio_region(), &AudioRegion::set_fade_in_shape), AudioRegion::LogB))); + items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->audio_region(), &AudioRegion::set_fade_in_shape), AudioRegion::Fast))); + items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->audio_region(), &AudioRegion::set_fade_in_shape), AudioRegion::LogA))); + items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->audio_region(), &AudioRegion::set_fade_in_shape), AudioRegion::Slow))); break; case FadeOutItem: case FadeOutHandleItem: - if (arv->region.fade_out_active()) { + if (arv->audio_region().fade_out_active()) { items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), false))); } else { items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), true))); @@ -1434,11 +1434,11 @@ Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* i items.push_back (SeparatorElem()); - items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Linear))); - items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Fast))); - items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogB))); - items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogA))); - items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Slow))); + items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->audio_region(), &AudioRegion::set_fade_out_shape), AudioRegion::Linear))); + items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->audio_region(), &AudioRegion::set_fade_out_shape), AudioRegion::Fast))); + items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->audio_region(), &AudioRegion::set_fade_out_shape), AudioRegion::LogB))); + items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->audio_region(), &AudioRegion::set_fade_out_shape), AudioRegion::LogA))); + items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->audio_region(), &AudioRegion::set_fade_out_shape), AudioRegion::Slow))); break; default: @@ -1460,8 +1460,8 @@ Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, switch (item_type) { case RegionItem: - case AudioRegionViewName: - case AudioRegionViewNameHighlight: + case RegionViewName: + case RegionViewNameHighlight: if (with_selection) { build_menu_function = &Editor::build_track_selection_context_menu; } else { @@ -1501,25 +1501,26 @@ Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, switch (item_type) { case RegionItem: - case AudioRegionViewName: - case AudioRegionViewNameHighlight: + case RegionViewName: + case RegionViewNameHighlight: if (!with_selection) { if (region_edit_menu_split_item) { - if (clicked_regionview && clicked_regionview->region.covers (edit_cursor->current_frame)) { + if (clicked_regionview && clicked_regionview->region().covers (edit_cursor->current_frame)) { ActionManager::set_sensitive (ActionManager::edit_cursor_in_region_sensitive_actions, true); } else { ActionManager::set_sensitive (ActionManager::edit_cursor_in_region_sensitive_actions, false); } } + /* if (region_edit_menu_split_multichannel_item) { - if (clicked_regionview && clicked_regionview->region.n_channels() > 1) { + if (clicked_regionview && clicked_regionview->region().n_channels() > 1) { // GTK2FIX find the action, change its sensitivity // region_edit_menu_split_multichannel_item->set_sensitive (true); } else { // GTK2FIX see above // region_edit_menu_split_multichannel_item->set_sensitive (false); } - } + }*/ } break; @@ -1605,7 +1606,7 @@ Editor::build_track_region_context_menu (jack_nframes_t frame) if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) { Playlist::RegionList* regions = pl->regions_at ((jack_nframes_t) floor ( (double)frame * ds->speed())); for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) { - add_region_context_items (atv->view, (*i), edit_items); + add_region_context_items (atv->audio_view(), (*i), edit_items); } delete regions; } @@ -1640,11 +1641,11 @@ Editor::build_track_crossfade_context_menu (jack_nframes_t frame) bool many = xfades.size() > 1; for (AudioPlaylist::Crossfades::iterator i = xfades.begin(); i != xfades.end(); ++i) { - add_crossfade_context_items (atv->view, (*i), edit_items, many); + add_crossfade_context_items (atv->audio_view(), (*i), edit_items, many); } for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) { - add_region_context_items (atv->view, (*i), edit_items); + add_region_context_items (atv->audio_view(), (*i), edit_items); } delete regions; @@ -1710,7 +1711,7 @@ Editor::build_track_selection_context_menu (jack_nframes_t ignored) } void -Editor::add_crossfade_context_items (StreamView* view, Crossfade* xfade, Menu_Helpers::MenuList& edit_items, bool many) +Editor::add_crossfade_context_items (AudioStreamView* view, Crossfade* xfade, Menu_Helpers::MenuList& edit_items, bool many) { using namespace Menu_Helpers; Menu *xfade_menu = manage (new Menu); @@ -1767,7 +1768,7 @@ Editor::xfade_edit_right_region () } void -Editor::add_region_context_items (StreamView* sv, Region* region, Menu_Helpers::MenuList& edit_items) +Editor::add_region_context_items (AudioStreamView* sv, Region* region, Menu_Helpers::MenuList& edit_items) { using namespace Menu_Helpers; Menu *region_menu = manage (new Menu); @@ -3019,31 +3020,31 @@ Editor::mapover_audio_tracks (slot<void,AudioTimeAxisView&,uint32_t> sl) } void -Editor::mapped_set_selected_regionview_from_click (AudioTimeAxisView& atv, uint32_t ignored, - AudioRegionView* basis, vector<AudioRegionView*>* all_equivs) +Editor::mapped_set_selected_regionview_from_click (RouteTimeAxisView& tv, uint32_t ignored, + RegionView* basis, vector<RegionView*>* all_equivs) { - AudioPlaylist* pl; - vector<AudioRegion*> results; - AudioRegionView* marv; - AudioDiskstream* ds; + Playlist* pl; + vector<Region*> results; + RegionView* marv; + Diskstream* ds; - if ((ds = atv.get_diskstream()) == 0) { + if ((ds = tv.get_diskstream()) == 0) { /* bus */ return; } - if (&atv == &basis->get_time_axis_view()) { + if (&tv == &basis->get_time_axis_view()) { /* looking in same track as the original */ return; } - if ((pl = dynamic_cast<AudioPlaylist*>(ds->playlist())) != 0) { - pl->get_equivalent_regions (basis->region, results); + if ((pl = dynamic_cast<Playlist*>(ds->playlist())) != 0) { + pl->get_equivalent_regions (basis->region(), results); } - for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) { - if ((marv = atv.view->find_view (**ir)) != 0) { + for (vector<Region*>::iterator ir = results.begin(); ir != results.end(); ++ir) { + if ((marv = tv.view()->find_view (**ir)) != 0) { all_equivs->push_back (marv); } } @@ -3052,7 +3053,7 @@ Editor::mapped_set_selected_regionview_from_click (AudioTimeAxisView& atv, uint3 bool Editor::set_selected_regionview_from_click (bool press, Selection::Operation op, bool no_track_remove) { - vector<AudioRegionView*> all_equivalent_regions; + vector<RegionView*> all_equivalent_regions; bool commit = false; if (!clicked_regionview || !clicked_audio_trackview) { @@ -3107,7 +3108,7 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op, commit = true; } - for (vector<AudioRegionView*>::iterator i = all_equivalent_regions.begin(); i != all_equivalent_regions.end(); ++i) { + for (vector<RegionView*>::iterator i = all_equivalent_regions.begin(); i != all_equivalent_regions.end(); ++i) { selection->add (*i); } } @@ -3140,58 +3141,58 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op, last_frame = 0; first_frame = max_frames; - for (AudioRegionSelection::iterator x = selection->audio_regions.begin(); x != selection->audio_regions.end(); ++x) { + for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) { if (&(*x)->get_time_axis_view() == &clicked_regionview->get_time_axis_view()) { - if ((*x)->region.last_frame() > last_frame) { - last_frame = (*x)->region.last_frame(); + if ((*x)->region().last_frame() > last_frame) { + last_frame = (*x)->region().last_frame(); } - if ((*x)->region.first_frame() < first_frame) { - first_frame = (*x)->region.first_frame(); + if ((*x)->region().first_frame() < first_frame) { + first_frame = (*x)->region().first_frame(); } } } /* 2. figure out the boundaries for our search for new objects */ - switch (clicked_regionview->region.coverage (first_frame, last_frame)) { + switch (clicked_regionview->region().coverage (first_frame, last_frame)) { case OverlapNone: cerr << "no overlap, first = " << first_frame << " last = " << last_frame << " region = " - << clicked_regionview->region.first_frame() << " .. " << clicked_regionview->region.last_frame() << endl; + << clicked_regionview->region().first_frame() << " .. " << clicked_regionview->region().last_frame() << endl; - if (last_frame < clicked_regionview->region.first_frame()) { + if (last_frame < clicked_regionview->region().first_frame()) { first_frame = last_frame; - last_frame = clicked_regionview->region.last_frame(); + last_frame = clicked_regionview->region().last_frame(); } else { last_frame = first_frame; - first_frame = clicked_regionview->region.first_frame(); + first_frame = clicked_regionview->region().first_frame(); } break; case OverlapExternal: cerr << "external overlap, first = " << first_frame << " last = " << last_frame << " region = " - << clicked_regionview->region.first_frame() << " .. " << clicked_regionview->region.last_frame() << endl; + << clicked_regionview->region().first_frame() << " .. " << clicked_regionview->region().last_frame() << endl; - if (last_frame < clicked_regionview->region.first_frame()) { + if (last_frame < clicked_regionview->region().first_frame()) { first_frame = last_frame; - last_frame = clicked_regionview->region.last_frame(); + last_frame = clicked_regionview->region().last_frame(); } else { last_frame = first_frame; - first_frame = clicked_regionview->region.first_frame(); + first_frame = clicked_regionview->region().first_frame(); } break; case OverlapInternal: cerr << "internal overlap, first = " << first_frame << " last = " << last_frame << " region = " - << clicked_regionview->region.first_frame() << " .. " << clicked_regionview->region.last_frame() << endl; + << clicked_regionview->region().first_frame() << " .. " << clicked_regionview->region().last_frame() << endl; - if (last_frame < clicked_regionview->region.first_frame()) { + if (last_frame < clicked_regionview->region().first_frame()) { first_frame = last_frame; - last_frame = clicked_regionview->region.last_frame(); + last_frame = clicked_regionview->region().last_frame(); } else { last_frame = first_frame; - first_frame = clicked_regionview->region.first_frame(); + first_frame = clicked_regionview->region().first_frame(); } break; @@ -3217,18 +3218,18 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op, /* 3. convert to a vector of audio regions */ - vector<AudioRegionView*> audio_regions; + vector<RegionView*> regions; for (list<Selectable*>::iterator x = results.begin(); x != results.end(); ++x) { - AudioRegionView* arv; + RegionView* arv; - if ((arv = dynamic_cast<AudioRegionView*>(*x)) != 0) { - audio_regions.push_back (arv); + if ((arv = dynamic_cast<RegionView*>(*x)) != 0) { + regions.push_back (arv); } } - if (!audio_regions.empty()) { - selection->add (audio_regions); + if (!regions.empty()) { + selection->add (regions); commit = true; } } @@ -3238,37 +3239,32 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op, } void -Editor::set_selected_regionview_from_region_list (Region& r, Selection::Operation op) +Editor::set_selected_regionview_from_region_list (Region& region, Selection::Operation op) { - vector<AudioRegionView*> all_equivalent_regions; - AudioRegion* region; - - if ((region = dynamic_cast<AudioRegion*>(&r)) == 0) { - return; - } + vector<RegionView*> all_equivalent_regions; for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { - AudioTimeAxisView* tatv; + RouteTimeAxisView* tatv; - if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) { + if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) { - AudioPlaylist* pl; - vector<AudioRegion*> results; - AudioRegionView* marv; - AudioDiskstream* ds; + Playlist* pl; + vector<Region*> results; + RegionView* marv; + Diskstream* ds; if ((ds = tatv->get_diskstream()) == 0) { /* bus */ continue; } - if ((pl = dynamic_cast<AudioPlaylist*>(ds->playlist())) != 0) { - pl->get_region_list_equivalent_regions (*region, results); + if ((pl = dynamic_cast<Playlist*>(ds->playlist())) != 0) { + pl->get_region_list_equivalent_regions (region, results); } - for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) { - if ((marv = tatv->view->find_view (**ir)) != 0) { + for (vector<Region*>::iterator ir = results.begin(); ir != results.end(); ++ir) { + if ((marv = tatv->view()->find_view (**ir)) != 0) { all_equivalent_regions.push_back (marv); } } @@ -3297,10 +3293,10 @@ Editor::set_selected_regionview_from_region_list (Region& r, Selection::Operatio bool Editor::set_selected_regionview_from_map_event (GdkEventAny* ev, StreamView* sv, Region* r) { - AudioRegionView* rv; - AudioRegion* ar; + RegionView* rv; + Region* ar; - if ((ar = dynamic_cast<AudioRegion*> (r)) == 0) { + if ((ar = dynamic_cast<Region*> (r)) == 0) { return TRUE; } @@ -3312,7 +3308,7 @@ Editor::set_selected_regionview_from_map_event (GdkEventAny* ev, StreamView* sv, a single other region. */ - if (selection->audio_regions.size() > 1) { + if (selection->regions.size() > 1) { return TRUE; } @@ -3477,7 +3473,7 @@ Editor::duplicate_dialog (bool dup_region) if (sscanf (text.c_str(), "%f", ×) == 1) { if (dup_region) { - AudioRegionSelection regions; + RegionSelection regions; regions.add (clicked_regionview); duplicate_some_regions (regions, times); } else { @@ -3699,7 +3695,7 @@ void Editor::region_selection_changed () { for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { - (*i)->set_selected_regionviews (selection->audio_regions); + (*i)->set_selected_regionviews (selection->regions); } } @@ -3969,8 +3965,8 @@ Editor::playlist_deletion_dialog (Playlist* pl) bool Editor::audio_region_selection_covers (jack_nframes_t where) { - for (AudioRegionSelection::iterator a = selection->audio_regions.begin(); a != selection->audio_regions.end(); ++a) { - if ((*a)->region.covers (where)) { + for (RegionSelection::iterator a = selection->regions.begin(); a != selection->regions.end(); ++a) { + if ((*a)->region().covers (where)) { return true; } } @@ -3981,10 +3977,10 @@ Editor::audio_region_selection_covers (jack_nframes_t where) void Editor::prepare_for_cleanup () { - cut_buffer->clear_audio_regions (); + cut_buffer->clear_regions (); cut_buffer->clear_playlists (); - selection->clear_audio_regions (); + selection->clear_regions (); selection->clear_playlists (); } diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 5e8fdc2b5c..0204e6b10a 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -101,6 +101,7 @@ class TrackSelection; class AutomationSelection; class MixerStrip; class StreamView; +class AudioStreamView; class ControlPoint; #ifdef FFT_ANALYSIS class AnalysisWindow; @@ -406,8 +407,8 @@ class Editor : public PublicEditor TimeAxisView* clicked_trackview; AudioTimeAxisView* clicked_audio_trackview; - AudioRegionView* clicked_regionview; - AudioRegionView* latest_regionview; + RegionView* clicked_regionview; + RegionView* latest_regionview; uint32_t clicked_selection; CrossfadeView* clicked_crossfadeview; ControlPoint* clicked_control_point; @@ -417,7 +418,7 @@ class Editor : public PublicEditor /* functions to be passed to mapover_audio_tracks(), possibly with sigc::bind()-supplied arguments */ - void mapped_set_selected_regionview_from_click (AudioTimeAxisView&, uint32_t, AudioRegionView*, vector<AudioRegionView*>*); + void mapped_set_selected_regionview_from_click (RouteTimeAxisView&, uint32_t, RegionView*, vector<RegionView*>*); void mapped_use_new_playlist (AudioTimeAxisView&, uint32_t); void mapped_use_copy_playlist (AudioTimeAxisView&, uint32_t); void mapped_clear_playlist (AudioTimeAxisView&, uint32_t); @@ -427,7 +428,7 @@ class Editor : public PublicEditor void button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type); bool button_release_can_deselect; - void catch_vanishing_audio_regionview (AudioRegionView *); + void catch_vanishing_regionview (RegionView *); bool set_selected_control_point_from_click (bool press, Selection::Operation op = Selection::Set, bool with_undo = true, bool no_remove=false); bool set_selected_track_from_click (bool press, Selection::Operation op = Selection::Set, bool with_undo = true, bool no_remove=false); @@ -435,7 +436,7 @@ class Editor : public PublicEditor void set_selected_regionview_from_region_list (ARDOUR::Region& region, Selection::Operation op = Selection::Set); bool set_selected_regionview_from_map_event (GdkEventAny*, StreamView*, ARDOUR::Region*); - void collect_new_region_view (AudioRegionView *); + void collect_new_region_view (RegionView *); Gtk::Menu track_context_menu; Gtk::Menu track_region_context_menu; @@ -456,12 +457,11 @@ class Editor : public PublicEditor Gtk::Menu* build_track_selection_context_menu (jack_nframes_t); void add_dstream_context_items (Gtk::Menu_Helpers::MenuList&); void add_bus_context_items (Gtk::Menu_Helpers::MenuList&); - void add_region_context_items (StreamView*, ARDOUR::Region*, Gtk::Menu_Helpers::MenuList&); - void add_crossfade_context_items (StreamView*, ARDOUR::Crossfade*, Gtk::Menu_Helpers::MenuList&, bool many); + void add_region_context_items (AudioStreamView*, ARDOUR::Region*, Gtk::Menu_Helpers::MenuList&); + void add_crossfade_context_items (AudioStreamView*, ARDOUR::Crossfade*, Gtk::Menu_Helpers::MenuList&, bool many); void add_selection_context_items (Gtk::Menu_Helpers::MenuList&); - void handle_new_route (ARDOUR::Route&); - void handle_new_route_p (ARDOUR::Route*); + void handle_new_route (ARDOUR::Route*); void remove_route (TimeAxisView *); bool route_removal; @@ -855,7 +855,7 @@ class Editor : public PublicEditor void lower_region_to_bottom (); void split_region (); void split_region_at (jack_nframes_t); - void split_regions_at (jack_nframes_t, AudioRegionSelection&); + void split_regions_at (jack_nframes_t, RegionSelection&); void crop_region_to_selection (); void set_a_regions_sync_position (ARDOUR::Region&, jack_nframes_t); void set_region_sync_from_edit_cursor (); @@ -868,13 +868,13 @@ class Editor : public PublicEditor void remove_clicked_region (); void destroy_clicked_region (); void edit_region (); - void duplicate_some_regions (AudioRegionSelection&, float times); + void duplicate_some_regions (RegionSelection&, float times); void duplicate_selection (float times); void region_fill_selection (); void region_fill_track (); - void audition_playlist_region_standalone (ARDOUR::AudioRegion&); - void audition_playlist_region_via_route (ARDOUR::AudioRegion&, ARDOUR::Route&); + void audition_playlist_region_standalone (ARDOUR::Region&); + void audition_playlist_region_via_route (ARDOUR::Region&, ARDOUR::Route&); void split_multichannel_region(); void reverse_region (); void normalize_region (); @@ -1021,7 +1021,7 @@ class Editor : public PublicEditor bool have_pending_keyboard_selection; jack_nframes_t pending_keyboard_selection_start; - ARDOUR::AudioRegion* select_region_for_operation (int dir, TimeAxisView **tv); + ARDOUR::Region* select_region_for_operation (int dir, TimeAxisView **tv); void extend_selection_to_end_of_region (bool next); void extend_selection_to_start_of_region (bool previous); @@ -1095,7 +1095,7 @@ class Editor : public PublicEditor void remove_gain_control_point (ArdourCanvas::Item*, GdkEvent*); void remove_control_point (ArdourCanvas::Item*, GdkEvent*); - void mouse_brush_insert_region (AudioRegionView*, jack_nframes_t pos); + void mouse_brush_insert_region (RegionView*, jack_nframes_t pos); void brush (jack_nframes_t); void show_verbose_time_cursor (jack_nframes_t frame, double offset = 0, double xpos=-1, double ypos=-1); @@ -1113,10 +1113,10 @@ class Editor : public PublicEditor bool canvas_fade_in_handle_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*); bool canvas_fade_out_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*); bool canvas_fade_out_handle_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*); - bool canvas_region_view_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*); - bool canvas_region_view_name_highlight_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*); + bool canvas_region_view_event (GdkEvent* event,ArdourCanvas::Item*, RegionView*); + bool canvas_region_view_name_highlight_event (GdkEvent* event,ArdourCanvas::Item*, RegionView*); bool canvas_region_view_name_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*); - bool canvas_stream_view_event (GdkEvent* event,ArdourCanvas::Item*, AudioTimeAxisView*); + bool canvas_stream_view_event (GdkEvent* event,ArdourCanvas::Item*, RouteTimeAxisView*); bool canvas_marker_event (GdkEvent* event,ArdourCanvas::Item*, Marker*); bool canvas_zoom_rect_event (GdkEvent* event,ArdourCanvas::Item*); bool canvas_tempo_marker_event (GdkEvent* event,ArdourCanvas::Item*, TempoMarker*); @@ -1520,12 +1520,12 @@ class Editor : public PublicEditor void start_trim (ArdourCanvas::Item*, GdkEvent*); void point_trim (GdkEvent*); void trim_motion_callback (ArdourCanvas::Item*, GdkEvent*); - void single_contents_trim (AudioRegionView&, jack_nframes_t, bool, bool, bool); - void single_start_trim (AudioRegionView&, jack_nframes_t, bool, bool); - void single_end_trim (AudioRegionView&, jack_nframes_t, bool, bool); + void single_contents_trim (RegionView&, jack_nframes_t, bool, bool, bool); + void single_start_trim (RegionView&, jack_nframes_t, bool, bool); + void single_end_trim (RegionView&, jack_nframes_t, bool, bool); void trim_finished_callback (ArdourCanvas::Item*, GdkEvent*); - void thaw_region_after_trim (AudioRegionView& rv); + void thaw_region_after_trim (RegionView& rv); void trim_region_to_edit_cursor (); void trim_region_from_edit_cursor (); @@ -1579,7 +1579,7 @@ class Editor : public PublicEditor void export_range (jack_nframes_t start, jack_nframes_t end); void export_range_markers (); - int write_region_selection(AudioRegionSelection&); + int write_region_selection(RegionSelection&); bool write_region (string path, ARDOUR::AudioRegion&); void export_region (); void bounce_region_selection (); @@ -1657,7 +1657,7 @@ class Editor : public PublicEditor struct TimeStretchDialog : public ArdourDialog { ARDOUR::Session::TimeStretchRequest request; Editor& editor; - AudioRegionSelection regions; + RegionSelection regions; Gtk::ProgressBar progress_bar; Gtk::ToggleButton quick_button; Gtk::ToggleButton antialias_button; @@ -1683,7 +1683,7 @@ class Editor : public PublicEditor TimeStretchDialog* current_timestretch; static void* timestretch_thread (void *arg); - int run_timestretch (AudioRegionSelection&, float fraction); + int run_timestretch (RegionSelection&, float fraction); void do_timestretch (TimeStretchDialog&); /* editor-mixer strip */ @@ -1784,11 +1784,11 @@ class Editor : public PublicEditor sigc::connection step_timeout; TimeAxisView* entered_track; - AudioRegionView* entered_regionview; + RegionView* entered_regionview; bool clear_entered_track; gint left_track_canvas (GdkEventCrossing*); void set_entered_track (TimeAxisView*); - void set_entered_regionview (AudioRegionView*); + void set_entered_regionview (RegionView*); gint left_automation_track (); bool _new_regionviews_show_envelope; diff --git a/gtk2_ardour/editor_audiotrack.cc b/gtk2_ardour/editor_audiotrack.cc index acad3371a0..cc6a36c95a 100644 --- a/gtk2_ardour/editor_audiotrack.cc +++ b/gtk2_ardour/editor_audiotrack.cc @@ -4,7 +4,7 @@ #include "editor.h" #include "editing.h" #include "audio_time_axis.h" -#include "regionview.h" +#include "audio_regionview.h" #include "selection.h" using namespace ARDOUR; diff --git a/gtk2_ardour/editor_canvas_events.cc b/gtk2_ardour/editor_canvas_events.cc index dd87fc0bce..090d3aa591 100644 --- a/gtk2_ardour/editor_canvas_events.cc +++ b/gtk2_ardour/editor_canvas_events.cc @@ -26,8 +26,8 @@ #include "editor.h" #include "public_editor.h" -#include "regionview.h" -#include "streamview.h" +#include "audio_regionview.h" +#include "audio_streamview.h" #include "crossfade_view.h" #include "audio_time_axis.h" #include "region_gain_line.h" @@ -212,10 +212,12 @@ Editor::typed_event (ArdourCanvas::Item* item, GdkEvent *event, ItemType type) } bool -Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv) +Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView *rv) { gint ret = FALSE; + /* FIXME: type specific */ + switch (event->type) { case GDK_BUTTON_PRESS: case GDK_2BUTTON_PRESS: @@ -251,8 +253,10 @@ Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, Aud } bool -Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, AudioTimeAxisView *tv) +Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, RouteTimeAxisView *tv) { + /* FIXME: type specific */ + bool ret = FALSE; switch (event->type) { @@ -262,7 +266,7 @@ Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, Aud clicked_regionview = 0; clicked_control_point = 0; clicked_trackview = tv; - clicked_audio_trackview = tv; + clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(tv); ret = button_press_handler (item, event, StreamItem); break; @@ -522,13 +526,13 @@ Editor::canvas_crossfade_view_event (GdkEvent* event, ArdourCanvas::Item* item, DescendingRegionLayerSorter cmp; rl->sort (cmp); - AudioRegionView* arv = atv->view->find_view (*(dynamic_cast<AudioRegion*> (rl->front()))); + RegionView* rv = atv->view()->find_view (*rl->front()); /* proxy */ delete rl; - return canvas_region_view_event (event, arv->get_canvas_group(), arv); + return canvas_region_view_event (event, rv->get_canvas_group(), rv); } } } @@ -699,10 +703,12 @@ Editor::canvas_selection_end_trim_event (GdkEvent *event, ArdourCanvas::Item* it bool -Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::Item* item, AudioRegionView* rv) +Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv) { bool ret = false; + /* FIXME: type specific (audio only) */ + switch (event->type) { case GDK_BUTTON_PRESS: case GDK_2BUTTON_PRESS: @@ -711,20 +717,20 @@ Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas:: clicked_control_point = 0; clicked_trackview = &clicked_regionview->get_time_axis_view(); clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview); - ret = button_press_handler (item, event, AudioRegionViewNameHighlight); + ret = button_press_handler (item, event, RegionViewNameHighlight); break; case GDK_BUTTON_RELEASE: - ret = button_release_handler (item, event, AudioRegionViewNameHighlight); + ret = button_release_handler (item, event, RegionViewNameHighlight); break; case GDK_MOTION_NOTIFY: - ret = motion_handler (item, event, AudioRegionViewNameHighlight); + ret = motion_handler (item, event, RegionViewNameHighlight); break; case GDK_ENTER_NOTIFY: - ret = enter_handler (item, event, AudioRegionViewNameHighlight); + ret = enter_handler (item, event, RegionViewNameHighlight); break; case GDK_LEAVE_NOTIFY: - ret = leave_handler (item, event, AudioRegionViewNameHighlight); + ret = leave_handler (item, event, RegionViewNameHighlight); break; default: @@ -747,20 +753,20 @@ Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item clicked_control_point = 0; clicked_trackview = &clicked_regionview->get_time_axis_view(); clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview); - ret = button_press_handler (item, event, AudioRegionViewName); + ret = button_press_handler (item, event, RegionViewName); break; case GDK_BUTTON_RELEASE: - ret = button_release_handler (item, event, AudioRegionViewName); + ret = button_release_handler (item, event, RegionViewName); break; case GDK_MOTION_NOTIFY: - ret = motion_handler (item, event, AudioRegionViewName); + ret = motion_handler (item, event, RegionViewName); break; case GDK_ENTER_NOTIFY: - ret = enter_handler (item, event, AudioRegionViewName); + ret = enter_handler (item, event, RegionViewName); break; case GDK_LEAVE_NOTIFY: - ret = leave_handler (item, event, AudioRegionViewName); + ret = leave_handler (item, event, RegionViewName); break; default: diff --git a/gtk2_ardour/editor_export_audio.cc b/gtk2_ardour/editor_export_audio.cc index f76f494e5f..9868a868c7 100644 --- a/gtk2_ardour/editor_export_audio.cc +++ b/gtk2_ardour/editor_export_audio.cc @@ -31,7 +31,7 @@ #include "selection.h" #include "time_axis_view.h" #include "audio_time_axis.h" -#include "regionview.h" +#include "audio_regionview.h" #include <pbd/pthread_utils.h> #include <ardour/types.h> @@ -92,12 +92,12 @@ Editor::export_region () return; } - ExportDialog* dialog = new ExportRegionDialog (*this, &clicked_regionview->region); + ExportDialog* dialog = new ExportRegionDialog (*this, &clicked_regionview->region()); dialog->connect_to_session (session); dialog->set_range ( - clicked_regionview->region.first_frame(), - clicked_regionview->region.last_frame()); + clicked_regionview->region().first_frame(), + clicked_regionview->region().last_frame()); dialog->start_export(); } @@ -123,24 +123,27 @@ Editor::export_range_markers () } int -Editor::write_region_selection (AudioRegionSelection& regions) +Editor::write_region_selection (RegionSelection& regions) { - for (AudioRegionSelection::iterator i = regions.begin(); i != regions.end(); ++i) { - if (write_region ("", (*i)->region) == false) { - return -1; - } + for (RegionSelection::iterator i = regions.begin(); i != regions.end(); ++i) { + // FIXME + AudioRegionView* arv = dynamic_cast<AudioRegionView*>(*i); + if (arv) + if (write_region ("", arv->audio_region()) == false) + return -1; } + return 0; } void Editor::bounce_region_selection () { - for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { + for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { - AudioRegion& region ((*i)->region); - AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&(*i)->get_time_axis_view()); - AudioTrack* track = dynamic_cast<AudioTrack*>(&(atv->route())); + Region& region ((*i)->region()); + RouteTimeAxisView* atv = dynamic_cast<RouteTimeAxisView*>(&(*i)->get_time_axis_view()); + Track* track = dynamic_cast<Track*>(&(atv->route())); InterThreadInfo itt; @@ -435,7 +438,7 @@ Editor::write_selection () { if (!selection->time.empty()) { write_audio_selection (selection->time); - } else if (!selection->audio_regions.empty()) { - write_region_selection (selection->audio_regions); + } else if (!selection->regions.empty()) { + write_region_selection (selection->regions); } } diff --git a/gtk2_ardour/editor_items.h b/gtk2_ardour/editor_items.h index 4f6010ec2c..7f3a0d3fcc 100644 --- a/gtk2_ardour/editor_items.h +++ b/gtk2_ardour/editor_items.h @@ -23,8 +23,8 @@ enum ItemType { TempoMarkerItem, MeterBarItem, TempoBarItem, - AudioRegionViewNameHighlight, - AudioRegionViewName, + RegionViewNameHighlight, + RegionViewName, StartSelectionTrimItem, EndSelectionTrimItem, AutomationTrackItem, diff --git a/gtk2_ardour/editor_keyboard.cc b/gtk2_ardour/editor_keyboard.cc index 1ffaf2146d..5258e6a70a 100644 --- a/gtk2_ardour/editor_keyboard.cc +++ b/gtk2_ardour/editor_keyboard.cc @@ -81,10 +81,10 @@ Editor::kbd_do_split (GdkEvent* ev) jack_nframes_t where = event_frame (ev); if (entered_regionview) { - if (selection->audio_regions.find (entered_regionview) != selection->audio_regions.end()) { - split_regions_at (where, selection->audio_regions); + if (selection->regions.find (entered_regionview) != selection->regions.end()) { + split_regions_at (where, selection->regions); } else { - AudioRegionSelection s; + RegionSelection s; s.add (entered_regionview); split_regions_at (where, s); } @@ -102,11 +102,11 @@ Editor::kbd_mute_unmute_region () { if (entered_regionview) { begin_reversible_command (_("mute region")); - session->add_undo (entered_regionview->region.playlist()->get_memento()); + session->add_undo (entered_regionview->region().playlist()->get_memento()); - entered_regionview->region.set_muted (!entered_regionview->region.muted()); + entered_regionview->region().set_muted (!entered_regionview->region().muted()); - session->add_redo_no_execute (entered_regionview->region.playlist()->get_memento()); + session->add_redo_no_execute (entered_regionview->region().playlist()->get_memento()); commit_reversible_command(); } } @@ -124,7 +124,7 @@ Editor::kbd_do_set_sync_position (GdkEvent* ev) snap_to (where); if (entered_regionview) { - set_a_regions_sync_position (entered_regionview->region, where); + set_a_regions_sync_position (entered_regionview->region(), where); } } diff --git a/gtk2_ardour/editor_keys.cc b/gtk2_ardour/editor_keys.cc index baa158cbf8..f18c5f164c 100644 --- a/gtk2_ardour/editor_keys.cc +++ b/gtk2_ardour/editor_keys.cc @@ -66,7 +66,7 @@ Editor::keyboard_selection_begin () void Editor::keyboard_duplicate_region () { - if (selection->audio_regions.empty()) { + if (selection->regions.empty()) { return; } @@ -74,9 +74,9 @@ Editor::keyboard_duplicate_region () bool was_floating; if (get_prefix (prefix, was_floating) == 0) { - duplicate_some_regions (selection->audio_regions, prefix); + duplicate_some_regions (selection->regions, prefix); } else { - duplicate_some_regions (selection->audio_regions, 1); + duplicate_some_regions (selection->regions, 1); } } diff --git a/gtk2_ardour/editor_markers.cc b/gtk2_ardour/editor_markers.cc index a584561e42..f34b8590a4 100644 --- a/gtk2_ardour/editor_markers.cc +++ b/gtk2_ardour/editor_markers.cc @@ -714,9 +714,9 @@ Editor::marker_menu_set_from_selection () } } else { - if (!selection->audio_regions.empty()) { - l->set_start (selection->audio_regions.start()); - l->set_end (selection->audio_regions.end_frame()); + if (!selection->regions.empty()) { + l->set_start (selection->regions.start()); + l->set_end (selection->regions.end_frame()); } } } diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index 80e559bec6..10d791a606 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -18,6 +18,7 @@ $Id$ */ +#include <cassert> #include <cstdlib> #include <stdint.h> #include <cmath> @@ -32,7 +33,7 @@ #include "editor.h" #include "time_axis_view.h" #include "audio_time_axis.h" -#include "regionview.h" +#include "audio_regionview.h" #include "marker.h" #include "streamview.h" #include "region_gain_line.h" @@ -51,6 +52,7 @@ #include <ardour/playlist.h> #include <ardour/audioplaylist.h> #include <ardour/audioregion.h> +#include <ardour/midi_region.h> #include <ardour/dB.h> #include <ardour/utils.h> #include <ardour/region_factory.h> @@ -182,7 +184,7 @@ Editor::set_mouse_mode (MouseMode m, bool force) show the object (region) selection. */ - for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { + for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { (*i)->set_should_show_selection (true); } for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { @@ -319,8 +321,8 @@ Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType it commit = (c1 || c2); break; - case AudioRegionViewNameHighlight: - case AudioRegionViewName: + case RegionViewNameHighlight: + case RegionViewName: c1 = set_selected_track_from_click (press, op, true, true); c2 = set_selected_regionview_from_click (press, op, true); commit = (c1 || c2); @@ -521,12 +523,12 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp } break; - case AudioRegionViewNameHighlight: + case RegionViewNameHighlight: start_trim (item, event); return true; break; - case AudioRegionViewName: + case RegionViewName: /* rename happens on edit clicks */ start_trim (clicked_regionview->get_name_highlight(), event); return true; @@ -692,12 +694,12 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp switch (item_type) { - case AudioRegionViewNameHighlight: + case RegionViewNameHighlight: start_trim (item, event); return true; break; - case AudioRegionViewName: + case RegionViewName: start_trim (clicked_regionview->get_name_highlight(), event); return true; break; @@ -853,7 +855,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT edit_meter_marker (item); break; - case AudioRegionViewName: + case RegionViewName: if (clicked_regionview->name_active()) { return mouse_rename_region (item, event); } @@ -888,8 +890,8 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT break; case RegionItem: - case AudioRegionViewNameHighlight: - case AudioRegionViewName: + case RegionViewNameHighlight: + case RegionViewName: popup_track_context_menu (1, event->button.time, item_type, false, where); break; @@ -1047,9 +1049,11 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT break; case MouseGain: + // FIXME + assert(dynamic_cast<AudioRegionView*>(clicked_regionview)); switch (item_type) { case RegionItem: - clicked_regionview->add_gain_point_event (item, event); + dynamic_cast<AudioRegionView*>(clicked_regionview)->add_gain_point_event (item, event); return true; break; @@ -1203,7 +1207,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ } break; - case AudioRegionViewNameHighlight: + case RegionViewNameHighlight: if (is_drawable() && mouse_mode == MouseObject) { track_canvas.get_window()->set_cursor (*trimmer_cursor); } @@ -1230,11 +1234,11 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ } break; - case AudioRegionViewName: + case RegionViewName: /* when the name is not an active item, the entire name highlight is for trimming */ - if (!reinterpret_cast<AudioRegionView *> (item->get_data ("regionview"))->name_active()) { + if (!reinterpret_cast<RegionView *> (item->get_data ("regionview"))->name_active()) { if (mouse_mode == MouseObject && is_drawable()) { track_canvas.get_window()->set_cursor (*trimmer_cursor); } @@ -1339,7 +1343,7 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ ControlPoint* cp; Marker *marker; Location *loc; - AudioRegionView* rv; + RegionView* rv; bool is_start; switch (item_type) { @@ -1361,7 +1365,7 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ hide_verbose_canvas_cursor (); break; - case AudioRegionViewNameHighlight: + case RegionViewNameHighlight: case StartSelectionTrimItem: case EndSelectionTrimItem: case EditCursorItem: @@ -1392,9 +1396,9 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ } break; - case AudioRegionViewName: + case RegionViewName: /* see enter_handler() for notes */ - if (!reinterpret_cast<AudioRegionView *> (item->get_data ("regionview"))->name_active()) { + if (!reinterpret_cast<RegionView *> (item->get_data ("regionview"))->name_active()) { if (is_drawable() && mouse_mode == MouseObject) { track_canvas.get_window()->set_cursor (*current_canvas_cursor); } @@ -1429,7 +1433,7 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ case FadeInHandleItem: case FadeOutHandleItem: - rv = static_cast<AudioRegionView*>(item->get_data ("regionview")); + rv = static_cast<RegionView*>(item->get_data ("regionview")); { ArdourCanvas::SimpleRect *rect = dynamic_cast<ArdourCanvas::SimpleRect *> (item); if (rect) { @@ -1524,7 +1528,7 @@ Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item case PanAutomationControlPointItem: case TempoMarkerItem: case MeterMarkerItem: - case AudioRegionViewNameHighlight: + case RegionViewNameHighlight: case StartSelectionTrimItem: case EndSelectionTrimItem: case SelectionItem: @@ -1745,7 +1749,7 @@ Editor::start_fade_in_grab (ArdourCanvas::Item* item, GdkEvent* event) AudioRegionView* arv = static_cast<AudioRegionView*>(drag_info.data); - drag_info.pointer_frame_offset = drag_info.grab_frame - ((jack_nframes_t) arv->region.fade_in().back()->when + arv->region.position()); + drag_info.pointer_frame_offset = drag_info.grab_frame - ((jack_nframes_t) arv->audio_region().fade_in().back()->when + arv->region().position()); } void @@ -1766,17 +1770,17 @@ Editor::fade_in_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) snap_to (pos); } - if (pos < (arv->region.position() + 64)) { + if (pos < (arv->region().position() + 64)) { fade_length = 64; // this should be a minimum defined somewhere - } else if (pos > arv->region.last_frame()) { - fade_length = arv->region.length(); + } else if (pos > arv->region().last_frame()) { + fade_length = arv->region().length(); } else { - fade_length = pos - arv->region.position(); + fade_length = pos - arv->region().position(); } arv->reset_fade_in_shape_width (fade_length); - show_verbose_duration_cursor (arv->region.position(), arv->region.position() + fade_length, 10); + show_verbose_duration_cursor (arv->region().position(), arv->region().position() + fade_length, 10); drag_info.first_move = false; } @@ -1801,20 +1805,20 @@ Editor::fade_in_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* even snap_to (pos); } - if (pos < (arv->region.position() + 64)) { + if (pos < (arv->region().position() + 64)) { fade_length = 64; // this should be a minimum defined somewhere } - else if (pos > arv->region.last_frame()) { - fade_length = arv->region.length(); + else if (pos > arv->region().last_frame()) { + fade_length = arv->region().length(); } else { - fade_length = pos - arv->region.position(); + fade_length = pos - arv->region().position(); } begin_reversible_command (_("change fade in length")); - session->add_undo (arv->region.get_memento()); - arv->region.set_fade_in_length (fade_length); - session->add_redo_no_execute (arv->region.get_memento()); + session->add_undo (arv->region().get_memento()); + arv->audio_region().set_fade_in_length (fade_length); + session->add_redo_no_execute (arv->region().get_memento()); commit_reversible_command (); fade_in_drag_motion_callback (item, event); } @@ -1835,7 +1839,7 @@ Editor::start_fade_out_grab (ArdourCanvas::Item* item, GdkEvent* event) AudioRegionView* arv = static_cast<AudioRegionView*>(drag_info.data); - drag_info.pointer_frame_offset = drag_info.grab_frame - (arv->region.length() - (jack_nframes_t) arv->region.fade_out().back()->when + arv->region.position()); + drag_info.pointer_frame_offset = drag_info.grab_frame - (arv->region().length() - (jack_nframes_t) arv->audio_region().fade_out().back()->when + arv->region().position()); } void @@ -1856,19 +1860,19 @@ Editor::fade_out_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event snap_to (pos); } - if (pos > (arv->region.last_frame() - 64)) { + if (pos > (arv->region().last_frame() - 64)) { fade_length = 64; // this should really be a minimum fade defined somewhere } - else if (pos < arv->region.position()) { - fade_length = arv->region.length(); + else if (pos < arv->region().position()) { + fade_length = arv->region().length(); } else { - fade_length = arv->region.last_frame() - pos; + fade_length = arv->region().last_frame() - pos; } arv->reset_fade_out_shape_width (fade_length); - show_verbose_duration_cursor (arv->region.last_frame() - fade_length, arv->region.last_frame(), 10); + show_verbose_duration_cursor (arv->region().last_frame() - fade_length, arv->region().last_frame(), 10); drag_info.first_move = false; } @@ -1893,20 +1897,20 @@ Editor::fade_out_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* eve snap_to (pos); } - if (pos > (arv->region.last_frame() - 64)) { + if (pos > (arv->region().last_frame() - 64)) { fade_length = 64; // this should really be a minimum fade defined somewhere } - else if (pos < arv->region.position()) { - fade_length = arv->region.length(); + else if (pos < arv->region().position()) { + fade_length = arv->region().length(); } else { - fade_length = arv->region.last_frame() - pos; + fade_length = arv->region().last_frame() - pos; } begin_reversible_command (_("change fade out length")); - session->add_undo (arv->region.get_memento()); - arv->region.set_fade_out_length (fade_length); - session->add_redo_no_execute (arv->region.get_memento()); + session->add_undo (arv->region().get_memento()); + arv->audio_region().set_fade_out_length (fade_length); + session->add_redo_no_execute (arv->region().get_memento()); commit_reversible_command (); fade_out_drag_motion_callback (item, event); @@ -2551,7 +2555,8 @@ Editor::start_line_grab_from_regionview (ArdourCanvas::Item* item, GdkEvent* eve { switch (mouse_mode) { case MouseGain: - start_line_grab (clicked_regionview->get_gain_line(), event); + assert(dynamic_cast<AudioRegionView*>(clicked_regionview)); + start_line_grab (dynamic_cast<AudioRegionView*>(clicked_regionview)->get_gain_line(), event); break; default: break; @@ -2645,7 +2650,7 @@ Editor::line_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event) void Editor::start_region_grab (ArdourCanvas::Item* item, GdkEvent* event) { - if (selection->audio_regions.empty() || clicked_regionview == 0) { + if (selection->regions.empty() || clicked_regionview == 0) { return; } @@ -2659,13 +2664,13 @@ Editor::start_region_grab (ArdourCanvas::Item* item, GdkEvent* event) double speed = 1.0; TimeAxisView* tvp = clicked_trackview; - AudioTimeAxisView* tv = dynamic_cast<AudioTimeAxisView*>(tvp); + RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp); if (tv && tv->is_audio_track()) { speed = tv->get_diskstream()->speed(); } - drag_info.last_frame_position = (jack_nframes_t) (clicked_regionview->region.position() / speed); + drag_info.last_frame_position = (jack_nframes_t) (clicked_regionview->region().position() / speed); drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position; drag_info.last_trackview = &clicked_regionview->get_time_axis_view(); // we want a move threshold @@ -2679,7 +2684,7 @@ Editor::start_region_grab (ArdourCanvas::Item* item, GdkEvent* event) void Editor::start_region_copy_grab (ArdourCanvas::Item* item, GdkEvent* event) { - if (selection->audio_regions.empty() || clicked_regionview == 0) { + if (selection->regions.empty() || clicked_regionview == 0) { return; } @@ -2690,7 +2695,7 @@ Editor::start_region_copy_grab (ArdourCanvas::Item* item, GdkEvent* event) start_grab(event); TimeAxisView* tv = &clicked_regionview->get_time_axis_view(); - AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(tv); + RouteTimeAxisView* atv = dynamic_cast<RouteTimeAxisView*>(tv); double speed = 1.0; if (atv && atv->is_audio_track()) { @@ -2698,7 +2703,7 @@ Editor::start_region_copy_grab (ArdourCanvas::Item* item, GdkEvent* event) } drag_info.last_trackview = &clicked_regionview->get_time_axis_view(); - drag_info.last_frame_position = (jack_nframes_t) (clicked_regionview->region.position() / speed); + drag_info.last_frame_position = (jack_nframes_t) (clicked_regionview->region().position() / speed); drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position; // we want a move threshold drag_info.want_move_threshold = true; @@ -2709,7 +2714,7 @@ Editor::start_region_copy_grab (ArdourCanvas::Item* item, GdkEvent* event) void Editor::start_region_brush_grab (ArdourCanvas::Item* item, GdkEvent* event) { - if (selection->audio_regions.empty() || clicked_regionview == 0) { + if (selection->regions.empty() || clicked_regionview == 0) { return; } @@ -2723,13 +2728,13 @@ Editor::start_region_brush_grab (ArdourCanvas::Item* item, GdkEvent* event) double speed = 1.0; TimeAxisView* tvp = clicked_trackview; - AudioTimeAxisView* tv = dynamic_cast<AudioTimeAxisView*>(tvp); + RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp); if (tv && tv->is_audio_track()) { speed = tv->get_diskstream()->speed(); } - drag_info.last_frame_position = (jack_nframes_t) (clicked_regionview->region.position() / speed); + drag_info.last_frame_position = (jack_nframes_t) (clicked_regionview->region().position() / speed); drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position; drag_info.last_trackview = &clicked_regionview->get_time_axis_view(); // we want a move threshold @@ -2742,9 +2747,12 @@ Editor::start_region_brush_grab (ArdourCanvas::Item* item, GdkEvent* event) void Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) { + /* FIXME: type specific (audio only) */ + double x_delta; double y_delta = 0; AudioRegionView *rv = reinterpret_cast<AudioRegionView*> (drag_info.data); + assert(rv); jack_nframes_t pending_region_position = 0; int32_t pointer_y_span = 0, canvas_pointer_y_span = 0, original_pointer_order; int32_t visible_y_high = 0, visible_y_low = 512; //high meaning higher numbered.. not the height on the screen @@ -2764,18 +2772,18 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) /* duplicate the region(s) */ - vector<AudioRegionView*> new_regionviews; + vector<RegionView*> new_regionviews; set<Playlist*> affected_playlists; pair<set<Playlist*>::iterator,bool> insert_result; - for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) { - AudioRegionView* rv; + for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) { + RegionView* rv; rv = (*i); - Playlist* to_playlist = rv->region.playlist(); - AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&rv->get_time_axis_view()); + Playlist* to_playlist = rv->region().playlist(); + RouteTimeAxisView* atv = dynamic_cast<RouteTimeAxisView*>(&rv->get_time_axis_view()); insert_result = affected_playlists.insert (to_playlist); if (insert_result.second) { @@ -2784,18 +2792,23 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) latest_regionview = 0; - sigc::connection c = atv->view->AudioRegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view)); + sigc::connection c = atv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view)); - /* create a new region with the same name. - */ - - AudioRegion* newregion = new AudioRegion (rv->region); + /* create a new region with the same name. */ + // FIXME: ew + Region* newregion = NULL; + if (dynamic_cast<AudioRegion*>(&rv->region())) + newregion = new AudioRegion (dynamic_cast<AudioRegion&>(rv->region())); + else if (dynamic_cast<MidiRegion*>(&rv->region())) + newregion = new MidiRegion (dynamic_cast<MidiRegion&>(rv->region())); + assert(newregion); + /* if the original region was locked, we don't care */ newregion->set_locked (false); - to_playlist->add_region (*newregion, (jack_nframes_t) (rv->region.position() * atv->get_diskstream()->speed())); + to_playlist->add_region (*newregion, (jack_nframes_t) (rv->region().position() * atv->get_diskstream()->speed())); c.disconnect (); @@ -2907,16 +2920,15 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) } } - for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) { - AudioRegionView* rv2; - rv2 = (*i); + for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) { + RegionView* rv2 = (*i); double ix1, ix2, iy1, iy2; int32_t n = 0; rv2->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2); rv2->get_canvas_group()->i2w (ix1, iy1); TimeAxisView* tvp2 = trackview_by_y_position (iy1); - AudioTimeAxisView* atv2 = dynamic_cast<AudioTimeAxisView*>(tvp2); + RouteTimeAxisView* atv2 = dynamic_cast<RouteTimeAxisView*>(tvp2); if (atv2->order != original_pointer_order) { /* this isn't the pointer track */ @@ -3011,8 +3023,8 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) pending_region_position = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; - sync_offset = rv->region.sync_offset (sync_dir); - sync_frame = rv->region.adjust_to_sync (pending_region_position); + sync_offset = rv->region().sync_offset (sync_dir); + sync_frame = rv->region().adjust_to_sync (pending_region_position); /* we snap if the snap modifier is not enabled. */ @@ -3031,7 +3043,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) pending_region_position = 0; } - if (pending_region_position > max_frames - rv->region.length()) { + if (pending_region_position > max_frames - rv->region().length()) { pending_region_position = drag_info.last_frame_position; } @@ -3073,14 +3085,11 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) } if (x_delta < 0) { - for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) { + for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) { - AudioRegionView* rv2; - rv2 = (*i); + RegionView* rv2 = (*i); - /* if any regionview is at zero, we need to know so we can - stop further leftward motion. - */ + // If any regionview is at zero, we need to know so we can stop further leftward motion. double ix1, ix2, iy1, iy2; rv2->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2); @@ -3098,12 +3107,11 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) ************************************************************/ pair<set<Playlist*>::iterator,bool> insert_result; - const list<AudioRegionView*>& layered_regions = selection->audio_regions.by_layer(); + const list<RegionView*>& layered_regions = selection->regions.by_layer(); - for (list<AudioRegionView*>::const_iterator i = layered_regions.begin(); i != layered_regions.end(); ++i) { + for (list<RegionView*>::const_iterator i = layered_regions.begin(); i != layered_regions.end(); ++i) { - AudioRegionView* rv; - rv = (*i); + RegionView* rv = (*i); double ix1, ix2, iy1, iy2; int32_t temp_pointer_y_span = pointer_y_span; @@ -3184,8 +3192,8 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) if (-x_delta > ix1) { x_delta = -ix1; } - } else if ((x_delta > 0) &&(rv->region.last_frame() > max_frames - x_delta)) { - x_delta = max_frames - rv->region.last_frame(); + } else if ((x_delta > 0) &&(rv->region().last_frame() > max_frames - x_delta)) { + x_delta = max_frames - rv->region().last_frame(); } if (drag_info.first_move) { @@ -3246,11 +3254,11 @@ void Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event) { jack_nframes_t where; - AudioRegionView* rv = reinterpret_cast<AudioRegionView *> (drag_info.data); + RegionView* rv = reinterpret_cast<RegionView *> (drag_info.data); pair<set<Playlist*>::iterator,bool> insert_result; bool nocommit = true; double speed; - AudioTimeAxisView* atv; + RouteTimeAxisView* atv; bool regionview_y_movement; bool regionview_x_movement; @@ -3284,7 +3292,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event speed = atv->get_diskstream()->speed(); } - regionview_x_movement = (drag_info.last_frame_position != (jack_nframes_t) (rv->region.position()/speed)); + regionview_x_movement = (drag_info.last_frame_position != (jack_nframes_t) (rv->region().position()/speed)); regionview_y_movement = (drag_info.last_trackview != &rv->get_time_axis_view()); //printf ("last_frame: %s position is %lu %g\n", rv->get_time_axis_view().name().c_str(), drag_info.last_frame_position, speed); @@ -3294,13 +3302,13 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event /* motion between tracks */ - list<AudioRegionView*> new_selection; + list<RegionView*> new_selection; /* moved to a different audio track. */ - for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ) { + for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ) { - AudioRegionView* rv2 = (*i); + RegionView* rv2 = (*i); /* the region that used to be in the old playlist is not moved to the new one - we make a copy of it. as a result, @@ -3317,7 +3325,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event /* first, freeze the target tracks */ - for (list<AudioRegionView*>::const_iterator i = new_selection.begin(); i != new_selection.end();i++ ) { + for (list<RegionView*>::const_iterator i = new_selection.begin(); i != new_selection.end();i++ ) { Playlist* from_playlist; Playlist* to_playlist; @@ -3329,7 +3337,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event TimeAxisView* tvp2 = trackview_by_y_position (iy1); AudioTimeAxisView* atv2 = dynamic_cast<AudioTimeAxisView*>(tvp2); - from_playlist = (*i)->region.playlist(); + from_playlist = (*i)->region().playlist(); to_playlist = atv2->playlist(); /* the from_playlist was frozen in the "first_move" case @@ -3352,7 +3360,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event /* now do it again with the actual operations */ - for (list<AudioRegionView*>::const_iterator i = new_selection.begin(); i != new_selection.end();i++ ) { + for (list<RegionView*>::const_iterator i = new_selection.begin(); i != new_selection.end();i++ ) { Playlist* from_playlist; Playlist* to_playlist; @@ -3364,17 +3372,17 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event TimeAxisView* tvp2 = trackview_by_y_position (iy1); AudioTimeAxisView* atv2 = dynamic_cast<AudioTimeAxisView*>(tvp2); - from_playlist = (*i)->region.playlist(); + from_playlist = (*i)->region().playlist(); to_playlist = atv2->playlist(); latest_regionview = 0; where = (jack_nframes_t) (unit_to_frame (ix1) * speed); - Region* new_region = createRegion ((*i)->region); + Region* new_region = createRegion ((*i)->region()); - from_playlist->remove_region (&((*i)->region)); + from_playlist->remove_region (&((*i)->region())); - sigc::connection c = atv2->view->AudioRegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view)); + sigc::connection c = atv2->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view)); to_playlist->add_region (*new_region, where); c.disconnect (); @@ -3387,11 +3395,11 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event /* motion within a single track */ - for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) { + for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) { rv = (*i); - if (rv->region.locked()) { + if (rv->region().locked()) { continue; } @@ -3413,14 +3421,14 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event } else { - where = rv->region.position(); + where = rv->region().position(); } rv->get_time_axis_view().reveal_dependent_views (*rv); /* no need to add an undo here, we did that when we added this playlist to motion_frozen playlists */ - rv->region.set_position (where, (void *) this); + rv->region().set_position (where, (void *) this); } } @@ -3454,15 +3462,15 @@ Editor::region_view_item_click (AudioRegionView& rv, GdkEventButton* event) if (Keyboard::modifier_state_equals (event->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Alt))) { - align_region (rv.region, SyncPoint, (jack_nframes_t) (edit_cursor->current_frame * speed)); + align_region (rv.region(), SyncPoint, (jack_nframes_t) (edit_cursor->current_frame * speed)); } else if (Keyboard::modifier_state_equals (event->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) { - align_region (rv.region, End, (jack_nframes_t) (edit_cursor->current_frame * speed)); + align_region (rv.region(), End, (jack_nframes_t) (edit_cursor->current_frame * speed)); } else { - align_region (rv.region, Start, (jack_nframes_t) (edit_cursor->current_frame * speed)); + align_region (rv.region(), Start, (jack_nframes_t) (edit_cursor->current_frame * speed)); } } } @@ -3579,7 +3587,7 @@ Editor::show_verbose_duration_cursor (jack_nframes_t start, jack_nframes_t end, } void -Editor::collect_new_region_view (AudioRegionView* rv) +Editor::collect_new_region_view (RegionView* rv) { latest_regionview = rv; } @@ -3612,7 +3620,7 @@ Editor::start_selection_grab (ArdourCanvas::Item* item, GdkEvent* event) */ latest_regionview = 0; - sigc::connection c = clicked_audio_trackview->view->AudioRegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view)); + sigc::connection c = clicked_audio_trackview->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view)); /* A selection grab currently creates two undo/redo operations, one for creating the new region and another for moving it. @@ -3647,7 +3655,7 @@ Editor::start_selection_grab (ArdourCanvas::Item* item, GdkEvent* event) start_grab (event); drag_info.last_trackview = clicked_trackview; - drag_info.last_frame_position = latest_regionview->region.position(); + drag_info.last_frame_position = latest_regionview->region().position(); drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position; show_verbose_time_cursor (drag_info.last_frame_position, 10); @@ -3888,9 +3896,9 @@ Editor::start_trim (ArdourCanvas::Item* item, GdkEvent* event) speed = tv->get_diskstream()->speed(); } - jack_nframes_t region_start = (jack_nframes_t) (clicked_regionview->region.position() / speed); - jack_nframes_t region_end = (jack_nframes_t) (clicked_regionview->region.last_frame() / speed); - jack_nframes_t region_length = (jack_nframes_t) (clicked_regionview->region.length() / speed); + jack_nframes_t region_start = (jack_nframes_t) (clicked_regionview->region().position() / speed); + jack_nframes_t region_end = (jack_nframes_t) (clicked_regionview->region().last_frame() / speed); + jack_nframes_t region_length = (jack_nframes_t) (clicked_regionview->region().length() / speed); motion_frozen_playlists.clear(); @@ -3930,7 +3938,7 @@ Editor::start_trim (ArdourCanvas::Item* item, GdkEvent* event) void Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) { - AudioRegionView* rv = clicked_regionview; + RegionView* rv = clicked_regionview; jack_nframes_t frame_delta = 0; bool left_direction; bool obey_snap = !Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier()); @@ -3942,7 +3950,7 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) double speed = 1.0; TimeAxisView* tvp = clicked_trackview; - AudioTimeAxisView* tv = dynamic_cast<AudioTimeAxisView*>(tvp); + RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp); pair<set<Playlist*>::iterator,bool> insert_result; if (tv && tv->is_audio_track()) { @@ -3981,11 +3989,14 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) begin_reversible_command (trim_type); - for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) { - (*i)->region.freeze (); - (*i)->temporarily_hide_envelope (); + for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) { + (*i)->region().freeze (); + + AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i); + if (arv) + arv->temporarily_hide_envelope (); - Playlist * pl = (*i)->region.playlist(); + Playlist * pl = (*i)->region().playlist(); insert_result = motion_frozen_playlists.insert (pl); if (insert_result.second) { session->add_undo (pl->get_memento()); @@ -4001,20 +4012,20 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) switch (trim_op) { case StartTrim: - if ((left_direction == false) && (drag_info.current_pointer_frame <= rv->region.first_frame()/speed)) { + if ((left_direction == false) && (drag_info.current_pointer_frame <= rv->region().first_frame()/speed)) { break; } else { - for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) { + for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) { single_start_trim (**i, frame_delta, left_direction, obey_snap); } break; } case EndTrim: - if ((left_direction == true) && (drag_info.current_pointer_frame > (jack_nframes_t) (rv->region.last_frame()/speed))) { + if ((left_direction == true) && (drag_info.current_pointer_frame > (jack_nframes_t) (rv->region().last_frame()/speed))) { break; } else { - for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) { + for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) { single_end_trim (**i, frame_delta, left_direction, obey_snap); } break; @@ -4028,8 +4039,8 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) swap_direction = true; } - for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); - i != selection->audio_regions.by_layer().end(); ++i) + for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); + i != selection->regions.by_layer().end(); ++i) { single_contents_trim (**i, frame_delta, left_direction, swap_direction, obey_snap); } @@ -4039,10 +4050,10 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) switch (trim_op) { case StartTrim: - show_verbose_time_cursor((jack_nframes_t) (rv->region.position()/speed), 10); + show_verbose_time_cursor((jack_nframes_t) (rv->region().position()/speed), 10); break; case EndTrim: - show_verbose_time_cursor((jack_nframes_t) (rv->region.last_frame()/speed), 10); + show_verbose_time_cursor((jack_nframes_t) (rv->region().last_frame()/speed), 10); break; case ContentsTrim: show_verbose_time_cursor(drag_info.current_pointer_frame, 10); @@ -4054,9 +4065,9 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) } void -Editor::single_contents_trim (AudioRegionView& rv, jack_nframes_t frame_delta, bool left_direction, bool swap_direction, bool obey_snap) +Editor::single_contents_trim (RegionView& rv, jack_nframes_t frame_delta, bool left_direction, bool swap_direction, bool obey_snap) { - Region& region (rv.region); + Region& region (rv.region()); if (region.locked()) { return; @@ -4066,7 +4077,7 @@ Editor::single_contents_trim (AudioRegionView& rv, jack_nframes_t frame_delta, b double speed = 1.0; TimeAxisView* tvp = clicked_trackview; - AudioTimeAxisView* tv = dynamic_cast<AudioTimeAxisView*>(tvp); + RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp); if (tv && tv->is_audio_track()) { speed = tv->get_diskstream()->speed(); @@ -4094,9 +4105,9 @@ Editor::single_contents_trim (AudioRegionView& rv, jack_nframes_t frame_delta, b } void -Editor::single_start_trim (AudioRegionView& rv, jack_nframes_t frame_delta, bool left_direction, bool obey_snap) +Editor::single_start_trim (RegionView& rv, jack_nframes_t frame_delta, bool left_direction, bool obey_snap) { - Region& region (rv.region); + Region& region (rv.region()); if (region.locked()) { return; @@ -4128,9 +4139,9 @@ Editor::single_start_trim (AudioRegionView& rv, jack_nframes_t frame_delta, bool } void -Editor::single_end_trim (AudioRegionView& rv, jack_nframes_t frame_delta, bool left_direction, bool obey_snap) +Editor::single_end_trim (RegionView& rv, jack_nframes_t frame_delta, bool left_direction, bool obey_snap) { - Region& region (rv.region); + Region& region (rv.region()); if (region.locked()) { return; @@ -4169,8 +4180,8 @@ Editor::trim_finished_callback (ArdourCanvas::Item* item, GdkEvent* event) thaw_region_after_trim (*clicked_regionview); } else { - for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); - i != selection->audio_regions.by_layer().end(); ++i) + for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); + i != selection->regions.by_layer().end(); ++i) { thaw_region_after_trim (**i); } @@ -4193,7 +4204,7 @@ Editor::trim_finished_callback (ArdourCanvas::Item* item, GdkEvent* event) void Editor::point_trim (GdkEvent* event) { - AudioRegionView* rv = clicked_regionview; + RegionView* rv = clicked_regionview; jack_nframes_t new_bound = drag_info.current_pointer_frame; if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { @@ -4208,22 +4219,22 @@ Editor::point_trim (GdkEvent* event) if (rv->get_selected()) { - for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); - i != selection->audio_regions.by_layer().end(); ++i) + for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); + i != selection->regions.by_layer().end(); ++i) { - if (!(*i)->region.locked()) { - session->add_undo ((*i)->region.playlist()->get_memento()); - (*i)->region.trim_front (new_bound, this); - session->add_redo_no_execute ((*i)->region.playlist()->get_memento()); + if (!(*i)->region().locked()) { + session->add_undo ((*i)->region().playlist()->get_memento()); + (*i)->region().trim_front (new_bound, this); + session->add_redo_no_execute ((*i)->region().playlist()->get_memento()); } } } else { - if (!rv->region.locked()) { - session->add_undo (rv->region.playlist()->get_memento()); - rv->region.trim_front (new_bound, this); - session->add_redo_no_execute (rv->region.playlist()->get_memento()); + if (!rv->region().locked()) { + session->add_undo (rv->region().playlist()->get_memento()); + rv->region().trim_front (new_bound, this); + session->add_redo_no_execute (rv->region().playlist()->get_memento()); } } @@ -4236,21 +4247,21 @@ Editor::point_trim (GdkEvent* event) if (rv->get_selected()) { - for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) + for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) { - if (!(*i)->region.locked()) { - session->add_undo ((*i)->region.playlist()->get_memento()); - (*i)->region.trim_end (new_bound, this); - session->add_redo_no_execute ((*i)->region.playlist()->get_memento()); + if (!(*i)->region().locked()) { + session->add_undo ((*i)->region().playlist()->get_memento()); + (*i)->region().trim_end (new_bound, this); + session->add_redo_no_execute ((*i)->region().playlist()->get_memento()); } } } else { - if (!rv->region.locked()) { - session->add_undo (rv->region.playlist()->get_memento()); - rv->region.trim_end (new_bound, this); - session->add_redo_no_execute (rv->region.playlist()->get_memento()); + if (!rv->region().locked()) { + session->add_undo (rv->region().playlist()->get_memento()); + rv->region().trim_end (new_bound, this); + session->add_redo_no_execute (rv->region().playlist()->get_memento()); } } @@ -4263,9 +4274,9 @@ Editor::point_trim (GdkEvent* event) } void -Editor::thaw_region_after_trim (AudioRegionView& rv) +Editor::thaw_region_after_trim (RegionView& rv) { - Region& region (rv.region); + Region& region (rv.region()); if (region.locked()) { return; @@ -4274,7 +4285,9 @@ Editor::thaw_region_after_trim (AudioRegionView& rv) region.thaw (_("trimmed region")); session->add_redo_no_execute (region.playlist()->get_memento()); - rv.unhide_envelope (); + AudioRegionView* arv = dynamic_cast<AudioRegionView*>(&rv); + if (arv) + arv->unhide_envelope (); } void @@ -4664,7 +4677,7 @@ Editor::end_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event) } } else { - selection->clear_audio_regions(); + selection->clear_regions(); selection->clear_points (); selection->clear_lines (); } @@ -4681,7 +4694,7 @@ Editor::mouse_rename_region (ArdourCanvas::Item* item, GdkEvent* event) ArdourPrompter prompter (false); prompter.set_prompt (_("Name for region:")); - prompter.set_initial_text (clicked_regionview->region.name()); + prompter.set_initial_text (clicked_regionview->region().name()); prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT); prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false); prompter.show_all (); @@ -4690,7 +4703,7 @@ Editor::mouse_rename_region (ArdourCanvas::Item* item, GdkEvent* event) string str; prompter.get_result(str); if (str.length()) { - clicked_regionview->region.set_name (str); + clicked_regionview->region().set_name (str); } break; } @@ -4712,7 +4725,7 @@ Editor::start_time_fx (ArdourCanvas::Item* item, GdkEvent* event) void Editor::time_fx_motion (ArdourCanvas::Item *item, GdkEvent* event) { - AudioRegionView* rv = clicked_regionview; + RegionView* rv = clicked_regionview; if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { snap_to (drag_info.current_pointer_frame); @@ -4722,8 +4735,8 @@ Editor::time_fx_motion (ArdourCanvas::Item *item, GdkEvent* event) return; } - if (drag_info.current_pointer_frame > rv->region.position()) { - rv->get_time_axis_view().show_timestretch (rv->region.position(), drag_info.current_pointer_frame); + if (drag_info.current_pointer_frame > rv->region().position()) { + rv->get_time_axis_view().show_timestretch (rv->region().position(), drag_info.current_pointer_frame); } drag_info.last_pointer_frame = drag_info.current_pointer_frame; @@ -4741,21 +4754,25 @@ Editor::end_time_fx (ArdourCanvas::Item* item, GdkEvent* event) return; } - jack_nframes_t newlen = drag_info.last_pointer_frame - clicked_regionview->region.position(); - float percentage = (float) ((double) newlen - (double) clicked_regionview->region.length()) / ((double) newlen) * 100.0f; + jack_nframes_t newlen = drag_info.last_pointer_frame - clicked_regionview->region().position(); + float percentage = (float) ((double) newlen - (double) clicked_regionview->region().length()) / ((double) newlen) * 100.0f; begin_reversible_command (_("timestretch")); - if (run_timestretch (selection->audio_regions, percentage) == 0) { + if (run_timestretch (selection->regions, percentage) == 0) { session->commit_reversible_command (); } } void -Editor::mouse_brush_insert_region (AudioRegionView* rv, jack_nframes_t pos) +Editor::mouse_brush_insert_region (RegionView* rv, jack_nframes_t pos) { /* no brushing without a useful snap setting */ + // FIXME + AudioRegionView* arv = dynamic_cast<AudioRegionView*>(rv); + assert(arv); + switch (snap_mode) { case SnapMagnetic: return; /* can't work because it allows region to be placed anywhere */ @@ -4775,11 +4792,11 @@ Editor::mouse_brush_insert_region (AudioRegionView* rv, jack_nframes_t pos) /* don't brush a copy over the original */ - if (pos == rv->region.position()) { + if (pos == rv->region().position()) { return; } - AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&rv->get_time_axis_view()); + RouteTimeAxisView* atv = dynamic_cast<RouteTimeAxisView*>(&arv->get_time_axis_view()); if (atv == 0 || !atv->is_audio_track()) { return; @@ -4789,7 +4806,7 @@ Editor::mouse_brush_insert_region (AudioRegionView* rv, jack_nframes_t pos) double speed = atv->get_diskstream()->speed(); session->add_undo (playlist->get_memento()); - playlist->add_region (*(new AudioRegion (rv->region)), (jack_nframes_t) (pos * speed)); + playlist->add_region (*(new AudioRegion (arv->audio_region())), (jack_nframes_t) (pos * speed)); session->add_redo_no_execute (playlist->get_memento()); // playlist is frozen, so we have to update manually diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index d3845dd26b..91409b3429 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -51,7 +51,7 @@ #include "audio_time_axis.h" #include "automation_time_axis.h" #include "streamview.h" -#include "regionview.h" +#include "audio_regionview.h" #include "rgb_macros.h" #include "selection_templates.h" #include "selection.h" @@ -186,29 +186,31 @@ Editor::split_region () void Editor::split_region_at (jack_nframes_t where) { - split_regions_at (where, selection->audio_regions); + split_regions_at (where, selection->regions); } void -Editor::split_regions_at (jack_nframes_t where, AudioRegionSelection& regions) +Editor::split_regions_at (jack_nframes_t where, RegionSelection& regions) { begin_reversible_command (_("split")); snap_to (where); - for (AudioRegionSelection::iterator a = regions.begin(); a != regions.end(); ) { + for (RegionSelection::iterator a = regions.begin(); a != regions.end(); ) { - AudioRegionSelection::iterator tmp; + RegionSelection::iterator tmp; tmp = a; ++tmp; - Playlist* pl = (*a)->region.playlist(); + Playlist* pl = (*a)->region().playlist(); - _new_regionviews_show_envelope = (*a)->envelope_visible(); + AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*a); + if (arv) + _new_regionviews_show_envelope = arv->envelope_visible(); if (pl) { session->add_undo (pl->get_memento()); - pl->split_region ((*a)->region, where); + pl->split_region ((*a)->region(), where); session->add_redo_no_execute (pl->get_memento()); } @@ -230,7 +232,7 @@ Editor::remove_clicked_region () begin_reversible_command (_("remove region")); session->add_undo (playlist->get_memento()); - playlist->remove_region (&clicked_regionview->region); + playlist->remove_region (&clicked_regionview->region()); session->add_redo_no_execute (playlist->get_memento()); commit_reversible_command (); } @@ -238,7 +240,7 @@ Editor::remove_clicked_region () void Editor::destroy_clicked_region () { - int32_t selected = selection->audio_regions.size(); + int32_t selected = selection->regions.size(); if (!session || clicked_regionview == 0 && selected == 0) { return; @@ -270,29 +272,29 @@ Do you really want to destroy %1 ?"), if (selected > 0) { list<Region*> r; - for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { - r.push_back (&(*i)->region); + for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { + r.push_back (&(*i)->region()); } session->destroy_regions (r); } else if (clicked_regionview) { - session->destroy_region (&clicked_regionview->region); + session->destroy_region (&clicked_regionview->region()); } } -AudioRegion * +Region * Editor::select_region_for_operation (int dir, TimeAxisView **tv) { - AudioRegionView* rv; - AudioRegion *region; + RegionView* rv; + Region *region; jack_nframes_t start = 0; if (selection->time.start () == selection->time.end_frame ()) { /* no current selection-> is there a selected regionview? */ - if (selection->audio_regions.empty()) { + if (selection->regions.empty()) { return 0; } @@ -300,26 +302,26 @@ Editor::select_region_for_operation (int dir, TimeAxisView **tv) region = 0; - if (!selection->audio_regions.empty()) { + if (!selection->regions.empty()) { - rv = *(selection->audio_regions.begin()); + rv = *(selection->regions.begin()); (*tv) = &rv->get_time_axis_view(); - region = &rv->region; + region = &rv->region(); } else if (!selection->tracks.empty()) { (*tv) = selection->tracks.front(); - AudioTimeAxisView* atv; + RouteTimeAxisView* rtv; - if ((atv = dynamic_cast<AudioTimeAxisView*> (*tv)) != 0) { + if ((rtv = dynamic_cast<RouteTimeAxisView*> (*tv)) != 0) { Playlist *pl; - if ((pl = atv->playlist()) == 0) { + if ((pl = rtv->playlist()) == 0) { return 0; } - region = dynamic_cast<AudioRegion*> (pl->top_region_at (start)); + region = pl->top_region_at (start); } } @@ -391,12 +393,12 @@ Editor::nudge_forward (bool next) if (!session) return; - if (!selection->audio_regions.empty()) { + if (!selection->regions.empty()) { begin_reversible_command (_("nudge forward")); - for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { - AudioRegion& r ((*i)->region); + for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { + Region& r ((*i)->region()); distance = get_nudge_distance (r.position(), next_distance); @@ -425,12 +427,12 @@ Editor::nudge_backward (bool next) if (!session) return; - if (!selection->audio_regions.empty()) { + if (!selection->regions.empty()) { begin_reversible_command (_("nudge forward")); - for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { - AudioRegion& r ((*i)->region); + for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { + Region& r ((*i)->region()); distance = get_nudge_distance (r.position(), next_distance); @@ -469,14 +471,14 @@ Editor::nudge_forward_capture_offset () if (!session) return; - if (!selection->audio_regions.empty()) { + if (!selection->regions.empty()) { begin_reversible_command (_("nudge forward")); distance = session->worst_output_latency(); - for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { - AudioRegion& r ((*i)->region); + for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { + Region& r ((*i)->region()); session->add_undo (r.playlist()->get_memento()); r.set_position (r.position() + distance, this); @@ -495,14 +497,14 @@ Editor::nudge_backward_capture_offset () if (!session) return; - if (!selection->audio_regions.empty()) { + if (!selection->regions.empty()) { begin_reversible_command (_("nudge forward")); distance = session->worst_output_latency(); - for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { - AudioRegion& r ((*i)->region); + for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { + Region& r ((*i)->region()); session->add_undo (r.playlist()->get_memento()); @@ -782,8 +784,8 @@ Editor::cursor_to_selection_start (Cursor *cursor) jack_nframes_t pos = 0; switch (mouse_mode) { case MouseObject: - if (!selection->audio_regions.empty()) { - pos = selection->audio_regions.start(); + if (!selection->regions.empty()) { + pos = selection->regions.start(); } break; @@ -811,8 +813,8 @@ Editor::cursor_to_selection_end (Cursor *cursor) switch (mouse_mode) { case MouseObject: - if (!selection->audio_regions.empty()) { - pos = selection->audio_regions.end_frame(); + if (!selection->regions.empty()) { + pos = selection->regions.end_frame(); } break; @@ -1310,12 +1312,12 @@ Editor::add_location_from_playhead_cursor () void Editor::add_location_from_audio_region () { - if (selection->audio_regions.empty()) { + if (selection->regions.empty()) { return; } - AudioRegionView* rv = *(selection->audio_regions.begin()); - Region& region = rv->region; + RegionView* rv = *(selection->regions.begin()); + Region& region = rv->region(); Location *location = new Location (region.position(), region.last_frame(), region.name()); session->begin_reversible_command (_("add marker")); @@ -1442,12 +1444,12 @@ Editor::select_all_within (jack_nframes_t start, jack_nframes_t end, double top, void Editor::set_selection_from_audio_region () { - if (selection->audio_regions.empty()) { + if (selection->regions.empty()) { return; } - AudioRegionView* rv = *(selection->audio_regions.begin()); - Region& region = rv->region; + RegionView* rv = *(selection->regions.begin()); + Region& region = rv->region(); begin_reversible_command (_("set selection from region")); selection->set (0, region.position(), region.last_frame()); @@ -1827,13 +1829,13 @@ Editor::insert_region_list_drag (AudioRegion& region, int x, int y) void Editor::insert_region_list_selection (float times) { - AudioTimeAxisView *tv = 0; + RouteTimeAxisView *tv = 0; Playlist *playlist; if (clicked_audio_trackview != 0) { tv = clicked_audio_trackview; } else if (!selection->tracks.empty()) { - if ((tv = dynamic_cast<AudioTimeAxisView*>(selection->tracks.front())) == 0) { + if ((tv = dynamic_cast<RouteTimeAxisView*>(selection->tracks.front())) == 0) { return; } } else { @@ -1928,23 +1930,23 @@ Editor::play_selection () void Editor::play_selected_region () { - if (!selection->audio_regions.empty()) { - AudioRegionView *rv = *(selection->audio_regions.begin()); + if (!selection->regions.empty()) { + RegionView *rv = *(selection->regions.begin()); - session->request_bounded_roll (rv->region.position(), rv->region.last_frame()); + session->request_bounded_roll (rv->region().position(), rv->region().last_frame()); } } void Editor::loop_selected_region () { - if (!selection->audio_regions.empty()) { - AudioRegionView *rv = *(selection->audio_regions.begin()); + if (!selection->regions.empty()) { + RegionView *rv = *(selection->regions.begin()); Location* tll; if ((tll = transport_loop_location()) != 0) { - tll->set (rv->region.position(), rv->region.last_frame()); + tll->set (rv->region().position(), rv->region().last_frame()); // enable looping, reposition and start rolling @@ -1987,10 +1989,10 @@ void Editor::toggle_region_mute () { if (clicked_regionview) { - clicked_regionview->region.set_muted (!clicked_regionview->region.muted()); - } else if (!selection->audio_regions.empty()) { - bool yn = ! (*selection->audio_regions.begin())->region.muted(); - selection->foreach_audio_region (&AudioRegion::set_muted, yn); + clicked_regionview->region().set_muted (!clicked_regionview->region().muted()); + } else if (!selection->regions.empty()) { + bool yn = ! (*selection->regions.begin())->region().muted(); + selection->foreach_region (&Region::set_muted, yn); } } @@ -1998,35 +2000,35 @@ void Editor::toggle_region_opaque () { if (clicked_regionview) { - clicked_regionview->region.set_opaque (!clicked_regionview->region.opaque()); - } else if (!selection->audio_regions.empty()) { - bool yn = ! (*selection->audio_regions.begin())->region.opaque(); - selection->foreach_audio_region (&Region::set_opaque, yn); + clicked_regionview->region().set_opaque (!clicked_regionview->region().opaque()); + } else if (!selection->regions.empty()) { + bool yn = ! (*selection->regions.begin())->region().opaque(); + selection->foreach_region (&Region::set_opaque, yn); } } void Editor::raise_region () { - selection->foreach_audio_region (&Region::raise); + selection->foreach_region (&Region::raise); } void Editor::raise_region_to_top () { - selection->foreach_audio_region (&Region::raise_to_top); + selection->foreach_region (&Region::raise_to_top); } void Editor::lower_region () { - selection->foreach_audio_region (&Region::lower); + selection->foreach_region (&Region::lower); } void Editor::lower_region_to_bottom () { - selection->foreach_audio_region (&Region::lower_to_bottom); + selection->foreach_region (&Region::lower_to_bottom); } void @@ -2047,7 +2049,7 @@ Editor::rename_region () Button ok_button (_("OK")); Button cancel_button (_("Cancel")); - if (selection->audio_regions.empty()) { + if (selection->regions.empty()) { return; } @@ -2078,7 +2080,7 @@ Editor::rename_region () Main::run (); if (region_renamed) { - (*selection->audio_regions.begin())->region.set_name (entry.get_text()); + (*selection->regions.begin())->region().set_name (entry.get_text()); redisplay_regions (); } } @@ -2092,7 +2094,7 @@ Editor::rename_region_finished (bool status) } void -Editor::audition_playlist_region_via_route (AudioRegion& region, Route& route) +Editor::audition_playlist_region_via_route (Region& region, Route& route) { if (session->is_auditioning()) { session->cancel_audition (); @@ -2113,16 +2115,22 @@ Editor::audition_playlist_region_via_route (AudioRegion& region, Route& route) void Editor::audition_selected_region () { - if (!selection->audio_regions.empty()) { - AudioRegionView* rv = *(selection->audio_regions.begin()); - session->audition_region (rv->region); + if (!selection->regions.empty()) { + RegionView* rv = *(selection->regions.begin()); + // FIXME + AudioRegion* const ar = dynamic_cast<AudioRegion*>(&rv->region()); + assert(ar); + session->audition_region (*ar); } } void -Editor::audition_playlist_region_standalone (AudioRegion& region) +Editor::audition_playlist_region_standalone (Region& region) { - session->audition_region (region); + // FIXME + AudioRegion* const ar = dynamic_cast<AudioRegion*>(®ion); + assert(ar); + session->audition_region (*ar); } void @@ -2191,6 +2199,8 @@ Editor::region_from_selection () internal_start = start - current->position(); session->region_name (new_name, current->name(), true); region = new AudioRegion (*current, internal_start, selection_cnt, new_name); + } else { + assert(false); // FIXME } } } @@ -2237,11 +2247,13 @@ Editor::split_multichannel_region () { vector<AudioRegion*> v; - if (!clicked_regionview || clicked_regionview->region.n_channels() < 2) { + AudioRegionView* clicked_arv = dynamic_cast<AudioRegionView*>(clicked_regionview); + + if (!clicked_arv || clicked_arv->audio_region().n_channels() < 2) { return; } - clicked_regionview->region.separate_by_channel (*session, v); + clicked_arv->audio_region().separate_by_channel (*session, v); /* nothing else to do, really */ } @@ -2419,7 +2431,7 @@ Editor::region_fill_track () { jack_nframes_t end; - if (!session || selection->audio_regions.empty()) { + if (!session || selection->regions.empty()) { return; } @@ -2427,9 +2439,15 @@ Editor::region_fill_track () begin_reversible_command (_("region fill")); - for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { + for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { + + Region& region ((*i)->region()); + + // FIXME + AudioRegion* const ar = dynamic_cast<AudioRegion*>(®ion); + if (!ar) + continue; - AudioRegion& region ((*i)->region); Playlist* pl = region.playlist(); if (end <= region.last_frame()) { @@ -2443,7 +2461,7 @@ Editor::region_fill_track () } session->add_undo (pl->get_memento()); - pl->add_region (*(new AudioRegion (region)), region.last_frame(), times); + pl->add_region (*(new AudioRegion (*ar)), ar->last_frame(), times); session->add_redo_no_execute (pl->get_memento()); } @@ -2522,12 +2540,12 @@ Editor::set_region_sync_from_edit_cursor () return; } - if (!clicked_regionview->region.covers (edit_cursor->current_frame)) { + if (!clicked_regionview->region().covers (edit_cursor->current_frame)) { error << _("Place the edit cursor at the desired sync point") << endmsg; return; } - Region& region (clicked_regionview->region); + Region& region (clicked_regionview->region()); begin_reversible_command (_("set sync from edit cursor")); session->add_undo (region.playlist()->get_memento()); region.set_sync_position (edit_cursor->current_frame); @@ -2539,7 +2557,7 @@ void Editor::remove_region_sync () { if (clicked_regionview) { - Region& region (clicked_regionview->region); + Region& region (clicked_regionview->region()); begin_reversible_command (_("remove sync")); session->add_undo (region.playlist()->get_memento()); region.clear_sync_position (); @@ -2551,14 +2569,14 @@ Editor::remove_region_sync () void Editor::naturalize () { - if (selection->audio_regions.empty()) { + if (selection->regions.empty()) { return; } begin_reversible_command (_("naturalize")); - for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { - session->add_undo ((*i)->region.get_memento()); - (*i)->region.move_to_natural_position (this); - session->add_redo_no_execute ((*i)->region.get_memento()); + for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { + session->add_undo ((*i)->region().get_memento()); + (*i)->region().move_to_natural_position (this); + session->add_redo_no_execute ((*i)->region().get_memento()); } commit_reversible_command (); } @@ -2577,14 +2595,14 @@ Editor::align_relative (RegionPoint what) struct RegionSortByTime { bool operator() (const AudioRegionView* a, const AudioRegionView* b) { - return a->region.position() < b->region.position(); + return a->region().position() < b->region().position(); } }; void Editor::align_selection_relative (RegionPoint point, jack_nframes_t position) { - if (selection->audio_regions.empty()) { + if (selection->regions.empty()) { return; } @@ -2592,9 +2610,9 @@ Editor::align_selection_relative (RegionPoint point, jack_nframes_t position) jack_nframes_t pos = 0; int dir; - list<AudioRegionView*> sorted; - selection->audio_regions.by_position (sorted); - Region& r ((*sorted.begin())->region); + list<RegionView*> sorted; + selection->regions.by_position (sorted); + Region& r ((*sorted.begin())->region()); switch (point) { case Start: @@ -2620,9 +2638,9 @@ Editor::align_selection_relative (RegionPoint point, jack_nframes_t position) begin_reversible_command (_("align selection (relative)")); - for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { + for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { - Region& region ((*i)->region); + Region& region ((*i)->region()); session->add_undo (region.playlist()->get_memento()); @@ -2642,14 +2660,14 @@ Editor::align_selection_relative (RegionPoint point, jack_nframes_t position) void Editor::align_selection (RegionPoint point, jack_nframes_t position) { - if (selection->audio_regions.empty()) { + if (selection->regions.empty()) { return; } begin_reversible_command (_("align selection")); - for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { - align_region_internal ((*i)->region, point, position); + for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { + align_region_internal ((*i)->region(), point, position); } commit_reversible_command (); @@ -2694,7 +2712,7 @@ Editor::trim_region_to_edit_cursor () return; } - Region& region (clicked_regionview->region); + Region& region (clicked_regionview->region()); float speed = 1.0f; AudioTimeAxisView *atav; @@ -2719,7 +2737,7 @@ Editor::trim_region_from_edit_cursor () return; } - Region& region (clicked_regionview->region); + Region& region (clicked_regionview->region()); float speed = 1.0f; AudioTimeAxisView *atav; @@ -2890,16 +2908,16 @@ Editor::cut_copy (CutCopyOp op) switch (current_mouse_mode()) { case MouseObject: - if (!selection->audio_regions.empty() || !selection->points.empty()) { + if (!selection->regions.empty() || !selection->points.empty()) { begin_reversible_command (opname + _(" objects")); - if (!selection->audio_regions.empty()) { + if (!selection->regions.empty()) { cut_copy_regions (op); if (op == Cut) { - selection->clear_audio_regions (); + selection->clear_regions (); } } @@ -2956,11 +2974,11 @@ Editor::cut_copy_regions (CutCopyOp op) set<Playlist*> freezelist; pair<set<Playlist*>::iterator,bool> insert_result; - for (AudioRegionSelection::iterator x = selection->audio_regions.begin(); x != selection->audio_regions.end(); ++x) { - first_position = min ((*x)->region.position(), first_position); + for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) { + first_position = min ((*x)->region().position(), first_position); if (op == Cut || op == Clear) { - AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region.playlist()); + AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region().playlist()); if (pl) { insert_result = freezelist.insert (pl); if (insert_result.second) { @@ -2971,11 +2989,11 @@ Editor::cut_copy_regions (CutCopyOp op) } } - for (AudioRegionSelection::iterator x = selection->audio_regions.begin(); x != selection->audio_regions.end(); ) { + for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ) { - AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region.playlist()); + AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region().playlist()); AudioPlaylist* npl; - AudioRegionSelection::iterator tmp; + RegionSelection::iterator tmp; tmp = x; ++tmp; @@ -2992,18 +3010,24 @@ Editor::cut_copy_regions (CutCopyOp op) npl = pi->second; } + // FIXME + AudioRegion* const ar = dynamic_cast<AudioRegion*>(&(*x)->region()); switch (op) { case Cut: - npl->add_region (*(new AudioRegion ((*x)->region)), (*x)->region.position() - first_position); - pl->remove_region (&((*x)->region)); + if (!ar) break; + + npl->add_region (*(new AudioRegion (*ar)), (*x)->region().position() - first_position); + pl->remove_region (&((*x)->region())); break; case Copy: - npl->add_region (*(new AudioRegion ((*x)->region)), (*x)->region.position() - first_position); + if (!ar) break; + + npl->add_region (*(new AudioRegion (*ar)), (*x)->region().position() - first_position); break; case Clear: - pl->remove_region (&((*x)->region)); + pl->remove_region (&((*x)->region())); break; } } @@ -3149,24 +3173,24 @@ Editor::paste_named_selection (float times) } void -Editor::duplicate_some_regions (AudioRegionSelection& regions, float times) +Editor::duplicate_some_regions (RegionSelection& regions, float times) { Playlist *playlist; - AudioRegionSelection sel = regions; // clear (below) will clear the argument list + RegionSelection sel = regions; // clear (below) will clear the argument list begin_reversible_command (_("duplicate region")); - selection->clear_audio_regions (); + selection->clear_regions (); - for (AudioRegionSelection::iterator i = sel.begin(); i != sel.end(); ++i) { + for (RegionSelection::iterator i = sel.begin(); i != sel.end(); ++i) { - Region& r ((*i)->region); + Region& r ((*i)->region()); TimeAxisView& tv = (*i)->get_time_axis_view(); AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (&tv); - sigc::connection c = atv->view->AudioRegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view)); + sigc::connection c = atv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view)); - playlist = (*i)->region.playlist(); + playlist = (*i)->region().playlist(); session->add_undo (playlist->get_memento()); playlist->duplicate (r, r.last_frame(), times); session->add_redo_no_execute (playlist->get_memento()); @@ -3336,7 +3360,7 @@ Editor::normalize_region () return; } - if (selection->audio_regions.empty()) { + if (selection->regions.empty()) { return; } @@ -3345,10 +3369,13 @@ Editor::normalize_region () track_canvas.get_window()->set_cursor (*wait_cursor); gdk_flush (); - for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ++r) { - session->add_undo ((*r)->region.get_memento()); - (*r)->region.normalize_to (0.0f); - session->add_redo_no_execute ((*r)->region.get_memento()); + for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) { + AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r); + if (!arv) + continue; + session->add_undo (arv->region().get_memento()); + arv->audio_region().normalize_to (0.0f); + session->add_redo_no_execute (arv->region().get_memento()); } commit_reversible_command (); @@ -3363,16 +3390,19 @@ Editor::denormalize_region () return; } - if (selection->audio_regions.empty()) { + if (selection->regions.empty()) { return; } begin_reversible_command ("denormalize"); - for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ++r) { - session->add_undo ((*r)->region.get_memento()); - (*r)->region.set_scale_amplitude (1.0f); - session->add_redo_no_execute ((*r)->region.get_memento()); + for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) { + AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r); + if (!arv) + continue; + session->add_undo (arv->region().get_memento()); + arv->audio_region().set_scale_amplitude (1.0f); + session->add_redo_no_execute (arv->region().get_memento()); } commit_reversible_command (); @@ -3393,7 +3423,7 @@ Editor::reverse_region () void Editor::apply_filter (AudioFilter& filter, string command) { - if (selection->audio_regions.empty()) { + if (selection->regions.empty()) { return; } @@ -3402,20 +3432,22 @@ Editor::apply_filter (AudioFilter& filter, string command) track_canvas.get_window()->set_cursor (*wait_cursor); gdk_flush (); - for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ) { + for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ) { + AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r); + if (!arv) + continue; - AudioRegion& region ((*r)->region); - Playlist* playlist = region.playlist(); + Playlist* playlist = arv->region().playlist(); - AudioRegionSelection::iterator tmp; + RegionSelection::iterator tmp; tmp = r; ++tmp; - if (region.apply (filter) == 0) { + if (arv->audio_region().apply (filter) == 0) { session->add_undo (playlist->get_memento()); - playlist->replace_region (region, *(filter.results.front()), region.position()); + playlist->replace_region (arv->region(), *(filter.results.front()), arv->region().position()); session->add_redo_no_execute (playlist->get_memento()); } else { goto out; @@ -3425,7 +3457,7 @@ Editor::apply_filter (AudioFilter& filter, string command) } commit_reversible_command (); - selection->audio_regions.clear (); + selection->regions.clear (); out: track_canvas.get_window()->set_cursor (*current_canvas_cursor); @@ -3434,8 +3466,8 @@ Editor::apply_filter (AudioFilter& filter, string command) void Editor::region_selection_op (void (Region::*pmf)(void)) { - for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { - ((*i)->region.*pmf)(); + for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { + ((*i)->region().*pmf)(); } } @@ -3443,16 +3475,16 @@ Editor::region_selection_op (void (Region::*pmf)(void)) void Editor::region_selection_op (void (Region::*pmf)(void*), void *arg) { - for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { - ((*i)->region.*pmf)(arg); + for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { + ((*i)->region().*pmf)(arg); } } void Editor::region_selection_op (void (Region::*pmf)(bool), bool yn) { - for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { - ((*i)->region.*pmf)(yn); + for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { + ((*i)->region().*pmf)(yn); } } @@ -3469,20 +3501,20 @@ Editor::external_edit_region () void Editor::brush (jack_nframes_t pos) { - AudioRegionSelection sel; + RegionSelection sel; snap_to (pos); - if (selection->audio_regions.empty()) { + if (selection->regions.empty()) { /* XXX get selection from region list */ } else { - sel = selection->audio_regions; + sel = selection->regions; } if (sel.empty()) { return; } - for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { + for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { mouse_brush_insert_region ((*i), pos); } } @@ -3490,18 +3522,19 @@ Editor::brush (jack_nframes_t pos) void Editor::toggle_gain_envelope_visibility () { - for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { - (*i)->set_envelope_visible (!(*i)->envelope_visible()); + for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { + AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i); + if (arv) + arv->set_envelope_visible (!arv->envelope_visible()); } } void Editor::toggle_gain_envelope_active () { - for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { - AudioRegion* ar = dynamic_cast<AudioRegion*>(&(*i)->region); - if (ar) { - ar->set_envelope_active (true); - } + for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { + AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i); + if (arv) + arv->audio_region().set_envelope_active (true); } } diff --git a/gtk2_ardour/editor_route_list.cc b/gtk2_ardour/editor_route_list.cc index 95ac358095..b79c6b3571 100644 --- a/gtk2_ardour/editor_route_list.cc +++ b/gtk2_ardour/editor_route_list.cc @@ -21,15 +21,17 @@ #include <algorithm> #include <cstdlib> #include <cmath> +#include <cassert> #include "editor.h" #include "ardour_ui.h" #include "audio_time_axis.h" +#include "midi_time_axis.h" #include "mixer_strip.h" #include "gui_thread.h" #include <ardour/route.h> -#include <ardour/audio_track.h> +//#include <ardour/audio_track.h> #include "i18n.h" @@ -39,26 +41,27 @@ using namespace PBD; using namespace Gtk; void -Editor::handle_new_route_p (Route* route) -{ - ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::handle_new_route_p), route)); - handle_new_route (*route); -} - -void -Editor::handle_new_route (Route& route) +Editor::handle_new_route (Route* route) { + ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::handle_new_route), route)); + TimeAxisView *tv; - AudioTimeAxisView *atv; TreeModel::Row parent; TreeModel::Row row; - if (route.hidden()) { + if (route->hidden()) { return; } - - tv = new AudioTimeAxisView (*this, *session, route, track_canvas); + // FIXME + Buffer::Type type = route->default_type(); + assert(type == Buffer::AUDIO || type == Buffer::MIDI); + + if (type == Buffer::AUDIO) + tv = new AudioTimeAxisView (*this, *session, *route, track_canvas); + else + tv = new MidiTimeAxisView (*this, *session, *route, track_canvas); + #if 0 if (route_display_model->children().size() == 0) { @@ -89,7 +92,7 @@ Editor::handle_new_route (Route& route) row = *(route_display_model->append ()); #endif - row[route_display_columns.text] = route.name(); + row[route_display_columns.text] = route->name(); row[route_display_columns.visible] = tv->marked_for_display(); row[route_display_columns.tv] = tv; @@ -97,16 +100,17 @@ Editor::handle_new_route (Route& route) ignore_route_list_reorder = true; - if ((atv = dynamic_cast<AudioTimeAxisView*> (tv)) != 0) { + RouteTimeAxisView* rtv = NULL; + if ((rtv = dynamic_cast<RouteTimeAxisView*> (tv)) != 0) { /* added a new fresh one at the end */ - if (atv->route().order_key(N_("editor")) == -1) { - atv->route().set_order_key (N_("editor"), route_display_model->children().size()-1); + if (rtv->route().order_key(N_("editor")) == -1) { + rtv->route().set_order_key (N_("editor"), route_display_model->children().size()-1); } } ignore_route_list_reorder = false; - route.gui_changed.connect (mem_fun(*this, &Editor::handle_gui_changes)); + route->gui_changed.connect (mem_fun(*this, &Editor::handle_gui_changes)); tv->GoingAway.connect (bind (mem_fun(*this, &Editor::remove_route), tv)); @@ -496,7 +500,7 @@ Editor::initial_route_list_display () route_display_model->clear (); for (Session::RouteList::iterator i = routes.begin(); i != routes.end(); ++i) { - handle_new_route (**i); + handle_new_route (*i); } no_route_list_redisplay = false; diff --git a/gtk2_ardour/editor_timefx.cc b/gtk2_ardour/editor_timefx.cc index 8315834b93..5c7470823f 100644 --- a/gtk2_ardour/editor_timefx.cc +++ b/gtk2_ardour/editor_timefx.cc @@ -28,7 +28,7 @@ #include "editor.h" #include "audio_time_axis.h" -#include "regionview.h" +#include "audio_regionview.h" #include "region_selection.h" #include <ardour/session.h> @@ -100,7 +100,7 @@ Editor::TimeStretchDialog::delete_timestretch_in_progress (GdkEventAny* ev) } int -Editor::run_timestretch (AudioRegionSelection& regions, float fraction) +Editor::run_timestretch (RegionSelection& regions, float fraction) { pthread_t thread; @@ -157,39 +157,42 @@ Editor::run_timestretch (AudioRegionSelection& regions, float fraction) void Editor::do_timestretch (TimeStretchDialog& dialog) { - AudioTrack* at; + Track* t; Playlist* playlist; - AudioRegion* new_region; + Region* new_region; - for (AudioRegionSelection::iterator i = dialog.regions.begin(); i != dialog.regions.end(); ) { + for (RegionSelection::iterator i = dialog.regions.begin(); i != dialog.regions.end(); ) { + AudioRegionView* arv = dynamic_cast<AudioRegionView*>(*i); + if (!arv) + continue; - AudioRegion& aregion ((*i)->region); - TimeAxisView* tv = &(*i)->get_time_axis_view(); - AudioTimeAxisView* atv; - AudioRegionSelection::iterator tmp; + AudioRegion& region (arv->audio_region()); + TimeAxisView* tv = &(arv->get_time_axis_view()); + RouteTimeAxisView* rtv; + RegionSelection::iterator tmp; - cerr << "stretch " << aregion.name() << endl; + cerr << "stretch " << region.name() << endl; tmp = i; ++tmp; - if ((atv = dynamic_cast<AudioTimeAxisView*> (tv)) == 0) { + if ((rtv = dynamic_cast<RouteTimeAxisView*> (tv)) == 0) { i = tmp; continue; } - if ((at = dynamic_cast<AudioTrack*> (&atv->route())) == 0) { + if ((t = dynamic_cast<Track*> (&rtv->route())) == 0) { i = tmp; continue; } - if ((playlist = at->diskstream().playlist()) == 0) { + if ((playlist = t->diskstream().playlist()) == 0) { i = tmp; continue; } - dialog.request.region = &aregion; + dialog.request.region = ®ion; if (!dialog.request.running) { /* we were cancelled */ @@ -204,7 +207,7 @@ Editor::do_timestretch (TimeStretchDialog& dialog) } session->add_undo (playlist->get_memento()); - playlist->replace_region (aregion, *new_region, aregion.position()); + playlist->replace_region (region, *new_region, region.position()); session->add_redo_no_execute (playlist->get_memento()); i = tmp; diff --git a/gtk2_ardour/export_region_dialog.cc b/gtk2_ardour/export_region_dialog.cc index 97bf7c22b1..1964fabbfe 100644 --- a/gtk2_ardour/export_region_dialog.cc +++ b/gtk2_ardour/export_region_dialog.cc @@ -18,6 +18,8 @@ */ +#include <cassert> + #include <pbd/pthread_utils.h> #include <ardour/audioregion.h> @@ -26,11 +28,13 @@ #include "i18n.h" -ExportRegionDialog::ExportRegionDialog (PublicEditor& editor, ARDOUR::AudioRegion* region) +ExportRegionDialog::ExportRegionDialog (PublicEditor& editor, ARDOUR::Region* region) : ExportDialog(editor) { - audio_region = region; - + // FIXME + ARDOUR::AudioRegion* audio_region = dynamic_cast<ARDOUR::AudioRegion*>(region); + assert(audio_region); + do_not_allow_track_and_master_selection(); do_not_allow_channel_count_selection(); } diff --git a/gtk2_ardour/export_region_dialog.h b/gtk2_ardour/export_region_dialog.h index 00464eb5b3..e8afe97d6b 100644 --- a/gtk2_ardour/export_region_dialog.h +++ b/gtk2_ardour/export_region_dialog.h @@ -27,7 +27,7 @@ class ExportRegionDialog : public ExportDialog { public: - ExportRegionDialog (PublicEditor&, ARDOUR::AudioRegion*); + ExportRegionDialog (PublicEditor&, ARDOUR::Region*); static void* _export_region_thread (void *); void export_region (); diff --git a/gtk2_ardour/midi_streamview.cc b/gtk2_ardour/midi_streamview.cc new file mode 100644 index 0000000000..9be0c8dfdd --- /dev/null +++ b/gtk2_ardour/midi_streamview.cc @@ -0,0 +1,435 @@ +/* + Copyright (C) 2001, 2006 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <cmath> +#include <cassert> + +#include <gtkmm.h> + +#include <gtkmm2ext/gtk_ui.h> + +#include <ardour/midi_playlist.h> +#include <ardour/midi_region.h> +#include <ardour/midi_source.h> +#include <ardour/midi_diskstream.h> +#include <ardour/midi_track.h> +//#include <ardour/playlist_templates.h> +#include <ardour/source.h> + +#include "midi_streamview.h" +#include "regionview.h" +//#include "midi_regionview.h" +#include "midi_time_axis.h" +#include "canvas-simplerect.h" +#include "region_selection.h" +#include "selection.h" +#include "public_editor.h" +#include "ardour_ui.h" +#include "rgb_macros.h" +#include "gui_thread.h" +#include "utils.h" +#include "color.h" + +using namespace ARDOUR; +using namespace PBD; +using namespace Editing; + +MidiStreamView::MidiStreamView (MidiTimeAxisView& tv) + : StreamView (tv) +{ + region_color = _trackview.color(); + + if (tv.is_midi_track()) + stream_base_color = color_map[cMidiTrackBase]; + else + stream_base_color = color_map[cMidiBusBase]; + + /* set_position() will position the group */ + + canvas_group = new ArdourCanvas::Group(*_trackview.canvas_display); + + canvas_rect = new ArdourCanvas::SimpleRect (*canvas_group); + canvas_rect->property_x1() = 0.0; + canvas_rect->property_y1() = 0.0; + canvas_rect->property_x2() = 1000000.0; + canvas_rect->property_y2() = (double) tv.height; + canvas_rect->property_outline_color_rgba() = color_map[cMidiTrackOutline]; + canvas_rect->property_outline_what() = (guint32) (0x1|0x2|0x8); // outline ends and bottom + canvas_rect->property_fill_color_rgba() = stream_base_color; + + canvas_rect->signal_event().connect (bind (mem_fun (_trackview.editor, &PublicEditor::canvas_stream_view_event), canvas_rect, &_trackview)); + + _samples_per_unit = _trackview.editor.get_current_zoom(); + + if (_trackview.is_midi_track()) { + _trackview.midi_track()->DiskstreamChanged.connect (mem_fun (*this, &MidiStreamView::diskstream_changed)); + _trackview.session().TransportStateChange.connect (mem_fun (*this, &MidiStreamView::transport_changed)); + _trackview.get_diskstream()->RecordEnableChanged.connect (mem_fun (*this, &MidiStreamView::rec_enable_changed)); + _trackview.session().RecordStateChanged.connect (mem_fun (*this, &MidiStreamView::sess_rec_enable_changed)); + } + + rec_updating = false; + rec_active = false; + use_rec_regions = tv.editor.show_waveforms_recording (); + + ColorChanged.connect (mem_fun (*this, &MidiStreamView::color_handler)); +} + +MidiStreamView::~MidiStreamView () +{ + undisplay_diskstream (); + delete canvas_group; +} + + +void +MidiStreamView::add_region_view_internal (Region *r, bool wait_for_waves) +{ +#if 0 + ENSURE_GUI_THREAD (bind (mem_fun (*this, &MidiStreamView::add_region_view), r)); + + MidiRegion* region = dynamic_cast<MidiRegion*> (r); + + if (region == 0) { + return; + } + + MidiRegionView *region_view; + list<RegionView *>::iterator i; + + for (i = region_views.begin(); i != region_views.end(); ++i) { + if (&(*i)->region() == r) { + + /* great. we already have a MidiRegionView for this Region. use it again. */ + + (*i)->set_valid (true); + return; + } + } + + /* FIXME + switch (_trackview.midi_track()->mode()) { + case Normal: + region_view = new MidiRegionView (canvas_group, _trackview, *region, + _samples_per_unit, region_color); + break; + case Destructive: + region_view = new TapeMidiRegionView (canvas_group, _trackview, *region, + _samples_per_unit, region_color); + break; + } + */ + region_view = new MidiRegionView (canvas_group, _trackview, *region, + _samples_per_unit, region_color); + + region_view->init (region_color, wait_for_waves); + region_views.push_front (region_view); + + /* catch regionview going away */ + + region->GoingAway.connect (mem_fun (*this, &MidiStreamView::remove_region_view)); + + RegionViewAdded (region_view); +#endif +} + +// FIXME: code duplication with AudioStreamVIew +void +MidiStreamView::redisplay_diskstream () +{ + list<RegionView *>::iterator i, tmp; + + for (i = region_views.begin(); i != region_views.end(); ++i) { + (*i)->set_valid (false); + } + + if (_trackview.is_midi_track()) { + _trackview.get_diskstream()->playlist()->foreach_region (static_cast<StreamView*>(this), &StreamView::add_region_view); + } + + for (i = region_views.begin(); i != region_views.end(); ) { + tmp = i; + tmp++; + + if (!(*i)->is_valid()) { + delete *i; + region_views.erase (i); + } + + i = tmp; + } + + /* now fix layering */ + + playlist_modified (); +} + + +void +MidiStreamView::setup_rec_box () +{ +#if 0 + // cerr << _trackview.name() << " streamview SRB\n"; + + if (_trackview.session().transport_rolling()) { + + // cerr << "\trolling\n"; + + if (!rec_active && + _trackview.session().record_status() == Session::Recording && + _trackview.get_diskstream()->record_enabled()) { + + if (_trackview.midi_track()->mode() == Normal && use_rec_regions && rec_regions.size() == rec_rects.size()) { + + /* add a new region, but don't bother if they set use_rec_regions mid-record */ + + MidiRegion::SourceList sources; + + // FIXME + MidiDiskstream* ads = dynamic_cast<MidiDiskstream*>(_trackview.get_diskstream()); + assert(ads); + + // handle multi + + jack_nframes_t start = 0; + if (rec_regions.size() > 0) { + start = rec_regions.back()->start() + _trackview.get_diskstream()->get_captured_frames(rec_regions.size()-1); + } + + MidiRegion * region = new MidiRegion(sources, start, 1 , "", 0, (Region::Flag)(Region::DefaultFlags | Region::DoNotSaveState), false); + region->set_position (_trackview.session().transport_frame(), this); + rec_regions.push_back (region); + /* catch it if it goes away */ + region->GoingAway.connect (mem_fun (*this, &MidiStreamView::remove_rec_region)); + + /* we add the region later */ + } + + /* start a new rec box */ + + MidiTrack* at; + + at = _trackview.midi_track(); /* we know what it is already */ + MidiDiskstream& ds = at->midi_diskstream(); + jack_nframes_t frame_pos = ds.current_capture_start (); + gdouble xstart = _trackview.editor.frame_to_pixel (frame_pos); + gdouble xend; + uint32_t fill_color; + + switch (_trackview.midi_track()->mode()) { + case Normal: + xend = xstart; + fill_color = color_map[cRecordingRectFill]; + break; + + case Destructive: + xend = xstart + 2; + fill_color = color_map[cRecordingRectFill]; + /* make the recording rect translucent to allow + the user to see the peak data coming in, etc. + */ + fill_color = UINT_RGBA_CHANGE_A (fill_color, 120); + break; + } + + ArdourCanvas::SimpleRect * rec_rect = new Gnome::Canvas::SimpleRect (*canvas_group); + rec_rect->property_x1() = xstart; + rec_rect->property_y1() = 1.0; + rec_rect->property_x2() = xend; + rec_rect->property_y2() = (double) _trackview.height - 1; + rec_rect->property_outline_color_rgba() = color_map[cRecordingRectOutline]; + rec_rect->property_fill_color_rgba() = fill_color; + + RecBoxInfo recbox; + recbox.rectangle = rec_rect; + recbox.start = _trackview.session().transport_frame(); + recbox.length = 0; + + rec_rects.push_back (recbox); + + screen_update_connection.disconnect(); + screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (mem_fun (*this, &MidiStreamView::update_rec_box)); + rec_updating = true; + rec_active = true; + + } else if (rec_active && + (_trackview.session().record_status() != Session::Recording || + !_trackview.get_diskstream()->record_enabled())) { + + screen_update_connection.disconnect(); + rec_active = false; + rec_updating = false; + + } + + } else { + + // cerr << "\tNOT rolling, rec_rects = " << rec_rects.size() << " rec_regions = " << rec_regions.size() << endl; + + if (!rec_rects.empty() || !rec_regions.empty()) { + + /* disconnect rapid update */ + screen_update_connection.disconnect(); + + for (list<sigc::connection>::iterator prc = peak_ready_connections.begin(); prc != peak_ready_connections.end(); ++prc) { + (*prc).disconnect(); + } + peak_ready_connections.clear(); + + rec_updating = false; + rec_active = false; + last_rec_peak_frame = 0; + + /* remove temp regions */ + for (list<Region*>::iterator iter=rec_regions.begin(); iter != rec_regions.end(); ) + { + list<Region*>::iterator tmp; + + tmp = iter; + ++tmp; + + /* this will trigger the remove_region_view */ + delete *iter; + + iter = tmp; + } + + rec_regions.clear(); + + // cerr << "\tclear " << rec_rects.size() << " rec rects\n"; + + + /* transport stopped, clear boxes */ + for (vector<RecBoxInfo>::iterator iter=rec_rects.begin(); iter != rec_rects.end(); ++iter) { + RecBoxInfo &rect = (*iter); + delete rect.rectangle; + } + + rec_rects.clear(); + + } + } +#endif +} + +void +MidiStreamView::update_rec_regions () +{ +#if 0 + if (use_rec_regions) { + + uint32_t n = 0; + + for (list<Region*>::iterator iter = rec_regions.begin(); iter != rec_regions.end(); n++) { + + list<Region*>::iterator tmp; + + tmp = iter; + ++tmp; + + if (!canvas_item_visible (rec_rects[n].rectangle)) { + /* rect already hidden, this region is done */ + iter = tmp; + continue; + } + + // FIXME + MidiRegion * region = dynamic_cast<MidiRegion*>(*iter); + assert(region); + + jack_nframes_t origlen = region->length(); + + if (region == rec_regions.back() && rec_active) { + + if (last_rec_peak_frame > region->start()) { + + jack_nframes_t nlen = last_rec_peak_frame - region->start(); + + if (nlen != region->length()) { + + region->freeze (); + region->set_position (_trackview.get_diskstream()->get_capture_start_frame(n), this); + region->set_length (nlen, this); + region->thaw ("updated"); + + if (origlen == 1) { + /* our special initial length */ + add_region_view_internal (region, false); + } + + /* also update rect */ + ArdourCanvas::SimpleRect * rect = rec_rects[n].rectangle; + gdouble xend = _trackview.editor.frame_to_pixel (region->position() + region->length()); + rect->property_x2() = xend; + } + } + + } else { + + jack_nframes_t nlen = _trackview.get_diskstream()->get_captured_frames(n); + + if (nlen != region->length()) { + + if (region->source(0).length() >= region->start() + nlen) { + + region->freeze (); + region->set_position (_trackview.get_diskstream()->get_capture_start_frame(n), this); + region->set_length (nlen, this); + region->thaw ("updated"); + + if (origlen == 1) { + /* our special initial length */ + add_region_view_internal (region, false); + } + + /* also hide rect */ + ArdourCanvas::Item * rect = rec_rects[n].rectangle; + rect->hide(); + + } + } + } + + iter = tmp; + } + } +#endif +} + +void +MidiStreamView::color_handler (ColorID id, uint32_t val) +{ + switch (id) { + case cMidiTrackBase: + if (_trackview.is_midi_track()) { + canvas_rect->property_fill_color_rgba() = val; + } + break; + case cMidiBusBase: + if (!_trackview.is_midi_track()) { + canvas_rect->property_fill_color_rgba() = val; + } + break; + case cMidiTrackOutline: + canvas_rect->property_outline_color_rgba() = val; + break; + + default: + break; + } +} diff --git a/gtk2_ardour/midi_streamview.h b/gtk2_ardour/midi_streamview.h new file mode 100644 index 0000000000..0b13f9fd7f --- /dev/null +++ b/gtk2_ardour/midi_streamview.h @@ -0,0 +1,77 @@ +/* + Copyright (C) 2001, 2006 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __ardour_midi_streamview_h__ +#define __ardour_midi_streamview_h__ + +#include <list> +#include <map> +#include <cmath> + +#include <ardour/location.h> +#include "enums.h" +#include "simplerect.h" +#include "color.h" +#include "streamview.h" + +namespace Gdk { + class Color; +} + +namespace ARDOUR { + class Route; + class Diskstream; + class Crossfade; + class PeakData; + class MidiRegion; + class Source; +} + +class PublicEditor; +class Selectable; +class MidiTimeAxisView; +class MidiRegionView; +class RegionSelection; +class CrossfadeView; +class Selection; + +class MidiStreamView : public StreamView +{ + public: + MidiStreamView (MidiTimeAxisView&); + ~MidiStreamView (); + + void set_selected_regionviews (RegionSelection&); + void get_selectables (jack_nframes_t start, jack_nframes_t end, list<Selectable* >&); + void get_inverted_selectables (Selection&, list<Selectable* >& results); + + private: + void setup_rec_box (); + void rec_peak_range_ready (jack_nframes_t start, jack_nframes_t cnt, ARDOUR::Source* src); + void update_rec_regions (); + + void add_region_view_internal (ARDOUR::Region*, bool wait_for_waves); + void remove_midi_region_view (ARDOUR::MidiRegion* ); + void remove_midi_rec_region (ARDOUR::MidiRegion*); + + void redisplay_diskstream (); + + void color_handler (ColorID id, uint32_t val); +}; + +#endif /* __ardour_midi_streamview_h__ */ diff --git a/gtk2_ardour/midi_time_axis.cc b/gtk2_ardour/midi_time_axis.cc new file mode 100644 index 0000000000..081fc543db --- /dev/null +++ b/gtk2_ardour/midi_time_axis.cc @@ -0,0 +1,298 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <cstdlib> +#include <cmath> + +#include <algorithm> +#include <string> +#include <vector> + +#include <sigc++/bind.h> + +#include <pbd/error.h> +#include <pbd/stl_delete.h> +#include <pbd/whitespace.h> + +#include <gtkmm2ext/gtk_ui.h> +#include <gtkmm2ext/selector.h> +#include <gtkmm2ext/stop_signal.h> +#include <gtkmm2ext/bindable_button.h> +#include <gtkmm2ext/utils.h> + +#include <ardour/midi_playlist.h> +#include <ardour/midi_diskstream.h> +#include <ardour/insert.h> +#include <ardour/ladspa_plugin.h> +#include <ardour/location.h> +#include <ardour/playlist.h> +#include <ardour/session.h> +#include <ardour/session_playlist.h> +#include <ardour/utils.h> + +#include "ardour_ui.h" +#include "midi_time_axis.h" +#include "automation_time_axis.h" +#include "canvas_impl.h" +#include "crossfade_view.h" +#include "enums.h" +#include "gui_thread.h" +#include "keyboard.h" +#include "playlist_selector.h" +#include "plugin_selector.h" +#include "plugin_ui.h" +#include "point_selection.h" +#include "prompter.h" +#include "public_editor.h" +#include "redirect_automation_line.h" +#include "redirect_automation_time_axis.h" +#include "regionview.h" +#include "rgb_macros.h" +#include "selection.h" +#include "simplerect.h" +#include "midi_streamview.h" +#include "utils.h" + +#include <ardour/midi_track.h> + +#include "i18n.h" + +using namespace ARDOUR; +using namespace PBD; +using namespace Gtk; +using namespace Editing; + + +MidiTimeAxisView::MidiTimeAxisView (PublicEditor& ed, Session& sess, Route& rt, Canvas& canvas) + : AxisView(sess), // FIXME: won't compile without this, why?? + RouteTimeAxisView(ed, sess, rt, canvas) +{ + subplugin_menu.set_name ("ArdourContextMenu"); + + _view = new MidiStreamView (*this); + + ignore_toggle = false; + + mute_button->set_active (false); + solo_button->set_active (false); + + if (is_midi_track()) + controls_ebox.set_name ("MidiTimeAxisViewControlsBaseUnselected"); + else // bus + controls_ebox.set_name ("MidiBusControlsBaseUnselected"); + + /* map current state of the route */ + + //redirects_changed (0); + + ensure_xml_node (); + + set_state (*xml_node); + + //_route.redirects_changed.connect (mem_fun(*this, &MidiTimeAxisView::redirects_changed)); + + if (is_midi_track()) { + + controls_ebox.set_name ("MidiTrackControlsBaseUnselected"); + controls_base_selected_name = "MidiTrackControlsBaseSelected"; + controls_base_unselected_name = "MidiTrackControlsBaseUnselected"; + + /* ask for notifications of any new RegionViews */ + //view->MidiRegionViewAdded.connect (mem_fun(*this, &MidiTimeAxisView::region_view_added)); + //view->attach (); + + } else { /* bus */ + + controls_ebox.set_name ("MidiBusControlsBaseUnselected"); + controls_base_selected_name = "MidiBusControlsBaseSelected"; + controls_base_unselected_name = "MidiBusControlsBaseUnselected"; + } +} + +MidiTimeAxisView::~MidiTimeAxisView () +{ +} + +guint32 +MidiTimeAxisView::show_at (double y, int& nth, Gtk::VBox *parent) +{ + ensure_xml_node (); + xml_node->add_property ("shown_editor", "yes"); + + return TimeAxisView::show_at (y, nth, parent); +} + +void +MidiTimeAxisView::hide () +{ + ensure_xml_node (); + xml_node->add_property ("shown_editor", "no"); + + TimeAxisView::hide (); +} + +void +MidiTimeAxisView::set_state (const XMLNode& node) +{ + const XMLProperty *prop; + + TimeAxisView::set_state (node); + + if ((prop = node.property ("shown_editor")) != 0) { + if (prop->value() == "no") { + _marked_for_display = false; + } else { + _marked_for_display = true; + } + } else { + _marked_for_display = true; + } + + XMLNodeList nlist = node.children(); + XMLNodeConstIterator niter; + XMLNode *child_node; + + for (niter = nlist.begin(); niter != nlist.end(); ++niter) { + child_node = *niter; + + // uh... do stuff.. + } +} + +void +MidiTimeAxisView::build_display_menu () +{ + using namespace Menu_Helpers; + + /* get the size menu ready */ + + build_size_menu (); + + /* prepare it */ + + TimeAxisView::build_display_menu (); + + /* now fill it with our stuff */ + + MenuList& items = display_menu->items(); + display_menu->set_name ("ArdourContextMenu"); + + items.push_back (MenuElem (_("Height"), *size_menu)); + items.push_back (MenuElem (_("Color"), mem_fun(*this, &MidiTimeAxisView::select_track_color))); + + + items.push_back (SeparatorElem()); + + build_remote_control_menu (); + items.push_back (MenuElem (_("Remote Control ID"), *remote_control_menu)); + + automation_action_menu = manage (new Menu); + MenuList& automation_items = automation_action_menu->items(); + automation_action_menu->set_name ("ArdourContextMenu"); + + automation_items.push_back (SeparatorElem()); + + automation_items.push_back (MenuElem (_("Plugins"), subplugin_menu)); + + if (is_midi_track()) { + + Menu* alignment_menu = manage (new Menu); + MenuList& alignment_items = alignment_menu->items(); + alignment_menu->set_name ("ArdourContextMenu"); + + RadioMenuItem::Group align_group; + + alignment_items.push_back (RadioMenuElem (align_group, _("Align with existing material"), bind (mem_fun(*this, &MidiTimeAxisView::set_align_style), ExistingMaterial))); + align_existing_item = dynamic_cast<RadioMenuItem*>(&alignment_items.back()); + if (get_diskstream()->alignment_style() == ExistingMaterial) { + align_existing_item->set_active(); + } + alignment_items.push_back (RadioMenuElem (align_group, _("Align with capture time"), bind (mem_fun(*this, &MidiTimeAxisView::set_align_style), CaptureTime))); + align_capture_item = dynamic_cast<RadioMenuItem*>(&alignment_items.back()); + if (get_diskstream()->alignment_style() == CaptureTime) { + align_capture_item->set_active(); + } + + items.push_back (MenuElem (_("Alignment"), *alignment_menu)); + + get_diskstream()->AlignmentStyleChanged.connect (mem_fun(*this, &MidiTimeAxisView::align_style_changed)); + } + + items.push_back (SeparatorElem()); + items.push_back (CheckMenuElem (_("Active"), mem_fun(*this, &RouteUI::toggle_route_active))); + route_active_menu_item = dynamic_cast<CheckMenuItem *> (&items.back()); + route_active_menu_item->set_active (_route.active()); + + items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Remove"), mem_fun(*this, &RouteUI::remove_this_route))); + +} + +// FIXME: duplicated in audio_time_axis.cc +/*static string +legalize_for_xml_node (string str) +{ + string::size_type pos; + string legal_chars = "abcdefghijklmnopqrtsuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_+=:"; + string legal; + + legal = str; + pos = 0; + + while ((pos = legal.find_first_not_of (legal_chars, pos)) != string::npos) { + legal.replace (pos, 1, "_"); + pos += 1; + } + + return legal; +}*/ + +void +MidiTimeAxisView::route_active_changed () +{ + RouteUI::route_active_changed (); + + if (is_midi_track()) { + if (_route.active()) { + controls_ebox.set_name ("MidiTrackControlsBaseUnselected"); + controls_base_selected_name = "MidiTrackControlsBaseSelected"; + controls_base_unselected_name = "MidiTrackControlsBaseUnselected"; + } else { + controls_ebox.set_name ("MidiTrackControlsBaseInactiveUnselected"); + controls_base_selected_name = "MidiTrackControlsBaseInactiveSelected"; + controls_base_unselected_name = "MidiTrackControlsBaseInactiveUnselected"; + } + } else { + if (_route.active()) { + controls_ebox.set_name ("BusControlsBaseUnselected"); + controls_base_selected_name = "BusControlsBaseSelected"; + controls_base_unselected_name = "BusControlsBaseUnselected"; + } else { + controls_ebox.set_name ("BusControlsBaseInactiveUnselected"); + controls_base_selected_name = "BusControlsBaseInactiveSelected"; + controls_base_unselected_name = "BusControlsBaseInactiveUnselected"; + } + } +} + +XMLNode* +MidiTimeAxisView::get_child_xml_node (const string & childname) +{ + return RouteUI::get_child_xml_node (childname); +} + diff --git a/gtk2_ardour/midi_time_axis.h b/gtk2_ardour/midi_time_axis.h new file mode 100644 index 0000000000..c34b25ea46 --- /dev/null +++ b/gtk2_ardour/midi_time_axis.h @@ -0,0 +1,91 @@ +/* + Copyright (C) 2006 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __ardour_midi_time_axis_h__ +#define __ardour_midi_time_axis_h__ + +#include <gtkmm/table.h> +#include <gtkmm/button.h> +#include <gtkmm/box.h> +#include <gtkmm/menu.h> +#include <gtkmm/menuitem.h> +#include <gtkmm/radiomenuitem.h> +#include <gtkmm/checkmenuitem.h> + +#include <gtkmm2ext/selector.h> +#include <list> + +#include <ardour/types.h> +#include <ardour/region.h> + +#include "ardour_dialog.h" +#include "route_ui.h" +#include "enums.h" +#include "route_time_axis.h" +#include "canvas.h" +#include "color.h" + +namespace ARDOUR { + class Session; + class MidiDiskstream; + class RouteGroup; + class Redirect; + class Insert; + class Location; + class MidiPlaylist; +} + +class PublicEditor; +class Selection; +class Selectable; +class AutomationLine; +class AutomationGainLine; +class AutomationPanLine; +class RedirectAutomationLine; +class TimeSelection; +class AutomationTimeAxisView; + +class MidiTimeAxisView : public RouteTimeAxisView +{ + public: + MidiTimeAxisView (PublicEditor&, ARDOUR::Session&, ARDOUR::Route&, ArdourCanvas::Canvas& canvas); + virtual ~MidiTimeAxisView (); + + /* overridden from parent to store display state */ + guint32 show_at (double y, int& nth, Gtk::VBox *parent); + void hide (); + + void set_state (const XMLNode&); + XMLNode* get_child_xml_node (const string & childname); + + private: + void region_view_added (RegionView*) {} + + void route_active_changed (); + + void redirects_changed (void *); + + void build_display_menu (); + + void add_redirect_to_subplugin_menu (ARDOUR::Redirect *); + + Gtk::Menu subplugin_menu; +}; + +#endif /* __ardour_midi_time_axis_h__ */ + diff --git a/gtk2_ardour/pan_automation_time_axis.cc b/gtk2_ardour/pan_automation_time_axis.cc index a39f2996f8..4cb319f267 100644 --- a/gtk2_ardour/pan_automation_time_axis.cc +++ b/gtk2_ardour/pan_automation_time_axis.cc @@ -104,7 +104,7 @@ void PanAutomationTimeAxisView::add_line (AutomationLine& line) { char buf[32]; - snprintf(buf,32,"Line %d",lines.size()+1); + snprintf(buf,32,"Line %ld",lines.size()+1); multiline_selector.append_text(buf); if (lines.empty()) { diff --git a/gtk2_ardour/panner_ui.cc b/gtk2_ardour/panner_ui.cc index fac92a2844..3af08b03f7 100644 --- a/gtk2_ardour/panner_ui.cc +++ b/gtk2_ardour/panner_ui.cc @@ -327,11 +327,7 @@ PannerUI::setup_pan () bc->StopGesture.connect (bind (mem_fun (_io, &IO::end_pan_touch), (uint32_t) asz)); char buf[64]; -#ifdef __APPLE__ - snprintf (buf, sizeof (buf), _("panner for channel %lu"), asz + 1); -#else - snprintf (buf, sizeof (buf), _("panner for channel %u"), asz + 1); -#endif + snprintf (buf, sizeof (buf), _("panner for channel %zu"), asz + 1); ARDOUR_UI::instance()->tooltips().set_tip (bc->event_widget(), buf); bc->event_widget().signal_button_release_event().connect diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h index 4c12b99d7c..42e313cf60 100644 --- a/gtk2_ardour/public_editor.h +++ b/gtk2_ardour/public_editor.h @@ -39,7 +39,9 @@ class AutomationLine; class ControlPoint; class SelectionRect; class CrossfadeView; +class RouteTimeAxisView; class AudioTimeAxisView; +class RegionView; class AudioRegionView; class TempoMarker; class MeterMarker; @@ -145,10 +147,10 @@ class PublicEditor : public Gtk::Window, public Stateful { virtual bool canvas_fade_in_handle_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*) = 0; virtual bool canvas_fade_out_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*) = 0; virtual bool canvas_fade_out_handle_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*) = 0; - virtual bool canvas_region_view_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*) = 0; - virtual bool canvas_region_view_name_highlight_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*) = 0; + virtual bool canvas_region_view_event (GdkEvent* event,ArdourCanvas::Item*, RegionView*) = 0; + virtual bool canvas_region_view_name_highlight_event (GdkEvent* event,ArdourCanvas::Item*, RegionView*) = 0; virtual bool canvas_region_view_name_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*) = 0; - virtual bool canvas_stream_view_event (GdkEvent* event,ArdourCanvas::Item*, AudioTimeAxisView*) = 0; + virtual bool canvas_stream_view_event (GdkEvent* event,ArdourCanvas::Item*, RouteTimeAxisView*) = 0; virtual bool canvas_marker_event (GdkEvent* event,ArdourCanvas::Item*, Marker*) = 0; virtual bool canvas_zoom_rect_event (GdkEvent* event,ArdourCanvas::Item*) = 0; virtual bool canvas_tempo_marker_event (GdkEvent* event,ArdourCanvas::Item*, TempoMarker*) = 0; diff --git a/gtk2_ardour/region_editor.h b/gtk2_ardour/region_editor.h index 65b0bbaa94..176ced0792 100644 --- a/gtk2_ardour/region_editor.h +++ b/gtk2_ardour/region_editor.h @@ -15,172 +15,29 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id$ + $Id: region_editor.h 231 2006-01-03 14:16:27Z karstenweise $ */ #ifndef __gtk_ardour_region_edit_h__ #define __gtk_ardour_region_edit_h__ -#include <map> - -#include <gtkmm/label.h> -#include <gtkmm/entry.h> -#include <gtkmm/box.h> -#include <gtkmm/togglebutton.h> -#include <gtkmm/button.h> -#include <gtkmm/arrow.h> -#include <gtkmm/frame.h> -#include <gtkmm/table.h> -#include <gtkmm/alignment.h> -#include <gtkmm/adjustment.h> -#include <gtkmm/separator.h> -#include <gtkmm/spinbutton.h> - -#include <libgnomecanvas/libgnomecanvas.h> -#include <sigc++/signal.h> - -#include "audio_clock.h" #include "ardour_dialog.h" -namespace ARDOUR { - class AudioRegion; - class Session; -} - -class AudioRegionView; +namespace ARDOUR { class Session; } -class AudioRegionEditor : public ArdourDialog +/** Just a useless stub for now... */ +class RegionEditor : public ArdourDialog { public: - AudioRegionEditor (ARDOUR::Session&, ARDOUR::AudioRegion&, AudioRegionView& rv); - ~AudioRegionEditor (); - - private: - ARDOUR::Session& _session; - ARDOUR::AudioRegion& _region; - AudioRegionView& _region_view; - - void connect_editor_events (); - - Gtk::Label name_label; - Gtk::Entry name_entry; - Gtk::HBox name_hbox; - - Gtk::HBox top_row_hbox; - Gtk::HBox top_row_button_hbox; - - Gtk::ToggleButton lock_button; - Gtk::ToggleButton mute_button; - Gtk::ToggleButton opaque_button; - Gtk::ToggleButton envelope_active_button; - Gtk::ToggleButton envelope_view_button; - - Gtk::Button raise_button; - Gtk::Arrow raise_arrow; - Gtk::Button lower_button; - Gtk::Arrow lower_arrow; - Gtk::Frame layer_frame; - Gtk::Label layer_value_label; - Gtk::Label layer_label; - Gtk::HBox layer_hbox; - - Gtk::ToggleButton audition_button; - - Gtk::HBox lower_hbox; - - Gtk::Table time_table; - - Gtk::Label start_label; - Gtk::Label end_label; - Gtk::Label length_label; - Gtk::Alignment start_alignment; - Gtk::Alignment end_alignment; - Gtk::Alignment length_alignment; - - AudioClock start_clock; - AudioClock end_clock; - AudioClock length_clock; - AudioClock sync_offset_clock; - - Gtk::Table envelope_loop_table; - Gtk::Button loop_button; - Gtk::Label loop_label; - Gtk::Label envelope_label; - - Gtk::Table fade_in_table; - Gtk::Label fade_in_label; - Gtk::Alignment fade_in_label_align; - Gtk::Label fade_in_active_button_label; - Gtk::ToggleButton fade_in_active_button; - Gtk::Label fade_in_length_label; - - Gtk::Adjustment fade_in_length_adjustment; - Gtk::SpinButton fade_in_length_spinner; - - Gtk::Table fade_out_table; - Gtk::Label fade_out_label; - Gtk::Alignment fade_out_label_align; - Gtk::Label fade_out_active_button_label; - Gtk::ToggleButton fade_out_active_button; - Gtk::Label fade_out_length_label; - - Gtk::Adjustment fade_out_length_adjustment; - Gtk::SpinButton fade_out_length_spinner; - - Gtk::HSeparator sep3; - Gtk::VSeparator sep1; - Gtk::VSeparator sep2; - - void region_changed (ARDOUR::Change); - void bounds_changed (ARDOUR::Change); - void name_changed (); - void opacity_changed (); - void mute_changed (); - void envelope_active_changed (); - void lock_changed (); - void layer_changed (); - - void fade_in_length_adjustment_changed (); - void fade_out_length_adjustment_changed (); - void fade_in_changed (); - void fade_out_changed (); - void audition_state_changed (bool); - - void activation (); - - void name_entry_changed (); - void start_clock_changed (); - void end_clock_changed (); - void length_clock_changed (); - - gint envelope_active_button_press (GdkEventButton *); - gint envelope_active_button_release (GdkEventButton *); - - void audition_button_toggled (); - void envelope_view_button_toggled (); - void lock_button_clicked (); - void mute_button_clicked (); - void opaque_button_clicked (); - void raise_button_clicked (); - void lower_button_clicked (); - - void fade_in_active_toggled (); - void fade_out_active_toggled (); - void fade_in_active_changed (); - void fade_out_active_changed (); - - void fade_in_realized (); - void fade_out_realized (); - - void start_editing_fade_in (); - void start_editing_fade_out (); - void stop_editing_fade_in (); - void stop_editing_fade_out (); + RegionEditor(ARDOUR::Session& s) + : ArdourDialog ("region editor") + , _session(s) + {} - gint bpressed (GdkEventButton* ev, Gtk::SpinButton* but, void (AudioRegionEditor::*pmf)()); - gint breleased (GdkEventButton* ev, Gtk::SpinButton* but, void (AudioRegionEditor::*pmf)()); + virtual ~RegionEditor () {} - bool spin_arrow_grab; + protected: + ARDOUR::Session& _session; }; #endif /* __gtk_ardour_region_edit_h__ */ diff --git a/gtk2_ardour/region_gain_line.cc b/gtk2_ardour/region_gain_line.cc index bba9410ffb..ee966a064f 100644 --- a/gtk2_ardour/region_gain_line.cc +++ b/gtk2_ardour/region_gain_line.cc @@ -2,7 +2,7 @@ #include <ardour/audioregion.h> #include "region_gain_line.h" -#include "regionview.h" +#include "audio_regionview.h" #include "utils.h" #include "time_axis_view.h" @@ -46,8 +46,8 @@ void AudioRegionGainLine::start_drag (ControlPoint* cp, float fraction) { AutomationLine::start_drag(cp,fraction); - if (!rv.region.envelope_active()) { - trackview.session().add_undo( bind( mem_fun(rv.region, &AudioRegion::set_envelope_active), false) ); + if (!rv.audio_region().envelope_active()) { + trackview.session().add_undo( bind( mem_fun(rv.audio_region(), &AudioRegion::set_envelope_active), false) ); } } @@ -62,10 +62,10 @@ AudioRegionGainLine::remove_point (ControlPoint& cp) trackview.editor.current_session()->begin_reversible_command (_("remove control point")); trackview.editor.current_session()->add_undo (get_memento()); - if (!rv.region.envelope_active()) { - trackview.session().add_undo( bind( mem_fun(rv.region, &AudioRegion::set_envelope_active), false) ); - trackview.session().add_redo( bind( mem_fun(rv.region, &AudioRegion::set_envelope_active), true) ); - rv.region.set_envelope_active(true); + if (!rv.audio_region().envelope_active()) { + trackview.session().add_undo( bind( mem_fun(rv.audio_region(), &AudioRegion::set_envelope_active), false) ); + trackview.session().add_redo( bind( mem_fun(rv.audio_region(), &AudioRegion::set_envelope_active), true) ); + rv.audio_region().set_envelope_active(true); } alist.erase (mr.start, mr.end); @@ -78,9 +78,9 @@ AudioRegionGainLine::remove_point (ControlPoint& cp) void AudioRegionGainLine::end_drag (ControlPoint* cp) { - if (!rv.region.envelope_active()) { - trackview.session().add_redo( bind( mem_fun(rv.region, &AudioRegion::set_envelope_active), true) ); - rv.region.set_envelope_active(true); + if (!rv.audio_region().envelope_active()) { + trackview.session().add_redo( bind( mem_fun(rv.audio_region(), &AudioRegion::set_envelope_active), true) ); + rv.audio_region().set_envelope_active(true); } AutomationLine::end_drag(cp); } diff --git a/gtk2_ardour/region_selection.cc b/gtk2_ardour/region_selection.cc index 751584cab7..aadedce423 100644 --- a/gtk2_ardour/region_selection.cc +++ b/gtk2_ardour/region_selection.cc @@ -1,6 +1,24 @@ +/* + Copyright (C) 2006 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + #include <algorithm> -#include <ardour/audioregion.h> +#include <ardour/region.h> #include "regionview.h" #include "region_selection.h" @@ -11,7 +29,7 @@ using namespace sigc; bool -AudioRegionComparator::operator() (const AudioRegionView* a, const AudioRegionView* b) const +RegionComparator::operator() (const RegionView* a, const RegionView* b) const { if (a == b) { return false; @@ -20,16 +38,16 @@ AudioRegionComparator::operator() (const AudioRegionView* a, const AudioRegionVi } } -AudioRegionSelection::AudioRegionSelection () +RegionSelection::RegionSelection () { _current_start = 0; _current_end = 0; } -AudioRegionSelection::AudioRegionSelection (const AudioRegionSelection& other) +RegionSelection::RegionSelection (const RegionSelection& other) { - for (AudioRegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) { + for (RegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) { add (*i, false); } _current_start = other._current_start; @@ -38,14 +56,14 @@ AudioRegionSelection::AudioRegionSelection (const AudioRegionSelection& other) -AudioRegionSelection& -AudioRegionSelection::operator= (const AudioRegionSelection& other) +RegionSelection& +RegionSelection::operator= (const RegionSelection& other) { if (this != &other) { clear_all(); - for (AudioRegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) { + for (RegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) { add (*i, false); } @@ -57,13 +75,13 @@ AudioRegionSelection::operator= (const AudioRegionSelection& other) } void -AudioRegionSelection::clear_all() +RegionSelection::clear_all() { clear(); _bylayer.clear(); } -bool AudioRegionSelection::contains (AudioRegionView* rv) +bool RegionSelection::contains (RegionView* rv) { if (this->find (rv) != end()) { return true; @@ -75,21 +93,21 @@ bool AudioRegionSelection::contains (AudioRegionView* rv) } void -AudioRegionSelection::add (AudioRegionView* rv, bool dosort) +RegionSelection::add (RegionView* rv, bool dosort) { if (this->find (rv) != end()) { /* we already have it */ return; } - rv->AudioRegionViewGoingAway.connect (mem_fun(*this, &AudioRegionSelection::remove_it)); + rv->RegionViewGoingAway.connect (mem_fun(*this, &RegionSelection::remove_it)); - if (rv->region.first_frame() < _current_start || empty()) { - _current_start = rv->region.first_frame(); + if (rv->region().first_frame() < _current_start || empty()) { + _current_start = rv->region().first_frame(); } - if (rv->region.last_frame() > _current_end || empty()) { - _current_end = rv->region.last_frame(); + if (rv->region().last_frame() > _current_end || empty()) { + _current_end = rv->region().last_frame(); } insert (rv); @@ -100,15 +118,15 @@ AudioRegionSelection::add (AudioRegionView* rv, bool dosort) } void -AudioRegionSelection::remove_it (AudioRegionView *rv) +RegionSelection::remove_it (RegionView *rv) { remove (rv); } bool -AudioRegionSelection::remove (AudioRegionView* rv) +RegionSelection::remove (RegionView* rv) { - AudioRegionSelection::iterator i; + RegionSelection::iterator i; if ((i = this->find (rv)) != end()) { @@ -124,7 +142,7 @@ AudioRegionSelection::remove (AudioRegionView* rv) } else { - AudioRegion& region ((*i)->region); + Region& region ((*i)->region()); if (region.first_frame() == _current_start) { @@ -165,15 +183,15 @@ AudioRegionSelection::remove (AudioRegionView* rv) } void -AudioRegionSelection::add_to_layer (AudioRegionView * rv) +RegionSelection::add_to_layer (RegionView * rv) { // insert it into layer sorted position - list<AudioRegionView*>::iterator i; + list<RegionView*>::iterator i; for (i = _bylayer.begin(); i != _bylayer.end(); ++i) { - if (rv->region.layer() < (*i)->region.layer()) { + if (rv->region().layer() < (*i)->region().layer()) { _bylayer.insert(i, rv); return; } @@ -184,16 +202,16 @@ AudioRegionSelection::add_to_layer (AudioRegionView * rv) } struct RegionSortByTime { - bool operator() (const AudioRegionView* a, const AudioRegionView* b) { - return a->region.position() < b->region.position(); + bool operator() (const RegionView* a, const RegionView* b) { + return a->region().position() < b->region().position(); } }; void -AudioRegionSelection::by_position (list<AudioRegionView*>& foo) const +RegionSelection::by_position (list<RegionView*>& foo) const { - list<AudioRegionView*>::const_iterator i; + list<RegionView*>::const_iterator i; RegionSortByTime sorter; for (i = _bylayer.begin(); i != _bylayer.end(); ++i) { diff --git a/gtk2_ardour/region_selection.h b/gtk2_ardour/region_selection.h index 0c2b7be025..2192442cb0 100644 --- a/gtk2_ardour/region_selection.h +++ b/gtk2_ardour/region_selection.h @@ -1,3 +1,21 @@ +/* + Copyright (C) 2006 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + #ifndef __ardour_gtk_region_selection_h__ #define __ardour_gtk_region_selection_h__ @@ -9,23 +27,23 @@ using std::list; using std::set; -class AudioRegionView; +class RegionView; -struct AudioRegionComparator { - bool operator() (const AudioRegionView* a, const AudioRegionView* b) const; +struct RegionComparator { + bool operator() (const RegionView* a, const RegionView* b) const; }; -class AudioRegionSelection : public set<AudioRegionView*, AudioRegionComparator>, public sigc::trackable +class RegionSelection : public set<RegionView*, RegionComparator>, public sigc::trackable { public: - AudioRegionSelection(); - AudioRegionSelection (const AudioRegionSelection&); + RegionSelection(); + RegionSelection (const RegionSelection&); - AudioRegionSelection& operator= (const AudioRegionSelection&); + RegionSelection& operator= (const RegionSelection&); - void add (AudioRegionView*, bool dosort = true); - bool remove (AudioRegionView*); - bool contains (AudioRegionView*); + void add (RegionView*, bool dosort = true); + bool remove (RegionView*); + bool contains (RegionView*); void clear_all(); @@ -39,18 +57,18 @@ class AudioRegionSelection : public set<AudioRegionView*, AudioRegionComparator> return _current_end; } - const list<AudioRegionView *> & by_layer() const { return _bylayer; } - void by_position (list<AudioRegionView*>&) const; + const list<RegionView *> & by_layer() const { return _bylayer; } + void by_position (list<RegionView*>&) const; private: - void remove_it (AudioRegionView*); + void remove_it (RegionView*); - void add_to_layer (AudioRegionView *); + void add_to_layer (RegionView *); jack_nframes_t _current_start; jack_nframes_t _current_end; - list<AudioRegionView *> _bylayer; + list<RegionView *> _bylayer; }; #endif /* __ardour_gtk_region_selection_h__ */ diff --git a/gtk2_ardour/regionview.cc b/gtk2_ardour/regionview.cc index fa51dd455c..d47b09853c 100644 --- a/gtk2_ardour/regionview.cc +++ b/gtk2_ardour/regionview.cc @@ -19,6 +19,7 @@ */ #include <cmath> +#include <cassert> #include <algorithm> #include <gtkmm.h> @@ -32,15 +33,14 @@ #include "streamview.h" #include "regionview.h" -#include "audio_time_axis.h" +#include "route_time_axis.h" #include "simplerect.h" #include "simpleline.h" #include "waveview.h" #include "public_editor.h" #include "region_editor.h" -#include "region_gain_line.h" #include "ghostregion.h" -#include "audio_time_axis.h" +#include "route_time_axis.h" #include "utils.h" #include "rgb_macros.h" #include "gui_thread.h" @@ -55,56 +55,55 @@ using namespace ArdourCanvas; static const int32_t sync_mark_width = 9; -sigc::signal<void,AudioRegionView*> AudioRegionView::AudioRegionViewGoingAway; +sigc::signal<void,RegionView*> RegionView::RegionViewGoingAway; -AudioRegionView::AudioRegionView (ArdourCanvas::Group *parent, AudioTimeAxisView &tv, AudioRegion& r, double spu, - Gdk::Color& basic_color) +RegionView::RegionView (ArdourCanvas::Group* parent, + TimeAxisView& tv, + ARDOUR::Region& r, + double spu, + Gdk::Color& basic_color) : TimeAxisViewItem (r.name(), *parent, tv, spu, basic_color, r.position(), r.length(), - TimeAxisViewItem::Visibility (TimeAxisViewItem::ShowNameText| - TimeAxisViewItem::ShowNameHighlight| - TimeAxisViewItem::ShowFrame)), - region (r) + TimeAxisViewItem::Visibility (TimeAxisViewItem::ShowNameText| + TimeAxisViewItem::ShowNameHighlight| + TimeAxisViewItem::ShowFrame)) + , _region (r) { } -AudioRegionView::AudioRegionView (ArdourCanvas::Group *parent, AudioTimeAxisView &tv, AudioRegion& r, double spu, - Gdk::Color& basic_color, TimeAxisViewItem::Visibility visibility) - : TimeAxisViewItem (r.name(), *parent, tv, spu, basic_color, r.position(), r.length(), visibility), - region (r) +RegionView::RegionView (ArdourCanvas::Group* parent, + TimeAxisView& tv, + ARDOUR::Region& r, + double spu, + Gdk::Color& basic_color, + TimeAxisViewItem::Visibility visibility) + : TimeAxisViewItem (r.name(), *parent, tv, spu, basic_color, r.position(), r.length(), visibility) + , _region (r) { } void -AudioRegionView::init (double amplitude_above_axis, Gdk::Color& basic_color, bool wfw) +RegionView::init (Gdk::Color& basic_color, bool wfw) { - ArdourCanvas::Points shape; - XMLNode *node; + ArdourCanvas::Points shape; + //XMLNode *node; editor = 0; valid = true; in_destructor = false; - _amplitude_above_axis = amplitude_above_axis; - zero_line = 0; - wait_for_waves = wfw; _height = 0; _flags = 0; - if ((node = region.extra_xml ("GUI")) != 0) { + /* + if ((node = _region.extra_xml ("GUI")) != 0) { set_flags (node); } else { - _flags = WaveformVisible; + //_flags = WaveformVisible; store_flags (); - } - - if (trackview.editor.new_regionviews_display_gain()) { - _flags |= EnvelopeVisible; - } + }*/ compute_colors (basic_color); - create_waves (); - name_highlight->set_data ("regionview", this); name_text->set_data ("regionview", this); @@ -122,91 +121,32 @@ AudioRegionView::init (double amplitude_above_axis, Gdk::Color& basic_color, boo sync_mark->property_fill_color_rgba() = fill_color; sync_mark->hide(); - fade_in_shape = new ArdourCanvas::Polygon (*group); - fade_in_shape->property_fill_color_rgba() = fade_color; - fade_in_shape->set_data ("regionview", this); - - fade_out_shape = new ArdourCanvas::Polygon (*group); - fade_out_shape->property_fill_color_rgba() = fade_color; - fade_out_shape->set_data ("regionview", this); - - - { - uint32_t r,g,b,a; - UINT_TO_RGBA(fill_color,&r,&g,&b,&a); - - - fade_in_handle = new ArdourCanvas::SimpleRect (*group); - fade_in_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,0); - fade_in_handle->property_outline_pixels() = 0; - fade_in_handle->property_y1() = 2.0; - fade_in_handle->property_y2() = 7.0; - - fade_in_handle->set_data ("regionview", this); - - fade_out_handle = new ArdourCanvas::SimpleRect (*group); - fade_out_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,0); - fade_out_handle->property_outline_pixels() = 0; - fade_out_handle->property_y1() = 2.0; - fade_out_handle->property_y2() = 7.0; - - fade_out_handle->set_data ("regionview", this); - } - - string foo = region.name(); - foo += ':'; - foo += "gain"; - - gain_line = new AudioRegionGainLine (foo, trackview.session(), *this, *group, region.envelope()); - - if (!(_flags & EnvelopeVisible)) { - gain_line->hide (); - } else { - gain_line->show (); - } - - reset_width_dependent_items ((double) region.length() / samples_per_unit); - - gain_line->reset (); + reset_width_dependent_items ((double) _region.length() / samples_per_unit); set_height (trackview.height); region_muted (); region_sync_changed (); region_resized (BoundsChanged); - set_waveview_data_src(); region_locked (); - envelope_active_changed (); - fade_in_active_changed (); - fade_out_active_changed (); - region.StateChanged.connect (mem_fun(*this, &AudioRegionView::region_changed)); + _region.StateChanged.connect (mem_fun(*this, &RegionView::region_changed)); group->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_region_view_event), group, this)); name_highlight->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_region_view_name_highlight_event), name_highlight, this)); - fade_in_shape->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_in_event), fade_in_shape, this)); - fade_in_handle->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_in_handle_event), fade_in_handle, this)); - fade_out_shape->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_out_event), fade_out_shape, this)); - fade_out_handle->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_out_handle_event), fade_out_handle, this)); set_colors (); - ColorChanged.connect (mem_fun (*this, &AudioRegionView::color_handler)); + ColorChanged.connect (mem_fun (*this, &RegionView::color_handler)); /* XXX sync mark drag? */ } -AudioRegionView::~AudioRegionView () +RegionView::~RegionView () { in_destructor = true; - AudioRegionViewGoingAway (this); /* EMIT_SIGNAL */ - - for (vector<GnomeCanvasWaveViewCache *>::iterator cache = wave_caches.begin(); cache != wave_caches.end() ; ++cache) { - gnome_canvas_waveview_cache_destroy (*cache); - } - - /* all waveviews etc will be destroyed when the group is destroyed */ + RegionViewGoingAway (this); /* EMIT_SIGNAL */ for (vector<GhostRegion*>::iterator g = ghosts.begin(); g != ghosts.end(); ++g) { delete *g; @@ -215,18 +155,14 @@ AudioRegionView::~AudioRegionView () if (editor) { delete editor; } - - if (gain_line) { - delete gain_line; - } } gint -AudioRegionView::_lock_toggle (ArdourCanvas::Item* item, GdkEvent* ev, void* arg) +RegionView::_lock_toggle (ArdourCanvas::Item* item, GdkEvent* ev, void* arg) { switch (ev->type) { case GDK_BUTTON_RELEASE: - static_cast<AudioRegionView*>(arg)->lock_toggle (); + static_cast<RegionView*>(arg)->lock_toggle (); return TRUE; break; default: @@ -236,15 +172,15 @@ AudioRegionView::_lock_toggle (ArdourCanvas::Item* item, GdkEvent* ev, void* arg } void -AudioRegionView::lock_toggle () +RegionView::lock_toggle () { - region.set_locked (!region.locked()); + _region.set_locked (!_region.locked()); } void -AudioRegionView::region_changed (Change what_changed) +RegionView::region_changed (Change what_changed) { - ENSURE_GUI_THREAD (bind (mem_fun(*this, &AudioRegionView::region_changed), what_changed)); + ENSURE_GUI_THREAD (bind (mem_fun(*this, &RegionView::region_changed), what_changed)); if (what_changed & BoundsChanged) { region_resized (what_changed); @@ -268,147 +204,49 @@ AudioRegionView::region_changed (Change what_changed) if (what_changed & Region::LockChanged) { region_locked (); } - if (what_changed & AudioRegion::ScaleAmplitudeChanged) { - region_scale_amplitude_changed (); - } - if (what_changed & AudioRegion::FadeInChanged) { - fade_in_changed (); - } - if (what_changed & AudioRegion::FadeOutChanged) { - fade_out_changed (); - } - if (what_changed & AudioRegion::FadeInActiveChanged) { - fade_in_active_changed (); - } - if (what_changed & AudioRegion::FadeOutActiveChanged) { - fade_out_active_changed (); - } - if (what_changed & AudioRegion::EnvelopeActiveChanged) { - envelope_active_changed (); - } -} - -void -AudioRegionView::fade_in_changed () -{ - reset_fade_in_shape (); -} - -void -AudioRegionView::fade_out_changed () -{ - reset_fade_out_shape (); -} - -void -AudioRegionView::set_fade_in_active (bool yn) -{ - region.set_fade_in_active (yn); -} - -void -AudioRegionView::set_fade_out_active (bool yn) -{ - region.set_fade_out_active (yn); -} - -void -AudioRegionView::fade_in_active_changed () -{ - uint32_t r,g,b,a; - uint32_t col; - UINT_TO_RGBA(fade_color,&r,&g,&b,&a); - - if (region.fade_in_active()) { - col = RGBA_TO_UINT(r,g,b,120); - fade_in_shape->property_fill_color_rgba() = col; - fade_in_shape->property_width_pixels() = 0; - fade_in_shape->property_outline_color_rgba() = RGBA_TO_UINT(r,g,b,0); - } else { - col = RGBA_TO_UINT(r,g,b,0); - fade_in_shape->property_fill_color_rgba() = col; - fade_in_shape->property_width_pixels() = 1; - fade_in_shape->property_outline_color_rgba() = RGBA_TO_UINT(r,g,b,255); - } } void -AudioRegionView::fade_out_active_changed () -{ - uint32_t r,g,b,a; - uint32_t col; - UINT_TO_RGBA(fade_color,&r,&g,&b,&a); - - if (region.fade_out_active()) { - col = RGBA_TO_UINT(r,g,b,120); - fade_out_shape->property_fill_color_rgba() = col; - fade_out_shape->property_width_pixels() = 0; - fade_out_shape->property_outline_color_rgba() = RGBA_TO_UINT(r,g,b,0); - } else { - col = RGBA_TO_UINT(r,g,b,0); - fade_out_shape->property_fill_color_rgba() = col; - fade_out_shape->property_width_pixels() = 1; - fade_out_shape->property_outline_color_rgba() = RGBA_TO_UINT(r,g,b,255); - } -} - - -void -AudioRegionView::region_scale_amplitude_changed () -{ - ENSURE_GUI_THREAD (mem_fun(*this, &AudioRegionView::region_scale_amplitude_changed)); - - for (uint32_t n = 0; n < waves.size(); ++n) { - // force a reload of the cache - waves[n]->property_data_src() = ®ion; - } -} - -void -AudioRegionView::region_locked () +RegionView::region_locked () { /* name will show locked status */ region_renamed (); } void -AudioRegionView::region_resized (Change what_changed) +RegionView::region_resized (Change what_changed) { double unit_length; if (what_changed & ARDOUR::PositionChanged) { - set_position (region.position(), 0); + set_position (_region.position(), 0); } if (what_changed & Change (StartChanged|LengthChanged)) { - set_duration (region.length(), 0); + set_duration (_region.length(), 0); - unit_length = region.length() / samples_per_unit; + unit_length = _region.length() / samples_per_unit; reset_width_dependent_items (unit_length); - for (uint32_t n = 0; n < waves.size(); ++n) { - waves[n]->property_region_start() = region.start(); - } - for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) { (*i)->set_duration (unit_length); - for (vector<WaveView*>::iterator w = (*i)->waves.begin(); w != (*i)->waves.end(); ++w) { - (*w)->property_region_start() = region.start(); - } + /*for (vector<WaveView*>::iterator w = (*i)->waves.begin(); w != (*i)->waves.end(); ++w) { + (*w)->property_region_start() = _region.start(); + }*/ } } } void -AudioRegionView::reset_width_dependent_items (double pixel_width) +RegionView::reset_width_dependent_items (double pixel_width) { TimeAxisViewItem::reset_width_dependent_items (pixel_width); _pixel_width = pixel_width; - +/* if (zero_line) { zero_line->property_x2() = pixel_width - 1.0; } @@ -428,63 +266,64 @@ AudioRegionView::reset_width_dependent_items (double pixel_width) } } - reset_fade_shapes (); + reset_fade_shapes ();*/ } void -AudioRegionView::region_layered () +RegionView::region_layered () { - AudioTimeAxisView *atv = dynamic_cast<AudioTimeAxisView*> (&get_time_axis_view()); - atv->view->region_layered (this); + RouteTimeAxisView *rtv = dynamic_cast<RouteTimeAxisView*>(&get_time_axis_view()); + assert(rtv); + rtv->view()->region_layered (this); } void -AudioRegionView::region_muted () +RegionView::region_muted () { set_frame_color (); region_renamed (); - for (uint32_t n=0; n < waves.size(); ++n) { - if (region.muted()) { + /*for (uint32_t n=0; n < waves.size(); ++n) { + if (_region.muted()) { waves[n]->property_wave_color() = color_map[cMutedWaveForm]; } else { waves[n]->property_wave_color() = color_map[cWaveForm]; } - } + }*/ } void -AudioRegionView::region_opacity () +RegionView::region_opacity () { set_frame_color (); } void -AudioRegionView::raise () +RegionView::raise () { - region.raise (); + _region.raise (); } void -AudioRegionView::raise_to_top () +RegionView::raise_to_top () { - region.raise_to_top (); + _region.raise_to_top (); } void -AudioRegionView::lower () +RegionView::lower () { - region.lower (); + _region.lower (); } void -AudioRegionView::lower_to_bottom () +RegionView::lower_to_bottom () { - region.lower_to_bottom (); + _region.lower_to_bottom (); } bool -AudioRegionView::set_position (jack_nframes_t pos, void* src, double* ignored) +RegionView::set_position (jack_nframes_t pos, void* src, double* ignored) { double delta; bool ret; @@ -507,323 +346,76 @@ AudioRegionView::set_position (jack_nframes_t pos, void* src, double* ignored) } void -AudioRegionView::set_height (gdouble height) -{ - uint32_t wcnt = waves.size(); - - TimeAxisViewItem::set_height (height - 2); - - _height = height; - - for (uint32_t n=0; n < wcnt; ++n) { - gdouble ht; - - if ((height) <= NAME_HIGHLIGHT_THRESH) { - ht = ((height-2*wcnt) / (double) wcnt); - } else { - ht = (((height-2*wcnt) - NAME_HIGHLIGHT_SIZE) / (double) wcnt); - } - - gdouble yoff = n * (ht+1); - - waves[n]->property_height() = ht; - waves[n]->property_y() = yoff + 2; - } - - if (gain_line) { - if ((height/wcnt) < NAME_HIGHLIGHT_SIZE) { - gain_line->hide (); - } else { - if (_flags & EnvelopeVisible) { - gain_line->show (); - } - } - gain_line->set_height ((uint32_t) rint (height - NAME_HIGHLIGHT_SIZE)); - } - - manage_zero_line (); - reset_fade_shapes (); - - if (name_text) { - name_text->raise_to_top(); - } -} - -void -AudioRegionView::manage_zero_line () -{ - if (!zero_line) { - return; - } - - if (_height >= 100) { - gdouble wave_midpoint = (_height - NAME_HIGHLIGHT_SIZE) / 2.0; - zero_line->property_y1() = wave_midpoint; - zero_line->property_y2() = wave_midpoint; - zero_line->show(); - } else { - zero_line->hide(); - } -} - -void -AudioRegionView::reset_fade_shapes () -{ - reset_fade_in_shape (); - reset_fade_out_shape (); -} - -void -AudioRegionView::reset_fade_in_shape () -{ - reset_fade_in_shape_width ((jack_nframes_t) region.fade_in().back()->when); -} - -void -AudioRegionView::reset_fade_in_shape_width (jack_nframes_t width) -{ - if (fade_in_handle == 0) { - return; - } - - /* smallest size for a fade is 64 frames */ - - width = std::max ((jack_nframes_t) 64, width); - - Points* points; - double pwidth = width / samples_per_unit; - uint32_t npoints = std::min (gdk_screen_width(), (int) pwidth); - double h; - - if (_height < 5) { - fade_in_shape->hide(); - fade_in_handle->hide(); - return; - } - - double handle_center; - handle_center = pwidth; - - if (handle_center > 7.0) { - handle_center -= 3.0; - } else { - handle_center = 3.0; - } - - fade_in_handle->property_x1() = handle_center - 3.0; - fade_in_handle->property_x2() = handle_center + 3.0; - - if (pwidth < 5) { - fade_in_shape->hide(); - return; - } - - fade_in_shape->show(); - - float curve[npoints]; - region.fade_in().get_vector (0, region.fade_in().back()->when, curve, npoints); - - points = get_canvas_points ("fade in shape", npoints+3); - - if (_height > NAME_HIGHLIGHT_THRESH) { - h = _height - NAME_HIGHLIGHT_SIZE; - } else { - h = _height; - } - - /* points *MUST* be in anti-clockwise order */ - - uint32_t pi, pc; - double xdelta = pwidth/npoints; - - for (pi = 0, pc = 0; pc < npoints; ++pc) { - (*points)[pi].set_x(1 + (pc * xdelta)); - (*points)[pi++].set_y(2 + (h - (curve[pc] * h))); - } - - /* fold back */ - - (*points)[pi].set_x(pwidth); - (*points)[pi++].set_y(2); - - (*points)[pi].set_x(1); - (*points)[pi++].set_y(2); - - /* connect the dots ... */ - - (*points)[pi] = (*points)[0]; - - fade_in_shape->property_points() = *points; - delete points; -} - -void -AudioRegionView::reset_fade_out_shape () -{ - reset_fade_out_shape_width ((jack_nframes_t) region.fade_out().back()->when); -} - -void -AudioRegionView::reset_fade_out_shape_width (jack_nframes_t width) -{ - if (fade_out_handle == 0) { - return; - } - - /* smallest size for a fade is 64 frames */ - - width = std::max ((jack_nframes_t) 64, width); - - Points* points; - double pwidth = width / samples_per_unit; - uint32_t npoints = std::min (gdk_screen_width(), (int) pwidth); - double h; - - if (_height < 5) { - fade_out_shape->hide(); - fade_out_handle->hide(); - return; - } - - double handle_center; - handle_center = (region.length() - width) / samples_per_unit; - - if (handle_center > 7.0) { - handle_center -= 3.0; - } else { - handle_center = 3.0; - } - - fade_out_handle->property_x1() = handle_center - 3.0; - fade_out_handle->property_x2() = handle_center + 3.0; - - /* don't show shape if its too small */ - - if (pwidth < 5) { - fade_out_shape->hide(); - return; - } - - fade_out_shape->show(); - - float curve[npoints]; - region.fade_out().get_vector (0, region.fade_out().back()->when, curve, npoints); - - if (_height > NAME_HIGHLIGHT_THRESH) { - h = _height - NAME_HIGHLIGHT_SIZE; - } else { - h = _height; - } - - /* points *MUST* be in anti-clockwise order */ - - points = get_canvas_points ("fade out shape", npoints+3); - - uint32_t pi, pc; - double xdelta = pwidth/npoints; - - for (pi = 0, pc = 0; pc < npoints; ++pc) { - (*points)[pi].set_x(_pixel_width - 1 - pwidth + (pc*xdelta)); - (*points)[pi++].set_y(2 + (h - (curve[pc] * h))); - } - - /* fold back */ - - (*points)[pi].set_x(_pixel_width); - (*points)[pi++].set_y(h); - - (*points)[pi].set_x(_pixel_width); - (*points)[pi++].set_y(2); - - /* connect the dots ... */ - - (*points)[pi] = (*points)[0]; - - fade_out_shape->property_points() = *points; - delete points; -} - -void -AudioRegionView::set_samples_per_unit (gdouble spu) +RegionView::set_samples_per_unit (gdouble spu) { TimeAxisViewItem::set_samples_per_unit (spu); - for (uint32_t n=0; n < waves.size(); ++n) { + /*for (uint32_t n=0; n < waves.size(); ++n) { waves[n]->property_samples_per_unit() = spu; - } + }*/ for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) { (*i)->set_samples_per_unit (spu); - (*i)->set_duration (region.length() / samples_per_unit); + (*i)->set_duration (_region.length() / samples_per_unit); } - if (gain_line) { + /*if (gain_line) { gain_line->reset (); - } - reset_fade_shapes (); + }*/ + //reset_fade_shapes (); region_sync_changed (); } bool -AudioRegionView::set_duration (jack_nframes_t frames, void *src) +RegionView::set_duration (jack_nframes_t frames, void *src) { if (!TimeAxisViewItem::set_duration (frames, src)) { return false; } for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) { - (*i)->set_duration (region.length() / samples_per_unit); + (*i)->set_duration (_region.length() / samples_per_unit); } return true; } void -AudioRegionView::set_amplitude_above_axis (gdouble spp) -{ - for (uint32_t n=0; n < waves.size(); ++n) { - waves[n]->property_amplitude_above_axis() = spp; - } -} - -void -AudioRegionView::compute_colors (Gdk::Color& basic_color) +RegionView::compute_colors (Gdk::Color& basic_color) { TimeAxisViewItem::compute_colors (basic_color); uint32_t r, g, b, a; - /* gain color computed in envelope_active_changed() */ - UINT_TO_RGBA (fill_color, &r, &g, &b, &a); fade_color = RGBA_TO_UINT(r,g,b,120); } void -AudioRegionView::set_colors () +RegionView::set_colors () { TimeAxisViewItem::set_colors (); - if (gain_line) { - gain_line->set_line_color (region.envelope_active() ? color_map[cGainLine] : color_map[cGainLineInactive]); - } + /*if (gain_line) { + gain_line->set_line_color (_region.envelope_active() ? color_map[cGainLine] : color_map[cGainLineInactive]); + }*/ if (sync_mark) { sync_mark->property_fill_color_rgba() = fill_color; } - for (uint32_t n=0; n < waves.size(); ++n) { - if (region.muted()) { + /*for (uint32_t n=0; n < waves.size(); ++n) { + if (_region.muted()) { waves[n]->property_wave_color() = color_map[cMutedWaveForm]; } else { waves[n]->property_wave_color() = color_map[cWaveForm]; } - } + }*/ } void -AudioRegionView::set_frame_color () +RegionView::set_frame_color () { - if (region.opaque()) { + if (_region.opaque()) { fill_opacity = 180; } else { fill_opacity = 100; @@ -833,21 +425,7 @@ AudioRegionView::set_frame_color () } void -AudioRegionView::show_region_editor () -{ - if (editor == 0) { - editor = new AudioRegionEditor (trackview.session(), region, *this); - // GTK2FIX : how to ensure float without realizing - // editor->realize (); - // trackview.editor.ensure_float (*editor); - } - - editor->show_all (); - editor->get_window()->raise(); -} - -void -AudioRegionView::hide_region_editor() +RegionView::hide_region_editor() { if (editor) { editor->hide_all (); @@ -855,23 +433,24 @@ AudioRegionView::hide_region_editor() } void -AudioRegionView::region_renamed () +RegionView::region_renamed () { string str; - if (region.locked()) { + if (_region.locked()) { str += '>'; - str += region.name(); + str += _region.name(); str += '<'; } else { - str = region.name(); + str = _region.name(); } - if (region.speed_mismatch (trackview.session().frame_rate())) { + /* FIXME + if (_region.speed_mismatch (trackview.session().frame_rate())) { str = string ("*") + str; - } + }*/ - if (region.muted()) { + if (_region.muted()) { str = string ("!") + str; } @@ -880,7 +459,7 @@ AudioRegionView::region_renamed () } void -AudioRegionView::region_sync_changed () +RegionView::region_sync_changed () { if (sync_mark == 0) { return; @@ -889,10 +468,10 @@ AudioRegionView::region_sync_changed () int sync_dir; jack_nframes_t sync_offset; - sync_offset = region.sync_offset (sync_dir); + sync_offset = _region.sync_offset (sync_dir); /* this has to handle both a genuine change of position, a change of samples_per_unit, - and a change in the bounds of the region. + and a change in the bounds of the _region. */ if (sync_offset == 0) { @@ -903,7 +482,7 @@ AudioRegionView::region_sync_changed () } else { - if ((sync_dir < 0) || ((sync_dir > 0) && (sync_offset > region.length()))) { + if ((sync_dir < 0) || ((sync_dir > 0) && (sync_offset > _region.length()))) { /* no sync mark - its out of the bounds of the region */ @@ -930,315 +509,9 @@ AudioRegionView::region_sync_changed () } void -AudioRegionView::set_waveform_visible (bool yn) +RegionView::move (double x_delta, double y_delta) { - if (((_flags & WaveformVisible) != yn)) { - if (yn) { - for (uint32_t n=0; n < waves.size(); ++n) { - waves[n]->show(); - } - _flags |= WaveformVisible; - } else { - for (uint32_t n=0; n < waves.size(); ++n) { - waves[n]->hide(); - } - _flags &= ~WaveformVisible; - } - store_flags (); - } -} - -void -AudioRegionView::temporarily_hide_envelope () -{ - if (gain_line) { - gain_line->hide (); - } -} - -void -AudioRegionView::unhide_envelope () -{ - if (gain_line && (_flags & EnvelopeVisible)) { - gain_line->show (); - } -} - -void -AudioRegionView::set_envelope_visible (bool yn) -{ - if (gain_line && ((_flags & EnvelopeVisible) != yn)) { - if (yn) { - gain_line->show (); - _flags |= EnvelopeVisible; - } else { - gain_line->hide (); - _flags &= ~EnvelopeVisible; - } - store_flags (); - } -} - -void -AudioRegionView::create_waves () -{ - bool create_zero_line = true; - - AudioTimeAxisView& atv (*(dynamic_cast<AudioTimeAxisView*>(&trackview))); // ick - - if (!atv.get_diskstream()) { - return; - } - - uint32_t nchans = atv.get_diskstream()->n_channels(); - - /* in tmp_waves, set up null pointers for each channel so the vector is allocated */ - for (uint32_t n = 0; n < nchans; ++n) { - tmp_waves.push_back (0); - } - - for (uint32_t n = 0; n < nchans; ++n) { - - if (n >= region.n_channels()) { - break; - } - - wave_caches.push_back (WaveView::create_cache ()); - - if (wait_for_waves) { - if (region.source(n).peaks_ready (bind (mem_fun(*this, &AudioRegionView::peaks_ready_handler), n), peaks_ready_connection)) { - create_one_wave (n, true); - } else { - create_zero_line = false; - } - } else { - create_one_wave (n, true); - } - } - - if (create_zero_line) { - zero_line = new ArdourCanvas::SimpleLine (*group); - zero_line->property_x1() = (gdouble) 1.0; - zero_line->property_x2() = (gdouble) (region.length() / samples_per_unit) - 1.0; - zero_line->property_color_rgba() = (guint) color_map[cZeroLine]; - manage_zero_line (); - } -} - -void -AudioRegionView::create_one_wave (uint32_t which, bool direct) -{ - AudioTimeAxisView& atv (*(dynamic_cast<AudioTimeAxisView*>(&trackview))); // ick - uint32_t nchans = atv.get_diskstream()->n_channels(); - uint32_t n; - uint32_t nwaves = std::min (nchans, region.n_channels()); - gdouble ht; - - if (trackview.height < NAME_HIGHLIGHT_SIZE) { - ht = ((trackview.height) / (double) nchans); - } else { - ht = ((trackview.height - NAME_HIGHLIGHT_SIZE) / (double) nchans); - } - - gdouble yoff = which * ht; - - WaveView *wave = new WaveView(*group); - - wave->property_data_src() = (gpointer) ®ion; - wave->property_cache() = wave_caches[which]; - wave->property_cache_updater() = true; - wave->property_channel() = which; - wave->property_length_function() = (gpointer) region_length_from_c; - wave->property_sourcefile_length_function() = (gpointer) sourcefile_length_from_c; - wave->property_peak_function() = (gpointer) region_read_peaks_from_c; - wave->property_x() = 0.0; - wave->property_y() = yoff; - wave->property_height() = (double) ht; - wave->property_samples_per_unit() = samples_per_unit; - wave->property_amplitude_above_axis() = _amplitude_above_axis; - wave->property_wave_color() = region.muted() ? color_map[cMutedWaveForm] : color_map[cWaveForm]; - wave->property_region_start() = region.start(); - - if (!(_flags & WaveformVisible)) { - wave->hide(); - } - - /* note: calling this function is serialized by the lock - held in the peak building thread that signals that - peaks are ready for use *or* by the fact that it is - called one by one from the GUI thread. - */ - - if (which < nchans) { - tmp_waves[which] = wave; - } else { - /* n-channel track, >n-channel source */ - } - - /* see if we're all ready */ - - for (n = 0; n < nchans; ++n) { - if (tmp_waves[n] == 0) { - break; - } - } - - if (n == nwaves && waves.empty()) { - /* all waves are ready */ - tmp_waves.resize(nwaves); - - waves = tmp_waves; - tmp_waves.clear (); - - if (!zero_line) { - zero_line = new ArdourCanvas::SimpleLine (*group); - zero_line->property_x1() = (gdouble) 1.0; - zero_line->property_x2() = (gdouble) (region.length() / samples_per_unit) - 1.0; - zero_line->property_color_rgba() = (guint) color_map[cZeroLine]; - manage_zero_line (); - } - } -} - -void -AudioRegionView::peaks_ready_handler (uint32_t which) -{ - Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &AudioRegionView::create_one_wave), which, false)); - - if (!waves.empty()) { - /* all waves created, don't hook into peaks ready anymore */ - peaks_ready_connection.disconnect (); - } -} - -void -AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev) -{ - if (gain_line == 0) { - return; - } - - double x, y; - - /* don't create points that can't be seen */ - - set_envelope_visible (true); - - x = ev->button.x; - y = ev->button.y; - - item->w2i (x, y); - - jack_nframes_t fx = trackview.editor.pixel_to_frame (x); - - if (fx > region.length()) { - return; - } - - /* compute vertical fractional position */ - - y = 1.0 - (y / (trackview.height - NAME_HIGHLIGHT_SIZE)); - - /* map using gain line */ - - gain_line->view_to_model_y (y); - - trackview.session().begin_reversible_command (_("add gain control point")); - trackview.session().add_undo (region.envelope().get_memento()); - - - if (!region.envelope_active()) { - trackview.session().add_undo( bind( mem_fun(region, &AudioRegion::set_envelope_active), false) ); - region.set_envelope_active(true); - trackview.session().add_redo( bind( mem_fun(region, &AudioRegion::set_envelope_active), true) ); - } - - region.envelope().add (fx, y); - - trackview.session().add_redo_no_execute (region.envelope().get_memento()); - trackview.session().commit_reversible_command (); -} - -void -AudioRegionView::remove_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev) -{ - ControlPoint *cp = reinterpret_cast<ControlPoint *> (item->get_data ("control_point")); - region.envelope().erase (cp->model); -} - -void -AudioRegionView::store_flags() -{ - XMLNode *node = new XMLNode ("GUI"); - - node->add_property ("waveform-visible", (_flags & WaveformVisible) ? "yes" : "no"); - node->add_property ("envelope-visible", (_flags & EnvelopeVisible) ? "yes" : "no"); - - region.add_extra_xml (*node); -} - -void -AudioRegionView::set_flags (XMLNode* node) -{ - XMLProperty *prop; - - if ((prop = node->property ("waveform-visible")) != 0) { - if (prop->value() == "yes") { - _flags |= WaveformVisible; - } - } - - if ((prop = node->property ("envelope-visible")) != 0) { - if (prop->value() == "yes") { - _flags |= EnvelopeVisible; - } - } -} - -void -AudioRegionView::set_waveform_shape (WaveformShape shape) -{ - bool yn; - - /* this slightly odd approach is to leave the door open to - other "shapes" such as spectral displays, etc. - */ - - switch (shape) { - case Rectified: - yn = true; - break; - - default: - yn = false; - break; - } - - if (yn != (bool) (_flags & WaveformRectified)) { - for (vector<WaveView *>::iterator wave = waves.begin(); wave != waves.end() ; ++wave) { - (*wave)->property_rectified() = yn; - } - - if (zero_line) { - if (yn) { - zero_line->hide(); - } else { - zero_line->show(); - } - } - - if (yn) { - _flags |= WaveformRectified; - } else { - _flags &= ~WaveformRectified; - } - } -} - -void -AudioRegionView::move (double x_delta, double y_delta) -{ - if (region.locked() || (x_delta == 0 && y_delta == 0)) { + if (_region.locked() || (x_delta == 0 && y_delta == 0)) { return; } @@ -1251,51 +524,8 @@ AudioRegionView::move (double x_delta, double y_delta) } } -GhostRegion* -AudioRegionView::add_ghost (AutomationTimeAxisView& atv) -{ - AudioTimeAxisView& myatv (*(dynamic_cast<AudioTimeAxisView*>(&trackview))); // ick - double unit_position = region.position () / samples_per_unit; - GhostRegion* ghost = new GhostRegion (atv, unit_position); - uint32_t nchans; - - nchans = myatv.get_diskstream()->n_channels(); - - for (uint32_t n = 0; n < nchans; ++n) { - - if (n >= region.n_channels()) { - break; - } - - WaveView *wave = new WaveView(*ghost->group); - - wave->property_data_src() = ®ion; - wave->property_cache() = wave_caches[n]; - wave->property_cache_updater() = false; - wave->property_channel() = n; - wave->property_length_function() = (gpointer)region_length_from_c; - wave->property_sourcefile_length_function() = (gpointer) sourcefile_length_from_c; - wave->property_peak_function() = (gpointer) region_read_peaks_from_c; - wave->property_x() = 0.0; - wave->property_samples_per_unit() = samples_per_unit; - wave->property_amplitude_above_axis() = _amplitude_above_axis; - wave->property_wave_color() = color_map[cGhostTrackWave]; - wave->property_region_start() = region.start(); - - ghost->waves.push_back(wave); - } - - ghost->set_height (); - ghost->set_duration (region.length() / samples_per_unit); - ghosts.push_back (ghost); - - ghost->GoingAway.connect (mem_fun(*this, &AudioRegionView::remove_ghost)); - - return ghost; -} - void -AudioRegionView::remove_ghost (GhostRegion* ghost) +RegionView::remove_ghost (GhostRegion* ghost) { if (in_destructor) { return; @@ -1310,99 +540,8 @@ AudioRegionView::remove_ghost (GhostRegion* ghost) } uint32_t -AudioRegionView::get_fill_color () +RegionView::get_fill_color () { return fill_color; } -void -AudioRegionView::entered () -{ - if (gain_line && _flags & EnvelopeVisible) { - gain_line->show_all_control_points (); - } - - uint32_t r,g,b,a; - UINT_TO_RGBA(fade_color,&r,&g,&b,&a); - a=255; - - if (fade_in_handle) { - fade_in_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,a); - fade_out_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,a); - } -} - -void -AudioRegionView::exited () -{ - if (gain_line) { - gain_line->hide_all_but_selected_control_points (); - } - - uint32_t r,g,b,a; - UINT_TO_RGBA(fade_color,&r,&g,&b,&a); - a=0; - - if (fade_in_handle) { - fade_in_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,a); - fade_out_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,a); - } -} - -void -AudioRegionView::envelope_active_changed () -{ - if (gain_line) { - gain_line->set_line_color (region.envelope_active() ? color_map[cGainLine] : color_map[cGainLineInactive]); - } -} - -void -AudioRegionView::set_waveview_data_src() -{ - - double unit_length= region.length() / samples_per_unit; - - for (uint32_t n = 0; n < waves.size(); ++n) { - // TODO: something else to let it know the channel - waves[n]->property_data_src() = ®ion; - } - - for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) { - - (*i)->set_duration (unit_length); - - for (vector<WaveView*>::iterator w = (*i)->waves.begin(); w != (*i)->waves.end(); ++w) { - (*w)->property_data_src() = ®ion; - } - } - -} - -void -AudioRegionView::color_handler (ColorID id, uint32_t val) -{ - switch (id) { - case cMutedWaveForm: - case cWaveForm: - set_colors (); - break; - - case cGainLineInactive: - case cGainLine: - envelope_active_changed(); - break; - - case cZeroLine: - if (zero_line) { - zero_line->property_color_rgba() = (guint) color_map[cZeroLine]; - } - break; - - case cGhostTrackWave: - break; - - default: - break; - } -} diff --git a/gtk2_ardour/regionview.h b/gtk2_ardour/regionview.h index f49b46aea4..29c5817a25 100644 --- a/gtk2_ardour/regionview.h +++ b/gtk2_ardour/regionview.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2001-2004 Paul Davis + Copyright (C) 2001-2006 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -14,8 +14,6 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id$ */ #ifndef __gtk_ardour_region_view_h__ @@ -35,40 +33,33 @@ #include "canvas.h" #include "color.h" -namespace ARDOUR { - class AudioRegion; - class PeakData; -}; - -class AudioTimeAxisView; -class AudioRegionGainLine; -class AudioRegionEditor; +class TimeAxisView; +class RegionEditor; class GhostRegion; class AutomationTimeAxisView; -class AudioRegionView : public TimeAxisViewItem +class RegionView : public TimeAxisViewItem { public: - AudioRegionView (ArdourCanvas::Group *, - AudioTimeAxisView&, - ARDOUR::AudioRegion&, - double initial_samples_per_unit, - Gdk::Color& basic_color); + RegionView (ArdourCanvas::Group* parent, + TimeAxisView& time_view, + ARDOUR::Region& region, + double samples_per_unit, + Gdk::Color& basic_color); - ~AudioRegionView (); + ~RegionView (); - virtual void init (double amplitude_above_axis, Gdk::Color& base_color, bool wait_for_waves); + virtual void init (Gdk::Color& base_color, bool wait_for_waves); - ARDOUR::AudioRegion& region; // ok, let 'em have it - bool is_valid() const { return valid; } + ARDOUR::Region& region() const { return _region; } + + bool is_valid() const { return valid; } void set_valid (bool yn) { valid = yn; } - void set_height (double); + virtual void set_height (double) = 0; void set_samples_per_unit (double); bool set_duration (jack_nframes_t, void*); - void set_amplitude_above_axis (gdouble spp); - void move (double xdelta, double ydelta); void raise (); @@ -77,58 +68,36 @@ class AudioRegionView : public TimeAxisViewItem void lower_to_bottom (); bool set_position(jack_nframes_t pos, void* src, double* delta = 0); - - void temporarily_hide_envelope (); // dangerous - void unhide_envelope (); // dangerous - void set_envelope_visible (bool); - void set_waveform_visible (bool yn); - void set_waveform_shape (WaveformShape); - - bool waveform_rectified() const { return _flags & WaveformRectified; } - bool waveform_visible() const { return _flags & WaveformVisible; } - bool envelope_visible() const { return _flags & EnvelopeVisible; } - - void show_region_editor (); + virtual void show_region_editor () = 0; void hide_region_editor(); - void add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *event); - void remove_gain_point_event (ArdourCanvas::Item *item, GdkEvent *event); - - AudioRegionGainLine* get_gain_line() const { return gain_line; } - void region_changed (ARDOUR::Change); - void envelope_active_changed (); - - static sigc::signal<void,AudioRegionView*> AudioRegionViewGoingAway; - sigc::signal<void> GoingAway; - - GhostRegion* add_ghost (AutomationTimeAxisView&); - void remove_ghost (GhostRegion*); - void reset_fade_in_shape_width (jack_nframes_t); - void reset_fade_out_shape_width (jack_nframes_t); - void set_fade_in_active (bool); - void set_fade_out_active (bool); + virtual GhostRegion* add_ghost (AutomationTimeAxisView&) = 0; + void remove_ghost (GhostRegion*); uint32_t get_fill_color (); - virtual void entered (); - virtual void exited (); + virtual void entered () {} + virtual void exited () {} + + static sigc::signal<void,RegionView*> RegionViewGoingAway; + sigc::signal<void> GoingAway; protected: - /* this constructor allows derived types - to specify their visibility requirements - to the TimeAxisViewItem parent class - */ + /** Allows derived types to specify their visibility requirements + * to the TimeAxisViewItem parent class + */ + RegionView (ArdourCanvas::Group *, + TimeAxisView&, + ARDOUR::Region&, + double initial_samples_per_unit, + Gdk::Color& basic_color, + TimeAxisViewItem::Visibility); - AudioRegionView (ArdourCanvas::Group *, - AudioTimeAxisView&, - ARDOUR::AudioRegion&, - double initial_samples_per_unit, - Gdk::Color& basic_color, - TimeAxisViewItem::Visibility); + ARDOUR::Region& _region; enum Flags { EnvelopeVisible = 0x1, @@ -136,39 +105,23 @@ class AudioRegionView : public TimeAxisViewItem WaveformRectified = 0x8 }; - vector<ArdourCanvas::WaveView *> waves; /* waveviews */ - vector<ArdourCanvas::WaveView *> tmp_waves; /* see ::create_waves()*/ - ArdourCanvas::Polygon* sync_mark; /* polgyon for sync position */ - ArdourCanvas::Text* no_wave_msg; /* text */ - ArdourCanvas::SimpleLine* zero_line; /* simpleline */ - ArdourCanvas::Polygon* fade_in_shape; /* polygon */ - ArdourCanvas::Polygon* fade_out_shape; /* polygon */ - ArdourCanvas::SimpleRect* fade_in_handle; /* simplerect */ - ArdourCanvas::SimpleRect* fade_out_handle; /* simplerect */ + ArdourCanvas::Polygon* sync_mark; ///< polgyon for sync position + ArdourCanvas::Text* no_wave_msg; ///< text - AudioRegionGainLine* gain_line; - AudioRegionEditor *editor; + RegionEditor *editor; vector<ControlPoint *> control_points; - double _amplitude_above_axis; double current_visible_sync_position; uint32_t _flags; uint32_t fade_color; - bool valid; /* see StreamView::redisplay_diskstream() */ - double _pixel_width; - double _height; + bool valid; ///< see StreamView::redisplay_diskstream() + double _pixel_width; + double _height; bool in_destructor; bool wait_for_waves; - sigc::connection peaks_ready_connection; - - void reset_fade_shapes (); - void reset_fade_in_shape (); - void reset_fade_out_shape (); - void fade_in_changed (); - void fade_out_changed (); - void fade_in_active_changed (); - void fade_out_active_changed (); + + sigc::connection peaks_ready_connection; void region_resized (ARDOUR::Change); void region_moved (void *); @@ -181,26 +134,19 @@ class AudioRegionView : public TimeAxisViewItem void region_scale_amplitude_changed (); static gint _lock_toggle (ArdourCanvas::Item*, GdkEvent*, void*); - void lock_toggle (); + void lock_toggle (); - void create_waves (); - void create_one_wave (uint32_t, bool); - void manage_zero_line (); void peaks_ready_handler (uint32_t); void reset_name (gdouble width); - void set_flags (XMLNode *); - void store_flags (); void set_colors (); void compute_colors (Gdk::Color&); virtual void set_frame_color (); void reset_width_dependent_items (double pixel_width); - void set_waveview_data_src(); - vector<GnomeCanvasWaveViewCache*> wave_caches; vector<GhostRegion*> ghosts; - void color_handler (ColorID, uint32_t); + virtual void color_handler (ColorID, uint32_t) {} }; #endif /* __gtk_ardour_region_view_h__ */ diff --git a/gtk2_ardour/route_time_axis.cc b/gtk2_ardour/route_time_axis.cc new file mode 100644 index 0000000000..f6a533d965 --- /dev/null +++ b/gtk2_ardour/route_time_axis.cc @@ -0,0 +1,1057 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <cstdlib> +#include <cmath> +#include <cassert> + +#include <algorithm> +#include <string> +#include <vector> + +#include <sigc++/bind.h> + +#include <pbd/error.h> +#include <pbd/stl_delete.h> +#include <pbd/whitespace.h> + +#include <gtkmm2ext/gtk_ui.h> +#include <gtkmm2ext/selector.h> +#include <gtkmm2ext/stop_signal.h> +#include <gtkmm2ext/bindable_button.h> +#include <gtkmm2ext/utils.h> + +#include <ardour/playlist.h> +#include <ardour/diskstream.h> +#include <ardour/insert.h> +#include <ardour/ladspa_plugin.h> +#include <ardour/location.h> +#include <ardour/panner.h> +#include <ardour/playlist.h> +#include <ardour/session.h> +#include <ardour/session_playlist.h> +#include <ardour/utils.h> + +#include "ardour_ui.h" +#include "route_time_axis.h" +#include "canvas_impl.h" +#include "crossfade_view.h" +#include "enums.h" +#include "gui_thread.h" +#include "keyboard.h" +#include "playlist_selector.h" +#include "plugin_selector.h" +#include "plugin_ui.h" +#include "point_selection.h" +#include "prompter.h" +#include "public_editor.h" +#include "regionview.h" +#include "rgb_macros.h" +#include "selection.h" +#include "simplerect.h" +#include "streamview.h" +#include "utils.h" + +#include <ardour/track.h> + +#include "i18n.h" + +using namespace ARDOUR; +using namespace PBD; +using namespace Gtk; +using namespace Editing; + + +RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, Route& rt, Canvas& canvas) + : AxisView(sess), + RouteUI(rt, sess, _("m"), _("s"), _("r")), // mute, solo, and record + TimeAxisView(sess,ed,(TimeAxisView*) 0, canvas), + parent_canvas (canvas), + button_table (3, 3), + edit_group_button (_("g")), // group + playlist_button (_("p")), + size_button (_("h")), // height + automation_button (_("a")), + visual_button (_("v")) + +{ + _has_state = true; + playlist_menu = 0; + playlist_action_menu = 0; + automation_action_menu = 0; + _view = 0; + timestretch_rect = 0; + no_redraw = false; + + //view = new AudioStreamView (*this); + + ignore_toggle = false; + + mute_button->set_active (false); + solo_button->set_active (false); + + mute_button->set_name ("TrackMuteButton"); + solo_button->set_name ("SoloButton"); + edit_group_button.set_name ("TrackGroupButton"); + playlist_button.set_name ("TrackPlaylistButton"); + automation_button.set_name ("TrackAutomationButton"); + size_button.set_name ("TrackSizeButton"); + visual_button.set_name ("TrackVisualButton"); + hide_button.set_name ("TrackRemoveButton"); + + hide_button.add (*(manage (new Image (get_xpm("small_x.xpm"))))); + + solo_button->signal_button_press_event().connect (mem_fun (*this, &RouteTimeAxisView::select_me), false); + mute_button->signal_button_press_event().connect (mem_fun (*this, &RouteTimeAxisView::select_me), false); + playlist_button.signal_button_press_event().connect (mem_fun (*this, &RouteTimeAxisView::select_me), false); + automation_button.signal_button_press_event().connect (mem_fun (*this, &RouteTimeAxisView::select_me), false); + size_button.signal_button_press_event().connect (mem_fun (*this, &RouteTimeAxisView::select_me), false); + visual_button.signal_button_press_event().connect (mem_fun (*this, &RouteTimeAxisView::select_me), false); + hide_button.signal_button_press_event().connect (mem_fun (*this, &RouteTimeAxisView::select_me), false); + + solo_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::solo_press), false); + solo_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::solo_release), false); + mute_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::mute_press), false); + mute_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::mute_release), false); + edit_group_button.signal_button_release_event().connect (mem_fun(*this, &RouteTimeAxisView::edit_click), false); + playlist_button.signal_clicked().connect (mem_fun(*this, &RouteTimeAxisView::playlist_click)); + automation_button.signal_clicked().connect (mem_fun(*this, &RouteTimeAxisView::automation_click)); + size_button.signal_button_release_event().connect (mem_fun(*this, &RouteTimeAxisView::size_click), false); + visual_button.signal_clicked().connect (mem_fun(*this, &RouteTimeAxisView::visual_click)); + hide_button.signal_clicked().connect (mem_fun(*this, &RouteTimeAxisView::hide_click)); + + if (is_track()) { + rec_enable_button->set_active (false); + rec_enable_button->set_name ("TrackRecordEnableButton"); + rec_enable_button->signal_button_press_event().connect (mem_fun (*this, &RouteTimeAxisView::select_me), false); + rec_enable_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::rec_enable_press)); + controls_table.attach (*rec_enable_button, 5, 6, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0); + ARDOUR_UI::instance()->tooltips().set_tip(*rec_enable_button, _("Record")); + } + + controls_table.attach (*mute_button, 6, 7, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0); + controls_table.attach (*solo_button, 7, 8, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::FILL|Gtk::EXPAND, 0, 0); + + controls_table.attach (edit_group_button, 6, 7, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0); + + ARDOUR_UI::instance()->tooltips().set_tip(*solo_button,_("Solo")); + ARDOUR_UI::instance()->tooltips().set_tip(*mute_button,_("Mute")); + ARDOUR_UI::instance()->tooltips().set_tip(edit_group_button,_("Edit Group")); + ARDOUR_UI::instance()->tooltips().set_tip(size_button,_("Display Height")); + ARDOUR_UI::instance()->tooltips().set_tip(playlist_button,_("Playlist")); + ARDOUR_UI::instance()->tooltips().set_tip(automation_button, _("Automation")); + ARDOUR_UI::instance()->tooltips().set_tip(visual_button, _("Visual options")); + ARDOUR_UI::instance()->tooltips().set_tip(hide_button, _("Hide this track")); + + label_view (); + + controls_table.attach (hide_button, 0, 1, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND); + controls_table.attach (visual_button, 1, 2, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND); + controls_table.attach (size_button, 2, 3, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND); + controls_table.attach (automation_button, 3, 4, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND); + + if (is_track() && track()->mode() == ARDOUR::Normal) { + controls_table.attach (playlist_button, 5, 6, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND); + } + + /* remove focus from the buttons */ + + automation_button.unset_flags (Gtk::CAN_FOCUS); + solo_button->unset_flags (Gtk::CAN_FOCUS); + mute_button->unset_flags (Gtk::CAN_FOCUS); + edit_group_button.unset_flags (Gtk::CAN_FOCUS); + size_button.unset_flags (Gtk::CAN_FOCUS); + playlist_button.unset_flags (Gtk::CAN_FOCUS); + hide_button.unset_flags (Gtk::CAN_FOCUS); + visual_button.unset_flags (Gtk::CAN_FOCUS); + + /* map current state of the route */ + + update_diskstream_display (); + solo_changed(0); + mute_changed(0); + //redirects_changed (0); + //reset_redirect_automation_curves (); + y_position = -1; + + _route.mute_changed.connect (mem_fun(*this, &RouteUI::mute_changed)); + _route.solo_changed.connect (mem_fun(*this, &RouteUI::solo_changed)); + //_route.redirects_changed.connect (mem_fun(*this, &RouteTimeAxisView::redirects_changed)); + _route.name_changed.connect (mem_fun(*this, &RouteTimeAxisView::route_name_changed)); + _route.solo_safe_changed.connect (mem_fun(*this, &RouteUI::solo_changed)); + + if (is_track()) { + + track()->FreezeChange.connect (mem_fun(*this, &RouteTimeAxisView::map_frozen)); + track()->DiskstreamChanged.connect (mem_fun(*this, &RouteTimeAxisView::diskstream_changed)); + get_diskstream()->SpeedChanged.connect (mem_fun(*this, &RouteTimeAxisView::speed_changed)); + + /* ask for notifications of any new RegionViews */ + // FIXME: _view is NULL, but it would be nice to attach this here :/ + //_view->RegionViewAdded.connect (mem_fun(*this, &RouteTimeAxisView::region_view_added)); + //_view->attach (); + + /* pick up the correct freeze state */ + map_frozen (); + + } + + editor.ZoomChanged.connect (mem_fun(*this, &RouteTimeAxisView::reset_samples_per_unit)); + ColorChanged.connect (mem_fun (*this, &RouteTimeAxisView::color_handler)); +} + +RouteTimeAxisView::~RouteTimeAxisView () +{ + GoingAway (); /* EMIT_SIGNAL */ + + if (playlist_menu) { + delete playlist_menu; + playlist_menu = 0; + } + + if (playlist_action_menu) { + delete playlist_action_menu; + playlist_action_menu = 0; + } + + if (_view) { + delete _view; + _view = 0; + } +} + +void +RouteTimeAxisView::set_playlist (Playlist *newplaylist) +{ + Playlist *pl = playlist(); + assert(pl); + + modified_connection.disconnect (); + state_changed_connection.disconnect (); + + state_changed_connection = pl->StateChanged.connect (mem_fun(*this, &RouteTimeAxisView::playlist_state_changed)); + modified_connection = pl->Modified.connect (mem_fun(*this, &RouteTimeAxisView::playlist_modified)); +} + +void +RouteTimeAxisView::playlist_modified () +{ +} + +gint +RouteTimeAxisView::edit_click (GdkEventButton *ev) +{ + if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) { + _route.set_edit_group (0, this); + return FALSE; + } + + using namespace Menu_Helpers; + + MenuList& items = edit_group_menu.items (); + RadioMenuItem::Group group; + + items.clear (); + items.push_back (RadioMenuElem (group, _("No group"), + bind (mem_fun(*this, &RouteTimeAxisView::set_edit_group_from_menu), (RouteGroup *) 0))); + + if (_route.edit_group() == 0) { + static_cast<RadioMenuItem*>(&items.back())->set_active (); + } + + _session.foreach_edit_group (bind (mem_fun (*this, &RouteTimeAxisView::add_edit_group_menu_item), &group)); + edit_group_menu.popup (ev->button, ev->time); + + return FALSE; +} + +void +RouteTimeAxisView::add_edit_group_menu_item (RouteGroup *eg, RadioMenuItem::Group* group) +{ + using namespace Menu_Helpers; + + MenuList &items = edit_group_menu.items(); + + cerr << "adding edit group " << eg->name() << endl; + + items.push_back (RadioMenuElem (*group, eg->name(), bind (mem_fun(*this, &RouteTimeAxisView::set_edit_group_from_menu), eg))); + if (_route.edit_group() == eg) { + static_cast<RadioMenuItem*>(&items.back())->set_active (); + } +} + +void +RouteTimeAxisView::set_edit_group_from_menu (RouteGroup *eg) + +{ + _route.set_edit_group (eg, this); +} + +void +RouteTimeAxisView::playlist_state_changed (Change ignored) +{ + // ENSURE_GUI_THREAD (bind (mem_fun(*this, &RouteTimeAxisView::playlist_state_changed), ignored)); + // why are we here ? +} + +void +RouteTimeAxisView::playlist_changed () + +{ + label_view (); + + if (is_track()) { + set_playlist (dynamic_cast<Playlist*>(get_diskstream()->playlist())); + } +} + +void +RouteTimeAxisView::label_view () +{ + string x = _route.name(); + + if (x != name_entry.get_text()) { + name_entry.set_text (x); + } + + ARDOUR_UI::instance()->tooltips().set_tip (name_entry, x); +} + +void +RouteTimeAxisView::route_name_changed (void *src) +{ + editor.route_name_changed (this); + label_view (); +} + +void +RouteTimeAxisView::take_name_changed (void *src) + +{ + if (src != this) { + label_view (); + } +} + +void +RouteTimeAxisView::playlist_click () +{ + // always build a new action menu + + if (playlist_action_menu == 0) { + playlist_action_menu = new Menu; + playlist_action_menu->set_name ("ArdourContextMenu"); + } + + build_playlist_menu(playlist_action_menu); + + playlist_action_menu->popup (1, 0); +} + +void +RouteTimeAxisView::automation_click () +{ + if (automation_action_menu == 0) { + /* this seems odd, but the automation action + menu is built as part of the display menu. + */ + build_display_menu (); + } + automation_action_menu->popup (1, 0); +} + +void +RouteTimeAxisView::show_timestretch (jack_nframes_t start, jack_nframes_t end) +{ + double x1; + double x2; + double y2; + + TimeAxisView::show_timestretch (start, end); + + hide_timestretch (); + +#if 0 + if (ts.empty()) { + return; + } + + + /* check that the time selection was made in our route, or our edit group. + remember that edit_group() == 0 implies the route is *not* in a edit group. + */ + + if (!(ts.track == this || (ts.group != 0 && ts.group == _route.edit_group()))) { + /* this doesn't apply to us */ + return; + } + + /* ignore it if our edit group is not active */ + + if ((ts.track != this) && _route.edit_group() && !_route.edit_group()->is_active()) { + return; + } +#endif + + if (timestretch_rect == 0) { + timestretch_rect = new SimpleRect (*canvas_display); + timestretch_rect->property_x1() = 0.0; + timestretch_rect->property_y1() = 0.0; + timestretch_rect->property_x2() = 0.0; + timestretch_rect->property_y2() = 0.0; + timestretch_rect->property_fill_color_rgba() = color_map[cTimeStretchFill]; + timestretch_rect->property_outline_color_rgba() = color_map[cTimeStretchOutline]; + } + + timestretch_rect->show (); + timestretch_rect->raise_to_top (); + + x1 = start / editor.get_current_zoom(); + x2 = (end - 1) / editor.get_current_zoom(); + y2 = height - 2; + + timestretch_rect->property_x1() = x1; + timestretch_rect->property_y1() = 1.0; + timestretch_rect->property_x2() = x2; + timestretch_rect->property_y2() = y2; +} + +void +RouteTimeAxisView::hide_timestretch () +{ + TimeAxisView::hide_timestretch (); + + if (timestretch_rect) { + timestretch_rect->hide (); + } +} + +void +RouteTimeAxisView::show_selection (TimeSelection& ts) +{ + +#if 0 + /* ignore it if our edit group is not active or if the selection was started + in some other track or edit group (remember that edit_group() == 0 means + that the track is not in an edit group). + */ + + if (((ts.track != this && !is_child (ts.track)) && _route.edit_group() && !_route.edit_group()->is_active()) || + (!(ts.track == this || is_child (ts.track) || (ts.group != 0 && ts.group == _route.edit_group())))) { + hide_selection (); + return; + } +#endif + + TimeAxisView::show_selection (ts); +} + +void +RouteTimeAxisView::set_height (TrackHeight h) +{ + bool height_changed = (height == 0) || (h != height_style); + + TimeAxisView::set_height (h); + + ensure_xml_node (); + + _view->set_height ((double) height); + + switch (height_style) { + case Largest: + xml_node->add_property ("track_height", "largest"); + show_name_entry (); + hide_name_label (); + controls_table.show_all(); + break; + case Large: + xml_node->add_property ("track_height", "large"); + show_name_entry (); + hide_name_label (); + controls_table.show_all(); + break; + case Larger: + xml_node->add_property ("track_height", "larger"); + show_name_entry (); + hide_name_label (); + controls_table.show_all(); + break; + case Normal: + xml_node->add_property ("track_height", "normal"); + show_name_entry (); + hide_name_label (); + controls_table.show_all(); + break; + case Smaller: + xml_node->add_property ("track_height", "smaller"); + controls_table.show_all (); + show_name_entry (); + hide_name_label (); + edit_group_button.hide (); + hide_button.hide (); + visual_button.hide (); + size_button.hide (); + automation_button.hide (); + playlist_button.hide (); + break; + case Small: + xml_node->add_property ("track_height", "small"); + controls_table.hide_all (); + controls_table.show (); + hide_name_entry (); + show_name_label (); + name_label.set_text (_route.name()); + break; + } + + if (height_changed) { + /* only emit the signal if the height really changed */ + _route.gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ + } +} + +void +RouteTimeAxisView::select_track_color () +{ + if (RouteUI::choose_color ()) { + + if (_view) { + _view->apply_color (_color, StreamView::RegionColor); + } + } +} + +void +RouteTimeAxisView::reset_samples_per_unit () +{ + set_samples_per_unit (editor.get_current_zoom()); +} + +void +RouteTimeAxisView::set_samples_per_unit (double spu) +{ + double speed = 1.0; + + if (get_diskstream() != 0) { + speed = get_diskstream()->speed(); + } + + if (_view) { + _view->set_samples_per_unit (spu * speed); + } + + TimeAxisView::set_samples_per_unit (spu * speed); +} + +void +RouteTimeAxisView::align_style_changed () +{ + switch (get_diskstream()->alignment_style()) { + case ExistingMaterial: + if (!align_existing_item->get_active()) { + align_existing_item->set_active(); + } + break; + case CaptureTime: + if (!align_capture_item->get_active()) { + align_capture_item->set_active(); + } + break; + } +} + +void +RouteTimeAxisView::set_align_style (AlignStyle style) +{ + get_diskstream()->set_align_style (style); +} + +void +RouteTimeAxisView::rename_current_playlist () +{ + ArdourPrompter prompter (true); + string name; + + Diskstream *const ds = get_diskstream(); + if (!ds || ds->destructive()) + return; + + Playlist *const pl = ds->playlist(); + if (!pl) + return; + + prompter.set_prompt (_("Name for playlist")); + prompter.set_initial_text (pl->name()); + prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT); + prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false); + + switch (prompter.run ()) { + case Gtk::RESPONSE_ACCEPT: + prompter.get_result (name); + if (name.length()) { + pl->set_name (name); + } + break; + + default: + break; + } +} + +void +RouteTimeAxisView::use_copy_playlist (bool prompt) +{ + string name; + + Diskstream *const ds = get_diskstream(); + if (!ds || ds->destructive()) + return; + + Playlist *const pl = ds->playlist(); + if (!pl) + return; + + name = Playlist::bump_name (pl->name(), _session); + + if (prompt) { + + ArdourPrompter prompter (true); + + prompter.set_prompt (_("Name for Playlist")); + prompter.set_initial_text (name); + prompter.add_button (Gtk::Stock::NEW, Gtk::RESPONSE_ACCEPT); + prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false); + prompter.show_all (); + + switch (prompter.run ()) { + case Gtk::RESPONSE_ACCEPT: + prompter.get_result (name); + break; + + default: + return; + } + } + + if (name.length()) { + ds->use_copy_playlist (); + pl->set_name (name); + } +} + +void +RouteTimeAxisView::use_new_playlist (bool prompt) +{ + string name; + + Diskstream *const ds = get_diskstream(); + if (!ds || ds->destructive()) + return; + + Playlist *const pl = ds->playlist(); + if (!pl) + return; + + name = Playlist::bump_name (pl->name(), _session); + + if (prompt) { + + ArdourPrompter prompter (true); + + prompter.set_prompt (_("Name for Playlist")); + prompter.set_initial_text (name); + prompter.add_button (Gtk::Stock::NEW, Gtk::RESPONSE_ACCEPT); + prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false); + + switch (prompter.run ()) { + case Gtk::RESPONSE_ACCEPT: + prompter.get_result (name); + break; + + default: + return; + } + } + + if (name.length()) { + ds->use_new_playlist (); + pl->set_name (name); + } +} + +void +RouteTimeAxisView::clear_playlist () +{ + Diskstream *const ds = get_diskstream(); + if (!ds || ds->destructive()) + return; + + Playlist *const pl = ds->playlist(); + if (!pl) + return; + + editor.clear_playlist (*pl); +} + +void +RouteTimeAxisView::speed_changed () +{ + Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &RouteTimeAxisView::reset_samples_per_unit)); +} + +void +RouteTimeAxisView::diskstream_changed (void *src) +{ + Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &RouteTimeAxisView::update_diskstream_display)); +} + +void +RouteTimeAxisView::update_diskstream_display () +{ + if (!get_diskstream()) // bus + return; + + set_playlist (get_diskstream()->playlist()); + map_frozen (); +} + +void +RouteTimeAxisView::selection_click (GdkEventButton* ev) +{ + PublicEditor::TrackViewList* tracks = editor.get_valid_views (this, _route.edit_group()); + + switch (Keyboard::selection_type (ev->state)) { + case Selection::Toggle: + /* XXX this is not right */ + editor.get_selection().add (*tracks); + break; + + case Selection::Set: + editor.get_selection().set (*tracks); + break; + + case Selection::Extend: + /* not defined yet */ + break; + } + + delete tracks; +} + +void +RouteTimeAxisView::set_selected_points (PointSelection& points) +{ + for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) { + (*i)->set_selected_points (points); + } +} + +void +RouteTimeAxisView::get_selectables (jack_nframes_t start, jack_nframes_t end, double top, double bot, list<Selectable*>& results) +{ + double speed = 1.0; + + if (get_diskstream() != 0) { + speed = get_diskstream()->speed(); + } + + jack_nframes_t start_adjusted = session_frame_to_track_frame(start, speed); + jack_nframes_t end_adjusted = session_frame_to_track_frame(end, speed); + + if (_view && ((top < 0.0 && bot < 0.0)) || touched (top, bot)) { + _view->get_selectables (start_adjusted, end_adjusted, results); + } + + /* pick up visible automation tracks */ + + for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) { + if (!(*i)->hidden()) { + (*i)->get_selectables (start_adjusted, end_adjusted, top, bot, results); + } + } +} + +void +RouteTimeAxisView::get_inverted_selectables (Selection& sel, list<Selectable*>& results) +{ + if (_view) { + _view->get_inverted_selectables (sel, results); + } + + for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) { + if (!(*i)->hidden()) { + (*i)->get_inverted_selectables (sel, results); + } + } + + return; +} + +RouteGroup* +RouteTimeAxisView::edit_group() const +{ + return _route.edit_group(); +} + +string +RouteTimeAxisView::name() const +{ + return _route.name(); +} + +Playlist * +RouteTimeAxisView::playlist () const +{ + Diskstream *ds; + + if ((ds = get_diskstream()) != 0) { + return ds->playlist(); + } else { + return 0; + } +} + +void +RouteTimeAxisView::name_entry_changed () +{ + string x; + + x = name_entry.get_text (); + + if (x == _route.name()) { + return; + } + + if (x.length() == 0) { + name_entry.set_text (_route.name()); + return; + } + + strip_whitespace_edges(x); + + if (_session.route_name_unique (x)) { + _route.set_name (x, this); + } else { + ARDOUR_UI::instance()->popup_error (_("a track already exists with that name")); + name_entry.set_text (_route.name()); + } +} + +void +RouteTimeAxisView::visual_click () +{ + popup_display_menu (0); +} + +void +RouteTimeAxisView::hide_click () +{ + editor.hide_track_in_display (*this); +} + +Region* +RouteTimeAxisView::find_next_region (jack_nframes_t pos, RegionPoint point, int32_t dir) +{ + Diskstream *stream; + Playlist *playlist; + + if ((stream = get_diskstream()) != 0 && (playlist = stream->playlist()) != 0) { + return playlist->find_next_region (pos, point, dir); + } + + return 0; +} + +bool +RouteTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op) +{ + Playlist* what_we_got; + Diskstream* ds = get_diskstream(); + Playlist* playlist; + bool ret = false; + + if (ds == 0) { + /* route is a bus, not a track */ + return false; + } + + playlist = ds->playlist(); + + + TimeSelection time (selection.time); + float speed = ds->speed(); + if (speed != 1.0f) { + for (TimeSelection::iterator i = time.begin(); i != time.end(); ++i) { + (*i).start = session_frame_to_track_frame((*i).start, speed); + (*i).end = session_frame_to_track_frame((*i).end, speed); + } + } + + switch (op) { + case Cut: + _session.add_undo (playlist->get_memento()); + if ((what_we_got = playlist->cut (time)) != 0) { + editor.get_cut_buffer().add (what_we_got); + _session.add_redo_no_execute (playlist->get_memento()); + ret = true; + } + break; + case Copy: + if ((what_we_got = playlist->copy (time)) != 0) { + editor.get_cut_buffer().add (what_we_got); + } + break; + + case Clear: + _session.add_undo (playlist->get_memento()); + if ((what_we_got = playlist->cut (time)) != 0) { + _session.add_redo_no_execute (playlist->get_memento()); + what_we_got->unref (); + ret = true; + } + break; + } + + return ret; +} + +bool +RouteTimeAxisView::paste (jack_nframes_t pos, float times, Selection& selection, size_t nth) +{ + if (!is_track()) { + return false; + } + + Playlist* playlist = get_diskstream()->playlist(); + PlaylistSelection::iterator p; + + for (p = selection.playlists.begin(); p != selection.playlists.end() && nth; ++p, --nth); + + if (p == selection.playlists.end()) { + return false; + } + + if (get_diskstream()->speed() != 1.0f) + pos = session_frame_to_track_frame(pos, get_diskstream()->speed() ); + + _session.add_undo (playlist->get_memento()); + playlist->paste (**p, pos, times); + _session.add_redo_no_execute (playlist->get_memento()); + + return true; +} + + +list<TimeAxisView*> +RouteTimeAxisView::get_child_list() +{ + + list<TimeAxisView*>redirect_children; + + for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) { + if (!(*i)->hidden()) { + redirect_children.push_back(*i); + } + } + return redirect_children; +} + + +void +RouteTimeAxisView::build_playlist_menu (Gtk::Menu * menu) +{ + using namespace Menu_Helpers; + + if (!menu || !is_track()) { + return; + } + + MenuList& playlist_items = menu->items(); + menu->set_name ("ArdourContextMenu"); + playlist_items.clear(); + + if (playlist_menu) { + delete playlist_menu; + } + playlist_menu = new Menu; + playlist_menu->set_name ("ArdourContextMenu"); + + playlist_items.push_back (MenuElem (string_compose (_("Current: %1"), get_diskstream()->playlist()->name()))); + playlist_items.push_back (SeparatorElem()); + + playlist_items.push_back (MenuElem (_("Rename"), mem_fun(*this, &RouteTimeAxisView::rename_current_playlist))); + playlist_items.push_back (SeparatorElem()); + + playlist_items.push_back (MenuElem (_("New"), mem_fun(editor, &PublicEditor::new_playlists))); + playlist_items.push_back (MenuElem (_("New Copy"), mem_fun(editor, &PublicEditor::copy_playlists))); + playlist_items.push_back (SeparatorElem()); + playlist_items.push_back (MenuElem (_("Clear Current"), mem_fun(editor, &PublicEditor::clear_playlists))); + playlist_items.push_back (SeparatorElem()); + playlist_items.push_back (MenuElem(_("Select"), mem_fun(*this, &RouteTimeAxisView::show_playlist_selector))); + +} + +void +RouteTimeAxisView::show_playlist_selector () +{ + editor.playlist_selector().show_for (this); +} + +void +RouteTimeAxisView::map_frozen () +{ + if (!is_track()) { + return; + } + + ENSURE_GUI_THREAD (mem_fun(*this, &RouteTimeAxisView::map_frozen)); + + switch (track()->freeze_state()) { + case Track::Frozen: + playlist_button.set_sensitive (false); + rec_enable_button->set_sensitive (false); + break; + default: + playlist_button.set_sensitive (true); + rec_enable_button->set_sensitive (true); + break; + } +} + +void +RouteTimeAxisView::color_handler (ColorID id, uint32_t val) +{ + switch (id) { + case cTimeStretchOutline: + timestretch_rect->property_outline_color_rgba() = val; + break; + case cTimeStretchFill: + timestretch_rect->property_fill_color_rgba() = val; + break; + default: + break; + } +} + +bool +RouteTimeAxisView::select_me (GdkEventButton* ev) +{ + editor.get_selection().add (this); + return false; +} + diff --git a/gtk2_ardour/route_time_axis.h b/gtk2_ardour/route_time_axis.h new file mode 100644 index 0000000000..e63253af24 --- /dev/null +++ b/gtk2_ardour/route_time_axis.h @@ -0,0 +1,205 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: audio_time_axis.h 664 2006-07-05 19:47:25Z drobilla $ +*/ + +#ifndef __ardour_route_time_axis_h__ +#define __ardour_route_time_axis_h__ + +#include <gtkmm/table.h> +#include <gtkmm/button.h> +#include <gtkmm/box.h> +#include <gtkmm/menu.h> +#include <gtkmm/menuitem.h> +#include <gtkmm/radiomenuitem.h> +#include <gtkmm/checkmenuitem.h> + +#include <gtkmm2ext/selector.h> +#include <list> + +#include <ardour/types.h> +#include <ardour/region.h> + +#include "ardour_dialog.h" +#include "route_ui.h" +#include "enums.h" +#include "time_axis_view.h" +#include "canvas.h" +#include "color.h" + +namespace ARDOUR { + class Session; + class Diskstream; + class RouteGroup; + class Redirect; + class Insert; + class Location; + class Playlist; +} + +class PublicEditor; +class RegionView; +class StreamView; +class Selection; +class Selectable; +class AutomationLine; +class TimeSelection; + +class RouteTimeAxisView : public RouteUI, public TimeAxisView +{ + public: + RouteTimeAxisView (PublicEditor&, ARDOUR::Session&, ARDOUR::Route&, ArdourCanvas::Canvas& canvas); + virtual ~RouteTimeAxisView (); + + void show_selection (TimeSelection&); + + void set_samples_per_unit (double); + void set_height (TimeAxisView::TrackHeight); + void show_timestretch (jack_nframes_t start, jack_nframes_t end); + void hide_timestretch (); + void selection_click (GdkEventButton*); + void set_selected_points (PointSelection&); + void get_selectables (jack_nframes_t start, jack_nframes_t end, double top, double bot, list<Selectable *>&); + void get_inverted_selectables (Selection&, list<Selectable*>&); + + ARDOUR::Region* find_next_region (jack_nframes_t pos, ARDOUR::RegionPoint, int32_t dir); + + string name() const; + + ARDOUR::RouteGroup* edit_group() const; + + void build_playlist_menu (Gtk::Menu *); + ARDOUR::Playlist* playlist() const; + + StreamView* view() { return _view; } + + /* editing operations */ + + bool cut_copy_clear (Selection&, Editing::CutCopyOp); + bool paste (jack_nframes_t, float times, Selection&, size_t nth); + + list<TimeAxisView*> get_child_list(); + + /* the editor calls these when mapping an operation across multiple tracks */ + + void use_new_playlist (bool prompt); + void use_copy_playlist (bool prompt); + void clear_playlist (); + + //private: + friend class StreamView; + + StreamView *_view; + + ArdourCanvas::Canvas& parent_canvas; + + bool no_redraw; + + Gtk::HBox other_button_hbox; + Gtk::Table button_table; + Gtk::Button redirect_button; + Gtk::Button edit_group_button; + Gtk::Button playlist_button; + Gtk::Button size_button; + Gtk::Button automation_button; + Gtk::Button hide_button; + Gtk::Button visual_button; + + void diskstream_changed (void *src); + void update_diskstream_display (); + + gint edit_click (GdkEventButton *); + + void build_redirect_window (); + void redirect_click (); + void redirect_add (); + void redirect_remove (); + void redirect_edit (); + void redirect_relist (); + void redirect_row_selected (gint row, gint col, GdkEvent *ev); + void add_to_redirect_display (ARDOUR::Redirect *); + //void redirects_changed (void *); + + sigc::connection modified_connection; + sigc::connection state_changed_connection; + + void take_name_changed (void *); + void route_name_changed (void *); + void name_entry_changed (); + + void on_area_realize (); + + virtual void label_view (); + + Gtk::Menu edit_group_menu; + + void add_edit_group_menu_item (ARDOUR::RouteGroup *, Gtk::RadioMenuItem::Group*); + void set_edit_group_from_menu (ARDOUR::RouteGroup *); + + void reset_samples_per_unit (); + + void select_track_color(); + + virtual void build_display_menu () = 0; + + Gtk::RadioMenuItem* align_existing_item; + Gtk::RadioMenuItem* align_capture_item; + + void align_style_changed (); + void set_align_style (ARDOUR::AlignStyle); + + Gtk::Menu *playlist_menu; + Gtk::Menu *playlist_action_menu; + Gtk::MenuItem *playlist_item; + + /* playlist */ + + virtual void set_playlist (ARDOUR::Playlist *); + void playlist_click (); + void show_playlist_selector (); + + void playlist_changed (); + void playlist_state_changed (ARDOUR::Change); + void playlist_modified (); + + void add_playlist_to_playlist_menu (ARDOUR::Playlist*); + void rename_current_playlist (); + + Gtk::Menu* automation_action_menu; + void automation_click (); + + ArdourCanvas::SimpleRect *timestretch_rect; + + void timestretch (jack_nframes_t start, jack_nframes_t end); + + void visual_click (); + void hide_click (); + gint when_displayed (GdkEventAny*); + + void speed_changed (); + + void map_frozen (); + + void color_handler (ColorID, uint32_t); + bool select_me (GdkEventButton*); + + virtual void region_view_added (RegionView*) = 0; +}; + +#endif /* __ardour_route_time_axis_h__ */ + diff --git a/gtk2_ardour/route_ui.cc b/gtk2_ardour/route_ui.cc index b18bff46e9..2713a666e4 100644 --- a/gtk2_ardour/route_ui.cc +++ b/gtk2_ardour/route_ui.cc @@ -72,14 +72,14 @@ RouteUI::RouteUI (ARDOUR::Route& rt, ARDOUR::Session& sess, const char* m_name, mute_button = manage (new BindableToggleButton (_route.mute_control(), m_name )); solo_button = manage (new BindableToggleButton (_route.solo_control(), s_name )); - if (is_audio_track()) { - AudioTrack* at = dynamic_cast<AudioTrack*>(&_route); + if (is_track()) { + Track* t = dynamic_cast<Track*>(&_route); get_diskstream()->RecordEnableChanged.connect (mem_fun (*this, &RouteUI::route_rec_enable_changed)); _session.RecordStateChanged.connect (mem_fun (*this, &RouteUI::session_rec_enable_changed)); - rec_enable_button = manage (new BindableToggleButton (at->rec_enable_control(), r_name )); + rec_enable_button = manage (new BindableToggleButton (t->rec_enable_control(), r_name )); rec_enable_button->unset_flags (Gtk::CAN_FOCUS); @@ -270,7 +270,7 @@ RouteUI::solo_release(GdkEventButton* ev) gint RouteUI::rec_enable_press(GdkEventButton* ev) { - if (!ignore_toggle && is_audio_track() && rec_enable_button) { + if (!ignore_toggle && is_track() && rec_enable_button) { if (ev->button == 2 && Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) { // do nothing on midi bind event @@ -696,7 +696,7 @@ RouteUI::remove_this_route () vector<string> choices; string prompt; - if (is_audio_track()) { + if (is_track()) { prompt = string_compose (_("Do you really want to remove track \"%1\" ?\n\nYou may also lose the playlist used by this track.\n(cannot be undone)"), _route.name()); } else { prompt = string_compose (_("Do you really want to remove bus \"%1\" ?\n(cannot be undone)"), _route.name()); @@ -872,6 +872,12 @@ RouteUI::disconnect_output () } bool +RouteUI::is_track () const +{ + return dynamic_cast<Track*>(&_route) != 0; +} + +bool RouteUI::is_audio_track () const { return dynamic_cast<AudioTrack*>(&_route) != 0; @@ -883,16 +889,10 @@ RouteUI::is_midi_track () const return dynamic_cast<MidiTrack*>(&_route) != 0; } -Diskstream* -RouteUI::get_diskstream () const +Track* +RouteUI::track() const { - Track *t; - - if ((t = dynamic_cast<Track*>(&_route)) != 0) { - return &t->diskstream(); - } else { - return 0; - } + return dynamic_cast<Track*>(&_route); } AudioTrack* @@ -907,6 +907,19 @@ RouteUI::midi_track() const return dynamic_cast<MidiTrack*>(&_route); } +Diskstream* +RouteUI::get_diskstream () const +{ + Track *t; + + if ((t = dynamic_cast<Track*>(&_route)) != 0) { + return &t->diskstream(); + } else { + return 0; + } +} + + string RouteUI::name() const { diff --git a/gtk2_ardour/route_ui.h b/gtk2_ardour/route_ui.h index 63fc4d9cb8..5236e204f8 100644 --- a/gtk2_ardour/route_ui.h +++ b/gtk2_ardour/route_ui.h @@ -26,6 +26,7 @@ #include <pbd/xml++.h> #include <ardour/ardour.h> #include <ardour/route.h> +#include <ardour/track.h> #include "axis_view.h" @@ -48,14 +49,17 @@ class RouteUI : public virtual AxisView RouteUI(ARDOUR::Route&, ARDOUR::Session&, const char*, const char*, const char*); virtual ~RouteUI(); + ARDOUR::Route& route() const { return _route; } + + bool is_track() const; bool is_audio_track() const; bool is_midi_track() const; - //ARDOUR::AudioDiskstream* get_diskstream() const; - ARDOUR::Diskstream* get_diskstream() const; - ARDOUR::Route& route() const { return _route; } + ARDOUR::Track* track() const; ARDOUR::AudioTrack* audio_track() const; - ARDOUR::MidiTrack* midi_track() const; + ARDOUR::MidiTrack* midi_track() const; + + ARDOUR::Diskstream* get_diskstream() const; string name() const; diff --git a/gtk2_ardour/selection.cc b/gtk2_ardour/selection.cc index 2e4ed8a117..fe7d754d13 100644 --- a/gtk2_ardour/selection.cc +++ b/gtk2_ardour/selection.cc @@ -46,7 +46,7 @@ Selection& Selection::operator= (const Selection& other) { if (&other != this) { - audio_regions = other.audio_regions; + regions = other.regions; tracks = other.tracks; time = other.time; lines = other.lines; @@ -57,7 +57,7 @@ Selection::operator= (const Selection& other) bool operator== (const Selection& a, const Selection& b) { - return a.audio_regions == b.audio_regions && + return a.regions == b.regions && a.tracks == b.tracks && a.time.track == b.time.track && a.time.group == b.time.group && @@ -71,7 +71,7 @@ void Selection::clear () { clear_tracks (); - clear_audio_regions (); + clear_regions (); clear_points (); clear_lines(); clear_time (); @@ -83,8 +83,8 @@ void Selection::dump_region_layers() { cerr << "region selection layer dump" << endl; - for (AudioRegionSelection::iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) { - cerr << "layer: " << (int)(*i)->region.layer() << endl; + for (RegionSelection::iterator i = regions.begin(); i != regions.end(); ++i) { + cerr << "layer: " << (int)(*i)->region().layer() << endl; } } @@ -99,10 +99,10 @@ Selection::clear_redirects () } void -Selection::clear_audio_regions () +Selection::clear_regions () { - if (!audio_regions.empty()) { - audio_regions.clear_all (); + if (!regions.empty()) { + regions.clear_all (); RegionsChanged(); } } @@ -196,29 +196,29 @@ Selection::toggle (TimeAxisView* track) } void -Selection::toggle (AudioRegionView* r) +Selection::toggle (RegionView* r) { - AudioRegionSelection::iterator i; + RegionSelection::iterator i; - if ((i = find (audio_regions.begin(), audio_regions.end(), r)) == audio_regions.end()) { - audio_regions.add (r); + if ((i = find (regions.begin(), regions.end(), r)) == regions.end()) { + regions.add (r); } else { - audio_regions.erase (i); + regions.erase (i); } RegionsChanged (); } void -Selection::toggle (vector<AudioRegionView*>& r) +Selection::toggle (vector<RegionView*>& r) { - AudioRegionSelection::iterator i; + RegionSelection::iterator i; - for (vector<AudioRegionView*>::iterator x = r.begin(); x != r.end(); ++x) { - if ((i = find (audio_regions.begin(), audio_regions.end(), (*x))) == audio_regions.end()) { - audio_regions.add ((*x)); + for (vector<RegionView*>::iterator x = r.begin(); x != r.end(); ++x) { + if ((i = find (regions.begin(), regions.end(), (*x))) == regions.end()) { + regions.add ((*x)); } else { - audio_regions.erase (i); + regions.erase (i); } } @@ -310,22 +310,22 @@ Selection::add (TimeAxisView* track) } void -Selection::add (AudioRegionView* r) +Selection::add (RegionView* r) { - if (find (audio_regions.begin(), audio_regions.end(), r) == audio_regions.end()) { - audio_regions.add (r); + if (find (regions.begin(), regions.end(), r) == regions.end()) { + regions.add (r); RegionsChanged (); } } void -Selection::add (vector<AudioRegionView*>& v) +Selection::add (vector<RegionView*>& v) { bool changed = false; - for (vector<AudioRegionView*>::iterator i = v.begin(); i != v.end(); ++i) { - if (find (audio_regions.begin(), audio_regions.end(), (*i)) == audio_regions.end()) { - audio_regions.add ((*i)); + for (vector<RegionView*>::iterator i = v.begin(); i != v.end(); ++i) { + if (find (regions.begin(), regions.end(), (*i)) == regions.end()) { + regions.add ((*i)); changed = true; } } @@ -451,9 +451,9 @@ Selection::remove (const list<Playlist*>& pllist) } void -Selection::remove (AudioRegionView* r) +Selection::remove (RegionView* r) { - audio_regions.remove (r); + regions.remove (r); RegionsChanged (); } @@ -526,17 +526,16 @@ Selection::set (const list<Playlist*>& pllist) } void -Selection::set (AudioRegionView* r) +Selection::set (RegionView* r) { - clear_audio_regions (); + clear_regions (); add (r); } void -Selection::set (vector<AudioRegionView*>& v) +Selection::set (vector<RegionView*>& v) { - - clear_audio_regions (); + clear_regions (); // make sure to deselect any automation selections clear_points(); add (v); @@ -590,15 +589,15 @@ Selection::selected (TimeAxisView* tv) } bool -Selection::selected (AudioRegionView* arv) +Selection::selected (RegionView* rv) { - return find (audio_regions.begin(), audio_regions.end(), arv) != audio_regions.end(); + return find (regions.begin(), regions.end(), rv) != regions.end(); } bool Selection::empty () { - return audio_regions.empty () && + return regions.empty () && tracks.empty () && points.empty () && playlists.empty () && @@ -612,7 +611,7 @@ Selection::empty () void Selection::set (list<Selectable*>& selectables) { - clear_audio_regions(); + clear_regions(); clear_points (); add (selectables); } @@ -620,14 +619,14 @@ Selection::set (list<Selectable*>& selectables) void Selection::add (list<Selectable*>& selectables) { - AudioRegionView* arv; + RegionView* rv; AutomationSelectable* as; - vector<AudioRegionView*> arvs; + vector<RegionView*> rvs; vector<AutomationSelectable*> autos; for (std::list<Selectable*>::iterator i = selectables.begin(); i != selectables.end(); ++i) { - if ((arv = dynamic_cast<AudioRegionView*> (*i)) != 0) { - arvs.push_back (arv); + if ((rv = dynamic_cast<RegionView*> (*i)) != 0) { + rvs.push_back (rv); } else if ((as = dynamic_cast<AutomationSelectable*> (*i)) != 0) { autos.push_back (as); } else { @@ -638,8 +637,8 @@ Selection::add (list<Selectable*>& selectables) } } - if (!arvs.empty()) { - add (arvs); + if (!rvs.empty()) { + add (rvs); } if (!autos.empty()) { diff --git a/gtk2_ardour/selection.h b/gtk2_ardour/selection.h index ebeda1aea7..1aab414453 100644 --- a/gtk2_ardour/selection.h +++ b/gtk2_ardour/selection.h @@ -34,7 +34,7 @@ #include "point_selection.h" class TimeAxisView; -class AudioRegionView; +class RegionView; class Selectable; namespace ARDOUR { @@ -60,7 +60,7 @@ class Selection : public sigc::trackable }; TrackSelection tracks; - AudioRegionSelection audio_regions; + RegionSelection regions; TimeSelection time; AutomationSelection lines; PlaylistSelection playlists; @@ -88,15 +88,15 @@ class Selection : public sigc::trackable void dump_region_layers(); bool selected (TimeAxisView*); - bool selected (AudioRegionView*); + bool selected (RegionView*); void set (list<Selectable*>&); void add (list<Selectable*>&); void set (TimeAxisView*); void set (const list<TimeAxisView*>&); - void set (AudioRegionView*); - void set (std::vector<AudioRegionView*>&); + void set (RegionView*); + void set (std::vector<RegionView*>&); long set (TimeAxisView*, jack_nframes_t, jack_nframes_t); void set (ARDOUR::AutomationList*); void set (ARDOUR::Playlist*); @@ -106,8 +106,8 @@ class Selection : public sigc::trackable void toggle (TimeAxisView*); void toggle (const list<TimeAxisView*>&); - void toggle (AudioRegionView*); - void toggle (std::vector<AudioRegionView*>&); + void toggle (RegionView*); + void toggle (std::vector<RegionView*>&); long toggle (jack_nframes_t, jack_nframes_t); void toggle (ARDOUR::AutomationList*); void toggle (ARDOUR::Playlist*); @@ -116,8 +116,8 @@ class Selection : public sigc::trackable void add (TimeAxisView*); void add (const list<TimeAxisView*>&); - void add (AudioRegionView*); - void add (std::vector<AudioRegionView*>&); + void add (RegionView*); + void add (std::vector<RegionView*>&); long add (jack_nframes_t, jack_nframes_t); void add (ARDOUR::AutomationList*); void add (ARDOUR::Playlist*); @@ -126,7 +126,7 @@ class Selection : public sigc::trackable void remove (TimeAxisView*); void remove (const list<TimeAxisView*>&); - void remove (AudioRegionView*); + void remove (RegionView*); void remove (uint32_t selection_id); void remove (jack_nframes_t, jack_nframes_t); void remove (ARDOUR::AutomationList*); @@ -136,7 +136,7 @@ class Selection : public sigc::trackable void replace (uint32_t time_index, jack_nframes_t start, jack_nframes_t end); - void clear_audio_regions(); + void clear_regions(); void clear_tracks (); void clear_time(); void clear_lines (); @@ -144,10 +144,8 @@ class Selection : public sigc::trackable void clear_redirects (); void clear_points (); - void foreach_audio_region (void (ARDOUR::AudioRegion::*method)(void)); - void foreach_audio_region (void (ARDOUR::Region::*method)(void)); - template<class A> void foreach_audio_region (void (ARDOUR::AudioRegion::*method)(A), A arg); - template<class A> void foreach_audio_region (void (ARDOUR::Region::*method)(A), A arg); + void foreach_region (void (ARDOUR::Region::*method)(void)); + template<class A> void foreach_region (void (ARDOUR::Region::*method)(A), A arg); private: uint32_t next_time_id; diff --git a/gtk2_ardour/selection_templates.h b/gtk2_ardour/selection_templates.h index c2ca70b526..5ff2c625bc 100644 --- a/gtk2_ardour/selection_templates.h +++ b/gtk2_ardour/selection_templates.h @@ -32,30 +32,16 @@ #include "selection.h" inline void -Selection::foreach_audio_region (void (ARDOUR::AudioRegion::*method)(void)) { - for (AudioRegionSelection::iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) { - ((*i)->region.*(method))(); - } -} - -inline void -Selection::foreach_audio_region (void (ARDOUR::Region::*method)(void)) { - for (AudioRegionSelection::iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) { - ((*i)->region.*(method))(); - } -} - -template<class A> inline void -Selection::foreach_audio_region (void (ARDOUR::AudioRegion::*method)(A), A arg) { - for (AudioRegionSelection::iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) { - ((*i)->region.*(method))(arg); +Selection::foreach_region (void (ARDOUR::Region::*method)(void)) { + for (RegionSelection::iterator i = regions.begin(); i != regions.end(); ++i) { + ((*i)->region().*(method))(); } } template<class A> inline void -Selection::foreach_audio_region (void (ARDOUR::Region::*method)(A), A arg) { - for (AudioRegionSelection::iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) { - ((*i)->region.*(method))(arg); +Selection::foreach_region (void (ARDOUR::Region::*method)(A), A arg) { + for (RegionSelection::iterator i = regions.begin(); i != regions.end(); ++i) { + ((*i)->region().*(method))(arg); } } @@ -64,14 +50,14 @@ Selection::foreach_audio_region (void (ARDOUR::Region::*method)(A), A arg) { template<class A> inline void Selection::foreach_route (void (ARDOUR::Route::*method)(A), A arg) { for (list<ARDOUR::Route*>::iterator i = routes.begin(); i != routes.end(); ++i) { - ((*i)->region.*(method))(arg); + ((*i)->region().*(method))(arg); } } template<class A1, class A2> inline void Selection::foreach_route (void (ARDOUR::Route::*method)(A1,A2), A1 arg1, A2 arg2) { for (list<ARDOUR::Route*>::iterator i = routes.begin(); i != routes.end(); ++i) { - ((*i)->region.*(method))(arg1, arg2); + ((*i)->region().*(method))(arg1, arg2); } } diff --git a/gtk2_ardour/streamview.cc b/gtk2_ardour/streamview.cc index dd37ba16ea..93d25b6a97 100644 --- a/gtk2_ardour/streamview.cc +++ b/gtk2_ardour/streamview.cc @@ -1,28 +1,42 @@ +/* + Copyright (C) 2001, 2006 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + #include <cmath> #include <gtkmm.h> #include <gtkmm2ext/gtk_ui.h> -#include <ardour/audioplaylist.h> -#include <ardour/audioregion.h> -#include <ardour/audiosource.h> -#include <ardour/audio_diskstream.h> -#include <ardour/audio_track.h> -#include <ardour/playlist_templates.h> +#include <ardour/playlist.h> +#include <ardour/region.h> #include <ardour/source.h> +#include <ardour/diskstream.h> +#include <ardour/track.h> #include "streamview.h" #include "regionview.h" -#include "taperegionview.h" -#include "audio_time_axis.h" +#include "route_time_axis.h" #include "canvas-waveview.h" #include "canvas-simplerect.h" #include "region_selection.h" #include "selection.h" #include "public_editor.h" #include "ardour_ui.h" -#include "crossfade_view.h" #include "rgb_macros.h" #include "gui_thread.h" #include "utils.h" @@ -32,25 +46,10 @@ using namespace ARDOUR; using namespace PBD; using namespace Editing; -StreamView::StreamView (AudioTimeAxisView& tv) +StreamView::StreamView (RouteTimeAxisView& tv) : _trackview (tv) { region_color = _trackview.color(); - crossfades_visible = true; - - if (tv.is_audio_track()) { - /* AUDIO TRACK */ - //stream_base_color = RGBA_TO_UINT (222,223,218,255); - stream_base_color = color_map[cAudioTrackBase]; - } else if (tv.is_midi_track()) { - /* MIDI TRACK */ - stream_base_color = color_map[cMidiTrackBase]; - } else { - // FIXME: distinction between audio and midi busses - /* BUS */ - //stream_base_color = RGBA_TO_UINT (230,226,238,255); - stream_base_color = color_map[cAudioBusBase]; - } /* set_position() will position the group */ @@ -61,17 +60,16 @@ StreamView::StreamView (AudioTimeAxisView& tv) canvas_rect->property_y1() = 0.0; canvas_rect->property_x2() = 1000000.0; canvas_rect->property_y2() = (double) tv.height; - canvas_rect->property_outline_color_rgba() = color_map[cAudioTrackOutline]; + canvas_rect->property_outline_color_rgba() = color_map[cAudioTrackOutline]; // FIXME canvas_rect->property_outline_what() = (guint32) (0x1|0x2|0x8); // outline ends and bottom canvas_rect->property_fill_color_rgba() = stream_base_color; canvas_rect->signal_event().connect (bind (mem_fun (_trackview.editor, &PublicEditor::canvas_stream_view_event), canvas_rect, &_trackview)); _samples_per_unit = _trackview.editor.get_current_zoom(); - _amplitude_above_axis = 1.0; - if (_trackview.is_audio_track()) { - _trackview.audio_track()->DiskstreamChanged.connect (mem_fun (*this, &StreamView::diskstream_changed)); + if (_trackview.is_track()) { + _trackview.track()->DiskstreamChanged.connect (mem_fun (*this, &StreamView::diskstream_changed)); _trackview.session().TransportStateChange.connect (mem_fun (*this, &StreamView::transport_changed)); _trackview.get_diskstream()->RecordEnableChanged.connect (mem_fun (*this, &StreamView::rec_enable_changed)); _trackview.session().RecordStateChanged.connect (mem_fun (*this, &StreamView::sess_rec_enable_changed)); @@ -80,7 +78,6 @@ StreamView::StreamView (AudioTimeAxisView& tv) rec_updating = false; rec_active = false; use_rec_regions = tv.editor.show_waveforms_recording (); - last_rec_peak_frame = 0; ColorChanged.connect (mem_fun (*this, &StreamView::color_handler)); } @@ -94,7 +91,7 @@ StreamView::~StreamView () void StreamView::attach () { - if (_trackview.is_audio_track()) { + if (_trackview.is_track()) { display_diskstream (_trackview.get_diskstream()); } } @@ -119,13 +116,13 @@ StreamView::set_height (gdouble h) canvas_rect->property_y2() = h; - for (AudioRegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) { + for (RegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) { (*i)->set_height (h); } - for (CrossfadeViewList::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) { + /*for (CrossfadeViewList::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) { (*i)->set_height (h); - } + }*/ for (vector<RecBoxInfo>::iterator i = rec_rects.begin(); i != rec_rects.end(); ++i) { RecBoxInfo &recbox = (*i); @@ -138,7 +135,7 @@ StreamView::set_height (gdouble h) int StreamView::set_samples_per_unit (gdouble spp) { - AudioRegionViewList::iterator i; + RegionViewList::iterator i; if (spp < 1.0) { return -1; @@ -150,10 +147,6 @@ StreamView::set_samples_per_unit (gdouble spp) (*i)->set_samples_per_unit (spp); } - for (CrossfadeViewList::iterator xi = crossfade_views.begin(); xi != crossfade_views.end(); ++xi) { - (*xi)->set_samples_per_unit (spp); - } - for (vector<RecBoxInfo>::iterator xi = rec_rects.begin(); xi != rec_rects.end(); ++xi) { RecBoxInfo &recbox = (*xi); @@ -167,25 +160,6 @@ StreamView::set_samples_per_unit (gdouble spp) return 0; } -int -StreamView::set_amplitude_above_axis (gdouble app) - -{ - AudioRegionViewList::iterator i; - - if (app < 1.0) { - return -1; - } - - _amplitude_above_axis = app; - - for (i = region_views.begin(); i != region_views.end(); ++i) { - (*i)->set_amplitude_above_axis (app); - } - - return 0; -} - void StreamView::add_region_view (Region *r) { @@ -193,87 +167,17 @@ StreamView::add_region_view (Region *r) } void -StreamView::add_region_view_internal (Region *r, bool wait_for_waves) -{ - ENSURE_GUI_THREAD (bind (mem_fun (*this, &StreamView::add_region_view), r)); - - AudioRegion* region = dynamic_cast<AudioRegion*> (r); - - if (region == 0) { - return; - } - - AudioRegionView *region_view; - list<AudioRegionView *>::iterator i; - - for (i = region_views.begin(); i != region_views.end(); ++i) { - if (&(*i)->region == region) { - - /* great. we already have a AudioRegionView for this Region. use it again. - */ - - (*i)->set_valid (true); - return; - } - } - - switch (_trackview.audio_track()->mode()) { - case Normal: - region_view = new AudioRegionView (canvas_group, _trackview, *region, - _samples_per_unit, region_color); - break; - case Destructive: - region_view = new TapeAudioRegionView (canvas_group, _trackview, *region, - _samples_per_unit, region_color); - break; - } - - region_view->init (_amplitude_above_axis, region_color, wait_for_waves); - region_views.push_front (region_view); - - /* follow global waveform setting */ - - region_view->set_waveform_visible(_trackview.editor.show_waveforms()); - - /* catch regionview going away */ - - region->GoingAway.connect (mem_fun (*this, &StreamView::remove_region_view)); - - AudioRegionViewAdded (region_view); -} - -void StreamView::remove_region_view (Region *r) { ENSURE_GUI_THREAD (bind (mem_fun (*this, &StreamView::remove_region_view), r)); - AudioRegion* ar = dynamic_cast<AudioRegion*> (r); - - if (ar == 0) { - return; - } - - for (list<AudioRegionView *>::iterator i = region_views.begin(); i != region_views.end(); ++i) { - if (&((*i)->region) == ar) { + for (list<RegionView *>::iterator i = region_views.begin(); i != region_views.end(); ++i) { + if (&((*i)->region()) == r) { delete *i; region_views.erase (i); break; } } - - for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end();) { - list<CrossfadeView*>::iterator tmp; - - tmp = i; - ++tmp; - - if ((*i)->crossfade.involves (*ar)) { - delete *i; - crossfade_views.erase (i); - } - - i = tmp; - } } void @@ -286,14 +190,8 @@ StreamView::remove_rec_region (Region *r) /*NOTREACHED*/ } - AudioRegion* ar = dynamic_cast<AudioRegion*> (r); - - if (ar == 0) { - return; - } - - for (list<AudioRegion *>::iterator i = rec_regions.begin(); i != rec_regions.end(); ++i) { - if (*i == ar) { + for (list<Region *>::iterator i = rec_regions.begin(); i != rec_regions.end(); ++i) { + if (*i == r) { rec_regions.erase (i); break; } @@ -303,21 +201,15 @@ StreamView::remove_rec_region (Region *r) void StreamView::undisplay_diskstream () { - - for (AudioRegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) { - delete *i; - } - - for (CrossfadeViewList::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) { + for (RegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) { delete *i; } region_views.clear(); - crossfade_views.clear (); } void -StreamView::display_diskstream (AudioDiskstream *ds) +StreamView::display_diskstream (Diskstream *ds) { playlist_change_connection.disconnect(); playlist_changed (ds); @@ -329,21 +221,13 @@ StreamView::playlist_modified () { ENSURE_GUI_THREAD (mem_fun (*this, &StreamView::playlist_modified)); - /* if the playlist is modified, make sure xfades are on top and all the regionviews are stacked - correctly. - */ - - for (AudioRegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) { + for (RegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) { region_layered (*i); } - - for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) { - (*i)->get_canvas_group()->raise_to_top(); - } } void -StreamView::playlist_changed (AudioDiskstream *ds) +StreamView::playlist_changed (Diskstream *ds) { ENSURE_GUI_THREAD (bind (mem_fun (*this, &StreamView::playlist_changed), ds)); @@ -366,71 +250,6 @@ StreamView::playlist_changed (AudioDiskstream *ds) playlist_connections.push_back (ds->playlist()->RegionRemoved.connect (mem_fun (*this, &StreamView::remove_region_view))); playlist_connections.push_back (ds->playlist()->StateChanged.connect (mem_fun (*this, &StreamView::playlist_state_changed))); playlist_connections.push_back (ds->playlist()->Modified.connect (mem_fun (*this, &StreamView::playlist_modified))); - AudioPlaylist* apl = dynamic_cast<AudioPlaylist*>(ds->playlist()); - if (apl) - playlist_connections.push_back (apl->NewCrossfade.connect (mem_fun (*this, &StreamView::add_crossfade))); -} - -void -StreamView::add_crossfade (Crossfade *crossfade) -{ - AudioRegionView* lview = 0; - AudioRegionView* rview = 0; - - ENSURE_GUI_THREAD (bind (mem_fun (*this, &StreamView::add_crossfade), crossfade)); - - /* first see if we already have a CrossfadeView for this Crossfade */ - - for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) { - if (&(*i)->crossfade == crossfade) { - if (!crossfades_visible) { - (*i)->hide(); - } else { - (*i)->show (); - } - (*i)->set_valid (true); - return; - } - } - - /* create a new one */ - - for (list<AudioRegionView *>::iterator i = region_views.begin(); i != region_views.end(); ++i) { - if (!lview && &((*i)->region) == &crossfade->out()) { - lview = *i; - } - if (!rview && &((*i)->region) == &crossfade->in()) { - rview = *i; - } - } - - CrossfadeView *cv = new CrossfadeView (_trackview.canvas_display, - _trackview, - *crossfade, - _samples_per_unit, - region_color, - *lview, *rview); - - crossfade->Invalidated.connect (mem_fun (*this, &StreamView::remove_crossfade)); - crossfade_views.push_back (cv); - - if (!crossfades_visible) { - cv->hide (); - } -} - -void -StreamView::remove_crossfade (Crossfade *xfade) -{ - ENSURE_GUI_THREAD (bind (mem_fun (*this, &StreamView::remove_crossfade), xfade)); - - for (list<CrossfadeView*>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) { - if (&(*i)->crossfade == xfade) { - delete *i; - crossfade_views.erase (i); - break; - } - } } void @@ -442,66 +261,12 @@ StreamView::playlist_state_changed (Change ignored) } void -StreamView::redisplay_diskstream () -{ - list<AudioRegionView *>::iterator i, tmp; - list<CrossfadeView*>::iterator xi, tmpx; - - - for (i = region_views.begin(); i != region_views.end(); ++i) { - (*i)->set_valid (false); - } - - for (xi = crossfade_views.begin(); xi != crossfade_views.end(); ++xi) { - (*xi)->set_valid (false); - if ((*xi)->visible()) { - (*xi)->show (); - } - } - - if (_trackview.is_audio_track()) { - _trackview.get_diskstream()->playlist()->foreach_region (this, &StreamView::add_region_view); - AudioPlaylist* apl = dynamic_cast<AudioPlaylist*>(_trackview.get_diskstream()->playlist()); - if (apl) - apl->foreach_crossfade (this, &StreamView::add_crossfade); - } - - for (i = region_views.begin(); i != region_views.end(); ) { - tmp = i; - tmp++; - - if (!(*i)->is_valid()) { - delete *i; - region_views.erase (i); - } - - i = tmp; - } - - for (xi = crossfade_views.begin(); xi != crossfade_views.end();) { - tmpx = xi; - tmpx++; - - if (!(*xi)->valid()) { - delete *xi; - crossfade_views.erase (xi); - } - - xi = tmpx; - } - - /* now fix layering */ - - playlist_modified (); -} - -void StreamView::diskstream_changed (void *src_ignored) { - AudioTrack *at; + Track *t; - if ((at = _trackview.audio_track()) != 0) { - AudioDiskstream& ds = at->audio_diskstream(); + if ((t = _trackview.track()) != 0) { + Diskstream& ds = t->diskstream(); /* XXX grrr: when will SigC++ allow me to bind references? */ Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun (*this, &StreamView::display_diskstream), &ds)); } else { @@ -513,7 +278,7 @@ void StreamView::apply_color (Gdk::Color& color, ColorTarget target) { - list<AudioRegionView *>::iterator i; + list<RegionView *>::iterator i; switch (target) { case RegionColor: @@ -533,64 +298,7 @@ StreamView::apply_color (Gdk::Color& color, ColorTarget target) } void -StreamView::set_show_waveforms (bool yn) -{ - for (list<AudioRegionView *>::iterator i = region_views.begin(); i != region_views.end(); ++i) { - (*i)->set_waveform_visible (yn); - } -} - -void -StreamView::set_selected_regionviews (AudioRegionSelection& regions) -{ - bool selected; - - // cerr << _trackview.name() << " (selected = " << regions.size() << ")" << endl; - for (list<AudioRegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) { - - selected = false; - - for (AudioRegionSelection::iterator ii = regions.begin(); ii != regions.end(); ++ii) { - if (*i == *ii) { - selected = true; - } - } - - // cerr << "\tregion " << (*i)->region.name() << " selected = " << selected << endl; - (*i)->set_selected (selected); - } -} - -void -StreamView::get_selectables (jack_nframes_t start, jack_nframes_t end, list<Selectable*>& results) -{ - for (list<AudioRegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) { - if ((*i)->region.coverage(start, end) != OverlapNone) { - results.push_back (*i); - } - } -} - -void -StreamView::get_inverted_selectables (Selection& sel, list<Selectable*>& results) -{ - for (list<AudioRegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) { - if (!sel.audio_regions.contains (*i)) { - results.push_back (*i); - } - } -} - -void -StreamView::set_waveform_shape (WaveformShape shape) -{ - for (AudioRegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) { - (*i)->set_waveform_shape (shape); - } -} - -void -StreamView::region_layered (AudioRegionView* rv) +StreamView::region_layered (RegionView* rv) { rv->get_canvas_group()->lower_to_bottom(); @@ -598,7 +306,7 @@ StreamView::region_layered (AudioRegionView* rv) get events - the parent group does instead ... */ - rv->get_canvas_group()->raise (rv->region.layer() + 1); + rv->get_canvas_group()->raise (rv->region().layer() + 1); } void @@ -620,161 +328,6 @@ StreamView::transport_changed() } void -StreamView::setup_rec_box () -{ - // cerr << _trackview.name() << " streamview SRB\n"; - - if (_trackview.session().transport_rolling()) { - - // cerr << "\trolling\n"; - - if (!rec_active && - _trackview.session().record_status() == Session::Recording && - _trackview.get_diskstream()->record_enabled()) { - - if (_trackview.audio_track()->mode() == Normal && use_rec_regions && rec_regions.size() == rec_rects.size()) { - - /* add a new region, but don't bother if they set use_rec_regions mid-record */ - - AudioRegion::SourceList sources; - - for (list<sigc::connection>::iterator prc = peak_ready_connections.begin(); prc != peak_ready_connections.end(); ++prc) { - (*prc).disconnect(); - } - peak_ready_connections.clear(); - - for (uint32_t n=0; n < _trackview.get_diskstream()->n_channels(); ++n) { - AudioSource *src = (AudioSource *) _trackview.get_diskstream()->write_source (n); - if (src) { - sources.push_back (src); - peak_ready_connections.push_back (src->PeakRangeReady.connect (bind (mem_fun (*this, &StreamView::rec_peak_range_ready), src))); - } - } - - // handle multi - - jack_nframes_t start = 0; - if (rec_regions.size() > 0) { - start = rec_regions.back()->start() + _trackview.get_diskstream()->get_captured_frames(rec_regions.size()-1); - } - - AudioRegion * region = new AudioRegion(sources, start, 1 , "", 0, (Region::Flag)(Region::DefaultFlags | Region::DoNotSaveState), false); - region->set_position (_trackview.session().transport_frame(), this); - rec_regions.push_back (region); - /* catch it if it goes away */ - region->GoingAway.connect (mem_fun (*this, &StreamView::remove_rec_region)); - - /* we add the region later */ - } - - /* start a new rec box */ - - AudioTrack* at; - - at = _trackview.audio_track(); /* we know what it is already */ - AudioDiskstream& ds = at->audio_diskstream(); - jack_nframes_t frame_pos = ds.current_capture_start (); - gdouble xstart = _trackview.editor.frame_to_pixel (frame_pos); - gdouble xend; - uint32_t fill_color; - - switch (_trackview.audio_track()->mode()) { - case Normal: - xend = xstart; - fill_color = color_map[cRecordingRectFill]; - break; - - case Destructive: - xend = xstart + 2; - fill_color = color_map[cRecordingRectFill]; - /* make the recording rect translucent to allow - the user to see the peak data coming in, etc. - */ - fill_color = UINT_RGBA_CHANGE_A (fill_color, 120); - break; - } - - ArdourCanvas::SimpleRect * rec_rect = new Gnome::Canvas::SimpleRect (*canvas_group); - rec_rect->property_x1() = xstart; - rec_rect->property_y1() = 1.0; - rec_rect->property_x2() = xend; - rec_rect->property_y2() = (double) _trackview.height - 1; - rec_rect->property_outline_color_rgba() = color_map[cRecordingRectOutline]; - rec_rect->property_fill_color_rgba() = fill_color; - - RecBoxInfo recbox; - recbox.rectangle = rec_rect; - recbox.start = _trackview.session().transport_frame(); - recbox.length = 0; - - rec_rects.push_back (recbox); - - screen_update_connection.disconnect(); - screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (mem_fun (*this, &StreamView::update_rec_box)); - rec_updating = true; - rec_active = true; - - } else if (rec_active && - (_trackview.session().record_status() != Session::Recording || - !_trackview.get_diskstream()->record_enabled())) { - - screen_update_connection.disconnect(); - rec_active = false; - rec_updating = false; - - } - - } else { - - // cerr << "\tNOT rolling, rec_rects = " << rec_rects.size() << " rec_regions = " << rec_regions.size() << endl; - - if (!rec_rects.empty() || !rec_regions.empty()) { - - /* disconnect rapid update */ - screen_update_connection.disconnect(); - - for (list<sigc::connection>::iterator prc = peak_ready_connections.begin(); prc != peak_ready_connections.end(); ++prc) { - (*prc).disconnect(); - } - peak_ready_connections.clear(); - - rec_updating = false; - rec_active = false; - last_rec_peak_frame = 0; - - /* remove temp regions */ - for (list<AudioRegion*>::iterator iter=rec_regions.begin(); iter != rec_regions.end(); ) - { - list<AudioRegion*>::iterator tmp; - - tmp = iter; - ++tmp; - - /* this will trigger the remove_region_view */ - delete *iter; - - iter = tmp; - } - - rec_regions.clear(); - - // cerr << "\tclear " << rec_rects.size() << " rec rects\n"; - - - /* transport stopped, clear boxes */ - for (vector<RecBoxInfo>::iterator iter=rec_rects.begin(); iter != rec_rects.end(); ++iter) { - RecBoxInfo &rect = (*iter); - delete rect.rectangle; - } - - rec_rects.clear(); - - } - } -} - - -void StreamView::update_rec_box () { if (rec_active && rec_rects.size() > 0) { @@ -784,7 +337,7 @@ StreamView::update_rec_box () double xstart; double xend; - switch (_trackview.audio_track()->mode()) { + switch (_trackview.track()->mode()) { case Normal: rect.length = at - rect.start; xstart = _trackview.editor.frame_to_pixel (rect.start); @@ -803,12 +356,12 @@ StreamView::update_rec_box () } } -AudioRegionView* -StreamView::find_view (const AudioRegion& region) +RegionView* +StreamView::find_view (const Region& region) { - for (list<AudioRegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) { + for (list<RegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) { - if (&(*i)->region == ®ion) { + if (&(*i)->region() == ®ion) { return *i; } } @@ -816,172 +369,51 @@ StreamView::find_view (const AudioRegion& region) } void -StreamView::foreach_regionview (sigc::slot<void,AudioRegionView*> slot) +StreamView::foreach_regionview (sigc::slot<void,RegionView*> slot) { - for (list<AudioRegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) { + for (list<RegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) { slot (*i); } } void -StreamView::foreach_crossfadeview (void (CrossfadeView::*pmf)(void)) +StreamView::set_selected_regionviews (RegionSelection& regions) { - for (list<CrossfadeView*>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) { - ((*i)->*pmf) (); - } -} - -void -StreamView::rec_peak_range_ready (jack_nframes_t start, jack_nframes_t cnt, Source * src) -{ - // this is called from the peak building thread - - ENSURE_GUI_THREAD(bind (mem_fun (*this, &StreamView::rec_peak_range_ready), start, cnt, src)); - - if (rec_peak_ready_map.size() == 0 || start+cnt > last_rec_peak_frame) { - last_rec_peak_frame = start + cnt; - } - - rec_peak_ready_map[src] = true; - - if (rec_peak_ready_map.size() == _trackview.get_diskstream()->n_channels()) { - this->update_rec_regions (); - rec_peak_ready_map.clear(); - } -} - -void -StreamView::update_rec_regions () -{ - if (use_rec_regions) { - - uint32_t n = 0; - - for (list<AudioRegion*>::iterator iter = rec_regions.begin(); iter != rec_regions.end(); n++) { - - list<AudioRegion*>::iterator tmp; - - tmp = iter; - ++tmp; - - if (!canvas_item_visible (rec_rects[n].rectangle)) { - /* rect already hidden, this region is done */ - iter = tmp; - continue; - } - - AudioRegion * region = (*iter); - jack_nframes_t origlen = region->length(); - - if (region == rec_regions.back() && rec_active) { - - if (last_rec_peak_frame > region->start()) { - - jack_nframes_t nlen = last_rec_peak_frame - region->start(); - - if (nlen != region->length()) { - - region->freeze (); - region->set_position (_trackview.get_diskstream()->get_capture_start_frame(n), this); - region->set_length (nlen, this); - region->thaw ("updated"); - - if (origlen == 1) { - /* our special initial length */ - add_region_view_internal (region, false); - } - - /* also update rect */ - ArdourCanvas::SimpleRect * rect = rec_rects[n].rectangle; - gdouble xend = _trackview.editor.frame_to_pixel (region->position() + region->length()); - rect->property_x2() = xend; - } - } - - } else { - - jack_nframes_t nlen = _trackview.get_diskstream()->get_captured_frames(n); - - if (nlen != region->length()) { - - if (region->source(0).length() >= region->start() + nlen) { - - region->freeze (); - region->set_position (_trackview.get_diskstream()->get_capture_start_frame(n), this); - region->set_length (nlen, this); - region->thaw ("updated"); - - if (origlen == 1) { - /* our special initial length */ - add_region_view_internal (region, false); - } - - /* also hide rect */ - ArdourCanvas::Item * rect = rec_rects[n].rectangle; - rect->hide(); + bool selected; - } - } + // cerr << _trackview.name() << " (selected = " << regions.size() << ")" << endl; + for (list<RegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) { + + selected = false; + + for (RegionSelection::iterator ii = regions.begin(); ii != regions.end(); ++ii) { + if (*i == *ii) { + selected = true; } - - iter = tmp; } + + // cerr << "\tregion " << (*i)->region().name() << " selected = " << selected << endl; + (*i)->set_selected (selected); } } void -StreamView::show_all_xfades () -{ - foreach_crossfadeview (&CrossfadeView::show); - crossfades_visible = true; -} - -void -StreamView::hide_all_xfades () -{ - foreach_crossfadeview (&CrossfadeView::hide); - crossfades_visible = false; -} - -void -StreamView::hide_xfades_involving (AudioRegionView& rv) +StreamView::get_selectables (jack_nframes_t start, jack_nframes_t end, list<Selectable*>& results) { - for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) { - if ((*i)->crossfade.involves (rv.region)) { - (*i)->fake_hide (); + for (list<RegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) { + if ((*i)->region().coverage(start, end) != OverlapNone) { + results.push_back (*i); } } } void -StreamView::reveal_xfades_involving (AudioRegionView& rv) +StreamView::get_inverted_selectables (Selection& sel, list<Selectable*>& results) { - for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) { - if ((*i)->crossfade.involves (rv.region) && (*i)->visible()) { - (*i)->show (); + for (list<RegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) { + if (!sel.regions.contains (*i)) { + results.push_back (*i); } } } -void -StreamView::color_handler (ColorID id, uint32_t val) -{ - switch (id) { - case cAudioTrackBase: - if (_trackview.is_audio_track()) { - canvas_rect->property_fill_color_rgba() = val; - } - break; - case cAudioBusBase: - if (!_trackview.is_audio_track()) { - canvas_rect->property_fill_color_rgba() = val; - } - break; - case cAudioTrackOutline: - canvas_rect->property_outline_color_rgba() = val; - break; - - default: - break; - } -} diff --git a/gtk2_ardour/streamview.h b/gtk2_ardour/streamview.h index 00ec2d93f2..f2906d40c4 100644 --- a/gtk2_ardour/streamview.h +++ b/gtk2_ardour/streamview.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2001 Paul Davis + Copyright (C) 2001, 2006 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -14,8 +14,6 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id$ */ #ifndef __ardour_streamview_h__ @@ -37,141 +35,117 @@ namespace Gdk { namespace ARDOUR { class Route; - class AudioDiskstream; + class Diskstream; class Crossfade; class PeakData; - class AudioRegion; + class Region; class Source; } struct RecBoxInfo { - ArdourCanvas::SimpleRect* rectangle; - jack_nframes_t start; - jack_nframes_t length; + ArdourCanvas::SimpleRect* rectangle; + jack_nframes_t start; + jack_nframes_t length; }; class PublicEditor; class Selectable; -class AudioTimeAxisView; -class AudioRegionView; -class AudioRegionSelection; +class RouteTimeAxisView; +class RegionView; +class RegionSelection; class CrossfadeView; class Selection; class StreamView : public sigc::trackable { - public: - StreamView (AudioTimeAxisView&); - ~StreamView (); +public: + virtual ~StreamView (); - void set_waveform_shape (WaveformShape); + RouteTimeAxisView& trackview() { return _trackview; } - AudioTimeAxisView& trackview() { return _trackview; } + void attach (); void set_zoom_all(); - int set_height (gdouble); int set_position (gdouble x, gdouble y); + virtual int set_height (gdouble); - int set_samples_per_unit (gdouble spp); - gdouble get_samples_per_unit () { return _samples_per_unit; } - - int set_amplitude_above_axis (gdouble app); - gdouble get_amplitude_above_axis () { return _amplitude_above_axis; } - - void set_show_waveforms (bool yn); - void set_show_waveforms_recording (bool yn) { use_rec_regions = yn; } + virtual int set_samples_per_unit (gdouble spp); + gdouble get_samples_per_unit () { return _samples_per_unit; } ArdourCanvas::Item* canvas_item() { return canvas_group; } - sigc::signal<void,AudioRegionView*> AudioRegionViewAdded; - enum ColorTarget { RegionColor, StreamBaseColor }; - void apply_color (Gdk::Color&, ColorTarget t); - void set_selected_regionviews (AudioRegionSelection&); - void get_selectables (jack_nframes_t start, jack_nframes_t end, list<Selectable* >&); - void get_inverted_selectables (Selection&, list<Selectable* >& results); Gdk::Color get_region_color () const { return region_color; } + void apply_color (Gdk::Color&, ColorTarget t); - void foreach_regionview (sigc::slot<void,AudioRegionView*> slot); - void foreach_crossfadeview (void (CrossfadeView::*pmf)(void)); - - void attach (); - - void region_layered (AudioRegionView*); - - AudioRegionView* find_view (const ARDOUR::AudioRegion&); - - void show_all_xfades (); - void hide_all_xfades (); - void hide_xfades_involving (AudioRegionView&); - void reveal_xfades_involving (AudioRegionView&); - - private: - AudioTimeAxisView& _trackview; - - ArdourCanvas::Group* canvas_group; - ArdourCanvas::SimpleRect* canvas_rect; /* frame around the whole thing */ + RegionView* find_view (const ARDOUR::Region&); + void foreach_regionview (sigc::slot<void,RegionView*> slot); - typedef list<AudioRegionView* > AudioRegionViewList; - AudioRegionViewList region_views; + void set_selected_regionviews (RegionSelection&); + void get_selectables (jack_nframes_t start, jack_nframes_t end, list<Selectable* >&); + void get_inverted_selectables (Selection&, list<Selectable* >& results); - typedef list<CrossfadeView*> CrossfadeViewList; - CrossfadeViewList crossfade_views; + void add_region_view (ARDOUR::Region*); + void region_layered (RegionView*); + + sigc::signal<void,RegionView*> RegionViewAdded; - double _samples_per_unit; - double _amplitude_above_axis; - - sigc::connection screen_update_connection; - vector<RecBoxInfo> rec_rects; - list<ARDOUR::AudioRegion* > rec_regions; - bool rec_updating; - bool rec_active; - bool use_rec_regions; - list<sigc::connection> peak_ready_connections; - jack_nframes_t last_rec_peak_frame; - map<ARDOUR::Source*, bool> rec_peak_ready_map; +protected: + StreamView (RouteTimeAxisView&); +//private: void update_rec_box (); void transport_changed(); void rec_enable_changed(void* src = 0); void sess_rec_enable_changed(); - void setup_rec_box (); + virtual void setup_rec_box () = 0; void rec_peak_range_ready (jack_nframes_t start, jack_nframes_t cnt, ARDOUR::Source* src); - void update_rec_regions (); + virtual void update_rec_regions () = 0; - void add_region_view (ARDOUR::Region*); - void add_region_view_internal (ARDOUR::Region*, bool wait_for_waves); - void remove_region_view (ARDOUR::Region* ); + virtual void add_region_view_internal (ARDOUR::Region*, bool wait_for_waves) = 0; + virtual void remove_region_view (ARDOUR::Region* ); void remove_rec_region (ARDOUR::Region*); - void remove_audio_region_view (ARDOUR::AudioRegion* ); - void remove_audio_rec_region (ARDOUR::AudioRegion*); - void display_diskstream (ARDOUR::AudioDiskstream* ); - void undisplay_diskstream (); - void redisplay_diskstream (); + void display_diskstream (ARDOUR::Diskstream* ); + virtual void undisplay_diskstream (); + virtual void redisplay_diskstream () = 0; void diskstream_changed (void* ); void playlist_state_changed (ARDOUR::Change); - void playlist_changed (ARDOUR::AudioDiskstream* ); - void playlist_modified (); + virtual void playlist_changed (ARDOUR::Diskstream* ); + virtual void playlist_modified (); - bool crossfades_visible; - void add_crossfade (ARDOUR::Crossfade*); - void remove_crossfade (ARDOUR::Crossfade*); - /* XXX why are these different? */ + RouteTimeAxisView& _trackview; + + ArdourCanvas::Group* canvas_group; + ArdourCanvas::SimpleRect* canvas_rect; /* frame around the whole thing */ + + typedef list<RegionView* > RegionViewList; + RegionViewList region_views; + + double _samples_per_unit; + + sigc::connection screen_update_connection; + vector<RecBoxInfo> rec_rects; + list<ARDOUR::Region* > rec_regions; + bool rec_updating; + bool rec_active; + bool use_rec_regions; + /* XXX why are these different? */ Gdk::Color region_color; - uint32_t stream_base_color; + uint32_t stream_base_color; - void color_handler (ColorID, uint32_t); + virtual void color_handler (ColorID, uint32_t) = 0; vector<sigc::connection> playlist_connections; - sigc::connection playlist_change_connection; + sigc::connection playlist_change_connection; }; #endif /* __ardour_streamview_h__ */ + diff --git a/gtk2_ardour/taperegionview.cc b/gtk2_ardour/taperegionview.cc index 228e45a9d5..76fd91337e 100644 --- a/gtk2_ardour/taperegionview.cc +++ b/gtk2_ardour/taperegionview.cc @@ -42,12 +42,14 @@ using namespace PBD; using namespace Editing; using namespace ArdourCanvas; -const TimeAxisViewItem::Visibility TapeAudioRegionView::default_tape_visibility = TimeAxisViewItem::Visibility (TimeAxisViewItem::ShowNameHighlight| - TimeAxisViewItem::ShowFrame| - TimeAxisViewItem::HideFrameRight| - TimeAxisViewItem::FullWidthNameHighlight); - -TapeAudioRegionView::TapeAudioRegionView (ArdourCanvas::Group *parent, AudioTimeAxisView &tv, +const TimeAxisViewItem::Visibility TapeAudioRegionView::default_tape_visibility + = TimeAxisViewItem::Visibility ( + TimeAxisViewItem::ShowNameHighlight | + TimeAxisViewItem::ShowFrame | + TimeAxisViewItem::HideFrameRight | + TimeAxisViewItem::FullWidthNameHighlight); + +TapeAudioRegionView::TapeAudioRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &tv, AudioRegion& r, double spu, Gdk::Color& basic_color) @@ -59,21 +61,21 @@ TapeAudioRegionView::TapeAudioRegionView (ArdourCanvas::Group *parent, AudioTime } void -TapeAudioRegionView::init (double amplitude_above_axis, Gdk::Color& basic_color, bool wfw) +TapeAudioRegionView::init (Gdk::Color& basic_color, bool wfw) { XMLNode *node; editor = 0; valid = true; in_destructor = false; - _amplitude_above_axis = amplitude_above_axis; + _amplitude_above_axis = 1.0; zero_line = 0; wait_for_waves = wfw; _height = 0; _flags = 0; - if ((node = region.extra_xml ("GUI")) != 0) { + if ((node = _region.extra_xml ("GUI")) != 0) { set_flags (node); } else { _flags = WaveformVisible; @@ -91,7 +93,7 @@ TapeAudioRegionView::init (double amplitude_above_axis, Gdk::Color& basic_color, name_highlight->set_data ("regionview", this); - reset_width_dependent_items ((double) region.length() / samples_per_unit); + reset_width_dependent_items ((double) _region.length() / samples_per_unit); set_height (trackview.height); @@ -109,8 +111,8 @@ TapeAudioRegionView::init (double amplitude_above_axis, Gdk::Color& basic_color, /* every time the wave data changes and peaks are ready, redraw */ - for (uint32_t n = 0; n < region.n_channels(); ++n) { - region.source(n).PeaksReady.connect (bind (mem_fun(*this, &TapeAudioRegionView::update), n)); + for (uint32_t n = 0; n < audio_region().n_channels(); ++n) { + audio_region().source(n).PeaksReady.connect (bind (mem_fun(*this, &TapeAudioRegionView::update), n)); } } @@ -132,7 +134,7 @@ TapeAudioRegionView::update (uint32_t n) /* this triggers a cache invalidation and redraw in the waveview */ - waves[n]->property_data_src() = ®ion; + waves[n]->property_data_src() = &_region; } void diff --git a/gtk2_ardour/taperegionview.h b/gtk2_ardour/taperegionview.h index 6b4a57fc97..c16e7a6916 100644 --- a/gtk2_ardour/taperegionview.h +++ b/gtk2_ardour/taperegionview.h @@ -23,20 +23,20 @@ #include <vector> -#include "regionview.h" +#include "audio_regionview.h" class TapeAudioRegionView : public AudioRegionView { public: TapeAudioRegionView (ArdourCanvas::Group *, - AudioTimeAxisView&, + RouteTimeAxisView&, ARDOUR::AudioRegion&, double initial_samples_per_unit, Gdk::Color& base_color); ~TapeAudioRegionView (); protected: - void init (double amplitude_above_axis, Gdk::Color& base_color, bool wait_for_waves); + void init (Gdk::Color& base_color, bool wait_for_waves); void set_frame_color (); void update (uint32_t n); diff --git a/gtk2_ardour/time_axis_view.cc b/gtk2_ardour/time_axis_view.cc index 89ff372140..842d4046d8 100644 --- a/gtk2_ardour/time_axis_view.cc +++ b/gtk2_ardour/time_axis_view.cc @@ -1033,3 +1033,4 @@ TimeAxisView::color_handler (ColorID id, uint32_t val) break; } } + diff --git a/gtk2_ardour/time_axis_view.h b/gtk2_ardour/time_axis_view.h index c607c78166..3eae76a802 100644 --- a/gtk2_ardour/time_axis_view.h +++ b/gtk2_ardour/time_axis_view.h @@ -54,19 +54,17 @@ namespace Gtk { } class PublicEditor; -class AudioRegionSelection; +class RegionSelection; class TimeSelection; class PointSelection; class TimeAxisViewItem; class Selection; class Selectable; -/** - * TimeAxisView defines the abstract base class for time-axis views. +/** Abstract base class for time-axis views (horizontal editor 'strips') * * This class provides the basic LHS controls and display methods. This should be * extended to create functional time-axis based views. - * */ class TimeAxisView : public virtual AxisView { @@ -103,13 +101,13 @@ class TimeAxisView : public virtual AxisView PublicEditor& editor; TrackHeight height_style; - uint32_t height; /* in canvas units */ - uint32_t effective_height; /* in canvas units */ - double y_position; - int order; + uint32_t height; /* in canvas units */ + uint32_t effective_height; /* in canvas units */ + double y_position; + int order; - ArdourCanvas::Group *canvas_display; - Gtk::VBox *control_parent; + ArdourCanvas::Group *canvas_display; + Gtk::VBox *control_parent; /* The Standard LHS Controls */ Gtk::Frame controls_frame; @@ -121,14 +119,13 @@ class TimeAxisView : public virtual AxisView Gtk::HBox name_hbox; Gtk::Frame name_frame; Gtk::Entry name_entry; - + void hide_name_label (); void hide_name_entry (); void show_name_label (); void show_name_entry (); - /** - * Display this TrackView as the nth component of the parent box, at y. + /** Display this TrackView as the nth component of the parent box, at y. * * @param y * @param nth @@ -139,9 +136,7 @@ class TimeAxisView : public virtual AxisView bool touched (double top, double bot); - /** - * Hides this TrackView - */ + /** Hides this TrackView */ virtual void hide (); bool hidden() const { return _hidden; } @@ -157,8 +152,7 @@ class TimeAxisView : public virtual AxisView virtual void set_height (TrackHeight h); void reset_height(); - /** - * Steps through the defined heights for this TrackView. + /** Steps through the defined heights for this TrackView. * Sets bigger to true to step up in size, set to fals eot step smaller. * * @param bigger true if stepping should increase in size, false otherwise @@ -183,7 +177,7 @@ class TimeAxisView : public virtual AxisView virtual bool cut_copy_clear (Selection&, Editing::CutCopyOp) { return false; } virtual bool paste (jack_nframes_t, float times, Selection&, size_t nth) { return false; } - virtual void set_selected_regionviews (AudioRegionSelection&) {} + virtual void set_selected_regionviews (RegionSelection&) {} virtual void set_selected_points (PointSelection&) {} virtual ARDOUR::Region* find_next_region (jack_nframes_t pos, ARDOUR::RegionPoint, int32_t dir) { @@ -226,49 +220,39 @@ class TimeAxisView : public virtual AxisView virtual bool name_entry_focus_in (GdkEventFocus *ev); virtual bool name_entry_focus_out (GdkEventFocus *ev); - /** - * Handle mouse relaese on our LHS control name ebox. + /** Handle mouse relaese on our LHS control name ebox. * *@ param ev the event */ virtual bool controls_ebox_button_release (GdkEventButton *ev); virtual bool controls_ebox_scroll (GdkEventScroll *ev); - /** - * Displays the standard LHS control menu at when. + /** Display the standard LHS control menu at when. * * @param when the popup activation time */ virtual void popup_display_menu (guint32 when); - /** - * Build the standard LHS control menu. + /** Build the standard LHS control menu. * Subclasses should extend this method to add their own menu options. - * */ virtual void build_display_menu (); - /** - * Do anything that needs to be done to dynamically reset - * the LHS control menu. + /** Do whatever needs to be done to dynamically reset the LHS control menu. */ virtual bool handle_display_menu_map_event (GdkEventAny *ev) { return false; } - /** - * Build the standard LHS control size menu for the default heights options. - * + /** Build the standard LHS control size menu for the default heights options. */ virtual void build_size_menu(); - /** - * Displays the standard LHS controls size menu for the track heights + /** Displays the standard LHS controls size menu for the track heights * - * @parem when the popup activation time + * @param when the popup activation time */ void popup_size_menu(guint32 when); - /** - * Handle the size option of out main menu. + /** Handle the size option of our main menu. * * @param ev the event */ @@ -283,8 +267,7 @@ class TimeAxisView : public virtual AxisView TimeAxisView* parent; - /* find the parent with state */ - + /** Find the parent with state */ TimeAxisView* get_parent_with_state(); std::vector<TimeAxisView*> children; diff --git a/gtk2_ardour/visual_time_axis.cc b/gtk2_ardour/visual_time_axis.cc index c27ed33089..e44ea4011e 100644 --- a/gtk2_ardour/visual_time_axis.cc +++ b/gtk2_ardour/visual_time_axis.cc @@ -255,7 +255,7 @@ VisualTimeAxis::set_time_axis_color(Gdk::Color c) } void -VisualTimeAxis::set_selected_regionviews (AudioRegionSelection& regions) +VisualTimeAxis::set_selected_regionviews (RegionSelection& regions) { // Not handled by purely visual TimeAxis } diff --git a/gtk2_ardour/visual_time_axis.h b/gtk2_ardour/visual_time_axis.h index 4be2da3b9a..c68ce8da1c 100644 --- a/gtk2_ardour/visual_time_axis.h +++ b/gtk2_ardour/visual_time_axis.h @@ -42,7 +42,7 @@ class ImageFrameView; class ImageFrameTimeAxisView; class MarkersTimeAxisView; class TimeSelection; -class AudioRegionSelection; +class RegionSelection; class MarkerTimeAxis; class TimeAxisViewStrip; @@ -105,7 +105,7 @@ class VisualTimeAxis : public TimeAxisView /** * Not implemented */ - virtual void set_selected_regionviews(AudioRegionSelection&) ; + virtual void set_selected_regionviews(RegionSelection&) ; //---------------------------------------------------------------------------------// diff --git a/libs/ardour/ardour/audioplaylist.h b/libs/ardour/ardour/audioplaylist.h index 1b60cf185d..5a77067f8f 100644 --- a/libs/ardour/ardour/audioplaylist.h +++ b/libs/ardour/ardour/audioplaylist.h @@ -77,9 +77,6 @@ class AudioPlaylist : public ARDOUR::Playlist bool destroy_region (Region*); - void get_equivalent_regions (const AudioRegion&, std::vector<AudioRegion*>&); - void get_region_list_equivalent_regions (const AudioRegion&, std::vector<AudioRegion*>&); - void drop_all_states (); protected: diff --git a/libs/ardour/ardour/audioregion.h b/libs/ardour/ardour/audioregion.h index 009aa4b5b0..f3d34eb262 100644 --- a/libs/ardour/ardour/audioregion.h +++ b/libs/ardour/ardour/audioregion.h @@ -75,11 +75,7 @@ class AudioRegion : public Region AudioRegion (SourceList &, const XMLNode&); ~AudioRegion(); - bool region_list_equivalent (const AudioRegion&) const ; - bool source_equivalent (const AudioRegion&) const; - bool equivalent (const AudioRegion&) const; - bool size_equivalent (const AudioRegion&) const; - bool overlap_equivalent (const AudioRegion&) const; + bool source_equivalent (const Region&) const; bool speed_mismatch (float) const; diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h index f696295b58..6cff58eef8 100644 --- a/libs/ardour/ardour/io.h +++ b/libs/ardour/ardour/io.h @@ -81,6 +81,8 @@ class IO : public Stateful, public ARDOUR::StateManager void set_output_minimum (int n); void set_output_maximum (int n); + Buffer::Type default_type() const { return _default_type; } + const string& name() const { return _name; } virtual int set_name (string str, void *src); diff --git a/libs/ardour/ardour/midi_region.h b/libs/ardour/ardour/midi_region.h index e4d8f48c6e..1371162b14 100644 --- a/libs/ardour/ardour/midi_region.h +++ b/libs/ardour/ardour/midi_region.h @@ -59,11 +59,7 @@ class MidiRegion : public Region MidiRegion (SourceList &, const XMLNode&); ~MidiRegion(); - bool region_list_equivalent (const MidiRegion&) const ; - bool source_equivalent (const MidiRegion&) const; - bool equivalent (const MidiRegion&) const; - bool size_equivalent (const MidiRegion&) const; - bool overlap_equivalent (const MidiRegion&) const; + bool source_equivalent (const Region&) const; bool speed_mismatch (float) const; diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h index 69b6a1fbc3..ca760a5ad5 100644 --- a/libs/ardour/ardour/playlist.h +++ b/libs/ardour/ardour/playlist.h @@ -81,6 +81,8 @@ class Playlist : public Stateful, public StateManager { void add_region (const Region&, jack_nframes_t position, float times = 1, bool with_save = true); void remove_region (Region *); + void get_equivalent_regions (const Region&, std::vector<Region*>&); + void get_region_list_equivalent_regions (const Region&, std::vector<Region*>&); void replace_region (Region& old, Region& newr, jack_nframes_t pos); void split_region (Region&, jack_nframes_t position); void partition (jack_nframes_t start, jack_nframes_t end, bool just_top_level); diff --git a/libs/ardour/ardour/region.h b/libs/ardour/ardour/region.h index d58f98adca..68ac55df67 100644 --- a/libs/ardour/ardour/region.h +++ b/libs/ardour/ardour/region.h @@ -121,7 +121,7 @@ class Region : public Stateful, public StateManager bool hidden() const { return _flags & Hidden; } bool muted() const { return _flags & Muted; } bool opaque () const { return _flags & Opaque; } - bool envelope_active () const { return _flags & EnvelopeActive; } + //bool envelope_active () const { return _flags & EnvelopeActive; } bool locked() const { return _flags & Locked; } bool automatic() const { return _flags & Automatic; } bool whole_file() const { return _flags & WholeFile ; } @@ -139,6 +139,12 @@ class Region : public Stateful, public StateManager OverlapType coverage (jack_nframes_t start, jack_nframes_t end) const { return ARDOUR::coverage (_position, _position + _length - 1, start, end); } + + bool equivalent (const Region&) const; + bool size_equivalent (const Region&) const; + bool overlap_equivalent (const Region&) const; + bool region_list_equivalent (const Region&) const; + virtual bool source_equivalent (const Region&) const = 0; /*virtual jack_nframes_t read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, char * workbuf, jack_nframes_t position, jack_nframes_t cnt, @@ -173,7 +179,7 @@ class Region : public Stateful, public StateManager void set_hidden (bool yn); void set_muted (bool yn); void set_opaque (bool yn); - void set_envelope_active (bool yn); + //void set_envelope_active (bool yn); void set_locked (bool yn); virtual uint32_t read_data_count() const { return _read_data_count; } diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 3b1a0bef99..10cb554842 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -636,7 +636,7 @@ class Session : public sigc::trackable, public Stateful string path_from_region_name (string name, string identifier); AudioRegion* find_whole_file_parent (AudioRegion&); - void find_equivalent_playlist_regions (AudioRegion&, std::vector<AudioRegion*>& result); + void find_equivalent_playlist_regions (Region&, std::vector<Region*>& result); AudioRegion *XMLRegionFactory (const XMLNode&, bool full); diff --git a/libs/ardour/audio_playlist.cc b/libs/ardour/audio_playlist.cc index aa8940dce4..93d380679d 100644 --- a/libs/ardour/audio_playlist.cc +++ b/libs/ardour/audio_playlist.cc @@ -882,38 +882,6 @@ AudioPlaylist::crossfade_changed (Change ignored) notify_modified (); } -void -AudioPlaylist::get_equivalent_regions (const AudioRegion& other, vector<AudioRegion*>& results) -{ - for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) { - - AudioRegion* ar = dynamic_cast<AudioRegion*> (*i); - - if (ar) { - if (Config->get_use_overlap_equivalency()) { - if (ar->overlap_equivalent (other)) { - results.push_back (ar); - } else if (ar->equivalent (other)) { - results.push_back (ar); - } - } - } - } -} - -void -AudioPlaylist::get_region_list_equivalent_regions (const AudioRegion& other, vector<AudioRegion*>& results) -{ - for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) { - - AudioRegion* ar = dynamic_cast<AudioRegion*> (*i); - - if (ar && ar->region_list_equivalent (other)) { - results.push_back (ar); - } - } -} - bool AudioPlaylist::region_changed (Change what_changed, Region* region) { diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc index 4a8593cd63..b137229c36 100644 --- a/libs/ardour/audioregion.cc +++ b/libs/ardour/audioregion.cc @@ -1139,24 +1139,22 @@ AudioRegion::master_source_names () } bool -AudioRegion::region_list_equivalent (const AudioRegion& other) const +AudioRegion::source_equivalent (const Region& o) const { - return size_equivalent (other) && source_equivalent (other) && _name == other._name; -} + const AudioRegion* other = dynamic_cast<const AudioRegion*>(&o); + if (!other) + return false; -bool -AudioRegion::source_equivalent (const AudioRegion& other) const -{ SourceList::const_iterator i; SourceList::const_iterator io; - for (i = sources.begin(), io = other.sources.begin(); i != sources.end() && io != other.sources.end(); ++i, ++io) { + for (i = sources.begin(), io = other->sources.begin(); i != sources.end() && io != other->sources.end(); ++i, ++io) { if ((*i)->id() != (*io)->id()) { return false; } } - for (i = master_sources.begin(), io = other.master_sources.begin(); i != master_sources.end() && io != other.master_sources.end(); ++i, ++io) { + for (i = master_sources.begin(), io = other->master_sources.begin(); i != master_sources.end() && io != other->master_sources.end(); ++i, ++io) { if ((*i)->id() != (*io)->id()) { return false; } @@ -1165,27 +1163,6 @@ AudioRegion::source_equivalent (const AudioRegion& other) const return true; } -bool -AudioRegion::overlap_equivalent (const AudioRegion& other) const -{ - return coverage (other.first_frame(), other.last_frame()) != OverlapNone; -} - -bool -AudioRegion::equivalent (const AudioRegion& other) const -{ - return _start == other._start && - _position == other._position && - _length == other._length; -} - -bool -AudioRegion::size_equivalent (const AudioRegion& other) const -{ - return _start == other._start && - _length == other._length; -} - int AudioRegion::apply (AudioFilter& filter) { diff --git a/libs/ardour/midi_region.cc b/libs/ardour/midi_region.cc index 6fbb2e8923..d78506c1fc 100644 --- a/libs/ardour/midi_region.cc +++ b/libs/ardour/midi_region.cc @@ -501,24 +501,22 @@ MidiRegion::master_source_names () } bool -MidiRegion::region_list_equivalent (const MidiRegion& other) const +MidiRegion::source_equivalent (const Region& o) const { - return size_equivalent (other) && source_equivalent (other) && _name == other._name; -} + const MidiRegion* other = dynamic_cast<const MidiRegion*>(&o); + if (!other) + return false; -bool -MidiRegion::source_equivalent (const MidiRegion& other) const -{ SourceList::const_iterator i; SourceList::const_iterator io; - for (i = sources.begin(), io = other.sources.begin(); i != sources.end() && io != other.sources.end(); ++i, ++io) { + for (i = sources.begin(), io = other->sources.begin(); i != sources.end() && io != other->sources.end(); ++i, ++io) { if ((*i)->id() != (*io)->id()) { return false; } } - for (i = master_sources.begin(), io = other.master_sources.begin(); i != master_sources.end() && io != other.master_sources.end(); ++i, ++io) { + for (i = master_sources.begin(), io = other->master_sources.begin(); i != master_sources.end() && io != other->master_sources.end(); ++i, ++io) { if ((*i)->id() != (*io)->id()) { return false; } @@ -527,27 +525,6 @@ MidiRegion::source_equivalent (const MidiRegion& other) const return true; } -bool -MidiRegion::overlap_equivalent (const MidiRegion& other) const -{ - return coverage (other.first_frame(), other.last_frame()) != OverlapNone; -} - -bool -MidiRegion::equivalent (const MidiRegion& other) const -{ - return _start == other._start && - _position == other._position && - _length == other._length; -} - -bool -MidiRegion::size_equivalent (const MidiRegion& other) const -{ - return _start == other._start && - _length == other._length; -} - #if 0 int MidiRegion::exportme (Session& session, AudioExportSpecification& spec) diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc index fc1dd84066..6d5e8f7847 100644 --- a/libs/ardour/playlist.cc +++ b/libs/ardour/playlist.cc @@ -599,6 +599,31 @@ Playlist::remove_region_internal (Region *region, bool delay_sort) } void +Playlist::get_equivalent_regions (const Region& other, vector<Region*>& results) +{ + for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) { + if (Config->get_use_overlap_equivalency()) { + if ((*i)->overlap_equivalent (other)) { + results.push_back ((*i)); + } else if ((*i)->equivalent (other)) { + results.push_back ((*i)); + } + } + } +} + +void +Playlist::get_region_list_equivalent_regions (const Region& other, vector<Region*>& results) +{ + for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) { + + if ((*i) && (*i)->region_list_equivalent (other)) { + results.push_back (*i); + } + } +} + +void Playlist::partition (jack_nframes_t start, jack_nframes_t end, bool just_top_level) { RegionList thawlist; diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc index f195e42148..50d0033080 100644 --- a/libs/ardour/region.cc +++ b/libs/ardour/region.cc @@ -990,3 +990,30 @@ Region::set_last_layer_op (uint64_t when) { _last_layer_op = when; } + +bool +Region::overlap_equivalent (const Region& other) const +{ + return coverage (other.first_frame(), other.last_frame()) != OverlapNone; +} + +bool +Region::equivalent (const Region& other) const +{ + return _start == other._start && + _position == other._position && + _length == other._length; +} + +bool +Region::size_equivalent (const Region& other) const +{ + return _start == other._start && + _length == other._length; +} + +bool +Region::region_list_equivalent (const Region& other) const +{ + return size_equivalent (other) && source_equivalent (other) && _name == other._name; +} diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 30c9f77aac..0bdff5bd5c 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -2774,18 +2774,10 @@ Session::find_whole_file_parent (AudioRegion& child) } void -Session::find_equivalent_playlist_regions (AudioRegion& region, vector<AudioRegion*>& result) +Session::find_equivalent_playlist_regions (Region& region, vector<Region*>& result) { - for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) { - - AudioPlaylist* pl; - - if ((pl = dynamic_cast<AudioPlaylist*>(*i)) == 0) { - continue; - } - - pl->get_region_list_equivalent_regions (region, result); - } + for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) + (*i)->get_region_list_equivalent_regions (region, result); } int |