Heavy-duty abstraction work to split type-specific classes into
authorDavid Robillard <d@drobilla.net>
Tue, 1 Aug 2006 03:23:35 +0000 (03:23 +0000)
committerDavid Robillard <d@drobilla.net>
Tue, 1 Aug 2006 03:23:35 +0000 (03:23 +0000)
specializations of (new, for the most part) generic bases.  (eg. most everything
from the MIDI branch except for actual MIDI things, so merges have a chance of
succeeding).  Also the new edit toolbar, and various other cleanup things I did
along the way.

Should be functionally equivalent (except the toolbar), this is just design work.

She's a big'un....

git-svn-id: svn://localhost/ardour2/trunk@727 d708f5d6-7413-0410-9779-e7cbd77b26cf

112 files changed:
SConstruct
gtk2_ardour/SConscript
gtk2_ardour/analysis_window.cc
gtk2_ardour/ardour_ui.cc
gtk2_ardour/ardour_ui.h
gtk2_ardour/ardour_ui_dialogs.cc
gtk2_ardour/audio_region_editor.cc [new file with mode: 0644]
gtk2_ardour/audio_region_editor.h [new file with mode: 0644]
gtk2_ardour/audio_region_view.cc [new file with mode: 0644]
gtk2_ardour/audio_region_view.h [new file with mode: 0644]
gtk2_ardour/audio_regionview.cc [new file with mode: 0644]
gtk2_ardour/audio_streamview.cc [new file with mode: 0644]
gtk2_ardour/audio_streamview.h [new file with mode: 0644]
gtk2_ardour/audio_time_axis.cc
gtk2_ardour/audio_time_axis.h
gtk2_ardour/automation_time_axis.h
gtk2_ardour/crossfade_view.cc
gtk2_ardour/crossfade_view.h
gtk2_ardour/editor.cc
gtk2_ardour/editor.h
gtk2_ardour/editor_audio_import.cc
gtk2_ardour/editor_audiotrack.cc
gtk2_ardour/editor_canvas_events.cc
gtk2_ardour/editor_export_audio.cc
gtk2_ardour/editor_items.h
gtk2_ardour/editor_keyboard.cc
gtk2_ardour/editor_keys.cc
gtk2_ardour/editor_markers.cc
gtk2_ardour/editor_mixer.cc
gtk2_ardour/editor_mouse.cc
gtk2_ardour/editor_ops.cc
gtk2_ardour/editor_route_list.cc
gtk2_ardour/editor_timefx.cc
gtk2_ardour/export_region_dialog.cc
gtk2_ardour/export_region_dialog.h
gtk2_ardour/mixer_strip.cc
gtk2_ardour/mixer_strip.h
gtk2_ardour/pixmaps/tool_audition.xpm [new file with mode: 0644]
gtk2_ardour/pixmaps/tool_gain.xpm [new file with mode: 0644]
gtk2_ardour/pixmaps/tool_object.xpm [new file with mode: 0644]
gtk2_ardour/pixmaps/tool_range.xpm [new file with mode: 0644]
gtk2_ardour/pixmaps/tool_stretch.xpm [new file with mode: 0644]
gtk2_ardour/pixmaps/tool_zoom.xpm [new file with mode: 0644]
gtk2_ardour/pixmaps/zoom_full.xpm [new file with mode: 0644]
gtk2_ardour/pixmaps/zoom_in.xpm [new file with mode: 0644]
gtk2_ardour/pixmaps/zoom_out.xpm [new file with mode: 0644]
gtk2_ardour/playlist_selector.cc
gtk2_ardour/plugin_selector.h
gtk2_ardour/public_editor.h
gtk2_ardour/region_editor.cc [deleted file]
gtk2_ardour/region_editor.h [deleted file]
gtk2_ardour/region_gain_line.cc
gtk2_ardour/region_selection.cc
gtk2_ardour/region_selection.h
gtk2_ardour/region_view.cc [new file with mode: 0644]
gtk2_ardour/region_view.h [new file with mode: 0644]
gtk2_ardour/regionview.cc [deleted file]
gtk2_ardour/regionview.h [deleted file]
gtk2_ardour/route_time_axis.cc [new file with mode: 0644]
gtk2_ardour/route_time_axis.h [new file with mode: 0644]
gtk2_ardour/route_ui.cc
gtk2_ardour/route_ui.h
gtk2_ardour/selection.cc
gtk2_ardour/selection.h
gtk2_ardour/selection_templates.h
gtk2_ardour/streamview.cc
gtk2_ardour/streamview.h
gtk2_ardour/tape_region_view.cc [new file with mode: 0644]
gtk2_ardour/tape_region_view.h [new file with mode: 0644]
gtk2_ardour/taperegionview.cc [deleted file]
gtk2_ardour/taperegionview.h [deleted file]
gtk2_ardour/time_axis_view.h
gtk2_ardour/visual_time_axis.cc
gtk2_ardour/visual_time_axis.h
libs/ardour/SConscript
libs/ardour/ardour/audio_diskstream.h
libs/ardour/ardour/audio_track.h
libs/ardour/ardour/audioengine.h
libs/ardour/ardour/audioplaylist.h
libs/ardour/ardour/audioregion.h
libs/ardour/ardour/buffer.h [new file with mode: 0644]
libs/ardour/ardour/diskstream.h [new file with mode: 0644]
libs/ardour/ardour/io.h
libs/ardour/ardour/playlist.h
libs/ardour/ardour/port.h
libs/ardour/ardour/region.h
libs/ardour/ardour/route.h
libs/ardour/ardour/route_group.h
libs/ardour/ardour/route_group_specialized.h
libs/ardour/ardour/session.h
libs/ardour/ardour/session_diskstream.h [deleted file]
libs/ardour/ardour/track.h [new file with mode: 0644]
libs/ardour/ardour/types.h
libs/ardour/audio_diskstream.cc
libs/ardour/audio_playlist.cc
libs/ardour/audio_track.cc
libs/ardour/audioengine.cc
libs/ardour/audioregion.cc
libs/ardour/auditioner.cc
libs/ardour/diskstream.cc [new file with mode: 0644]
libs/ardour/io.cc
libs/ardour/playlist.cc
libs/ardour/port.cc
libs/ardour/region.cc
libs/ardour/route.cc
libs/ardour/session.cc
libs/ardour/session_butler.cc
libs/ardour/session_export.cc
libs/ardour/session_process.cc
libs/ardour/session_state.cc
libs/ardour/session_transport.cc
libs/ardour/track.cc [new file with mode: 0644]

index 7c441a8d87a1dd6c4bff0cd56a846d22bbd23d01..90c426300dad2f14cc1b6b5c31d59e6341a917cd 100644 (file)
@@ -539,7 +539,7 @@ if env['SYSLIBS']:
 
 #    libraries['flowcanvas'] = LibraryInfo(LIBS='flowcanvas', LIBPATH='#/libs/flowcanvas', CPPPATH='#libs/flowcanvas')
     libraries['soundtouch'] = LibraryInfo()
-    libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs soundtouch-1.0')
+    libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs libSoundTouch')
     
     coredirs = [
         'templates'
index c5409d7f8b0e3e88c5c7ff22cd6b4a5f0e84de67..43dd09cfb4d08ee0bc1b0104987c04e6b5428402 100644 (file)
@@ -75,6 +75,7 @@ ardour_ui_ed.cc
 ardour_ui_mixer.cc
 ardour_ui_options.cc
 audio_clock.cc
+route_time_axis.cc
 audio_time_axis.cc
 automation_gain_line.cc
 automation_line.cc
@@ -157,10 +158,11 @@ public_editor.cc
 redirect_automation_line.cc
 redirect_automation_time_axis.cc
 redirect_box.cc
-region_editor.cc
+audio_region_editor.cc
 region_gain_line.cc
 region_selection.cc
-regionview.cc
+region_view.cc
+audio_region_view.cc
 route_params_ui.cc
 route_redirect_selection.cc
 route_ui.cc
@@ -168,7 +170,8 @@ selection.cc
 sfdb_ui.cc
 send_ui.cc
 streamview.cc
-taperegionview.cc
+audio_streamview.cc
+tape_region_view.cc
 tempo_dialog.cc
 time_axis_view.cc
 time_axis_view_item.cc
index 8809c84e7abb477c4d39a7d97b485382600dfaaf..f742afd7274a9a66ee901236919c3962e75d198c 100644 (file)
@@ -26,7 +26,7 @@
 #include <gtkmm/treeiter.h>
 
 #include <ardour/audioregion.h>
-#include <ardour/playlist.h>
+#include <ardour/audioplaylist.h>
 #include <ardour/types.h>
 
 #include "analysis_window.h"
@@ -35,7 +35,7 @@
 #include "time_axis_view.h"
 #include "public_editor.h"
 #include "selection.h"
-#include "regionview.h"
+#include "audio_region_view.h"
 
 #include "i18n.h"
 
@@ -225,11 +225,16 @@ 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) {
-                       ARDOUR::Playlist *pl = (*i)->playlist();
+                       ARDOUR::AudioPlaylist *pl
+                               = dynamic_cast<ARDOUR::AudioPlaylist*>((*i)->playlist());
+
+                       if (!pl)
+                               continue;
+
                        RouteUI *rui = dynamic_cast<RouteUI *>(*i);
                        
                        // Busses don't have playlists, so we need to check that we actually are working with a playlist
@@ -274,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++) {
index c9116ac4e9eb243ebd4c46f848aff483a2b55e0d..201fc0988025b0d897c5c8aceea3335b0f17e06b 100644 (file)
@@ -46,6 +46,7 @@
 #include <midi++/mmc.h>
 
 #include <ardour/ardour.h>
+#include <ardour/session_route.h>
 #include <ardour/port.h>
 #include <ardour/audioengine.h>
 #include <ardour/playlist.h>
@@ -53,7 +54,6 @@
 #include <ardour/audio_diskstream.h>
 #include <ardour/audiofilesource.h>
 #include <ardour/recent_sessions.h>
-#include <ardour/session_diskstream.h>
 #include <ardour/port.h>
 #include <ardour/audio_track.h>
 
@@ -186,8 +186,8 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
        gettimeofday (&last_shuttle_request, 0);
 
        ARDOUR::AudioDiskstream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread));
-       ARDOUR::AudioDiskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
-       ARDOUR::AudioDiskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
+       ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
+       ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
 
        /* handle pending state with a dialog */
 
@@ -543,9 +543,10 @@ ARDOUR_UI::update_buffer_load ()
 }
 
 void
-ARDOUR_UI::count_recenabled_diskstreams (AudioDiskstream& ds)
+ARDOUR_UI::count_recenabled_diskstreams (Route& route)
 {
-       if (ds.record_enabled()) {
+       Track* track = dynamic_cast<Track*>(&route);
+       if (track && track->diskstream().record_enabled()) {
                rec_enabled_diskstreams++;
        }
 }
@@ -571,7 +572,7 @@ ARDOUR_UI::update_disk_space()
                if (session->actively_recording()){
                        
                        rec_enabled_diskstreams = 0;
-                       session->foreach_audio_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
+                       session->foreach_route (this, &ARDOUR_UI::count_recenabled_diskstreams);
                        
                        if (rec_enabled_diskstreams) {
                                frames /= rec_enabled_diskstreams;
@@ -918,7 +919,7 @@ restart JACK with more ports."));
 }
 
 void
-ARDOUR_UI::diskstream_added (AudioDiskstream* ds)
+ARDOUR_UI::diskstream_added (Diskstream* ds)
 {
 }
 
@@ -1169,12 +1170,15 @@ ARDOUR_UI::toggle_record_enable (uint32_t dstream)
        
        if ((r = session->route_by_remote_id (dstream)) != 0) {
 
-               AudioTrack* at;
+               Track* t;
 
-               if ((at = dynamic_cast<AudioTrack*>(r.get())) != 0) {
-                       at->disk_stream().set_record_enabled (!at->disk_stream().record_enabled(), this);
+               if ((t = dynamic_cast<Track*>(r.get())) != 0) {
+                       t->diskstream().set_record_enabled (!t->diskstream().record_enabled());
                }
        }
+       if (session == 0) {
+               return;
+       }
 }
 
 void
@@ -2150,11 +2154,11 @@ ARDOUR_UI::halt_on_xrun_message ()
 }
 
 void 
-ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::AudioFileSource*>* deletion_list)
+ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
 {
        ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
 
-       for (list<AudioFileSource*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
+       for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
                delete *i;
        }
 
index 5fb9dd95e7e6805564bbc5fc7d141a6bab1eb55a..297c9c3c65e60a965dd2c2290c1ef8b8bf6ebf39 100644 (file)
@@ -520,7 +520,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
        sigc::connection point_one_second_connection;
        sigc::connection point_zero_one_second_connection;
 
-       void diskstream_added (ARDOUR::AudioDiskstream*);
+       void diskstream_added (ARDOUR::Diskstream*);
 
        gint session_menu (GdkEventButton *);
 
@@ -621,7 +621,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
        void toggle_record_enable (uint32_t);
 
        uint32_t rec_enabled_diskstreams;
-       void count_recenabled_diskstreams (ARDOUR::AudioDiskstream&);
+       void count_recenabled_diskstreams (ARDOUR::Route&);
 
        About* about;
        bool shown_flag;
@@ -640,7 +640,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
        struct timeval last_peak_grab;
        struct timeval last_shuttle_request;
 
-       void delete_sources_in_the_right_thread (list<ARDOUR::AudioFileSource*>*);
+       void delete_sources_in_the_right_thread (list<ARDOUR::Source*>*);
 
        void editor_display_control_changed (Editing::DisplayControl c);
 
index 202fa88b59f3011a825c4e9bd4c50e245c3e30a7..25f3068a813d39c04d0b38157e98f79dee0e6c7c 100644 (file)
@@ -76,8 +76,8 @@ ARDOUR_UI::connect_to_session (Session *s)
        rec_button.set_sensitive (true);
        shuttle_box.set_sensitive (true);
        
-       if (session->n_audio_diskstreams() == 0) {
-               session->AudioDiskstreamAdded.connect (mem_fun(*this, &ARDOUR_UI::diskstream_added));
+       if (session->n_diskstreams() == 0) {
+               session->DiskstreamAdded.connect (mem_fun(*this, &ARDOUR_UI::diskstream_added));
        }
 
        if (connection_editor) {
diff --git a/gtk2_ardour/audio_region_editor.cc b/gtk2_ardour/audio_region_editor.cc
new file mode 100644 (file)
index 0000000..194f358
--- /dev/null
@@ -0,0 +1,731 @@
+/*
+    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$
+*/
+
+#include <ardour/audioregion.h>
+#include <ardour/utils.h>
+#include <gtkmm2ext/utils.h>
+#include <gtkmm2ext/stop_signal.h>
+#include <cmath>
+
+#include "audio_region_editor.h"
+#include "audio_region_view.h"
+#include "ardour_ui.h"
+#include "utils.h"
+#include "gui_thread.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace PBD;
+using namespace sigc;
+using namespace std;
+
+AudioRegionEditor::AudioRegionEditor (Session& s, AudioRegion& r, AudioRegionView& rv)
+       : RegionEditor (s),
+         _region (r),
+         _region_view (rv),
+         name_label (_("NAME:")),
+         lock_button (_("lock")),
+         mute_button (_("mute")),
+         opaque_button (_("opaque")),
+         envelope_active_button(_("active")),
+         envelope_view_button(_("visible")),
+         raise_arrow (Gtk::ARROW_UP, Gtk::SHADOW_OUT),
+         lower_arrow (Gtk::ARROW_DOWN, Gtk::SHADOW_OUT),
+         layer_label (_("Layer")),
+         audition_button (_("play")),
+         time_table (3, 2),
+         start_clock ("AudioRegionEditorClock", true),
+         end_clock ("AudioRegionEditorClock", true),
+         length_clock ("AudioRegionEditorClock", true, true),
+         sync_offset_clock ("AudioRegionEditorClock", true, true),
+         envelope_loop_table (1, 3),
+         envelope_label (_("ENVELOPE")),
+         fade_in_table (4, 3),
+         fade_in_length_adjustment (5.0, 0.0, 10000, 0.05, 1),
+         fade_in_length_spinner (fade_in_length_adjustment, 10),
+         fade_out_table (4, 3),
+         fade_out_length_adjustment (5.0, 0.0, 10000, 0.05, 1),
+         fade_out_length_spinner (fade_out_length_adjustment, 10)
+
+{
+       start_clock.set_session (&_session);
+       end_clock.set_session (&_session);
+       length_clock.set_session (&_session);
+
+       name_entry.set_name ("AudioRegionEditorEntry");
+       name_label.set_name ("AudioRegionEditorLabel");
+
+       name_hbox.set_spacing (5);
+       name_hbox.pack_start (name_label, false, false);
+       name_hbox.pack_start (name_entry, false, false);
+
+       raise_button.add (raise_arrow);
+       lower_button.add (lower_arrow);
+       layer_frame.set_name ("BaseFrame");
+       layer_frame.set_shadow_type (Gtk::SHADOW_IN);
+       layer_frame.add (layer_value_label);
+       layer_label.set_name ("AudioRegionEditorLabel");
+       layer_value_label.set_name ("AudioRegionEditorLabel");
+       Gtkmm2ext::set_size_request_to_display_given_text (layer_value_label, "99", 5, 2);
+
+       layer_hbox.set_spacing (5);
+       layer_hbox.pack_start (layer_label, false, false);
+       layer_hbox.pack_start (layer_frame, false, false);
+#if 0
+       layer_hbox.pack_start (raise_button, false, false);
+       layer_hbox.pack_start (lower_button, false, false);
+#endif
+
+       mute_button.set_name ("AudioRegionEditorToggleButton");
+       opaque_button.set_name ("AudioRegionEditorToggleButton");
+       lock_button.set_name ("AudioRegionEditorToggleButton");
+       envelope_active_button.set_name ("AudioRegionEditorToggleButton");
+       envelope_view_button.set_name ("AudioRegionEditorToggleButton");
+       fade_in_active_button.set_name ("AudioRegionEditorToggleButton");
+       fade_out_active_button.set_name ("AudioRegionEditorToggleButton");
+       audition_button.set_name ("AudioRegionEditorToggleButton");
+
+       ARDOUR_UI::instance()->tooltips().set_tip (mute_button, _("mute this region"));
+       ARDOUR_UI::instance()->tooltips().set_tip (opaque_button, _("regions underneath this one cannot be heard"));
+       ARDOUR_UI::instance()->tooltips().set_tip (lock_button, _("prevent any changes to this region"));
+       ARDOUR_UI::instance()->tooltips().set_tip (envelope_active_button, _("use the gain envelope during playback"));
+       ARDOUR_UI::instance()->tooltips().set_tip (envelope_view_button, _("show the gain envelope"));
+       ARDOUR_UI::instance()->tooltips().set_tip (fade_in_active_button, _("use fade in curve during playback"));
+       ARDOUR_UI::instance()->tooltips().set_tip (fade_out_active_button, _("use fade out curve during playback"));
+       ARDOUR_UI::instance()->tooltips().set_tip (audition_button, _("audition this region"));
+
+       mute_button.unset_flags (Gtk::CAN_FOCUS);
+       opaque_button.unset_flags (Gtk::CAN_FOCUS);
+       lock_button.unset_flags (Gtk::CAN_FOCUS);
+       envelope_active_button.unset_flags (Gtk::CAN_FOCUS);
+       envelope_view_button.unset_flags (Gtk::CAN_FOCUS);
+       fade_in_active_button.unset_flags (Gtk::CAN_FOCUS);
+       fade_out_active_button.unset_flags (Gtk::CAN_FOCUS);
+       audition_button.unset_flags (Gtk::CAN_FOCUS);
+       
+       mute_button.set_events (mute_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
+       opaque_button.set_events (opaque_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
+       lock_button.set_events (lock_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
+       envelope_active_button.set_events (envelope_active_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
+       envelope_view_button.set_events (envelope_view_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
+       fade_in_active_button.set_events (fade_in_active_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
+       fade_out_active_button.set_events (fade_out_active_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
+       audition_button.set_events (audition_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
+
+       top_row_button_hbox.set_border_width (5);
+       top_row_button_hbox.set_spacing (5);
+       top_row_button_hbox.set_homogeneous (false);
+       top_row_button_hbox.pack_start (mute_button, false, false);
+       top_row_button_hbox.pack_start (opaque_button, false, false);
+       top_row_button_hbox.pack_start (lock_button, false, false);
+       top_row_button_hbox.pack_start (layer_hbox, false, false, 5);
+       top_row_button_hbox.pack_end (audition_button, false, false);
+       
+       top_row_hbox.pack_start (name_hbox, true, true);
+       top_row_hbox.pack_end (top_row_button_hbox, true, true);
+
+       start_label.set_name ("AudioRegionEditorLabel");
+       start_label.set_text (_("START:"));
+       end_label.set_name ("AudioRegionEditorLabel");
+       end_label.set_text (_("END:"));
+       length_label.set_name ("AudioRegionEditorLabel");
+       length_label.set_text (_("LENGTH:"));
+       
+       time_table.set_col_spacings (2);
+       time_table.set_row_spacings (5);
+       time_table.set_border_width (5);
+
+       start_alignment.set (1.0, 0.5);
+       end_alignment.set (1.0, 0.5);
+       length_alignment.set (1.0, 0.5);
+
+       start_alignment.add (start_label);
+       end_alignment.add (end_label);
+       length_alignment.add (length_label);
+
+       time_table.attach (start_alignment, 0, 1, 0, 1, Gtk::FILL, Gtk::FILL);
+       time_table.attach (start_clock, 1, 2, 0, 1, Gtk::FILL, Gtk::FILL);
+
+       time_table.attach (end_alignment, 0, 1, 1, 2, Gtk::FILL, Gtk::FILL);
+       time_table.attach (end_clock, 1, 2, 1, 2, Gtk::FILL, Gtk::FILL);
+
+       time_table.attach (length_alignment, 0, 1, 2, 3, Gtk::FILL, Gtk::FILL);
+       time_table.attach (length_clock, 1, 2, 2, 3, Gtk::FILL, Gtk::FILL);
+
+       envelope_label.set_name ("AudioRegionEditorLabel");
+
+       envelope_loop_table.set_border_width (5);
+       envelope_loop_table.set_row_spacings (2);
+       envelope_loop_table.attach (envelope_label, 0, 1, 0, 1, Gtk::FILL, Gtk::FILL);
+       envelope_loop_table.attach (envelope_active_button, 0, 1, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
+       envelope_loop_table.attach (envelope_view_button, 0, 1, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
+
+       /* fade in */
+
+       fade_in_table.set_border_width (5);
+       fade_in_table.set_homogeneous (false);
+
+       fade_in_label.set_name ("AudioRegionEditorLabel");
+       fade_in_active_button_label.set_name ("AudioRegionEditorSmallLabel");
+       fade_in_length_label.set_name ("AudioRegionEditorSmallLabel");
+
+       fade_in_label.set_text (_("FADE IN"));
+       fade_in_active_button_label.set_text (_("active"));
+       fade_in_length_label.set_text (_("msecs"));
+
+       fade_in_active_button.add (fade_in_active_button_label);
+
+       fade_in_length_spinner.set_name("GenericSpinner");
+
+       fade_in_length_spinner.set_digits (3);
+
+       // fade_in_length_spinner.signal_activate().connect (mem_fun(*this, &AudioRegionEditor::activation));
+
+       Gtkmm2ext::set_size_request_to_display_given_text (fade_in_length_spinner, "500g", 20, -1);
+
+       fade_in_label_align.add (fade_in_label);
+       fade_in_label_align.set (0.5);
+
+
+       fade_in_table.attach (fade_in_label_align,   0, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
+
+       fade_in_table.attach (fade_in_length_label,   0, 1, 1, 2, Gtk::EXPAND, Gtk::FILL);
+       fade_in_table.attach (fade_in_length_spinner, 0, 1, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
+
+       fade_in_table.attach (fade_in_active_button,        0, 2, 3, 5, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
+
+       /* fade out */
+
+       fade_out_table.set_border_width (5);
+       fade_out_table.set_homogeneous (false);
+
+       fade_out_label.set_name ("AudioRegionEditorLabel");
+       fade_out_active_button_label.set_name ("AudioRegionEditorSmallLabel");
+       fade_out_length_label.set_name ("AudioRegionEditorSmallLabel");
+
+       fade_out_label.set_text (_("FADE OUT"));
+       fade_out_active_button_label.set_text (_("active"));
+       fade_out_length_label.set_text (_("msecs"));
+
+       fade_out_active_button.add (fade_out_active_button_label);
+
+       fade_out_length_spinner.set_name("GenericSpinner");
+       
+       fade_out_length_spinner.set_digits (3);
+
+       fade_out_length_spinner.signal_activate().connect (mem_fun(*this, &AudioRegionEditor::activation));
+
+       Gtkmm2ext::set_size_request_to_display_given_text (fade_out_length_spinner, "500g", 20, -1);
+
+       fade_out_label_align.add (fade_out_label);
+       fade_out_label_align.set (0.5);
+
+       fade_out_table.attach (fade_out_label_align,   0, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
+
+       fade_out_table.attach (fade_out_length_label,   0, 1, 1, 2, Gtk::EXPAND, Gtk::FILL);
+       fade_out_table.attach (fade_out_length_spinner, 0, 1, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
+
+       fade_out_table.attach (fade_out_active_button,        0, 2, 3, 5, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
+
+       lower_hbox.pack_start (time_table, true, true);
+       lower_hbox.pack_start (sep1, false, false);
+       lower_hbox.pack_start (envelope_loop_table, true, true);
+       lower_hbox.pack_start (sep2, false, false);
+       lower_hbox.pack_start (fade_in_table, true, true);
+       lower_hbox.pack_start (fade_out_table, true, true);
+
+       get_vbox()->pack_start (top_row_hbox, true, true);
+       get_vbox()->pack_start (sep3, false, false);
+       get_vbox()->pack_start (lower_hbox, true, true);
+
+       set_name ("AudioRegionEditorWindow");
+       add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
+
+       signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (this)));
+
+       string title = _("ardour: region ");
+       title += _region.name();
+       set_title (title);
+
+       show_all();
+
+       name_changed ();
+       bounds_changed (Change (StartChanged|LengthChanged|PositionChanged));
+       envelope_active_changed ();
+       mute_changed ();
+       opacity_changed ();
+       lock_changed ();
+       layer_changed ();
+       fade_in_changed ();
+       fade_out_changed ();
+
+       XMLNode *node  = _region.extra_xml ("GUI");
+       XMLProperty *prop = 0;
+       bool showing_envelope = false;
+
+       if (node && (prop = node->property ("envelope-visible")) != 0) {
+               if (prop->value() == "yes") {
+                       showing_envelope = true;
+               } 
+       } 
+
+       if (showing_envelope) {
+               envelope_view_button.set_active (true);
+       } else {
+               envelope_view_button.set_active (false);
+       }
+
+       _region.StateChanged.connect (mem_fun(*this, &AudioRegionEditor::region_changed));
+       
+       spin_arrow_grab = false;
+       
+       connect_editor_events ();
+}
+
+AudioRegionEditor::~AudioRegionEditor ()
+{
+}
+
+void
+AudioRegionEditor::region_changed (Change what_changed)
+{
+       if (what_changed & NameChanged) {
+               name_changed ();
+       }
+       if (what_changed & BoundsChanged) {
+               bounds_changed (what_changed);
+       }
+
+       if (what_changed & Region::OpacityChanged) {
+               opacity_changed ();
+       }
+       if (what_changed & Region::MuteChanged) {
+               mute_changed ();
+       }
+       if (what_changed & Region::LockChanged) {
+               lock_changed ();
+       }
+       if (what_changed & Region::LayerChanged) {
+               layer_changed ();
+       }
+
+       if (what_changed & AudioRegion::EnvelopeActiveChanged) {
+               envelope_active_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 ();
+       }
+}
+
+void
+AudioRegionEditor::fade_in_realized ()
+{
+       fade_in_changed ();
+}
+
+void
+AudioRegionEditor::fade_out_realized ()
+{
+       fade_out_changed ();
+}
+
+gint 
+AudioRegionEditor::bpressed (GdkEventButton* ev, Gtk::SpinButton* but, void (AudioRegionEditor::*pmf)())
+{
+       switch (ev->button) {
+       case 1:
+       case 2:
+       case 3:
+               if (ev->type == GDK_BUTTON_PRESS) { /* no double clicks here */
+                       if (!spin_arrow_grab) {
+                               // GTK2FIX probably nuke the region editor
+                               // if ((ev->window == but->gobj()->panel)) {
+                               // spin_arrow_grab = true;
+                               // (this->*pmf)();
+                               // } 
+                       } 
+               } 
+               break;
+       default:
+               break;
+       }
+       return FALSE;
+}
+
+gint 
+AudioRegionEditor::breleased (GdkEventButton* ev, Gtk::SpinButton* but, void (AudioRegionEditor::*pmf)())
+{
+       if (spin_arrow_grab) {
+               (this->*pmf)();
+               spin_arrow_grab = false;
+       }
+       return FALSE;
+}
+
+void
+AudioRegionEditor::start_editing_fade_in ()
+{
+       _region.freeze ();
+}
+
+void
+AudioRegionEditor::stop_editing_fade_in ()
+{
+       _region.thaw (_("fade in edit"));
+}
+
+void
+AudioRegionEditor::start_editing_fade_out ()
+{
+       _region.freeze ();
+}
+
+void
+AudioRegionEditor::stop_editing_fade_out ()
+{
+       _region.thaw (_("fade out edit"));
+}
+
+void
+AudioRegionEditor::connect_editor_events ()
+{
+  name_entry.signal_changed().connect (mem_fun(*this, &AudioRegionEditor::name_entry_changed));
+
+       start_clock.ValueChanged.connect (mem_fun(*this, &AudioRegionEditor::start_clock_changed));
+       end_clock.ValueChanged.connect (mem_fun(*this, &AudioRegionEditor::end_clock_changed));
+       length_clock.ValueChanged.connect (mem_fun(*this, &AudioRegionEditor::length_clock_changed));
+
+       fade_in_length_spinner.signal_button_press_event().connect (bind (mem_fun(*this, &AudioRegionEditor::bpressed), &fade_in_length_spinner, 
+                                                                &AudioRegionEditor::start_editing_fade_in));
+       fade_in_length_spinner.signal_button_release_event().connect (bind (mem_fun (*this, &AudioRegionEditor::breleased), &fade_in_length_spinner, 
+                                                                  &AudioRegionEditor::stop_editing_fade_in));
+
+       fade_out_length_spinner.signal_button_press_event().connect (bind (mem_fun(*this, &AudioRegionEditor::bpressed), &fade_out_length_spinner, 
+                                                                &AudioRegionEditor::start_editing_fade_out));
+       fade_out_length_spinner.signal_button_release_event().connect (bind (mem_fun (*this, &AudioRegionEditor::breleased), &fade_out_length_spinner, 
+                                                                  &AudioRegionEditor::stop_editing_fade_out));
+
+       fade_in_length_adjustment.signal_value_changed().connect (mem_fun(*this, &AudioRegionEditor::fade_in_length_adjustment_changed));
+       fade_out_length_adjustment.signal_value_changed().connect (mem_fun(*this, &AudioRegionEditor::fade_out_length_adjustment_changed));
+
+       fade_in_active_button.signal_toggled().connect (mem_fun(*this, &AudioRegionEditor::fade_in_active_toggled));
+       fade_out_active_button.signal_toggled().connect (mem_fun(*this, &AudioRegionEditor::fade_out_active_toggled));
+
+       envelope_active_button.signal_button_press_event().connect (mem_fun(*this, &AudioRegionEditor::envelope_active_button_press));
+       envelope_active_button.signal_button_release_event().connect (mem_fun(*this, &AudioRegionEditor::envelope_active_button_release));
+       audition_button.signal_toggled().connect (mem_fun(*this, &AudioRegionEditor::audition_button_toggled));
+       envelope_view_button.signal_toggled().connect (mem_fun(*this, &AudioRegionEditor::envelope_view_button_toggled));
+       lock_button.signal_clicked().connect (mem_fun(*this, &AudioRegionEditor::lock_button_clicked));
+       mute_button.signal_clicked().connect (mem_fun(*this, &AudioRegionEditor::mute_button_clicked));
+       opaque_button.signal_clicked().connect (mem_fun(*this, &AudioRegionEditor::opaque_button_clicked));
+       raise_button.signal_clicked().connect (mem_fun(*this, &AudioRegionEditor::raise_button_clicked));
+       lower_button.signal_clicked().connect (mem_fun(*this, &AudioRegionEditor::lower_button_clicked));
+       _session.AuditionActive.connect (mem_fun(*this, &AudioRegionEditor::audition_state_changed));
+}
+
+void
+AudioRegionEditor::start_clock_changed ()
+{
+       _region.set_position (start_clock.current_time(), this);
+}
+
+void
+AudioRegionEditor::end_clock_changed ()
+{
+       _region.trim_end (end_clock.current_time(), this);
+
+       end_clock.set (_region.position() + _region.length(), true);
+}
+
+void
+AudioRegionEditor::length_clock_changed ()
+{
+       jack_nframes_t frames = length_clock.current_time();
+       _region.trim_end (_region.position() + frames, this);
+
+       length_clock.set (_region.length());
+}
+
+gint
+AudioRegionEditor::envelope_active_button_press(GdkEventButton *ev)
+{
+       return stop_signal (envelope_active_button, "button_press_event");
+}
+
+gint
+AudioRegionEditor::envelope_active_button_release (GdkEventButton *ev)
+{
+       _region.set_envelope_active (!_region.envelope_active());
+       return stop_signal (envelope_active_button, "button_release_event");
+}
+
+void
+AudioRegionEditor::envelope_view_button_toggled ()
+{
+       bool visible = envelope_view_button.get_active ();
+
+       _region_view.set_envelope_visible (visible);
+}
+
+void
+AudioRegionEditor::audition_button_toggled ()
+{
+       if (audition_button.get_active()) {
+               _session.audition_region (_region);
+       } else {
+               _session.cancel_audition ();
+       }
+}
+
+void
+AudioRegionEditor::raise_button_clicked ()
+{
+       _region.raise ();
+}
+
+void
+AudioRegionEditor::lower_button_clicked ()
+{
+       _region.lower ();
+}
+
+void
+AudioRegionEditor::opaque_button_clicked ()
+{
+       bool ractive = _region.opaque();
+
+       if (opaque_button.get_active() != ractive) {
+               _region.set_opaque (!ractive);
+       }
+}
+
+void
+AudioRegionEditor::mute_button_clicked ()
+{
+       bool ractive = _region.muted();
+
+       if (mute_button.get_active() != ractive) {
+               _region.set_muted (!ractive);
+       }
+}
+
+void
+AudioRegionEditor::lock_button_clicked ()
+{
+       bool ractive = _region.locked();
+
+       if (lock_button.get_active() != ractive) {
+               _region.set_locked (!ractive);
+       }
+}
+
+void
+AudioRegionEditor::layer_changed ()
+{
+       char buf[8];
+       snprintf (buf, sizeof(buf), "%d", (int) _region.layer() + 1);
+       layer_value_label.set_text (buf);
+}
+
+void
+AudioRegionEditor::name_changed ()
+{
+       if (name_entry.get_text() != _region.name()) {
+               name_entry.set_text (_region.name());
+       }
+}
+
+void
+AudioRegionEditor::lock_changed ()
+{
+       bool yn;
+
+       if ((yn = _region.locked()) != lock_button.get_active()) {
+               lock_button.set_active (yn);
+       }
+
+       start_clock.set_sensitive (!yn);
+       end_clock.set_sensitive (!yn);
+       length_clock.set_sensitive (!yn);
+}
+
+void
+AudioRegionEditor::envelope_active_changed ()
+{
+       bool yn;
+
+       if ((yn = _region.envelope_active()) != envelope_active_button.get_active()) {
+               envelope_active_button.set_active (yn);
+       }
+}
+
+void
+AudioRegionEditor::opacity_changed ()
+{
+       bool yn;
+       if ((yn = _region.opaque()) != opaque_button.get_active()) {
+               opaque_button.set_active (yn);
+       }
+}
+
+void
+AudioRegionEditor::mute_changed ()
+{
+       bool yn;
+       if ((yn = _region.muted()) != mute_button.get_active()) {
+               mute_button.set_active (yn);
+       }
+}
+
+void
+AudioRegionEditor::bounds_changed (Change what_changed)
+{
+       if (what_changed & Change ((PositionChanged|LengthChanged))) {
+               start_clock.set (_region.position(), true);
+               end_clock.set (_region.position() + _region.length(), true);
+               length_clock.set (_region.length(), true);
+       }
+}
+
+void
+AudioRegionEditor::activation ()
+{
+       
+}      
+
+void
+AudioRegionEditor::name_entry_changed ()
+{
+       if (name_entry.get_text() != _region.name()) {
+               _region.set_name (name_entry.get_text());
+       }
+}
+
+void
+AudioRegionEditor::fade_in_changed ()
+{
+       float msecs = fade_in_length_adjustment.get_value();
+       jack_nframes_t sr = _session.frame_rate();
+       jack_nframes_t adj_frames = (jack_nframes_t) floor (msecs * (sr/1000.0f));
+       jack_nframes_t frames;
+       bool x;
+
+       if (adj_frames != (frames = (jack_nframes_t) _region.fade_in().back()->when)) {
+               fade_in_length_adjustment.set_value ((frames * 1000.0f) / sr);
+       }
+
+       if ((x = _region.fade_in_active()) != fade_in_active_button.get_active()) {
+               fade_in_active_button.set_active (x);
+       }
+}
+
+void
+AudioRegionEditor::fade_out_changed ()
+{
+       float msecs = fade_out_length_adjustment.get_value();
+       jack_nframes_t sr = _session.frame_rate();
+       jack_nframes_t adj_frames = (jack_nframes_t) floor (msecs * (sr/1000.0f));
+       jack_nframes_t frames;
+       bool x;
+       if (adj_frames != (frames = (jack_nframes_t) _region.fade_out().back()->when)) {
+               fade_out_length_adjustment.set_value ((frames * 1000.0f) / sr);
+       }
+
+       if ((x = _region.fade_out_active()) != fade_out_active_button.get_active()) {
+               fade_out_active_button.set_active (x);
+       }
+}
+
+void
+AudioRegionEditor::fade_in_length_adjustment_changed ()
+{
+       jack_nframes_t fade_length = (jack_nframes_t) floor (fade_in_length_adjustment.get_value() * _session.frame_rate() * 0.001); 
+       fade_length = max (fade_length, (jack_nframes_t) 64);
+       fade_length = min (fade_length, _region.length());
+       
+       _region.set_fade_in_length (fade_length);
+       /* region is frozen, no worries */
+       fade_in_changed();
+}
+
+void
+AudioRegionEditor::fade_out_length_adjustment_changed ()
+{
+       jack_nframes_t fade_length = (jack_nframes_t) floor (fade_out_length_adjustment.get_value() * _session.frame_rate() * 0.001); 
+       fade_length = max (fade_length, (jack_nframes_t) 64);
+       fade_length = min (fade_length, _region.length());
+       
+       _region.set_fade_out_length (fade_length);      
+       /* region is frozen, no worries */
+       fade_out_changed();
+}
+
+void
+AudioRegionEditor::fade_in_active_toggled ()
+{
+       _region.set_fade_in_active (fade_in_active_button.get_active());
+}
+
+void
+AudioRegionEditor::fade_out_active_toggled ()
+{
+       _region.set_fade_out_active (fade_out_active_button.get_active());
+}
+
+void
+AudioRegionEditor::fade_out_active_changed ()
+{
+       bool x;
+
+       if ((x = _region.fade_out_active()) != fade_out_active_button.get_active()) {
+               fade_out_active_button.set_active (x);
+       }
+}
+
+void
+AudioRegionEditor::fade_in_active_changed ()
+{
+       bool x;
+
+       if ((x = _region.fade_in_active()) != fade_in_active_button.get_active()) {
+               fade_in_active_button.set_active (x);
+       }
+}
+
+void
+AudioRegionEditor::audition_state_changed (bool yn)
+{
+       ENSURE_GUI_THREAD (bind (mem_fun(*this, &AudioRegionEditor::audition_state_changed), yn));
+
+       if (!yn) {
+               audition_button.set_active (false);
+       }
+}
+
diff --git a/gtk2_ardour/audio_region_editor.h b/gtk2_ardour/audio_region_editor.h
new file mode 100644 (file)
index 0000000..38cd920
--- /dev/null
@@ -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_region_view.cc b/gtk2_ardour/audio_region_view.cc
new file mode 100644 (file)
index 0000000..a9a7584
--- /dev/null
@@ -0,0 +1,1125 @@
+/*
+    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.
+
+    $Id$
+*/
+
+#include <cmath>
+#include <cassert>
+#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_region_view.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)
+       , sync_mark(0)
+       , zero_line(0)
+       , fade_in_shape(0)
+       , fade_out_shape(0)
+       , fade_in_handle(0)
+       , fade_out_handle(0)
+       , gain_line(0)
+       , _amplitude_above_axis(1.0)
+       , _flags(0)
+       , fade_color(0)
+{
+}
+
+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)
+       , sync_mark(0)
+       , zero_line(0)
+       , fade_in_shape(0)
+       , fade_out_shape(0)
+       , fade_in_handle(0)
+       , fade_out_handle(0)
+       , gain_line(0)
+       , _amplitude_above_axis(1.0)
+       , _flags(0)
+       , fade_color(0)
+{
+}
+
+void
+AudioRegionView::init (Gdk::Color& basic_color, bool wfd)
+{
+       // FIXME: Some redundancy here with RegionView::init.  Need to figure out
+       // where order is important and where it isn't...
+       
+       RegionView::init(basic_color, wfd);
+
+       XMLNode *node;
+
+       _amplitude_above_axis = 1.0;
+       zero_line             = 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 ();
+
+       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));
+
+       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 ();
+
+       /* 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 */
+
+       if (gain_line) {
+               delete gain_line;
+       }
+}
+
+ARDOUR::AudioRegion&
+AudioRegionView::audio_region() const
+{
+       // "Guaranteed" to succeed...
+       return dynamic_cast<AudioRegion&>(_region);
+}
+
+void
+AudioRegionView::region_changed (Change what_changed)
+{
+       ENSURE_GUI_THREAD (bind (mem_fun(*this, &AudioRegionView::region_changed), what_changed));
+
+       RegionView::region_changed(what_changed);
+
+       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_resized (Change what_changed)
+{
+       RegionView::region_resized(what_changed);
+
+       if (what_changed & Change (StartChanged|LengthChanged)) {
+
+               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) {
+
+                       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(pixel_width);
+       assert(_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_muted ()
+{
+       RegionView::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_height (gdouble height)
+{
+       uint32_t wcnt = waves.size();
+
+       // FIXME: ick
+       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)
+{
+       RegionView::set_samples_per_unit (spu);
+
+       for (uint32_t n=0; n < waves.size(); ++n) {
+               waves[n]->property_samples_per_unit() = spu;
+       }
+
+       if (gain_line) {
+               gain_line->reset ();
+       }
+       reset_fade_shapes ();
+}
+
+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(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();
+       
+       if (gain_line) {
+               gain_line->set_line_color (audio_region().envelope_active() ? color_map[cGainLine] : color_map[cGainLineInactive]);
+       }
+
+       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::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::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_data) {
+                       if (audio_region().source(n).peaks_ready (bind (mem_fun(*this, &AudioRegionView::peaks_ready_handler), n), data_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 */
+               data_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;
+               }
+       }
+}
+
+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::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_region_view.h b/gtk2_ardour/audio_region_view.h
new file mode 100644 (file)
index 0000000..ec3ea6c
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+    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 "region_view.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_data = false);
+       
+       ARDOUR::AudioRegion& audio_region() const;
+    
+    void set_height (double);
+    void set_samples_per_unit (double);
+
+    void set_amplitude_above_axis (gdouble spp);
+
+    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 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 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      samples_per_unit,
+                            Gdk::Color& basic_color,
+                            TimeAxisViewItem::Visibility);
+    
+    enum Flags {
+           EnvelopeVisible = 0x1,
+           WaveformVisible = 0x4,
+           WaveformRectified = 0x8
+    };
+    
+    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_scale_amplitude_changed ();
+
+    void create_waves ();
+    void create_one_wave (uint32_t, bool);
+    void manage_zero_line ();
+    void peaks_ready_handler (uint32_t);
+    void set_flags (XMLNode *);
+    void store_flags ();
+
+    void set_colors ();
+    void compute_colors (Gdk::Color&);
+    void reset_width_dependent_items (double pixel_width);
+    void set_waveview_data_src();
+    
+       void color_handler (ColorID, uint32_t);
+
+    vector<GnomeCanvasWaveViewCache*> wave_caches;
+    vector<ArdourCanvas::WaveView *>  waves;
+    vector<ArdourCanvas::WaveView *>  tmp_waves; ///< see ::create_waves()
+    ArdourCanvas::Polygon*            sync_mark; ///< polgyon for sync position 
+    ArdourCanvas::SimpleLine*         zero_line;
+    ArdourCanvas::Polygon*            fade_in_shape;
+    ArdourCanvas::Polygon*            fade_out_shape;
+    ArdourCanvas::SimpleRect*         fade_in_handle;
+    ArdourCanvas::SimpleRect*         fade_out_handle;
+    AudioRegionGainLine*              gain_line;
+
+    double _amplitude_above_axis;
+
+    uint32_t _flags;
+    uint32_t fade_color;
+};
+
+#endif /* __gtk_ardour_audio_region_view_h__ */
diff --git a/gtk2_ardour/audio_regionview.cc b/gtk2_ardour/audio_regionview.cc
new file mode 100644 (file)
index 0000000..e2d20c0
--- /dev/null
@@ -0,0 +1,1408 @@
+/*
+    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 678 2006-07-11 15:45:19Z paul $
+*/
+
+#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 "region_view.h"
+#include "audio_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 "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;
+
+sigc::signal<void,AudioRegionView*> AudioRegionView::AudioRegionViewGoingAway;
+
+AudioRegionView::AudioRegionView (ArdourCanvas::Group *parent, AudioTimeAxisView &tv, AudioRegion& 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)
+{
+}
+
+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)
+{
+}
+
+void
+AudioRegionView::init (double amplitude_above_axis, Gdk::Color& basic_color, bool wfw)
+{
+        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) {
+               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, 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;
+
+       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 */
+
+       for (vector<GhostRegion*>::iterator g = ghosts.begin(); g != ghosts.end(); ++g) {
+               delete *g;
+       }
+
+       if (editor) {
+               delete editor;
+       }
+
+       if (gain_line) {
+               delete gain_line;
+       }
+}
+
+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)
+{
+       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() = &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 ()
+{
+       AudioTimeAxisView *atv = dynamic_cast<AudioTimeAxisView*> (&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::region_opacity ()
+{
+       set_frame_color ();
+}
+
+void
+AudioRegionView::raise ()
+{
+       region.raise ();
+}
+
+void
+AudioRegionView::raise_to_top ()
+{
+       region.raise_to_top ();
+}
+
+void
+AudioRegionView::lower ()
+{
+       region.lower ();
+}
+
+void
+AudioRegionView::lower_to_bottom ()
+{
+       region.lower_to_bottom ();
+}
+
+bool
+AudioRegionView::set_position (jack_nframes_t pos, void* src, double* ignored)
+{
+       double delta;
+       bool ret;
+
+       if (!(ret = TimeAxisViewItem::set_position (pos, this, &delta))) {
+               return false;
+       }
+
+       if (ignored) {
+               *ignored = delta;
+       }
+
+       if (delta) {
+               for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
+                       (*i)->group->move (delta, 0.0);
+               }
+       }
+
+       return ret;
+}
+
+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)
+{
+       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 (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(), 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 (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;
+
+       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) &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 (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)) {
+               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)
+{
+       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() =  &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;
+               }
+       }
+}
+
+uint32_t
+AudioRegionView::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() = &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_streamview.cc b/gtk2_ardour/audio_streamview.cc
new file mode 100644 (file)
index 0000000..68df5ff
--- /dev/null
@@ -0,0 +1,698 @@
+/*
+    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_region_view.h"
+#include "tape_region_view.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)
+{
+       crossfades_visible = true;
+
+       if (tv.is_audio_track())
+               stream_base_color = color_map[cAudioTrackBase];
+       else
+               stream_base_color = color_map[cAudioBusBase];
+
+       canvas_rect->property_outline_color_rgba() = color_map[cAudioTrackOutline];
+
+       _amplitude_above_axis = 1.0;
+
+       use_rec_regions = tv.editor.show_waveforms_recording ();
+       last_rec_peak_frame = 0;
+}
+
+AudioStreamView::~AudioStreamView ()
+{
+}
+
+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));
+
+       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;
+       }
+
+       StreamView::remove_region_view(r);
+}
+
+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 (file)
index 0000000..05ce812
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+    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);
+
+       void add_crossfade (ARDOUR::Crossfade*);
+       void remove_crossfade (ARDOUR::Crossfade*);
+
+       void color_handler (ColorID id, uint32_t val);
+       
+
+       double _amplitude_above_axis;
+       
+       typedef list<CrossfadeView*> CrossfadeViewList;
+       CrossfadeViewList crossfade_views;
+       bool              crossfades_visible;
+
+       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__ */
index 5f6d29f9ffcd201841115141b3a2fd6f03cb30fa..376e05aa4c7b6ac4ba48e0dec645154f9c10b073 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2000 Paul Davis 
+    Copyright (C) 2000-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
@@ -20,6 +20,7 @@
 
 #include <cstdlib>
 #include <cmath>
+#include <cassert>
 
 #include <algorithm>
 #include <string>
@@ -40,7 +41,6 @@
 #include <ardour/audioplaylist.h>
 #include <ardour/audio_diskstream.h>
 #include <ardour/insert.h>
-#include <ardour/ladspa_plugin.h>
 #include <ardour/location.h>
 #include <ardour/panner.h>
 #include <ardour/playlist.h>
 #include "audio_time_axis.h"
 #include "automation_gain_line.h"
 #include "automation_pan_line.h"
-#include "automation_time_axis.h"
 #include "canvas_impl.h"
 #include "crossfade_view.h"
 #include "enums.h"
 #include "gain_automation_time_axis.h"
-#include "gui_thread.h"
 #include "keyboard.h"
 #include "pan_automation_time_axis.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 "audio_region_view.h"
 #include "simplerect.h"
-#include "streamview.h"
+#include "audio_streamview.h"
 #include "utils.h"
 
 #include <ardour/audio_track.h>
 
 using namespace ARDOUR;
 using namespace PBD;
-using namespace LADSPA;
 using namespace Gtk;
 using namespace Editing;
 
 
 AudioTimeAxisView::AudioTimeAxisView (PublicEditor& ed, Session& sess, boost::shared_ptr<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)
+       , RouteTimeAxisView(ed, sess, rt, canvas)
 {
-       _has_state = true;
+       // Make sure things are sane...
+       assert(!is_track() || is_audio_track());
+
        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,161 +102,48 @@ AudioTimeAxisView::AudioTimeAxisView (PublicEditor& ed, Session& sess, boost::sh
        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));
-
-       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);
+       if (is_audio_track())
+               controls_ebox.set_name ("AudioTimeAxisViewControlsBaseUnselected");
+       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()->diskstream_changed.connect (mem_fun(*this, &AudioTimeAxisView::diskstream_changed));
-               get_diskstream()->speed_changed.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 ();
-
-               /* pick up the correct freeze state */
-
-               map_frozen ();
-
-       } else {
-
-               /* bus */
+       } 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
@@ -298,233 +164,6 @@ AudioTimeAxisView::hide ()
        TimeAxisView::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 (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)
 {
@@ -578,153 +217,14 @@ 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) {
-               (*i)->reset();
-       }
-}
-
-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 ()
+AudioTimeAxisView::build_automation_action_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, &AudioTimeAxisView::select_track_color)));
-
+       RouteTimeAxisView::build_automation_action_menu ();
 
-       items.push_back (SeparatorElem());
-       items.push_back (MenuElem (_("Hide all crossfades"), mem_fun(*this, &AudioTimeAxisView::hide_all_xfades)));
-       items.push_back (MenuElem (_("Show all crossfades"), mem_fun(*this, &AudioTimeAxisView::show_all_xfades)));
-       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 (MenuElem (_("Show all automation"),
-                                             mem_fun(*this, &AudioTimeAxisView::show_all_automation)));
-
-       automation_items.push_back (MenuElem (_("Show existing automation"),
-                                             mem_fun(*this, &AudioTimeAxisView::show_existing_automation)));
-
-       automation_items.push_back (MenuElem (_("Hide all automation"),
-                                             mem_fun(*this, &AudioTimeAxisView::hide_all_automation)));
-
        automation_items.push_back (SeparatorElem());
 
        automation_items.push_back (CheckMenuElem (_("Fader"), 
@@ -736,11 +236,21 @@ AudioTimeAxisView::build_display_menu ()
                                                   mem_fun(*this, &AudioTimeAxisView::toggle_pan_track)));
        pan_automation_item = static_cast<CheckMenuItem*> (&automation_items.back());
        pan_automation_item->set_active(show_pan_automation);
+       
+}
+
+void
+AudioTimeAxisView::append_extra_display_menu_items ()
+{
+       using namespace Menu_Helpers;
 
-       automation_items.push_back (MenuElem (_("Plugins"), subplugin_menu));
+       MenuList& items = display_menu->items();
 
-       items.push_back (MenuElem (_("Automation"), *automation_action_menu));
+       // crossfade stuff
+       items.push_back (MenuElem (_("Hide all crossfades"), mem_fun(*this, &AudioTimeAxisView::hide_all_xfades)));
+       items.push_back (MenuElem (_("Show all crossfades"), mem_fun(*this, &AudioTimeAxisView::show_all_xfades)));
 
+       // waveform menu
        Menu *waveform_menu = manage(new Menu);
        MenuList& waveform_items = waveform_menu->items();
        waveform_menu->set_name ("ArdourContextMenu");
@@ -760,399 +270,53 @@ AudioTimeAxisView::build_display_menu ()
        rectified_item = static_cast<RadioMenuItem *> (&waveform_items.back());
 
        items.push_back (MenuElem (_("Waveform"), *waveform_menu));
-
-       if (is_audio_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, &AudioTimeAxisView::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, &AudioTimeAxisView::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, &AudioTimeAxisView::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)));
-
-}
-
-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 = get_diskstream()) == 0) || ds->destructive() || ((pl = 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 = get_diskstream()) == 0) || ds->destructive() || ((pl = 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 = ds->playlist();
-               pl->set_name (name);
-       }
-}
-
-void
-AudioTimeAxisView::use_new_playlist (bool prompt)
-{
-       AudioPlaylist *pl;
-       AudioDiskstream *ds;
-       string name;
-
-       if (((ds = get_diskstream()) == 0) || ds->destructive() || ((pl = 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 = ds->playlist();
-               pl->set_name (name);
-       }
-}
-
-void
-AudioTimeAxisView::clear_playlist ()
-{
-       AudioPlaylist *pl;
-       AudioDiskstream *ds;
-       
-       if ((ds = get_diskstream()) != 0) {
-               if ((pl = 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 = get_diskstream()) != 0) {
-               set_playlist (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);
-
-       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
-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 
-{
-       AudioDiskstream *ds;
-
-       if ((ds = get_diskstream()) != 0) {
-               return ds->playlist(); 
-       } else {
-               return 0; 
-       }
-}
-
-void
-AudioTimeAxisView::name_entry_changed ()
-{
-       string x;
-
-       x = name_entry.get_text ();
-       
-       if (x == _route->name()) {
-               return;
-       }
+       AudioStreamView* asv = audio_view();
 
-       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());
+       if (asv) {
+               asv->set_show_waveforms_recording (yn);
        }
 }
 
 void
-AudioTimeAxisView::visual_click ()
-{
-       popup_display_menu (0);
-}
-
-void
-AudioTimeAxisView::hide_click ()
-{
-       editor.hide_track_in_display (*this);
-}
-
-Region*
-AudioTimeAxisView::find_next_region (jack_nframes_t pos, RegionPoint point, int32_t dir)
+AudioTimeAxisView::set_waveform_shape (WaveformShape shape)
 {
-       AudioDiskstream *stream;
-       AudioPlaylist *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_waveform_shape (shape);
        }
 
-       return 0;
-}
+       map_frozen ();
+}      
 
 void
 AudioTimeAxisView::add_gain_automation_child ()
@@ -1338,321 +502,6 @@ AudioTimeAxisView::pan_hidden ()
         _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
 }
 
-AudioTimeAxisView::RedirectAutomationInfo::~RedirectAutomationInfo ()
-{
-       for (vector<RedirectAutomationNode*>::iterator i = lines.begin(); i != lines.end(); ++i) {
-               delete *i;
-       }
-}
-
-
-AudioTimeAxisView::RedirectAutomationNode::~RedirectAutomationNode ()
-{
-       parent.remove_ran (this);
-
-       if (view) {
-               delete view;
-       }
-}
-
-void
-AudioTimeAxisView::remove_ran (RedirectAutomationNode* ran)
-{
-       if (ran->view) {
-               remove_child (ran->view);
-       }
-}
-
-AudioTimeAxisView::RedirectAutomationNode*
-AudioTimeAxisView::find_redirect_automation_node (boost::shared_ptr<Redirect> redirect, uint32_t what)
-{
-       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
-
-               if ((*i)->redirect == redirect) {
-
-                       for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
-                               if ((*ii)->what == what) {
-                                       return *ii;
-                               }
-                       }
-               }
-       }
-
-       return 0;
-}
-
-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
-AudioTimeAxisView::add_redirect_automation_curve (boost::shared_ptr<Redirect> redirect, uint32_t what)
-{
-       RedirectAutomationLine* ral;
-       string name;
-       RedirectAutomationNode* ran;
-
-       if ((ran = find_redirect_automation_node (redirect, what)) == 0) {
-               fatal << _("programming error: ")
-                     << string_compose (X_("redirect automation curve for %1:%2 not registered with audio track!"),
-                                 redirect->name(), what)
-                     << endmsg;
-               /*NOTREACHED*/
-               return;
-       }
-
-       if (ran->view) {
-               return;
-       }
-
-       name = redirect->describe_parameter (what);
-
-       /* create a string that is a legal XML node name that can be used to refer to this redirect+port combination */
-
-       char state_name[256];
-       snprintf (state_name, sizeof (state_name), "Redirect-%s-%" PRIu32, legalize_for_xml_node (redirect->name()).c_str(), what);
-
-       ran->view = new RedirectAutomationTimeAxisView (_session, _route, editor, *this, parent_canvas, name, what, *redirect, state_name);
-
-       ral = new RedirectAutomationLine (name, 
-                                         *redirect, what, _session, *ran->view,
-                                         *ran->view->canvas_display, redirect->automation_list (what));
-       
-       ral->set_line_color (color_map[cRedirectAutomationLine]);
-       ral->queue_reset ();
-
-       ran->view->add_line (*ral);
-
-       ran->view->Hiding.connect (bind (mem_fun(*this, &AudioTimeAxisView::redirect_automation_track_hidden), ran, redirect));
-
-       if (!ran->view->marked_for_display()) {
-               ran->view->hide ();
-       } else {
-               ran->menu_item->set_active (true);
-       }
-
-       add_child (ran->view);
-
-       view->foreach_regionview (bind (mem_fun(*this, &AudioTimeAxisView::add_ghost_to_redirect), ran->view));
-
-       redirect->mark_automation_visible (what, true);
-}
-
-void
-AudioTimeAxisView::redirect_automation_track_hidden (AudioTimeAxisView::RedirectAutomationNode* ran, boost::shared_ptr<Redirect> r)
-{
-       if (!_hidden) {
-               ran->menu_item->set_active (false);
-       }
-
-       r->mark_automation_visible (ran->what, false);
-
-        _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
-}
-
-void
-AudioTimeAxisView::add_existing_redirect_automation_curves (boost::shared_ptr<Redirect> redirect)
-{
-       set<uint32_t> s;
-       RedirectAutomationLine *ral;
-
-       redirect->what_has_visible_automation (s);
-
-       for (set<uint32_t>::iterator i = s.begin(); i != s.end(); ++i) {
-               
-               if ((ral = find_redirect_automation_curve (redirect, *i)) != 0) {
-                       ral->queue_reset ();
-               } else {
-                       add_redirect_automation_curve (redirect, (*i));
-               }
-       }
-}
-
-void
-AudioTimeAxisView::add_redirect_to_subplugin_menu (boost::shared_ptr<Redirect> r)
-{
-       using namespace Menu_Helpers;
-       RedirectAutomationInfo *rai;
-       list<RedirectAutomationInfo*>::iterator x;
-       
-       const std::set<uint32_t>& automatable = r->what_can_be_automated ();
-       std::set<uint32_t> has_visible_automation;
-
-       r->what_has_visible_automation(has_visible_automation);
-
-       if (automatable.empty()) {
-               return;
-       }
-
-       for (x = redirect_automation.begin(); x != redirect_automation.end(); ++x) {
-               if ((*x)->redirect == r) {
-                       break;
-               }
-       }
-
-       if (x == redirect_automation.end()) {
-
-               rai = new RedirectAutomationInfo (r);
-               redirect_automation.push_back (rai);
-
-       } else {
-
-               rai = *x;
-
-       }
-
-       /* any older menu was deleted at the top of redirects_changed()
-          when we cleared the subplugin menu.
-       */
-
-       rai->menu = manage (new Menu);
-       MenuList& items = rai->menu->items();
-       rai->menu->set_name ("ArdourContextMenu");
-
-       items.clear ();
-
-       for (std::set<uint32_t>::const_iterator i = automatable.begin(); i != automatable.end(); ++i) {
-
-               RedirectAutomationNode* ran;
-               CheckMenuItem* mitem;
-               
-               string name = r->describe_parameter (*i);
-               
-               items.push_back (CheckMenuElem (name));
-               mitem = dynamic_cast<CheckMenuItem*> (&items.back());
-
-               if (has_visible_automation.find((*i)) != has_visible_automation.end()) {
-                       mitem->set_active(true);
-               }
-
-               if ((ran = find_redirect_automation_node (r, *i)) == 0) {
-
-                       /* new item */
-                       
-                       ran = new RedirectAutomationNode (*i, mitem, *this);
-                       
-                       rai->lines.push_back (ran);
-
-               } else {
-
-                       ran->menu_item = mitem;
-
-               }
-
-               mitem->signal_toggled().connect (bind (mem_fun(*this, &AudioTimeAxisView::redirect_menu_item_toggled), rai, ran));
-       }
-
-       /* add the menu for this redirect, because the subplugin
-          menu is always cleared at the top of redirects_changed().
-          this is the result of some poor design in gtkmm and/or
-          GTK+.
-       */
-
-       subplugin_menu.items().push_back (MenuElem (r->name(), *rai->menu));
-       rai->valid = true;
-}
-
-void
-AudioTimeAxisView::redirect_menu_item_toggled (AudioTimeAxisView::RedirectAutomationInfo* rai,
-                                              AudioTimeAxisView::RedirectAutomationNode* ran)
-{
-       bool showit = ran->menu_item->get_active();
-       bool redraw = false;
-
-       if (ran->view == 0 && showit) {
-               add_redirect_automation_curve (rai->redirect, ran->what);
-               redraw = true;
-       }
-
-       if (showit != ran->view->marked_for_display()) {
-
-               if (showit) {
-                       ran->view->set_marked_for_display (true);
-                       ran->view->canvas_display->show();
-               } else {
-                       rai->redirect->mark_automation_visible (ran->what, true);
-                       ran->view->set_marked_for_display (false);
-                       ran->view->hide ();
-               }
-
-               redraw = true;
-
-       }
-
-       if (redraw && !no_redraw) {
-
-               /* now trigger a redisplay */
-               
-                _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
-
-       }
-}
-
-void
-AudioTimeAxisView::redirects_changed (void *src)
-{
-       using namespace Menu_Helpers;
-
-       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
-               (*i)->valid = false;
-       }
-
-       subplugin_menu.items().clear ();
-
-       _route->foreach_redirect (this, &AudioTimeAxisView::add_redirect_to_subplugin_menu);
-       _route->foreach_redirect (this, &AudioTimeAxisView::add_existing_redirect_automation_curves);
-
-       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ) {
-
-               list<RedirectAutomationInfo*>::iterator tmp;
-
-               tmp = i;
-               ++tmp;
-
-               if (!(*i)->valid) {
-
-                       delete *i;
-                       redirect_automation.erase (i);
-
-               } 
-
-               i = tmp;
-       }
-
-       /* change in visibility was possible */
-
-       _route->gui_changed ("track_height", this);
-}
-
-RedirectAutomationLine *
-AudioTimeAxisView::find_redirect_automation_curve (boost::shared_ptr<Redirect> redirect, uint32_t what)
-{
-       RedirectAutomationNode* ran;
-
-       if ((ran = find_redirect_automation_node (redirect, what)) != 0) {
-               if (ran->view) {
-                       return dynamic_cast<RedirectAutomationLine*> (ran->view->lines.front());
-               } 
-       }
-
-       return 0;
-}
-
 void
 AudioTimeAxisView::show_all_automation ()
 {
@@ -1661,15 +510,7 @@ AudioTimeAxisView::show_all_automation ()
        pan_automation_item->set_active (true);
        gain_automation_item->set_active (true);
        
-       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
-               for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
-                       if ((*ii)->view == 0) {
-                               add_redirect_automation_curve ((*i)->redirect, (*ii)->what);
-                       } 
-
-                       (*ii)->menu_item->set_active (true);
-               }
-       }
+       RouteTimeAxisView::show_all_automation ();
 
        no_redraw = false;
 
@@ -1684,13 +525,7 @@ AudioTimeAxisView::show_existing_automation ()
        pan_automation_item->set_active (true);
        gain_automation_item->set_active (true);
 
-       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
-               for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
-                       if ((*ii)->view != 0) {
-                               (*ii)->menu_item->set_active (true);
-                       }
-               }
-       }
+       RouteTimeAxisView::show_existing_automation ();
 
        no_redraw = false;
 
@@ -1705,230 +540,58 @@ AudioTimeAxisView::hide_all_automation ()
        pan_automation_item->set_active (false);
        gain_automation_item->set_active (false);
 
-       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
-               for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
-                       (*ii)->menu_item->set_active (false);
-               }
-       }
+       RouteTimeAxisView::hide_all_automation();
 
        no_redraw = false;
         _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
 }
 
-bool
-AudioTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
-{
-       Playlist* what_we_got;
-       AudioDiskstream* 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
-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)
-{
-       for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
-               AutomationTimeAxisView* atv;
-
-               if ((atv = dynamic_cast<AutomationTimeAxisView*> (*i)) != 0) {
-                       arv->add_ghost (*atv);
-               }
-       }
-}
-
-void
-AudioTimeAxisView::add_ghost_to_redirect (AudioRegionView* arv, AutomationTimeAxisView* atv)
-{
-       arv->add_ghost (*atv);
-}
-
-list<TimeAxisView*>
-AudioTimeAxisView::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
-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;
-       }
-}
-
 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);
        }
 }
 
 void
 AudioTimeAxisView::route_active_changed ()
 {
-       RouteUI::route_active_changed ();
+       RouteTimeAxisView::route_active_changed ();
 
        if (is_audio_track()) {
                if (_route->active()) {
@@ -1959,24 +622,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;
-}
index 8a7cf4f9a2fe372d3eafadf5697fe0baa23a10fd..2162771285c32f915c2a45baedcaa2cfdd9884a1 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2000 Paul Davis 
+    Copyright (C) 2000-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
@@ -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>
 #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 "route_time_axis.h"
 #include "canvas.h"
 #include "color.h"
 
-namespace ALSA {
-       class MultiChannelDevice;
-}
-
 namespace ARDOUR {
        class Session;
        class AudioDiskstream;
@@ -56,247 +51,58 @@ 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;
 class AutomationPanLine;
-class RedirectAutomationLine;
 class TimeSelection;
 class AutomationTimeAxisView;
 
-class AudioTimeAxisView : public RouteUI, public TimeAxisView
+class AudioTimeAxisView : public RouteTimeAxisView
 {
   public:
        AudioTimeAxisView (PublicEditor&, ARDOUR::Session&, boost::shared_ptr<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 hide_dependent_views (TimeAxisViewItem&);
        void reveal_dependent_views (TimeAxisViewItem&);
                
-       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 */
+       /* 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;
-
-       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 (boost::shared_ptr<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 route_active_changed ();
 
-       void select_track_color();
+       void build_automation_action_menu ();
+       void append_extra_display_menu_items ();
        
-       virtual 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::CheckMenuItem* gain_automation_item;
-       Gtk::CheckMenuItem* pan_automation_item;
-
-       void automation_click ();
-       void clear_automation ();
-       void hide_all_automation ();
        void show_all_automation ();
        void show_existing_automation ();
+       void hide_all_automation ();
 
-       struct RedirectAutomationNode {
-           uint32_t     what;
-           Gtk::CheckMenuItem* menu_item;
-           AutomationTimeAxisView* view;
-           AudioTimeAxisView& parent;
-
-           RedirectAutomationNode (uint32_t w, Gtk::CheckMenuItem* mitem, AudioTimeAxisView& p)
-                   : what (w), menu_item (mitem), view (0), parent (p) {}
-
-           ~RedirectAutomationNode ();
-       };
-
-       struct RedirectAutomationInfo {
-           boost::shared_ptr<ARDOUR::Redirect> redirect;
-           bool valid;
-           Gtk::Menu* menu;
-           vector<RedirectAutomationNode*> lines;
-
-           RedirectAutomationInfo (boost::shared_ptr<ARDOUR::Redirect> r) 
-                   : redirect (r), valid (true) {}
-
-           ~RedirectAutomationInfo ();
-       };
-
-       list<RedirectAutomationInfo*> redirect_automation;
-       RedirectAutomationNode* find_redirect_automation_node (boost::shared_ptr<ARDOUR::Redirect> redirect, uint32_t what);
-       
-       Gtk::Menu subplugin_menu;
-       void add_redirect_to_subplugin_menu (boost::shared_ptr<ARDOUR::Redirect>);
-
-       void remove_ran (RedirectAutomationNode* ran);
-
-       void redirect_menu_item_toggled (AudioTimeAxisView::RedirectAutomationInfo*,
-                                        AudioTimeAxisView::RedirectAutomationNode*);
-       void redirect_automation_track_hidden (RedirectAutomationNode*, boost::shared_ptr<ARDOUR::Redirect>);
-       
-       vector<RedirectAutomationLine*> redirect_automation_curves;
-       RedirectAutomationLine *find_redirect_automation_curve (boost::shared_ptr<ARDOUR::Redirect>,uint32_t);
-       void add_redirect_automation_curve (boost::shared_ptr<ARDOUR::Redirect>, uint32_t);
-       void add_existing_redirect_automation_curves (boost::shared_ptr<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 ();
@@ -309,14 +115,19 @@ class AudioTimeAxisView : public RouteUI, public TimeAxisView
 
        void update_pans ();
 
-       void region_view_added (AudioRegionView*);
-       void add_ghost_to_redirect (AudioRegionView*, AutomationTimeAxisView*);
-
-       void map_frozen ();
+       AutomationTimeAxisView* gain_track;
+       AutomationTimeAxisView* pan_track;
 
-       void color_handler (ColorID, uint32_t);
-       bool select_me (GdkEventButton*);
+       // Set from XML so context menu automation buttons can be correctly initialized
+       bool show_gain_automation;
+       bool show_pan_automation;
+       
+       Gtk::CheckMenuItem* waveform_item;
+       Gtk::RadioMenuItem* traditional_item;
+       Gtk::RadioMenuItem* rectified_item;
+       Gtk::CheckMenuItem* gain_automation_item;
+       Gtk::CheckMenuItem* pan_automation_item;
 };
 
-#endif /* __ardour_trackview_h__ */
+#endif /* __ardour_audio_time_axis_h__ */
 
index 0c72ed14f976a9d9dced6e0dd099a63c6a81b419..6de11a7c6d90323f6312ea8f6d84284b2e2a728a 100644 (file)
@@ -24,7 +24,7 @@ namespace ARDOUR {
 
 class PublicEditor;
 class TimeSelection;
-class AudioRegionSelection;
+class RegionSelection;
 class PointSelection;
 class AutomationLine;
 class GhostRegion;
index 350698ec483b4ef8e16119a6cd743b08aca6ac43..087af25e7317e9a59e172eaabe4eb7c4a8ca819a 100644 (file)
@@ -29,7 +29,7 @@
 #include "rgb_macros.h"
 #include "audio_time_axis.h"
 #include "public_editor.h"
-#include "regionview.h"
+#include "audio_region_view.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;
index 403edfe297d3ca338a76adf0da0cfda8a54ce4b2..adbd74b42027da577d37d5857ace317eac45fbb9 100644 (file)
 
 #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,
index 95bcf785f9b959456bf4c820e9c93d9672ef2009..518ef7217a2933ede038639747015e010a453303 100644 (file)
 #include "keyboard.h"
 #include "marker.h"
 #include "playlist_selector.h"
-#include "regionview.h"
+#include "audio_region_view.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"
@@ -101,8 +101,8 @@ static const int32_t slide_index = 0;
 static const int32_t splice_index = 1;
 
 static const gchar *edit_mode_strings[] = {
-       N_("Slide"),
-       N_("Splice"),
+       N_("Slide Edit"),
+       N_("Splice Edit"),
        0
 };
 
@@ -131,17 +131,17 @@ static const gchar *snap_type_strings[] = {
 };
 
 static const gchar *snap_mode_strings[] = {
-       N_("Normal"),
-       N_("Magnetic"),
+       N_("Normal Snap"),
+       N_("Magnetic Snap"),
        0
 };
 
 static const gchar *zoom_focus_strings[] = {
-       N_("Left"),
-       N_("Right"),
-       N_("Center"),
-       N_("Playhead"),
-       N_("Edit Cursor"),
+       N_("Focus Left"),
+       N_("Focus Right"),
+       N_("Focus Center"),
+       N_("Focus Play"),
+       N_("Focus Edit"),
        0
 };
 
@@ -204,37 +204,20 @@ Editor::Editor (AudioEngine& eng)
 
          /* tool bar related */
 
-         selection_start_clock (X_("SelectionStartClock"), true),
-         selection_end_clock (X_("SelectionEndClock"), true),
          edit_cursor_clock (X_("EditCursorClock"), true),
          zoom_range_clock (X_("ZoomRangeClock"), true, true),
          
          toolbar_selection_clock_table (2,3),
          
-         mouse_mode_button_table (2, 3),
-
-         mouse_select_button (_("range")),
-         mouse_move_button (_("object")),
-         mouse_gain_button (_("gain")),
-         mouse_zoom_button (_("zoom")),
-         mouse_timefx_button (_("timefx")),
-         mouse_audition_button (_("listen")),
-
          automation_mode_button (_("mode")),
          global_automation_button (_("automation")),
 
-         edit_mode_label (_("Edit Mode")),
-         snap_type_label (_("Snap To")),
-         snap_mode_label(_("Snap Mode")),
-         zoom_focus_label (_("Zoom Focus")),
-
          /* <CMT Additions> */
          image_socket_listener(0),
          /* </CMT Additions> */
 
          /* nudge */
 
-         nudge_label (_("Nudge")),
          nudge_clock (X_("NudgeClock"), true, true)
 
 {
@@ -345,6 +328,7 @@ Editor::Editor (AudioEngine& eng)
        reset_hscrollbar_stepping ();
        
        zoom_focus = ZoomFocusLeft;
+       set_zoom_focus (ZoomFocusLeft);
        zoom_range_clock.ValueChanged.connect (mem_fun(*this, &Editor::zoom_adjustment_changed));
 
        initialize_rulers ();
@@ -465,36 +449,7 @@ Editor::Editor (AudioEngine& eng)
 
        edit_packer.attach (edit_hscrollbar,         2, 3, 2, 3,    FILL|EXPAND,  FILL, 0, 0);
 
-       zoom_in_button.set_name ("EditorTimeButton");
-       zoom_out_button.set_name ("EditorTimeButton");
-       ARDOUR_UI::instance()->tooltips().set_tip (zoom_in_button, _("Zoom in"));
-       ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_button, _("Zoom out"));
-
-       zoom_out_full_button.set_name ("EditorTimeButton");
-       ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_full_button, _("Zoom to session"));
-
-       zoom_in_button.add (*(manage (new Image (Stock::ZOOM_IN, ICON_SIZE_BUTTON))));
-       zoom_out_button.add (*(manage (new Image (Stock::ZOOM_OUT, ICON_SIZE_BUTTON))));
-       zoom_out_full_button.add (*(manage (new Image (Stock::ZOOM_FIT, ICON_SIZE_BUTTON))));
-       
-       zoom_in_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), false));
-       zoom_out_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), true));
-       zoom_out_full_button.signal_clicked().connect (mem_fun(*this, &Editor::temporal_zoom_session));
-       
-       zoom_indicator_box.pack_start (zoom_out_button, false, false);
-       zoom_indicator_box.pack_start (zoom_in_button, false, false);
-       zoom_indicator_box.pack_start (zoom_range_clock, false, false); 
-       zoom_indicator_box.pack_start (zoom_out_full_button, false, false);
-       
-       zoom_indicator_label.set_text (_("Zoom Span"));
-       zoom_indicator_label.set_name ("ToolBarLabel");
-
-       zoom_indicator_vbox.set_spacing (3);
-       zoom_indicator_vbox.set_border_width (3);
-       zoom_indicator_vbox.pack_start (zoom_indicator_label, false, false);
-       zoom_indicator_vbox.pack_start (zoom_indicator_box, false, false);
-
-       bottom_hbox.set_border_width (3);
+       bottom_hbox.set_border_width (2);
        bottom_hbox.set_spacing (3);
 
        route_display_model = ListStore::create(route_display_columns);
@@ -717,15 +672,15 @@ 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 */
 
        nudge_forward_button.add (*(manage (new Image (get_xpm("right_arrow.xpm")))));
        nudge_backward_button.add (*(manage (new Image (get_xpm("left_arrow.xpm")))));
 
-       ARDOUR_UI::instance()->tooltips().set_tip (nudge_forward_button, _("Nudge region/selection forwards"));
-       ARDOUR_UI::instance()->tooltips().set_tip (nudge_backward_button, _("Nudge region/selection backwards"));
+       ARDOUR_UI::instance()->tooltips().set_tip (nudge_forward_button, _("Nudge Region/Selection Forwards"));
+       ARDOUR_UI::instance()->tooltips().set_tip (nudge_backward_button, _("Nudge Region/Selection Backwards"));
 
        nudge_forward_button.set_name ("TransportButton");
        nudge_backward_button.set_name ("TransportButton");
@@ -775,7 +730,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.
@@ -791,7 +746,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;
@@ -1221,7 +1176,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)));
@@ -1242,8 +1197,6 @@ Editor::connect_to_session (Session *t)
        edit_groups_changed ();
 
        edit_cursor_clock.set_session (session);
-       selection_start_clock.set_session (session);
-       selection_end_clock.set_session (session);
        zoom_range_clock.set_session (session);
        _playlist_selector->set_session (session);
        nudge_clock.set_session (session);
@@ -1447,7 +1400,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)));
@@ -1455,16 +1408,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)));
@@ -1472,11 +1425,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:
@@ -1498,8 +1451,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 {
@@ -1539,25 +1492,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;
 
@@ -1637,13 +1591,13 @@ Editor::build_track_region_context_menu (jack_nframes_t frame)
        AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
 
        if (atv) {
-               AudioDiskstream* ds;
+               Diskstream* ds;
                Playlist* pl;
                
                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;
                }
@@ -1664,7 +1618,7 @@ Editor::build_track_crossfade_context_menu (jack_nframes_t frame)
        AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
 
        if (atv) {
-               AudioDiskstream* ds;
+               Diskstream* ds;
                Playlist* pl;
                AudioPlaylist* apl;
 
@@ -1678,11 +1632,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;
@@ -1748,7 +1702,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);
@@ -1805,7 +1759,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);
@@ -2584,30 +2538,56 @@ void
 Editor::setup_toolbar ()
 {
        string pixmap_path;
+
+       const guint32 FUDGE = 18; // Combo's are stupid - they steal space from the entry for the button
+
+
+       /* Mode Buttons (tool selection) */
+
        vector<ToggleButton *> mouse_mode_buttons;
 
+       mouse_move_button.add (*(manage (new Image (get_xpm("tool_object.xpm")))));
+       mouse_move_button.set_relief(Gtk::RELIEF_NONE);
        mouse_mode_buttons.push_back (&mouse_move_button);
+       mouse_select_button.add (*(manage (new Image (get_xpm("tool_range.xpm")))));
+       mouse_select_button.set_relief(Gtk::RELIEF_NONE);
        mouse_mode_buttons.push_back (&mouse_select_button);
+       mouse_gain_button.add (*(manage (new Image (get_xpm("tool_gain.xpm")))));
+       mouse_gain_button.set_relief(Gtk::RELIEF_NONE);
        mouse_mode_buttons.push_back (&mouse_gain_button);
+       mouse_zoom_button.add (*(manage (new Image (get_xpm("tool_zoom.xpm")))));
+       mouse_zoom_button.set_relief(Gtk::RELIEF_NONE);
        mouse_mode_buttons.push_back (&mouse_zoom_button);
+       mouse_timefx_button.add (*(manage (new Image (get_xpm("tool_stretch.xpm")))));
+       mouse_timefx_button.set_relief(Gtk::RELIEF_NONE);
        mouse_mode_buttons.push_back (&mouse_timefx_button);
+       mouse_audition_button.add (*(manage (new Image (get_xpm("tool_audition.xpm")))));
+       mouse_audition_button.set_relief(Gtk::RELIEF_NONE);
        mouse_mode_buttons.push_back (&mouse_audition_button);
+       
        mouse_mode_button_set = new GroupedButtons (mouse_mode_buttons);
 
-       mouse_mode_button_table.set_homogeneous (true);
-       mouse_mode_button_table.set_col_spacings (2);
-       mouse_mode_button_table.set_row_spacings (2);
-       mouse_mode_button_table.set_border_width (5);
+       HBox* mode_box = manage(new HBox);
+       mode_box->set_border_width (2);
+       mode_box->set_spacing(4);
+       mouse_mode_button_box.set_spacing(1);
+       mouse_mode_button_box.pack_start(mouse_move_button, true, true);
+       mouse_mode_button_box.pack_start(mouse_select_button, true, true);
+       mouse_mode_button_box.pack_start(mouse_zoom_button, true, true);
+       mouse_mode_button_box.pack_start(mouse_gain_button, true, true);
+       mouse_mode_button_box.pack_start(mouse_timefx_button, true, true);
+       mouse_mode_button_box.pack_start(mouse_audition_button, true, true);
+       mouse_mode_button_box.set_homogeneous(true);
 
-       mouse_mode_button_table.attach (mouse_move_button, 0, 1, 0, 1);
-       mouse_mode_button_table.attach (mouse_select_button, 1, 2, 0, 1);
-       mouse_mode_button_table.attach (mouse_zoom_button, 2, 3, 0, 1);
-       mouse_mode_button_table.attach (mouse_gain_button, 0, 1, 1, 2);
-       mouse_mode_button_table.attach (mouse_timefx_button, 1, 2, 1, 2);
-       mouse_mode_button_table.attach (mouse_audition_button, 2, 3, 1, 2);
+       edit_mode_selector.set_name ("EditModeSelector");
+       Gtkmm2ext::set_size_request_to_display_given_text (edit_mode_selector, "Splice Edit", 2+FUDGE, 10);
+       set_popdown_strings (edit_mode_selector, internationalize (edit_mode_strings));
+       edit_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::edit_mode_selection_done));
 
-       mouse_mode_tearoff = manage (new TearOff (mouse_mode_button_table));
+       mode_box->pack_start(edit_mode_selector);
+       mode_box->pack_start(mouse_mode_button_box);
+       
+       mouse_mode_tearoff = manage (new TearOff (*mode_box));
        mouse_mode_tearoff->set_name ("MouseModeBase");
 
        mouse_mode_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox), 
@@ -2626,12 +2606,12 @@ Editor::setup_toolbar ()
        mouse_timefx_button.set_name ("MouseModeButton");
        mouse_audition_button.set_name ("MouseModeButton");
 
-       ARDOUR_UI::instance()->tooltips().set_tip (mouse_move_button, _("select/move objects"));
-       ARDOUR_UI::instance()->tooltips().set_tip (mouse_select_button, _("select/move ranges"));
-       ARDOUR_UI::instance()->tooltips().set_tip (mouse_gain_button, _("draw gain automation"));
-       ARDOUR_UI::instance()->tooltips().set_tip (mouse_zoom_button, _("select zoom range"));
-       ARDOUR_UI::instance()->tooltips().set_tip (mouse_timefx_button, _("stretch/shrink regions"));
-       ARDOUR_UI::instance()->tooltips().set_tip (mouse_audition_button, _("listen to specific regions"));
+       ARDOUR_UI::instance()->tooltips().set_tip (mouse_move_button, _("Select/Move Objects"));
+       ARDOUR_UI::instance()->tooltips().set_tip (mouse_select_button, _("Select/Move Ranges"));
+       ARDOUR_UI::instance()->tooltips().set_tip (mouse_gain_button, _("Draw Gain Automation"));
+       ARDOUR_UI::instance()->tooltips().set_tip (mouse_zoom_button, _("Select Zoom Range"));
+       ARDOUR_UI::instance()->tooltips().set_tip (mouse_timefx_button, _("Stretch/Shrink Regions"));
+       ARDOUR_UI::instance()->tooltips().set_tip (mouse_audition_button, _("Listen to Specific Regions"));
 
        mouse_move_button.unset_flags (CAN_FOCUS);
        mouse_select_button.unset_flags (CAN_FOCUS);
@@ -2650,160 +2630,82 @@ Editor::setup_toolbar ()
        mouse_audition_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseAudition));
 
        // mouse_move_button.set_active (true);
+       
 
-       /* automation control */
-
-       global_automation_button.set_name ("MouseModeButton");
-       automation_mode_button.set_name ("MouseModeButton");
-
-       automation_box.set_spacing (2);
-       automation_box.set_border_width (2);
-       automation_box.pack_start (global_automation_button, false, false);
-       automation_box.pack_start (automation_mode_button, false, false);
-
-       /* Edit mode */
-
-       edit_mode_label.set_name ("ToolBarLabel");
-
-       edit_mode_selector.set_name ("EditModeSelector");
+       /* Zoom */
+       
+       zoom_box.set_spacing (1);
+       zoom_box.set_border_width (2);
 
-       edit_mode_box.set_spacing (3);
-       edit_mode_box.set_border_width (3);
+       zoom_in_button.set_name ("EditorTimeButton");
+       zoom_in_button.add (*(manage (new Image (get_xpm("zoom_in.xpm")))));
+       zoom_in_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), false));
+       ARDOUR_UI::instance()->tooltips().set_tip (zoom_in_button, _("Zoom In"));
+       
+       zoom_out_button.set_name ("EditorTimeButton");
+       zoom_out_button.add (*(manage (new Image (get_xpm("zoom_out.xpm")))));
+       zoom_out_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), true));
+       ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_button, _("Zoom Out"));
 
-       /* XXX another disgusting hack because of the way combo boxes size themselves */
+       zoom_out_full_button.set_name ("EditorTimeButton");
+       zoom_out_full_button.add (*(manage (new Image (get_xpm("zoom_full.xpm")))));
+       zoom_out_full_button.signal_clicked().connect (mem_fun(*this, &Editor::temporal_zoom_session));
+       ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_full_button, _("Zoom to Session"));
+       
+       zoom_box.pack_start (zoom_out_button, false, false);
+       zoom_box.pack_start (zoom_in_button, false, false);
+       zoom_box.pack_start (zoom_range_clock, false, false);   
+       zoom_box.pack_start (zoom_out_full_button, false, false);
+       
+       ARDOUR_UI::instance()->tooltips().set_tip (zoom_range_clock, _("Current Zoom Range\n(Width of visible area)"));
+       
+       zoom_focus_selector.set_name ("ZoomFocusSelector");
+       Gtkmm2ext::set_size_request_to_display_given_text (zoom_focus_selector, "Focus Center", 2+FUDGE, 0);
+       set_popdown_strings (zoom_focus_selector, internationalize (zoom_focus_strings));
+       zoom_focus_selector.signal_changed().connect (mem_fun(*this, &Editor::zoom_focus_selection_done));
 
-       const guint32 FUDGE = 20; // Combo's are stupid - they steal space from the entry for the button
-       Gtkmm2ext::set_size_request_to_display_given_text (edit_mode_selector, "EdgtMode", 2+FUDGE, 10);
-       set_popdown_strings (edit_mode_selector, internationalize (edit_mode_strings));
-       edit_mode_box.pack_start (edit_mode_label, false, false);
-       edit_mode_box.pack_start (edit_mode_selector, false, false);
+       zoom_box.pack_start (zoom_focus_selector, false, false);
 
-       edit_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::edit_mode_selection_done));
 
-       /* Snap Type */
+       /* Edit Cursor / Snap */
 
-       snap_type_label.set_name ("ToolBarLabel");
+       snap_box.set_spacing (1);
+       snap_box.set_border_width (2);
 
        snap_type_selector.set_name ("SnapTypeSelector");
-
-       snap_type_box.set_spacing (3);
-       snap_type_box.set_border_width (3);
-
-       /* XXX another disgusting hack because of the way combo boxes size themselves */
-
        Gtkmm2ext::set_size_request_to_display_given_text (snap_type_selector, "SMPTE Seconds", 2+FUDGE, 10);
        set_popdown_strings (snap_type_selector, internationalize (snap_type_strings));
-
-       snap_type_box.pack_start (snap_type_label, false, false);
-       snap_type_box.pack_start (snap_type_selector, false, false);
-
        snap_type_selector.signal_changed().connect (mem_fun(*this, &Editor::snap_type_selection_done));
-
-       /* Snap mode, not snap type */
-
-       snap_mode_label.set_name ("ToolBarLabel");
+       ARDOUR_UI::instance()->tooltips().set_tip (snap_type_selector, _("Unit to snap cursors and ranges to"));
 
        snap_mode_selector.set_name ("SnapModeSelector");
-       
-       snap_mode_box.set_spacing (3);
-       snap_mode_box.set_border_width (3);
-
-       Gtkmm2ext::set_size_request_to_display_given_text (snap_mode_selector, "SngpMode", 2+FUDGE, 10);
+       Gtkmm2ext::set_size_request_to_display_given_text (snap_mode_selector, "Magnetic Snap", 2+FUDGE, 10);
        set_popdown_strings (snap_mode_selector, internationalize (snap_mode_strings));
-
-       snap_mode_box.pack_start (snap_mode_label, false, false);
-       snap_mode_box.pack_start (snap_mode_selector, false, false);
-
        snap_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::snap_mode_selection_done));
 
-       /* Zoom focus mode */
-
-       zoom_focus_label.set_name ("ToolBarLabel");
-
-       zoom_focus_selector.set_name ("ZoomFocusSelector");
-
-       zoom_focus_box.set_spacing (3);
-       zoom_focus_box.set_border_width (3);
-
-       /* XXX another disgusting hack because of the way combo boxes size themselves */
-
-       Gtkmm2ext::set_size_request_to_display_given_text (zoom_focus_selector, "Edgt Cursor", 2+FUDGE, 10);
-       set_popdown_strings (zoom_focus_selector, internationalize (zoom_focus_strings));
-
-       zoom_focus_box.pack_start (zoom_focus_label, false, false);
-       zoom_focus_box.pack_start (zoom_focus_selector, false, false);
-
-       zoom_focus_selector.signal_changed().connect (mem_fun(*this, &Editor::zoom_focus_selection_done));
-
-       /* selection/cursor clocks */
-
-       toolbar_selection_cursor_label.set_name ("ToolBarLabel");
-       selection_start_clock_label.set_name ("ToolBarLabel");
-       selection_end_clock_label.set_name ("ToolBarLabel");
-       edit_cursor_clock_label.set_name ("ToolBarLabel");
-
-       selection_start_clock_label.set_text (_("Start:"));
-       selection_end_clock_label.set_text (_("End:"));
-       edit_cursor_clock_label.set_text (_("Edit"));
-
-       /* the zoom in/out buttons are generally taller than the clocks, so
-          put all the toolbar clocks into a size group with one of the 
-          buttons to make them all equal height.
+       snap_box.pack_start (edit_cursor_clock, false, false);
+       snap_box.pack_start (snap_mode_selector, false, false);
+       snap_box.pack_start (snap_type_selector, false, false);
 
-          this also applies to the various toolbar combos
-       */
-
-       RefPtr<SizeGroup> toolbar_clock_size_group = SizeGroup::create (SIZE_GROUP_VERTICAL);
-       toolbar_clock_size_group->add_widget (zoom_out_button);
-       toolbar_clock_size_group->add_widget (edit_cursor_clock);
-       toolbar_clock_size_group->add_widget (zoom_range_clock);
-       toolbar_clock_size_group->add_widget (nudge_clock);
-       toolbar_clock_size_group->add_widget (edit_mode_selector);
-       toolbar_clock_size_group->add_widget (snap_type_selector);
-       toolbar_clock_size_group->add_widget (snap_mode_selector);
-       toolbar_clock_size_group->add_widget (zoom_focus_selector);
-
-       HBox* edit_clock_hbox = manage (new HBox());
-       VBox* edit_clock_vbox = manage (new VBox());
-
-       edit_clock_hbox->pack_start (edit_cursor_clock, false, false);
-
-       edit_clock_vbox->set_spacing (3);
-       edit_clock_vbox->set_border_width (3);
-       edit_clock_vbox->pack_start (edit_cursor_clock_label, false, false);
-       edit_clock_vbox->pack_start (*edit_clock_hbox, false, false);
-
-       HBox* hbox = new HBox;
 
-       hbox->pack_start (*edit_clock_vbox, false, false);
-       hbox->pack_start (zoom_indicator_vbox, false, false); 
-       hbox->pack_start (zoom_focus_box, false, false);
-       hbox->pack_start (snap_type_box, false, false);
-       hbox->pack_start (snap_mode_box, false, false);
-       hbox->pack_start (edit_mode_box, false, false);
+       /* Nudge */
 
-       VBox *vbox = manage (new VBox);
+       HBox *nudge_box = manage (new HBox);
+       nudge_box->set_spacing(1);
+       nudge_box->set_border_width (2);
 
-       vbox->set_spacing (3);
-       vbox->set_border_width (3);
-
-       HBox *nbox = manage (new HBox);
-       
        nudge_forward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_forward), false));
        nudge_backward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_backward), false));
 
-       nbox->pack_start (nudge_backward_button, false, false);
-       nbox->pack_start (nudge_forward_button, false, false);
-       nbox->pack_start (nudge_clock, false, false, 5);
-
-       nudge_label.set_name ("ToolBarLabel");
+       nudge_box->pack_start (nudge_backward_button, false, false);
+       nudge_box->pack_start (nudge_forward_button, false, false);
+       nudge_box->pack_start (nudge_clock, false, false);
 
-       vbox->pack_start (nudge_label, false, false);
-       vbox->pack_start (*nbox, false, false);
 
-       hbox->pack_start (*vbox, false, false);
+       /* Pack everything in... */
 
-       hbox->show_all ();
+       HBox* hbox = new HBox;
+       hbox->set_spacing(10);
 
        tools_tearoff = new TearOff (*hbox);
        tools_tearoff->set_name ("MouseModeBase");
@@ -2817,11 +2719,18 @@ Editor::setup_toolbar ()
        tools_tearoff->Visible.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox), 
                                              &tools_tearoff->tearoff_window(), 0));
 
-       toolbar_hbox.set_spacing (8);
-       toolbar_hbox.set_border_width (2);
+       toolbar_hbox.set_spacing (10);
+       toolbar_hbox.set_border_width (1);
 
-       toolbar_hbox.pack_start (*tools_tearoff, false, false);
        toolbar_hbox.pack_start (*mouse_mode_tearoff, false, false);
+       toolbar_hbox.pack_start (*tools_tearoff, false, false);
+
+       
+       hbox->pack_start (snap_box, false, false);
+       hbox->pack_start (zoom_box, false, false); 
+       hbox->pack_start (*nudge_box, false, false);
+
+       hbox->show_all ();
        
        toolbar_base.set_name ("ToolBarBase");
        toolbar_base.add (toolbar_hbox);
@@ -3101,31 +3010,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 = 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);
                }
        }
@@ -3134,7 +3043,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) {
@@ -3189,7 +3098,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);
                                        }
                                } 
@@ -3222,58 +3131,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;
 
@@ -3299,18 +3208,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;
                }
        }
@@ -3320,37 +3229,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 = 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);
                                }
                        }
@@ -3379,10 +3283,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;
        }
 
@@ -3394,7 +3298,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;
        }
        
@@ -3559,7 +3463,7 @@ Editor::duplicate_dialog (bool dup_region)
 
        if (sscanf (text.c_str(), "%f", &times) == 1) {
                if (dup_region) {
-                       AudioRegionSelection regions;
+                       RegionSelection regions;
                        regions.add (clicked_regionview);
                        duplicate_some_regions (regions, times);
                } else {
@@ -3610,9 +3514,9 @@ Editor::edit_mode_selection_done ()
        string choice = edit_mode_selector.get_active_text();
        EditMode mode = Slide;
 
-       if (choice == _("Splice")) {
+       if (choice == _("Splice Edit")) {
                mode = Splice;
-       } else if (choice == _("Slide")) {
+       } else if (choice == _("Slide Edit")) {
                mode = Slide;
        }
 
@@ -3628,18 +3532,18 @@ Editor::snap_type_selection_done ()
 
        string choice = snap_type_selector.get_active_text();
        SnapType snaptype = SnapToFrame;
-       
+
        if (choice == _("Beats/3")) {
-                snaptype = SnapToAThirdBeat;
-        } else if (choice == _("Beats/4")) {
-                snaptype = SnapToAQuarterBeat;
-        } else if (choice == _("Beats/8")) {
-                snaptype = SnapToAEighthBeat;
-        } else if (choice == _("Beats/16")) {
-                snaptype = SnapToASixteenthBeat;
-        } else if (choice == _("Beats/32")) {
-                snaptype = SnapToAThirtysecondBeat;
-        } else if (choice == _("Beats")) {
+               snaptype = SnapToAThirdBeat;
+       } else if (choice == _("Beats/4")) {
+               snaptype = SnapToAQuarterBeat;
+       } else if (choice == _("Beats/8")) {
+               snaptype = SnapToAEighthBeat;
+       } else if (choice == _("Beats/16")) {
+               snaptype = SnapToASixteenthBeat;
+       } else if (choice == _("Beats/32")) {
+               snaptype = SnapToAThirtysecondBeat;
+       } else if (choice == _("Beats")) {
                snaptype = SnapToBeat;
        } else if (choice == _("Bars")) {
                snaptype = SnapToBar;
@@ -3667,10 +3571,10 @@ Editor::snap_type_selection_done ()
                snaptype = SnapToSeconds;
        } else if (choice == _("Minutes")) {
                snaptype = SnapToMinutes;
-        } else if (choice == _("None")) {
+       } else if (choice == _("None")) {
                snaptype = SnapToFrame;
        }
-       
+
        set_snap_to (snaptype);
 }      
 
@@ -3684,9 +3588,9 @@ Editor::snap_mode_selection_done ()
        string choice = snap_mode_selector.get_active_text();
        SnapMode mode = SnapNormal;
 
-       if (choice == _("Normal")) {
+       if (choice == _("Normal Snap")) {
                mode = SnapNormal;
-       } else if (choice == _("Magnetic")) {
+       } else if (choice == _("Magnetic Snap")) {
                mode = SnapMagnetic;
        }
 
@@ -3703,15 +3607,15 @@ Editor::zoom_focus_selection_done ()
        string choice = zoom_focus_selector.get_active_text();
        ZoomFocus focus_type = ZoomFocusLeft;
 
-       if (choice == _("Left")) {
+       if (choice == _("Focus Left")) {
                focus_type = ZoomFocusLeft;
-       } else if (choice == _("Right")) {
+       } else if (choice == _("Focus Right")) {
                focus_type = ZoomFocusRight;
-       } else if (choice == _("Center")) {
+       } else if (choice == _("Focus Center")) {
                focus_type = ZoomFocusCenter;
-        } else if (choice == _("Playhead")) {
+       } else if (choice == _("Focus Playhead")) {
                focus_type = ZoomFocusPlayhead;
-        } else if (choice == _("Edit Cursor")) {
+       } else if (choice == _("Focus Edit Cursor")) {
                focus_type = ZoomFocusEdit;
        } 
 
@@ -3781,7 +3685,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);
        }
 }
 
@@ -4051,8 +3955,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;
                }
        }
@@ -4063,10 +3967,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 ();
 }
 
index bfc49b7d0da481998b3d5a54613278e461aaaade..a1e69e2ad1f7a0ed43efeced646a6ae66a45b4c5 100644 (file)
@@ -69,6 +69,7 @@ namespace ARDOUR {
        class AudioDiskstream;
        class RouteGroup;
        class Playlist;
+       class AudioPlaylist;
        class Region;
        class Location;
        class TempoSection;
@@ -83,6 +84,7 @@ namespace LADSPA {
 }
 
 class TimeAxisView;
+class RouteTimeAxisView;
 class AudioTimeAxisView;
 class AutomationTimeAxisView;
 class AudioRegionView;
@@ -100,6 +102,7 @@ class TrackSelection;
 class AutomationSelection;
 class MixerStrip;
 class StreamView;
+class AudioStreamView;
 class ControlPoint;
 #ifdef FFT_ANALYSIS
 class AnalysisWindow;
@@ -405,8 +408,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;
@@ -416,7 +419,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);
@@ -426,7 +429,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);
@@ -434,7 +437,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;
@@ -455,12 +458,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 (boost::shared_ptr<ARDOUR::Route>);
-       void handle_new_route_p (boost::shared_ptr<ARDOUR::Route>);
        void remove_route (TimeAxisView *);
        bool route_removal;
 
@@ -854,7 +856,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 ();
@@ -867,13 +869,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 ();
@@ -1020,7 +1022,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);
 
@@ -1094,7 +1096,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);
@@ -1112,10 +1114,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_name_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*);
-       bool canvas_stream_view_event (GdkEvent* event,ArdourCanvas::Item*, AudioTimeAxisView*);
+       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*, RegionView*);
+       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*);
@@ -1263,12 +1265,7 @@ class Editor : public PublicEditor
 
        void editor_mixer_button_toggled ();
 
-       AudioClock               selection_start_clock;
-       Gtk::Label               selection_start_clock_label;
-       AudioClock               selection_end_clock;
-       Gtk::Label               selection_end_clock_label;
        AudioClock               edit_cursor_clock;
-       Gtk::Label               edit_cursor_clock_label;
        AudioClock               zoom_range_clock;
        Gtk::Button              zoom_in_button;
        Gtk::Button              zoom_out_button;
@@ -1280,8 +1277,8 @@ class Editor : public PublicEditor
        Gtk::Table               toolbar_selection_clock_table;
        Gtk::Label               toolbar_selection_cursor_label;
        
-       Gtk::Table               mouse_mode_button_table;
-       Gtkmm2ext::TearOff*       mouse_mode_tearoff;
+       Gtk::HBox                mouse_mode_button_box;
+       Gtkmm2ext::TearOff*      mouse_mode_tearoff;
        Gtk::ToggleButton        mouse_select_button;
        Gtk::ToggleButton        mouse_move_button;
        Gtk::ToggleButton        mouse_gain_button;
@@ -1299,32 +1296,23 @@ class Editor : public PublicEditor
        Gtk::ToggleButton        global_automation_button;
 
        Gtk::ComboBoxText edit_mode_selector;
-       Gtk::Label               edit_mode_label;
-       Gtk::VBox                edit_mode_box;
+       Gtk::VBox         edit_mode_box;
 
        void edit_mode_selection_done ();
 
        Gtk::ComboBoxText snap_type_selector;
-       Gtk::Label               snap_type_label;
-       Gtk::VBox                snap_type_box;
+       Gtk::ComboBoxText snap_mode_selector;
+       Gtk::HBox         snap_box;
 
        void snap_type_selection_done ();
-
-       Gtk::ComboBoxText               snap_mode_selector;
-       Gtk::Label               snap_mode_label;
-       Gtk::VBox                snap_mode_box;
-
        void snap_mode_selection_done ();
        
        Gtk::ComboBoxText zoom_focus_selector;
-       Gtk::Label               zoom_focus_label;
        Gtk::VBox                zoom_focus_box;
        
        void zoom_focus_selection_done ();
 
-       Gtk::Label          zoom_indicator_label;
-       Gtk::HBox           zoom_indicator_box;
-       Gtk::VBox           zoom_indicator_vbox;
+       Gtk::HBox           zoom_box;
 
        void                update_zoom_indicator ();
        void                zoom_adjustment_changed();
@@ -1533,12 +1521,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 ();
@@ -1592,7 +1580,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 ();
@@ -1600,7 +1588,7 @@ class Editor : public PublicEditor
        void external_edit_region ();
 
        int write_audio_selection (TimeSelection&);
-       bool write_audio_range (ARDOUR::Playlist&, uint32_t channels, list<ARDOUR::AudioRange>&);
+       bool write_audio_range (ARDOUR::AudioPlaylist&, uint32_t channels, list<ARDOUR::AudioRange>&);
 
        void write_selection ();
 
@@ -1670,7 +1658,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;
@@ -1696,7 +1684,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 */
@@ -1775,7 +1763,6 @@ class Editor : public PublicEditor
        Gtk::Button      nudge_backward_button;
        Gtk::HBox        nudge_hbox;
        Gtk::VBox        nudge_vbox;
-       Gtk::Label       nudge_label;
        AudioClock       nudge_clock;
 
        jack_nframes_t get_nudge_distance (jack_nframes_t pos, jack_nframes_t& next);
@@ -1798,11 +1785,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;
index 68c481aa0192337476b8841ee7ffb82bdac1e1ba..f8c632f08a0fc4b0883c581849712b79d9112369 100644 (file)
@@ -316,7 +316,7 @@ Editor::finish_bringing_in_audio (AudioRegion& region, uint32_t in_chans, uint32
                
        case ImportToTrack:
                if (track) {
-                       Playlist* playlist  = track->disk_stream().playlist();
+                       Playlist* playlist  = track->diskstream().playlist();
                        
                        AudioRegion* copy = new AudioRegion (region);
                        begin_reversible_command (_("insert sndfile"));
@@ -333,7 +333,7 @@ Editor::finish_bringing_in_audio (AudioRegion& region, uint32_t in_chans, uint32
        { 
                boost::shared_ptr<AudioTrack> at (session->new_audio_track (in_chans, out_chans, Normal));
                copy = new AudioRegion (region);
-               at->disk_stream().playlist()->add_region (*copy, pos);
+               at->diskstream().playlist()->add_region (*copy, pos);
                break;
        }
 
@@ -341,7 +341,7 @@ Editor::finish_bringing_in_audio (AudioRegion& region, uint32_t in_chans, uint32
        {
                boost::shared_ptr<AudioTrack> at (session->new_audio_track (in_chans, out_chans, Destructive));
                copy = new AudioRegion (region);
-               at->disk_stream().playlist()->add_region (*copy, pos);
+               at->diskstream().playlist()->add_region (*copy, pos);
                break;
        }
        }
index acad3371a0d8cd09cf8feeaf5a127930969085ee..5b575b4814f48ae25a12295822ef04706c14fd76 100644 (file)
@@ -4,7 +4,7 @@
 #include "editor.h"
 #include "editing.h"
 #include "audio_time_axis.h"
-#include "regionview.h"
+#include "region_view.h"
 #include "selection.h"
 
 using namespace ARDOUR;
index 43114534c5a4bf780325b1499f9ee2b7142483f9..8e635bbe13a20bfc7ac49673b017bf00b965dd3e 100644 (file)
@@ -26,8 +26,8 @@
 
 #include "editor.h"
 #include "public_editor.h"
-#include "regionview.h"
-#include "streamview.h"
+#include "audio_region_view.h"
+#include "audio_streamview.h"
 #include "crossfade_view.h"
 #include "audio_time_axis.h"
 #include "region_gain_line.h"
@@ -212,7 +212,7 @@ 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;
 
@@ -251,7 +251,7 @@ 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)
 {
        bool ret = FALSE;
        
@@ -262,7 +262,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;
 
@@ -512,22 +512,25 @@ Editor::canvas_crossfade_view_event (GdkEvent* event, ArdourCanvas::Item* item,
        if ((atv = dynamic_cast<AudioTimeAxisView*>(&tv)) != 0) {
 
                if (atv->is_audio_track()) {
-                       
-                       AudioPlaylist* pl = atv->get_diskstream()->playlist();
-                       Playlist::RegionList* rl = pl->regions_at (event_frame (event));
 
-                       if (!rl->empty()) {
-                               DescendingRegionLayerSorter cmp;
-                               rl->sort (cmp);
+                       AudioPlaylist* pl;
+                       if ((pl = dynamic_cast<AudioPlaylist*> (atv->get_diskstream()->playlist())) != 0) {
+
+                               Playlist::RegionList* rl = pl->regions_at (event_frame (event));
+
+                               if (!rl->empty()) {
+                                       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;
+                                       /* proxy */
 
-                               return canvas_region_view_event (event, arv->get_canvas_group(), arv);
-                       } 
+                                       delete rl;
+
+                                       return canvas_region_view_event (event, rv->get_canvas_group(), rv);
+                               } 
+                       }
                }
        }
 
@@ -696,7 +699,7 @@ 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;
        
@@ -708,20 +711,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:
@@ -732,7 +735,7 @@ Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::
 }
 
 bool
-Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView* rv)
+Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView* rv)
 {
        bool ret = false;
 
@@ -744,20 +747,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:
index 0be0a61b23ed1f4346b573995b1d1b7cec15974d..46a704b435003603f35fde7ff0e72cd32caf89a8 100644 (file)
@@ -31,7 +31,7 @@
 #include "selection.h"
 #include "time_axis_view.h"
 #include "audio_time_axis.h"
-#include "regionview.h"
+#include "audio_region_view.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,26 @@ 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) {
+               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().get());
+               Region& region ((*i)->region());
+               RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(&(*i)->get_time_axis_view());
+               Track* track = dynamic_cast<Track*>(rtv->route().get());
 
                InterThreadInfo itt;
 
@@ -287,7 +289,7 @@ Editor::write_audio_selection (TimeSelection& ts)
 
                if (atv->is_audio_track()) {
 
-                       Playlist* playlist = atv->get_diskstream()->playlist();
+                       AudioPlaylist* playlist = dynamic_cast<AudioPlaylist*>(atv->get_diskstream()->playlist());
                        
                        if (playlist && write_audio_range (*playlist, atv->get_diskstream()->n_channels(), ts) == 0) {
                                ret = -1;
@@ -300,7 +302,7 @@ Editor::write_audio_selection (TimeSelection& ts)
 }
 
 bool
-Editor::write_audio_range (Playlist& playlist, uint32_t channels, list<AudioRange>& range)
+Editor::write_audio_range (AudioPlaylist& playlist, uint32_t channels, list<AudioRange>& range)
 {
        AudioFileSource* fs;
        const jack_nframes_t chunk_size = 4096;
@@ -435,7 +437,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);
        }
 }
index 4f6010ec2c08565971733c5cd71b96f7a0e75aaa..7f3a0d3fccc22c3bbf874e367d9065dc24e9fd8a 100644 (file)
@@ -23,8 +23,8 @@ enum ItemType {
        TempoMarkerItem,
        MeterBarItem,
        TempoBarItem,
-       AudioRegionViewNameHighlight,
-       AudioRegionViewName,
+       RegionViewNameHighlight,
+       RegionViewName,
        StartSelectionTrimItem,
        EndSelectionTrimItem,
        AutomationTrackItem,
index 1ffaf2146d906878cf9a5f7287b93d29349f5af6..d2b7c1160e5af6de11e273ebc47bdbe6528c4ca1 100644 (file)
@@ -22,7 +22,7 @@
 #include <ardour/playlist.h>
 
 #include "editor.h"
-#include "regionview.h"
+#include "region_view.h"
 #include "selection.h"
 
 #include "i18n.h"
@@ -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);
        }
 }
 
index baa158cbf8374c6e73ceda214b1227ccbbcda0db..1bcaafd27957f1a045f801b012698b9498592630 100644 (file)
@@ -30,7 +30,7 @@
 #include "ardour_ui.h"
 #include "editor.h"
 #include "time_axis_view.h"
-#include "regionview.h"
+#include "region_view.h"
 #include "selection.h"
 
 #include "i18n.h"
@@ -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);
        }
 }
 
index a584561e428bc3b5f1fa33ed7cb87fecbe5beb3c..f34b8590a48a9d0e079a67c7b290354b53ea5daf 100644 (file)
@@ -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());
                                }
                        }
                }
index 1418ece574e00c63e5157c29ddb0cce3c81678e1..246dbdc6473337501d943c82165bf8c175b27cdd 100644 (file)
@@ -270,8 +270,6 @@ Editor::session_going_away ()
        group_model->clear ();
 
        edit_cursor_clock.set_session (0);
-       selection_start_clock.set_session (0);
-       selection_end_clock.set_session (0);
        zoom_range_clock.set_session (0);
        nudge_clock.set_session (0);
 
index 8b6729cc4a3bf43ac39534920478214bbeb8105f..7e9af2dcb01f1acdec388a0ae9ea895c3c1c558f 100644 (file)
@@ -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_region_view.h"
 #include "marker.h"
 #include "streamview.h"
 #include "region_gain_line.h"
@@ -182,7 +183,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 +320,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 +522,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 +693,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 +854,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 +889,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 +1048,13 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                        break;
 
                case MouseGain:
+                       // Gain only makes sense for audio regions
+                       if ( ! dynamic_cast<AudioRegionView*>(clicked_regionview))
+                               break;
+
                        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 +1208,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 +1235,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 +1344,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 +1366,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 +1397,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 +1434,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 +1529,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 +1750,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 +1771,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 +1806,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 +1840,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 +1861,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 +1898,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 +2556,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 +2651,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 +2665,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 +2685,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 +2696,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 +2704,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 +2715,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 +2729,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
@@ -2744,7 +2750,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
 {
        double x_delta;
        double y_delta = 0;
-       AudioRegionView *rv = reinterpret_cast<AudioRegionView*> (drag_info.data); 
+       RegionView* rv = reinterpret_cast<RegionView*> (drag_info.data); 
        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 +2770,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 +2790,21 @@ 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.  need a (virtual) Region::duplicate() or something?
+                       Region* newregion = NULL;
+                       if (dynamic_cast<AudioRegion*>(&rv->region()))
+                               newregion = new AudioRegion (dynamic_cast<AudioRegion&>(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 +2916,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 +3019,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 +3039,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 +3081,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 +3103,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 +3188,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) {
@@ -3210,7 +3214,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
 
                        AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (&rv->get_time_axis_view());
                        if (atv && atv->is_audio_track()) {
-                               AudioPlaylist* pl = atv->get_diskstream()->playlist();
+                               AudioPlaylist* pl = dynamic_cast<AudioPlaylist*>(atv->get_diskstream()->playlist());
                                if (pl) {
                                        /* only freeze and capture state once */
 
@@ -3246,11 +3250,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 +3288,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 +3298,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 +3321,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 +3333,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 +3356,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 +3368,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 +3391,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 +3417,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 +3458,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 +3583,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 +3616,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 +3651,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 +3892,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 +3934,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 +3946,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 +3985,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 +4008,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 +4035,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 +4046,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 +4061,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 +4073,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 +4101,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 +4135,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 +4176,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 +4200,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 +4215,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 +4243,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 +4270,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 +4281,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 +4673,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 +4690,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 +4699,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 +4721,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 +4731,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 +4750,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 +4788,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 +4802,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
index d3845dd26bb6b09d7cd889180be5e900cd400b06..bdaeb5aa9716a44e1c7f94d6966d967070ae201f 100644 (file)
@@ -51,7 +51,7 @@
 #include "audio_time_axis.h"
 #include "automation_time_axis.h"
 #include "streamview.h"
-#include "regionview.h"
+#include "audio_region_view.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,14 +2115,14 @@ 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());
+               session->audition_region (rv->region());
        }
 }
 
 void
-Editor::audition_playlist_region_standalone (AudioRegion& region)
+Editor::audition_playlist_region_standalone (Region& region)
 {
        session->audition_region (region);
 }
@@ -2170,7 +2172,6 @@ Editor::region_from_selection ()
        jack_nframes_t selection_cnt = end - start + 1;
        
        for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
-
                AudioRegion *region;
                AudioRegion *current;
                Region* current_r;
@@ -2187,7 +2188,9 @@ Editor::region_from_selection ()
                        continue;
                }
 
-               if ((current = dynamic_cast<AudioRegion*> (current_r)) != 0) {
+               current = dynamic_cast<AudioRegion*> (current_r);
+               // FIXME: audio only
+               if (current != 0) {
                        internal_start = start - current->position();
                        session->region_name (new_name, current->name(), true);
                        region = new AudioRegion (*current, internal_start, selection_cnt, new_name);
@@ -2237,11 +2240,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 +2424,7 @@ Editor::region_fill_track ()
 {
        jack_nframes_t end;
 
-       if (!session || selection->audio_regions.empty()) {
+       if (!session || selection->regions.empty()) {
                return;
        }
 
@@ -2427,9 +2432,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*>(&region);
+               if (!ar)
+                       continue;
 
-               AudioRegion& region ((*i)->region);
                Playlist* pl = region.playlist();
 
                if (end <= region.last_frame()) {
@@ -2443,7 +2454,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 +2533,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 +2550,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 +2562,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 +2588,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 +2603,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 +2631,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 +2653,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 +2705,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 +2730,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 +2901,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 +2967,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 +2982,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 +3003,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 +3166,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 +3353,7 @@ Editor::normalize_region ()
                return;
        }
 
-       if (selection->audio_regions.empty()) {
+       if (selection->regions.empty()) {
                return;
        }
 
@@ -3345,10 +3362,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 +3383,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 +3416,7 @@ Editor::reverse_region ()
 void
 Editor::apply_filter (AudioFilter& filter, string command)
 {
-       if (selection->audio_regions.empty()) {
+       if (selection->regions.empty()) {
                return;
        }
 
@@ -3402,20 +3425,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 +3450,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 +3459,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 +3468,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 +3494,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 +3515,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);
        }
 }
index 12240dfb132531c3664924848bdee339c503cefe..c93cf9aba290f64ec80a3cacba65f80d46737574 100644 (file)
@@ -38,16 +38,11 @@ using namespace ARDOUR;
 using namespace PBD;
 using namespace Gtk;
 
-void
-Editor::handle_new_route_p (boost::shared_ptr<Route> route)
-{
-       ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::handle_new_route_p), route));
-       handle_new_route (route);
-}
-
 void
 Editor::handle_new_route (boost::shared_ptr<Route> route)
 {
+       ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::handle_new_route), route));
+       
        TimeAxisView *tv;
        AudioTimeAxisView *atv;
        TreeModel::Row parent;
index 278ab57ebde106c2f3b52c97a7c497ddd4c2a7b0..79772090f6b61b86de2d540327c43c750b7dd169 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "editor.h"
 #include "audio_time_axis.h"
-#include "regionview.h"
+#include "audio_region_view.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 = atv->audio_track()) == 0) {
+               if ((t = dynamic_cast<Track*> (rtv->route().get())) == 0) {
                        i = tmp;
                        continue;
                }
        
-               if ((playlist = at->disk_stream().playlist()) == 0) {
+               if ((playlist = t->diskstream().playlist()) == 0) {
                        i = tmp;
                        continue;
                }
 
-               dialog.request.region = &aregion;
+               dialog.request.region = &region;
 
                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;
index 97bf7c22b1ec4190be28c06dcb6e62903a67ea1e..1964fabbfe61ce979143ed3455f7dc8d969ccd65 100644 (file)
@@ -18,6 +18,8 @@
 
 */
 
+#include <cassert>
+
 #include <pbd/pthread_utils.h>
 #include <ardour/audioregion.h>
 
 #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();
 }
index 00464eb5b39f86ac6aabed5d8808295d887cb268..e8afe97d6b188416ffb86f98e635f93b669843b0 100644 (file)
@@ -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 ();
index 1313fc40826d29fdbaa90c775e33eace13719eee..4f3dc720d917aac8074ca5bc8cbbbd4a901b392a 100644 (file)
@@ -290,8 +290,8 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr<Route> rt
        _route->panner().Changed.connect (mem_fun(*this, &MixerStrip::connect_to_pan));
 
        if (is_audio_track()) {
-               audio_track()->diskstream_changed.connect (mem_fun(*this, &MixerStrip::diskstream_changed));
-               get_diskstream()->speed_changed.connect (mem_fun(*this, &MixerStrip::speed_changed));
+               audio_track()->DiskstreamChanged.connect (mem_fun(*this, &MixerStrip::diskstream_changed));
+               get_diskstream()->SpeedChanged.connect (mem_fun(*this, &MixerStrip::speed_changed));
        }
 
        _route->name_changed.connect (mem_fun(*this, &RouteUI::name_changed));
@@ -558,11 +558,6 @@ MixerStrip::input_press (GdkEventButton *ev)
 
        case 1:
 
-#if ADVANCED_ROUTE_DISKSTREAM_CONNECTIVITY
-               if (is_audio_track()) {
-                       citems.push_back (MenuElem (_("Track"), mem_fun(*this, &MixerStrip::select_stream_input)));
-               }
-#endif
                citems.push_back (MenuElem (_("Edit"), mem_fun(*this, &MixerStrip::edit_input_configuration)));
                citems.push_back (SeparatorElem());
                citems.push_back (MenuElem (_("Disconnect"), mem_fun (*(static_cast<RouteUI*>(this)), &RouteUI::disconnect_input)));
@@ -659,42 +654,6 @@ MixerStrip::add_connection_to_output_menu (ARDOUR::Connection* c)
        }
 }
 
-void
-MixerStrip::select_stream_input ()
-{
-       using namespace Menu_Helpers;
-
-       Menu *stream_menu = manage (new Menu);
-       MenuList& items = stream_menu->items();
-       stream_menu->set_name ("ArdourContextMenu");
-       
-       Session::AudioDiskstreamList streams = _session.audio_disk_streams();
-
-       for (Session::AudioDiskstreamList::iterator i = streams.begin(); i != streams.end(); ++i) {
-
-               if (!(*i)->hidden()) {
-
-                       items.push_back (CheckMenuElem ((*i)->name(), bind (mem_fun(*this, &MixerStrip::stream_input_chosen), *i)));
-                       
-                       if (get_diskstream() == *i) {
-                               ignore_toggle = true;
-                               static_cast<CheckMenuItem *> (&items.back())->set_active (true);
-                               ignore_toggle = false;
-                       } 
-               }
-       }
-       
-       stream_menu->popup (1, 0);
-}
-
-void
-MixerStrip::stream_input_chosen (AudioDiskstream *stream)
-{
-       if (is_audio_track()) {
-               audio_track()->set_diskstream (*stream, this);
-       }
-}
-
 void
 MixerStrip::update_diskstream_display ()
 {
@@ -785,7 +744,7 @@ MixerStrip::fast_update ()
 }
 
 void
-MixerStrip::diskstream_changed (void *src)
+MixerStrip::diskstream_changed ()
 {
        Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &MixerStrip::update_diskstream_display));
 }      
@@ -1181,7 +1140,7 @@ MixerStrip::route_active_changed ()
                        gpm.set_meter_strip_name ("AudioTrackStripBaseInactive");
                }
                gpm.set_fader_name ("AudioTrackFader");
-       } else {
+       } else { // FIXME: assumed audio bus
                if (_route->active()) {
                        set_name ("AudioBusStripBase");
                        gpm.set_meter_strip_name ("AudioBusStripBase");
index e7b68ade48f1ccb75bae9d980bcae6fd19cdea3e..831b75eeaf2867dbfec8091251c8d164e97f6c68 100644 (file)
@@ -179,7 +179,7 @@ class MixerStrip : public RouteUI, public Gtk::EventBox
        void edit_input_configuration ();
        void edit_output_configuration ();
 
-       void diskstream_changed (void *src);
+       void diskstream_changed ();
 
        Gtk::Menu *send_action_menu;
        void build_send_action_menu ();
diff --git a/gtk2_ardour/pixmaps/tool_audition.xpm b/gtk2_ardour/pixmaps/tool_audition.xpm
new file mode 100644 (file)
index 0000000..d6f2ccd
--- /dev/null
@@ -0,0 +1,19 @@
+/* XPM */
+static char * tool_audition_xpm[] = {
+"16 12 4 1",
+"      c None",
+".     c #000000",
+"+     c #ECECEC",
+"@     c #FFFFFF",
+"      ..        ",
+"     .+.    .   ",
+"    .++.   .@.  ",
+"....+@+...  .@. ",
+".+++@@+..@.  .@.",
+".+@@@@+. .@. .@.",
+".+@@@@+. .@. .@.",
+".+++@@+..@.  .@.",
+"....+@+...  .@. ",
+"    .++.   .@.  ",
+"     .+.    .   ",
+"      ..        "};
diff --git a/gtk2_ardour/pixmaps/tool_gain.xpm b/gtk2_ardour/pixmaps/tool_gain.xpm
new file mode 100644 (file)
index 0000000..480426f
--- /dev/null
@@ -0,0 +1,18 @@
+/* XPM */
+static char * tool_gain_xpm[] = {
+"16 12 3 1",
+"      c None",
+".     c #000000",
+"+     c #FFFFFF",
+"...             ",
+".++..           ",
+"...++.          ",
+"   ..+.         ",
+"     .+.        ",
+"     .+.        ",
+"      .+.       ",
+"      .+.       ",
+"       .+..     ",
+"        .++.....",
+"         ..++++.",
+"           ....."};
diff --git a/gtk2_ardour/pixmaps/tool_object.xpm b/gtk2_ardour/pixmaps/tool_object.xpm
new file mode 100644 (file)
index 0000000..3d18ab8
--- /dev/null
@@ -0,0 +1,18 @@
+/* XPM */
+static char * tool_object_xpm[] = {
+"16 12 3 1",
+"      c None",
+".     c #000000",
+"+     c #FFFFFF",
+"     ...        ",
+"     .+.        ",
+"     .+.        ",
+"     .+.        ",
+"     .+.....    ",
+"     .+.+.+...  ",
+"   ...+.+.+.+.  ",
+"   .+.+++++++.  ",
+"   .+++++++++.  ",
+"   ..+++++++..  ",
+"    ...+++++.   ",
+"      .+++++.   "};
diff --git a/gtk2_ardour/pixmaps/tool_range.xpm b/gtk2_ardour/pixmaps/tool_range.xpm
new file mode 100644 (file)
index 0000000..75ee865
--- /dev/null
@@ -0,0 +1,18 @@
+/* XPM */
+static char * tool_range_xpm[] = {
+"16 12 3 1",
+"      c None",
+".     c #000000",
+"+     c #FFFFFF",
+"...          ...",
+".+.  ..  ..  .+.",
+".+. .+.  .+. .+.",
+".+..+.    .+..+.",
+".+.++......++.+.",
+".++++++++++++++.",
+".+.++......++.+.",
+".+..+.    .+..+.",
+".+. .+.  .+. .+.",
+".+.  ..  ..  .+.",
+".+.          .+.",
+"...          ..."};
diff --git a/gtk2_ardour/pixmaps/tool_stretch.xpm b/gtk2_ardour/pixmaps/tool_stretch.xpm
new file mode 100644 (file)
index 0000000..77943cd
--- /dev/null
@@ -0,0 +1,18 @@
+/* XPM */
+static char * tool_stretch_xpm[] = {
+"16 12 3 1",
+"      c None",
+".     c #000000",
+"+     c #FFFFFF",
+"  ..        ..  ",
+" .+.        .+. ",
+".++..........++.",
+"++++++++++++++++",
+".++..........++.",
+" .+.        .+. ",
+"  ..        ..  ",
+" +  +   +    +  ",
+" ++ +++ + + +++ ",
+"++++++++++++++++",
+"  ++  +  ++ + + ",
+"  +   +   +   + "};
diff --git a/gtk2_ardour/pixmaps/tool_zoom.xpm b/gtk2_ardour/pixmaps/tool_zoom.xpm
new file mode 100644 (file)
index 0000000..581363f
--- /dev/null
@@ -0,0 +1,29 @@
+/* XPM */
+static char * tool_zoom_xpm[] = {
+"16 12 14 1",
+"      c None",
+".     c #000000",
+"+     c #474747",
+"@     c #E7E7E7",
+"#     c #F6F6F6",
+"$     c #DCDCDC",
+"%     c #FFFFFF",
+"&     c #DFDFDF",
+"*     c #D7D7D7",
+"=     c #D6D6D6",
+"-     c #040404",
+";     c #070707",
+">     c #060606",
+",     c #050505",
+"     ...        ",
+"   +.@#$.+      ",
+"   .%%%%%.      ",
+"  .&%%%%%*.     ",
+"  .#%%%%%#.     ",
+"  .$%%%%%&.     ",
+"   .%%%%%.+     ",
+"   +.*#=...     ",
+"     ...+...    ",
+"          -.;   ",
+"           >.-  ",
+"            ,.  "};
diff --git a/gtk2_ardour/pixmaps/zoom_full.xpm b/gtk2_ardour/pixmaps/zoom_full.xpm
new file mode 100644 (file)
index 0000000..5564074
--- /dev/null
@@ -0,0 +1,30 @@
+/* XPM */
+static char * zoom_full_xpm[] = {
+"12 12 15 1",
+"      c None",
+".     c #000000",
+"+     c #474747",
+"@     c #E7E7E7",
+"#     c #F6F6F6",
+"$     c #DCDCDC",
+"%     c #ACACAC",
+"&     c #FFFFFF",
+"*     c #DFDFDF",
+"=     c #D7D7D7",
+"-     c #D6D6D6",
+";     c #040404",
+">     c #070707",
+",     c #060606",
+"'     c #050505",
+"   ...      ",
+" +.@#$.+    ",
+" .%&&&%.    ",
+".*..&..=.   ",
+".#.&&&.#.   ",
+".$..&..*.   ",
+" .%&&&%.+   ",
+" +.=#-...   ",
+"   ...+...  ",
+"        ;.> ",
+"         ,.;",
+"          '."};
diff --git a/gtk2_ardour/pixmaps/zoom_in.xpm b/gtk2_ardour/pixmaps/zoom_in.xpm
new file mode 100644 (file)
index 0000000..1f8d4e8
--- /dev/null
@@ -0,0 +1,29 @@
+/* XPM */
+static char * zoom_in_xpm[] = {
+"12 12 14 1",
+"      c None",
+".     c #000000",
+"+     c #474747",
+"@     c #E7E7E7",
+"#     c #F6F6F6",
+"$     c #DCDCDC",
+"%     c #FFFFFF",
+"&     c #DFDFDF",
+"*     c #D7D7D7",
+"=     c #D6D6D6",
+"-     c #040404",
+";     c #070707",
+">     c #060606",
+",     c #050505",
+"   ...      ",
+" +.@#$.+    ",
+" .%%.%%.    ",
+".&%%.%%*.   ",
+".#.....#.   ",
+".$%%.%%&.   ",
+" .%%.%%.+   ",
+" +.*#=...   ",
+"   ...+...  ",
+"        -.; ",
+"         >.-",
+"          ,."};
diff --git a/gtk2_ardour/pixmaps/zoom_out.xpm b/gtk2_ardour/pixmaps/zoom_out.xpm
new file mode 100644 (file)
index 0000000..ea50d14
--- /dev/null
@@ -0,0 +1,29 @@
+/* XPM */
+static char * zoom_out_xpm[] = {
+"12 12 14 1",
+"      c None",
+".     c #000000",
+"+     c #474747",
+"@     c #E7E7E7",
+"#     c #F6F6F6",
+"$     c #DCDCDC",
+"%     c #FFFFFF",
+"&     c #DFDFDF",
+"*     c #D7D7D7",
+"=     c #D6D6D6",
+"-     c #040404",
+";     c #070707",
+">     c #060606",
+",     c #050505",
+"   ...      ",
+" +.@#$.+    ",
+" .%%%%%.    ",
+".&%%%%%*.   ",
+".#.....#.   ",
+".$%%%%%&.   ",
+" .%%%%%.+   ",
+" +.*#=...   ",
+"   ...+...  ",
+"        -.; ",
+"         >.-",
+"          ,."};
index 5633404094b6246512485aa090baf881e37c88f5..8eaac7cb9d3e74814db7bab3523fc1dd3075d03b 100644 (file)
@@ -90,7 +90,7 @@ void
 PlaylistSelector::show_for (RouteUI* ruix)
 {
        vector<const char*> item;
-       AudioDiskstream* this_ds;
+       Diskstream* this_ds;
        string str;
 
        rui = ruix;
@@ -116,7 +116,7 @@ PlaylistSelector::show_for (RouteUI* ruix)
        
        for (DSPL_Map::iterator x = dspl_map.begin(); x != dspl_map.end(); ++x) {
 
-               AudioDiskstream* ds = session->diskstream_by_id (x->first);
+               Diskstream* ds = session->diskstream_by_id (x->first);
 
                if (ds == 0) {
                        continue;
@@ -243,7 +243,7 @@ PlaylistSelector::selection_changed ()
                        return;
                }
                
-               at->disk_stream().use_playlist (apl);
+               at->diskstream().use_playlist (apl);
 
                hide ();
        }
index 25cba998dfa5910b0a1234ee03f2c04646c939f5..18bf06bf04dd2aea14ca4fe9acfe670a23ac82bf 100644 (file)
@@ -29,6 +29,7 @@ namespace ARDOUR {
        class Session;
        class PluginManager;
        class Plugin;
+       class PluginInfo;
 }
 
 class PluginSelector : public ArdourDialog
index 4c12b99d7c64ee6c1edbf3fc9d6d86968bd49cbb..f70e4c20bd5ee163f2bbf7ea2ccfe581d21194bc 100644 (file)
@@ -39,7 +39,7 @@ class AutomationLine;
 class ControlPoint;
 class SelectionRect;
 class CrossfadeView;
-class AudioTimeAxisView;
+class RouteTimeAxisView;
 class AudioRegionView;
 class TempoMarker;
 class MeterMarker;
@@ -145,10 +145,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_name_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*) = 0;
-       virtual bool canvas_stream_view_event (GdkEvent* event,ArdourCanvas::Item*, AudioTimeAxisView*) = 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*, RegionView*) = 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.cc b/gtk2_ardour/region_editor.cc
deleted file mode 100644 (file)
index 413ff01..0000000
+++ /dev/null
@@ -1,732 +0,0 @@
-/*
-    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$
-*/
-
-#include <ardour/audioregion.h>
-#include <ardour/utils.h>
-#include <gtkmm2ext/utils.h>
-#include <gtkmm2ext/stop_signal.h>
-#include <cmath>
-
-#include "region_editor.h"
-#include "regionview.h"
-#include "ardour_ui.h"
-#include "utils.h"
-#include "gui_thread.h"
-
-#include "i18n.h"
-
-using namespace ARDOUR;
-using namespace PBD;
-using namespace sigc;
-using namespace std;
-
-AudioRegionEditor::AudioRegionEditor (Session&s, AudioRegion& r, AudioRegionView& rv)
-       : ArdourDialog ("audio region editor"),
-         _session (s),
-         _region (r),
-         _region_view (rv),
-         name_label (_("NAME:")),
-         lock_button (_("lock")),
-         mute_button (_("mute")),
-         opaque_button (_("opaque")),
-         envelope_active_button(_("active")),
-         envelope_view_button(_("visible")),
-         raise_arrow (Gtk::ARROW_UP, Gtk::SHADOW_OUT),
-         lower_arrow (Gtk::ARROW_DOWN, Gtk::SHADOW_OUT),
-         layer_label (_("Layer")),
-         audition_button (_("play")),
-         time_table (3, 2),
-         start_clock ("AudioRegionEditorClock", true),
-         end_clock ("AudioRegionEditorClock", true),
-         length_clock ("AudioRegionEditorClock", true, true),
-         sync_offset_clock ("AudioRegionEditorClock", true, true),
-         envelope_loop_table (1, 3),
-         envelope_label (_("ENVELOPE")),
-         fade_in_table (4, 3),
-         fade_in_length_adjustment (5.0, 0.0, 10000, 0.05, 1),
-         fade_in_length_spinner (fade_in_length_adjustment, 10),
-         fade_out_table (4, 3),
-         fade_out_length_adjustment (5.0, 0.0, 10000, 0.05, 1),
-         fade_out_length_spinner (fade_out_length_adjustment, 10)
-
-{
-       start_clock.set_session (&_session);
-       end_clock.set_session (&_session);
-       length_clock.set_session (&_session);
-
-       name_entry.set_name ("AudioRegionEditorEntry");
-       name_label.set_name ("AudioRegionEditorLabel");
-
-       name_hbox.set_spacing (5);
-       name_hbox.pack_start (name_label, false, false);
-       name_hbox.pack_start (name_entry, false, false);
-
-       raise_button.add (raise_arrow);
-       lower_button.add (lower_arrow);
-       layer_frame.set_name ("BaseFrame");
-       layer_frame.set_shadow_type (Gtk::SHADOW_IN);
-       layer_frame.add (layer_value_label);
-       layer_label.set_name ("AudioRegionEditorLabel");
-       layer_value_label.set_name ("AudioRegionEditorLabel");
-       Gtkmm2ext::set_size_request_to_display_given_text (layer_value_label, "99", 5, 2);
-
-       layer_hbox.set_spacing (5);
-       layer_hbox.pack_start (layer_label, false, false);
-       layer_hbox.pack_start (layer_frame, false, false);
-#if 0
-       layer_hbox.pack_start (raise_button, false, false);
-       layer_hbox.pack_start (lower_button, false, false);
-#endif
-
-       mute_button.set_name ("AudioRegionEditorToggleButton");
-       opaque_button.set_name ("AudioRegionEditorToggleButton");
-       lock_button.set_name ("AudioRegionEditorToggleButton");
-       envelope_active_button.set_name ("AudioRegionEditorToggleButton");
-       envelope_view_button.set_name ("AudioRegionEditorToggleButton");
-       fade_in_active_button.set_name ("AudioRegionEditorToggleButton");
-       fade_out_active_button.set_name ("AudioRegionEditorToggleButton");
-       audition_button.set_name ("AudioRegionEditorToggleButton");
-
-       ARDOUR_UI::instance()->tooltips().set_tip (mute_button, _("mute this region"));
-       ARDOUR_UI::instance()->tooltips().set_tip (opaque_button, _("regions underneath this one cannot be heard"));
-       ARDOUR_UI::instance()->tooltips().set_tip (lock_button, _("prevent any changes to this region"));
-       ARDOUR_UI::instance()->tooltips().set_tip (envelope_active_button, _("use the gain envelope during playback"));
-       ARDOUR_UI::instance()->tooltips().set_tip (envelope_view_button, _("show the gain envelope"));
-       ARDOUR_UI::instance()->tooltips().set_tip (fade_in_active_button, _("use fade in curve during playback"));
-       ARDOUR_UI::instance()->tooltips().set_tip (fade_out_active_button, _("use fade out curve during playback"));
-       ARDOUR_UI::instance()->tooltips().set_tip (audition_button, _("audition this region"));
-
-       mute_button.unset_flags (Gtk::CAN_FOCUS);
-       opaque_button.unset_flags (Gtk::CAN_FOCUS);
-       lock_button.unset_flags (Gtk::CAN_FOCUS);
-       envelope_active_button.unset_flags (Gtk::CAN_FOCUS);
-       envelope_view_button.unset_flags (Gtk::CAN_FOCUS);
-       fade_in_active_button.unset_flags (Gtk::CAN_FOCUS);
-       fade_out_active_button.unset_flags (Gtk::CAN_FOCUS);
-       audition_button.unset_flags (Gtk::CAN_FOCUS);
-       
-       mute_button.set_events (mute_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
-       opaque_button.set_events (opaque_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
-       lock_button.set_events (lock_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
-       envelope_active_button.set_events (envelope_active_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
-       envelope_view_button.set_events (envelope_view_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
-       fade_in_active_button.set_events (fade_in_active_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
-       fade_out_active_button.set_events (fade_out_active_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
-       audition_button.set_events (audition_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
-
-       top_row_button_hbox.set_border_width (5);
-       top_row_button_hbox.set_spacing (5);
-       top_row_button_hbox.set_homogeneous (false);
-       top_row_button_hbox.pack_start (mute_button, false, false);
-       top_row_button_hbox.pack_start (opaque_button, false, false);
-       top_row_button_hbox.pack_start (lock_button, false, false);
-       top_row_button_hbox.pack_start (layer_hbox, false, false, 5);
-       top_row_button_hbox.pack_end (audition_button, false, false);
-       
-       top_row_hbox.pack_start (name_hbox, true, true);
-       top_row_hbox.pack_end (top_row_button_hbox, true, true);
-
-       start_label.set_name ("AudioRegionEditorLabel");
-       start_label.set_text (_("START:"));
-       end_label.set_name ("AudioRegionEditorLabel");
-       end_label.set_text (_("END:"));
-       length_label.set_name ("AudioRegionEditorLabel");
-       length_label.set_text (_("LENGTH:"));
-       
-       time_table.set_col_spacings (2);
-       time_table.set_row_spacings (5);
-       time_table.set_border_width (5);
-
-       start_alignment.set (1.0, 0.5);
-       end_alignment.set (1.0, 0.5);
-       length_alignment.set (1.0, 0.5);
-
-       start_alignment.add (start_label);
-       end_alignment.add (end_label);
-       length_alignment.add (length_label);
-
-       time_table.attach (start_alignment, 0, 1, 0, 1, Gtk::FILL, Gtk::FILL);
-       time_table.attach (start_clock, 1, 2, 0, 1, Gtk::FILL, Gtk::FILL);
-
-       time_table.attach (end_alignment, 0, 1, 1, 2, Gtk::FILL, Gtk::FILL);
-       time_table.attach (end_clock, 1, 2, 1, 2, Gtk::FILL, Gtk::FILL);
-
-       time_table.attach (length_alignment, 0, 1, 2, 3, Gtk::FILL, Gtk::FILL);
-       time_table.attach (length_clock, 1, 2, 2, 3, Gtk::FILL, Gtk::FILL);
-
-       envelope_label.set_name ("AudioRegionEditorLabel");
-
-       envelope_loop_table.set_border_width (5);
-       envelope_loop_table.set_row_spacings (2);
-       envelope_loop_table.attach (envelope_label, 0, 1, 0, 1, Gtk::FILL, Gtk::FILL);
-       envelope_loop_table.attach (envelope_active_button, 0, 1, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
-       envelope_loop_table.attach (envelope_view_button, 0, 1, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
-
-       /* fade in */
-
-       fade_in_table.set_border_width (5);
-       fade_in_table.set_homogeneous (false);
-
-       fade_in_label.set_name ("AudioRegionEditorLabel");
-       fade_in_active_button_label.set_name ("AudioRegionEditorSmallLabel");
-       fade_in_length_label.set_name ("AudioRegionEditorSmallLabel");
-
-       fade_in_label.set_text (_("FADE IN"));
-       fade_in_active_button_label.set_text (_("active"));
-       fade_in_length_label.set_text (_("msecs"));
-
-       fade_in_active_button.add (fade_in_active_button_label);
-
-       fade_in_length_spinner.set_name("GenericSpinner");
-
-       fade_in_length_spinner.set_digits (3);
-
-       // fade_in_length_spinner.signal_activate().connect (mem_fun(*this, &AudioRegionEditor::activation));
-
-       Gtkmm2ext::set_size_request_to_display_given_text (fade_in_length_spinner, "500g", 20, -1);
-
-       fade_in_label_align.add (fade_in_label);
-       fade_in_label_align.set (0.5);
-
-
-       fade_in_table.attach (fade_in_label_align,   0, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
-
-       fade_in_table.attach (fade_in_length_label,   0, 1, 1, 2, Gtk::EXPAND, Gtk::FILL);
-       fade_in_table.attach (fade_in_length_spinner, 0, 1, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
-
-       fade_in_table.attach (fade_in_active_button,        0, 2, 3, 5, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
-
-       /* fade out */
-
-       fade_out_table.set_border_width (5);
-       fade_out_table.set_homogeneous (false);
-
-       fade_out_label.set_name ("AudioRegionEditorLabel");
-       fade_out_active_button_label.set_name ("AudioRegionEditorSmallLabel");
-       fade_out_length_label.set_name ("AudioRegionEditorSmallLabel");
-
-       fade_out_label.set_text (_("FADE OUT"));
-       fade_out_active_button_label.set_text (_("active"));
-       fade_out_length_label.set_text (_("msecs"));
-
-       fade_out_active_button.add (fade_out_active_button_label);
-
-       fade_out_length_spinner.set_name("GenericSpinner");
-       
-       fade_out_length_spinner.set_digits (3);
-
-       fade_out_length_spinner.signal_activate().connect (mem_fun(*this, &AudioRegionEditor::activation));
-
-       Gtkmm2ext::set_size_request_to_display_given_text (fade_out_length_spinner, "500g", 20, -1);
-
-       fade_out_label_align.add (fade_out_label);
-       fade_out_label_align.set (0.5);
-
-       fade_out_table.attach (fade_out_label_align,   0, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
-
-       fade_out_table.attach (fade_out_length_label,   0, 1, 1, 2, Gtk::EXPAND, Gtk::FILL);
-       fade_out_table.attach (fade_out_length_spinner, 0, 1, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
-
-       fade_out_table.attach (fade_out_active_button,        0, 2, 3, 5, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
-
-       lower_hbox.pack_start (time_table, true, true);
-       lower_hbox.pack_start (sep1, false, false);
-       lower_hbox.pack_start (envelope_loop_table, true, true);
-       lower_hbox.pack_start (sep2, false, false);
-       lower_hbox.pack_start (fade_in_table, true, true);
-       lower_hbox.pack_start (fade_out_table, true, true);
-
-       get_vbox()->pack_start (top_row_hbox, true, true);
-       get_vbox()->pack_start (sep3, false, false);
-       get_vbox()->pack_start (lower_hbox, true, true);
-
-       set_name ("AudioRegionEditorWindow");
-       add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
-
-       signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (this)));
-
-       string title = _("ardour: region ");
-       title += _region.name();
-       set_title (title);
-
-       show_all();
-
-       name_changed ();
-       bounds_changed (Change (StartChanged|LengthChanged|PositionChanged));
-       envelope_active_changed ();
-       mute_changed ();
-       opacity_changed ();
-       lock_changed ();
-       layer_changed ();
-       fade_in_changed ();
-       fade_out_changed ();
-
-       XMLNode *node  = _region.extra_xml ("GUI");
-       XMLProperty *prop = 0;
-       bool showing_envelope = false;
-
-       if (node && (prop = node->property ("envelope-visible")) != 0) {
-               if (prop->value() == "yes") {
-                       showing_envelope = true;
-               } 
-       } 
-
-       if (showing_envelope) {
-               envelope_view_button.set_active (true);
-       } else {
-               envelope_view_button.set_active (false);
-       }
-
-       _region.StateChanged.connect (mem_fun(*this, &AudioRegionEditor::region_changed));
-       
-       spin_arrow_grab = false;
-       
-       connect_editor_events ();
-}
-
-AudioRegionEditor::~AudioRegionEditor ()
-{
-}
-
-void
-AudioRegionEditor::region_changed (Change what_changed)
-{
-       if (what_changed & NameChanged) {
-               name_changed ();
-       }
-       if (what_changed & BoundsChanged) {
-               bounds_changed (what_changed);
-       }
-
-       if (what_changed & Region::OpacityChanged) {
-               opacity_changed ();
-       }
-       if (what_changed & Region::MuteChanged) {
-               mute_changed ();
-       }
-       if (what_changed & Region::LockChanged) {
-               lock_changed ();
-       }
-       if (what_changed & Region::LayerChanged) {
-               layer_changed ();
-       }
-
-       if (what_changed & AudioRegion::EnvelopeActiveChanged) {
-               envelope_active_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 ();
-       }
-}
-
-void
-AudioRegionEditor::fade_in_realized ()
-{
-       fade_in_changed ();
-}
-
-void
-AudioRegionEditor::fade_out_realized ()
-{
-       fade_out_changed ();
-}
-
-gint 
-AudioRegionEditor::bpressed (GdkEventButton* ev, Gtk::SpinButton* but, void (AudioRegionEditor::*pmf)())
-{
-       switch (ev->button) {
-       case 1:
-       case 2:
-       case 3:
-               if (ev->type == GDK_BUTTON_PRESS) { /* no double clicks here */
-                       if (!spin_arrow_grab) {
-                               // GTK2FIX probably nuke the region editor
-                               // if ((ev->window == but->gobj()->panel)) {
-                               // spin_arrow_grab = true;
-                               // (this->*pmf)();
-                               // } 
-                       } 
-               } 
-               break;
-       default:
-               break;
-       }
-       return FALSE;
-}
-
-gint 
-AudioRegionEditor::breleased (GdkEventButton* ev, Gtk::SpinButton* but, void (AudioRegionEditor::*pmf)())
-{
-       if (spin_arrow_grab) {
-               (this->*pmf)();
-               spin_arrow_grab = false;
-       }
-       return FALSE;
-}
-
-void
-AudioRegionEditor::start_editing_fade_in ()
-{
-       _region.freeze ();
-}
-
-void
-AudioRegionEditor::stop_editing_fade_in ()
-{
-       _region.thaw (_("fade in edit"));
-}
-
-void
-AudioRegionEditor::start_editing_fade_out ()
-{
-       _region.freeze ();
-}
-
-void
-AudioRegionEditor::stop_editing_fade_out ()
-{
-       _region.thaw (_("fade out edit"));
-}
-
-void
-AudioRegionEditor::connect_editor_events ()
-{
-  name_entry.signal_changed().connect (mem_fun(*this, &AudioRegionEditor::name_entry_changed));
-
-       start_clock.ValueChanged.connect (mem_fun(*this, &AudioRegionEditor::start_clock_changed));
-       end_clock.ValueChanged.connect (mem_fun(*this, &AudioRegionEditor::end_clock_changed));
-       length_clock.ValueChanged.connect (mem_fun(*this, &AudioRegionEditor::length_clock_changed));
-
-       fade_in_length_spinner.signal_button_press_event().connect (bind (mem_fun(*this, &AudioRegionEditor::bpressed), &fade_in_length_spinner, 
-                                                                &AudioRegionEditor::start_editing_fade_in));
-       fade_in_length_spinner.signal_button_release_event().connect (bind (mem_fun (*this, &AudioRegionEditor::breleased), &fade_in_length_spinner, 
-                                                                  &AudioRegionEditor::stop_editing_fade_in));
-
-       fade_out_length_spinner.signal_button_press_event().connect (bind (mem_fun(*this, &AudioRegionEditor::bpressed), &fade_out_length_spinner, 
-                                                                &AudioRegionEditor::start_editing_fade_out));
-       fade_out_length_spinner.signal_button_release_event().connect (bind (mem_fun (*this, &AudioRegionEditor::breleased), &fade_out_length_spinner, 
-                                                                  &AudioRegionEditor::stop_editing_fade_out));
-
-       fade_in_length_adjustment.signal_value_changed().connect (mem_fun(*this, &AudioRegionEditor::fade_in_length_adjustment_changed));
-       fade_out_length_adjustment.signal_value_changed().connect (mem_fun(*this, &AudioRegionEditor::fade_out_length_adjustment_changed));
-
-       fade_in_active_button.signal_toggled().connect (mem_fun(*this, &AudioRegionEditor::fade_in_active_toggled));
-       fade_out_active_button.signal_toggled().connect (mem_fun(*this, &AudioRegionEditor::fade_out_active_toggled));
-
-       envelope_active_button.signal_button_press_event().connect (mem_fun(*this, &AudioRegionEditor::envelope_active_button_press));
-       envelope_active_button.signal_button_release_event().connect (mem_fun(*this, &AudioRegionEditor::envelope_active_button_release));
-       audition_button.signal_toggled().connect (mem_fun(*this, &AudioRegionEditor::audition_button_toggled));
-       envelope_view_button.signal_toggled().connect (mem_fun(*this, &AudioRegionEditor::envelope_view_button_toggled));
-       lock_button.signal_clicked().connect (mem_fun(*this, &AudioRegionEditor::lock_button_clicked));
-       mute_button.signal_clicked().connect (mem_fun(*this, &AudioRegionEditor::mute_button_clicked));
-       opaque_button.signal_clicked().connect (mem_fun(*this, &AudioRegionEditor::opaque_button_clicked));
-       raise_button.signal_clicked().connect (mem_fun(*this, &AudioRegionEditor::raise_button_clicked));
-       lower_button.signal_clicked().connect (mem_fun(*this, &AudioRegionEditor::lower_button_clicked));
-       _session.AuditionActive.connect (mem_fun(*this, &AudioRegionEditor::audition_state_changed));
-}
-
-void
-AudioRegionEditor::start_clock_changed ()
-{
-       _region.set_position (start_clock.current_time(), this);
-}
-
-void
-AudioRegionEditor::end_clock_changed ()
-{
-       _region.trim_end (end_clock.current_time(), this);
-
-       end_clock.set (_region.position() + _region.length(), true);
-}
-
-void
-AudioRegionEditor::length_clock_changed ()
-{
-       jack_nframes_t frames = length_clock.current_time();
-       _region.trim_end (_region.position() + frames, this);
-
-       length_clock.set (_region.length());
-}
-
-gint
-AudioRegionEditor::envelope_active_button_press(GdkEventButton *ev)
-{
-       return stop_signal (envelope_active_button, "button_press_event");
-}
-
-gint
-AudioRegionEditor::envelope_active_button_release (GdkEventButton *ev)
-{
-       _region.set_envelope_active (!_region.envelope_active());
-       return stop_signal (envelope_active_button, "button_release_event");
-}
-
-void
-AudioRegionEditor::envelope_view_button_toggled ()
-{
-       bool visible = envelope_view_button.get_active ();
-
-       _region_view.set_envelope_visible (visible);
-}
-
-void
-AudioRegionEditor::audition_button_toggled ()
-{
-       if (audition_button.get_active()) {
-               _session.audition_region (_region);
-       } else {
-               _session.cancel_audition ();
-       }
-}
-
-void
-AudioRegionEditor::raise_button_clicked ()
-{
-       _region.raise ();
-}
-
-void
-AudioRegionEditor::lower_button_clicked ()
-{
-       _region.lower ();
-}
-
-void
-AudioRegionEditor::opaque_button_clicked ()
-{
-       bool ractive = _region.opaque();
-
-       if (opaque_button.get_active() != ractive) {
-               _region.set_opaque (!ractive);
-       }
-}
-
-void
-AudioRegionEditor::mute_button_clicked ()
-{
-       bool ractive = _region.muted();
-
-       if (mute_button.get_active() != ractive) {
-               _region.set_muted (!ractive);
-       }
-}
-
-void
-AudioRegionEditor::lock_button_clicked ()
-{
-       bool ractive = _region.locked();
-
-       if (lock_button.get_active() != ractive) {
-               _region.set_locked (!ractive);
-       }
-}
-
-void
-AudioRegionEditor::layer_changed ()
-{
-       char buf[8];
-       snprintf (buf, sizeof(buf), "%d", (int) _region.layer() + 1);
-       layer_value_label.set_text (buf);
-}
-
-void
-AudioRegionEditor::name_changed ()
-{
-       if (name_entry.get_text() != _region.name()) {
-               name_entry.set_text (_region.name());
-       }
-}
-
-void
-AudioRegionEditor::lock_changed ()
-{
-       bool yn;
-
-       if ((yn = _region.locked()) != lock_button.get_active()) {
-               lock_button.set_active (yn);
-       }
-
-       start_clock.set_sensitive (!yn);
-       end_clock.set_sensitive (!yn);
-       length_clock.set_sensitive (!yn);
-}
-
-void
-AudioRegionEditor::envelope_active_changed ()
-{
-       bool yn;
-
-       if ((yn = _region.envelope_active()) != envelope_active_button.get_active()) {
-               envelope_active_button.set_active (yn);
-       }
-}
-
-void
-AudioRegionEditor::opacity_changed ()
-{
-       bool yn;
-       if ((yn = _region.opaque()) != opaque_button.get_active()) {
-               opaque_button.set_active (yn);
-       }
-}
-
-void
-AudioRegionEditor::mute_changed ()
-{
-       bool yn;
-       if ((yn = _region.muted()) != mute_button.get_active()) {
-               mute_button.set_active (yn);
-       }
-}
-
-void
-AudioRegionEditor::bounds_changed (Change what_changed)
-{
-       if (what_changed & Change ((PositionChanged|LengthChanged))) {
-               start_clock.set (_region.position(), true);
-               end_clock.set (_region.position() + _region.length(), true);
-               length_clock.set (_region.length(), true);
-       }
-}
-
-void
-AudioRegionEditor::activation ()
-{
-       
-}      
-
-void
-AudioRegionEditor::name_entry_changed ()
-{
-       if (name_entry.get_text() != _region.name()) {
-               _region.set_name (name_entry.get_text());
-       }
-}
-
-void
-AudioRegionEditor::fade_in_changed ()
-{
-       float msecs = fade_in_length_adjustment.get_value();
-       jack_nframes_t sr = _session.frame_rate();
-       jack_nframes_t adj_frames = (jack_nframes_t) floor (msecs * (sr/1000.0f));
-       jack_nframes_t frames;
-       bool x;
-
-       if (adj_frames != (frames = (jack_nframes_t) _region.fade_in().back()->when)) {
-               fade_in_length_adjustment.set_value ((frames * 1000.0f) / sr);
-       }
-
-       if ((x = _region.fade_in_active()) != fade_in_active_button.get_active()) {
-               fade_in_active_button.set_active (x);
-       }
-}
-
-void
-AudioRegionEditor::fade_out_changed ()
-{
-       float msecs = fade_out_length_adjustment.get_value();
-       jack_nframes_t sr = _session.frame_rate();
-       jack_nframes_t adj_frames = (jack_nframes_t) floor (msecs * (sr/1000.0f));
-       jack_nframes_t frames;
-       bool x;
-       if (adj_frames != (frames = (jack_nframes_t) _region.fade_out().back()->when)) {
-               fade_out_length_adjustment.set_value ((frames * 1000.0f) / sr);
-       }
-
-       if ((x = _region.fade_out_active()) != fade_out_active_button.get_active()) {
-               fade_out_active_button.set_active (x);
-       }
-}
-
-void
-AudioRegionEditor::fade_in_length_adjustment_changed ()
-{
-       jack_nframes_t fade_length = (jack_nframes_t) floor (fade_in_length_adjustment.get_value() * _session.frame_rate() * 0.001); 
-       fade_length = max (fade_length, (jack_nframes_t) 64);
-       fade_length = min (fade_length, _region.length());
-       
-       _region.set_fade_in_length (fade_length);
-       /* region is frozen, no worries */
-       fade_in_changed();
-}
-
-void
-AudioRegionEditor::fade_out_length_adjustment_changed ()
-{
-       jack_nframes_t fade_length = (jack_nframes_t) floor (fade_out_length_adjustment.get_value() * _session.frame_rate() * 0.001); 
-       fade_length = max (fade_length, (jack_nframes_t) 64);
-       fade_length = min (fade_length, _region.length());
-       
-       _region.set_fade_out_length (fade_length);      
-       /* region is frozen, no worries */
-       fade_out_changed();
-}
-
-void
-AudioRegionEditor::fade_in_active_toggled ()
-{
-       _region.set_fade_in_active (fade_in_active_button.get_active());
-}
-
-void
-AudioRegionEditor::fade_out_active_toggled ()
-{
-       _region.set_fade_out_active (fade_out_active_button.get_active());
-}
-
-void
-AudioRegionEditor::fade_out_active_changed ()
-{
-       bool x;
-
-       if ((x = _region.fade_out_active()) != fade_out_active_button.get_active()) {
-               fade_out_active_button.set_active (x);
-       }
-}
-
-void
-AudioRegionEditor::fade_in_active_changed ()
-{
-       bool x;
-
-       if ((x = _region.fade_in_active()) != fade_in_active_button.get_active()) {
-               fade_in_active_button.set_active (x);
-       }
-}
-
-void
-AudioRegionEditor::audition_state_changed (bool yn)
-{
-       ENSURE_GUI_THREAD (bind (mem_fun(*this, &AudioRegionEditor::audition_state_changed), yn));
-
-       if (!yn) {
-               audition_button.set_active (false);
-       }
-}
-
diff --git a/gtk2_ardour/region_editor.h b/gtk2_ardour/region_editor.h
deleted file mode 100644 (file)
index 65b0bba..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
-    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_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;
-
-class AudioRegionEditor : 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 ();
-
-       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_region_edit_h__ */
index bba9410ffba344e4a4a4121eba9993e61e2625c6..a542be054e115676c1e0e95fcbda0d70faffff3a 100644 (file)
@@ -2,7 +2,7 @@
 #include <ardour/audioregion.h>
 
 #include "region_gain_line.h"
-#include "regionview.h"
+#include "audio_region_view.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);
 }
index 751584cab7a5ddfe6ff9c13b308b1b6ef89c2eba..f8c9f384a9b13ce5069dc233b9cb756029016c2c 100644 (file)
@@ -1,8 +1,26 @@
+/*
+    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_view.h"
 #include "region_selection.h"
 
 using namespace ARDOUR;
@@ -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) {
index 0c2b7be0255d73e42a807f834098c3099925735e..2192442cb0cbdf5ac0eb53435f1af27c5fdd3716 100644 (file)
@@ -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__
 
 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/region_view.cc b/gtk2_ardour/region_view.cc
new file mode 100644 (file)
index 0000000..ebec426
--- /dev/null
@@ -0,0 +1,494 @@
+/*
+    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.
+
+    $Id: regionview.cc 691 2006-07-23 12:03:19Z drobilla $
+*/
+
+#include <cmath>
+#include <cassert>
+#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 "region_view.h"
+#include "route_time_axis.h"
+#include "simplerect.h"
+#include "simpleline.h"
+#include "waveview.h"
+#include "public_editor.h"
+#include "region_editor.h"
+#include "ghostregion.h"
+#include "route_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;
+
+sigc::signal<void,RegionView*> RegionView::RegionViewGoingAway;
+
+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)
+       , sync_mark(0)
+       , no_wave_msg(0)
+       , editor(0)
+       , current_visible_sync_position(0.0)
+       , valid(false)
+       , _pixel_width(1.0)
+       , _height(1.0)
+       , in_destructor(false)
+       , wait_for_data(false)
+{
+}
+
+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)
+       , sync_mark(0)
+       , no_wave_msg(0)
+       , editor(0)
+       , current_visible_sync_position(0.0)
+       , valid(false)
+       , _pixel_width(1.0)
+       , _height(1.0)
+       , in_destructor(false)
+       , wait_for_data(false)
+{
+}
+
+void
+RegionView::init (Gdk::Color& basic_color, bool wfd)
+{
+       editor        = 0;
+       valid         = true;
+       in_destructor = false;
+       _height       = 0;
+       wait_for_data = wfd;
+
+       compute_colors (basic_color);
+
+       name_highlight->set_data ("regionview", this);
+       name_text->set_data ("regionview", this);
+
+       /* an equilateral triangle */
+    ArdourCanvas::Points shape;
+       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();
+
+       reset_width_dependent_items ((double) _region.length() / samples_per_unit);
+
+       set_height (trackview.height);
+
+       region_muted ();
+       region_sync_changed ();
+       region_resized (BoundsChanged);
+       region_locked ();
+
+       _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));
+
+       set_colors ();
+
+       ColorChanged.connect (mem_fun (*this, &RegionView::color_handler));
+
+       /* XXX sync mark drag? */
+}
+
+RegionView::~RegionView ()
+{
+       in_destructor = true;
+
+       RegionViewGoingAway (this); /* EMIT_SIGNAL */
+
+       for (vector<GhostRegion*>::iterator g = ghosts.begin(); g != ghosts.end(); ++g) {
+               delete *g;
+       }
+
+       if (editor) {
+               delete editor;
+       }
+}
+
+gint
+RegionView::_lock_toggle (ArdourCanvas::Item* item, GdkEvent* ev, void* arg)
+{
+       switch (ev->type) {
+       case GDK_BUTTON_RELEASE:
+               static_cast<RegionView*>(arg)->lock_toggle ();
+               return TRUE;
+               break;
+       default:
+               break;
+       } 
+       return FALSE;
+}
+
+void
+RegionView::lock_toggle ()
+{
+       _region.set_locked (!_region.locked());
+}
+
+void
+RegionView::region_changed (Change what_changed)
+{
+       ENSURE_GUI_THREAD (bind (mem_fun(*this, &RegionView::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 ();
+       }
+}
+
+void
+RegionView::region_locked ()
+{
+       /* name will show locked status */
+       region_renamed ();
+}
+
+void
+RegionView::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 (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
+
+                       (*i)->set_duration (unit_length);
+
+               }
+       }
+}
+
+void
+RegionView::reset_width_dependent_items (double pixel_width)
+{
+       TimeAxisViewItem::reset_width_dependent_items (pixel_width);
+       _pixel_width = pixel_width;
+}
+
+void
+RegionView::region_layered ()
+{
+       RouteTimeAxisView *rtv = dynamic_cast<RouteTimeAxisView*>(&get_time_axis_view());
+       assert(rtv);
+       rtv->view()->region_layered (this);
+}
+       
+void
+RegionView::region_muted ()
+{
+       set_frame_color ();
+       region_renamed ();
+}
+
+void
+RegionView::region_opacity ()
+{
+       set_frame_color ();
+}
+
+void
+RegionView::raise ()
+{
+       _region.raise ();
+}
+
+void
+RegionView::raise_to_top ()
+{
+       _region.raise_to_top ();
+}
+
+void
+RegionView::lower ()
+{
+       _region.lower ();
+}
+
+void
+RegionView::lower_to_bottom ()
+{
+       _region.lower_to_bottom ();
+}
+
+bool
+RegionView::set_position (jack_nframes_t pos, void* src, double* ignored)
+{
+       double delta;
+       bool ret;
+
+       if (!(ret = TimeAxisViewItem::set_position (pos, this, &delta))) {
+               return false;
+       }
+
+       if (ignored) {
+               *ignored = delta;
+       }
+
+       if (delta) {
+               for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
+                       (*i)->group->move (delta, 0.0);
+               }
+       }
+
+       return ret;
+}
+
+void
+RegionView::set_samples_per_unit (gdouble spu)
+{
+       TimeAxisViewItem::set_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);
+       }
+
+       region_sync_changed ();
+}
+
+bool
+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);
+       }
+
+       return true;
+}
+
+void
+RegionView::compute_colors (Gdk::Color& basic_color)
+{
+       TimeAxisViewItem::compute_colors (basic_color);
+}
+
+void
+RegionView::set_colors ()
+{
+       TimeAxisViewItem::set_colors ();
+       
+       if (sync_mark) {
+               sync_mark->property_fill_color_rgba() = fill_color;
+       }
+}
+
+void
+RegionView::set_frame_color ()
+{
+       if (_region.opaque()) {
+               fill_opacity = 180;
+       } else {
+               fill_opacity = 100;
+       }
+
+       TimeAxisViewItem::set_frame_color ();
+}
+
+void
+RegionView::hide_region_editor()
+{
+       if (editor) {
+               editor->hide_all ();
+       }
+}
+
+void
+RegionView::region_renamed ()
+{
+       string str;
+
+       if (_region.locked()) {
+               str += '>';
+               str += _region.name();
+               str += '<';
+       } else {
+               str = _region.name();
+       }
+
+       if (_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
+RegionView::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
+RegionView::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);
+       }
+}
+
+void
+RegionView::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;
+               }
+       }
+}
+
+uint32_t
+RegionView::get_fill_color ()
+{
+       return fill_color;
+}
+
diff --git a/gtk2_ardour/region_view.h b/gtk2_ardour/region_view.h
new file mode 100644 (file)
index 0000000..fdc69ea
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+    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_region_view_h__
+#define __gtk_ardour_region_view_h__
+
+#include <vector>
+
+#include <libgnomecanvasmm.h>
+#include <libgnomecanvasmm/polygon.h>
+#include <sigc++/signal.h>
+#include <ardour/region.h>
+
+#include "time_axis_view_item.h"
+#include "automation_line.h"
+#include "enums.h"
+#include "waveview.h"
+#include "canvas.h"
+#include "color.h"
+
+class TimeAxisView;
+class RegionEditor;
+class GhostRegion;
+class AutomationTimeAxisView;
+
+class RegionView : public TimeAxisViewItem
+{
+  public:
+       RegionView (ArdourCanvas::Group* parent, 
+                   TimeAxisView&        time_view,
+                   ARDOUR::Region&      region,
+                   double               samples_per_unit,
+                   Gdk::Color&          basic_color);
+
+       ~RegionView ();
+       
+       virtual void init (Gdk::Color& base_color, bool wait_for_data);
+    
+       ARDOUR::Region& region() const { return _region; }
+       
+       bool is_valid() const    { return valid; }
+    void set_valid (bool yn) { valid = yn; }
+
+    virtual void set_height (double) = 0;
+    virtual void set_samples_per_unit (double);
+    virtual bool set_duration (jack_nframes_t, void*);
+
+    void move (double xdelta, double ydelta);
+
+    void raise ();
+    void raise_to_top ();
+    void lower ();
+    void lower_to_bottom ();
+
+    bool set_position(jack_nframes_t pos, void* src, double* delta = 0);
+
+    virtual void show_region_editor () = 0;
+    virtual void hide_region_editor();
+
+    virtual void region_changed (ARDOUR::Change);
+
+    virtual GhostRegion* add_ghost (AutomationTimeAxisView&) = 0;
+    void                 remove_ghost (GhostRegion*);
+
+    uint32_t get_fill_color ();
+
+    virtual void entered () {}
+    virtual void exited () {}
+    
+       static sigc::signal<void,RegionView*> RegionViewGoingAway;
+    sigc::signal<void>                    GoingAway;
+
+  protected:
+
+    /** Allows derived types to specify their visibility requirements
+     * to the TimeAxisViewItem parent class
+        */
+    RegionView (ArdourCanvas::Group *, 
+                   TimeAxisView&,
+                   ARDOUR::Region&,
+                   double      samples_per_unit,
+                   Gdk::Color& basic_color,
+                   TimeAxisViewItem::Visibility);
+
+    virtual void region_resized (ARDOUR::Change);
+    void         region_moved (void *);
+    virtual void region_muted ();
+    void         region_locked ();
+    void         region_opacity ();
+    void         region_layered ();
+    void         region_renamed ();
+    void         region_sync_changed ();
+
+    static gint _lock_toggle (ArdourCanvas::Item*, GdkEvent*, void*);
+    void        lock_toggle ();
+
+    virtual void set_colors ();
+    virtual void compute_colors (Gdk::Color&);
+    virtual void set_frame_color ();
+    virtual void reset_width_dependent_items (double pixel_width);
+    
+    virtual void color_handler (ColorID, uint32_t) {}
+       
+       ARDOUR::Region& _region;
+    
+    ArdourCanvas::Polygon* sync_mark; ///< polgyon for sync position 
+    ArdourCanvas::Text*    no_wave_msg;
+
+    RegionEditor* editor;
+
+    vector<ControlPoint *> control_points;
+    double current_visible_sync_position;
+
+    bool     valid; ///< see StreamView::redisplay_diskstream() 
+    double  _pixel_width;
+    double  _height;
+    bool    in_destructor;
+
+    bool             wait_for_data;
+       sigc::connection data_ready_connection;
+    
+       vector<GhostRegion*> ghosts;
+};
+
+#endif /* __gtk_ardour_region_view_h__ */
diff --git a/gtk2_ardour/regionview.cc b/gtk2_ardour/regionview.cc
deleted file mode 100644 (file)
index fa51dd4..0000000
+++ /dev/null
@@ -1,1408 +0,0 @@
-/*
-    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$
-*/
-
-#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 "regionview.h"
-#include "audio_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 "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;
-
-sigc::signal<void,AudioRegionView*> AudioRegionView::AudioRegionViewGoingAway;
-
-AudioRegionView::AudioRegionView (ArdourCanvas::Group *parent, AudioTimeAxisView &tv, AudioRegion& 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)
-{
-}
-
-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)
-{
-}
-
-void
-AudioRegionView::init (double amplitude_above_axis, Gdk::Color& basic_color, bool wfw)
-{
-        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) {
-               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, 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;
-
-       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 */
-
-       for (vector<GhostRegion*>::iterator g = ghosts.begin(); g != ghosts.end(); ++g) {
-               delete *g;
-       }
-
-       if (editor) {
-               delete editor;
-       }
-
-       if (gain_line) {
-               delete gain_line;
-       }
-}
-
-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)
-{
-       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() = &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 ()
-{
-       AudioTimeAxisView *atv = dynamic_cast<AudioTimeAxisView*> (&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::region_opacity ()
-{
-       set_frame_color ();
-}
-
-void
-AudioRegionView::raise ()
-{
-       region.raise ();
-}
-
-void
-AudioRegionView::raise_to_top ()
-{
-       region.raise_to_top ();
-}
-
-void
-AudioRegionView::lower ()
-{
-       region.lower ();
-}
-
-void
-AudioRegionView::lower_to_bottom ()
-{
-       region.lower_to_bottom ();
-}
-
-bool
-AudioRegionView::set_position (jack_nframes_t pos, void* src, double* ignored)
-{
-       double delta;
-       bool ret;
-
-       if (!(ret = TimeAxisViewItem::set_position (pos, this, &delta))) {
-               return false;
-       }
-
-       if (ignored) {
-               *ignored = delta;
-       }
-
-       if (delta) {
-               for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
-                       (*i)->group->move (delta, 0.0);
-               }
-       }
-
-       return ret;
-}
-
-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)
-{
-       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 (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(), 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 (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;
-
-       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) &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 (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)) {
-               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)
-{
-       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() =  &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;
-               }
-       }
-}
-
-uint32_t
-AudioRegionView::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() = &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/regionview.h b/gtk2_ardour/regionview.h
deleted file mode 100644 (file)
index f49b46a..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
-    Copyright (C) 2001-2004 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_region_view_h__
-#define __gtk_ardour_region_view_h__
-
-#include <vector>
-
-#include <libgnomecanvasmm.h>
-#include <libgnomecanvasmm/polygon.h>
-#include <sigc++/signal.h>
-#include <ardour/region.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 TimeAxisViewItem
-{
-  public:
-       AudioRegionView (ArdourCanvas::Group *, 
-                        AudioTimeAxisView&,
-                        ARDOUR::AudioRegion&,
-                        double initial_samples_per_unit,
-                        Gdk::Color& basic_color);
-
-       ~AudioRegionView ();
-       
-       virtual void init (double amplitude_above_axis, Gdk::Color& base_color, bool wait_for_waves);
-    
-    ARDOUR::AudioRegion& region;  // ok, let 'em have it
-    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 raise ();
-    void raise_to_top ();
-    void lower ();
-    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 ();
-    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);
-
-    uint32_t get_fill_color ();
-
-    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 *, 
-                    AudioTimeAxisView&,
-                    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_opacity ();
-    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_region_view_h__ */
diff --git a/gtk2_ardour/route_time_axis.cc b/gtk2_ardour/route_time_axis.cc
new file mode 100644 (file)
index 0000000..cb9883b
--- /dev/null
@@ -0,0 +1,1559 @@
+/*
+    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 <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 <gtkmm/menu.h>
+#include <gtkmm/menuitem.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 "automation_time_axis.h"
+#include "redirect_automation_time_axis.h"
+#include "redirect_automation_line.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 "region_view.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, boost::shared_ptr<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;
+
+       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 */
+
+       vector_delete (&redirect_automation_curves);
+
+       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
+               delete *i;
+       }
+
+       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::build_automation_action_menu ()
+{
+       using namespace Menu_Helpers;
+
+       automation_action_menu = manage (new Menu);
+       MenuList& automation_items = automation_action_menu->items();
+       automation_action_menu->set_name ("ArdourContextMenu");
+       
+       automation_items.push_back (MenuElem (_("Show all automation"),
+                                             mem_fun(*this, &RouteTimeAxisView::show_all_automation)));
+
+       automation_items.push_back (MenuElem (_("Show existing automation"),
+                                             mem_fun(*this, &RouteTimeAxisView::show_existing_automation)));
+
+       automation_items.push_back (MenuElem (_("Hide all automation"),
+                                             mem_fun(*this, &RouteTimeAxisView::hide_all_automation)));
+
+       automation_items.push_back (MenuElem (_("Plugins"), subplugin_menu));
+}
+
+void
+RouteTimeAxisView::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, &RouteTimeAxisView::select_track_color)));
+
+       items.push_back (SeparatorElem());
+
+       build_remote_control_menu ();
+       items.push_back (MenuElem (_("Remote Control ID"), *remote_control_menu));
+
+       build_automation_action_menu ();
+       items.push_back (MenuElem (_("Automation"), *automation_action_menu));
+
+       // Hook for derived classes to add type specific stuff
+       items.push_back (SeparatorElem());
+       append_extra_display_menu_items ();
+       items.push_back (SeparatorElem());
+       
+       if (is_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, &RouteTimeAxisView::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, &RouteTimeAxisView::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, &RouteTimeAxisView::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)));
+}
+
+
+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 ()
+{
+       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::set_selected_regionviews (RegionSelection& regions)
+{
+       _view->set_selected_regionviews (regions);
+}
+
+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;
+}
+
+void
+RouteTimeAxisView::show_all_automation ()
+{
+       no_redraw = true;
+
+       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
+               for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
+                       if ((*ii)->view == 0) {
+                               add_redirect_automation_curve ((*i)->redirect, (*ii)->what);
+                       } 
+
+                       (*ii)->menu_item->set_active (true);
+               }
+       }
+
+       no_redraw = false;
+
+        _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
+}
+
+void
+RouteTimeAxisView::show_existing_automation ()
+{
+       no_redraw = true;
+
+       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
+               for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
+                       if ((*ii)->view != 0) {
+                               (*ii)->menu_item->set_active (true);
+                       }
+               }
+       }
+
+       no_redraw = false;
+
+        _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
+}
+
+void
+RouteTimeAxisView::hide_all_automation ()
+{
+       no_redraw = true;
+
+       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
+               for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
+                       (*ii)->menu_item->set_active (false);
+               }
+       }
+
+       no_redraw = false;
+        _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
+}
+
+
+void
+RouteTimeAxisView::region_view_added (RegionView* rv)
+{
+       for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
+               AutomationTimeAxisView* atv;
+
+               if ((atv = dynamic_cast<AutomationTimeAxisView*> (*i)) != 0) {
+                       rv->add_ghost (*atv);
+               }
+       }
+}
+
+void
+RouteTimeAxisView::add_ghost_to_redirect (RegionView* rv, AutomationTimeAxisView* atv)
+{
+       rv->add_ghost (*atv);
+}
+
+RouteTimeAxisView::RedirectAutomationInfo::~RedirectAutomationInfo ()
+{
+       for (vector<RedirectAutomationNode*>::iterator i = lines.begin(); i != lines.end(); ++i) {
+               delete *i;
+       }
+}
+
+
+RouteTimeAxisView::RedirectAutomationNode::~RedirectAutomationNode ()
+{
+       parent.remove_ran (this);
+
+       if (view) {
+               delete view;
+       }
+}
+
+void
+RouteTimeAxisView::remove_ran (RedirectAutomationNode* ran)
+{
+       if (ran->view) {
+               remove_child (ran->view);
+       }
+}
+
+RouteTimeAxisView::RedirectAutomationNode*
+RouteTimeAxisView::find_redirect_automation_node (boost::shared_ptr<Redirect> redirect, uint32_t what)
+{
+       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
+
+               if ((*i)->redirect == redirect) {
+
+                       for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
+                               if ((*ii)->what == what) {
+                                       return *ii;
+                               }
+                       }
+               }
+       }
+
+       return 0;
+}
+
+// FIXME: duplicated in midi_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
+RouteTimeAxisView::add_redirect_automation_curve (boost::shared_ptr<Redirect> redirect, uint32_t what)
+{
+       RedirectAutomationLine* ral;
+       string name;
+       RedirectAutomationNode* ran;
+
+       if ((ran = find_redirect_automation_node (redirect, what)) == 0) {
+               fatal << _("programming error: ")
+                     << string_compose (X_("redirect automation curve for %1:%2 not registered with audio track!"),
+                                 redirect->name(), what)
+                     << endmsg;
+               /*NOTREACHED*/
+               return;
+       }
+
+       if (ran->view) {
+               return;
+       }
+
+       name = redirect->describe_parameter (what);
+
+       /* create a string that is a legal XML node name that can be used to refer to this redirect+port combination */
+
+       char state_name[256];
+       snprintf (state_name, sizeof (state_name), "Redirect-%s-%" PRIu32, legalize_for_xml_node (redirect->name()).c_str(), what);
+
+       ran->view = new RedirectAutomationTimeAxisView (_session, _route, editor, *this, parent_canvas, name, what, *redirect, state_name);
+
+       ral = new RedirectAutomationLine (name, 
+                                         *redirect, what, _session, *ran->view,
+                                         *ran->view->canvas_display, redirect->automation_list (what));
+       
+       ral->set_line_color (color_map[cRedirectAutomationLine]);
+       ral->queue_reset ();
+
+       ran->view->add_line (*ral);
+
+       ran->view->Hiding.connect (bind (mem_fun(*this, &RouteTimeAxisView::redirect_automation_track_hidden), ran, redirect));
+
+       if (!ran->view->marked_for_display()) {
+               ran->view->hide ();
+       } else {
+               ran->menu_item->set_active (true);
+       }
+
+       add_child (ran->view);
+
+       _view->foreach_regionview (bind (mem_fun(*this, &RouteTimeAxisView::add_ghost_to_redirect), ran->view));
+
+       redirect->mark_automation_visible (what, true);
+}
+
+void
+RouteTimeAxisView::redirect_automation_track_hidden (RouteTimeAxisView::RedirectAutomationNode* ran, boost::shared_ptr<Redirect> r)
+{
+       if (!_hidden) {
+               ran->menu_item->set_active (false);
+       }
+
+       r->mark_automation_visible (ran->what, false);
+
+        _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
+}
+
+void
+RouteTimeAxisView::add_existing_redirect_automation_curves (boost::shared_ptr<Redirect> redirect)
+{
+       set<uint32_t> s;
+       RedirectAutomationLine *ral;
+
+       redirect->what_has_visible_automation (s);
+
+       for (set<uint32_t>::iterator i = s.begin(); i != s.end(); ++i) {
+               
+               if ((ral = find_redirect_automation_curve (redirect, *i)) != 0) {
+                       ral->queue_reset ();
+               } else {
+                       add_redirect_automation_curve (redirect, (*i));
+               }
+       }
+}
+
+void
+RouteTimeAxisView::add_redirect_to_subplugin_menu (boost::shared_ptr<Redirect> r)
+{
+       using namespace Menu_Helpers;
+       RedirectAutomationInfo *rai;
+       list<RedirectAutomationInfo*>::iterator x;
+       
+       const std::set<uint32_t>& automatable = r->what_can_be_automated ();
+       std::set<uint32_t> has_visible_automation;
+
+       r->what_has_visible_automation(has_visible_automation);
+
+       if (automatable.empty()) {
+               return;
+       }
+
+       for (x = redirect_automation.begin(); x != redirect_automation.end(); ++x) {
+               if ((*x)->redirect == r) {
+                       break;
+               }
+       }
+
+       if (x == redirect_automation.end()) {
+
+               rai = new RedirectAutomationInfo (r);
+               redirect_automation.push_back (rai);
+
+       } else {
+
+               rai = *x;
+
+       }
+
+       /* any older menu was deleted at the top of redirects_changed()
+          when we cleared the subplugin menu.
+       */
+
+       rai->menu = manage (new Menu);
+       MenuList& items = rai->menu->items();
+       rai->menu->set_name ("ArdourContextMenu");
+
+       items.clear ();
+
+       for (std::set<uint32_t>::const_iterator i = automatable.begin(); i != automatable.end(); ++i) {
+
+               RedirectAutomationNode* ran;
+               CheckMenuItem* mitem;
+               
+               string name = r->describe_parameter (*i);
+               
+               items.push_back (CheckMenuElem (name));
+               mitem = dynamic_cast<CheckMenuItem*> (&items.back());
+
+               if (has_visible_automation.find((*i)) != has_visible_automation.end()) {
+                       mitem->set_active(true);
+               }
+
+               if ((ran = find_redirect_automation_node (r, *i)) == 0) {
+
+                       /* new item */
+                       
+                       ran = new RedirectAutomationNode (*i, mitem, *this);
+                       
+                       rai->lines.push_back (ran);
+
+               } else {
+
+                       ran->menu_item = mitem;
+
+               }
+
+               mitem->signal_toggled().connect (bind (mem_fun(*this, &RouteTimeAxisView::redirect_menu_item_toggled), rai, ran));
+       }
+
+       /* add the menu for this redirect, because the subplugin
+          menu is always cleared at the top of redirects_changed().
+          this is the result of some poor design in gtkmm and/or
+          GTK+.
+       */
+
+       subplugin_menu.items().push_back (MenuElem (r->name(), *rai->menu));
+       rai->valid = true;
+}
+
+void
+RouteTimeAxisView::redirect_menu_item_toggled (RouteTimeAxisView::RedirectAutomationInfo* rai,
+                                              RouteTimeAxisView::RedirectAutomationNode* ran)
+{
+       bool showit = ran->menu_item->get_active();
+       bool redraw = false;
+
+       if (ran->view == 0 && showit) {
+               add_redirect_automation_curve (rai->redirect, ran->what);
+               redraw = true;
+       }
+
+       if (showit != ran->view->marked_for_display()) {
+
+               if (showit) {
+                       ran->view->set_marked_for_display (true);
+                       ran->view->canvas_display->show();
+               } else {
+                       rai->redirect->mark_automation_visible (ran->what, true);
+                       ran->view->set_marked_for_display (false);
+                       ran->view->hide ();
+               }
+
+               redraw = true;
+
+       }
+
+       if (redraw && !no_redraw) {
+
+               /* now trigger a redisplay */
+               
+                _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
+
+       }
+}
+
+void
+RouteTimeAxisView::redirects_changed (void *src)
+{
+       using namespace Menu_Helpers;
+
+       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
+               (*i)->valid = false;
+       }
+
+       subplugin_menu.items().clear ();
+
+       _route->foreach_redirect (this, &RouteTimeAxisView::add_redirect_to_subplugin_menu);
+       _route->foreach_redirect (this, &RouteTimeAxisView::add_existing_redirect_automation_curves);
+
+       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ) {
+
+               list<RedirectAutomationInfo*>::iterator tmp;
+
+               tmp = i;
+               ++tmp;
+
+               if (!(*i)->valid) {
+
+                       delete *i;
+                       redirect_automation.erase (i);
+
+               } 
+
+               i = tmp;
+       }
+
+       /* change in visibility was possible */
+
+       _route->gui_changed ("track_height", this);
+}
+
+RedirectAutomationLine *
+RouteTimeAxisView::find_redirect_automation_curve (boost::shared_ptr<Redirect> redirect, uint32_t what)
+{
+       RedirectAutomationNode* ran;
+
+       if ((ran = find_redirect_automation_node (redirect, what)) != 0) {
+               if (ran->view) {
+                       return dynamic_cast<RedirectAutomationLine*> (ran->view->lines.front());
+               } 
+       }
+
+       return 0;
+}
+
+void
+RouteTimeAxisView::reset_redirect_automation_curves ()
+{
+       for (vector<RedirectAutomationLine*>::iterator i = redirect_automation_curves.begin(); i != redirect_automation_curves.end(); ++i) {
+               (*i)->reset();
+       }
+}
+
diff --git a/gtk2_ardour/route_time_axis.h b/gtk2_ardour/route_time_axis.h
new file mode 100644 (file)
index 0000000..d305fd3
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+    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.
+
+    $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_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 Region;
+       class Diskstream;
+       class RouteGroup;
+       class Redirect;
+       class Insert;
+       class Location;
+       class Playlist;
+}
+
+class PublicEditor;
+class RegionView;
+class StreamView;
+class Selection;
+class RegionSelection;
+class Selectable;
+class AutomationTimeAxisView;
+class AutomationLine;
+class RedirectAutomationLine;
+class TimeSelection;
+
+class RouteTimeAxisView : public RouteUI, public TimeAxisView
+{
+public:
+       RouteTimeAxisView (PublicEditor&, ARDOUR::Session&, boost::shared_ptr<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 set_selected_regionviews (RegionSelection&);
+       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);
+
+       /* 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 ();
+       
+       void build_playlist_menu (Gtk::Menu *);
+       
+       string              name() const;
+       StreamView*         view() const { return _view; }
+       ARDOUR::RouteGroup* edit_group() const;
+       ARDOUR::Playlist*   playlist() const;
+
+protected:
+       friend class StreamView;
+       
+       struct RedirectAutomationNode {
+           uint32_t                what;
+           Gtk::CheckMenuItem*     menu_item;
+           AutomationTimeAxisView* view;
+           RouteTimeAxisView&      parent;
+
+           RedirectAutomationNode (uint32_t w, Gtk::CheckMenuItem* mitem, RouteTimeAxisView& p)
+                   : what (w), menu_item (mitem), view (0), parent (p) {}
+
+           ~RedirectAutomationNode ();
+       };
+
+       struct RedirectAutomationInfo {
+           boost::shared_ptr<ARDOUR::Redirect> redirect;
+           bool                                valid;
+           Gtk::Menu*                          menu;
+           vector<RedirectAutomationNode*>     lines;
+
+           RedirectAutomationInfo (boost::shared_ptr<ARDOUR::Redirect> r) 
+                   : redirect (r), valid (true), menu (0) {}
+
+           ~RedirectAutomationInfo ();
+       };
+       
+
+       void diskstream_changed ();
+       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 *);
+       
+       void add_redirect_to_subplugin_menu (boost::shared_ptr<ARDOUR::Redirect>);
+       void remove_ran (RedirectAutomationNode* ran);
+
+       void redirect_menu_item_toggled (RouteTimeAxisView::RedirectAutomationInfo*,
+                                        RouteTimeAxisView::RedirectAutomationNode*);
+       
+       void redirect_automation_track_hidden (RedirectAutomationNode*,
+                                              boost::shared_ptr<ARDOUR::Redirect>);
+
+       RedirectAutomationNode*
+       find_redirect_automation_node (boost::shared_ptr<ARDOUR::Redirect> r, uint32_t);
+       
+       RedirectAutomationLine*
+       find_redirect_automation_curve (boost::shared_ptr<ARDOUR::Redirect> r, uint32_t);
+
+       void add_redirect_automation_curve (boost::shared_ptr<ARDOUR::Redirect> r, uint32_t);
+       void add_existing_redirect_automation_curves (boost::shared_ptr<ARDOUR::Redirect>);
+       
+       void reset_redirect_automation_curves ();
+
+       void update_automation_view (ARDOUR::AutomationType);
+       
+       void take_name_changed (void *);
+       void route_name_changed (void *);
+       void name_entry_changed ();
+
+       void on_area_realize ();
+
+       virtual void label_view ();
+       
+       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_automation_action_menu ();
+       virtual void append_extra_display_menu_items () {}
+       void         build_display_menu ();
+       
+       void align_style_changed ();
+       void set_align_style (ARDOUR::AlignStyle);
+       
+       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 ();
+       
+       void         automation_click ();
+       virtual void show_all_automation ();
+       virtual void show_existing_automation ();
+       virtual void hide_all_automation ();
+
+       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*);
+       
+       void region_view_added (RegionView*);
+       void add_ghost_to_redirect (RegionView*, AutomationTimeAxisView*);
+       
+       
+       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;
+       
+       Gtk::Menu           subplugin_menu;
+       Gtk::Menu*          automation_action_menu;
+       Gtk::Menu           edit_group_menu;
+       Gtk::RadioMenuItem* align_existing_item;
+       Gtk::RadioMenuItem* align_capture_item;
+       Gtk::Menu*          playlist_menu;
+       Gtk::Menu*          playlist_action_menu;
+       Gtk::MenuItem*      playlist_item;
+
+       ArdourCanvas::SimpleRect* timestretch_rect;
+       
+       list<RedirectAutomationInfo*>   redirect_automation;
+       vector<RedirectAutomationLine*> redirect_automation_curves;
+
+       sigc::connection modified_connection;
+       sigc::connection state_changed_connection;
+};
+
+#endif /* __ardour_route_time_axis_h__ */
+
index eb20eeac082f0da6bd28def4b47dec4420db6b4b..eaf28470daa1c7e95cccbabcff28a30f54140439 100644 (file)
@@ -70,14 +70,14 @@ RouteUI::RouteUI (boost::shared_ptr<ARDOUR::Route> rt, ARDOUR::Session& sess, co
         mute_button = manage (new BindableToggleButton (_route->mute_control(), m_name ));
         solo_button = manage (new BindableToggleButton (_route->solo_control(), s_name ));
        
-       if (is_audio_track()) {
-               boost::shared_ptr<AudioTrack> at = boost::dynamic_pointer_cast<AudioTrack>(_route);
+       if (is_track()) {
+               boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
 
-               at->disk_stream().record_enable_changed.connect (mem_fun (*this, &RouteUI::route_rec_enable_changed));
+               t->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);
                
@@ -268,7 +268,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
@@ -351,7 +351,7 @@ RouteUI::update_mute_display ()
 }
 
 void
-RouteUI::route_rec_enable_changed (void *src)
+RouteUI::route_rec_enable_changed ()
 {
        Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_rec_display));
 }
@@ -694,7 +694,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());
@@ -870,21 +870,21 @@ RouteUI::disconnect_output ()
 }
 
 bool
-RouteUI::is_audio_track () const
+RouteUI::is_track () const
 {
-       return dynamic_cast<AudioTrack*>(_route.get()) != 0;
+       return dynamic_cast<Track*>(_route.get()) != 0;
 }
 
-AudioDiskstream*
-RouteUI::get_diskstream () const
+Track*
+RouteUI::track() const
 {
-       boost::shared_ptr<AudioTrack> at;
+       return dynamic_cast<Track*>(_route.get());
+}
 
-       if ((at = boost::dynamic_pointer_cast<AudioTrack>(_route)) != 0) {
-               return &at->disk_stream();
-       } else {
-               return 0;
-       }
+bool
+RouteUI::is_audio_track () const
+{
+       return dynamic_cast<AudioTrack*>(_route.get()) != 0;
 }
 
 AudioTrack*
@@ -893,6 +893,18 @@ RouteUI::audio_track() const
        return dynamic_cast<AudioTrack*>(_route.get());
 }
 
+Diskstream*
+RouteUI::get_diskstream () const
+{
+       boost::shared_ptr<Track> t;
+
+       if ((t = boost::dynamic_pointer_cast<Track>(_route)) != 0) {
+               return &t->diskstream();
+       } else {
+               return 0;
+       }
+}
+
 string
 RouteUI::name() const
 {
@@ -917,3 +929,4 @@ RouteUI::map_frozen ()
                }
        }
 }
+
index 48f7d47b97dd7e70a9e5623cff88434fd2aa09e7..7415eddad6b58367eb13217da207e515c4e91a4e 100644 (file)
@@ -26,6 +26,7 @@
 #include <pbd/xml++.h>
 #include <ardour/ardour.h>
 #include <ardour/route.h>
+#include <ardour/track.h>
 
 #include "axis_view.h"
 
@@ -47,11 +48,16 @@ class RouteUI : public virtual AxisView
        RouteUI(boost::shared_ptr<ARDOUR::Route>, ARDOUR::Session&, const char*, const char*, const char*);
        virtual ~RouteUI();
 
+       bool is_track() const;
        bool is_audio_track() const;
-       ARDOUR::AudioDiskstream* get_diskstream() const;
 
        boost::shared_ptr<ARDOUR::Route> route() const { return _route; }
+       
+       // FIXME: make these return shared_ptr
+       ARDOUR::Track*      track() const;
        ARDOUR::AudioTrack* audio_track() const;
+       
+       ARDOUR::Diskstream* get_diskstream() const;
 
        string name() const;
 
@@ -89,7 +95,8 @@ class RouteUI : public virtual AxisView
 
        void solo_changed(void*);
        void mute_changed(void*);
-       void route_rec_enable_changed(void*);
+       virtual void redirects_changed (void *) {}
+       void route_rec_enable_changed();
        void session_rec_enable_changed();
 
        void build_solo_menu (void);
index 6dae5b0bcde81b9c5bebe248b66b29912203a6c9..086d878994813f56ce96e2faa98cbfd7b15b46da 100644 (file)
@@ -24,7 +24,7 @@
 
 #include <ardour/playlist.h>
 
-#include "regionview.h"
+#include "region_view.h"
 #include "selection.h"
 #include "selection_templates.h"
 #include "time_axis_view.h"
@@ -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()) {
index 102e6e941078691178adb321f14037f24d8ae066..7b503a5e63ef0f0dca17c583e8011cf5cac5d2d6 100644 (file)
@@ -35,7 +35,7 @@
 #include "point_selection.h"
 
 class TimeAxisView;
-class AudioRegionView;
+class RegionView;
 class Selectable;
 
 namespace ARDOUR {
@@ -61,7 +61,7 @@ class Selection : public sigc::trackable
        };
 
        TrackSelection       tracks;
-       AudioRegionSelection audio_regions;
+       RegionSelection      regions;
        TimeSelection        time;
        AutomationSelection  lines;
        PlaylistSelection    playlists;
@@ -89,15 +89,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*);
@@ -107,8 +107,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*);
@@ -117,8 +117,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*);
@@ -127,7 +127,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*);
@@ -137,7 +137,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 ();
@@ -145,10 +145,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;
index c2ca70b526583e5bd4d34df15497e31c27d4d72a..9511db7d618b0d840c8e3d75399cca5178f445c8 100644 (file)
 */
 
 #include <ardour/region.h>
-#include <ardour/audioregion.h>
 
 #include "selection.h"
+#include "region_view.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);
        }
 }
 
index a60e0d59e78fd9c474b49c7d19f4621052981ed4..31452e315b8325f941645fd23c5a41e2cb7601a6 100644 (file)
@@ -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 "region_view.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,21 +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()) {
-               /* TRACK */
-               //stream_base_color = RGBA_TO_UINT (222,223,218,255);
-               stream_base_color = color_map[cAudioTrackBase];
-       } else {
-               /* BUS */
-               //stream_base_color = RGBA_TO_UINT (230,226,238,255);
-               stream_base_color = color_map[cAudioBusBase];
-       }
 
        /* set_position() will position the group */
 
@@ -57,26 +60,23 @@ 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_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()->diskstream_changed.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()->record_enable_changed.connect (mem_fun (*this, &StreamView::rec_enable_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));
        } 
 
        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));
 }
@@ -90,7 +90,7 @@ StreamView::~StreamView ()
 void
 StreamView::attach ()
 {
-       if (_trackview.is_audio_track()) {
+       if (_trackview.is_track()) {
                display_diskstream (_trackview.get_diskstream());
        }
 }
@@ -115,13 +115,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);
@@ -134,7 +134,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;
@@ -146,10 +146,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);
                
@@ -163,113 +159,24 @@ 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)
 {
        add_region_view_internal (r, true);
 }
 
-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
@@ -282,14 +189,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;
                }
@@ -299,21 +200,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);
@@ -325,21 +220,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));
 
@@ -362,69 +249,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)));
-       playlist_connections.push_back (ds->playlist()->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
@@ -436,64 +260,12 @@ StreamView::playlist_state_changed (Change ignored)
 }
 
 void
-StreamView::redisplay_diskstream ()
+StreamView::diskstream_changed ()
 {
-       list<AudioRegionView *>::iterator i, tmp;
-       list<CrossfadeView*>::iterator xi, tmpx;
-
-       
-       for (i = region_views.begin(); i != region_views.end(); ++i) {
-               (*i)->set_valid (false);
-       }
+       Track *t;
 
-       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);
-               _trackview.get_diskstream()->playlist()->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;
-
-       if ((at = _trackview.audio_track()) != 0) {
-               AudioDiskstream& ds = at->disk_stream();
+       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 {
@@ -505,7 +277,7 @@ void
 StreamView::apply_color (Gdk::Color& color, ColorTarget target)
 
 {
-       list<AudioRegionView *>::iterator i;
+       list<RegionView *>::iterator i;
 
        switch (target) {
        case RegionColor:
@@ -525,64 +297,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();
 
@@ -590,11 +305,11 @@ 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
-StreamView::rec_enable_changed (void *src)
+StreamView::rec_enable_changed ()
 {
        Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &StreamView::setup_rec_box));
 }
@@ -611,161 +326,6 @@ StreamView::transport_changed()
        Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &StreamView::setup_rec_box));
 }
 
-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->disk_stream();
-                       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 ()
 {
@@ -776,7 +336,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);
@@ -795,12 +355,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 == &region) {
+               if (&(*i)->region() == &region) {
                        return *i;
                }
        }
@@ -808,172 +368,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;
-       }
-}
index 00ec2d93f2a8a13b52a52fd10f935b805caaf87f..0bec3197586651fdba638b8a576729b8dd154f16 100644 (file)
@@ -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&);
+       Gdk::Color get_region_color () const { return region_color; }
+       void       apply_color (Gdk::Color&, ColorTarget t);
+
+       RegionView*  find_view (const ARDOUR::Region&);
+       void         foreach_regionview (sigc::slot<void,RegionView*> slot);
+
+       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);
-       Gdk::Color get_region_color () const { return region_color; }
 
-       void foreach_regionview (sigc::slot<void,AudioRegionView*> slot);
-       void foreach_crossfadeview (void (CrossfadeView::*pmf)(void));
+       void add_region_view (ARDOUR::Region*);
+       void region_layered (RegionView*);
+       
+       sigc::signal<void,RegionView*> RegionViewAdded;
 
-       void attach ();
+protected:
+       StreamView (RouteTimeAxisView&);
        
-       void region_layered (AudioRegionView*);
+//private: (FIXME?)
+
+       void         transport_changed();
+       void         rec_enable_changed();
+       void         sess_rec_enable_changed();
+       virtual void setup_rec_box () = 0;
+       void         update_rec_box ();
+       virtual void update_rec_regions () = 0;
        
-       AudioRegionView* find_view (const ARDOUR::AudioRegion&);
-
-       void show_all_xfades ();
-       void hide_all_xfades ();
-       void hide_xfades_involving (AudioRegionView&);
-       void reveal_xfades_involving (AudioRegionView&);
+       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         display_diskstream (ARDOUR::Diskstream* );
+       virtual void undisplay_diskstream ();
+       virtual void redisplay_diskstream () = 0;
+       void         diskstream_changed ();
+       
+       void         playlist_state_changed (ARDOUR::Change);
+       virtual void playlist_changed (ARDOUR::Diskstream* );
+       virtual void playlist_modified ();
+       
+       virtual void color_handler (ColorID, uint32_t) = 0;
 
-  private:
-       AudioTimeAxisView& _trackview;
 
-       ArdourCanvas::Group* canvas_group;
+       RouteTimeAxisView&        _trackview;
+       ArdourCanvas::Group*      canvas_group;
        ArdourCanvas::SimpleRect* canvas_rect; /* frame around the whole thing */
 
-       typedef list<AudioRegionView* > AudioRegionViewList;
-       AudioRegionViewList region_views;
-
-       typedef list<CrossfadeView*> CrossfadeViewList;
-       CrossfadeViewList crossfade_views;
+       typedef list<RegionView* > RegionViewList;
+       RegionViewList  region_views;
 
        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;
-       
-       void update_rec_box ();
-       void transport_changed();
-       void rec_enable_changed(void*  src = 0);
-       void sess_rec_enable_changed();
-       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 (ARDOUR::Region*);
-       void add_region_view_internal (ARDOUR::Region*, bool wait_for_waves);
-       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 diskstream_changed (void* );
-       void playlist_state_changed (ARDOUR::Change);
-       void playlist_changed (ARDOUR::AudioDiskstream* );
-       void playlist_modified ();
-
-       bool crossfades_visible;
-       void add_crossfade (ARDOUR::Crossfade*);
-       void remove_crossfade (ARDOUR::Crossfade*);
 
-       /* XXX why are these different? */
+       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;
-
-       void color_handler (ColorID, uint32_t);
+       uint32_t   stream_base_color;
 
        vector<sigc::connection> playlist_connections;
-       sigc::connection playlist_change_connection;
+       sigc::connection         playlist_change_connection;
 };
 
 #endif /* __ardour_streamview_h__ */
+
diff --git a/gtk2_ardour/tape_region_view.cc b/gtk2_ardour/tape_region_view.cc
new file mode 100644 (file)
index 0000000..bd5ce8a
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+    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.
+
+    $Id$
+*/
+
+#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 "tape_region_view.h"
+#include "audio_time_axis.h"
+#include "gui_thread.h"
+
+#include "i18n.h"
+
+using namespace sigc;
+using namespace ARDOUR;
+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, RouteTimeAxisView &tv, 
+                                         AudioRegion& r, 
+                                         double spu, 
+                                         Gdk::Color& basic_color)
+
+       : AudioRegionView (parent, tv, r, spu, basic_color, 
+                          TimeAxisViewItem::Visibility ((r.position() != 0) ? default_tape_visibility : 
+                                                        TimeAxisViewItem::Visibility (default_tape_visibility|TimeAxisViewItem::HideFrameLeft)))
+{
+}
+
+void
+TapeAudioRegionView::init (Gdk::Color& basic_color, bool wfw)
+{
+       AudioRegionView::init(basic_color, wfw);
+
+       /* every time the wave data changes and peaks are ready, redraw */
+       
+       for (uint32_t n = 0; n < audio_region().n_channels(); ++n) {
+               audio_region().source(n).PeaksReady.connect (bind (mem_fun(*this, &TapeAudioRegionView::update), n));
+       }
+       
+}
+
+TapeAudioRegionView::~TapeAudioRegionView()
+{
+}
+
+void
+TapeAudioRegionView::update (uint32_t n)
+{
+       /* check that all waves are build and ready */
+
+       if (!tmp_waves.empty()) {
+               return;
+       }
+
+       ENSURE_GUI_THREAD (bind (mem_fun(*this, &TapeAudioRegionView::update), n));
+
+       /* this triggers a cache invalidation and redraw in the waveview */
+
+       waves[n]->property_data_src() = &_region;
+}
+
+void
+TapeAudioRegionView::set_frame_color ()
+{
+       fill_opacity = 255;
+       TimeAxisViewItem::set_frame_color ();
+}
diff --git a/gtk2_ardour/tape_region_view.h b/gtk2_ardour/tape_region_view.h
new file mode 100644 (file)
index 0000000..ed3852e
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+    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.
+
+    $Id$
+*/
+
+#ifndef __gtk_ardour_tape_audio_region_view_h__
+#define __gtk_ardour_tape_audio_region_view_h__
+
+#include <vector>
+
+#include "audio_region_view.h"
+
+class TapeAudioRegionView : public AudioRegionView
+{
+  public:
+       TapeAudioRegionView (ArdourCanvas::Group *, 
+                            RouteTimeAxisView&,
+                            ARDOUR::AudioRegion&,
+                            double initial_samples_per_unit,
+                            Gdk::Color& base_color);
+       ~TapeAudioRegionView ();
+
+  protected:
+       void init (Gdk::Color& base_color, bool wait_for_waves);
+
+       void set_frame_color ();
+       void update (uint32_t n);
+
+       static const TimeAxisViewItem::Visibility default_tape_visibility;
+};
+
+#endif /* __gtk_ardour_tape_audio_region_view_h__ */
diff --git a/gtk2_ardour/taperegionview.cc b/gtk2_ardour/taperegionview.cc
deleted file mode 100644 (file)
index 228e45a..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
-    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.
-
-    $Id$
-*/
-
-#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 "taperegionview.h"
-#include "audio_time_axis.h"
-#include "gui_thread.h"
-
-#include "i18n.h"
-
-using namespace sigc;
-using namespace ARDOUR;
-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, 
-                                         AudioRegion& r, 
-                                         double spu, 
-                                         Gdk::Color& basic_color)
-
-       : AudioRegionView (parent, tv, r, spu, basic_color, 
-                          TimeAxisViewItem::Visibility ((r.position() != 0) ? default_tape_visibility : 
-                                                        TimeAxisViewItem::Visibility (default_tape_visibility|TimeAxisViewItem::HideFrameLeft)))
-{
-}
-
-void
-TapeAudioRegionView::init (double amplitude_above_axis, Gdk::Color& basic_color, bool wfw)
-{
-       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) {
-               set_flags (node);
-       } else {
-               _flags = WaveformVisible;
-               store_flags ();
-       }
-
-       fade_in_handle = 0;
-       fade_out_handle = 0;
-       gain_line = 0;
-       sync_mark = 0;
-
-       compute_colors (basic_color);
-
-       create_waves ();
-
-       name_highlight->set_data ("regionview", this);
-
-       reset_width_dependent_items ((double) region.length() / samples_per_unit);
-
-       set_height (trackview.height);
-
-       region_muted ();
-       region_resized (BoundsChanged);
-       set_waveview_data_src();
-       region_locked ();
-
-       /* no events, no state changes */
-
-       set_colors ();
-
-       // ColorChanged.connect (mem_fun (*this, &AudioRegionView::color_handler));
-
-       /* 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));
-       }
-       
-}
-
-TapeAudioRegionView::~TapeAudioRegionView()
-{
-}
-
-void
-TapeAudioRegionView::update (uint32_t n)
-{
-       /* check that all waves are build and ready */
-
-       if (!tmp_waves.empty()) {
-               return;
-       }
-
-       ENSURE_GUI_THREAD (bind (mem_fun(*this, &TapeAudioRegionView::update), n));
-
-       /* this triggers a cache invalidation and redraw in the waveview */
-
-       waves[n]->property_data_src() = &region;
-}
-
-void
-TapeAudioRegionView::set_frame_color ()
-{
-       fill_opacity = 255;
-       TimeAxisViewItem::set_frame_color ();
-}
diff --git a/gtk2_ardour/taperegionview.h b/gtk2_ardour/taperegionview.h
deleted file mode 100644 (file)
index 6b4a57f..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
-    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.
-
-    $Id$
-*/
-
-#ifndef __gtk_ardour_tape_audio_region_view_h__
-#define __gtk_ardour_tape_audio_region_view_h__
-
-#include <vector>
-
-#include "regionview.h"
-
-class TapeAudioRegionView : public AudioRegionView
-{
-  public:
-       TapeAudioRegionView (ArdourCanvas::Group *, 
-                            AudioTimeAxisView&,
-                            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 set_frame_color ();
-       void update (uint32_t n);
-
-       static const TimeAxisViewItem::Visibility default_tape_visibility;
-};
-
-#endif /* __gtk_ardour_tape_audio_region_view_h__ */
index c607c781664a43acd0761cf8c0fff5760b9d919e..31ff3d84eefc40f06c604396b28965d979d8be16 100644 (file)
@@ -54,7 +54,7 @@ namespace Gtk {
 }
 
 class PublicEditor;
-class AudioRegionSelection;
+class RegionSelection;
 class TimeSelection;
 class PointSelection;
 class TimeAxisViewItem;
@@ -183,7 +183,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) {
index c27ed33089bdab3ee2ce10ea3eb5c257ff7f80d2..e44ea4011e2d3fdcac138371f03e7198dd999cb0 100644 (file)
@@ -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
 }
index 4be2da3b9a495eeb7ec12d64ac15ac02728a3347..c68ce8da1c63e97ed54d5642a18843cb17a5e9d5 100644 (file)
@@ -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&) ;
        
 
                //---------------------------------------------------------------------------------//
index 1c3092135382f54ac46c8c88fffe2269835bd595..303f021f429f40b48a7f38c7eb2b31b83d65a5c8 100644 (file)
@@ -27,9 +27,11 @@ ardour.Append(POTFILE = domain + '.pot')
 ardour.Append(CPPPATH = '#libs/surfaces/control_protocol')
 
 ardour_files=Split("""
+diskstream.cc
 audio_diskstream.cc
 audio_library.cc
 audio_playlist.cc
+track.cc
 audio_track.cc
 audioengine.cc
 audiofilesource.cc
index 0a0c908d31e573f89ef8882a80b2a089b5408c7e..e2dfc5fd0c92051300162059667ff37097cd9ab9 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2000 Paul Davis 
+    Copyright (C) 2000-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
     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: diskstream.h 579 2006-06-12 19:56:37Z essej $
 */
 
-#ifndef __ardour_diskstream_h__
-#define __ardour_diskstream_h__
+#ifndef __ardour_audio_diskstream_h__
+#define __ardour_audio_diskstream_h__
 
 #include <sigc++/signal.h>
 
@@ -42,6 +40,8 @@
 #include <ardour/route.h>
 #include <ardour/port.h>
 #include <ardour/utils.h>
+#include <ardour/diskstream.h>
+#include <ardour/audioplaylist.h>
 
 struct tm;
 
@@ -54,53 +54,20 @@ class AudioPlaylist;
 class AudioFileSource;
 class IO;
 
-class AudioDiskstream : public Stateful, public sigc::trackable
+class AudioDiskstream : public Diskstream
 {      
   public:
-       enum Flag {
-               Recordable = 0x1,
-               Hidden = 0x2,
-               Destructive = 0x4
-       };
-
-       AudioDiskstream (Session &, const string& name, Flag f = Recordable);
+       AudioDiskstream (Session &, const string& name, Diskstream::Flag f = Recordable);
        AudioDiskstream (Session &, const XMLNode&);
 
-       string name() const { return _name; }
-
-       ARDOUR::IO* io() const { return _io; }
-       void set_io (ARDOUR::IO& io);
+       const PBD::ID& id() const { return _id; }
 
+       // FIXME
        AudioDiskstream& ref() { _refcnt++; return *this; }
-       void unref() { if (_refcnt) _refcnt--; if (_refcnt == 0) delete this; }
-       uint32_t refcnt() const { return _refcnt; }
 
        float playback_buffer_load() const;
        float capture_buffer_load() const;
 
-       void set_flag (Flag f) {
-               _flags |= f;
-       }
-
-       void unset_flag (Flag f) {
-               _flags &= ~f;
-       }
-
-       AlignStyle alignment_style() const { return _alignment_style; }
-       void set_align_style (AlignStyle);
-       void set_persistent_align_style (AlignStyle);
-
-       bool hidden() const { return _flags & Hidden; }
-       bool recordable() const { return _flags & Recordable; }
-       bool destructive() const { return _flags & Destructive; }
-
-       void set_destructive (bool yn);
-
-       jack_nframes_t roll_delay() const { return _roll_delay; }
-       void set_roll_delay (jack_nframes_t);
-
-       int set_name (string str, void* src);
-
        string input_source (uint32_t n=0) const {
                if (n < channels.size()) {
                        return channels[n].source ? channels[n].source->name() : "";
@@ -113,14 +80,7 @@ class AudioDiskstream : public Stateful, public sigc::trackable
                if (n < channels.size()) return channels[n].source; return 0; 
        }
 
-       void set_record_enabled (bool yn, void *src);
-       bool record_enabled() const { return g_atomic_int_get (&_record_enabled); }
-       void punch_in ();
-       void punch_out ();
-
-       bool  reversed() const { return _actual_speed < 0.0f; }
-       double speed() const { return _visible_speed; }
-       void set_speed (double);
+       void set_record_enabled (bool yn);
 
        float peak_power(uint32_t n=0) { 
                float x = channels[n].peak_power;
@@ -131,14 +91,13 @@ class AudioDiskstream : public Stateful, public sigc::trackable
                        return minus_infinity();
                }
        }
+       
+       AudioPlaylist* audio_playlist () { return dynamic_cast<AudioPlaylist*>(_playlist); }
 
-       int  use_playlist (AudioPlaylist *);
+       int use_playlist (Playlist *);
        int use_new_playlist ();
        int use_copy_playlist ();
 
-       void start_scrub (jack_nframes_t where);
-       void end_scrub ();
-
        Sample *playback_buffer (uint32_t n=0) {
                if (n < channels.size())
                        return channels[n].current_playback_buffer;
@@ -151,51 +110,23 @@ class AudioDiskstream : public Stateful, public sigc::trackable
                return 0;
        }
 
-       AudioPlaylist *playlist () { return _playlist; }
-
        AudioFileSource *write_source (uint32_t n=0) {
                if (n < channels.size())
                        return channels[n].write_source;
                return 0;
        }
 
-       jack_nframes_t current_capture_start() const { return capture_start_frame; }
-       jack_nframes_t current_capture_end() const { return capture_start_frame + capture_captured; }
-       jack_nframes_t get_capture_start_frame (uint32_t n=0);
-       jack_nframes_t get_captured_frames (uint32_t n=0);
-       
-       uint32_t n_channels() { return _n_channels; }
-
        int add_channel ();
        int remove_channel ();
        
-       static void set_disk_io_chunk_frames (uint32_t n) {
-               disk_io_chunk_frames = n;
-       }
-
-       static jack_nframes_t disk_io_frames() { return disk_io_chunk_frames; }
        
-       sigc::signal<void,void*> record_enable_changed;
-       sigc::signal<void>       speed_changed;
-       sigc::signal<void,void*> reverse_changed;
-       sigc::signal<void>       PlaylistChanged;
-       sigc::signal<void>       AlignmentStyleChanged;
-
-       static sigc::signal<void> DiskOverrun;
-       static sigc::signal<void> DiskUnderrun;
-       static sigc::signal<void,AudioDiskstream*> AudioDiskstreamCreated;   // XXX use a ref with sigc2
-       static sigc::signal<void,list<AudioFileSource*>*> DeleteSources;
-
        /* stateful */
 
        XMLNode& get_state(void);
-       int set_state(const XMLNode& node);
+       int      set_state(const XMLNode& node);
 
        void monitor_input (bool);
 
-       jack_nframes_t capture_offset() const { return _capture_offset; }
-       void           set_capture_offset ();
-
        static void swap_by_ptr (Sample *first, Sample *last) {
                while (first < last) {
                        Sample tmp = *first;
@@ -212,19 +143,7 @@ class AudioDiskstream : public Stateful, public sigc::trackable
                }
        }
 
-       bool slaved() const { return _slaved; }
-       void set_slaved(bool yn) { _slaved = yn; }
-
-       int set_loop (Location *loc);
-       sigc::signal<void,Location *> LoopSet;
-
-       std::list<Region*>& last_capture_regions () {
-               return _last_capture_regions;
-       }
-
-       void handle_input_change (IOChange, void *src);
-
-       const PBD::ID& id() const { return _id; }
+       std::list<Region*>& last_capture_regions () { return _last_capture_regions; }
 
        XMLNode* deprecated_io_node;
 
@@ -236,9 +155,8 @@ class AudioDiskstream : public Stateful, public sigc::trackable
           while they are called.
        */
 
-       void set_pending_overwrite (bool);
+       void set_pending_overwrite(bool);
        int  overwrite_existing_buffers ();
-       void reverse_scrub_buffer (bool to_forward);
        void set_block_size (jack_nframes_t);
        int  internal_playback_seek (jack_nframes_t distance);
        int  can_internal_playback_seek (jack_nframes_t distance);
@@ -246,9 +164,6 @@ class AudioDiskstream : public Stateful, public sigc::trackable
        void reset_write_sources (bool, bool force = false);
        void non_realtime_input_change ();
 
-       uint32_t read_data_count() const { return _read_data_count; }
-       uint32_t write_data_count() const { return _write_data_count; }
-
   protected:
        friend class Auditioner;
        int  seek (jack_nframes_t which_sample, bool complete_refill = false);
@@ -256,38 +171,23 @@ class AudioDiskstream : public Stateful, public sigc::trackable
   protected:
        friend class AudioTrack;
 
-       void prepare ();
        int  process (jack_nframes_t transport_frame, jack_nframes_t nframes, jack_nframes_t offset, bool can_record, bool rec_monitors_input);
        bool commit  (jack_nframes_t nframes);
-       void recover (); /* called if commit will not be called, but process was */
 
   private:
 
        /* use unref() to destroy a diskstream */
-
        ~AudioDiskstream();
 
-       enum TransitionType {
-               CaptureStart = 0,
-               CaptureEnd
-       };
-       
-       struct CaptureTransition {
-
-               TransitionType   type;
-               // the start or end file frame pos
-               jack_nframes_t   capture_val;
-       };
-       
        struct ChannelInfo {
 
                Sample     *playback_wrap_buffer;
                Sample     *capture_wrap_buffer;
                Sample     *speed_buffer;
 
-               float       peak_power;
+               float       peak_power;
 
-               AudioFileSource   *fades_source;
+               AudioFileSource   *fades_source;
                AudioFileSource   *write_source;
 
                Port         *source;
@@ -309,129 +209,30 @@ class AudioDiskstream : public Stateful, public sigc::trackable
                jack_nframes_t                     curr_capture_cnt;
        };
 
-       typedef vector<ChannelInfo> ChannelList;
-
-
-       string            _name;
-       ARDOUR::Session&  _session;
-       ARDOUR::IO*       _io;
-       ChannelList        channels;
-       uint32_t      _n_channels;
-       PBD::ID           _id;
-
-       mutable gint             _record_enabled;
-       AudioPlaylist*           _playlist;
-       double                   _visible_speed;
-       double                   _actual_speed;
-       /* items needed for speed change logic */
-       bool                     _buffer_reallocation_required;
-       bool                     _seek_required;
-       
-       bool                      force_refill;
-       jack_nframes_t            capture_start_frame;
-       jack_nframes_t            capture_captured;
-       bool                      was_recording;
-       jack_nframes_t            adjust_capture_position;
-       jack_nframes_t           _capture_offset;
-       jack_nframes_t           _roll_delay;
-       jack_nframes_t            first_recordable_frame;
-       jack_nframes_t            last_recordable_frame;
-       int                       last_possibly_recording;
-       AlignStyle               _alignment_style;
-       bool                     _scrubbing;
-       bool                     _slaved;
-       bool                     _processed;
-       Location*                 loop_location;
-       jack_nframes_t            overwrite_frame;
-       off_t                     overwrite_offset;
-       bool                      pending_overwrite;
-       bool                      overwrite_queued;
-       IOChange                  input_change_pending;
-       jack_nframes_t            wrap_buffer_size;
-       jack_nframes_t            speed_buffer_size;
-
-       uint64_t                  last_phase;
-       uint64_t                  phi;
-       
-       jack_nframes_t            file_frame;           
-       jack_nframes_t            playback_sample;
-       jack_nframes_t            playback_distance;
-
-       uint32_t                 _read_data_count;
-       uint32_t                 _write_data_count;
-
-       bool                      in_set_state;
-       AlignStyle               _persistent_alignment_style;
-       bool                      first_input_change;
-
-       Glib::Mutex  state_lock;
-
-       jack_nframes_t scrub_start;
-       jack_nframes_t scrub_buffer_size;
-       jack_nframes_t scrub_offset;
-       uint32_t _refcnt;
-
-       sigc::connection ports_created_c;
-       sigc::connection plmod_connection;
-       sigc::connection plstate_connection;
-       sigc::connection plgone_connection;
-
-       /* the two central butler operations */
-
-       int do_flush (char * workbuf, bool force = false);
-       int do_refill (Sample *mixdown_buffer, float *gain_buffer, char *workbuf);
-
-       int read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, char * workbuf, jack_nframes_t& start, jack_nframes_t cnt, 
-                 ChannelInfo& channel_info, int channel, bool reversed);
-
-       uint32_t i_am_the_modifier;
+       /* The two central butler operations */
+       int do_flush (Session::RunContext context, bool force = false);
+       int do_refill () { return _do_refill(_mixdown_buffer, _gain_buffer, _conversion_buffer); }
        
-       /* XXX fix this redundancy ... */
+       int do_refill_with_alloc();
 
-       void playlist_changed (Change);
-       void playlist_modified ();
-       void playlist_deleted (Playlist*);
-       void session_controls_changed (Session::ControlType);
+       int read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, char * workbuf,
+               jack_nframes_t& start, jack_nframes_t cnt, 
+               ChannelInfo& channel_info, int channel, bool reversed);
 
        void finish_capture (bool rec_monitors_input);
-       void clean_up_capture (struct tm&, time_t, bool abort);
        void transport_stopped (struct tm&, time_t, bool abort);
 
-       struct CaptureInfo {
-           uint32_t start;
-           uint32_t frames;
-       };
-
-       vector<CaptureInfo*> capture_info;
-       Glib::Mutex  capture_info_lock;
-       
-       void init (Flag);
+       void init (Diskstream::Flag);
 
        void init_channel (ChannelInfo &chan);
        void destroy_channel (ChannelInfo &chan);
        
-       static jack_nframes_t disk_io_chunk_frames;
-
        int use_new_write_source (uint32_t n=0);
-       int use_new_fade_source (uint32_t n=0);
 
        int find_and_use_playlist (const string&);
 
        void allocate_temporary_buffers ();
 
-       unsigned char _flags;
-
-       int  create_input_port ();
-       int  connect_input_port ();
-       int  seek_unlocked (jack_nframes_t which_sample);
-
-       int ports_created ();
-
-       bool realtime_set_speed (double, bool global_change);
-       void non_realtime_set_speed ();
-
-       std::list<Region*> _last_capture_regions;
-       std::vector<AudioFileSource*> capturing_sources;
        int use_pending_capture_data (XMLNode& node);
 
        void get_input_sources ();
@@ -439,10 +240,29 @@ class AudioDiskstream : public Stateful, public sigc::trackable
        void set_align_style_from_io();
        void setup_destructive_playlist ();
        void use_destructive_playlist ();
-       void engage_record_enable (void* src);
-       void disengage_record_enable (void* src);
+
+       void engage_record_enable ();
+       void disengage_record_enable ();
+
+       // Working buffers for do_refill (butler thread)
+       static void allocate_working_buffers();
+       static void free_working_buffers();
+
+       static size_t  _working_buffers_size;
+       static Sample* _mixdown_buffer;
+       static gain_t* _gain_buffer;
+       static char*   _conversion_buffer;
+
+       // Uh, /really/ private?  (death to friend classes)
+       int _do_refill (Sample *mixdown_buffer, float *gain_buffer, char *workbuf);
+       
+       
+       std::vector<AudioFileSource*> capturing_sources;
+       
+       typedef vector<ChannelInfo> ChannelList;
+       ChannelList channels;
 };
 
 } // namespace ARDOUR
 
-#endif /* __ardour_diskstream_h__ */
+#endif /* __ardour_audio_diskstream_h__ */
index 5f65e2591d2edf8d741b7f4a1682f07126e85080..15b99297c883b42dd5e9de0de1d65f2c9ad4523c 100644 (file)
@@ -21,7 +21,7 @@
 #ifndef __ardour_audio_track_h__
 #define __ardour_audio_track_h__
 
-#include <ardour/route.h>
+#include <ardour/track.h>
 
 namespace ARDOUR {
 
@@ -30,76 +30,38 @@ class AudioDiskstream;
 class AudioPlaylist;
 class RouteGroup;
 
-class AudioTrack : public Route
+class AudioTrack : public Track
 {
   public:
        AudioTrack (Session&, string name, Route::Flag f = Route::Flag (0), TrackMode m = Normal);
        AudioTrack (Session&, const XMLNode&);
        ~AudioTrack ();
-       
-       int set_name (string str, void *src);
-
-       int  roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, 
 
-                  jack_nframes_t offset, int declick, bool can_record, bool rec_monitors_input);
-       int  no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, 
-                     jack_nframes_t offset, bool state_changing, bool can_record, bool rec_monitors_input);
-       int  silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, 
-                         jack_nframes_t offset, bool can_record, bool rec_monitors_input);
-
-       void toggle_monitor_input ();
+       int roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, 
+               jack_nframes_t offset, int declick, bool can_record, bool rec_monitors_input);
+       
+       int no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, 
+               jack_nframes_t offset, bool state_changing, bool can_record, bool rec_monitors_input);
+       
+       int silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, 
+               jack_nframes_t offset, bool can_record, bool rec_monitors_input);
 
-       bool can_record() const { return true; }
-       void set_record_enable (bool yn, void *src);
+       AudioDiskstream& audio_diskstream() const;
 
-       AudioDiskstream& disk_stream() const { return *diskstream; }
-       int set_diskstream (AudioDiskstream&, void *);
        int use_diskstream (string name);
        int use_diskstream (const PBD::ID& id);
-
-       TrackMode mode() const { return _mode; }
-       void set_mode (TrackMode m);
-       sigc::signal<void> ModeChanged;
-
-       jack_nframes_t update_total_latency();
-       void set_latency_delay (jack_nframes_t);
        
        int export_stuff (vector<Sample*>& buffers, char * workbuf, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t end_frame);
 
-       sigc::signal<void,void*> diskstream_changed;
-
-       enum FreezeState {
-               NoFreeze,
-               Frozen,
-               UnFrozen
-       };
-
-       FreezeState freeze_state() const;
-
-       sigc::signal<void> FreezeChange;
        void freeze (InterThreadInfo&);
        void unfreeze ();
 
        void bounce (InterThreadInfo&);
        void bounce_range (jack_nframes_t start, jack_nframes_t end, InterThreadInfo&);
 
-       XMLNode& get_state();
-       XMLNode& get_template();
        int set_state(const XMLNode& node);
 
-       PBD::Controllable& rec_enable_control() {
-               return _rec_enable_control;
-       }
-
-       bool record_enabled() const;
-       void set_meter_point (MeterPoint, void* src);
-
   protected:
-       AudioDiskstream *diskstream;
-       MeterPoint _saved_meter_point;
-       TrackMode _mode;
-
        XMLNode& state (bool full);
 
        void passthru_silence (jack_nframes_t start_frame, jack_nframes_t end_frame, 
@@ -107,59 +69,12 @@ class AudioTrack : public Route
                               bool meter);
 
        uint32_t n_process_buffers ();
-
+       
   private:
-       struct FreezeRecordInsertInfo {
-           FreezeRecordInsertInfo(XMLNode& st, boost::shared_ptr<Insert> ins) 
-                   : state (st), insert (ins) {}
-
-           XMLNode    state;
-           boost::shared_ptr<Insert>    insert;
-           PBD::ID    id;
-           UndoAction memento;
-       };
-
-       struct FreezeRecord {
-           FreezeRecord() {
-                   playlist = 0;
-                   have_mementos = false;
-           }
-
-           ~FreezeRecord();
-
-           AudioPlaylist* playlist;
-           vector<FreezeRecordInsertInfo*> insert_info;
-           bool have_mementos;
-           FreezeState state;
-       };
-
-       FreezeRecord _freeze_record;
-       XMLNode* pending_state;
-
-       void diskstream_record_enable_changed (void *src);
-       void diskstream_input_channel_changed (void *src);
-
-       void input_change_handler (void *src);
-
-       sigc::connection recenable_connection;
-       sigc::connection ic_connection;
-
-       int deprecated_use_diskstream_connections ();
+       int  set_diskstream (AudioDiskstream&, void *);
+       int  deprecated_use_diskstream_connections ();
        void set_state_part_two ();
        void set_state_part_three ();
-
-       struct RecEnableControllable : public PBD::Controllable {
-           RecEnableControllable (AudioTrack&);
-           
-           void set_value (float);
-           float get_value (void) const;
-
-           AudioTrack& track;
-       };
-
-       RecEnableControllable _rec_enable_control;
-
-       bool _destructive;
 };
 
 } // namespace ARDOUR
index 8db795ae902fc49fbc331d6d327619623f79b7e2..81370e379c4746d38f92f85da20f5af6fd89c47e 100644 (file)
@@ -34,6 +34,7 @@
 #include <ardour/ardour.h>
 #include <jack/jack.h>
 #include <jack/transport.h>
+#include <ardour/types.h>
 
 namespace ARDOUR {
 
@@ -104,8 +105,8 @@ class AudioEngine : public sigc::trackable
                virtual const char *what() const throw() { return "could not connect to engine backend"; }
        };
 
-       Port *register_audio_input_port (const std::string& portname);
-       Port *register_audio_output_port (const std::string& portname);
+       Port *register_input_port (DataType type, const std::string& portname);
+       Port *register_output_port (DataType type, const std::string& portname);
        int   unregister_port (Port *);
        
        int connect (const std::string& source, const std::string& destination);
index 1b60cf185d2a0dd31bccc2b72169eb23247316fe..5a77067f8fd76f95b2d127bae9e120ffb9e9f127 100644 (file)
@@ -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:
index d7bb0c916b3734bf0ebac9005fa22bc1c487c110..683e946713029d31ecd9986554e270f16c8dc7a3 100644 (file)
@@ -27,8 +27,9 @@
 #include <pbd/undo.h>
 
 #include <ardour/ardour.h>
-#include <ardour/gain.h>
 #include <ardour/region.h>
+#include <ardour/gain.h>
+#include <ardour/logcurve.h>
 #include <ardour/export.h>
 
 class XMLNode;
@@ -43,14 +44,14 @@ class AudioSource;
 
 struct AudioRegionState : public RegionState 
 {
-    AudioRegionState (std::string why);
-
-    Curve _fade_in;
-    Curve _fade_out;
-    Curve _envelope;
-    gain_t _scale_amplitude;
-    uint32_t _fade_in_disabled;
-    uint32_t _fade_out_disabled;
+       AudioRegionState (std::string why);
+
+       Curve    _fade_in;
+       Curve    _fade_out;
+       Curve    _envelope;
+       gain_t   _scale_amplitude;
+       uint32_t _fade_in_disabled;
+       uint32_t _fade_out_disabled;
 };
 
 class AudioRegion : public Region
@@ -75,11 +76,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;
 
@@ -96,7 +93,7 @@ class AudioRegion : public Region
        vector<string> master_source_names();
        
        bool envelope_active () const { return _flags & Region::EnvelopeActive; }
-       bool fade_in_active () const { return _flags & Region::FadeIn; }
+       bool fade_in_active ()  const { return _flags & Region::FadeIn; }
        bool fade_out_active () const { return _flags & Region::FadeOut; }
        bool captured() const { return !(_flags & (Region::Flag (Region::Import|Region::External))); }
 
@@ -104,20 +101,21 @@ class AudioRegion : public Region
        Curve& fade_out() { return _fade_out; }
        Curve& envelope() { return _envelope; }
 
-       jack_nframes_t read_peaks (PeakData *buf, jack_nframes_t npeaks, jack_nframes_t offset, jack_nframes_t cnt, uint32_t chan_n=0, double samples_per_unit= 1.0) const;
-
-       virtual jack_nframes_t read_at (Sample *buf, Sample *mixdown_buffer, 
-                                       float *gain_buffer, char * workbuf, jack_nframes_t position, jack_nframes_t cnt, 
-                                       uint32_t chan_n = 0,
-                                       jack_nframes_t read_frames = 0,
-                                       jack_nframes_t skip_frames = 0) const;
+       jack_nframes_t read_peaks (PeakData *buf, jack_nframes_t npeaks,
+                       jack_nframes_t offset, jack_nframes_t cnt,
+                       uint32_t chan_n=0, double samples_per_unit= 1.0) const;
 
-       jack_nframes_t master_read_at (Sample *buf, Sample *mixdown_buffer, 
-                                      float *gain_buffer, char * workbuf, jack_nframes_t position, jack_nframes_t cnt, uint32_t chan_n=0) const;
+       virtual jack_nframes_t read_at (Sample *buf, Sample *mixdown_buf,
+                       float *gain_buf, char * workbuf, jack_nframes_t position, jack_nframes_t cnt, 
+                       uint32_t       chan_n      = 0,
+                       jack_nframes_t read_frames = 0,
+                       jack_nframes_t skip_frames = 0) const;
 
+       jack_nframes_t master_read_at (Sample *buf, Sample *mixdown_buf, 
+                       float *gain_buf, char * workbuf,
+                       jack_nframes_t position, jack_nframes_t cnt, uint32_t chan_n=0) const;
 
        XMLNode& state (bool);
-       XMLNode& get_state ();
        int      set_state (const XMLNode&);
 
        static void set_default_fade (float steepness, jack_nframes_t len);
@@ -144,10 +142,6 @@ class AudioRegion : public Region
 
        int separate_by_channel (ARDOUR::Session&, vector<AudioRegion*>&) const;
 
-       uint32_t read_data_count() const { return _read_data_count; }
-
-       ARDOUR::Playlist* playlist() const { return _playlist; }
-
        UndoAction get_memento() const;
 
        /* filter */
@@ -171,20 +165,6 @@ class AudioRegion : public Region
        friend class Playlist;
 
   private:
-       SourceList        sources;
-       SourceList        master_sources; /* used when timefx are applied, so 
-                                            we can always use the original
-                                            source.
-                                         */
-       mutable Curve     _fade_in;
-       FadeShape         _fade_in_shape;
-       mutable Curve     _fade_out;
-       FadeShape         _fade_out_shape;
-       mutable Curve     _envelope;
-       gain_t            _scale_amplitude;
-       uint32_t          _fade_in_disabled;
-       uint32_t          _fade_out_disabled;
-
        void set_default_fades ();
        void set_default_fade_in ();
        void set_default_fade_out ();
@@ -196,10 +176,6 @@ class AudioRegion : public Region
        void recompute_gain_at_end ();
        void recompute_gain_at_start ();
 
-       bool copied() const { return _flags & Copied; }
-       void maybe_uncopy ();
-       void rename_after_first_edit ();
-
        jack_nframes_t _read_at (const SourceList&, Sample *buf, Sample *mixdown_buffer, 
                                 float *gain_buffer, char * workbuf, jack_nframes_t position, jack_nframes_t cnt, 
                                 uint32_t chan_n = 0,
@@ -216,6 +192,21 @@ class AudioRegion : public Region
        void envelope_changed (Change);
 
        void source_deleted (Source*);
+       
+       
+       SourceList        sources;
+       
+       /** Used when timefx are applied, so we can always use the original source. */
+       SourceList        master_sources; 
+
+       mutable Curve     _fade_in;
+       FadeShape         _fade_in_shape;
+       mutable Curve     _fade_out;
+       FadeShape         _fade_out_shape;
+       mutable Curve     _envelope;
+       gain_t            _scale_amplitude;
+       uint32_t          _fade_in_disabled;
+       uint32_t          _fade_out_disabled;
 };
 
 } /* namespace ARDOUR */
diff --git a/libs/ardour/ardour/buffer.h b/libs/ardour/ardour/buffer.h
new file mode 100644 (file)
index 0000000..6604e55
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+    Copyright (C) 2006 Paul Davis 
+    Written by Dave Robillard, 2006
+    
+    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_buffer_h__
+#define __ardour_buffer_h__
+
+#define _XOPEN_SOURCE 600
+#include <cstdlib> // for posix_memalign
+#include <cassert>
+#include <ardour/types.h>
+#include <jack/jack.h>
+
+namespace ARDOUR {
+
+
+/* Yes, this is a bit of a mess right now.  I'll clean it up when everything
+ * using it works out.. */
+
+
+/** A buffer of recordable/playable data.
+ *
+ * This is a datatype-agnostic base class for all buffers (there are no
+ * methods to actually access the data).  This provides a way for code that
+ * doesn't care about the data type to still deal with buffers (which is
+ * why the base class can't be a template).
+ * 
+ * To actually read/write buffer contents, use the appropriate derived class.
+ */
+class Buffer
+{
+public:
+       Buffer(DataType type, size_t capacity)
+       : _type(type), _capacity(capacity), _size(0) 
+       {}
+
+       virtual ~Buffer() {}
+
+       /** Maximum capacity of buffer.
+        * Note in some cases the entire buffer may not contain valid data, use size. */
+       size_t capacity() const { return _capacity; }
+
+       /** Amount of valid data in buffer.  Use this over capacity almost always. */
+       size_t size() const { return _size; }
+
+       /** Type of this buffer.
+        * Based on this you can static cast a Buffer* to the desired type. */
+       virtual DataType type() const { return _type; }
+
+       /** Jack type (eg JACK_DEFAULT_AUDIO_TYPE) */
+       const char* jack_type() const { return type_to_jack_type(type()); }
+       
+       /** String type as saved in session XML files (eg "audio" or "midi") */
+       const char* type_string() const { return type_to_string(type()); }
+
+       /* The below static methods need to be separate from the above methods
+        * because the conversion is needed in places where there's no Buffer.
+        * These should probably live somewhere else...
+        */
+
+       static const char* type_to_jack_type(DataType t) {
+               switch (t) {
+                       case AUDIO: return JACK_DEFAULT_AUDIO_TYPE;
+                       case MIDI:  return JACK_DEFAULT_MIDI_TYPE;
+                       default:    return "";
+               }
+       }
+       
+       static const char* type_to_string(DataType t) {
+               switch (t) {
+                       case AUDIO: return "audio";
+                       case MIDI:  return "midi";
+                       default:    return "unknown"; // reeeally shouldn't ever happen
+               }
+       }
+
+       /** Used for loading from XML (route default types etc) */
+       static DataType type_from_string(const string& str) {
+               if (str == "audio")
+                       return AUDIO;
+               else if (str == "midi")
+                       return MIDI;
+               else
+                       return NIL;
+       }
+
+protected:
+       DataType _type;
+       size_t   _capacity;
+       size_t   _size;
+};
+
+
+/* Inside every class with a type in it's name is a template waiting to get out... */
+
+
+/** Buffer containing 32-bit floating point (audio) data. */
+class AudioBuffer : public Buffer
+{
+public:
+       AudioBuffer(size_t capacity)
+               : Buffer(AUDIO, capacity)
+               , _data(NULL)
+       {
+               _size = capacity; // For audio buffers, size = capacity (always)
+#ifdef NO_POSIX_MEMALIGN
+               b =  (Sample *) malloc(sizeof(Sample) * capacity);
+#else
+               posix_memalign((void**)_data, 16, sizeof(Sample) * capacity);
+#endif 
+               assert(_data);
+               memset(_data, 0, sizeof(Sample) * capacity);
+       }
+
+       const Sample* data() const { return _data; }
+       Sample*       data()       { return _data; }
+
+private:
+       // These are undefined (prevent copies)
+       AudioBuffer(const AudioBuffer& copy);            
+       AudioBuffer& operator=(const AudioBuffer& copy);
+
+       Sample* const _data; ///< Actual buffer contents
+};
+
+
+} // namespace ARDOUR
+
+#endif // __ardour_buffer_h__
diff --git a/libs/ardour/ardour/diskstream.h b/libs/ardour/ardour/diskstream.h
new file mode 100644 (file)
index 0000000..ebce516
--- /dev/null
@@ -0,0 +1,319 @@
+/*
+    Copyright (C) 2000-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.
+
+    $Id: diskstream.h 579 2006-06-12 19:56:37Z essej $
+*/
+
+#ifndef __ardour_diskstream_h__
+#define __ardour_diskstream_h__
+
+#include <sigc++/signal.h>
+
+#include <cmath>
+#include <string>
+#include <queue>
+#include <map>
+#include <vector>
+
+#include <time.h>
+
+#include <pbd/fastlog.h>
+#include <pbd/ringbufferNPT.h>
+#include <pbd/stateful.h>
+
+#include <ardour/ardour.h>
+#include <ardour/configuration.h>
+#include <ardour/session.h>
+#include <ardour/route_group.h>
+#include <ardour/route.h>
+#include <ardour/port.h>
+#include <ardour/utils.h>
+
+
+struct tm;
+
+namespace ARDOUR {
+
+class AudioEngine;
+class Send;
+class Session;
+class Playlist;
+class IO;
+
+class Diskstream : public Stateful, public sigc::trackable
+{      
+  public:
+       enum Flag {
+               Recordable = 0x1,
+               Hidden = 0x2,
+               Destructive = 0x4
+       };
+
+       string      name () const { return _name; }
+       virtual int set_name (string str);
+
+       ARDOUR::IO* io() const { return _io; }
+       void set_io (ARDOUR::IO& io);
+
+       virtual Diskstream& ref() { _refcnt++; return *this; }
+       void     unref() { if (_refcnt) _refcnt--; if (_refcnt == 0) delete this; }
+       uint32_t refcnt() const { return _refcnt; }
+
+       virtual float playback_buffer_load() const = 0;
+       virtual float capture_buffer_load() const = 0;
+
+       void set_flag (Flag f)   { _flags |= f; }
+       void unset_flag (Flag f) { _flags &= ~f; }
+
+       AlignStyle alignment_style() const { return _alignment_style; }
+       void       set_align_style (AlignStyle);
+       void       set_persistent_align_style (AlignStyle a) { _persistent_alignment_style = a; }
+       
+       jack_nframes_t roll_delay() const { return _roll_delay; }
+       void           set_roll_delay (jack_nframes_t);
+
+       bool         record_enabled() const { return g_atomic_int_get (&_record_enabled); }
+       virtual void set_record_enabled (bool yn) = 0;
+
+       bool destructive() const { return _flags & Destructive; }
+       virtual void set_destructive (bool yn);
+
+       const PBD::ID& id()          const { return _id; }
+       bool           hidden()      const { return _flags & Hidden; }
+       bool           recordable()  const { return _flags & Recordable; }
+       bool           reversed()    const { return _actual_speed < 0.0f; }
+       double         speed()       const { return _visible_speed; }
+       
+       virtual void punch_in()  {}
+       virtual void punch_out() {}
+
+       void set_speed (double);
+       void non_realtime_set_speed ();
+
+       Playlist* playlist () { return _playlist; }
+
+       virtual int use_playlist (Playlist *);
+       virtual int use_new_playlist () = 0;
+       virtual int use_copy_playlist () = 0;
+
+       jack_nframes_t current_capture_start() const { return capture_start_frame; }
+       jack_nframes_t current_capture_end()   const { return capture_start_frame + capture_captured; }
+       jack_nframes_t get_capture_start_frame (uint32_t n=0);
+       jack_nframes_t get_captured_frames (uint32_t n=0);
+       
+       uint32_t n_channels() { return _n_channels; }
+
+       static jack_nframes_t disk_io_frames()                      { return disk_io_chunk_frames; }
+       static void           set_disk_io_chunk_frames (uint32_t n) { disk_io_chunk_frames = n; }
+
+       /* Stateful */
+       virtual XMLNode& get_state(void) = 0;
+       virtual int      set_state(const XMLNode& node) = 0;
+       
+       // FIXME: makes sense for all diskstream types?
+       virtual void monitor_input (bool) {}
+
+       jack_nframes_t capture_offset() const { return _capture_offset; }
+       virtual void   set_capture_offset ();
+
+       bool slaved() const      { return _slaved; }
+       void set_slaved(bool yn) { _slaved = yn; }
+
+       int set_loop (Location *loc);
+
+       std::list<Region*>& last_capture_regions () { return _last_capture_regions; }
+
+       void handle_input_change (IOChange, void *src);
+
+       sigc::signal<void>            RecordEnableChanged;
+       sigc::signal<void>            SpeedChanged;
+       sigc::signal<void>            ReverseChanged;
+       sigc::signal<void>            PlaylistChanged;
+       sigc::signal<void>            AlignmentStyleChanged;
+       sigc::signal<void,Location *> LoopSet;
+
+       static sigc::signal<void>                DiskOverrun;
+       static sigc::signal<void>                DiskUnderrun;
+       static sigc::signal<void,Diskstream*>    DiskstreamCreated; // XXX use a ref with sigc2
+       static sigc::signal<void,list<Source*>*> DeleteSources;
+
+  protected:
+       friend class Session;
+
+       Diskstream (Session &, const string& name, Flag f = Recordable);
+       Diskstream (Session &, const XMLNode&);
+
+       /* the Session is the only point of access for these because they require
+        * that the Session is "inactive" while they are called.
+        */
+
+       virtual void set_pending_overwrite (bool) = 0;
+       virtual int  overwrite_existing_buffers () = 0;
+       virtual void set_block_size (jack_nframes_t) = 0;
+       virtual int  internal_playback_seek (jack_nframes_t distance) = 0;
+       virtual int  can_internal_playback_seek (jack_nframes_t distance) = 0;
+       virtual int  rename_write_sources () = 0;
+       virtual void reset_write_sources (bool, bool force = false) = 0;
+       virtual void non_realtime_input_change () = 0;
+
+       uint32_t read_data_count() const { return _read_data_count; }
+       uint32_t write_data_count() const { return _write_data_count; }
+
+  protected:
+       friend class Auditioner;
+       virtual int  seek (jack_nframes_t which_sample, bool complete_refill = false) = 0;
+
+  protected:
+       friend class Track;
+
+       virtual void prepare ();
+       virtual int  process (jack_nframes_t transport_frame, jack_nframes_t nframes, jack_nframes_t offset, bool can_record, bool rec_monitors_input) = 0;
+       virtual bool commit  (jack_nframes_t nframes) = 0;
+       virtual void recover (); /* called if commit will not be called, but process was */
+
+       //private:
+       
+       /** Use unref() to destroy a diskstream */
+       virtual ~Diskstream();
+
+       enum TransitionType {
+               CaptureStart = 0,
+               CaptureEnd
+       };
+       
+       struct CaptureTransition {
+               TransitionType   type;
+               jack_nframes_t   capture_val; ///< The start or end file frame position
+       };
+
+       /* The two central butler operations */
+       virtual int do_flush (Session::RunContext context, bool force = false) = 0;
+       virtual int do_refill () = 0;
+       
+       /** For non-butler contexts (allocates temporary working buffers) */
+       virtual int do_refill_with_alloc() = 0;
+
+       
+       /* XXX fix this redundancy ... */
+
+       virtual void playlist_changed (Change);
+       virtual void playlist_modified ();
+       virtual void playlist_deleted (Playlist*);
+
+       virtual void finish_capture (bool rec_monitors_input) = 0;
+       virtual void transport_stopped (struct tm&, time_t, bool abort) = 0;
+
+       struct CaptureInfo {
+           uint32_t start;
+           uint32_t frames;
+       };
+
+       virtual void init (Flag);
+
+       virtual int use_new_write_source (uint32_t n=0) = 0;
+
+       virtual int find_and_use_playlist (const string&) = 0;
+
+       virtual void allocate_temporary_buffers () = 0;
+
+       virtual bool realtime_set_speed (double, bool global_change);
+
+       std::list<Region*> _last_capture_regions;
+       virtual int use_pending_capture_data (XMLNode& node) = 0;
+
+       virtual void get_input_sources () = 0;
+       virtual void check_record_status (jack_nframes_t transport_frame, jack_nframes_t nframes, bool can_record) = 0;
+       virtual void set_align_style_from_io() {}
+       virtual void setup_destructive_playlist () = 0;
+       virtual void use_destructive_playlist () = 0;
+
+       static jack_nframes_t disk_io_chunk_frames;
+       vector<CaptureInfo*>  capture_info;
+       Glib::Mutex           capture_info_lock;
+
+       uint32_t i_am_the_modifier;
+
+       string            _name;
+       ARDOUR::Session&  _session;
+       ARDOUR::IO*       _io;
+       uint32_t          _n_channels;
+       PBD::ID           _id;
+       Playlist*         _playlist;
+
+       mutable gint             _record_enabled;
+       double                   _visible_speed;
+       double                   _actual_speed;
+       /* items needed for speed change logic */
+       bool                     _buffer_reallocation_required;
+       bool                     _seek_required;
+       
+       bool                      force_refill;
+       jack_nframes_t            capture_start_frame;
+       jack_nframes_t            capture_captured;
+       bool                      was_recording;
+       jack_nframes_t            adjust_capture_position;
+       jack_nframes_t           _capture_offset;
+       jack_nframes_t           _roll_delay;
+       jack_nframes_t            first_recordable_frame;
+       jack_nframes_t            last_recordable_frame;
+       int                       last_possibly_recording;
+       AlignStyle               _alignment_style;
+       bool                     _scrubbing;
+       bool                     _slaved;
+       bool                     _processed;
+       Location*                 loop_location;
+       jack_nframes_t            overwrite_frame;
+       off_t                     overwrite_offset;
+       bool                      pending_overwrite;
+       bool                      overwrite_queued;
+       IOChange                  input_change_pending;
+       jack_nframes_t            wrap_buffer_size;
+       jack_nframes_t            speed_buffer_size;
+
+       uint64_t                  last_phase;
+       uint64_t                  phi;
+       
+       jack_nframes_t            file_frame;           
+       jack_nframes_t            playback_sample;
+       jack_nframes_t            playback_distance;
+
+       uint32_t                 _read_data_count;
+       uint32_t                 _write_data_count;
+
+       bool                      in_set_state;
+       AlignStyle               _persistent_alignment_style;
+       bool                      first_input_change;
+
+       Glib::Mutex  state_lock;
+
+       jack_nframes_t scrub_start;
+       jack_nframes_t scrub_buffer_size;
+       jack_nframes_t scrub_offset;
+
+       uint32_t _refcnt;
+
+       sigc::connection ports_created_c;
+       sigc::connection plmod_connection;
+       sigc::connection plstate_connection;
+       sigc::connection plgone_connection;
+       
+       unsigned char _flags;
+};
+
+}; /* namespace ARDOUR */
+
+#endif /* __ardour_diskstream_h__ */
index 0356da8dc83944e67b8d70d5a898b06d888fcc15..35b20f655e7725514f3c3d0677917b5015344c71 100644 (file)
@@ -38,6 +38,7 @@
 #include <ardour/utils.h>
 #include <ardour/state_manager.h>
 #include <ardour/curve.h>
+#include <ardour/types.h>
 
 using std::string;
 using std::vector;
@@ -52,6 +53,11 @@ class Port;
 class Connection;
 class Panner;
 
+/** A collection of input and output ports with connections.
+ *
+ * An IO can contain ports of varying types, making routes/inserts/etc with
+ * varied combinations of types (eg MIDI and audio) possible.
+ */
 class IO : public Stateful, public ARDOUR::StateManager
 {
 
@@ -60,7 +66,8 @@ class IO : public Stateful, public ARDOUR::StateManager
 
        IO (Session&, string name, 
            int input_min = -1, int input_max = -1, 
-           int output_min = -1, int output_max = -1);
+           int output_min = -1, int output_max = -1,
+               DataType default_type = AUDIO);
 
        virtual ~IO();
 
@@ -74,25 +81,29 @@ class IO : public Stateful, public ARDOUR::StateManager
        void set_output_minimum (int n);
        void set_output_maximum (int n);
 
+       DataType default_type() const { return _default_type; }
+
        const string& name() const { return _name; }
        virtual int set_name (string str, void *src);
        
        virtual void silence  (jack_nframes_t, jack_nframes_t offset);
 
+       // These should be moved in to a separate object that manipulates an IO
+       
        void pan (vector<Sample*>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset, gain_t gain_coeff);
        void pan_automated (vector<Sample*>& bufs, uint32_t nbufs, jack_nframes_t start_frame, jack_nframes_t end_frame, 
                            jack_nframes_t nframes, jack_nframes_t offset);
        void collect_input  (vector<Sample*>&, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset);
-       void deliver_output (vector<Sample *>&, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset);
-       void deliver_output_no_pan (vector<Sample *>&, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset);
+       void deliver_output (vector<Sample*>&, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset);
+       void deliver_output_no_pan (vector<Sample*>&, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset);
        void just_meter_input (jack_nframes_t start_frame, jack_nframes_t end_frame, 
                               jack_nframes_t nframes, jack_nframes_t offset);
 
        virtual uint32_t n_process_buffers () { return 0; }
 
        virtual void   set_gain (gain_t g, void *src);
-       void   inc_gain (gain_t delta, void *src);
-       gain_t         gain () const                      { return _desired_gain; }
+       void           inc_gain (gain_t delta, void *src);
+       gain_t         gain () const { return _desired_gain; }
        virtual gain_t effective_gain () const;
 
        Panner& panner() { return *_panner; }
@@ -105,8 +116,8 @@ class IO : public Stateful, public ARDOUR::StateManager
        Connection *input_connection() const { return _input_connection; }
        Connection *output_connection() const { return _output_connection; }
 
-       int add_input_port (string source, void *src);
-       int add_output_port (string destination, void *src);
+       int add_input_port (string source, void *src, DataType type = NIL);
+       int add_output_port (string destination, void *src, DataType type = NIL);
 
        int remove_input_port (Port *, void *src);
        int remove_output_port (Port *, void *src);
@@ -273,6 +284,7 @@ public:
        PBD::ID             _id;
        bool                 no_panner_reset;
        XMLNode*             deferred_state;
+       DataType        _default_type;
 
        virtual void set_deferred_state() {}
 
index 9fb1950bfaef180d2425806379fd5f28b4172adc..9fb5b0eb2b5b2baf97a6bb054f51754027695aa9 100644 (file)
@@ -54,7 +54,6 @@ class Playlist : public Stateful, public StateManager {
        Playlist (const Playlist&, string name, bool hidden = false);
        Playlist (const Playlist&, jack_nframes_t start, jack_nframes_t cnt, string name, bool hidden = false);
 
-       virtual jack_nframes_t read (Sample *dst, Sample *mixdown, float *gain_buffer, char * workbuf, jack_nframes_t start, jack_nframes_t cnt, uint32_t chan_n=0) = 0;
        virtual void clear (bool with_delete = false, bool with_save = true);
        virtual void dump () const;
        virtual UndoAction get_memento() const = 0;
@@ -81,6 +80,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);
@@ -108,16 +109,15 @@ class Playlist : public Stateful, public StateManager {
        int set_state (const XMLNode&);
        XMLNode& get_template ();
 
-       sigc::signal<void,Region *> RegionAdded;
-       sigc::signal<void,Region *> RegionRemoved;
-
+       sigc::signal<void,Region *>       RegionAdded;
+       sigc::signal<void,Region *>       RegionRemoved;
        sigc::signal<void,Playlist*,bool> InUse;
-       sigc::signal<void>            Modified;
-       sigc::signal<void>            NameChanged;
-       sigc::signal<void>            LengthChanged;
-       sigc::signal<void>            LayeringChanged;
-       sigc::signal<void,Playlist *> GoingAway;
-       sigc::signal<void>            StatePushed;
+       sigc::signal<void>                Modified;
+       sigc::signal<void>                NameChanged;
+       sigc::signal<void>                LengthChanged;
+       sigc::signal<void>                LayeringChanged;
+       sigc::signal<void,Playlist *>     GoingAway;
+       sigc::signal<void>                StatePushed;
 
        static sigc::signal<void,Playlist*> PlaylistCreated;
 
index 93ed2777e40a28402100345330929ddb089b6cf5..86c99cb7e3e24533f326a1d1b2d2c5691c70a2f7 100644 (file)
@@ -33,24 +33,24 @@ class AudioEngine;
 class Port : public sigc::trackable {
    public:
        virtual ~Port() { 
-               free (port);
+               free (_port);
        }
 
        Sample *get_buffer (jack_nframes_t nframes) {
                if (_flags & JackPortIsOutput) {
                        return _buffer;
                } else {
-                       return (Sample *) jack_port_get_buffer (port, nframes);
+                       return (Sample *) jack_port_get_buffer (_port, nframes);
                }
        }
 
        void reset_buffer () {
                if (_flags & JackPortIsOutput) {
-                       _buffer = (Sample *) jack_port_get_buffer (port, 0);
+                       _buffer = (Sample *) jack_port_get_buffer (_port, 0);
                } else {
                        _buffer = 0; /* catch illegal attempts to use it */
                }
-               silent = false;
+               _silent = false;
        }
 
        std::string name() { 
@@ -58,7 +58,7 @@ class Port : public sigc::trackable {
        }
 
        std::string short_name() { 
-               return jack_port_short_name (port);
+               return jack_port_short_name (_port);
        }
        
        int set_name (std::string str);
@@ -68,7 +68,7 @@ class Port : public sigc::trackable {
        }
 
        bool is_mine (jack_client_t *client) { 
-               return jack_port_is_mine (client, port);
+               return jack_port_is_mine (client, _port);
        }
 
        const char* type() const {
@@ -76,21 +76,21 @@ class Port : public sigc::trackable {
        }
 
        int connected () const {
-               return jack_port_connected (port);
+               return jack_port_connected (_port);
        }
        
        bool connected_to (const std::string& portname) const {
-               return jack_port_connected_to (port, portname.c_str());
+               return jack_port_connected_to (_port, portname.c_str());
        }
 
        const char ** get_connections () const {
-               return jack_port_get_connections (port);
+               return jack_port_get_connections (_port);
        }
 
        void reset_overs () {
                _short_overs = 0;
                _long_overs = 0;
-               overlen = 0;
+               _overlen = 0;
        }
 
        void reset_peak_meter () {
@@ -103,18 +103,18 @@ class Port : public sigc::trackable {
        }
 
        void enable_metering() {
-               metering++;
+               _metering++;
        }
        
        void disable_metering () {
-               if (metering) { metering--; }
+               if (_metering) { _metering--; }
        }
 
-       float    peak_db() const { return _peak_db; }
+       float                       peak_db() const { return _peak_db; }
        jack_default_audio_sample_t peak()    const { return _peak; }
 
        uint32_t short_overs () const { return _short_overs; }
-       uint32_t long_overs () const { return _long_overs; }
+       uint32_t long_overs ()  const { return _long_overs; }
        
        static void set_short_over_length (jack_nframes_t);
        static void set_long_over_length (jack_nframes_t);
@@ -128,7 +128,7 @@ class Port : public sigc::trackable {
        }
        
        bool monitoring_input () const {
-               return jack_port_monitoring_input (port);
+               return jack_port_monitoring_input (_port);
        }
 
        bool can_monitor () const {
@@ -136,30 +136,29 @@ class Port : public sigc::trackable {
        }
        
        void ensure_monitor_input (bool yn) {
-               jack_port_request_monitor (port, yn);
+               jack_port_request_monitor (_port, yn);
        }
        
        void request_monitor_input (bool yn) {
-               jack_port_request_monitor (port, yn);
+               jack_port_request_monitor (_port, yn);
        }
 
        jack_nframes_t latency () const {
-               return jack_port_get_latency (port);
+               return jack_port_get_latency (_port);
        }
 
        void set_latency (jack_nframes_t nframes) {
-               jack_port_set_latency (port, nframes);
+               jack_port_set_latency (_port, nframes);
        }
 
        sigc::signal<void,bool> MonitorInputChanged;
        sigc::signal<void,bool> ClockSyncChanged;
 
-       bool is_silent() const { return silent; }
+       bool is_silent() const { return _silent; }
 
+       /** Assumes that the port is an audio output port */
        void silence (jack_nframes_t nframes, jack_nframes_t offset) {
-               /* assumes that the port is an output port */
-
-               if (!silent) {
+               if (!_silent) {
                        memset (_buffer + offset, 0, sizeof (Sample) * nframes);
                        if (offset == 0) {
                                /* XXX this isn't really true, but i am not sure
@@ -167,13 +166,13 @@ class Port : public sigc::trackable {
                                   want to set it true when the entire port
                                   buffer has been overrwritten.
                                */
-                               silent = true;
+                               _silent = true;
                        }
                }
        }
        
        void mark_silence (bool yn) {
-               silent = yn;
+               _silent = yn;
        }
 
   private:
@@ -184,7 +183,7 @@ class Port : public sigc::trackable {
        
        /* engine isn't supposed to below here */
 
-       Sample       *_buffer;
+       Sample *_buffer;
 
        /* cache these 3 from JACK so that we can
           access them for reconnecting.
@@ -194,18 +193,18 @@ class Port : public sigc::trackable {
        std::string   _type;
        std::string   _name;
 
-       bool           last_monitor : 1;
-       bool           silent : 1;
-       jack_port_t   *port;
-       jack_nframes_t      overlen;
-       jack_default_audio_sample_t      _peak;
-       float         _peak_db;
-       uint32_t _short_overs;
-       uint32_t _long_overs;
-       unsigned short  metering;
+       bool                         _last_monitor : 1;
+       bool                         _silent : 1;
+       jack_port_t                 *_port;
+       jack_nframes_t               _overlen;
+       jack_default_audio_sample_t  _peak;
+       float                        _peak_db;
+       uint32_t                     _short_overs;
+       uint32_t                     _long_overs;
+       unsigned short               _metering;
        
-       static jack_nframes_t long_over_length;
-       static jack_nframes_t short_over_length;
+       static jack_nframes_t        _long_over_length;
+       static jack_nframes_t        _short_over_length;
 };
  
 } // namespace ARDOUR
index baf93a8f77add925069aec61946cead330f874c4..3773a3b893fe21a52c03d2aa36a4cddebdb8dc7e 100644 (file)
@@ -24,7 +24,6 @@
 #include <pbd/undo.h>
 
 #include <ardour/ardour.h>
-#include <ardour/logcurve.h>
 #include <ardour/state_manager.h>
 
 class XMLNode;
@@ -36,22 +35,22 @@ class Source;
 
 enum RegionEditState {
        EditChangesNothing = 0,
-       EditChangesName = 1,
-       EditChangesID = 2
+       EditChangesName    = 1,
+       EditChangesID      = 2
 };
 
-struct RegionState : public StateManager::State {
-
-    RegionState (std::string why) : StateManager::State (why) {}
-    
-    jack_nframes_t      _start;
-    jack_nframes_t      _length;
-    jack_nframes_t      _position;
-    uint32_t        _flags;
-    jack_nframes_t      _sync_position;
-    layer_t            _layer;
-    string              _name;        
-    mutable RegionEditState _first_edit;
+struct RegionState : public StateManager::State
+{
+       RegionState (std::string why) : StateManager::State (why) {}
+
+       jack_nframes_t          _start;
+       jack_nframes_t          _length;
+       jack_nframes_t          _position;
+       uint32_t                _flags;
+       jack_nframes_t          _sync_position;
+       layer_t                 _layer;
+       string                  _name;        
+       mutable RegionEditState _first_edit;
 };
 
 class Region : public Stateful, public StateManager
@@ -95,7 +94,7 @@ class Region : public Stateful, public StateManager
        Region (const Region&, jack_nframes_t start, jack_nframes_t length, const string& name, layer_t = 0, Flag flags = DefaultFlags);
        Region (const Region&);
        Region (const XMLNode&);
-       ~Region();
+       virtual ~Region();
 
        const PBD::ID& id() const { return _id; }
 
@@ -105,9 +104,10 @@ class Region : public Stateful, public StateManager
        void set_name (string str);
 
        jack_nframes_t position () const { return _position; }
-       jack_nframes_t start () const { return _start; }
-       jack_nframes_t length() const { return _length; }
-       layer_t layer () const { return _layer; }
+       jack_nframes_t start ()    const { return _start; }
+       jack_nframes_t length()    const { return _length; }
+       layer_t        layer ()    const { return _layer; }
+       
        jack_nframes_t sync_offset(int& dir) const;
        jack_nframes_t sync_position() const;
 
@@ -118,14 +118,13 @@ class Region : public Stateful, public StateManager
        jack_nframes_t first_frame() const { return _position; }
        jack_nframes_t last_frame() const { return _position + _length - 1; }
 
-       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 locked() const { return _flags & Locked; }
-       bool automatic() const { return  _flags & Automatic; }
+       bool hidden()     const { return _flags & Hidden; }
+       bool muted()      const { return _flags & Muted; }
+       bool opaque ()    const { return _flags & Opaque; }
+       bool locked()     const { return _flags & Locked; }
+       bool automatic()  const { return _flags & Automatic; }
        bool whole_file() const { return _flags & WholeFile ; }
-       Flag flags() const { return _flags; }
+       Flag flags()      const { return _flags; }
 
        virtual bool should_save_state () const { return !(_flags & DoNotSaveState); };
 
@@ -139,12 +138,14 @@ 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);
        }
-
-       virtual jack_nframes_t read_at (Sample *buf, Sample *mixdown_buffer, 
-                                       float *gain_buffer, char * workbuf, jack_nframes_t position, jack_nframes_t cnt, 
-                                       uint32_t chan_n = 0,
-                                       jack_nframes_t read_frames = 0,
-                                       jack_nframes_t skip_frames = 0) const = 0;
+       
+       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 bool speed_mismatch (float) const = 0;
 
        /* EDITING OPERATIONS */
 
@@ -173,7 +174,6 @@ 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_locked (bool yn);
 
        virtual uint32_t read_data_count() const { return _read_data_count; }
@@ -189,9 +189,9 @@ class Region : public Stateful, public StateManager
 
        /* serialization */
        
+       XMLNode&         get_state ();
        virtual XMLNode& state (bool);
-       XMLNode& get_state ();
-       int      set_state (const XMLNode&);
+       virtual int      set_state (const XMLNode&);
 
        sigc::signal<void,Region*> GoingAway;
 
@@ -211,23 +211,6 @@ class Region : public Stateful, public StateManager
        void set_last_layer_op (uint64_t when);
 
   protected:
-
-       jack_nframes_t        _start;
-       jack_nframes_t        _length;
-       jack_nframes_t        _position;
-       Flag                  _flags;
-       jack_nframes_t        _sync_position;
-       layer_t               _layer;
-       string                _name;        
-       mutable RegionEditState _first_edit;
-       int                   _frozen;
-       Glib::Mutex              lock;
-       PBD::ID               _id;
-       ARDOUR::Playlist*     _playlist;
-       mutable uint32_t      _read_data_count; // modified in read()
-       Change                 pending_changed;
-       uint64_t              _last_layer_op; // timestamp
        XMLNode& get_short_state (); /* used only by Session */
 
        /* state management */
@@ -251,6 +234,23 @@ class Region : public Stateful, public StateManager
        virtual bool verify_length (jack_nframes_t) = 0;
        virtual void recompute_at_start () = 0;
        virtual void recompute_at_end () = 0;
+       
+       
+       jack_nframes_t          _start;
+       jack_nframes_t          _length;
+       jack_nframes_t          _position;
+       Flag                     _flags;
+       jack_nframes_t          _sync_position;
+       layer_t                 _layer;
+       string                  _name;        
+       mutable RegionEditState _first_edit;
+       int                     _frozen;
+       Glib::Mutex             lock;
+       PBD::ID                 _id;
+       ARDOUR::Playlist*       _playlist;
+       mutable uint32_t        _read_data_count; // modified in read()
+       Change                   pending_changed;
+       uint64_t                _last_layer_op; // timestamp
 };
 
 } /* namespace ARDOUR */
index b8a11301ca564b92ffc44746854c11475ed21173..ea4a2374d4dc0e875b4a61c276ca33be47531a3e 100644 (file)
@@ -40,6 +40,7 @@
 #include <ardour/io.h>
 #include <ardour/session.h>
 #include <ardour/redirect.h>
+#include <ardour/types.h>
 
 namespace ARDOUR {
 
@@ -68,7 +69,9 @@ class Route : public IO
        };
 
 
-       Route (Session&, std::string name, int input_min, int input_max, int output_min, int output_max, Flag flags = Flag(0));
+       Route (Session&, std::string name, int input_min, int input_max, int output_min, int output_max,
+              Flag flags = Flag(0), DataType default_type = AUDIO);
+       
        Route (Session&, const XMLNode&);
        virtual ~Route();
 
index 11253eda5bc1ebf4ed9ca5c3d39a993cd3f03fea..e9fad1aa2b66986fe8123bbf2f78a7d287ca6040 100644 (file)
@@ -35,6 +35,7 @@ using std::list;
 namespace ARDOUR {
 
 class Route;
+class Track;
 class AudioTrack;
 class Session;
 
@@ -90,7 +91,7 @@ class RouteGroup : public Stateful, public sigc::trackable {
 
     /* to use these, #include <ardour/route_group_specialized.h> */
 
-    template<class T> void apply (void (AudioTrack::*func)(T, void *), T val, void *src);
+    template<class T> void apply (void (Track::*func)(T, void *), T val, void *src);
 
     /* fills at_set with all members of the group that are AudioTracks */
 
index 0424002dcd5211c841ae7d836c3d480adba653ed..250d3744dfae6b327dec5706a357b383d3e1d1ce 100644 (file)
@@ -7,11 +7,11 @@
 namespace ARDOUR {
 
 template<class T> void 
-RouteGroup::apply (void (AudioTrack::*func)(T, void *), T val, void *src) 
+RouteGroup::apply (void (Track::*func)(T, void *), T val, void *src) 
 {
        for (list<Route *>::iterator i = routes.begin(); i != routes.end(); i++) {
-               AudioTrack *at;
-               if ((at = dynamic_cast<AudioTrack*>(*i)) != 0) {
+               Track *at;
+               if ((at = dynamic_cast<Track*>(*i)) != 0) {
                        (at->*func)(val, this);
                }
        }
index dbcd830a044add00e709dae1ab57cdc26ab4e700..8d10d9f5987f1966478085a69e233807da53219a 100644 (file)
@@ -66,6 +66,7 @@ namespace ARDOUR {
 class Port;
 class AudioEngine;
 class Slave;
+class Diskstream;      
 class AudioDiskstream; 
 class Route;
 class AuxInput;
@@ -157,17 +158,17 @@ class Session : public sigc::trackable, public Stateful
                    Clear
            };
 
-           Type                type;
-           Action              action;
-           jack_nframes_t      action_frame;
-           jack_nframes_t      target_frame;
-           float               speed;
+           Type           type;
+           Action         action;
+           jack_nframes_t action_frame;
+           jack_nframes_t target_frame;
+           float          speed;
 
            union {
-               void*                ptr;
-               bool                 yes_or_no;
-               Session::SlaveSource slave;
-               Route*               route;
+                       void*                ptr;
+                       bool                 yes_or_no;
+                       Session::SlaveSource slave;
+                       Route*               route;
            };
 
            list<AudioRange>     audio_range;
@@ -269,30 +270,18 @@ class Session : public sigc::trackable, public Stateful
        vector<Sample*>& get_silent_buffers (uint32_t howmany);
        vector<Sample*>& get_send_buffers () { return _send_buffers; }
 
-       AudioDiskstream    *diskstream_by_id (const PBD::ID& id);
-       AudioDiskstream    *diskstream_by_name (string name);
+       Diskstream* diskstream_by_id (const PBD::ID& id);
+       Diskstream* diskstream_by_name (string name);
 
        bool have_captured() const { return _have_captured; }
 
        void refill_all_diskstream_buffers ();
        uint32_t diskstream_buffer_size() const { return dstream_buffer_size; }
        
-       /* XXX fix required here when we get new diskstream types *, but
-          not sure of the direction to take this in until then.
-       */
-
-       uint32_t get_next_diskstream_id() const { return n_audio_diskstreams(); }
-       uint32_t n_audio_diskstreams() const;
+       uint32_t get_next_diskstream_id() const { return n_diskstreams(); }
+       uint32_t n_diskstreams() const;
        
-       typedef list<AudioDiskstream *> AudioDiskstreamList;
-
-       Session::AudioDiskstreamList audio_disk_streams() const {
-               Glib::RWLock::ReaderLock lm (diskstream_lock);
-               return audio_diskstreams; /* XXX yes, force a copy */
-       }
-
-       void foreach_audio_diskstream (void (AudioDiskstream::*func)(void));
-       template<class T> void foreach_audio_diskstream (T *obj, void (T::*func)(AudioDiskstream&));
+       typedef list<Diskstream *> DiskstreamList;
 
        typedef std::list<boost::shared_ptr<Route> > RouteList; 
 
@@ -356,7 +345,7 @@ class Session : public sigc::trackable, public Stateful
        sigc::signal<void> HaltOnXrun;
 
        sigc::signal<void,boost::shared_ptr<Route> > RouteAdded;
-       sigc::signal<void,AudioDiskstream*> AudioDiskstreamAdded;
+       sigc::signal<void,Diskstream*> DiskstreamAdded; // FIXME: make a shared_ptr
 
        void request_roll ();
        void request_bounded_roll (jack_nframes_t start, jack_nframes_t end);
@@ -368,15 +357,14 @@ class Session : public sigc::trackable, public Stateful
        void goto_start () { request_locate (start_location->start(), false); }
        void use_rf_shuttle_speed ();
        void request_transport_speed (float speed);
-       void request_overwrite_buffer (AudioDiskstream*);
-       void request_diskstream_speed (AudioDiskstream&, float speed);
+       void request_overwrite_buffer (Diskstream*);
+       void request_diskstream_speed (Diskstream&, float speed);
        void request_input_change_handling ();
 
        bool locate_pending() const { return static_cast<bool>(post_transport_work&PostTransportLocate); }
        bool transport_locked () const;
 
        int wipe ();
-       int wipe_diskstream (AudioDiskstream *);
 
        int remove_region_from_region_list (Region&);
 
@@ -553,9 +541,6 @@ class Session : public sigc::trackable, public Stateful
 
        void   resort_routes ();
        void   resort_routes_using (boost::shared_ptr<RouteList>);
-       void   resort_routes_proxy (void* src) {
-               resort_routes ();
-       }
 
        AudioEngine &engine() { return _engine; };
 
@@ -636,7 +621,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);
 
@@ -713,8 +698,6 @@ class Session : public sigc::trackable, public Stateful
        sigc::signal<void,Playlist*> PlaylistAdded;
        sigc::signal<void,Playlist*> PlaylistRemoved;
 
-       Playlist *get_playlist (string name);
-
        uint32_t n_playlists() const;
 
        template<class T> void foreach_playlist (T *obj, void (T::*func)(Playlist *));
@@ -739,7 +722,7 @@ class Session : public sigc::trackable, public Stateful
 
        boost::shared_ptr<Auditioner> the_auditioner() { return auditioner; }
        void audition_playlist ();
-       void audition_region (AudioRegion&);
+       void audition_region (Region&);
        void cancel_audition ();
        bool is_auditioning () const;
        
@@ -980,7 +963,7 @@ class Session : public sigc::trackable, public Stateful
        void set_frame_rate (jack_nframes_t nframes);
 
   protected:
-       friend class AudioDiskstream;
+       friend class Diskstream;
        void stop_butler ();
        void wait_till_butler_finished();
 
@@ -1442,12 +1425,12 @@ class Session : public sigc::trackable, public Stateful
        bool waiting_to_start;
 
        void set_auto_loop (bool yn);
-       void overwrite_some_buffers (AudioDiskstream*);
+       void overwrite_some_buffers (Diskstream*);
        void flush_all_redirects ();
        void locate (jack_nframes_t, bool with_roll, bool with_flush, bool with_loop=false);
        void start_locate (jack_nframes_t, bool with_roll, bool with_flush, bool with_loop=false);
        void force_locate (jack_nframes_t frame, bool with_roll = false);
-       void set_diskstream_speed (AudioDiskstream*, float speed);
+       void set_diskstream_speed (Diskstream*, float speed);
        void set_transport_speed (float speed, bool abort = false);
        void stop_transport (bool abort = false);
        void start_transport ();
@@ -1478,10 +1461,10 @@ class Session : public sigc::trackable, public Stateful
 
        /* disk-streams */
 
-       AudioDiskstreamList  audio_diskstreams; 
+       DiskstreamList  diskstreams; 
        mutable Glib::RWLock diskstream_lock;
        uint32_t dstream_buffer_size;
-       void add_diskstream (AudioDiskstream*);
+       void add_diskstream (Diskstream*);
        int  load_diskstreams (const XMLNode&);
 
        /* routes stuff */
@@ -1549,7 +1532,7 @@ class Session : public sigc::trackable, public Stateful
        Playlist *XMLPlaylistFactory (const XMLNode&);
 
        void playlist_length_changed (Playlist *);
-       void diskstream_playlist_changed (AudioDiskstream *);
+       void diskstream_playlist_changed (Diskstream *);
 
        /* NAMED SELECTIONS */
 
diff --git a/libs/ardour/ardour/session_diskstream.h b/libs/ardour/ardour/session_diskstream.h
deleted file mode 100644 (file)
index 33fc541..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
-    Copyright (C) 2002 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  __ardour_session_diskstream_h__
-#define __ardour_session_diskstream_h__
-
-#include <ardour/session.h>
-#include <ardour/audio_diskstream.h>
-
-namespace ARDOUR {
-
-template<class T> void 
-Session::foreach_audio_diskstream (T *obj, void (T::*func)(AudioDiskstream&)) 
-{
-       Glib::RWLock::ReaderLock lm (diskstream_lock);
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); i++) {
-               if (!(*i)->hidden()) {
-                       (obj->*func) (**i);
-               }
-       }
-}
-
-} /* namespace */
-
-#endif /* __ardour_session_diskstream_h__ */
diff --git a/libs/ardour/ardour/track.h b/libs/ardour/ardour/track.h
new file mode 100644 (file)
index 0000000..707ead1
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+    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_track_h__
+#define __ardour_track_h__
+
+#include <ardour/route.h>
+
+namespace ARDOUR {
+
+class Session;
+class Diskstream;
+class Playlist;
+class RouteGroup;
+
+class Track : public Route
+{
+  public:
+       Track (Session&, string name, Route::Flag f = Route::Flag (0), TrackMode m = Normal, DataType default_type = AUDIO);
+
+       virtual ~Track ();
+       
+       int set_name (string str, void *src);
+
+       virtual int roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, 
+               jack_nframes_t offset, int declick, bool can_record, bool rec_monitors_input) = 0;
+       
+       virtual int no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, 
+               jack_nframes_t offset, bool state_changing, bool can_record, bool rec_monitors_input) = 0;
+       
+       virtual int silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, 
+               jack_nframes_t offset, bool can_record, bool rec_monitors_input) = 0;
+
+       void toggle_monitor_input ();
+
+       bool can_record() const { return true; }
+
+       Diskstream& diskstream() const { return *_diskstream; }
+
+       virtual int use_diskstream (string name) = 0;
+       virtual int use_diskstream (const PBD::ID& id) = 0;
+
+       TrackMode mode() const { return _mode; }
+       void      set_mode (TrackMode m);
+
+       jack_nframes_t update_total_latency();
+       void           set_latency_delay (jack_nframes_t);
+
+       enum FreezeState {
+               NoFreeze,
+               Frozen,
+               UnFrozen
+       };
+
+       FreezeState freeze_state() const;
+       virtual void freeze (InterThreadInfo&) = 0;
+       virtual void unfreeze () = 0;
+
+       virtual void bounce (InterThreadInfo&) = 0;
+       virtual void bounce_range (jack_nframes_t start, jack_nframes_t end, InterThreadInfo&) = 0;
+
+       XMLNode&    get_state();
+       XMLNode&    get_template();
+       virtual int set_state(const XMLNode& node) = 0;
+
+       PBD::Controllable& rec_enable_control() { return _rec_enable_control; }
+
+       bool record_enabled() const;
+       void set_record_enable (bool yn, void *src);
+       
+       void set_meter_point (MeterPoint, void* src);
+       
+       sigc::signal<void> ModeChanged;
+       sigc::signal<void> DiskstreamChanged;
+       sigc::signal<void> FreezeChange;
+
+  protected:
+       Track (Session& sess, const XMLNode& node, DataType default_type = AUDIO);
+
+       virtual XMLNode& state (bool full) = 0;
+
+       virtual void passthru_silence (jack_nframes_t start_frame, jack_nframes_t end_frame, 
+               jack_nframes_t nframes, jack_nframes_t offset, int declick, bool meter) = 0;
+
+       virtual uint32_t n_process_buffers () = 0;
+       
+       Diskstream *_diskstream;
+       MeterPoint  _saved_meter_point;
+       TrackMode   _mode;
+
+       //private: (FIXME)
+       struct FreezeRecordInsertInfo {
+           FreezeRecordInsertInfo(XMLNode& st, boost::shared_ptr<Insert> ins) 
+                   : state (st), insert (ins) {}
+
+           XMLNode                   state;
+           boost::shared_ptr<Insert> insert;
+           PBD::ID                   id;
+           UndoAction                memento;
+       };
+
+       struct FreezeRecord {
+           FreezeRecord()
+               : playlist(0)
+               , have_mementos(false)
+           {}
+
+           ~FreezeRecord();
+
+           Playlist*                       playlist;
+           vector<FreezeRecordInsertInfo*> insert_info;
+           bool                            have_mementos;
+           FreezeState                     state;
+       };
+
+       struct RecEnableControllable : public PBD::Controllable {
+           RecEnableControllable (Track&);
+           
+           void set_value (float);
+           float get_value (void) const;
+
+           Track& track;
+       };
+
+       //virtual void diskstream_record_enable_changed (void *src) = 0;
+       //virtual void diskstream_input_channel_changed (void *src) = 0;
+
+       //virtual void input_change_handler (void *src) = 0;
+
+       virtual void set_state_part_two () = 0;
+
+       FreezeRecord          _freeze_record;
+       XMLNode*              pending_state;
+       sigc::connection      recenable_connection;
+       sigc::connection      ic_connection;
+       RecEnableControllable _rec_enable_control;
+       bool                  _destructive;
+};
+
+}; /* namespace ARDOUR*/
+
+#endif /* __ardour_track_h__ */
index fa1d121d02aa5db06c8b2127b6df54d71aab19cf..e073b413bb5f6f064c249348921e56dee4c45e9f 100644 (file)
@@ -243,6 +243,12 @@ namespace ARDOUR {
            PeakDatum min;
            PeakDatum max;
        };
+
+       enum DataType {
+               NIL = 0,
+               AUDIO,
+               MIDI
+       };
 }
 
 std::istream& operator>>(std::istream& o, ARDOUR::SampleFormat& sf);
index e7cb48452b0f090f09db8cce587813555ecca9ce..7f0cb55821f591f2fa05f37e5e10b2058a1c9ccc 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2000-2003 Paul Davis 
+    Copyright (C) 2000-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: diskstream.cc 567 2006-06-07 14:54:12Z trutkin $
 */
 
 #include <fstream>
@@ -23,6 +21,7 @@
 #include <unistd.h>
 #include <cmath>
 #include <cerrno>
+#include <cassert>
 #include <string>
 #include <climits>
 #include <fcntl.h>
@@ -55,32 +54,30 @@ using namespace std;
 using namespace ARDOUR;
 using namespace PBD;
 
-jack_nframes_t AudioDiskstream::disk_io_chunk_frames;
-
-sigc::signal<void,AudioDiskstream*>    AudioDiskstream::AudioDiskstreamCreated;
-sigc::signal<void,list<AudioFileSource*>*> AudioDiskstream::DeleteSources;
-sigc::signal<void>                AudioDiskstream::DiskOverrun;
-sigc::signal<void>                AudioDiskstream::DiskUnderrun;
+size_t  AudioDiskstream::_working_buffers_size = 0;
+Sample* AudioDiskstream::_mixdown_buffer       = 0;
+gain_t* AudioDiskstream::_gain_buffer          = 0;
+char*   AudioDiskstream::_conversion_buffer    = 0;
 
-AudioDiskstream::AudioDiskstream (Session &sess, const string &name, Flag flag)
-       : _name (name),
-         _session (sess)
+AudioDiskstream::AudioDiskstream (Session &sess, const string &name, Diskstream::Flag flag)
+       : Diskstream(sess, name, flag)
+       , deprecated_io_node(NULL)
 {
        /* prevent any write sources from being created */
 
        in_set_state = true;
 
-       init (flag);
+       init(flag);
        use_new_playlist ();
 
        in_set_state = false;
 
-       AudioDiskstreamCreated (this); /* EMIT SIGNAL */
+       DiskstreamCreated (this); /* EMIT SIGNAL */
 }
        
 AudioDiskstream::AudioDiskstream (Session& sess, const XMLNode& node)
-       : _session (sess)
-       
+       : Diskstream(sess, node)
+       , deprecated_io_node(NULL)
 {
        in_set_state = true;
        init (Recordable);
@@ -96,7 +93,7 @@ AudioDiskstream::AudioDiskstream (Session& sess, const XMLNode& node)
                use_destructive_playlist ();
        }
 
-       AudioDiskstreamCreated (this); /* EMIT SIGNAL */
+       DiskstreamCreated (this); /* EMIT SIGNAL */
 }
 
 void
@@ -129,43 +126,9 @@ AudioDiskstream::init_channel (ChannelInfo &chan)
 
 
 void
-AudioDiskstream::init (Flag f)
+AudioDiskstream::init (Diskstream::Flag f)
 {
-       _refcnt = 0;
-       _flags = f;
-       _io = 0;
-       _alignment_style = ExistingMaterial;
-       _persistent_alignment_style = ExistingMaterial;
-       first_input_change = true;
-       _playlist = 0;
-       i_am_the_modifier = 0;
-       g_atomic_int_set (&_record_enabled, 0);
-       was_recording = false;
-       capture_start_frame = 0;
-       capture_captured = 0;
-       _visible_speed = 1.0f;
-       _actual_speed = 1.0f;
-       _buffer_reallocation_required = false;
-       _seek_required = false;
-       first_recordable_frame = max_frames;
-       last_recordable_frame = max_frames;
-       _roll_delay = 0;
-       _capture_offset = 0;
-       _processed = false;
-       _slaved = false;
-       adjust_capture_position = 0;
-       last_possibly_recording = 0;
-       loop_location = 0;
-       wrap_buffer_size = 0;
-       speed_buffer_size = 0;
-       last_phase = 0;
-       phi = (uint64_t) (0x1000000);
-       file_frame = 0;
-       playback_sample = 0;
-       playback_distance = 0;
-       _read_data_count = 0;
-       _write_data_count = 0;
-       deprecated_io_node = 0;
+       Diskstream::init(f);
 
        /* there are no channels at this point, so these
           two calls just get speed_buffer_size and wrap_buffer
@@ -175,13 +138,8 @@ AudioDiskstream::init (Flag f)
        set_block_size (_session.get_block_size());
        allocate_temporary_buffers ();
 
-       pending_overwrite = false;
-       overwrite_frame = 0;
-       overwrite_queued = false;
-       input_change_pending = NoChange;
-
        add_channel ();
-       _n_channels = 1;
+       assert(_n_channels == 1);
 }
 
 void
@@ -215,26 +173,33 @@ AudioDiskstream::~AudioDiskstream ()
 {
        Glib::Mutex::Lock lm (state_lock);
 
-       if (_playlist) {
-               _playlist->unref ();
-       }
-
-       for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
+       for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan)
                destroy_channel((*chan));
-       }
        
        channels.clear();
 }
 
 void
-AudioDiskstream::handle_input_change (IOChange change, void *src)
+AudioDiskstream::allocate_working_buffers()
 {
-       Glib::Mutex::Lock lm (state_lock);
+       assert(disk_io_frames() > 0);
 
-       if (!(input_change_pending & change)) {
-               input_change_pending = IOChange (input_change_pending|change);
-               _session.request_input_change_handling ();
-       }
+       _working_buffers_size = disk_io_frames();
+       _mixdown_buffer       = new Sample[_working_buffers_size];
+       _gain_buffer          = new gain_t[_working_buffers_size];
+       _conversion_buffer    = new char[_working_buffers_size * 4];
+}
+
+void
+AudioDiskstream::free_working_buffers()
+{
+       delete _mixdown_buffer;
+       delete _gain_buffer;
+       delete _conversion_buffer;
+       _working_buffers_size = 0;
+       _mixdown_buffer       = 0;
+       _gain_buffer          = 0;
+       _conversion_buffer    = 0;
 }
 
 void
@@ -332,9 +297,9 @@ AudioDiskstream::find_and_use_playlist (const string& name)
        Playlist* pl;
        AudioPlaylist* playlist;
                
-       if ((pl = _session.get_playlist (name)) == 0) {
-               error << string_compose(_("AudioDiskstream: Session doesn't know about a Playlist called \"%1\""), name) << endmsg;
-               return -1;
+       if ((pl = _session.playlist_by_name (name)) == 0) {
+               playlist = new AudioPlaylist(_session, name);
+               pl = playlist;
        }
 
        if ((playlist = dynamic_cast<AudioPlaylist*> (pl)) == 0) {
@@ -346,57 +311,15 @@ AudioDiskstream::find_and_use_playlist (const string& name)
 }
 
 int
-AudioDiskstream::use_playlist (AudioPlaylist* playlist)
+AudioDiskstream::use_playlist (Playlist* playlist)
 {
-       {
-               Glib::Mutex::Lock lm (state_lock);
+       assert(dynamic_cast<AudioPlaylist*>(playlist));
 
-               if (playlist == _playlist) {
-                       return 0;
-               }
-
-               plstate_connection.disconnect();
-               plmod_connection.disconnect ();
-               plgone_connection.disconnect ();
-
-               if (_playlist) {
-                       _playlist->unref();
-               }
-                       
-               _playlist = playlist;
-               _playlist->ref();
-
-               if (!in_set_state && recordable()) {
-                       reset_write_sources (false);
-               }
-               
-               plstate_connection = _playlist->StateChanged.connect (mem_fun (*this, &AudioDiskstream::playlist_changed));
-               plmod_connection = _playlist->Modified.connect (mem_fun (*this, &AudioDiskstream::playlist_modified));
-               plgone_connection = _playlist->GoingAway.connect (mem_fun (*this, &AudioDiskstream::playlist_deleted));
-       }
-
-       if (!overwrite_queued) {
-               _session.request_overwrite_buffer (this);
-               overwrite_queued = true;
-       }
-       
-       PlaylistChanged (); /* EMIT SIGNAL */
-       _session.set_dirty ();
+       Diskstream::use_playlist(playlist);
 
        return 0;
 }
 
-void
-AudioDiskstream::playlist_deleted (Playlist* pl)
-{
-       /* this catches an ordering issue with session destruction. playlists 
-          are destroyed before diskstreams. we have to invalidate any handles
-          we have to the playlist.
-       */
-
-       _playlist = 0;
-}
-
 int
 AudioDiskstream::use_new_playlist ()
 {
@@ -424,6 +347,8 @@ AudioDiskstream::use_new_playlist ()
 int
 AudioDiskstream::use_copy_playlist ()
 {
+       assert(audio_playlist());
+
        if (destructive()) {
                return 0;
        }
@@ -438,7 +363,7 @@ AudioDiskstream::use_copy_playlist ()
 
        newname = Playlist::bump_name (_playlist->name(), _session);
        
-       if ((playlist  = new AudioPlaylist (*_playlist, newname)) != 0) {
+       if ((playlist  = new AudioPlaylist (*audio_playlist(), newname)) != 0) {
                playlist->set_orig_diskstream_id (id());
                return use_playlist (playlist);
        } else { 
@@ -488,110 +413,13 @@ AudioDiskstream::use_destructive_playlist ()
 
        for (n = 0, chan = channels.begin(); chan != channels.end(); ++chan, ++n) {
                (*chan).write_source = dynamic_cast<AudioFileSource*>(&region->source (n));
+               assert((*chan).write_source);
                (*chan).write_source->set_allow_remove_if_empty (false);
        }
 
        /* the source list will never be reset for a destructive track */
 }
 
-void
-AudioDiskstream::set_io (IO& io)
-{
-       _io = &io;
-       set_align_style_from_io ();
-}
-
-int
-AudioDiskstream::set_name (string str, void *src)
-{
-       if (str != _name) {
-               _playlist->set_name (str);
-               _name = str;
-               
-               if (!in_set_state && recordable()) {
-                       /* rename existing capture files so that they have the correct name */
-                       return rename_write_sources ();
-               } else {
-                       return -1;
-               }
-       }
-
-       return 0;
-}
-
-void
-AudioDiskstream::set_speed (double sp)
-{
-       _session.request_diskstream_speed (*this, sp);
-
-       /* to force a rebuffering at the right place */
-       playlist_modified();
-}
-
-bool
-AudioDiskstream::realtime_set_speed (double sp, bool global)
-{
-       bool changed = false;
-       double new_speed = sp * _session.transport_speed();
-       
-       if (_visible_speed != sp) {
-               _visible_speed = sp;
-               changed = true;
-       }
-       
-       if (new_speed != _actual_speed) {
-               
-               jack_nframes_t required_wrap_size = (jack_nframes_t) floor (_session.get_block_size() * 
-                                                                           fabs (new_speed)) + 1;
-               
-               if (required_wrap_size > wrap_buffer_size) {
-                       _buffer_reallocation_required = true;
-               }
-               
-               _actual_speed = new_speed;
-               phi = (uint64_t) (0x1000000 * fabs(_actual_speed));
-       }
-
-       if (changed) {
-               if (!global) {
-                       _seek_required = true;
-               }
-                speed_changed (); /* EMIT SIGNAL */
-       }
-
-       return _buffer_reallocation_required || _seek_required;
-}
-
-void
-AudioDiskstream::non_realtime_set_speed ()
-{
-       if (_buffer_reallocation_required)
-       {
-               Glib::Mutex::Lock lm (state_lock);
-               allocate_temporary_buffers ();
-
-               _buffer_reallocation_required = false;
-       }
-
-       if (_seek_required) {
-               if (speed() != 1.0f || speed() != -1.0f) {
-                       seek ((jack_nframes_t) (_session.transport_frame() * (double) speed()), true);
-               }
-               else {
-                       seek (_session.transport_frame(), true);
-               }
-
-               _seek_required = false;
-       }
-}
-
-void
-AudioDiskstream::prepare ()
-{
-       _processed = false;
-       playback_distance = 0;
-}
-
 void
 AudioDiskstream::check_record_status (jack_nframes_t transport_frame, jack_nframes_t nframes, bool can_record)
 {
@@ -755,7 +583,7 @@ AudioDiskstream::process (jack_nframes_t transport_frame, jack_nframes_t nframes
           returns a non-zero value, in which case, ::commit should not be called.
        */
 
-        // If we can't take the state lock return.
+       // If we can't take the state lock return.
        if (!state_lock.trylock()) {
                return 1;
        }
@@ -1011,13 +839,6 @@ AudioDiskstream::process (jack_nframes_t transport_frame, jack_nframes_t nframes
        return ret;
 }
 
-void
-AudioDiskstream::recover ()
-{
-       state_lock.unlock();
-       _processed = false;
-}
-
 bool
 AudioDiskstream::commit (jack_nframes_t nframes)
 {
@@ -1156,16 +977,16 @@ AudioDiskstream::seek (jack_nframes_t frame, bool complete_refill)
        /* can't rec-enable in destructive mode if transport is before start */
 
        if (destructive() && record_enabled() && frame < _session.current_start_frame()) {
-               disengage_record_enable (this);
+               disengage_record_enable ();
        }
 
        playback_sample = frame;
        file_frame = frame;
 
        if (complete_refill) {
-               while ((ret = do_refill (0, 0, 0)) > 0);
+               while ((ret = do_refill_with_alloc ()) > 0) ;
        } else {
-               ret = do_refill (0, 0, 0);
+               ret = do_refill_with_alloc ();
        }
 
        return ret;
@@ -1257,7 +1078,7 @@ AudioDiskstream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer,
 
                this_read = min(cnt,this_read);
 
-               if (_playlist->read (buf+offset, mixdown_buffer, gain_buffer, workbuf, start, this_read, channel) != this_read) {
+               if (audio_playlist()->read (buf+offset, mixdown_buffer, gain_buffer, workbuf, start, this_read, channel) != this_read) {
                        error << string_compose(_("AudioDiskstream %1: cannot read %2 from playlist at frame %3"), _id, this_read, 
                                         start) << endmsg;
                        return -1;
@@ -1291,14 +1112,27 @@ AudioDiskstream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer,
 }
 
 int
-AudioDiskstream::do_refill (Sample* mixdown_buffer, float* gain_buffer, char * workbuf)
+AudioDiskstream::do_refill_with_alloc()
+{
+       Sample* mix_buf  = new Sample[disk_io_chunk_frames];
+       float*  gain_buf = new float[disk_io_chunk_frames];
+       char*   work_buf = new char[disk_io_chunk_frames * 4];
+
+       int ret = _do_refill(mix_buf, gain_buf, work_buf);
+       
+       delete [] mix_buf;
+       delete [] gain_buf;
+       delete [] work_buf;
+
+       return ret;
+}
+
+int
+AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer, char * workbuf)
 {
        int32_t ret = 0;
        jack_nframes_t to_read;
        RingBufferNPT<Sample>::rw_vector vector;
-       bool free_mixdown;
-       bool free_gain;
-       bool free_workbuf;
        bool reversed = (_visible_speed * _session.transport_speed()) < 0.0f;
        jack_nframes_t total_space;
        jack_nframes_t zero_fill;
@@ -1306,6 +1140,10 @@ AudioDiskstream::do_refill (Sample* mixdown_buffer, float* gain_buffer, char * w
        ChannelList::iterator i;
        jack_nframes_t ts;
 
+       assert(mixdown_buffer);
+       assert(gain_buffer);
+       assert(workbuf);
+
        channels.front().playback_buf->get_write_vector (&vector);
        
        if ((total_space = vector.len[0] + vector.len[1]) == 0) {
@@ -1412,33 +1250,6 @@ AudioDiskstream::do_refill (Sample* mixdown_buffer, float* gain_buffer, char * w
                        zero_fill = 0;
                }
        }
-
-       /* Please note: the code to allocate buffers isn't run
-          during normal butler thread operation. Its there
-          for other times when we need to call do_refill()
-          from somewhere other than the butler thread.
-       */
-
-       if (mixdown_buffer == 0) {
-               mixdown_buffer = new Sample[disk_io_chunk_frames];
-               free_mixdown = true;
-       } else {
-               free_mixdown = false;
-       }
-
-       if (gain_buffer == 0) {
-               gain_buffer = new float[disk_io_chunk_frames];
-               free_gain = true;
-       } else {
-               free_gain = false;
-       }
-
-       if (workbuf == 0) {
-               workbuf = new char[disk_io_chunk_frames * 4];
-               free_workbuf = true;
-       } else {
-               free_workbuf = false;
-       }
        
        jack_nframes_t file_frame_tmp = 0;
 
@@ -1507,37 +1318,30 @@ AudioDiskstream::do_refill (Sample* mixdown_buffer, float* gain_buffer, char * w
        file_frame = file_frame_tmp;
 
   out:
-       if (free_mixdown) {
-               delete [] mixdown_buffer;
-       }
-       if (free_gain) {
-               delete [] gain_buffer;
-       }
-       if (free_workbuf) {
-               delete [] workbuf;
-       }
 
        return ret;
 }      
 
+/** Flush pending data to disk.
+ *
+ * Important note: this function will write *AT MOST* disk_io_chunk_frames
+ * of data to disk. it will never write more than that.  If it writes that
+ * much and there is more than that waiting to be written, it will return 1,
+ * otherwise 0 on success or -1 on failure.
+ * 
+ * If there is less than disk_io_chunk_frames to be written, no data will be
+ * written at all unless @a force_flush is true.
+ */
 int
-AudioDiskstream::do_flush (char * workbuf, bool force_flush)
+AudioDiskstream::do_flush (Session::RunContext context, bool force_flush)
 {
+       char* workbuf = _session.conversion_buffer(context);
+
        uint32_t to_write;
        int32_t ret = 0;
        RingBufferNPT<Sample>::rw_vector vector;
        RingBufferNPT<CaptureTransition>::rw_vector transvec;
        jack_nframes_t total;
-       
-       /* important note: this function will write *AT MOST* 
-          disk_io_chunk_frames of data to disk. it will never 
-          write more than that. if its writes that much and there 
-          is more than that waiting to be written, it will return 1,
-          otherwise 0 on success or -1 on failure.
-
-          if there is less than disk_io_chunk_frames to be written, 
-          no data will be written at all unless `force_flush' is true.  
-       */
 
        _write_data_count = 0;
 
@@ -1552,7 +1356,6 @@ AudioDiskstream::do_flush (char * workbuf, bool force_flush)
                        goto out;
                }
 
-               
                /* if there are 2+ chunks of disk i/o possible for
                   this track, let the caller know so that it can arrange
                   for us to be called again, ASAP.
@@ -1656,21 +1459,6 @@ AudioDiskstream::do_flush (char * workbuf, bool force_flush)
        return ret;
 }
 
-void
-AudioDiskstream::playlist_changed (Change ignored)
-{
-       playlist_modified ();
-}
-
-void
-AudioDiskstream::playlist_modified ()
-{
-       if (!i_am_the_modifier && !overwrite_queued) {
-               _session.request_overwrite_buffer (this);
-               overwrite_queued = true;
-       } 
-}
-
 void
 AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_capture)
 {
@@ -1684,7 +1472,6 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca
        ChannelList::iterator chan;
        vector<CaptureInfo*>::iterator ci;
        uint32_t n = 0; 
-       list<AudioFileSource*>* deletion_list;
        bool mark_write_completed = false;
 
        finish_capture (true);
@@ -1694,7 +1481,7 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca
        */
 
        while (more_work && !err) {
-               switch (do_flush ( _session.conversion_buffer(Session::TransportContext), true)) {
+               switch (do_flush (Session::TransportContext, true)) {
                case 0:
                        more_work = false;
                        break;
@@ -1717,7 +1504,7 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca
                
                ChannelList::iterator chan;
                
-               deletion_list = new list<AudioFileSource*>;
+               list<Source*>* deletion_list = new list<Source*>;
 
                for ( chan = channels.begin(); chan != channels.end(); ++chan) {
 
@@ -1904,7 +1691,7 @@ AudioDiskstream::finish_capture (bool rec_monitors_input)
 }
 
 void
-AudioDiskstream::set_record_enabled (bool yn, void* src)
+AudioDiskstream::set_record_enabled (bool yn)
 {
        if (!recordable() || !_session.record_enabling_legal()) {
                return;
@@ -1931,17 +1718,17 @@ AudioDiskstream::set_record_enabled (bool yn, void* src)
 
        if (record_enabled() != yn) {
                if (yn) {
-                       engage_record_enable (src);
+                       engage_record_enable ();
                } else {
-                       disengage_record_enable (src);
+                       disengage_record_enable ();
                }
        }
 }
 
 void
-AudioDiskstream::engage_record_enable (void* src)
+AudioDiskstream::engage_record_enable ()
 {
-        bool rolling = _session.transport_speed() != 0.0f;
+    bool rolling = _session.transport_speed() != 0.0f;
 
        g_atomic_int_set (&_record_enabled, 1);
        capturing_sources.clear ();
@@ -1958,11 +1745,11 @@ AudioDiskstream::engage_record_enable (void* src)
                }
        }
 
-       record_enable_changed (src); /* EMIT SIGNAL */
+       RecordEnableChanged (); /* EMIT SIGNAL */
 }
 
 void
-AudioDiskstream::disengage_record_enable (void* src)
+AudioDiskstream::disengage_record_enable ()
 {
        g_atomic_int_set (&_record_enabled, 0);
        if (Config->get_use_hardware_monitoring()) {
@@ -1973,7 +1760,7 @@ AudioDiskstream::disengage_record_enable (void* src)
                }
        }
        capturing_sources.clear ();
-       record_enable_changed (src); /* EMIT SIGNAL */
+       RecordEnableChanged (); /* EMIT SIGNAL */
 }
                
 
@@ -1981,7 +1768,7 @@ XMLNode&
 AudioDiskstream::get_state ()
 {
        XMLNode* node = new XMLNode ("AudioDiskstream");
-       char buf[64];
+       char buf[64] = "";
        LocaleGuard lg (X_("POSIX"));
 
        snprintf (buf, sizeof(buf), "0x%x", _flags);
@@ -2080,8 +1867,7 @@ AudioDiskstream::set_state (const XMLNode& node)
        }
        
        // create necessary extra channels
-       // we are always constructed with one
-       // and we always need one
+       // we are always constructed with one and we always need one
 
        if (nchans > _n_channels) {
 
@@ -2311,23 +2097,6 @@ AudioDiskstream::monitor_input (bool yn)
        }
 }
 
-void
-AudioDiskstream::set_capture_offset ()
-{
-       if (_io == 0) {
-               /* can't capture, so forget it */
-               return;
-       }
-
-       _capture_offset = _io->input_latency();
-}
-
-void
-AudioDiskstream::set_persistent_align_style (AlignStyle a)
-{
-       _persistent_alignment_style = a;
-}
-
 void
 AudioDiskstream::set_align_style_from_io ()
 {
@@ -2353,20 +2122,6 @@ AudioDiskstream::set_align_style_from_io ()
        }
 }
 
-void
-AudioDiskstream::set_align_style (AlignStyle a)
-{
-       if (record_enabled() && _session.actively_recording()) {
-               return;
-       }
-
-
-       if (a != _alignment_style) {
-               _alignment_style = a;
-               AlignmentStyleChanged ();
-       }
-}
-
 int
 AudioDiskstream::add_channel ()
 {
@@ -2417,58 +2172,6 @@ AudioDiskstream::capture_buffer_load () const
                        (double) channels.front().capture_buf->bufsize());
 }
 
-int
-AudioDiskstream::set_loop (Location *location)
-{
-       if (location) {
-               if (location->start() >= location->end()) {
-                       error << string_compose(_("Location \"%1\" not valid for track loop (start >= end)"), location->name()) << endl;
-                       return -1;
-               }
-       }
-
-       loop_location = location;
-
-        LoopSet (location); /* EMIT SIGNAL */
-       return 0;
-}
-
-jack_nframes_t
-AudioDiskstream::get_capture_start_frame (uint32_t n)
-{
-       Glib::Mutex::Lock lm (capture_info_lock);
-
-       if (capture_info.size() > n) {
-               return capture_info[n]->start;
-       }
-       else {
-               return capture_start_frame;
-       }
-}
-
-jack_nframes_t
-AudioDiskstream::get_captured_frames (uint32_t n)
-{
-       Glib::Mutex::Lock lm (capture_info_lock);
-
-       if (capture_info.size() > n) {
-               return capture_info[n]->frames;
-       }
-       else {
-               return capture_captured;
-       }
-}
-
-void
-AudioDiskstream::punch_in ()
-{
-}
-
-void
-AudioDiskstream::punch_out ()
-{
-}
-
 int
 AudioDiskstream::use_pending_capture_data (XMLNode& node)
 {
@@ -2564,22 +2267,3 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node)
 
        return 0;
 }
-
-void
-AudioDiskstream::set_roll_delay (jack_nframes_t nframes)
-{
-       _roll_delay = nframes;
-}
-
-void
-AudioDiskstream::set_destructive (bool yn)
-{
-       if (yn != destructive()) {
-               reset_write_sources (true, true);
-               if (yn) {
-                       _flags |= Destructive;
-               } else {
-                       _flags &= ~Destructive;
-               }
-       }
-}
index 85c11647f45e34ceb97953738beeae68a0943b36..93d380679d9e396ef43e961bdf7a099c9a6b1785 100644 (file)
@@ -243,16 +243,18 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, ch
 
        for (vector<uint32_t>::iterator l = relevant_layers.begin(); l != relevant_layers.end(); ++l) {
 
+               // FIXME: Should be vector<AudioRegion*>
                vector<Region*>& r (relevant_regions[*l]);
                vector<Crossfade*>& x (relevant_xfades[*l]);
 
                for (vector<Region*>::iterator i = r.begin(); i != r.end(); ++i) {
-                       (*i)->read_at (buf, mixdown_buffer, gain_buffer, workbuf, start, cnt, chan_n, read_frames, skip_frames);
-                       _read_data_count += (*i)->read_data_count();
+                       AudioRegion* const ar = dynamic_cast<AudioRegion*>(*i);
+                       assert(ar);
+                       ar->read_at (buf, mixdown_buffer, gain_buffer, workbuf, start, cnt, chan_n, read_frames, skip_frames);
+                       _read_data_count += ar->read_data_count();
                }
                
                for (vector<Crossfade*>::iterator i = x.begin(); i != x.end(); ++i) {
-                       
                        (*i)->read_at (buf, mixdown_buffer, gain_buffer, workbuf, start, cnt, chan_n);
 
                        /* don't JACK up _read_data_count, since its the same data as we just
@@ -880,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)
 {
index f425f0172e5e071bc5c2623c1bfa7ded045f3049..78af23e3df8bf7cdea43b2f2ad91dc5fbe8b02ae 100644 (file)
@@ -41,9 +41,7 @@ using namespace ARDOUR;
 using namespace PBD;
 
 AudioTrack::AudioTrack (Session& sess, string name, Route::Flag flag, TrackMode mode)
-       : Route (sess, name, 1, -1, -1, -1, flag),
-         diskstream (0),
-         _rec_enable_control (*this)
+       : Track (sess, name, flag, mode)
 {
        AudioDiskstream::Flag dflags = AudioDiskstream::Flag (0);
 
@@ -59,45 +57,34 @@ AudioTrack::AudioTrack (Session& sess, string name, Route::Flag flag, TrackMode
 
        AudioDiskstream* ds = new AudioDiskstream (_session, name, dflags);
        
-       _declickable = true;
-       _freeze_record.state = NoFreeze;
-       _saved_meter_point = _meter_point;
-       _mode = mode;
-
        set_diskstream (*ds, this);
 }
 
 AudioTrack::AudioTrack (Session& sess, const XMLNode& node)
-       : Route (sess, "to be renamed", 0, 0, -1, -1),
-         diskstream (0),
-         _rec_enable_control (*this)
+       : Track (sess, node)
 {
-       _freeze_record.state = NoFreeze;
        set_state (node);
-       _declickable = true;
-       _saved_meter_point = _meter_point;
 }
 
 AudioTrack::~AudioTrack ()
 {
-       if (diskstream) {
-               diskstream->unref();
-       }
 }
 
 int
 AudioTrack::deprecated_use_diskstream_connections ()
 {
-       if (diskstream->deprecated_io_node == 0) {
+       AudioDiskstream& diskstream = audio_diskstream();
+
+       if (diskstream.deprecated_io_node == 0) {
                return 0;
        }
 
        const XMLProperty* prop;
-       XMLNode& node (*diskstream->deprecated_io_node);
+       XMLNode& node (*diskstream.deprecated_io_node);
 
        /* don't do this more than once. */
 
-       diskstream->deprecated_io_node = 0;
+       diskstream.deprecated_io_node = 0;
 
        set_input_minimum (-1);
        set_input_maximum (-1);
@@ -140,15 +127,15 @@ AudioTrack::deprecated_use_diskstream_connections ()
 int
 AudioTrack::set_diskstream (AudioDiskstream& ds, void *src)
 {
-       if (diskstream) {
-               diskstream->unref();
+       if (_diskstream) {
+               _diskstream->unref();
        }
 
-       diskstream = &ds.ref();
-       diskstream->set_io (*this);
-       diskstream->set_destructive (_mode == Destructive);
+       _diskstream = &ds.ref();
+       _diskstream->set_io (*this);
+       _diskstream->set_destructive (_mode == Destructive);
 
-       if (diskstream->deprecated_io_node) {
+       if (audio_diskstream().deprecated_io_node) {
 
                if (!connecting_legal) {
                        ConnectingLegal.connect (mem_fun (*this, &AudioTrack::deprecated_use_diskstream_connections));
@@ -157,13 +144,13 @@ AudioTrack::set_diskstream (AudioDiskstream& ds, void *src)
                }
        }
 
-       diskstream->set_record_enabled (false, this);
-       diskstream->monitor_input (false);
+       _diskstream->set_record_enabled (false);
+       _diskstream->monitor_input (false);
 
        ic_connection.disconnect();
-       ic_connection = input_changed.connect (mem_fun (*diskstream, &AudioDiskstream::handle_input_change));
+       ic_connection = input_changed.connect (mem_fun (*_diskstream, &Diskstream::handle_input_change));
 
-       diskstream_changed (src); /* EMIT SIGNAL */
+       DiskstreamChanged (); /* EMIT SIGNAL */
 
        return 0;
 }      
@@ -173,8 +160,8 @@ AudioTrack::use_diskstream (string name)
 {
        AudioDiskstream *dstream;
 
-       if ((dstream = _session.diskstream_by_name (name)) == 0) {
-         error << string_compose(_("AudioTrack: diskstream \"%1\" not known by session"), name) << endmsg;
+       if ((dstream = dynamic_cast<AudioDiskstream*>(_session.diskstream_by_name (name))) == 0) {
+         error << string_compose(_("AudioTrack: audio diskstream \"%1\" not known by session"), name) << endmsg;
                return -1;
        }
        
@@ -186,53 +173,18 @@ AudioTrack::use_diskstream (const PBD::ID& id)
 {
        AudioDiskstream *dstream;
 
-       if ((dstream = _session.diskstream_by_id (id)) == 0) {
-               error << string_compose(_("AudioTrack: diskstream \"%1\" not known by session"), id) << endmsg;
+       if ((dstream = dynamic_cast<AudioDiskstream*>(_session.diskstream_by_id (id))) == 0) {
+               error << string_compose(_("AudioTrack: audio diskstream \"%1\" not known by session"), id) << endmsg;
                return -1;
        }
        
        return set_diskstream (*dstream, this);
 }
 
-bool
-AudioTrack::record_enabled () const
-{
-       return diskstream->record_enabled ();
-}
-
-void
-AudioTrack::set_record_enable (bool yn, void *src)
-{
-       if (_freeze_record.state == Frozen) {
-               return;
-       }
-
-       if (_mix_group && src != _mix_group && _mix_group->is_active()) {
-               _mix_group->apply (&AudioTrack::set_record_enable, yn, _mix_group);
-               return;
-       }
-
-       /* keep track of the meter point as it was before we rec-enabled */
-
-       if (!diskstream->record_enabled()) {
-               _saved_meter_point = _meter_point;
-       }
-       
-       diskstream->set_record_enabled (yn, src);
-
-       if (diskstream->record_enabled()) {
-               set_meter_point (MeterInput, this);
-       } else {
-               set_meter_point (_saved_meter_point, this);
-       }
-
-       _rec_enable_control.Changed ();
-}
-
-void
-AudioTrack::set_meter_point (MeterPoint p, void *src)
+AudioDiskstream&
+AudioTrack::audio_diskstream() const
 {
-       Route::set_meter_point (p, src);
+       return *dynamic_cast<AudioDiskstream*>(_diskstream);
 }
 
 int
@@ -306,18 +258,6 @@ AudioTrack::set_state (const XMLNode& node)
        return 0;
 }
 
-XMLNode&
-AudioTrack::get_template ()
-{
-       return state (false);
-}
-
-XMLNode&
-AudioTrack::get_state ()
-{
-       return state (true);
-}
-
 XMLNode& 
 AudioTrack::state(bool full_state)
 {
@@ -348,7 +288,7 @@ AudioTrack::state(bool full_state)
        /* Alignment: act as a proxy for the diskstream */
        
        XMLNode* align_node = new XMLNode (X_("alignment"));
-       switch (diskstream->alignment_style()) {
+       switch (_diskstream->alignment_style()) {
        case ExistingMaterial:
                snprintf (buf, sizeof (buf), X_("existing"));
                break;
@@ -379,7 +319,7 @@ AudioTrack::state(bool full_state)
           diskstream.
        */
 
-       diskstream->id().print (buf);
+       _diskstream->id().print (buf);
        root.add_property ("diskstream-id", buf);
 
        return root;
@@ -451,9 +391,9 @@ AudioTrack::set_state_part_two ()
 
                if ((prop = fnode->property (X_("style"))) != 0) {
                        if (prop->value() == "existing") {
-                               diskstream->set_persistent_align_style (ExistingMaterial);
+                               _diskstream->set_persistent_align_style (ExistingMaterial);
                        } else if (prop->value() == "capture") {
-                               diskstream->set_persistent_align_style (CaptureTime);
+                               _diskstream->set_persistent_align_style (CaptureTime);
                        }
                }
        }
@@ -463,7 +403,7 @@ AudioTrack::set_state_part_two ()
 uint32_t
 AudioTrack::n_process_buffers ()
 {
-       return max ((uint32_t) diskstream->n_channels(), redirect_max_outs);
+       return max ((uint32_t) _diskstream->n_channels(), redirect_max_outs);
 }
 
 void
@@ -494,7 +434,7 @@ AudioTrack::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nf
                return 0;
        }
 
-       diskstream->check_record_status (start_frame, nframes, can_record);
+       audio_diskstream().check_record_status (start_frame, nframes, can_record);
 
        bool send_silence;
        
@@ -513,7 +453,7 @@ AudioTrack::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nf
                                send_silence = true;
                        }
                } else {
-                       if (diskstream->record_enabled()) {
+                       if (_diskstream->record_enabled()) {
                                if (Config->get_use_sw_monitoring()) {
                                        send_silence = false;
                                } else {
@@ -561,7 +501,8 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
        Sample* b;
        Sample* tmpb;
        jack_nframes_t transport_frame;
-
+       AudioDiskstream& diskstream = audio_diskstream();
+       
        {
                Glib::RWLock::ReaderLock lm (redirect_lock, Glib::TRY_LOCK);
                if (lm.locked()) {
@@ -587,13 +528,13 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
                   playback distance to zero, thus causing diskstream::commit
                   to do nothing.
                */
-               return diskstream->process (transport_frame, 0, 0, can_record, rec_monitors_input);
+               return diskstream.process (transport_frame, 0, 0, can_record, rec_monitors_input);
        } 
 
        _silent = false;
        apply_gain_automation = false;
 
-       if ((dret = diskstream->process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) {
+       if ((dret = diskstream.process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) {
                
                silence (nframes, offset);
 
@@ -606,7 +547,7 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
                just_meter_input (start_frame, end_frame, nframes, offset);
        }
 
-       if (diskstream->record_enabled() && !can_record && !_session.get_auto_input()) {
+       if (diskstream.record_enabled() && !can_record && !_session.get_auto_input()) {
 
                /* not actually recording, but we want to hear the input material anyway,
                   at least potentially (depending on monitoring options)
@@ -614,7 +555,7 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
 
                passthru (start_frame, end_frame, nframes, offset, 0, true);
 
-       } else if ((b = diskstream->playback_buffer(0)) != 0) {
+       } else if ((b = diskstream.playback_buffer(0)) != 0) {
 
                /*
                  XXX is it true that the earlier test on n_outputs()
@@ -636,8 +577,8 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
 
                for (i = 0, n = 1; i < limit; ++i, ++n) {
                        memcpy (bufs[i], b, sizeof (Sample) * nframes); 
-                       if (n < diskstream->n_channels()) {
-                               tmpb = diskstream->playback_buffer(n);
+                       if (n < diskstream.n_channels()) {
+                               tmpb = diskstream.playback_buffer(n);
                                if (tmpb!=0) {
                                        b = tmpb;
                                }
@@ -646,7 +587,7 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
 
                /* don't waste time with automation if we're recording or we've just stopped (yes it can happen) */
 
-               if (!diskstream->record_enabled() && _session.transport_rolling()) {
+               if (!diskstream.record_enabled() && _session.transport_rolling()) {
                        Glib::Mutex::Lock am (automation_lock, Glib::TRY_LOCK);
                        
                        if (am.locked() && gain_automation_playback()) {
@@ -682,37 +623,7 @@ AudioTrack::silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jac
 
        silence (nframes, offset);
 
-       return diskstream->process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input);
-}
-
-void
-AudioTrack::toggle_monitor_input ()
-{
-       for (vector<Port*>::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
-               (*i)->request_monitor_input(!(*i)->monitoring_input());
-       }
-}
-
-int
-AudioTrack::set_name (string str, void *src)
-{
-       int ret;
-
-       if (record_enabled() && _session.actively_recording()) {
-               /* this messes things up if done while recording */
-               return -1;
-       }
-
-       if (diskstream->set_name (str, src)) {
-               return -1;
-       }
-
-       /* save state so that the statefile fully reflects any filename changes */
-
-       if ((ret = IO::set_name (str, src)) == 0) {
-               _session.save_state ("");
-       }
-       return ret;
+       return audio_diskstream().process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input);
 }
 
 int
@@ -726,10 +637,15 @@ AudioTrack::export_stuff (vector<Sample*>& buffers, char * workbuf, uint32_t nbu
        gain_t this_gain = _gain;
        vector<Sample*>::iterator bi;
        Sample * b;
+       AudioDiskstream& diskstream = audio_diskstream();
        
        Glib::RWLock::ReaderLock rlock (redirect_lock);
-               
-       if (diskstream->playlist()->read (buffers[0], mix_buffer, gain_buffer, workbuf, start, nframes) != nframes) {
+
+       // FIXME
+       AudioPlaylist* const apl = dynamic_cast<AudioPlaylist*>(diskstream.playlist());
+       assert(apl);
+
+       if (apl->read (buffers[0], mix_buffer, gain_buffer, workbuf, start, nframes) != nframes) {
                return -1;
        }
 
@@ -738,8 +654,8 @@ AudioTrack::export_stuff (vector<Sample*>& buffers, char * workbuf, uint32_t nbu
        b = buffers[0];
        ++bi;
        for (; bi != buffers.end(); ++bi, ++n) {
-               if (n < diskstream->n_channels()) {
-                       if (diskstream->playlist()->read ((*bi), mix_buffer, gain_buffer, workbuf, start, nframes, n) != nframes) {
+               if (n < diskstream.n_channels()) {
+                       if (apl->read ((*bi), mix_buffer, gain_buffer, workbuf, start, nframes, n) != nframes) {
                                return -1;
                        }
                        b = (*bi);
@@ -811,29 +727,6 @@ AudioTrack::export_stuff (vector<Sample*>& buffers, char * workbuf, uint32_t nbu
        return 0;
 }
 
-void
-AudioTrack::set_latency_delay (jack_nframes_t longest_session_latency)
-{
-       Route::set_latency_delay (longest_session_latency);
-       diskstream->set_roll_delay (_roll_delay);
-}
-
-jack_nframes_t
-AudioTrack::update_total_latency ()
-{
-       _own_latency = 0;
-
-       for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
-               if ((*i)->active ()) {
-                       _own_latency += (*i)->latency ();
-               }
-       }
-
-       set_port_latency (_own_latency);
-
-       return _own_latency;
-}
-
 void
 AudioTrack::bounce (InterThreadInfo& itt)
 {
@@ -858,8 +751,9 @@ AudioTrack::freeze (InterThreadInfo& itt)
        string dir;
        AudioRegion* region;
        string region_name;
+       AudioDiskstream& diskstream = audio_diskstream();
        
-       if ((_freeze_record.playlist = diskstream->playlist()) == 0) {
+       if ((_freeze_record.playlist = dynamic_cast<AudioPlaylist*>(diskstream.playlist())) == 0) {
                return;
        }
 
@@ -881,7 +775,7 @@ AudioTrack::freeze (InterThreadInfo& itt)
        } 
 
        if (n == (UINT_MAX-1)) {
-         error << string_compose (X_("There Are too many frozen versions of playlist \"%1\""
+         error << string_compose (X_("There are too many frozen versions of playlist \"%1\""
                            " to create another one"), _freeze_record.playlist->name())
               << endmsg;
                return;
@@ -927,13 +821,13 @@ AudioTrack::freeze (InterThreadInfo& itt)
                                  (AudioRegion::Flag) (AudioRegion::WholeFile|AudioRegion::DefaultFlags),
                                  false);
 
-       new_playlist->set_orig_diskstream_id (diskstream->id());
+       new_playlist->set_orig_diskstream_id (diskstream.id());
        new_playlist->add_region (*region, 0);
        new_playlist->set_frozen (true);
        region->set_locked (true);
 
-       diskstream->use_playlist (dynamic_cast<AudioPlaylist*>(new_playlist));
-       diskstream->set_record_enabled (false, this);
+       diskstream.use_playlist (dynamic_cast<AudioPlaylist*>(new_playlist));
+       diskstream.set_record_enabled (false);
 
        _freeze_record.state = Frozen;
        FreezeChange(); /* EMIT SIGNAL */
@@ -943,7 +837,7 @@ void
 AudioTrack::unfreeze ()
 {
        if (_freeze_record.playlist) {
-               diskstream->use_playlist (_freeze_record.playlist);
+               audio_diskstream().use_playlist (_freeze_record.playlist);
 
                if (_freeze_record.have_mementos) {
 
@@ -971,46 +865,3 @@ AudioTrack::unfreeze ()
        FreezeChange (); /* EMIT SIGNAL */
 }
 
-AudioTrack::FreezeRecord::~FreezeRecord ()
-{
-       for (vector<FreezeRecordInsertInfo*>::iterator i = insert_info.begin(); i != insert_info.end(); ++i) {
-               delete *i;
-       }
-}
-
-AudioTrack::FreezeState
-AudioTrack::freeze_state() const
-{
-       return _freeze_record.state;
-}
-
-AudioTrack::RecEnableControllable::RecEnableControllable (AudioTrack& s)
-       : track (s)
-{
-}
-
-void
-AudioTrack::RecEnableControllable::set_value (float val)
-{
-       bool bval = ((val >= 0.5f) ? true: false);
-       track.set_record_enable (bval, this);
-}
-
-float
-AudioTrack::RecEnableControllable::get_value (void) const
-{
-       if (track.record_enabled()) { return 1.0f; }
-       return 0.0f;
-}
-
-void
-AudioTrack::set_mode (TrackMode m)
-{
-       if (diskstream) {
-               if (_mode != m) {
-                       _mode = m;
-                       diskstream->set_destructive (m == Destructive);
-                       ModeChanged();
-               }
-       }
-}
index 5a5e20053187db19c0d33ddb07cc12765f72ad3a..5618c7ef5f20819ec7c4cae23702d8272de24272 100644 (file)
@@ -26,6 +26,7 @@
 #include <pbd/pthread_utils.h>
 
 #include <ardour/audioengine.h>
+#include <ardour/buffer.h>
 #include <ardour/port.h>
 #include <ardour/session.h>
 #include <ardour/cycle_timer.h>
@@ -42,8 +43,8 @@ using namespace std;
 using namespace ARDOUR;
 using namespace PBD;
 
-jack_nframes_t Port::short_over_length = 2;
-jack_nframes_t Port::long_over_length = 10;
+jack_nframes_t Port::_short_over_length = 2;
+jack_nframes_t Port::_long_over_length = 10;
 
 AudioEngine::AudioEngine (string client_name) 
 {
@@ -274,8 +275,8 @@ AudioEngine::process_callback (jack_nframes_t nframes)
                        Port *port = (*i);
                        bool x;
                        
-                       if (port->last_monitor != (x = port->monitoring_input ())) {
-                               port->last_monitor = x;
+                       if (port->_last_monitor != (x = port->monitoring_input ())) {
+                               port->_last_monitor = x;
                                /* XXX I think this is dangerous, due to 
                                   a likely mutex in the signal handlers ...
                                */
@@ -388,18 +389,19 @@ AudioEngine::remove_session ()
 }
 
 Port *
-AudioEngine::register_audio_input_port (const string& portname)
+AudioEngine::register_input_port (DataType type, const string& portname)
 {
        if (!_running) {
                if (!_has_run) {
-                       fatal << _("register audio input port called before engine was started") << endmsg;
+                       fatal << _("register input port called before engine was started") << endmsg;
                        /*NOTREACHED*/
                } else {
                        return 0;
                }
        }
 
-       jack_port_t *p = jack_port_register (_jack, portname.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
+       jack_port_t *p = jack_port_register (_jack, portname.c_str(),
+               Buffer::type_to_jack_type(type), JackPortIsInput, 0);
 
        if (p) {
 
@@ -419,11 +421,11 @@ AudioEngine::register_audio_input_port (const string& portname)
 }
 
 Port *
-AudioEngine::register_audio_output_port (const string& portname)
+AudioEngine::register_output_port (DataType type, const string& portname)
 {
        if (!_running) {
                if (!_has_run) {
-                       fatal << _("register audio output port called before engine was started") << endmsg;
+                       fatal << _("register output port called before engine was started") << endmsg;
                        /*NOTREACHED*/
                } else {
                        return 0;
@@ -432,7 +434,8 @@ AudioEngine::register_audio_output_port (const string& portname)
 
        jack_port_t *p;
 
-       if ((p = jack_port_register (_jack, portname.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)) != 0) {
+       if ((p = jack_port_register (_jack, portname.c_str(),
+               Buffer::type_to_jack_type(type), JackPortIsOutput, 0)) != 0) {
                Port *newport = new Port (p);
                ports.insert (ports.begin(), newport);
                return newport;
@@ -446,6 +449,7 @@ AudioEngine::register_audio_output_port (const string& portname)
        return 0;
 }
 
+
 int          
 AudioEngine::unregister_port (Port *port)
 {
@@ -458,7 +462,7 @@ AudioEngine::unregister_port (Port *port)
 
        if (port) {
 
-               int ret = jack_port_unregister (_jack, port->port);
+               int ret = jack_port_unregister (_jack, port->_port);
                
                if (ret == 0) {
 
@@ -549,7 +553,7 @@ AudioEngine::disconnect (Port *port)
                }
        }
 
-       int ret = jack_port_disconnect (_jack, port->port);
+       int ret = jack_port_disconnect (_jack, port->_port);
 
        if (ret == 0) {
                remove_connections_for (port);
@@ -699,7 +703,6 @@ AudioEngine::n_physical_inputs () const
 }
 
 string
-
 AudioEngine::get_nth_physical (uint32_t n, int flag)
 {
        const char ** ports;
@@ -747,7 +750,7 @@ AudioEngine::get_port_total_latency (const Port& port)
                } 
        }
 
-       return jack_port_get_total_latency (_jack, port.port);
+       return jack_port_get_total_latency (_jack, port._port);
 }
 
 void
@@ -825,7 +828,7 @@ AudioEngine::remove_all_ports ()
 
        if (_jack) {
                for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) {
-                       jack_port_unregister (_jack, (*i)->port);
+                       jack_port_unregister (_jack, (*i)->_port);
                }
        }
 
@@ -948,7 +951,7 @@ AudioEngine::reconnect_to_jack ()
                
                short_name = long_name.substr (long_name.find_last_of (':') + 1);
 
-               if (((*i)->port = jack_port_register (_jack, short_name.c_str(), (*i)->type(), (*i)->flags(), 0)) == 0) {
+               if (((*i)->_port = jack_port_register (_jack, short_name.c_str(), (*i)->type(), (*i)->flags(), 0)) == 0) {
                        error << string_compose (_("could not reregister %1"), (*i)->name()) << endmsg;
                        break;
                } else {
@@ -963,7 +966,7 @@ AudioEngine::reconnect_to_jack ()
 
        if (i != ports.end()) {
                for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) {
-                       jack_port_unregister (_jack, (*i)->port);
+                       jack_port_unregister (_jack, (*i)->_port);
                }
                return -1;
        } 
index 4a8593cd631e35c6f21574a1996b820c45d68ab6..fff1c99598fa18c848646c04dadcf9e99b2253db 100644 (file)
@@ -48,13 +48,13 @@ using namespace ARDOUR;
 
 /* a Session will reset these to its chosen defaults by calling AudioRegion::set_default_fade() */
 
-Change AudioRegion::FadeInChanged = ARDOUR::new_change();
-Change AudioRegion::FadeOutChanged = ARDOUR::new_change();
-Change AudioRegion::FadeInActiveChanged = ARDOUR::new_change();
-Change AudioRegion::FadeOutActiveChanged = ARDOUR::new_change();
+Change AudioRegion::FadeInChanged         = ARDOUR::new_change();
+Change AudioRegion::FadeOutChanged        = ARDOUR::new_change();
+Change AudioRegion::FadeInActiveChanged   = ARDOUR::new_change();
+Change AudioRegion::FadeOutActiveChanged  = ARDOUR::new_change();
 Change AudioRegion::EnvelopeActiveChanged = ARDOUR::new_change();
 Change AudioRegion::ScaleAmplitudeChanged = ARDOUR::new_change();
-Change AudioRegion::EnvelopeChanged = ARDOUR::new_change();
+Change AudioRegion::EnvelopeChanged       = ARDOUR::new_change();
 
 AudioRegionState::AudioRegionState (string why)
        : RegionState (why),
@@ -633,12 +633,6 @@ AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buff
        return to_read;
 }
        
-XMLNode&
-AudioRegion::get_state ()
-{
-       return state (true);
-}
-
 XMLNode&
 AudioRegion::state (bool full)
 {
@@ -1139,24 +1133,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 +1157,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)
 {
index 2f0b943c0e68e95827a4476b64c35946d02205d4..81f64d26717364bb830c66317b87c002d006d354 100644 (file)
@@ -44,12 +44,12 @@ Auditioner::Auditioner (Session& s)
        defer_pan_reset ();
 
        if (left.length()) {
-               add_output_port (left, this);
+               add_output_port (left, this, AUDIO);
        }
 
        if (right.length()) {
-               disk_stream().add_channel();
-               add_output_port (right, this);
+               audio_diskstream().add_channel();
+               add_output_port (right, this, AUDIO);
        }
 
        allow_pan_reset ();
@@ -67,8 +67,12 @@ Auditioner::~Auditioner ()
 AudioPlaylist&
 Auditioner::prepare_playlist ()
 {
-       diskstream->playlist()->clear (false, false);
-       return *diskstream->playlist();
+       // FIXME auditioner is still audio-only
+       AudioPlaylist* const apl = dynamic_cast<AudioPlaylist*>(_diskstream->playlist());
+       assert(apl);
+
+       apl->clear (false, false);
+       return *apl;
 }
 
 void
@@ -82,13 +86,13 @@ Auditioner::audition_current_playlist ()
        }
 
        Glib::Mutex::Lock lm (lock);
-       diskstream->seek (0);
-       length = diskstream->playlist()->get_maximum_extent();
+       _diskstream->seek (0);
+       length = _diskstream->playlist()->get_maximum_extent();
        current_frame = 0;
 
        /* force a panner reset now that we have all channels */
 
-       _panner->reset (n_outputs(), diskstream->n_channels());
+       _panner->reset (n_outputs(), _diskstream->n_channels());
 
        g_atomic_int_set (&_active, 1);
 }
@@ -108,23 +112,23 @@ Auditioner::audition_region (AudioRegion& region)
        the_region = new AudioRegion (region);
        the_region->set_position (0, this);
 
-       diskstream->playlist()->clear (true, false);
-       diskstream->playlist()->add_region (*the_region, 0, 1, false);
+       _diskstream->playlist()->clear (true, false);
+       _diskstream->playlist()->add_region (*the_region, 0, 1, false);
 
-       while (diskstream->n_channels() < the_region->n_channels()) {
-               diskstream->add_channel ();
+       while (_diskstream->n_channels() < the_region->n_channels()) {
+               audio_diskstream().add_channel ();
        }
 
-       while (diskstream->n_channels() > the_region->n_channels()) {
-               diskstream->remove_channel ();
+       while (_diskstream->n_channels() > the_region->n_channels()) {
+               audio_diskstream().remove_channel ();
        }
 
        /* force a panner reset now that we have all channels */
 
-       _panner->reset (n_outputs(), diskstream->n_channels());
+       _panner->reset (n_outputs(), _diskstream->n_channels());
 
        length = the_region->length();
-       diskstream->seek (0);
+       _diskstream->seek (0);
        current_frame = 0;
        g_atomic_int_set (&_active, 1);
 }
@@ -143,14 +147,14 @@ Auditioner::play_audition (jack_nframes_t nframes)
 
        this_nframes = min (nframes, length - current_frame);
 
-       diskstream->prepare ();
+       _diskstream->prepare ();
 
        if ((ret = roll (this_nframes, current_frame, current_frame + nframes, 0, false, false, false)) != 0) {
                silence (nframes, 0);
                return ret;
        }
 
-       need_butler = diskstream->commit (this_nframes);
+       need_butler = _diskstream->commit (this_nframes);
        current_frame += this_nframes;
 
        if (current_frame >= length) {
diff --git a/libs/ardour/diskstream.cc b/libs/ardour/diskstream.cc
new file mode 100644 (file)
index 0000000..9312de5
--- /dev/null
@@ -0,0 +1,401 @@
+/*
+    Copyright (C) 2000-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.
+
+    $Id: diskstream.cc 567 2006-06-07 14:54:12Z trutkin $
+*/
+
+#include <fstream>
+#include <cstdio>
+#include <unistd.h>
+#include <cmath>
+#include <cerrno>
+#include <string>
+#include <climits>
+#include <fcntl.h>
+#include <cstdlib>
+#include <ctime>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#include <pbd/error.h>
+#include <pbd/basename.h>
+#include <glibmm/thread.h>
+#include <pbd/xml++.h>
+
+#include <ardour/ardour.h>
+#include <ardour/audioengine.h>
+#include <ardour/diskstream.h>
+#include <ardour/utils.h>
+#include <ardour/configuration.h>
+#include <ardour/audiofilesource.h>
+#include <ardour/destructive_filesource.h>
+#include <ardour/send.h>
+#include <ardour/playlist.h>
+#include <ardour/cycle_timer.h>
+#include <ardour/region.h>
+
+#include "i18n.h"
+#include <locale.h>
+
+using namespace std;
+using namespace ARDOUR;
+using namespace PBD;
+
+jack_nframes_t Diskstream::disk_io_chunk_frames = 0;
+
+sigc::signal<void,Diskstream*>    Diskstream::DiskstreamCreated;
+sigc::signal<void,list<Source*>*> Diskstream::DeleteSources;
+sigc::signal<void>                Diskstream::DiskOverrun;
+sigc::signal<void>                Diskstream::DiskUnderrun;
+
+Diskstream::Diskstream (Session &sess, const string &name, Flag flag)
+       : _name (name)
+       , _session (sess)
+       , _playlist(NULL)
+{
+       init (flag);
+}
+       
+Diskstream::Diskstream (Session& sess, const XMLNode& node)
+       : _session (sess)
+       , _playlist(NULL)
+{
+       init (Recordable);
+}
+
+void
+Diskstream::init (Flag f)
+{
+       _refcnt = 0;
+       _flags = f;
+       _io = 0;
+       _alignment_style = ExistingMaterial;
+       _persistent_alignment_style = ExistingMaterial;
+       first_input_change = true;
+       i_am_the_modifier = 0;
+       g_atomic_int_set (&_record_enabled, 0);
+       was_recording = false;
+       capture_start_frame = 0;
+       capture_captured = 0;
+       _visible_speed = 1.0f;
+       _actual_speed = 1.0f;
+       _buffer_reallocation_required = false;
+       _seek_required = false;
+       first_recordable_frame = max_frames;
+       last_recordable_frame = max_frames;
+       _roll_delay = 0;
+       _capture_offset = 0;
+       _processed = false;
+       _slaved = false;
+       adjust_capture_position = 0;
+       last_possibly_recording = 0;
+       loop_location = 0;
+       wrap_buffer_size = 0;
+       speed_buffer_size = 0;
+       last_phase = 0;
+       phi = (uint64_t) (0x1000000);
+       file_frame = 0;
+       playback_sample = 0;
+       playback_distance = 0;
+       _read_data_count = 0;
+       _write_data_count = 0;
+
+       pending_overwrite = false;
+       overwrite_frame = 0;
+       overwrite_queued = false;
+       input_change_pending = NoChange;
+
+       _n_channels = 0;
+}
+
+Diskstream::~Diskstream ()
+{
+       // Taken by derived class destrctors.. should assure locked here somehow?
+       //Glib::Mutex::Lock lm (state_lock);
+
+       if (_playlist)
+               _playlist->unref ();
+}
+
+void
+Diskstream::set_io (IO& io)
+{
+       _io = &io;
+       set_align_style_from_io ();
+}
+
+void
+Diskstream::handle_input_change (IOChange change, void *src)
+{
+       Glib::Mutex::Lock lm (state_lock);
+
+       if (!(input_change_pending & change)) {
+               input_change_pending = IOChange (input_change_pending|change);
+               _session.request_input_change_handling ();
+       }
+}
+
+void
+Diskstream::non_realtime_set_speed ()
+{
+       if (_buffer_reallocation_required)
+       {
+               Glib::Mutex::Lock lm (state_lock);
+               allocate_temporary_buffers ();
+
+               _buffer_reallocation_required = false;
+       }
+
+       if (_seek_required) {
+               if (speed() != 1.0f || speed() != -1.0f) {
+                       seek ((jack_nframes_t) (_session.transport_frame() * (double) speed()), true);
+               }
+               else {
+                       seek (_session.transport_frame(), true);
+               }
+
+               _seek_required = false;
+       }
+}
+
+bool
+Diskstream::realtime_set_speed (double sp, bool global)
+{
+       bool changed = false;
+       double new_speed = sp * _session.transport_speed();
+       
+       if (_visible_speed != sp) {
+               _visible_speed = sp;
+               changed = true;
+       }
+       
+       if (new_speed != _actual_speed) {
+               
+               jack_nframes_t required_wrap_size = (jack_nframes_t) floor (_session.get_block_size() * 
+                                                                           fabs (new_speed)) + 1;
+               
+               if (required_wrap_size > wrap_buffer_size) {
+                       _buffer_reallocation_required = true;
+               }
+               
+               _actual_speed = new_speed;
+               phi = (uint64_t) (0x1000000 * fabs(_actual_speed));
+       }
+
+       if (changed) {
+               if (!global) {
+                       _seek_required = true;
+               }
+               SpeedChanged (); /* EMIT SIGNAL */
+       }
+
+       return _buffer_reallocation_required || _seek_required;
+}
+
+void
+Diskstream::prepare ()
+{
+       _processed = false;
+       playback_distance = 0;
+}
+
+void
+Diskstream::recover ()
+{
+       state_lock.unlock();
+       _processed = false;
+}
+
+void
+Diskstream::set_capture_offset ()
+{
+       if (_io == 0) {
+               /* can't capture, so forget it */
+               return;
+       }
+
+       _capture_offset = _io->input_latency();
+}
+
+void
+Diskstream::set_align_style (AlignStyle a)
+{
+       if (record_enabled() && _session.actively_recording()) {
+               return;
+       }
+
+       if (a != _alignment_style) {
+               _alignment_style = a;
+               AlignmentStyleChanged ();
+       }
+}
+
+int
+Diskstream::set_loop (Location *location)
+{
+       if (location) {
+               if (location->start() >= location->end()) {
+                       error << string_compose(_("Location \"%1\" not valid for track loop (start >= end)"), location->name()) << endl;
+                       return -1;
+               }
+       }
+
+       loop_location = location;
+
+        LoopSet (location); /* EMIT SIGNAL */
+       return 0;
+}
+
+jack_nframes_t
+Diskstream::get_capture_start_frame (uint32_t n)
+{
+       Glib::Mutex::Lock lm (capture_info_lock);
+
+       if (capture_info.size() > n) {
+               return capture_info[n]->start;
+       }
+       else {
+               return capture_start_frame;
+       }
+}
+
+jack_nframes_t
+Diskstream::get_captured_frames (uint32_t n)
+{
+       Glib::Mutex::Lock lm (capture_info_lock);
+
+       if (capture_info.size() > n) {
+               return capture_info[n]->frames;
+       }
+       else {
+               return capture_captured;
+       }
+}
+
+void
+Diskstream::set_roll_delay (jack_nframes_t nframes)
+{
+       _roll_delay = nframes;
+}
+
+void
+Diskstream::set_speed (double sp)
+{
+       _session.request_diskstream_speed (*this, sp);
+
+       /* to force a rebuffering at the right place */
+       playlist_modified();
+}
+
+int
+Diskstream::use_playlist (Playlist* playlist)
+{
+       {
+               Glib::Mutex::Lock lm (state_lock);
+
+               if (playlist == _playlist) {
+                       return 0;
+               }
+
+               plstate_connection.disconnect();
+               plmod_connection.disconnect ();
+               plgone_connection.disconnect ();
+
+               if (_playlist) {
+                       _playlist->unref();
+               }
+                       
+               _playlist = playlist;
+               _playlist->ref();
+
+               if (!in_set_state && recordable()) {
+                       reset_write_sources (false);
+               }
+               
+               plstate_connection = _playlist->StateChanged.connect (mem_fun (*this, &Diskstream::playlist_changed));
+               plmod_connection = _playlist->Modified.connect (mem_fun (*this, &Diskstream::playlist_modified));
+               plgone_connection = _playlist->GoingAway.connect (mem_fun (*this, &Diskstream::playlist_deleted));
+       }
+
+       if (!overwrite_queued) {
+               _session.request_overwrite_buffer (this);
+               overwrite_queued = true;
+       }
+       
+       PlaylistChanged (); /* EMIT SIGNAL */
+       _session.set_dirty ();
+
+       return 0;
+}
+
+void
+Diskstream::playlist_changed (Change ignored)
+{
+       playlist_modified ();
+}
+
+void
+Diskstream::playlist_modified ()
+{
+       if (!i_am_the_modifier && !overwrite_queued) {
+               _session.request_overwrite_buffer (this);
+               overwrite_queued = true;
+       } 
+}
+
+void
+Diskstream::playlist_deleted (Playlist* pl)
+{
+       /* this catches an ordering issue with session destruction. playlists 
+          are destroyed before diskstreams. we have to invalidate any handles
+          we have to the playlist.
+       */
+
+       _playlist = 0;
+}
+
+int
+Diskstream::set_name (string str)
+{
+       if (str != _name) {
+               assert(playlist());
+               playlist()->set_name (str);
+               _name = str;
+               
+               if (!in_set_state && recordable()) {
+                       /* rename existing capture files so that they have the correct name */
+                       return rename_write_sources ();
+               } else {
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+void
+Diskstream::set_destructive (bool yn)
+{
+       if (yn != destructive()) {
+               reset_write_sources (true, true);
+               if (yn) {
+                       _flags |= Destructive;
+               } else {
+                       _flags &= ~Destructive;
+               }
+       }
+}
index bb2bb52e9e55998475ccce0b80e4eb5bffada6be..a70bf8abd32f28c7f33bd5568aa831c0999d9307 100644 (file)
@@ -97,11 +97,15 @@ static bool sort_ports_by_name (Port* a, Port* b)
 }
 
 
+/** @param default_type The type of port that will be created by ensure_io
+ * and friends if no type is explicitly requested (to avoid breakage).
+ */
 IO::IO (Session& s, string name,
-
-       int input_min, int input_max, int output_min, int output_max)
+       int input_min, int input_max, int output_min, int output_max,
+       DataType default_type)
        : _session (s),
          _name (name),
+         _default_type(default_type),
          _gain_control (*this),
          _gain_automation_curve (0.0, 2.0, 1.0),
          _input_minimum (input_min),
@@ -781,11 +785,20 @@ IO::remove_output_port (Port* port, void* src)
        return -1;
 }
 
+/** Add an output port.
+ *
+ * @param destination Name of input port to connect new port to.
+ * @param src Source for emitted ConfigurationChanged signal.
+ * @param type Data type of port.  Default value (NIL) will use this IO's default type.
+ */
 int
-IO::add_output_port (string destination, void* src)
+IO::add_output_port (string destination, void* src, DataType type)
 {
        Port* our_port;
-       char buf[64];
+       char name[64];
+
+       if (type == NIL)
+               type = _default_type;
 
        {
                Glib::Mutex::Lock em(_session.engine().process_lock());
@@ -799,14 +812,15 @@ IO::add_output_port (string destination, void* src)
                
                        /* Create a new output port */
                        
+                       // FIXME: naming scheme for differently typed ports?
                        if (_output_maximum == 1) {
-                               snprintf (buf, sizeof (buf), _("%s/out"), _name.c_str());
+                               snprintf (name, sizeof (name), _("%s/out"), _name.c_str());
                        } else {
-                               snprintf (buf, sizeof (buf), _("%s/out %u"), _name.c_str(), find_output_port_hole());
+                               snprintf (name, sizeof (name), _("%s/out %u"), _name.c_str(), find_output_port_hole());
                        }
                        
-                       if ((our_port = _session.engine().register_audio_output_port (buf)) == 0) {
-                               error << string_compose(_("IO: cannot register output port %1"), buf) << endmsg;
+                       if ((our_port = _session.engine().register_output_port (type, name)) == 0) {
+                               error << string_compose(_("IO: cannot register output port %1"), name) << endmsg;
                                return -1;
                        }
                        
@@ -882,11 +896,21 @@ IO::remove_input_port (Port* port, void* src)
        return -1;
 }
 
+
+/** Add an input port.
+ *
+ * @param type Data type of port.  The appropriate Jack port type, and @ref Port will be created.
+ * @param destination Name of input port to connect new port to.
+ * @param src Source for emitted ConfigurationChanged signal.
+ */
 int
-IO::add_input_port (string source, void* src)
+IO::add_input_port (string source, void* src, DataType type)
 {
        Port* our_port;
-       char buf[64];
+       char name[64];
+       
+       if (type == NIL)
+               type = _default_type;
 
        {
                Glib::Mutex::Lock em (_session.engine().process_lock());
@@ -900,14 +924,15 @@ IO::add_input_port (string source, void* src)
 
                        /* Create a new input port */
                        
+                       // FIXME: naming scheme for differently typed ports?
                        if (_input_maximum == 1) {
-                               snprintf (buf, sizeof (buf), _("%s/in"), _name.c_str());
+                               snprintf (name, sizeof (name), _("%s/in"), _name.c_str());
                        } else {
-                               snprintf (buf, sizeof (buf), _("%s/in %u"), _name.c_str(), find_input_port_hole());
+                               snprintf (name, sizeof (name), _("%s/in %u"), _name.c_str(), find_input_port_hole());
                        }
                        
-                       if ((our_port = _session.engine().register_audio_input_port (buf)) == 0) {
-                               error << string_compose(_("IO: cannot register input port %1"), buf) << endmsg;
+                       if ((our_port = _session.engine().register_input_port (type, name)) == 0) {
+                               error << string_compose(_("IO: cannot register input port %1"), name) << endmsg;
                                return -1;
                        }
                        
@@ -1001,7 +1026,7 @@ IO::ensure_inputs_locked (uint32_t n, bool clear, void* src)
                
                char buf[64];
                
-               /* Create a new input port */
+               /* Create a new input port (of the default type) */
                
                if (_input_maximum == 1) {
                        snprintf (buf, sizeof (buf), _("%s/in"), _name.c_str());
@@ -1012,7 +1037,7 @@ IO::ensure_inputs_locked (uint32_t n, bool clear, void* src)
                
                try {
                        
-                       if ((input_port = _session.engine().register_audio_input_port (buf)) == 0) {
+                       if ((input_port = _session.engine().register_input_port (_default_type, buf)) == 0) {
                                error << string_compose(_("IO: cannot register input port %1"), buf) << endmsg;
                                return -1;
                        }
@@ -1101,7 +1126,7 @@ IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src)
                        out_changed = true;
                }
                
-               /* create any necessary new ports */
+               /* create any necessary new ports (of the default type) */
                
                while (_ninputs < nin) {
                        
@@ -1117,7 +1142,7 @@ IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src)
                        }
                        
                        try {
-                               if ((port = _session.engine().register_audio_input_port (buf)) == 0) {
+                               if ((port = _session.engine().register_input_port (_default_type, buf)) == 0) {
                                        error << string_compose(_("IO: cannot register input port %1"), buf) << endmsg;
                                        return -1;
                                }
@@ -1150,7 +1175,7 @@ IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src)
                        }
                        
                        try { 
-                               if ((port = _session.engine().register_audio_output_port (buf)) == 0) {
+                               if ((port = _session.engine().register_output_port (_default_type, buf)) == 0) {
                                        error << string_compose(_("IO: cannot register output port %1"), buf) << endmsg;
                                        return -1;
                                }
@@ -1275,7 +1300,7 @@ IO::ensure_outputs_locked (uint32_t n, bool clear, void* src)
                        snprintf (buf, sizeof (buf), _("%s/out %u"), _name.c_str(), find_output_port_hole());
                }
                
-               if ((output_port = _session.engine().register_audio_output_port (buf)) == 0) {
+               if ((output_port = _session.engine().register_output_port (_default_type, buf)) == 0) {
                        error << string_compose(_("IO: cannot register output port %1"), buf) << endmsg;
                        return -1;
                }
index fc1dd840662db9beed64c90e9493ee35b7dd72b6..6d5e8f7847d5f0287cb96bbc21f540810b8d2a98 100644 (file)
@@ -598,6 +598,31 @@ Playlist::remove_region_internal (Region *region, bool delay_sort)
        return -1;
 }
 
+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)
 {
index c5c03d0a05948255066a4dccda538db478324228..7ec0d5a05ab2824827b29b965ca30ff16dbada79 100644 (file)
@@ -24,15 +24,15 @@ using namespace ARDOUR;
 using namespace std;
 
 Port::Port (jack_port_t *p) 
-       : port (p)
+       : _port (p)
 {
-       if (port == 0) {
+       if (_port == 0) {
                throw failed_constructor();
        }
        
-       _flags = JackPortFlags (jack_port_flags (port));
-       _type  = jack_port_type (port); 
-       _name = jack_port_name (port);
+       _flags = JackPortFlags (jack_port_flags (_port));
+       _type  = jack_port_type (_port); 
+       _name = jack_port_name (_port);
 
        reset ();
 }
@@ -42,9 +42,9 @@ Port::reset ()
 {
        reset_buffer ();
        
-       last_monitor = false;
-       silent = false;
-       metering = 0;
+       _last_monitor = false;
+       _silent = false;
+       _metering = 0;
        
        reset_meters ();
 }
@@ -54,7 +54,7 @@ Port::set_name (string str)
 {
        int ret;
 
-       if ((ret = jack_port_set_name (port, str.c_str())) == 0) {
+       if ((ret = jack_port_set_name (_port, str.c_str())) == 0) {
                _name = str;
        }
        
index f195e421488e2899686ba097b8802b55ec8c8dbe..037c84432470ef068e5d79d71cd7be922ad472e2 100644 (file)
@@ -39,13 +39,13 @@ using namespace std;
 using namespace ARDOUR;
 using namespace PBD;
 
-Change Region::FadeChanged = ARDOUR::new_change ();
+Change Region::FadeChanged       = ARDOUR::new_change ();
 Change Region::SyncOffsetChanged = ARDOUR::new_change ();
-Change Region::MuteChanged = ARDOUR::new_change ();
-Change Region::OpacityChanged = ARDOUR::new_change ();
-Change Region::LockChanged = ARDOUR::new_change ();
-Change Region::LayerChanged = ARDOUR::new_change ();
-Change Region::HiddenChanged = ARDOUR::new_change ();
+Change Region::MuteChanged       = ARDOUR::new_change ();
+Change Region::OpacityChanged    = ARDOUR::new_change ();
+Change Region::LockChanged       = ARDOUR::new_change ();
+Change Region::LayerChanged      = ARDOUR::new_change ();
+Change Region::HiddenChanged     = ARDOUR::new_change ();
 
 sigc::signal<void,Region *> Region::CheckNewRegion;
 
@@ -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;
+}
index f3162f9131a7a80fa529b2f3e102abbfe7e0a34c..effb8432d15171269f032802b1f1118cc54ccdb4 100644 (file)
 
 #include <cmath>
 #include <fstream>
+#include <cassert>
 
 #include <sigc++/bind.h>
 #include <pbd/xml++.h>
 
 #include <ardour/timestamps.h>
+#include <ardour/buffer.h>
 #include <ardour/audioengine.h>
 #include <ardour/route.h>
 #include <ardour/insert.h>
@@ -50,8 +52,8 @@ using namespace PBD;
 uint32_t Route::order_key_cnt = 0;
 
 
-Route::Route (Session& sess, string name, int input_min, int input_max, int output_min, int output_max, Flag flg)
-       : IO (sess, name, input_min, input_max, output_min, output_max),
+Route::Route (Session& sess, string name, int input_min, int input_max, int output_min, int output_max, Flag flg, DataType default_type)
+       : IO (sess, name, input_min, input_max, output_min, output_max, default_type),
          _flags (flg),
          _solo_control (*this, ToggleControllable::SoloControl),
          _mute_control (*this, ToggleControllable::MuteControl)
@@ -1330,6 +1332,9 @@ Route::state(bool full_state)
                snprintf (buf, sizeof (buf), "0x%x", _flags);
                node->add_property("flags", buf);
        }
+       
+       node->add_property("default-type", Buffer::type_to_string(_default_type));
+
        node->add_property("active", _active?"yes":"no");
        node->add_property("muted", _muted?"yes":"no");
        node->add_property("soloed", _soloed?"yes":"no");
@@ -1503,6 +1508,11 @@ Route::set_state (const XMLNode& node)
        } else {
                _flags = Flag (0);
        }
+       
+       if ((prop = node.property ("default-type")) != 0) {
+               _default_type = Buffer::type_from_string(prop->value());
+               assert(_default_type != NIL);
+       }
 
        if ((prop = node.property ("phase-invert")) != 0) {
                set_phase_invert(prop->value()=="yes"?true:false, this);
index ae879ed0835c972c49c4c0e65f6a7c1ec7571daf..45afdf479fdde63bf18e81d45a553fd98584be6d 100644 (file)
@@ -397,6 +397,8 @@ Session::~Session ()
                delete [] (i->second);
        }
        
+       AudioDiskstream::free_working_buffers();
+       
 #undef TRACK_DESTRUCTION
 #ifdef TRACK_DESTRUCTION
        cerr << "delete named selections\n";
@@ -440,10 +442,10 @@ Session::~Session ()
        }
        
 #ifdef TRACK_DESTRUCTION
-       cerr << "delete audio_diskstreams\n";
+       cerr << "delete diskstreams\n";
 #endif /* TRACK_DESTRUCTION */
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ) {
-               AudioDiskstreamList::iterator tmp;
+       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ) {
+               DiskstreamList::iterator tmp;
 
                tmp = i;
                ++tmp;
@@ -860,7 +862,7 @@ Session::playlist_length_changed (Playlist* pl)
 }
 
 void
-Session::diskstream_playlist_changed (AudioDiskstream* dstream)
+Session::diskstream_playlist_changed (Diskstream* dstream)
 {
        Playlist *playlist;
 
@@ -940,7 +942,7 @@ Session::set_auto_input (bool yn)
                           The rarity and short potential lock duration makes this "OK"
                        */
                        Glib::RWLock::ReaderLock dsm (diskstream_lock);
-                       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+                       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                                if ((*i)->record_enabled ()) {
                                        //cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
                                        (*i)->monitor_input (!auto_input);   
@@ -958,7 +960,7 @@ Session::reset_input_monitor_state ()
 {
        if (transport_rolling()) {
                Glib::RWLock::ReaderLock dsm (diskstream_lock);
-               for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+               for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                        if ((*i)->record_enabled ()) {
                                //cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
                                (*i)->monitor_input (Config->get_use_hardware_monitoring() && !auto_input);
@@ -966,7 +968,7 @@ Session::reset_input_monitor_state ()
                }
        } else {
                Glib::RWLock::ReaderLock dsm (diskstream_lock);
-               for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+               for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                        if ((*i)->record_enabled ()) {
                                //cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
                                (*i)->monitor_input (Config->get_use_hardware_monitoring());
@@ -1047,7 +1049,7 @@ Session::auto_loop_changed (Location* location)
                }
                else if (seamless_loop && !loop_changing) {
                        
-                       // schedule a locate-roll to refill the audio_diskstreams at the
+                       // schedule a locate-roll to refill the diskstreams at the
                        // previous loop end
                        loop_changing = true;
 
@@ -1244,7 +1246,7 @@ Session::enable_record ()
                        */
                        Glib::RWLock::ReaderLock dsm (diskstream_lock);
                        
-                       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+                       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                                if ((*i)->record_enabled ()) {
                                        (*i)->monitor_input (true);   
                                }
@@ -1279,7 +1281,7 @@ Session::disable_record (bool rt_context, bool force)
                        */
                        Glib::RWLock::ReaderLock dsm (diskstream_lock);
                        
-                       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+                       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                                if ((*i)->record_enabled ()) {
                                        (*i)->monitor_input (false);   
                                }
@@ -1306,7 +1308,7 @@ Session::step_back_from_record ()
                */
                Glib::RWLock::ReaderLock dsm (diskstream_lock);
                
-               for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+               for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                        if (auto_input && (*i)->record_enabled ()) {
                                //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
                                (*i)->monitor_input (false);   
@@ -1476,7 +1478,7 @@ Session::set_block_size (jack_nframes_t nframes)
                        (*i)->set_block_size (nframes);
                }
                
-               for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+               for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                        (*i)->set_block_size (nframes);
                }
 
@@ -1760,7 +1762,7 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
                        track->set_control_outs (cports);
                }
 
-               track->diskstream_changed.connect (mem_fun (this, &Session::resort_routes_proxy));
+               track->DiskstreamChanged.connect (mem_fun (this, &Session::resort_routes));
 
                add_route (track);
 
@@ -1805,7 +1807,7 @@ Session::new_audio_route (int input_channels, int output_channels)
        } while (n < (UINT_MAX-1));
 
        try {
-               shared_ptr<Route> bus (new Route (*this, bus_name, -1, -1, -1, -1));
+               shared_ptr<Route> bus (new Route (*this, bus_name, -1, -1, -1, -1, Route::Flag(0), AUDIO));
 
                if (bus->ensure_io (input_channels, output_channels, false, this)) {
                        error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
@@ -1858,7 +1860,7 @@ Session::new_audio_route (int input_channels, int output_channels)
        }
 
        catch (failed_constructor &err) {
-               error << _("Session: could not create new route.") << endmsg;
+               error << _("Session: could not create new audio route.") << endmsg;
                return shared_ptr<Route> ((Route*) 0);
        }
 }
@@ -1893,14 +1895,14 @@ Session::add_route (shared_ptr<Route> route)
 }
 
 void
-Session::add_diskstream (AudioDiskstream* dstream)
+Session::add_diskstream (Diskstream* dstream)
 {
        /* need to do this in case we're rolling at the time, to prevent false underruns */
-       dstream->do_refill(0, 0, 0);
+       dstream->do_refill_with_alloc();
        
        { 
                Glib::RWLock::WriterLock lm (diskstream_lock);
-               audio_diskstreams.push_back (dstream);
+               diskstreams.push_back (dstream);
        }
 
        /* take a reference to the diskstream, preventing it from
@@ -1920,7 +1922,7 @@ Session::add_diskstream (AudioDiskstream* dstream)
        set_dirty();
        save_state (_current_snapshot_name);
 
-       AudioDiskstreamAdded (dstream); /* EMIT SIGNAL */
+       DiskstreamAdded (dstream); /* EMIT SIGNAL */
 }
 
 void
@@ -1957,18 +1959,19 @@ Session::remove_route (shared_ptr<Route> route)
                /* writer goes out of scope, forces route list update */
        }
 
+       // FIXME: audio specific
        AudioTrack* at;
        AudioDiskstream* ds = 0;
        
        if ((at = dynamic_cast<AudioTrack*>(route.get())) != 0) {
-               ds = &at->disk_stream();
+               ds = &at->audio_diskstream();
        }
        
        if (ds) {
 
                {
                        Glib::RWLock::WriterLock lm (diskstream_lock);
-                       audio_diskstreams.remove (ds);
+                       diskstreams.remove (ds);
                }
 
                ds->unref ();
@@ -2261,7 +2264,7 @@ Session::get_maximum_extent () const
           ensure atomicity.
        */
 
-       for (AudioDiskstreamList::const_iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+       for (DiskstreamList::const_iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                Playlist* pl = (*i)->playlist();
                if ((me = pl->get_maximum_extent()) > max) {
                        max = me;
@@ -2271,12 +2274,12 @@ Session::get_maximum_extent () const
        return max;
 }
 
-AudioDiskstream *
+Diskstream *
 Session::diskstream_by_name (string name)
 {
        Glib::RWLock::ReaderLock lm (diskstream_lock);
 
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                if ((*i)->name() == name) {
                        return* i;
                }
@@ -2285,12 +2288,12 @@ Session::diskstream_by_name (string name)
        return 0;
 }
 
-AudioDiskstream *
+Diskstream *
 Session::diskstream_by_id (const PBD::ID& id)
 {
        Glib::RWLock::ReaderLock lm (diskstream_lock);
 
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                if ((*i)->id() == id) {
                        return *i;
                }
@@ -2555,18 +2558,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
@@ -2618,7 +2613,7 @@ Session::remove_last_capture ()
 
        Glib::RWLock::ReaderLock lm (diskstream_lock);
        
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                list<Region*>& l = (*i)->last_capture_regions();
                
                if (!l.empty()) {
@@ -2925,18 +2920,6 @@ Session::create_audio_source_for_session (AudioDiskstream& ds, uint32_t chan, bo
 
 /* Playlist management */
 
-Playlist *
-Session::get_playlist (string name)
-{
-       Playlist* ret = 0;
-
-       if ((ret = playlist_by_name (name)) == 0) {
-               ret = new AudioPlaylist (*this, name);
-       }
-
-       return ret;
-}
-
 Playlist *
 Session::playlist_by_name (string name)
 {
@@ -3066,11 +3049,14 @@ Session::audition_playlist ()
 }
 
 void
-Session::audition_region (AudioRegion& r)
+Session::audition_region (Region& r)
 {
-       Event* ev = new Event (Event::Audition, Event::Add, Event::Immediate, 0, 0.0);
-       ev->set_ptr (&r);
-       queue_event (ev);
+       AudioRegion* ar = dynamic_cast<AudioRegion*>(&r);
+       if (ar) {
+               Event* ev = new Event (Event::Audition, Event::Add, Event::Immediate, 0, 0.0);
+               ev->set_ptr (ar);
+               queue_event (ev);
+       }
 }
 
 void
@@ -3155,12 +3141,12 @@ Session::set_all_mute (bool yn)
 }
                
 uint32_t
-Session::n_audio_diskstreams () const
+Session::n_diskstreams () const
 {
        Glib::RWLock::ReaderLock lm (diskstream_lock);
        uint32_t n = 0;
 
-       for (AudioDiskstreamList::const_iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+       for (DiskstreamList::const_iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                if (!(*i)->hidden()) {
                        n++;
                }
@@ -3168,17 +3154,6 @@ Session::n_audio_diskstreams () const
        return n;
 }
 
-void 
-Session::foreach_audio_diskstream (void (AudioDiskstream::*func)(void)) 
-{
-       Glib::RWLock::ReaderLock lm (diskstream_lock);
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
-               if (!(*i)->hidden()) {
-                       ((*i)->*func)();
-               }
-       }
-}
-
 void
 Session::graph_reordered ()
 {
@@ -3198,7 +3173,7 @@ Session::graph_reordered ()
           reflect any changes in latencies within the graph.
        */
        
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                (*i)->set_capture_offset ();
        }
 }
@@ -3481,7 +3456,7 @@ Session::reset_native_file_format ()
        //RWLockMonitor lm1 (route_lock, true, __LINE__, __FILE__);
        Glib::RWLock::ReaderLock lm2 (diskstream_lock);
 
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                (*i)->reset_write_sources (false);
        }
 }
@@ -3592,7 +3567,7 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf
        
        /* call tree *MUST* hold route_lock */
        
-       if ((playlist = track.disk_stream().playlist()) == 0) {
+       if ((playlist = track.diskstream().playlist()) == 0) {
                goto out;
        }
 
@@ -3602,7 +3577,7 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf
                goto out;
        }
 
-       nchans = track.disk_stream().n_channels();
+       nchans = track.audio_diskstream().n_channels();
        
        dir = discover_best_sound_dir ();
 
index 4613bfccf9c2b4467b2ed8da5d43b6fb20ae581b..6509a783bb8ad8481050480cea09241087001c81 100644 (file)
@@ -168,15 +168,9 @@ Session::butler_thread_work ()
        struct timeval begin, end;
        struct pollfd pfd[1];
        bool disk_work_outstanding = false;
-       AudioDiskstreamList::iterator i;
-
-       butler_mixdown_buffer = new Sample[AudioDiskstream::disk_io_frames()];
-       butler_gain_buffer = new gain_t[AudioDiskstream::disk_io_frames()];
-       // this buffer is used for temp conversion purposes in filesources
-       char * conv_buffer = conversion_buffer(ButlerContext);
+       DiskstreamList::iterator i;
 
        while (true) {
-
                pfd[0].fd = butler_request_pipe[0];
                pfd[0].events = POLLIN|POLLERR|POLLHUP;
                
@@ -198,14 +192,13 @@ Session::butler_thread_work ()
                }
                
                if (pfd[0].revents & POLLIN) {
-                       
+
                        char req;
                        
                        /* empty the pipe of all current requests */
                        
                        while (1) {
                                size_t nread = ::read (butler_request_pipe[0], &req, sizeof (req));
-                               
                                if (nread == 1) {
                                        
                                        switch ((ButlerRequest::Type) req) {
@@ -240,10 +233,10 @@ Session::butler_thread_work ()
                                }
                        }
                }
-       
-               for (i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+
+               //for (i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                        // cerr << "BEFORE " << (*i)->name() << ": pb = " << (*i)->playback_buffer_load() << " cp = " << (*i)->capture_buffer_load() << endl;
-               }
+               //}
 
                if (transport_work_requested()) {
                        butler_transport_work ();
@@ -257,16 +250,16 @@ Session::butler_thread_work ()
 
                Glib::RWLock::ReaderLock dsm (diskstream_lock);
                
-               for (i = audio_diskstreams.begin(); !transport_work_requested() && butler_should_run && i != audio_diskstreams.end(); ++i) {
-                       
-                       // cerr << "rah fondr " << (*i)->io()->name () << endl;
+               for (i = diskstreams.begin(); !transport_work_requested() && butler_should_run && i != diskstreams.end(); ++i) {
+
+                       Diskstream* const ds = *i;
 
-                       switch ((*i)->do_refill (butler_mixdown_buffer, butler_gain_buffer, conv_buffer)) {
+                       switch (ds->do_refill ()) {
                        case 0:
-                               bytes += (*i)->read_data_count();
+                               bytes += ds->read_data_count();
                                break;
                        case 1:
-                               bytes += (*i)->read_data_count();
+                               bytes += ds->read_data_count();
                                disk_work_outstanding = true;
                                break;
                                
@@ -278,7 +271,7 @@ Session::butler_thread_work ()
 
                }
 
-               if (i != audio_diskstreams.end()) {
+               if (i != diskstreams.end()) {
                        /* we didn't get to all the streams */
                        disk_work_outstanding = true;
                }
@@ -299,12 +292,11 @@ Session::butler_thread_work ()
                bytes = 0;
                compute_io = true;
                gettimeofday (&begin, 0);
-               
-               for (i = audio_diskstreams.begin(); !transport_work_requested() && butler_should_run && i != audio_diskstreams.end(); ++i) {
-                       
+
+               for (i = diskstreams.begin(); !transport_work_requested() && butler_should_run && i != diskstreams.end(); ++i) {
                        // cerr << "write behind for " << (*i)->name () << endl;
                        
-                       switch ((*i)->do_flush (conv_buffer)) {
+                       switch ((*i)->do_flush (Session::ButlerContext)) {
                        case 0:
                                bytes += (*i)->write_data_count();
                                break;
@@ -330,7 +322,7 @@ Session::butler_thread_work ()
                        request_stop ();
                }
 
-               if (i != audio_diskstreams.end()) {
+               if (i != diskstreams.end()) {
                        /* we didn't get to all the streams */
                        disk_work_outstanding = true;
                }
@@ -357,7 +349,7 @@ Session::butler_thread_work ()
                        Glib::Mutex::Lock lm (butler_request_lock);
 
                        if (butler_should_run && (disk_work_outstanding || transport_work_requested())) {
-//                             for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+//                             for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
 //                                     cerr << "AFTER " << (*i)->name() << ": pb = " << (*i)->playback_buffer_load() << " cp = " << (*i)->capture_buffer_load() << endl;
 //                             }
 
@@ -375,18 +367,17 @@ Session::butler_thread_work ()
 
 
 void
-Session::request_overwrite_buffer (AudioDiskstream* stream)
+Session::request_overwrite_buffer (Diskstream* stream)
 {
        Event *ev = new Event (Event::Overwrite, Event::Add, Event::Immediate, 0, 0, 0.0);
        ev->set_ptr (stream);
        queue_event (ev);
 }
 
+/** Process thread. */
 void
-Session::overwrite_some_buffers (AudioDiskstream* ds)
+Session::overwrite_some_buffers (Diskstream* ds)
 {
-       /* executed by the audio thread */
-
        if (actively_recording()) {
                return;
        }
@@ -398,7 +389,7 @@ Session::overwrite_some_buffers (AudioDiskstream* ds)
        } else {
 
                Glib::RWLock::ReaderLock dm (diskstream_lock);
-               for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+               for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                        (*i)->set_pending_overwrite (true);
                }
        }
index ad8ce7c40759992cbeb4d008d13ee08c70dd8780..b39c4f22185cb4398c181b3400420dd76d28f0b9 100644 (file)
@@ -496,7 +496,7 @@ Session::prepare_to_export (AudioExportSpecification& spec)
 
        {
                Glib::RWLock::ReaderLock lm (diskstream_lock);
-               for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+               for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                        if ((*i)-> seek (spec.start_frame, true)) {
                                error << string_compose (_("%1: cannot seek to %2 for export"),
                                                  (*i)->name(), spec.start_frame)
index 2024730292bff5a673cff23c379dc722e4a3b50a..88b111a1fbedb24fd8d1ea25b47065c2e60237b4 100644 (file)
@@ -66,7 +66,7 @@ Session::process (jack_nframes_t nframes)
 void
 Session::prepare_diskstreams ()
 {
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                (*i)->prepare ();
        }
 }
@@ -141,7 +141,7 @@ Session::process_routes (jack_nframes_t nframes, jack_nframes_t offset)
                           call path, so make sure we release any outstanding locks here before we return failure.
                        */
 
-                       for (AudioDiskstreamList::iterator ids = audio_diskstreams.begin(); ids != audio_diskstreams.end(); ++ids) {
+                       for (DiskstreamList::iterator ids = diskstreams.begin(); ids != diskstreams.end(); ++ids) {
                                (*ids)->recover ();
                        }
 
@@ -181,7 +181,7 @@ Session::silent_process_routes (jack_nframes_t nframes, jack_nframes_t offset)
                           call path, so make sure we release any outstanding locks here before we return failure.
                        */
 
-                       for (AudioDiskstreamList::iterator ids = audio_diskstreams.begin(); ids != audio_diskstreams.end(); ++ids) {
+                       for (DiskstreamList::iterator ids = diskstreams.begin(); ids != diskstreams.end(); ++ids) {
                                (*ids)->recover ();
                        }
 
@@ -200,7 +200,7 @@ Session::commit_diskstreams (jack_nframes_t nframes, bool &needs_butler)
        float pworst = 1.0f;
        float cworst = 1.0f;
 
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
 
                if ((*i)->hidden()) {
                        continue;
@@ -570,7 +570,7 @@ Session::follow_slave (jack_nframes_t nframes, jack_nframes_t offset)
                                bool ok = true;
                                jack_nframes_t frame_delta = slave_transport_frame - _transport_frame;
                                
-                               for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+                               for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                                        if (!(*i)->can_internal_playback_seek (frame_delta)) {
                                                ok = false;
                                                break;
@@ -578,7 +578,7 @@ Session::follow_slave (jack_nframes_t nframes, jack_nframes_t offset)
                                }
 
                                if (ok) {
-                                       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+                                       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                                                (*i)->internal_playback_seek (frame_delta);
                                        }
                                        _transport_frame += frame_delta;
index 2f6f57e2d822058d4624599e65aa724590fc2af1..c90fd91d735ac821b7d7bde82684765c1d84b8f4 100644 (file)
@@ -194,6 +194,7 @@ Session::first_stage_init (string fullpath, string snapshot_name)
        /* allocate conversion buffers */
        _conversion_buffers[ButlerContext] = new char[AudioDiskstream::disk_io_frames() * 4];
        _conversion_buffers[TransportContext] = new char[AudioDiskstream::disk_io_frames() * 4];
+       AudioDiskstream::allocate_working_buffers();
        
        /* default short fade = 15ms */
 
@@ -266,7 +267,7 @@ Session::first_stage_init (string fullpath, string snapshot_name)
        AudioSource::AudioSourceCreated.connect (mem_fun (*this, &Session::add_audio_source));
        Playlist::PlaylistCreated.connect (mem_fun (*this, &Session::add_playlist));
        Redirect::RedirectCreated.connect (mem_fun (*this, &Session::add_redirect));
-       AudioDiskstream::AudioDiskstreamCreated.connect (mem_fun (*this, &Session::add_diskstream));
+       AudioDiskstream::DiskstreamCreated.connect (mem_fun (*this, &Session::add_diskstream));
        NamedSelection::NamedSelectionCreated.connect (mem_fun (*this, &Session::add_named_selection));
 
        Controllable::Created.connect (mem_fun (*this, &Session::add_controllable));
@@ -1386,7 +1387,7 @@ Session::state(bool full_state)
 
        { 
                Glib::RWLock::ReaderLock dl (diskstream_lock);
-               for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+               for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                        if (!(*i)->hidden()) {
                                child->add_child_nocopy ((*i)->get_state());
                        }
index 03e078ecde8b14fe4273ae04e3e65c0c319183be..d850fb94c810c7d18c0ddc0615f347c6637a9eff 100644 (file)
@@ -79,7 +79,7 @@ Session::request_transport_speed (float speed)
 }
 
 void
-Session::request_diskstream_speed (AudioDiskstream& ds, float speed)
+Session::request_diskstream_speed (Diskstream& ds, float speed)
 {
        Event* ev = new Event (Event::SetDiskstreamSpeed, Event::Add, Event::Immediate, 0, speed);
        ev->set_ptr (&ds);
@@ -201,7 +201,7 @@ Session::butler_transport_work ()
        }
 
        if (post_transport_work & PostTransportInputChange) {
-               for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+               for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                        (*i)->non_realtime_input_change ();
                }
        }
@@ -217,7 +217,7 @@ Session::butler_transport_work ()
                cumulative_rf_motion = 0;
                reset_rf_scale (0);
 
-               for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+               for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                        if (!(*i)->hidden()) {
                                if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
                                        (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
@@ -249,7 +249,7 @@ Session::non_realtime_set_speed ()
 {
        Glib::RWLock::ReaderLock lm (diskstream_lock);
 
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                (*i)->non_realtime_set_speed ();
        }
 }
@@ -259,7 +259,7 @@ Session::non_realtime_overwrite ()
 {
        Glib::RWLock::ReaderLock lm (diskstream_lock);
 
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                if ((*i)->pending_overwrite) {
                        (*i)->overwrite_existing_buffers ();
                }
@@ -275,7 +275,7 @@ Session::non_realtime_stop (bool abort)
        
        did_record = false;
        
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                if ((*i)->get_captured_frames () != 0) {
                        did_record = true;
                        break;
@@ -328,7 +328,7 @@ Session::non_realtime_stop (bool abort)
                _have_captured = true;
        }
 
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                (*i)->transport_stopped (*now, xnow, abort);
        }
        
@@ -367,7 +367,7 @@ Session::non_realtime_stop (bool abort)
        }
 #endif
 
-               for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+               for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                        if (!(*i)->hidden()) {
                                if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
                                        (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
@@ -494,7 +494,7 @@ Session::set_auto_loop (bool yn)
 
                        if (seamless_loop) {
                                // set all diskstreams to use internal looping
-                               for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+                               for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                                        if (!(*i)->hidden()) {
                                                (*i)->set_loop (loc);
                                        }
@@ -502,7 +502,7 @@ Session::set_auto_loop (bool yn)
                        }
                        else {
                                // set all diskstreams to NOT use internal looping
-                               for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+                               for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                                        if (!(*i)->hidden()) {
                                                (*i)->set_loop (0);
                                        }
@@ -532,7 +532,7 @@ Session::set_auto_loop (bool yn)
                clear_events (Event::AutoLoop);
 
                // set all diskstreams to NOT use internal looping
-               for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+               for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                        if (!(*i)->hidden()) {
                                (*i)->set_loop (0);
                        }
@@ -650,7 +650,7 @@ Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, b
                           The rarity and short potential lock duration makes this "OK"
                        */
                        Glib::RWLock::ReaderLock dsm (diskstream_lock);
-                       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+                       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                                if ((*i)->record_enabled ()) {
                                        //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
                                        (*i)->monitor_input (!auto_input);
@@ -665,7 +665,7 @@ Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, b
                           The rarity and short potential lock duration makes this "OK"
                        */
                        Glib::RWLock::ReaderLock dsm (diskstream_lock);
-                       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+                       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                                if ((*i)->record_enabled ()) {
                                        //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
                                        (*i)->monitor_input (true);
@@ -709,7 +709,7 @@ Session::set_transport_speed (float speed, bool abort)
                           The rarity and short potential lock duration makes this "OK"
                        */
                        Glib::RWLock::ReaderLock dsm (diskstream_lock);
-                       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+                       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                                if ((*i)->record_enabled ()) {
                                        //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
                                        (*i)->monitor_input (true);     
@@ -735,7 +735,7 @@ Session::set_transport_speed (float speed, bool abort)
                           The rarity and short potential lock duration makes this "OK"
                        */
                        Glib::RWLock::ReaderLock dsm (diskstream_lock);
-                       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+                       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                                if (auto_input && (*i)->record_enabled ()) {
                                        //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
                                        (*i)->monitor_input (false);    
@@ -786,7 +786,7 @@ Session::set_transport_speed (float speed, bool abort)
                _last_transport_speed = _transport_speed;
                _transport_speed = speed;
                
-               for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+               for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                        if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
                                post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
                        }
@@ -876,7 +876,7 @@ Session::actually_start_transport ()
        transport_sub_state |= PendingDeclickIn;
        _transport_speed = 1.0;
        
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                (*i)->realtime_set_speed ((*i)->speed(), true);
        }
 
@@ -1006,7 +1006,7 @@ Session::set_slave_source (SlaveSource src, jack_nframes_t frame)
        
        _slave_type = src;
 
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                if (!(*i)->hidden()) {
                        if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
                                non_rt_required = true;
@@ -1038,7 +1038,7 @@ Session::reverse_diskstream_buffers ()
 }
 
 void
-Session::set_diskstream_speed (AudioDiskstream* stream, float speed)
+Session::set_diskstream_speed (Diskstream* stream, float speed)
 {
        if (stream->realtime_set_speed (speed, false)) {
                post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
@@ -1235,7 +1235,7 @@ Session::update_latency_compensation (bool with_stop, bool abort)
        /* reflect any changes in latencies into capture offsets
        */
        
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                (*i)->set_capture_offset ();
        }
 }
diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc
new file mode 100644 (file)
index 0000000..3b3b705
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+    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 <pbd/error.h>
+#include <sigc++/retype.h>
+#include <sigc++/retype_return.h>
+#include <sigc++/bind.h>
+
+#include <ardour/track.h>
+#include <ardour/diskstream.h>
+#include <ardour/session.h>
+#include <ardour/redirect.h>
+#include <ardour/audioregion.h>
+#include <ardour/audiosource.h>
+#include <ardour/route_group_specialized.h>
+#include <ardour/insert.h>
+#include <ardour/audioplaylist.h>
+#include <ardour/panner.h>
+#include <ardour/utils.h>
+
+#include "i18n.h"
+
+using namespace std;
+using namespace ARDOUR;
+using namespace PBD;
+
+Track::Track (Session& sess, string name, Route::Flag flag, TrackMode mode, DataType default_type)
+       : Route (sess, name, 1, -1, -1, -1, flag, default_type)
+       , _diskstream (0)
+       ,  _rec_enable_control (*this)
+{
+       _declickable = true;
+       _freeze_record.state = NoFreeze;
+       _saved_meter_point = _meter_point;
+       _mode = mode;
+}
+
+Track::Track (Session& sess, const XMLNode& node, DataType default_type)
+       : Route (sess, "to be renamed", 0, 0, -1, -1, Route::Flag(0), default_type)
+       , _diskstream (0)
+       , _rec_enable_control (*this)
+{
+       _freeze_record.state = NoFreeze;
+       _declickable = true;
+       _saved_meter_point = _meter_point;
+}
+
+Track::~Track ()
+{
+       if (_diskstream) {
+               _diskstream->unref();
+       }
+}
+
+void
+Track::set_meter_point (MeterPoint p, void *src)
+{
+       Route::set_meter_point (p, src);
+}
+
+XMLNode&
+Track::get_state ()
+{
+       return state (true);
+}
+
+XMLNode&
+Track::get_template ()
+{
+       return state (false);
+}
+
+void
+Track::toggle_monitor_input ()
+{
+       for (vector<Port*>::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
+               (*i)->request_monitor_input(!(*i)->monitoring_input());
+       }
+}
+
+jack_nframes_t
+Track::update_total_latency ()
+{
+       _own_latency = 0;
+
+       for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
+               if ((*i)->active ()) {
+                       _own_latency += (*i)->latency ();
+               }
+       }
+
+       set_port_latency (_own_latency);
+
+       return _own_latency;
+}
+
+
+Track::FreezeRecord::~FreezeRecord ()
+{
+       for (vector<FreezeRecordInsertInfo*>::iterator i = insert_info.begin(); i != insert_info.end(); ++i) {
+               delete *i;
+       }
+}
+
+Track::FreezeState
+Track::freeze_state() const
+{
+       return _freeze_record.state;
+}
+
+Track::RecEnableControllable::RecEnableControllable (Track& s)
+       : track (s)
+{
+}
+
+void
+Track::RecEnableControllable::set_value (float val)
+{
+       bool bval = ((val >= 0.5f) ? true: false);
+       track.set_record_enable (bval, this);
+}
+
+float
+Track::RecEnableControllable::get_value (void) const
+{
+       if (track.record_enabled()) { return 1.0f; }
+       return 0.0f;
+}
+
+bool
+Track::record_enabled () const
+{
+       return _diskstream->record_enabled ();
+}
+       
+void
+Track::set_record_enable (bool yn, void *src)
+{
+       if (_freeze_record.state == Frozen) {
+               return;
+       }
+
+       if (_mix_group && src != _mix_group && _mix_group->is_active()) {
+               _mix_group->apply (&Track::set_record_enable, yn, _mix_group);
+               return;
+       }
+
+       /* keep track of the meter point as it was before we rec-enabled */
+
+       if (!_diskstream->record_enabled()) {
+               _saved_meter_point = _meter_point;
+       }
+       
+       _diskstream->set_record_enabled (yn);
+
+       if (_diskstream->record_enabled()) {
+               set_meter_point (MeterInput, this);
+       } else {
+               set_meter_point (_saved_meter_point, this);
+       }
+
+       _rec_enable_control.Changed ();
+}
+
+void
+Track::set_mode (TrackMode m)
+{
+       if (_diskstream) {
+               if (_mode != m) {
+                       _mode = m;
+                       _diskstream->set_destructive (m == Destructive);
+                       ModeChanged();
+               }
+       }
+}
+
+int
+Track::set_name (string str, void *src)
+{
+       int ret;
+
+       if (record_enabled() && _session.actively_recording()) {
+               /* this messes things up if done while recording */
+               return -1;
+       }
+
+       if (_diskstream->set_name (str)) {
+               return -1;
+       }
+
+       /* save state so that the statefile fully reflects any filename changes */
+
+       if ((ret = IO::set_name (str, src)) == 0) {
+               _session.save_state ("");
+       }
+       return ret;
+}
+
+void
+Track::set_latency_delay (jack_nframes_t longest_session_latency)
+{
+       Route::set_latency_delay (longest_session_latency);
+       _diskstream->set_roll_delay (_roll_delay);
+}
+