# 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'
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
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
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
#include <gtkmm/treeiter.h>
#include <ardour/audioregion.h>
-#include <ardour/playlist.h>
+#include <ardour/audioplaylist.h>
#include <ardour/types.h>
#include "analysis_window.h"
#include "time_axis_view.h"
#include "public_editor.h"
#include "selection.h"
-#include "regionview.h"
+#include "audio_region_view.h"
#include "i18n.h"
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
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++) {
#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>
#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>
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 */
}
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++;
}
}
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;
}
void
-ARDOUR_UI::diskstream_added (AudioDiskstream* ds)
+ARDOUR_UI::diskstream_added (Diskstream* ds)
{
}
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
}
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;
}
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 *);
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;
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);
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) {
--- /dev/null
+/*
+ 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);
+ }
+}
+
--- /dev/null
+/*
+ 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__ */
--- /dev/null
+/*
+ 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;
+ }
+}
--- /dev/null
+/*
+ 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__ */
--- /dev/null
+/*
+ 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() = ®ion;
+ }
+}
+
+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) ®ion;
+ wave->property_cache() = wave_caches[which];
+ wave->property_cache_updater() = true;
+ wave->property_channel() = which;
+ wave->property_length_function() = (gpointer) region_length_from_c;
+ wave->property_sourcefile_length_function() = (gpointer) sourcefile_length_from_c;
+ wave->property_peak_function() = (gpointer) region_read_peaks_from_c;
+ wave->property_x() = 0.0;
+ wave->property_y() = yoff;
+ wave->property_height() = (double) ht;
+ wave->property_samples_per_unit() = samples_per_unit;
+ wave->property_amplitude_above_axis() = _amplitude_above_axis;
+ wave->property_wave_color() = region.muted() ? color_map[cMutedWaveForm] : color_map[cWaveForm];
+ wave->property_region_start() = region.start();
+
+ if (!(_flags & WaveformVisible)) {
+ wave->hide();
+ }
+
+ /* note: calling this function is serialized by the lock
+ held in the peak building thread that signals that
+ peaks are ready for use *or* by the fact that it is
+ called one by one from the GUI thread.
+ */
+
+ if (which < nchans) {
+ tmp_waves[which] = wave;
+ } else {
+ /* n-channel track, >n-channel source */
+ }
+
+ /* see if we're all ready */
+
+ for (n = 0; n < nchans; ++n) {
+ if (tmp_waves[n] == 0) {
+ break;
+ }
+ }
+
+ if (n == nwaves && waves.empty()) {
+ /* all waves are ready */
+ tmp_waves.resize(nwaves);
+
+ waves = tmp_waves;
+ tmp_waves.clear ();
+
+ if (!zero_line) {
+ zero_line = new ArdourCanvas::SimpleLine (*group);
+ zero_line->property_x1() = (gdouble) 1.0;
+ zero_line->property_x2() = (gdouble) (region.length() / samples_per_unit) - 1.0;
+ zero_line->property_color_rgba() = (guint) color_map[cZeroLine];
+ manage_zero_line ();
+ }
+ }
+}
+
+void
+AudioRegionView::peaks_ready_handler (uint32_t which)
+{
+ Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &AudioRegionView::create_one_wave), which, false));
+
+ if (!waves.empty()) {
+ /* all waves created, don't hook into peaks ready anymore */
+ peaks_ready_connection.disconnect ();
+ }
+}
+
+void
+AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev)
+{
+ if (gain_line == 0) {
+ return;
+ }
+
+ double x, y;
+
+ /* don't create points that can't be seen */
+
+ set_envelope_visible (true);
+
+ x = ev->button.x;
+ y = ev->button.y;
+
+ item->w2i (x, y);
+
+ jack_nframes_t fx = trackview.editor.pixel_to_frame (x);
+
+ if (fx > region.length()) {
+ return;
+ }
+
+ /* compute vertical fractional position */
+
+ y = 1.0 - (y / (trackview.height - NAME_HIGHLIGHT_SIZE));
+
+ /* map using gain line */
+
+ gain_line->view_to_model_y (y);
+
+ trackview.session().begin_reversible_command (_("add gain control point"));
+ trackview.session().add_undo (region.envelope().get_memento());
+
+
+ if (!region.envelope_active()) {
+ trackview.session().add_undo( bind( mem_fun(region, &AudioRegion::set_envelope_active), false) );
+ region.set_envelope_active(true);
+ trackview.session().add_redo( bind( mem_fun(region, &AudioRegion::set_envelope_active), true) );
+ }
+
+ region.envelope().add (fx, y);
+
+ trackview.session().add_redo_no_execute (region.envelope().get_memento());
+ trackview.session().commit_reversible_command ();
+}
+
+void
+AudioRegionView::remove_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev)
+{
+ ControlPoint *cp = reinterpret_cast<ControlPoint *> (item->get_data ("control_point"));
+ region.envelope().erase (cp->model);
+}
+
+void
+AudioRegionView::store_flags()
+{
+ XMLNode *node = new XMLNode ("GUI");
+
+ node->add_property ("waveform-visible", (_flags & WaveformVisible) ? "yes" : "no");
+ node->add_property ("envelope-visible", (_flags & EnvelopeVisible) ? "yes" : "no");
+
+ region.add_extra_xml (*node);
+}
+
+void
+AudioRegionView::set_flags (XMLNode* node)
+{
+ XMLProperty *prop;
+
+ if ((prop = node->property ("waveform-visible")) != 0) {
+ if (prop->value() == "yes") {
+ _flags |= WaveformVisible;
+ }
+ }
+
+ if ((prop = node->property ("envelope-visible")) != 0) {
+ if (prop->value() == "yes") {
+ _flags |= EnvelopeVisible;
+ }
+ }
+}
+
+void
+AudioRegionView::set_waveform_shape (WaveformShape shape)
+{
+ bool yn;
+
+ /* this slightly odd approach is to leave the door open to
+ other "shapes" such as spectral displays, etc.
+ */
+
+ switch (shape) {
+ case Rectified:
+ yn = true;
+ break;
+
+ default:
+ yn = false;
+ break;
+ }
+
+ if (yn != (bool) (_flags & WaveformRectified)) {
+ for (vector<WaveView *>::iterator wave = waves.begin(); wave != waves.end() ; ++wave) {
+ (*wave)->property_rectified() = yn;
+ }
+
+ if (zero_line) {
+ if (yn) {
+ zero_line->hide();
+ } else {
+ zero_line->show();
+ }
+ }
+
+ if (yn) {
+ _flags |= WaveformRectified;
+ } else {
+ _flags &= ~WaveformRectified;
+ }
+ }
+}
+
+void
+AudioRegionView::move (double x_delta, double y_delta)
+{
+ if (region.locked() || (x_delta == 0 && y_delta == 0)) {
+ 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() = ®ion;
+ wave->property_cache() = wave_caches[n];
+ wave->property_cache_updater() = false;
+ wave->property_channel() = n;
+ wave->property_length_function() = (gpointer)region_length_from_c;
+ wave->property_sourcefile_length_function() = (gpointer) sourcefile_length_from_c;
+ wave->property_peak_function() = (gpointer) region_read_peaks_from_c;
+ wave->property_x() = 0.0;
+ wave->property_samples_per_unit() = samples_per_unit;
+ wave->property_amplitude_above_axis() = _amplitude_above_axis;
+ wave->property_wave_color() = color_map[cGhostTrackWave];
+ wave->property_region_start() = region.start();
+
+ ghost->waves.push_back(wave);
+ }
+
+ ghost->set_height ();
+ ghost->set_duration (region.length() / samples_per_unit);
+ ghosts.push_back (ghost);
+
+ ghost->GoingAway.connect (mem_fun(*this, &AudioRegionView::remove_ghost));
+
+ return ghost;
+}
+
+void
+AudioRegionView::remove_ghost (GhostRegion* ghost)
+{
+ 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() = ®ion;
+ }
+
+ for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
+
+ (*i)->set_duration (unit_length);
+
+ for (vector<WaveView*>::iterator w = (*i)->waves.begin(); w != (*i)->waves.end(); ++w) {
+ (*w)->property_data_src() = ®ion;
+ }
+ }
+
+}
+
+void
+AudioRegionView::color_handler (ColorID id, uint32_t val)
+{
+ switch (id) {
+ case cMutedWaveForm:
+ case cWaveForm:
+ set_colors ();
+ break;
+
+ case cGainLineInactive:
+ case cGainLine:
+ envelope_active_changed();
+ break;
+
+ case cZeroLine:
+ if (zero_line) {
+ zero_line->property_color_rgba() = (guint) color_map[cZeroLine];
+ }
+ break;
+
+ case cGhostTrackWave:
+ break;
+
+ default:
+ break;
+ }
+}
--- /dev/null
+/*
+ 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;
+ }
+}
--- /dev/null
+/*
+ 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__ */
/*
- 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
#include <cstdlib>
#include <cmath>
+#include <cassert>
#include <algorithm>
#include <string>
#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 ();
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
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)
{
}
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"),
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");
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 ()
_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 ()
{
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;
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;
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()) {
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;
-}
/*
- 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
$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;
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 ();
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__ */
class PublicEditor;
class TimeSelection;
-class AudioRegionSelection;
+class RegionSelection;
class PointSelection;
class AutomationLine;
class GhostRegion;
#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"
sigc::signal<void,CrossfadeView*> CrossfadeView::GoingAway;
CrossfadeView::CrossfadeView (ArdourCanvas::Group *parent,
- AudioTimeAxisView &tv,
+ RouteTimeAxisView &tv,
Crossfade& xf,
double spu,
Gdk::Color& basic_color,
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;
#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,
#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"
static const int32_t splice_index = 1;
static const gchar *edit_mode_strings[] = {
- N_("Slide"),
- N_("Splice"),
+ N_("Slide Edit"),
+ N_("Splice Edit"),
0
};
};
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
};
/* 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)
{
reset_hscrollbar_stepping ();
zoom_focus = ZoomFocusLeft;
+ set_zoom_focus (ZoomFocusLeft);
zoom_range_clock.ValueChanged.connect (mem_fun(*this, &Editor::zoom_adjustment_changed));
initialize_rulers ();
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);
_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");
}
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.
}
void
-Editor::set_entered_regionview (AudioRegionView* rv)
+Editor::set_entered_regionview (RegionView* rv)
{
if (rv == entered_regionview) {
return;
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)));
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);
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)));
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)));
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:
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 {
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;
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;
}
AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
if (atv) {
- AudioDiskstream* ds;
+ Diskstream* ds;
Playlist* pl;
AudioPlaylist* apl;
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;
}
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);
}
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);
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),
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);
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");
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);
}
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);
}
}
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) {
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);
}
}
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;
/* 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;
}
}
}
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);
}
}
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;
}
a single other region.
*/
- if (selection->audio_regions.size() > 1) {
+ if (selection->regions.size() > 1) {
return TRUE;
}
if (sscanf (text.c_str(), "%f", ×) == 1) {
if (dup_region) {
- AudioRegionSelection regions;
+ RegionSelection regions;
regions.add (clicked_regionview);
duplicate_some_regions (regions, times);
} else {
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;
}
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;
snaptype = SnapToSeconds;
} else if (choice == _("Minutes")) {
snaptype = SnapToMinutes;
- } else if (choice == _("None")) {
+ } else if (choice == _("None")) {
snaptype = SnapToFrame;
}
-
+
set_snap_to (snaptype);
}
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;
}
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;
}
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);
}
}
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;
}
}
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 ();
}
class AudioDiskstream;
class RouteGroup;
class Playlist;
+ class AudioPlaylist;
class Region;
class Location;
class TempoSection;
}
class TimeAxisView;
+class RouteTimeAxisView;
class AudioTimeAxisView;
class AutomationTimeAxisView;
class AudioRegionView;
class AutomationSelection;
class MixerStrip;
class StreamView;
+class AudioStreamView;
class ControlPoint;
#ifdef FFT_ANALYSIS
class AnalysisWindow;
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;
/* 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);
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);
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;
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;
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 ();
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 ();
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);
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);
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*);
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;
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;
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();
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 ();
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 ();
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 ();
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;
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 */
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);
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;
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"));
{
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;
}
{
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;
}
}
#include "editor.h"
#include "editing.h"
#include "audio_time_axis.h"
-#include "regionview.h"
+#include "region_view.h"
#include "selection.h"
using namespace ARDOUR;
#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"
}
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;
}
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;
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;
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);
+ }
+ }
}
}
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;
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:
}
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;
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:
#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>
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();
}
}
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;
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;
}
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;
{
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);
}
}
TempoMarkerItem,
MeterBarItem,
TempoBarItem,
- AudioRegionViewNameHighlight,
- AudioRegionViewName,
+ RegionViewNameHighlight,
+ RegionViewName,
StartSelectionTrimItem,
EndSelectionTrimItem,
AutomationTrackItem,
#include <ardour/playlist.h>
#include "editor.h"
-#include "regionview.h"
+#include "region_view.h"
#include "selection.h"
#include "i18n.h"
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);
}
{
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();
}
}
snap_to (where);
if (entered_regionview) {
- set_a_regions_sync_position (entered_regionview->region, where);
+ set_a_regions_sync_position (entered_regionview->region(), where);
}
}
#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"
void
Editor::keyboard_duplicate_region ()
{
- if (selection->audio_regions.empty()) {
+ if (selection->regions.empty()) {
return;
}
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);
}
}
}
}
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());
}
}
}
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);
$Id$
*/
+#include <cassert>
#include <cstdlib>
#include <stdint.h>
#include <cmath>
#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"
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) {
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);
}
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;
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;
edit_meter_marker (item);
break;
- case AudioRegionViewName:
+ case RegionViewName:
if (clicked_regionview->name_active()) {
return mouse_rename_region (item, event);
}
break;
case RegionItem:
- case AudioRegionViewNameHighlight:
- case AudioRegionViewName:
+ case RegionViewNameHighlight:
+ case RegionViewName:
popup_track_context_menu (1, event->button.time, item_type, false, where);
break;
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;
}
break;
- case AudioRegionViewNameHighlight:
+ case RegionViewNameHighlight:
if (is_drawable() && mouse_mode == MouseObject) {
track_canvas.get_window()->set_cursor (*trimmer_cursor);
}
}
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);
}
ControlPoint* cp;
Marker *marker;
Location *loc;
- AudioRegionView* rv;
+ RegionView* rv;
bool is_start;
switch (item_type) {
hide_verbose_canvas_cursor ();
break;
- case AudioRegionViewNameHighlight:
+ case RegionViewNameHighlight:
case StartSelectionTrimItem:
case EndSelectionTrimItem:
case EditCursorItem:
}
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);
}
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) {
case PanAutomationControlPointItem:
case TempoMarkerItem:
case MeterMarkerItem:
- case AudioRegionViewNameHighlight:
+ case RegionViewNameHighlight:
case StartSelectionTrimItem:
case EndSelectionTrimItem:
case SelectionItem:
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
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;
}
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);
}
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
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;
}
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);
{
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;
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;
}
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
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;
}
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()) {
}
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;
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;
}
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
{
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
/* 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) {
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 ();
}
}
- 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 */
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.
*/
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;
}
}
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);
************************************************************/
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;
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) {
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 */
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;
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);
/* 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,
/* 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;
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
/* 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;
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 ();
/* 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;
}
} 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);
}
}
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));
}
}
}
}
void
-Editor::collect_new_region_view (AudioRegionView* rv)
+Editor::collect_new_region_view (RegionView* rv)
{
latest_regionview = rv;
}
*/
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.
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);
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();
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());
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()) {
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());
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;
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);
}
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);
}
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;
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();
}
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;
}
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;
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);
}
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())) {
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());
}
}
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());
}
}
}
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;
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
}
} else {
- selection->clear_audio_regions();
+ selection->clear_regions();
selection->clear_points ();
selection->clear_lines ();
}
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 ();
string str;
prompter.get_result(str);
if (str.length()) {
- clicked_regionview->region.set_name (str);
+ clicked_regionview->region().set_name (str);
}
break;
}
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);
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;
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 */
/* 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;
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
#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"
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());
}
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 ();
}
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;
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;
}
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);
}
}
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);
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);
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);
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());
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;
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;
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"));
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());
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 {
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
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);
}
}
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
Button ok_button (_("OK"));
Button cancel_button (_("Cancel"));
- if (selection->audio_regions.empty()) {
+ if (selection->regions.empty()) {
return;
}
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 ();
}
}
}
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 ();
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);
}
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;
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);
{
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 */
}
{
jack_nframes_t end;
- if (!session || selection->audio_regions.empty()) {
+ if (!session || selection->regions.empty()) {
return;
}
begin_reversible_command (_("region fill"));
- for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
+ for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
+
+ Region& region ((*i)->region());
+
+ // FIXME
+ AudioRegion* const ar = dynamic_cast<AudioRegion*>(®ion);
+ if (!ar)
+ continue;
- AudioRegion& region ((*i)->region);
Playlist* pl = region.playlist();
if (end <= region.last_frame()) {
}
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());
}
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);
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 ();
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 ();
}
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;
}
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:
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());
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 ();
return;
}
- Region& region (clicked_regionview->region);
+ Region& region (clicked_regionview->region());
float speed = 1.0f;
AudioTimeAxisView *atav;
return;
}
- Region& region (clicked_regionview->region);
+ Region& region (clicked_regionview->region());
float speed = 1.0f;
AudioTimeAxisView *atav;
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 ();
}
}
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) {
}
}
- 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;
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;
}
}
}
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());
return;
}
- if (selection->audio_regions.empty()) {
+ if (selection->regions.empty()) {
return;
}
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 ();
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 ();
void
Editor::apply_filter (AudioFilter& filter, string command)
{
- if (selection->audio_regions.empty()) {
+ if (selection->regions.empty()) {
return;
}
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;
}
commit_reversible_command ();
- selection->audio_regions.clear ();
+ selection->regions.clear ();
out:
track_canvas.get_window()->set_cursor (*current_canvas_cursor);
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)();
}
}
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);
}
}
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);
}
}
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);
}
}
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;
#include "editor.h"
#include "audio_time_axis.h"
-#include "regionview.h"
+#include "audio_region_view.h"
#include "region_selection.h"
#include <ardour/session.h>
}
int
-Editor::run_timestretch (AudioRegionSelection& regions, float fraction)
+Editor::run_timestretch (RegionSelection& regions, float fraction)
{
pthread_t thread;
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 = ®ion;
if (!dialog.request.running) {
/* we were cancelled */
}
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;
*/
+#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();
}
class ExportRegionDialog : public ExportDialog
{
public:
- ExportRegionDialog (PublicEditor&, ARDOUR::AudioRegion*);
+ ExportRegionDialog (PublicEditor&, ARDOUR::Region*);
static void* _export_region_thread (void *);
void export_region ();
_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));
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)));
}
}
-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 ()
{
}
void
-MixerStrip::diskstream_changed (void *src)
+MixerStrip::diskstream_changed ()
{
Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &MixerStrip::update_diskstream_display));
}
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");
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 ();
--- /dev/null
+/* XPM */
+static char * tool_audition_xpm[] = {
+"16 12 4 1",
+" c None",
+". c #000000",
+"+ c #ECECEC",
+"@ c #FFFFFF",
+" .. ",
+" .+. . ",
+" .++. .@. ",
+"....+@+... .@. ",
+".+++@@+..@. .@.",
+".+@@@@+. .@. .@.",
+".+@@@@+. .@. .@.",
+".+++@@+..@. .@.",
+"....+@+... .@. ",
+" .++. .@. ",
+" .+. . ",
+" .. "};
--- /dev/null
+/* XPM */
+static char * tool_gain_xpm[] = {
+"16 12 3 1",
+" c None",
+". c #000000",
+"+ c #FFFFFF",
+"... ",
+".++.. ",
+"...++. ",
+" ..+. ",
+" .+. ",
+" .+. ",
+" .+. ",
+" .+. ",
+" .+.. ",
+" .++.....",
+" ..++++.",
+" ....."};
--- /dev/null
+/* XPM */
+static char * tool_object_xpm[] = {
+"16 12 3 1",
+" c None",
+". c #000000",
+"+ c #FFFFFF",
+" ... ",
+" .+. ",
+" .+. ",
+" .+. ",
+" .+..... ",
+" .+.+.+... ",
+" ...+.+.+.+. ",
+" .+.+++++++. ",
+" .+++++++++. ",
+" ..+++++++.. ",
+" ...+++++. ",
+" .+++++. "};
--- /dev/null
+/* XPM */
+static char * tool_range_xpm[] = {
+"16 12 3 1",
+" c None",
+". c #000000",
+"+ c #FFFFFF",
+"... ...",
+".+. .. .. .+.",
+".+. .+. .+. .+.",
+".+..+. .+..+.",
+".+.++......++.+.",
+".++++++++++++++.",
+".+.++......++.+.",
+".+..+. .+..+.",
+".+. .+. .+. .+.",
+".+. .. .. .+.",
+".+. .+.",
+"... ..."};
--- /dev/null
+/* XPM */
+static char * tool_stretch_xpm[] = {
+"16 12 3 1",
+" c None",
+". c #000000",
+"+ c #FFFFFF",
+" .. .. ",
+" .+. .+. ",
+".++..........++.",
+"++++++++++++++++",
+".++..........++.",
+" .+. .+. ",
+" .. .. ",
+" + + + + ",
+" ++ +++ + + +++ ",
+"++++++++++++++++",
+" ++ + ++ + + ",
+" + + + + "};
--- /dev/null
+/* 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",
+" ... ",
+" +.@#$.+ ",
+" .%%%%%. ",
+" .&%%%%%*. ",
+" .#%%%%%#. ",
+" .$%%%%%&. ",
+" .%%%%%.+ ",
+" +.*#=... ",
+" ...+... ",
+" -.; ",
+" >.- ",
+" ,. "};
--- /dev/null
+/* 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",
+" ... ",
+" +.@#$.+ ",
+" .%&&&%. ",
+".*..&..=. ",
+".#.&&&.#. ",
+".$..&..*. ",
+" .%&&&%.+ ",
+" +.=#-... ",
+" ...+... ",
+" ;.> ",
+" ,.;",
+" '."};
--- /dev/null
+/* 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",
+" ... ",
+" +.@#$.+ ",
+" .%%.%%. ",
+".&%%.%%*. ",
+".#.....#. ",
+".$%%.%%&. ",
+" .%%.%%.+ ",
+" +.*#=... ",
+" ...+... ",
+" -.; ",
+" >.-",
+" ,."};
--- /dev/null
+/* 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",
+" ... ",
+" +.@#$.+ ",
+" .%%%%%. ",
+".&%%%%%*. ",
+".#.....#. ",
+".$%%%%%&. ",
+" .%%%%%.+ ",
+" +.*#=... ",
+" ...+... ",
+" -.; ",
+" >.-",
+" ,."};
PlaylistSelector::show_for (RouteUI* ruix)
{
vector<const char*> item;
- AudioDiskstream* this_ds;
+ Diskstream* this_ds;
string str;
rui = 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;
return;
}
- at->disk_stream().use_playlist (apl);
+ at->diskstream().use_playlist (apl);
hide ();
}
class Session;
class PluginManager;
class Plugin;
+ class PluginInfo;
}
class PluginSelector : public ArdourDialog
class ControlPoint;
class SelectionRect;
class CrossfadeView;
-class AudioTimeAxisView;
+class RouteTimeAxisView;
class AudioRegionView;
class TempoMarker;
class MeterMarker;
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;
+++ /dev/null
-/*
- 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);
- }
-}
-
+++ /dev/null
-/*
- 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__ */
#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"
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) );
}
}
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);
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);
}
+/*
+ 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;
bool
-AudioRegionComparator::operator() (const AudioRegionView* a, const AudioRegionView* b) const
+RegionComparator::operator() (const RegionView* a, const RegionView* b) const
{
if (a == b) {
return false;
}
}
-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;
-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);
}
}
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;
}
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);
}
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()) {
} else {
- AudioRegion& region ((*i)->region);
+ Region& region ((*i)->region());
if (region.first_frame() == _current_start) {
}
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;
}
}
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) {
+/*
+ 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();
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__ */
--- /dev/null
+/*
+ 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;
+}
+
--- /dev/null
+/*
+ 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__ */
+++ /dev/null
-/*
- 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() = ®ion;
- }
-}
-
-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) ®ion;
- wave->property_cache() = wave_caches[which];
- wave->property_cache_updater() = true;
- wave->property_channel() = which;
- wave->property_length_function() = (gpointer) region_length_from_c;
- wave->property_sourcefile_length_function() = (gpointer) sourcefile_length_from_c;
- wave->property_peak_function() = (gpointer) region_read_peaks_from_c;
- wave->property_x() = 0.0;
- wave->property_y() = yoff;
- wave->property_height() = (double) ht;
- wave->property_samples_per_unit() = samples_per_unit;
- wave->property_amplitude_above_axis() = _amplitude_above_axis;
- wave->property_wave_color() = region.muted() ? color_map[cMutedWaveForm] : color_map[cWaveForm];
- wave->property_region_start() = region.start();
-
- if (!(_flags & WaveformVisible)) {
- wave->hide();
- }
-
- /* note: calling this function is serialized by the lock
- held in the peak building thread that signals that
- peaks are ready for use *or* by the fact that it is
- called one by one from the GUI thread.
- */
-
- if (which < nchans) {
- tmp_waves[which] = wave;
- } else {
- /* n-channel track, >n-channel source */
- }
-
- /* see if we're all ready */
-
- for (n = 0; n < nchans; ++n) {
- if (tmp_waves[n] == 0) {
- break;
- }
- }
-
- if (n == nwaves && waves.empty()) {
- /* all waves are ready */
- tmp_waves.resize(nwaves);
-
- waves = tmp_waves;
- tmp_waves.clear ();
-
- if (!zero_line) {
- zero_line = new ArdourCanvas::SimpleLine (*group);
- zero_line->property_x1() = (gdouble) 1.0;
- zero_line->property_x2() = (gdouble) (region.length() / samples_per_unit) - 1.0;
- zero_line->property_color_rgba() = (guint) color_map[cZeroLine];
- manage_zero_line ();
- }
- }
-}
-
-void
-AudioRegionView::peaks_ready_handler (uint32_t which)
-{
- Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &AudioRegionView::create_one_wave), which, false));
-
- if (!waves.empty()) {
- /* all waves created, don't hook into peaks ready anymore */
- peaks_ready_connection.disconnect ();
- }
-}
-
-void
-AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev)
-{
- if (gain_line == 0) {
- return;
- }
-
- double x, y;
-
- /* don't create points that can't be seen */
-
- set_envelope_visible (true);
-
- x = ev->button.x;
- y = ev->button.y;
-
- item->w2i (x, y);
-
- jack_nframes_t fx = trackview.editor.pixel_to_frame (x);
-
- if (fx > region.length()) {
- return;
- }
-
- /* compute vertical fractional position */
-
- y = 1.0 - (y / (trackview.height - NAME_HIGHLIGHT_SIZE));
-
- /* map using gain line */
-
- gain_line->view_to_model_y (y);
-
- trackview.session().begin_reversible_command (_("add gain control point"));
- trackview.session().add_undo (region.envelope().get_memento());
-
-
- if (!region.envelope_active()) {
- trackview.session().add_undo( bind( mem_fun(region, &AudioRegion::set_envelope_active), false) );
- region.set_envelope_active(true);
- trackview.session().add_redo( bind( mem_fun(region, &AudioRegion::set_envelope_active), true) );
- }
-
- region.envelope().add (fx, y);
-
- trackview.session().add_redo_no_execute (region.envelope().get_memento());
- trackview.session().commit_reversible_command ();
-}
-
-void
-AudioRegionView::remove_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev)
-{
- ControlPoint *cp = reinterpret_cast<ControlPoint *> (item->get_data ("control_point"));
- region.envelope().erase (cp->model);
-}
-
-void
-AudioRegionView::store_flags()
-{
- XMLNode *node = new XMLNode ("GUI");
-
- node->add_property ("waveform-visible", (_flags & WaveformVisible) ? "yes" : "no");
- node->add_property ("envelope-visible", (_flags & EnvelopeVisible) ? "yes" : "no");
-
- region.add_extra_xml (*node);
-}
-
-void
-AudioRegionView::set_flags (XMLNode* node)
-{
- XMLProperty *prop;
-
- if ((prop = node->property ("waveform-visible")) != 0) {
- if (prop->value() == "yes") {
- _flags |= WaveformVisible;
- }
- }
-
- if ((prop = node->property ("envelope-visible")) != 0) {
- if (prop->value() == "yes") {
- _flags |= EnvelopeVisible;
- }
- }
-}
-
-void
-AudioRegionView::set_waveform_shape (WaveformShape shape)
-{
- bool yn;
-
- /* this slightly odd approach is to leave the door open to
- other "shapes" such as spectral displays, etc.
- */
-
- switch (shape) {
- case Rectified:
- yn = true;
- break;
-
- default:
- yn = false;
- break;
- }
-
- if (yn != (bool) (_flags & WaveformRectified)) {
- for (vector<WaveView *>::iterator wave = waves.begin(); wave != waves.end() ; ++wave) {
- (*wave)->property_rectified() = yn;
- }
-
- if (zero_line) {
- if (yn) {
- zero_line->hide();
- } else {
- zero_line->show();
- }
- }
-
- if (yn) {
- _flags |= WaveformRectified;
- } else {
- _flags &= ~WaveformRectified;
- }
- }
-}
-
-void
-AudioRegionView::move (double x_delta, double y_delta)
-{
- if (region.locked() || (x_delta == 0 && y_delta == 0)) {
- 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() = ®ion;
- wave->property_cache() = wave_caches[n];
- wave->property_cache_updater() = false;
- wave->property_channel() = n;
- wave->property_length_function() = (gpointer)region_length_from_c;
- wave->property_sourcefile_length_function() = (gpointer) sourcefile_length_from_c;
- wave->property_peak_function() = (gpointer) region_read_peaks_from_c;
- wave->property_x() = 0.0;
- wave->property_samples_per_unit() = samples_per_unit;
- wave->property_amplitude_above_axis() = _amplitude_above_axis;
- wave->property_wave_color() = color_map[cGhostTrackWave];
- wave->property_region_start() = region.start();
-
- ghost->waves.push_back(wave);
- }
-
- ghost->set_height ();
- ghost->set_duration (region.length() / samples_per_unit);
- ghosts.push_back (ghost);
-
- ghost->GoingAway.connect (mem_fun(*this, &AudioRegionView::remove_ghost));
-
- return ghost;
-}
-
-void
-AudioRegionView::remove_ghost (GhostRegion* ghost)
-{
- 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() = ®ion;
- }
-
- for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
-
- (*i)->set_duration (unit_length);
-
- for (vector<WaveView*>::iterator w = (*i)->waves.begin(); w != (*i)->waves.end(); ++w) {
- (*w)->property_data_src() = ®ion;
- }
- }
-
-}
-
-void
-AudioRegionView::color_handler (ColorID id, uint32_t val)
-{
- switch (id) {
- case cMutedWaveForm:
- case cWaveForm:
- set_colors ();
- break;
-
- case cGainLineInactive:
- case cGainLine:
- envelope_active_changed();
- break;
-
- case cZeroLine:
- if (zero_line) {
- zero_line->property_color_rgba() = (guint) color_map[cZeroLine];
- }
- break;
-
- case cGhostTrackWave:
- break;
-
- default:
- break;
- }
-}
+++ /dev/null
-/*
- 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__ */
--- /dev/null
+/*
+ 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();
+ }
+}
+
--- /dev/null
+/*
+ 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__ */
+
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);
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
}
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));
}
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());
}
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*
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
{
}
}
}
+
#include <pbd/xml++.h>
#include <ardour/ardour.h>
#include <ardour/route.h>
+#include <ardour/track.h>
#include "axis_view.h"
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;
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);
#include <ardour/playlist.h>
-#include "regionview.h"
+#include "region_view.h"
#include "selection.h"
#include "selection_templates.h"
#include "time_axis_view.h"
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;
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 &&
Selection::clear ()
{
clear_tracks ();
- clear_audio_regions ();
+ clear_regions ();
clear_points ();
clear_lines();
clear_time ();
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;
}
}
}
void
-Selection::clear_audio_regions ()
+Selection::clear_regions ()
{
- if (!audio_regions.empty()) {
- audio_regions.clear_all ();
+ if (!regions.empty()) {
+ regions.clear_all ();
RegionsChanged();
}
}
}
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);
}
}
}
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;
}
}
}
void
-Selection::remove (AudioRegionView* r)
+Selection::remove (RegionView* r)
{
- audio_regions.remove (r);
+ regions.remove (r);
RegionsChanged ();
}
}
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);
}
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 () &&
void
Selection::set (list<Selectable*>& selectables)
{
- clear_audio_regions();
+ clear_regions();
clear_points ();
add (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 {
}
}
- if (!arvs.empty()) {
- add (arvs);
+ if (!rvs.empty()) {
+ add (rvs);
}
if (!autos.empty()) {
#include "point_selection.h"
class TimeAxisView;
-class AudioRegionView;
+class RegionView;
class Selectable;
namespace ARDOUR {
};
TrackSelection tracks;
- AudioRegionSelection audio_regions;
+ RegionSelection regions;
TimeSelection time;
AutomationSelection lines;
PlaylistSelection playlists;
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*);
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*);
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*);
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*);
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 ();
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;
*/
#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);
}
}
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);
}
}
+/*
+ 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"
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 */
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));
}
void
StreamView::attach ()
{
- if (_trackview.is_audio_track()) {
+ if (_trackview.is_track()) {
display_diskstream (_trackview.get_diskstream());
}
}
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);
int
StreamView::set_samples_per_unit (gdouble spp)
{
- AudioRegionViewList::iterator i;
+ RegionViewList::iterator i;
if (spp < 1.0) {
return -1;
(*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);
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
/*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;
}
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);
{
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));
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
}
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 {
StreamView::apply_color (Gdk::Color& color, ColorTarget target)
{
- list<AudioRegionView *>::iterator i;
+ list<RegionView *>::iterator i;
switch (target) {
case RegionColor:
}
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();
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));
}
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 ()
{
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);
}
}
-AudioRegionView*
-StreamView::find_view (const AudioRegion& region)
+RegionView*
+StreamView::find_view (const Region& region)
{
- for (list<AudioRegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
+ for (list<RegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
- if (&(*i)->region == ®ion) {
+ if (&(*i)->region() == ®ion) {
return *i;
}
}
}
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;
- }
-}
/*
- 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
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__
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__ */
+
--- /dev/null
+/*
+ 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 ();
+}
--- /dev/null
+/*
+ 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__ */
+++ /dev/null
-/*
- 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() = ®ion;
-}
-
-void
-TapeAudioRegionView::set_frame_color ()
-{
- fill_opacity = 255;
- TimeAxisViewItem::set_frame_color ();
-}
+++ /dev/null
-/*
- 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__ */
}
class PublicEditor;
-class AudioRegionSelection;
+class RegionSelection;
class TimeSelection;
class PointSelection;
class TimeAxisViewItem;
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) {
}
void
-VisualTimeAxis::set_selected_regionviews (AudioRegionSelection& regions)
+VisualTimeAxis::set_selected_regionviews (RegionSelection& regions)
{
// Not handled by purely visual TimeAxis
}
class ImageFrameTimeAxisView;
class MarkersTimeAxisView;
class TimeSelection;
-class AudioRegionSelection;
+class RegionSelection;
class MarkerTimeAxis;
class TimeAxisViewStrip;
/**
* Not implemented
*/
- virtual void set_selected_regionviews(AudioRegionSelection&) ;
+ virtual void set_selected_regionviews(RegionSelection&) ;
//---------------------------------------------------------------------------------//
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
/*
- 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>
#include <ardour/route.h>
#include <ardour/port.h>
#include <ardour/utils.h>
+#include <ardour/diskstream.h>
+#include <ardour/audioplaylist.h>
struct tm;
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() : "";
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;
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;
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;
}
}
- 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;
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);
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);
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;
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 ();
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__ */
#ifndef __ardour_audio_track_h__
#define __ardour_audio_track_h__
-#include <ardour/route.h>
+#include <ardour/track.h>
namespace ARDOUR {
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,
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
#include <ardour/ardour.h>
#include <jack/jack.h>
#include <jack/transport.h>
+#include <ardour/types.h>
namespace ARDOUR {
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);
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:
#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;
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
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;
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))); }
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);
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 */
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 ();
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,
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 */
--- /dev/null
+/*
+ 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__
--- /dev/null
+/*
+ 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__ */
#include <ardour/utils.h>
#include <ardour/state_manager.h>
#include <ardour/curve.h>
+#include <ardour/types.h>
using std::string;
using std::vector;
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
{
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();
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; }
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);
PBD::ID _id;
bool no_panner_reset;
XMLNode* deferred_state;
+ DataType _default_type;
virtual void set_deferred_state() {}
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;
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);
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;
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() {
}
std::string short_name() {
- return jack_port_short_name (port);
+ return jack_port_short_name (_port);
}
int set_name (std::string str);
}
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 {
}
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 () {
}
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);
}
bool monitoring_input () const {
- return jack_port_monitoring_input (port);
+ return jack_port_monitoring_input (_port);
}
bool can_monitor () const {
}
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
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:
/* engine isn't supposed to below here */
- Sample *_buffer;
+ Sample *_buffer;
/* cache these 3 from JACK so that we can
access them for reconnecting.
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
#include <pbd/undo.h>
#include <ardour/ardour.h>
-#include <ardour/logcurve.h>
#include <ardour/state_manager.h>
class XMLNode;
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
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; }
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;
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); };
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 */
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; }
/* 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;
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 */
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 */
#include <ardour/io.h>
#include <ardour/session.h>
#include <ardour/redirect.h>
+#include <ardour/types.h>
namespace ARDOUR {
};
- 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();
namespace ARDOUR {
class Route;
+class Track;
class AudioTrack;
class Session;
/* 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 */
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);
}
}
class Port;
class AudioEngine;
class Slave;
+class Diskstream;
class AudioDiskstream;
class Route;
class AuxInput;
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;
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;
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);
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&);
void resort_routes ();
void resort_routes_using (boost::shared_ptr<RouteList>);
- void resort_routes_proxy (void* src) {
- resort_routes ();
- }
AudioEngine &engine() { return _engine; };
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);
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 *));
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;
void set_frame_rate (jack_nframes_t nframes);
protected:
- friend class AudioDiskstream;
+ friend class Diskstream;
void stop_butler ();
void wait_till_butler_finished();
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 ();
/* 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 */
Playlist *XMLPlaylistFactory (const XMLNode&);
void playlist_length_changed (Playlist *);
- void diskstream_playlist_changed (AudioDiskstream *);
+ void diskstream_playlist_changed (Diskstream *);
/* NAMED SELECTIONS */
+++ /dev/null
-/*
- 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__ */
--- /dev/null
+/*
+ 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__ */
PeakDatum min;
PeakDatum max;
};
+
+ enum DataType {
+ NIL = 0,
+ AUDIO,
+ MIDI
+ };
}
std::istream& operator>>(std::istream& o, ARDOUR::SampleFormat& sf);
/*
- 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
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 <unistd.h>
#include <cmath>
#include <cerrno>
+#include <cassert>
#include <string>
#include <climits>
#include <fcntl.h>
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);
use_destructive_playlist ();
}
- AudioDiskstreamCreated (this); /* EMIT SIGNAL */
+ DiskstreamCreated (this); /* EMIT SIGNAL */
}
void
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
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
{
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
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) {
}
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 ()
{
int
AudioDiskstream::use_copy_playlist ()
{
+ assert(audio_playlist());
+
if (destructive()) {
return 0;
}
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 {
for (n = 0, chan = channels.begin(); chan != channels.end(); ++chan, ++n) {
(*chan).write_source = dynamic_cast<AudioFileSource*>(®ion->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)
{
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;
}
return ret;
}
-void
-AudioDiskstream::recover ()
-{
- state_lock.unlock();
- _processed = false;
-}
-
bool
AudioDiskstream::commit (jack_nframes_t nframes)
{
/* 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;
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;
}
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;
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) {
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;
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;
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.
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)
{
ChannelList::iterator chan;
vector<CaptureInfo*>::iterator ci;
uint32_t n = 0;
- list<AudioFileSource*>* deletion_list;
bool mark_write_completed = false;
finish_capture (true);
*/
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;
ChannelList::iterator chan;
- deletion_list = new list<AudioFileSource*>;
+ list<Source*>* deletion_list = new list<Source*>;
for ( chan = channels.begin(); chan != channels.end(); ++chan) {
}
void
-AudioDiskstream::set_record_enabled (bool yn, void* src)
+AudioDiskstream::set_record_enabled (bool yn)
{
if (!recordable() || !_session.record_enabling_legal()) {
return;
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 ();
}
}
- 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()) {
}
}
capturing_sources.clear ();
- record_enable_changed (src); /* EMIT SIGNAL */
+ RecordEnableChanged (); /* EMIT SIGNAL */
}
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);
}
// 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) {
}
}
-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 ()
{
}
}
-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 ()
{
(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)
{
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;
- }
- }
-}
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
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)
{
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);
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);
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));
}
}
- 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;
}
{
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;
}
{
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
return 0;
}
-XMLNode&
-AudioTrack::get_template ()
-{
- return state (false);
-}
-
-XMLNode&
-AudioTrack::get_state ()
-{
- return state (true);
-}
-
XMLNode&
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;
diskstream.
*/
- diskstream->id().print (buf);
+ _diskstream->id().print (buf);
root.add_property ("diskstream-id", buf);
return root;
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);
}
}
}
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
return 0;
}
- diskstream->check_record_status (start_frame, nframes, can_record);
+ audio_diskstream().check_record_status (start_frame, nframes, can_record);
bool send_silence;
send_silence = true;
}
} else {
- if (diskstream->record_enabled()) {
+ if (_diskstream->record_enabled()) {
if (Config->get_use_sw_monitoring()) {
send_silence = false;
} else {
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()) {
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);
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)
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()
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;
}
/* 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()) {
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
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;
}
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);
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)
{
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;
}
}
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;
(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 */
AudioTrack::unfreeze ()
{
if (_freeze_record.playlist) {
- diskstream->use_playlist (_freeze_record.playlist);
+ audio_diskstream().use_playlist (_freeze_record.playlist);
if (_freeze_record.have_mementos) {
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();
- }
- }
-}
#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>
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)
{
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 ...
*/
}
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) {
}
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;
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;
return 0;
}
+
int
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) {
}
}
- int ret = jack_port_disconnect (_jack, port->port);
+ int ret = jack_port_disconnect (_jack, port->_port);
if (ret == 0) {
remove_connections_for (port);
}
string
-
AudioEngine::get_nth_physical (uint32_t n, int flag)
{
const char ** ports;
}
}
- return jack_port_get_total_latency (_jack, port.port);
+ return jack_port_get_total_latency (_jack, port._port);
}
void
if (_jack) {
for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) {
- jack_port_unregister (_jack, (*i)->port);
+ jack_port_unregister (_jack, (*i)->_port);
}
}
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 {
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;
}
/* 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),
return to_read;
}
-XMLNode&
-AudioRegion::get_state ()
-{
- return state (true);
-}
-
XMLNode&
AudioRegion::state (bool full)
{
}
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;
}
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)
{
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 ();
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
}
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);
}
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);
}
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) {
--- /dev/null
+/*
+ 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;
+ }
+ }
+}
}
+/** @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),
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());
/* 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;
}
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());
/* 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;
}
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());
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;
}
out_changed = true;
}
- /* create any necessary new ports */
+ /* create any necessary new ports (of the default type) */
while (_ninputs < nin) {
}
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;
}
}
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;
}
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;
}
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)
{
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 ();
}
{
reset_buffer ();
- last_monitor = false;
- silent = false;
- metering = 0;
+ _last_monitor = false;
+ _silent = false;
+ _metering = 0;
reset_meters ();
}
{
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;
}
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;
{
_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;
+}
#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>
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)
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");
} 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);
delete [] (i->second);
}
+ AudioDiskstream::free_working_buffers();
+
#undef TRACK_DESTRUCTION
#ifdef TRACK_DESTRUCTION
cerr << "delete named selections\n";
}
#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;
}
void
-Session::diskstream_playlist_changed (AudioDiskstream* dstream)
+Session::diskstream_playlist_changed (Diskstream* dstream)
{
Playlist *playlist;
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);
{
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);
}
} 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());
}
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;
*/
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);
}
*/
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);
}
*/
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);
(*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);
}
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);
} 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"),
}
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);
}
}
}
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
set_dirty();
save_state (_current_snapshot_name);
- AudioDiskstreamAdded (dstream); /* EMIT SIGNAL */
+ DiskstreamAdded (dstream); /* EMIT SIGNAL */
}
void
/* 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 ();
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;
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;
}
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;
}
}
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
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()) {
/* 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)
{
}
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
}
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++;
}
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 ()
{
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 ();
}
}
//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);
}
}
/* call tree *MUST* hold route_lock */
- if ((playlist = track.disk_stream().playlist()) == 0) {
+ if ((playlist = track.diskstream().playlist()) == 0) {
goto out;
}
goto out;
}
- nchans = track.disk_stream().n_channels();
+ nchans = track.audio_diskstream().n_channels();
dir = discover_best_sound_dir ();
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;
}
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) {
}
}
}
-
- 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 ();
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;
}
- if (i != audio_diskstreams.end()) {
+ if (i != diskstreams.end()) {
/* we didn't get to all the streams */
disk_work_outstanding = true;
}
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;
request_stop ();
}
- if (i != audio_diskstreams.end()) {
+ if (i != diskstreams.end()) {
/* we didn't get to all the streams */
disk_work_outstanding = true;
}
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;
// }
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;
}
} 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);
}
}
{
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)
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 ();
}
}
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 ();
}
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 ();
}
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;
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;
}
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;
/* 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 */
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));
{
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());
}
}
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);
}
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 ();
}
}
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()));
{
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 ();
}
}
{
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 ();
}
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;
_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);
}
}
#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()));
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);
}
}
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);
}
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);
}
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);
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);
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);
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);
_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);
}
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);
}
_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;
}
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);
/* 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 ();
}
}
--- /dev/null
+/*
+ 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);
+}
+