Heavy-duty abstraction work to split type-specific classes into

specializations of (new, for the most part) generic bases.  (eg. most everything
from the MIDI branch except for actual MIDI things, so merges have a chance of
succeeding).  Also the new edit toolbar, and various other cleanup things I did
along the way.

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

She's a big'un....



git-svn-id: svn://localhost/ardour2/trunk@727 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
David Robillard
2006-08-01 03:23:35 +00:00
parent ba0c8bc2ef
commit 6f4a92f740
106 changed files with 7844 additions and 5056 deletions

View File

@@ -539,7 +539,7 @@ if env['SYSLIBS']:
# libraries['flowcanvas'] = LibraryInfo(LIBS='flowcanvas', LIBPATH='#/libs/flowcanvas', CPPPATH='#libs/flowcanvas')
libraries['soundtouch'] = LibraryInfo()
libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs soundtouch-1.0')
libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs libSoundTouch')
coredirs = [
'templates'

View File

@@ -75,6 +75,7 @@ ardour_ui_ed.cc
ardour_ui_mixer.cc
ardour_ui_options.cc
audio_clock.cc
route_time_axis.cc
audio_time_axis.cc
automation_gain_line.cc
automation_line.cc
@@ -157,10 +158,11 @@ public_editor.cc
redirect_automation_line.cc
redirect_automation_time_axis.cc
redirect_box.cc
region_editor.cc
audio_region_editor.cc
region_gain_line.cc
region_selection.cc
regionview.cc
region_view.cc
audio_region_view.cc
route_params_ui.cc
route_redirect_selection.cc
route_ui.cc
@@ -168,7 +170,8 @@ selection.cc
sfdb_ui.cc
send_ui.cc
streamview.cc
taperegionview.cc
audio_streamview.cc
tape_region_view.cc
tempo_dialog.cc
time_axis_view.cc
time_axis_view_item.cc

View File

@@ -26,7 +26,7 @@
#include <gtkmm/treeiter.h>
#include <ardour/audioregion.h>
#include <ardour/playlist.h>
#include <ardour/audioplaylist.h>
#include <ardour/types.h>
#include "analysis_window.h"
@@ -35,7 +35,7 @@
#include "time_axis_view.h"
#include "public_editor.h"
#include "selection.h"
#include "regionview.h"
#include "audio_region_view.h"
#include "i18n.h"
@@ -225,11 +225,16 @@ AnalysisWindow::analyze_data (Gtk::Button *button)
Selection s = PublicEditor::instance().get_selection();
TimeSelection ts = s.time;
AudioRegionSelection ars = s.audio_regions;
RegionSelection ars = s.regions;
for (TrackSelection::iterator i = s.tracks.begin(); i != s.tracks.end(); ++i) {
ARDOUR::Playlist *pl = (*i)->playlist();
ARDOUR::AudioPlaylist *pl
= dynamic_cast<ARDOUR::AudioPlaylist*>((*i)->playlist());
if (!pl)
continue;
RouteUI *rui = dynamic_cast<RouteUI *>(*i);
// Busses don't have playlists, so we need to check that we actually are working with a playlist
@@ -274,24 +279,29 @@ AnalysisWindow::analyze_data (Gtk::Button *button)
TimeAxisView *current_axis = (*i);
for (std::set<AudioRegionView *>::iterator j = ars.begin(); j != ars.end(); ++j) {
for (std::set<RegionView *>::iterator j = ars.begin(); j != ars.end(); ++j) {
// Check that the region is actually audio (so we can analyze it)
AudioRegionView* arv = dynamic_cast<AudioRegionView*>(*j);
if (!arv)
continue;
// Check that the region really is selected on _this_ track/solo
if ( &(*j)->get_time_axis_view() != current_axis)
if ( &arv->get_time_axis_view() != current_axis)
continue;
// cerr << " - " << (*j)->region.name() << ": " << (*j)->region.length() << " samples starting at " << (*j)->region.position() << endl;
// cerr << " - " << (*j)->region().name() << ": " << (*j)->region().length() << " samples starting at " << (*j)->region().position() << endl;
jack_nframes_t i = 0;
int n;
while ( i < (*j)->region.length() ) {
while ( i < arv->region().length() ) {
// TODO: What about stereo+ channels? composite all to one, I guess
n = fft_graph.windowSize();
if (i + n >= (*j)->region.length() ) {
n = (*j)->region.length() - i;
if (i + n >= arv->region().length() ) {
n = arv->region().length() - i;
}
n = (*j)->region.read_at(buf, mixbuf, gain, work, (*j)->region.position() + i, n);
n = arv->audio_region().read_at(buf, mixbuf, gain, work, arv->region().position() + i, n);
if ( n < fft_graph.windowSize()) {
for (int j = n; j < fft_graph.windowSize(); j++) {

View File

@@ -46,6 +46,7 @@
#include <midi++/mmc.h>
#include <ardour/ardour.h>
#include <ardour/session_route.h>
#include <ardour/port.h>
#include <ardour/audioengine.h>
#include <ardour/playlist.h>
@@ -53,7 +54,6 @@
#include <ardour/audio_diskstream.h>
#include <ardour/audiofilesource.h>
#include <ardour/recent_sessions.h>
#include <ardour/session_diskstream.h>
#include <ardour/port.h>
#include <ardour/audio_track.h>
@@ -186,8 +186,8 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
gettimeofday (&last_shuttle_request, 0);
ARDOUR::AudioDiskstream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread));
ARDOUR::AudioDiskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
ARDOUR::AudioDiskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
/* handle pending state with a dialog */
@@ -543,9 +543,10 @@ ARDOUR_UI::update_buffer_load ()
}
void
ARDOUR_UI::count_recenabled_diskstreams (AudioDiskstream& ds)
ARDOUR_UI::count_recenabled_diskstreams (Route& route)
{
if (ds.record_enabled()) {
Track* track = dynamic_cast<Track*>(&route);
if (track && track->diskstream().record_enabled()) {
rec_enabled_diskstreams++;
}
}
@@ -571,7 +572,7 @@ ARDOUR_UI::update_disk_space()
if (session->actively_recording()){
rec_enabled_diskstreams = 0;
session->foreach_audio_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
session->foreach_route (this, &ARDOUR_UI::count_recenabled_diskstreams);
if (rec_enabled_diskstreams) {
frames /= rec_enabled_diskstreams;
@@ -918,7 +919,7 @@ restart JACK with more ports."));
}
void
ARDOUR_UI::diskstream_added (AudioDiskstream* ds)
ARDOUR_UI::diskstream_added (Diskstream* ds)
{
}
@@ -1169,12 +1170,15 @@ ARDOUR_UI::toggle_record_enable (uint32_t dstream)
if ((r = session->route_by_remote_id (dstream)) != 0) {
AudioTrack* at;
Track* t;
if ((at = dynamic_cast<AudioTrack*>(r.get())) != 0) {
at->disk_stream().set_record_enabled (!at->disk_stream().record_enabled(), this);
if ((t = dynamic_cast<Track*>(r.get())) != 0) {
t->diskstream().set_record_enabled (!t->diskstream().record_enabled());
}
}
if (session == 0) {
return;
}
}
void
@@ -2150,11 +2154,11 @@ ARDOUR_UI::halt_on_xrun_message ()
}
void
ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::AudioFileSource*>* deletion_list)
ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
{
ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
for (list<AudioFileSource*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
delete *i;
}

View File

@@ -520,7 +520,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
sigc::connection point_one_second_connection;
sigc::connection point_zero_one_second_connection;
void diskstream_added (ARDOUR::AudioDiskstream*);
void diskstream_added (ARDOUR::Diskstream*);
gint session_menu (GdkEventButton *);
@@ -621,7 +621,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
void toggle_record_enable (uint32_t);
uint32_t rec_enabled_diskstreams;
void count_recenabled_diskstreams (ARDOUR::AudioDiskstream&);
void count_recenabled_diskstreams (ARDOUR::Route&);
About* about;
bool shown_flag;
@@ -640,7 +640,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
struct timeval last_peak_grab;
struct timeval last_shuttle_request;
void delete_sources_in_the_right_thread (list<ARDOUR::AudioFileSource*>*);
void delete_sources_in_the_right_thread (list<ARDOUR::Source*>*);
void editor_display_control_changed (Editing::DisplayControl c);

View File

@@ -76,8 +76,8 @@ ARDOUR_UI::connect_to_session (Session *s)
rec_button.set_sensitive (true);
shuttle_box.set_sensitive (true);
if (session->n_audio_diskstreams() == 0) {
session->AudioDiskstreamAdded.connect (mem_fun(*this, &ARDOUR_UI::diskstream_added));
if (session->n_diskstreams() == 0) {
session->DiskstreamAdded.connect (mem_fun(*this, &ARDOUR_UI::diskstream_added));
}
if (connection_editor) {

View File

@@ -24,8 +24,8 @@
#include <gtkmm2ext/stop_signal.h>
#include <cmath>
#include "region_editor.h"
#include "regionview.h"
#include "audio_region_editor.h"
#include "audio_region_view.h"
#include "ardour_ui.h"
#include "utils.h"
#include "gui_thread.h"
@@ -37,9 +37,8 @@ using namespace PBD;
using namespace sigc;
using namespace std;
AudioRegionEditor::AudioRegionEditor (Session&s, AudioRegion& r, AudioRegionView& rv)
: ArdourDialog ("audio region editor"),
_session (s),
AudioRegionEditor::AudioRegionEditor (Session& s, AudioRegion& r, AudioRegionView& rv)
: RegionEditor (s),
_region (r),
_region_view (rv),
name_label (_("NAME:")),

View File

@@ -18,8 +18,8 @@
$Id$
*/
#ifndef __gtk_ardour_region_edit_h__
#define __gtk_ardour_region_edit_h__
#ifndef __gtk_ardour_audio_region_edit_h__
#define __gtk_ardour_audio_region_edit_h__
#include <map>
@@ -41,6 +41,7 @@
#include "audio_clock.h"
#include "ardour_dialog.h"
#include "region_editor.h"
namespace ARDOUR {
class AudioRegion;
@@ -49,14 +50,13 @@ namespace ARDOUR {
class AudioRegionView;
class AudioRegionEditor : public ArdourDialog
class AudioRegionEditor : public RegionEditor
{
public:
AudioRegionEditor (ARDOUR::Session&, ARDOUR::AudioRegion&, AudioRegionView& rv);
~AudioRegionEditor ();
private:
ARDOUR::Session& _session;
ARDOUR::AudioRegion& _region;
AudioRegionView& _region_view;
@@ -183,4 +183,4 @@ class AudioRegionEditor : public ArdourDialog
bool spin_arrow_grab;
};
#endif /* __gtk_ardour_region_edit_h__ */
#endif /* __gtk_ardour_audio_region_edit_h__ */

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/*
Copyright (C) 2001-2004 Paul Davis
Copyright (C) 2001-2006 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -14,12 +14,10 @@
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__
#ifndef __gtk_ardour_audio_region_view_h__
#define __gtk_ardour_audio_region_view_h__
#include <vector>
@@ -28,6 +26,8 @@
#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"
@@ -46,51 +46,38 @@ class AudioRegionEditor;
class GhostRegion;
class AutomationTimeAxisView;
class AudioRegionView : public TimeAxisViewItem
class AudioRegionView : public RegionView
{
public:
AudioRegionView (ArdourCanvas::Group *,
AudioTimeAxisView&,
RouteTimeAxisView&,
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);
virtual void init (Gdk::Color& base_color, bool wait_for_data = false);
ARDOUR::AudioRegion& audio_region() const;
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 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; }
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);
@@ -100,19 +87,13 @@ class AudioRegionView : public TimeAxisViewItem
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 ();
@@ -124,44 +105,18 @@ class AudioRegionView : public TimeAxisViewItem
*/
AudioRegionView (ArdourCanvas::Group *,
AudioTimeAxisView&,
ARDOUR::AudioRegion&,
double initial_samples_per_unit,
Gdk::Color& basic_color,
TimeAxisViewItem::Visibility);
RouteTimeAxisView&,
ARDOUR::AudioRegion&,
double 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 ();
@@ -173,34 +128,37 @@ class AudioRegionView : public TimeAxisViewItem
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();
void color_handler (ColorID, uint32_t);
vector<GnomeCanvasWaveViewCache*> wave_caches;
vector<GhostRegion*> ghosts;
void color_handler (ColorID, uint32_t);
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_region_view_h__ */
#endif /* __gtk_ardour_audio_region_view_h__ */

View File

@@ -15,7 +15,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id$
$Id: regionview.cc 678 2006-07-11 15:45:19Z paul $
*/
#include <cmath>
@@ -31,7 +31,7 @@
#include <ardour/audio_diskstream.h>
#include "streamview.h"
#include "regionview.h"
#include "region_view.h"
#include "audio_time_axis.h"
#include "simplerect.h"
#include "simpleline.h"

View File

@@ -0,0 +1,698 @@
/*
Copyright (C) 2001, 2006 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <cmath>
#include <cassert>
#include <gtkmm.h>
#include <gtkmm2ext/gtk_ui.h>
#include <ardour/audioplaylist.h>
#include <ardour/audioregion.h>
#include <ardour/audiosource.h>
#include <ardour/audio_diskstream.h>
#include <ardour/audio_track.h>
#include <ardour/playlist_templates.h>
#include <ardour/source.h>
#include "audio_streamview.h"
#include "audio_region_view.h"
#include "tape_region_view.h"
#include "audio_time_axis.h"
#include "canvas-waveview.h"
#include "canvas-simplerect.h"
#include "region_selection.h"
#include "selection.h"
#include "public_editor.h"
#include "ardour_ui.h"
#include "crossfade_view.h"
#include "rgb_macros.h"
#include "gui_thread.h"
#include "utils.h"
#include "color.h"
using namespace ARDOUR;
using namespace PBD;
using namespace Editing;
AudioStreamView::AudioStreamView (AudioTimeAxisView& tv)
: StreamView (tv)
{
crossfades_visible = true;
if (tv.is_audio_track())
stream_base_color = color_map[cAudioTrackBase];
else
stream_base_color = color_map[cAudioBusBase];
canvas_rect->property_outline_color_rgba() = color_map[cAudioTrackOutline];
_amplitude_above_axis = 1.0;
use_rec_regions = tv.editor.show_waveforms_recording ();
last_rec_peak_frame = 0;
}
AudioStreamView::~AudioStreamView ()
{
}
int
AudioStreamView::set_height (gdouble h)
{
/* limit the values to something sane-ish */
if (h < 10.0 || h > 1000.0) {
return -1;
}
StreamView::set_height(h);
for (CrossfadeViewList::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
(*i)->set_height (h);
}
return 0;
}
int
AudioStreamView::set_samples_per_unit (gdouble spp)
{
StreamView::set_samples_per_unit(spp);
for (CrossfadeViewList::iterator xi = crossfade_views.begin(); xi != crossfade_views.end(); ++xi) {
(*xi)->set_samples_per_unit (spp);
}
return 0;
}
int
AudioStreamView::set_amplitude_above_axis (gdouble app)
{
RegionViewList::iterator i;
if (app < 1.0) {
return -1;
}
_amplitude_above_axis = app;
for (i = region_views.begin(); i != region_views.end(); ++i) {
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
if (arv)
arv->set_amplitude_above_axis (app);
}
return 0;
}
void
AudioStreamView::add_region_view_internal (Region *r, bool wait_for_waves)
{
ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::add_region_view), r));
AudioRegion* region = dynamic_cast<AudioRegion*> (r);
if (region == 0) {
return;
}
AudioRegionView *region_view;
list<RegionView *>::iterator i;
for (i = region_views.begin(); i != region_views.end(); ++i) {
if (&(*i)->region() == r) {
/* great. we already have a AudioRegionView for this Region. use it again. */
(*i)->set_valid (true);
return;
}
}
switch (_trackview.audio_track()->mode()) {
case Normal:
region_view = new AudioRegionView (canvas_group, _trackview, *region,
_samples_per_unit, region_color);
break;
case Destructive:
region_view = new TapeAudioRegionView (canvas_group, _trackview, *region,
_samples_per_unit, region_color);
break;
}
region_view->init (region_color, wait_for_waves);
region_view->set_amplitude_above_axis(_amplitude_above_axis);
region_views.push_front (region_view);
/* follow global waveform setting */
region_view->set_waveform_visible(_trackview.editor.show_waveforms());
/* catch regionview going away */
region->GoingAway.connect (mem_fun (*this, &AudioStreamView::remove_region_view));
RegionViewAdded (region_view);
}
void
AudioStreamView::remove_region_view (Region *r)
{
ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::remove_region_view), r));
for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end();) {
list<CrossfadeView*>::iterator tmp;
tmp = i;
++tmp;
AudioRegion* ar = dynamic_cast<AudioRegion*>(r);
if (ar && (*i)->crossfade.involves (*ar)) {
delete *i;
crossfade_views.erase (i);
}
i = tmp;
}
StreamView::remove_region_view(r);
}
void
AudioStreamView::undisplay_diskstream ()
{
StreamView::undisplay_diskstream();
for (CrossfadeViewList::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
delete *i;
}
crossfade_views.clear ();
}
void
AudioStreamView::playlist_modified ()
{
ENSURE_GUI_THREAD (mem_fun (*this, &AudioStreamView::playlist_modified));
StreamView::playlist_modified();
/* if the playlist is modified, make sure xfades are on top and all the regionviews are stacked
correctly.
*/
for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
(*i)->get_canvas_group()->raise_to_top();
}
}
void
AudioStreamView::playlist_changed (Diskstream *ds)
{
ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::playlist_changed), ds));
StreamView::playlist_changed(ds);
AudioPlaylist* apl = dynamic_cast<AudioPlaylist*>(ds->playlist());
if (apl)
playlist_connections.push_back (apl->NewCrossfade.connect (mem_fun (*this, &AudioStreamView::add_crossfade)));
}
void
AudioStreamView::add_crossfade (Crossfade *crossfade)
{
AudioRegionView* lview = 0;
AudioRegionView* rview = 0;
ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::add_crossfade), crossfade));
/* first see if we already have a CrossfadeView for this Crossfade */
for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
if (&(*i)->crossfade == crossfade) {
if (!crossfades_visible) {
(*i)->hide();
} else {
(*i)->show ();
}
(*i)->set_valid (true);
return;
}
}
/* create a new one */
for (list<RegionView *>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
AudioRegionView* arv = dynamic_cast<AudioRegionView*>(*i);
if (!lview && arv && &(arv->region()) == &crossfade->out()) {
lview = arv;
}
if (!rview && arv && &(arv->region()) == &crossfade->in()) {
rview = arv;
}
}
CrossfadeView *cv = new CrossfadeView (_trackview.canvas_display,
_trackview,
*crossfade,
_samples_per_unit,
region_color,
*lview, *rview);
crossfade->Invalidated.connect (mem_fun (*this, &AudioStreamView::remove_crossfade));
crossfade_views.push_back (cv);
if (!crossfades_visible) {
cv->hide ();
}
}
void
AudioStreamView::remove_crossfade (Crossfade *xfade)
{
ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::remove_crossfade), xfade));
for (list<CrossfadeView*>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
if (&(*i)->crossfade == xfade) {
delete *i;
crossfade_views.erase (i);
break;
}
}
}
void
AudioStreamView::redisplay_diskstream ()
{
list<RegionView *>::iterator i, tmp;
list<CrossfadeView*>::iterator xi, tmpx;
for (i = region_views.begin(); i != region_views.end(); ++i) {
(*i)->set_valid (false);
}
for (xi = crossfade_views.begin(); xi != crossfade_views.end(); ++xi) {
(*xi)->set_valid (false);
if ((*xi)->visible()) {
(*xi)->show ();
}
}
if (_trackview.is_audio_track()) {
_trackview.get_diskstream()->playlist()->foreach_region (static_cast<StreamView*>(this), &StreamView::add_region_view);
AudioPlaylist* apl = dynamic_cast<AudioPlaylist*>(_trackview.get_diskstream()->playlist());
if (apl)
apl->foreach_crossfade (this, &AudioStreamView::add_crossfade);
}
for (i = region_views.begin(); i != region_views.end(); ) {
tmp = i;
tmp++;
if (!(*i)->is_valid()) {
delete *i;
region_views.erase (i);
}
i = tmp;
}
for (xi = crossfade_views.begin(); xi != crossfade_views.end();) {
tmpx = xi;
tmpx++;
if (!(*xi)->valid()) {
delete *xi;
crossfade_views.erase (xi);
}
xi = tmpx;
}
/* now fix layering */
playlist_modified ();
}
void
AudioStreamView::set_show_waveforms (bool yn)
{
for (list<RegionView *>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
if (arv)
arv->set_waveform_visible (yn);
}
}
void
AudioStreamView::set_waveform_shape (WaveformShape shape)
{
for (RegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) {
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
if (arv)
arv->set_waveform_shape (shape);
}
}
void
AudioStreamView::setup_rec_box ()
{
// cerr << _trackview.name() << " streamview SRB\n";
if (_trackview.session().transport_rolling()) {
// cerr << "\trolling\n";
if (!rec_active &&
_trackview.session().record_status() == Session::Recording &&
_trackview.get_diskstream()->record_enabled()) {
if (_trackview.audio_track()->mode() == Normal && use_rec_regions && rec_regions.size() == rec_rects.size()) {
/* add a new region, but don't bother if they set use_rec_regions mid-record */
AudioRegion::SourceList sources;
for (list<sigc::connection>::iterator prc = peak_ready_connections.begin(); prc != peak_ready_connections.end(); ++prc) {
(*prc).disconnect();
}
peak_ready_connections.clear();
// FIXME
AudioDiskstream* ads = dynamic_cast<AudioDiskstream*>(_trackview.get_diskstream());
assert(ads);
for (uint32_t n=0; n < ads->n_channels(); ++n) {
AudioSource *src = (AudioSource *) ads->write_source (n);
if (src) {
sources.push_back (src);
peak_ready_connections.push_back (src->PeakRangeReady.connect (bind (mem_fun (*this, &AudioStreamView::rec_peak_range_ready), src)));
}
}
// handle multi
jack_nframes_t start = 0;
if (rec_regions.size() > 0) {
start = rec_regions.back()->start() + _trackview.get_diskstream()->get_captured_frames(rec_regions.size()-1);
}
AudioRegion * region = new AudioRegion(sources, start, 1 , "", 0, (Region::Flag)(Region::DefaultFlags | Region::DoNotSaveState), false);
region->set_position (_trackview.session().transport_frame(), this);
rec_regions.push_back (region);
/* catch it if it goes away */
region->GoingAway.connect (mem_fun (*this, &AudioStreamView::remove_rec_region));
/* we add the region later */
}
/* start a new rec box */
AudioTrack* at;
at = _trackview.audio_track(); /* we know what it is already */
AudioDiskstream& ds = at->audio_diskstream();
jack_nframes_t frame_pos = ds.current_capture_start ();
gdouble xstart = _trackview.editor.frame_to_pixel (frame_pos);
gdouble xend;
uint32_t fill_color;
switch (_trackview.audio_track()->mode()) {
case Normal:
xend = xstart;
fill_color = color_map[cRecordingRectFill];
break;
case Destructive:
xend = xstart + 2;
fill_color = color_map[cRecordingRectFill];
/* make the recording rect translucent to allow
the user to see the peak data coming in, etc.
*/
fill_color = UINT_RGBA_CHANGE_A (fill_color, 120);
break;
}
ArdourCanvas::SimpleRect * rec_rect = new Gnome::Canvas::SimpleRect (*canvas_group);
rec_rect->property_x1() = xstart;
rec_rect->property_y1() = 1.0;
rec_rect->property_x2() = xend;
rec_rect->property_y2() = (double) _trackview.height - 1;
rec_rect->property_outline_color_rgba() = color_map[cRecordingRectOutline];
rec_rect->property_fill_color_rgba() = fill_color;
RecBoxInfo recbox;
recbox.rectangle = rec_rect;
recbox.start = _trackview.session().transport_frame();
recbox.length = 0;
rec_rects.push_back (recbox);
screen_update_connection.disconnect();
screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (mem_fun (*this, &AudioStreamView::update_rec_box));
rec_updating = true;
rec_active = true;
} else if (rec_active &&
(_trackview.session().record_status() != Session::Recording ||
!_trackview.get_diskstream()->record_enabled())) {
screen_update_connection.disconnect();
rec_active = false;
rec_updating = false;
}
} else {
// cerr << "\tNOT rolling, rec_rects = " << rec_rects.size() << " rec_regions = " << rec_regions.size() << endl;
if (!rec_rects.empty() || !rec_regions.empty()) {
/* disconnect rapid update */
screen_update_connection.disconnect();
for (list<sigc::connection>::iterator prc = peak_ready_connections.begin(); prc != peak_ready_connections.end(); ++prc) {
(*prc).disconnect();
}
peak_ready_connections.clear();
rec_updating = false;
rec_active = false;
last_rec_peak_frame = 0;
/* remove temp regions */
for (list<Region*>::iterator iter=rec_regions.begin(); iter != rec_regions.end(); )
{
list<Region*>::iterator tmp;
tmp = iter;
++tmp;
/* this will trigger the remove_region_view */
delete *iter;
iter = tmp;
}
rec_regions.clear();
// cerr << "\tclear " << rec_rects.size() << " rec rects\n";
/* transport stopped, clear boxes */
for (vector<RecBoxInfo>::iterator iter=rec_rects.begin(); iter != rec_rects.end(); ++iter) {
RecBoxInfo &rect = (*iter);
delete rect.rectangle;
}
rec_rects.clear();
}
}
}
void
AudioStreamView::foreach_crossfadeview (void (CrossfadeView::*pmf)(void))
{
for (list<CrossfadeView*>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
((*i)->*pmf) ();
}
}
void
AudioStreamView::rec_peak_range_ready (jack_nframes_t start, jack_nframes_t cnt, Source * src)
{
// this is called from the peak building thread
ENSURE_GUI_THREAD(bind (mem_fun (*this, &AudioStreamView::rec_peak_range_ready), start, cnt, src));
if (rec_peak_ready_map.size() == 0 || start+cnt > last_rec_peak_frame) {
last_rec_peak_frame = start + cnt;
}
rec_peak_ready_map[src] = true;
if (rec_peak_ready_map.size() == _trackview.get_diskstream()->n_channels()) {
this->update_rec_regions ();
rec_peak_ready_map.clear();
}
}
void
AudioStreamView::update_rec_regions ()
{
if (use_rec_regions) {
uint32_t n = 0;
for (list<Region*>::iterator iter = rec_regions.begin(); iter != rec_regions.end(); n++) {
list<Region*>::iterator tmp;
tmp = iter;
++tmp;
if (!canvas_item_visible (rec_rects[n].rectangle)) {
/* rect already hidden, this region is done */
iter = tmp;
continue;
}
// FIXME
AudioRegion * region = dynamic_cast<AudioRegion*>(*iter);
assert(region);
jack_nframes_t origlen = region->length();
if (region == rec_regions.back() && rec_active) {
if (last_rec_peak_frame > region->start()) {
jack_nframes_t nlen = last_rec_peak_frame - region->start();
if (nlen != region->length()) {
region->freeze ();
region->set_position (_trackview.get_diskstream()->get_capture_start_frame(n), this);
region->set_length (nlen, this);
region->thaw ("updated");
if (origlen == 1) {
/* our special initial length */
add_region_view_internal (region, false);
}
/* also update rect */
ArdourCanvas::SimpleRect * rect = rec_rects[n].rectangle;
gdouble xend = _trackview.editor.frame_to_pixel (region->position() + region->length());
rect->property_x2() = xend;
}
}
} else {
jack_nframes_t nlen = _trackview.get_diskstream()->get_captured_frames(n);
if (nlen != region->length()) {
if (region->source(0).length() >= region->start() + nlen) {
region->freeze ();
region->set_position (_trackview.get_diskstream()->get_capture_start_frame(n), this);
region->set_length (nlen, this);
region->thaw ("updated");
if (origlen == 1) {
/* our special initial length */
add_region_view_internal (region, false);
}
/* also hide rect */
ArdourCanvas::Item * rect = rec_rects[n].rectangle;
rect->hide();
}
}
}
iter = tmp;
}
}
}
void
AudioStreamView::show_all_xfades ()
{
foreach_crossfadeview (&CrossfadeView::show);
crossfades_visible = true;
}
void
AudioStreamView::hide_all_xfades ()
{
foreach_crossfadeview (&CrossfadeView::hide);
crossfades_visible = false;
}
void
AudioStreamView::hide_xfades_involving (AudioRegionView& rv)
{
for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
if ((*i)->crossfade.involves (rv.audio_region())) {
(*i)->fake_hide ();
}
}
}
void
AudioStreamView::reveal_xfades_involving (AudioRegionView& rv)
{
for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
if ((*i)->crossfade.involves (rv.audio_region()) && (*i)->visible()) {
(*i)->show ();
}
}
}
void
AudioStreamView::color_handler (ColorID id, uint32_t val)
{
switch (id) {
case cAudioTrackBase:
if (_trackview.is_audio_track()) {
canvas_rect->property_fill_color_rgba() = val;
}
break;
case cAudioBusBase:
if (!_trackview.is_audio_track()) {
canvas_rect->property_fill_color_rgba() = val;
}
break;
case cAudioTrackOutline:
canvas_rect->property_outline_color_rgba() = val;
break;
default:
break;
}
}

View File

@@ -0,0 +1,110 @@
/*
Copyright (C) 2001, 2006 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __ardour_audio_streamview_h__
#define __ardour_audio_streamview_h__
#include <list>
#include <map>
#include <cmath>
#include <ardour/location.h>
#include "enums.h"
#include "simplerect.h"
#include "color.h"
#include "streamview.h"
namespace Gdk {
class Color;
}
namespace ARDOUR {
class Route;
class Diskstream;
class Crossfade;
class PeakData;
class AudioRegion;
class Source;
}
class PublicEditor;
class Selectable;
class AudioTimeAxisView;
class AudioRegionView;
class RegionSelection;
class CrossfadeView;
class Selection;
class AudioStreamView : public StreamView
{
public:
AudioStreamView (AudioTimeAxisView&);
~AudioStreamView ();
void set_waveform_shape (WaveformShape);
int set_height (gdouble h);
int set_samples_per_unit (gdouble spp);
int set_amplitude_above_axis (gdouble app);
gdouble get_amplitude_above_axis () { return _amplitude_above_axis; }
void set_show_waveforms (bool yn);
void set_show_waveforms_recording (bool yn) { use_rec_regions = yn; }
void foreach_crossfadeview (void (CrossfadeView::*pmf)(void));
void show_all_xfades ();
void hide_all_xfades ();
void hide_xfades_involving (AudioRegionView&);
void reveal_xfades_involving (AudioRegionView&);
private:
void setup_rec_box ();
void rec_peak_range_ready (jack_nframes_t start, jack_nframes_t cnt, ARDOUR::Source* src);
void update_rec_regions ();
void add_region_view_internal (ARDOUR::Region*, bool wait_for_waves);
void remove_region_view (ARDOUR::Region* );
void remove_audio_region_view (ARDOUR::AudioRegion* );
void remove_audio_rec_region (ARDOUR::AudioRegion*);
void undisplay_diskstream ();
void redisplay_diskstream ();
void playlist_modified ();
void playlist_changed (ARDOUR::Diskstream *ds);
void add_crossfade (ARDOUR::Crossfade*);
void remove_crossfade (ARDOUR::Crossfade*);
void color_handler (ColorID id, uint32_t val);
double _amplitude_above_axis;
typedef list<CrossfadeView*> CrossfadeViewList;
CrossfadeViewList crossfade_views;
bool crossfades_visible;
list<sigc::connection> peak_ready_connections;
jack_nframes_t last_rec_peak_frame;
map<ARDOUR::Source*, bool> rec_peak_ready_map;
};
#endif /* __ardour_audio_streamview_h__ */

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/*
Copyright (C) 2000 Paul Davis
Copyright (C) 2000-2006 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -18,8 +18,8 @@
$Id$
*/
#ifndef __ardour_trackview_h__
#define __ardour_trackview_h__
#ifndef __ardour_audio_time_axis_h__
#define __ardour_audio_time_axis_h__
#include <gtkmm/table.h>
#include <gtkmm/button.h>
@@ -33,19 +33,14 @@
#include <list>
#include <ardour/types.h>
#include <ardour/region.h>
#include "ardour_dialog.h"
#include "route_ui.h"
#include "enums.h"
#include "time_axis_view.h"
#include "route_time_axis.h"
#include "canvas.h"
#include "color.h"
namespace ALSA {
class MultiChannelDevice;
}
namespace ARDOUR {
class Session;
class AudioDiskstream;
@@ -56,247 +51,58 @@ namespace ARDOUR {
class AudioPlaylist;
}
namespace LADSPA {
class Manager;
class Plugin;
}
class PublicEditor;
class AudioThing;
class StreamView;
class AudioStreamView;
class Selection;
class Selectable;
class RegionView;
class AudioRegionView;
class AutomationLine;
class AutomationGainLine;
class AutomationPanLine;
class RedirectAutomationLine;
class TimeSelection;
class AutomationTimeAxisView;
class AudioTimeAxisView : public RouteUI, public TimeAxisView
class AudioTimeAxisView : public RouteTimeAxisView
{
public:
AudioTimeAxisView (PublicEditor&, ARDOUR::Session&, boost::shared_ptr<ARDOUR::Route>, ArdourCanvas::Canvas& canvas);
virtual ~AudioTimeAxisView ();
AudioStreamView* audio_view();
void show_selection (TimeSelection&);
void automation_control_point_changed (ARDOUR::AutomationType);
void set_samples_per_unit (double);
void set_height (TimeAxisView::TrackHeight);
void set_show_waveforms (bool yn);
void set_show_waveforms_recording (bool yn);
void show_timestretch (jack_nframes_t start, jack_nframes_t end);
void hide_timestretch ();
void selection_click (GdkEventButton*);
void set_selected_regionviews (AudioRegionSelection&);
void set_selected_points (PointSelection&);
void get_selectables (jack_nframes_t start, jack_nframes_t end, double top, double bot, list<Selectable *>&);
void get_inverted_selectables (Selection&, list<Selectable*>&);
void show_all_xfades ();
void hide_all_xfades ();
void hide_dependent_views (TimeAxisViewItem&);
void reveal_dependent_views (TimeAxisViewItem&);
ARDOUR::Region* find_next_region (jack_nframes_t pos, ARDOUR::RegionPoint, int32_t dir);
string name() const;
ARDOUR::RouteGroup* edit_group() const;
void build_playlist_menu (Gtk::Menu *);
ARDOUR::Playlist* playlist() const;
/* overridden from parent to store display state */
/* Overridden from parent to store display state */
guint32 show_at (double y, int& nth, Gtk::VBox *parent);
void hide ();
/* need accessors/mutators */
StreamView *view;
/* editing operations */
bool cut_copy_clear (Selection&, Editing::CutCopyOp);
bool paste (jack_nframes_t, float times, Selection&, size_t nth);
list<TimeAxisView*>get_child_list();
void set_state (const XMLNode&);
XMLNode* get_child_xml_node (const string & childname);
/* the editor calls these when mapping an operation across multiple tracks */
void use_new_playlist (bool prompt);
void use_copy_playlist (bool prompt);
void clear_playlist ();
private:
friend class StreamView;
friend class AudioStreamView;
friend class AudioRegionView;
ArdourCanvas::Canvas& parent_canvas;
bool no_redraw;
AutomationTimeAxisView *gain_track;
AutomationTimeAxisView *pan_track;
void update_automation_view (ARDOUR::AutomationType);
void reset_redirect_automation_curves ();
Gtk::HBox other_button_hbox;
Gtk::Table button_table;
Gtk::Button redirect_button;
Gtk::Button edit_group_button;
Gtk::Button playlist_button;
Gtk::Button size_button;
Gtk::Button automation_button;
Gtk::Button hide_button;
Gtk::Button visual_button;
void route_active_changed ();
void diskstream_changed (void *src);
void update_diskstream_display ();
void build_automation_action_menu ();
void append_extra_display_menu_items ();
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 select_track_color();
virtual void build_display_menu ();
Gtk::CheckMenuItem* waveform_item;
Gtk::RadioMenuItem* traditional_item;
Gtk::RadioMenuItem* rectified_item;
Gtk::RadioMenuItem* align_existing_item;
Gtk::RadioMenuItem* align_capture_item;
void align_style_changed ();
void set_align_style (ARDOUR::AlignStyle);
void toggle_show_waveforms ();
void set_waveform_shape (WaveformShape);
void toggle_waveforms ();
Gtk::Menu *playlist_menu;
Gtk::Menu *playlist_action_menu;
Gtk::MenuItem *playlist_item;
/* playlist */
void set_playlist (ARDOUR::AudioPlaylist *);
void playlist_click ();
void show_playlist_selector ();
void playlist_changed ();
void playlist_state_changed (ARDOUR::Change);
void playlist_modified ();
void add_playlist_to_playlist_menu (ARDOUR::Playlist*);
void rename_current_playlist ();
/* automation stuff */
Gtk::Menu* automation_action_menu;
Gtk::CheckMenuItem* gain_automation_item;
Gtk::CheckMenuItem* pan_automation_item;
void automation_click ();
void clear_automation ();
void hide_all_automation ();
void show_all_automation ();
void show_existing_automation ();
void hide_all_automation ();
struct RedirectAutomationNode {
uint32_t what;
Gtk::CheckMenuItem* menu_item;
AutomationTimeAxisView* view;
AudioTimeAxisView& parent;
RedirectAutomationNode (uint32_t w, Gtk::CheckMenuItem* mitem, AudioTimeAxisView& p)
: what (w), menu_item (mitem), view (0), parent (p) {}
~RedirectAutomationNode ();
};
struct RedirectAutomationInfo {
boost::shared_ptr<ARDOUR::Redirect> redirect;
bool valid;
Gtk::Menu* menu;
vector<RedirectAutomationNode*> lines;
RedirectAutomationInfo (boost::shared_ptr<ARDOUR::Redirect> r)
: redirect (r), valid (true) {}
~RedirectAutomationInfo ();
};
list<RedirectAutomationInfo*> redirect_automation;
RedirectAutomationNode* find_redirect_automation_node (boost::shared_ptr<ARDOUR::Redirect> redirect, uint32_t what);
Gtk::Menu subplugin_menu;
void add_redirect_to_subplugin_menu (boost::shared_ptr<ARDOUR::Redirect>);
void remove_ran (RedirectAutomationNode* ran);
void redirect_menu_item_toggled (AudioTimeAxisView::RedirectAutomationInfo*,
AudioTimeAxisView::RedirectAutomationNode*);
void redirect_automation_track_hidden (RedirectAutomationNode*, boost::shared_ptr<ARDOUR::Redirect>);
vector<RedirectAutomationLine*> redirect_automation_curves;
RedirectAutomationLine *find_redirect_automation_curve (boost::shared_ptr<ARDOUR::Redirect>,uint32_t);
void add_redirect_automation_curve (boost::shared_ptr<ARDOUR::Redirect>, uint32_t);
void add_existing_redirect_automation_curves (boost::shared_ptr<ARDOUR::Redirect>);
ArdourCanvas::SimpleRect *timestretch_rect;
void timestretch (jack_nframes_t start, jack_nframes_t end);
void visual_click ();
void hide_click ();
gint when_displayed (GdkEventAny*);
void speed_changed ();
void add_gain_automation_child ();
void add_pan_automation_child ();
void add_parameter_automation_child ();
@@ -309,14 +115,19 @@ class AudioTimeAxisView : public RouteUI, public TimeAxisView
void update_pans ();
void region_view_added (AudioRegionView*);
void add_ghost_to_redirect (AudioRegionView*, AutomationTimeAxisView*);
AutomationTimeAxisView* gain_track;
AutomationTimeAxisView* pan_track;
void map_frozen ();
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__ */

View File

@@ -24,7 +24,7 @@ namespace ARDOUR {
class PublicEditor;
class TimeSelection;
class AudioRegionSelection;
class RegionSelection;
class PointSelection;
class AutomationLine;
class GhostRegion;

View File

@@ -29,7 +29,7 @@
#include "rgb_macros.h"
#include "audio_time_axis.h"
#include "public_editor.h"
#include "regionview.h"
#include "audio_region_view.h"
#include "utils.h"
#include "canvas_impl.h"
@@ -43,7 +43,7 @@ using namespace Canvas;
sigc::signal<void,CrossfadeView*> CrossfadeView::GoingAway;
CrossfadeView::CrossfadeView (ArdourCanvas::Group *parent,
AudioTimeAxisView &tv,
RouteTimeAxisView &tv,
Crossfade& xf,
double spu,
Gdk::Color& basic_color,
@@ -227,7 +227,7 @@ CrossfadeView::set_valid (bool yn)
AudioRegionView&
CrossfadeView::upper_regionview () const
{
if (left_view.region.layer() > right_view.region.layer()) {
if (left_view.region().layer() > right_view.region().layer()) {
return left_view;
} else {
return right_view;

View File

@@ -28,13 +28,13 @@
#include "time_axis_view_item.h"
class AudioTimeAxisView;
class RouteTimeAxisView;
class AudioRegionView;
struct CrossfadeView : public TimeAxisViewItem
{
CrossfadeView (ArdourCanvas::Group*,
AudioTimeAxisView&,
RouteTimeAxisView&,
ARDOUR::Crossfade&,
double initial_samples_per_unit,
Gdk::Color& basic_color,

View File

@@ -56,10 +56,10 @@
#include "keyboard.h"
#include "marker.h"
#include "playlist_selector.h"
#include "regionview.h"
#include "audio_region_view.h"
#include "rgb_macros.h"
#include "selection.h"
#include "streamview.h"
#include "audio_streamview.h"
#include "time_axis_view.h"
#include "utils.h"
#include "crossfade_view.h"
@@ -101,8 +101,8 @@ static const int32_t slide_index = 0;
static const int32_t splice_index = 1;
static const gchar *edit_mode_strings[] = {
N_("Slide"),
N_("Splice"),
N_("Slide Edit"),
N_("Splice Edit"),
0
};
@@ -131,17 +131,17 @@ static const gchar *snap_type_strings[] = {
};
static const gchar *snap_mode_strings[] = {
N_("Normal"),
N_("Magnetic"),
N_("Normal Snap"),
N_("Magnetic Snap"),
0
};
static const gchar *zoom_focus_strings[] = {
N_("Left"),
N_("Right"),
N_("Center"),
N_("Playhead"),
N_("Edit Cursor"),
N_("Focus Left"),
N_("Focus Right"),
N_("Focus Center"),
N_("Focus Play"),
N_("Focus Edit"),
0
};
@@ -204,37 +204,20 @@ Editor::Editor (AudioEngine& eng)
/* tool bar related */
selection_start_clock (X_("SelectionStartClock"), true),
selection_end_clock (X_("SelectionEndClock"), true),
edit_cursor_clock (X_("EditCursorClock"), true),
zoom_range_clock (X_("ZoomRangeClock"), true, true),
toolbar_selection_clock_table (2,3),
mouse_mode_button_table (2, 3),
mouse_select_button (_("range")),
mouse_move_button (_("object")),
mouse_gain_button (_("gain")),
mouse_zoom_button (_("zoom")),
mouse_timefx_button (_("timefx")),
mouse_audition_button (_("listen")),
automation_mode_button (_("mode")),
global_automation_button (_("automation")),
edit_mode_label (_("Edit Mode")),
snap_type_label (_("Snap To")),
snap_mode_label(_("Snap Mode")),
zoom_focus_label (_("Zoom Focus")),
/* <CMT Additions> */
image_socket_listener(0),
/* </CMT Additions> */
/* nudge */
nudge_label (_("Nudge")),
nudge_clock (X_("NudgeClock"), true, true)
{
@@ -345,6 +328,7 @@ Editor::Editor (AudioEngine& eng)
reset_hscrollbar_stepping ();
zoom_focus = ZoomFocusLeft;
set_zoom_focus (ZoomFocusLeft);
zoom_range_clock.ValueChanged.connect (mem_fun(*this, &Editor::zoom_adjustment_changed));
initialize_rulers ();
@@ -465,36 +449,7 @@ Editor::Editor (AudioEngine& eng)
edit_packer.attach (edit_hscrollbar, 2, 3, 2, 3, FILL|EXPAND, FILL, 0, 0);
zoom_in_button.set_name ("EditorTimeButton");
zoom_out_button.set_name ("EditorTimeButton");
ARDOUR_UI::instance()->tooltips().set_tip (zoom_in_button, _("Zoom in"));
ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_button, _("Zoom out"));
zoom_out_full_button.set_name ("EditorTimeButton");
ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_full_button, _("Zoom to session"));
zoom_in_button.add (*(manage (new Image (Stock::ZOOM_IN, ICON_SIZE_BUTTON))));
zoom_out_button.add (*(manage (new Image (Stock::ZOOM_OUT, ICON_SIZE_BUTTON))));
zoom_out_full_button.add (*(manage (new Image (Stock::ZOOM_FIT, ICON_SIZE_BUTTON))));
zoom_in_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), false));
zoom_out_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), true));
zoom_out_full_button.signal_clicked().connect (mem_fun(*this, &Editor::temporal_zoom_session));
zoom_indicator_box.pack_start (zoom_out_button, false, false);
zoom_indicator_box.pack_start (zoom_in_button, false, false);
zoom_indicator_box.pack_start (zoom_range_clock, false, false);
zoom_indicator_box.pack_start (zoom_out_full_button, false, false);
zoom_indicator_label.set_text (_("Zoom Span"));
zoom_indicator_label.set_name ("ToolBarLabel");
zoom_indicator_vbox.set_spacing (3);
zoom_indicator_vbox.set_border_width (3);
zoom_indicator_vbox.pack_start (zoom_indicator_label, false, false);
zoom_indicator_vbox.pack_start (zoom_indicator_box, false, false);
bottom_hbox.set_border_width (3);
bottom_hbox.set_border_width (2);
bottom_hbox.set_spacing (3);
route_display_model = ListStore::create(route_display_columns);
@@ -717,15 +672,15 @@ Editor::Editor (AudioEngine& eng)
_playlist_selector = new PlaylistSelector();
_playlist_selector->signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
AudioRegionView::AudioRegionViewGoingAway.connect (mem_fun(*this, &Editor::catch_vanishing_audio_regionview));
RegionView::RegionViewGoingAway.connect (mem_fun(*this, &Editor::catch_vanishing_regionview));
/* nudge stuff */
nudge_forward_button.add (*(manage (new Image (get_xpm("right_arrow.xpm")))));
nudge_backward_button.add (*(manage (new Image (get_xpm("left_arrow.xpm")))));
ARDOUR_UI::instance()->tooltips().set_tip (nudge_forward_button, _("Nudge region/selection forwards"));
ARDOUR_UI::instance()->tooltips().set_tip (nudge_backward_button, _("Nudge region/selection backwards"));
ARDOUR_UI::instance()->tooltips().set_tip (nudge_forward_button, _("Nudge Region/Selection Forwards"));
ARDOUR_UI::instance()->tooltips().set_tip (nudge_backward_button, _("Nudge Region/Selection Backwards"));
nudge_forward_button.set_name ("TransportButton");
nudge_backward_button.set_name ("TransportButton");
@@ -775,7 +730,7 @@ Editor::add_toplevel_controls (Container& cont)
}
void
Editor::catch_vanishing_audio_regionview (AudioRegionView *rv)
Editor::catch_vanishing_regionview (RegionView *rv)
{
/* note: the selection will take care of the vanishing
audioregionview by itself.
@@ -791,7 +746,7 @@ Editor::catch_vanishing_audio_regionview (AudioRegionView *rv)
}
void
Editor::set_entered_regionview (AudioRegionView* rv)
Editor::set_entered_regionview (RegionView* rv)
{
if (rv == entered_regionview) {
return;
@@ -1221,7 +1176,7 @@ Editor::connect_to_session (Session *t)
session_connections.push_back (session->TransportStateChange.connect (mem_fun(*this, &Editor::map_transport_state)));
session_connections.push_back (session->PositionChanged.connect (mem_fun(*this, &Editor::map_position_change)));
session_connections.push_back (session->RouteAdded.connect (mem_fun(*this, &Editor::handle_new_route_p)));
session_connections.push_back (session->RouteAdded.connect (mem_fun(*this, &Editor::handle_new_route)));
session_connections.push_back (session->AudioRegionAdded.connect (mem_fun(*this, &Editor::handle_new_audio_region)));
session_connections.push_back (session->AudioRegionRemoved.connect (mem_fun(*this, &Editor::handle_audio_region_removed)));
session_connections.push_back (session->DurationChanged.connect (mem_fun(*this, &Editor::handle_new_duration)));
@@ -1242,8 +1197,6 @@ Editor::connect_to_session (Session *t)
edit_groups_changed ();
edit_cursor_clock.set_session (session);
selection_start_clock.set_session (session);
selection_end_clock.set_session (session);
zoom_range_clock.set_session (session);
_playlist_selector->set_session (session);
nudge_clock.set_session (session);
@@ -1447,7 +1400,7 @@ Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* i
switch (item_type) {
case FadeInItem:
case FadeInHandleItem:
if (arv->region.fade_in_active()) {
if (arv->audio_region().fade_in_active()) {
items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), false)));
} else {
items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), true)));
@@ -1455,16 +1408,16 @@ Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* i
items.push_back (SeparatorElem());
items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Linear)));
items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogB)));
items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Fast)));
items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogA)));
items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Slow)));
items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->audio_region(), &AudioRegion::set_fade_in_shape), AudioRegion::Linear)));
items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->audio_region(), &AudioRegion::set_fade_in_shape), AudioRegion::LogB)));
items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->audio_region(), &AudioRegion::set_fade_in_shape), AudioRegion::Fast)));
items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->audio_region(), &AudioRegion::set_fade_in_shape), AudioRegion::LogA)));
items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->audio_region(), &AudioRegion::set_fade_in_shape), AudioRegion::Slow)));
break;
case FadeOutItem:
case FadeOutHandleItem:
if (arv->region.fade_out_active()) {
if (arv->audio_region().fade_out_active()) {
items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), false)));
} else {
items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), true)));
@@ -1472,11 +1425,11 @@ Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* i
items.push_back (SeparatorElem());
items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Linear)));
items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Fast)));
items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogB)));
items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogA)));
items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Slow)));
items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->audio_region(), &AudioRegion::set_fade_out_shape), AudioRegion::Linear)));
items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->audio_region(), &AudioRegion::set_fade_out_shape), AudioRegion::Fast)));
items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->audio_region(), &AudioRegion::set_fade_out_shape), AudioRegion::LogB)));
items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->audio_region(), &AudioRegion::set_fade_out_shape), AudioRegion::LogA)));
items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->audio_region(), &AudioRegion::set_fade_out_shape), AudioRegion::Slow)));
break;
default:
@@ -1498,8 +1451,8 @@ Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type,
switch (item_type) {
case RegionItem:
case AudioRegionViewName:
case AudioRegionViewNameHighlight:
case RegionViewName:
case RegionViewNameHighlight:
if (with_selection) {
build_menu_function = &Editor::build_track_selection_context_menu;
} else {
@@ -1539,25 +1492,26 @@ Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type,
switch (item_type) {
case RegionItem:
case AudioRegionViewName:
case AudioRegionViewNameHighlight:
case RegionViewName:
case RegionViewNameHighlight:
if (!with_selection) {
if (region_edit_menu_split_item) {
if (clicked_regionview && clicked_regionview->region.covers (edit_cursor->current_frame)) {
if (clicked_regionview && clicked_regionview->region().covers (edit_cursor->current_frame)) {
ActionManager::set_sensitive (ActionManager::edit_cursor_in_region_sensitive_actions, true);
} else {
ActionManager::set_sensitive (ActionManager::edit_cursor_in_region_sensitive_actions, false);
}
}
/*
if (region_edit_menu_split_multichannel_item) {
if (clicked_regionview && clicked_regionview->region.n_channels() > 1) {
if (clicked_regionview && clicked_regionview->region().n_channels() > 1) {
// GTK2FIX find the action, change its sensitivity
// region_edit_menu_split_multichannel_item->set_sensitive (true);
} else {
// GTK2FIX see above
// region_edit_menu_split_multichannel_item->set_sensitive (false);
}
}
}*/
}
break;
@@ -1637,13 +1591,13 @@ Editor::build_track_region_context_menu (jack_nframes_t frame)
AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
if (atv) {
AudioDiskstream* ds;
Diskstream* ds;
Playlist* pl;
if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
Playlist::RegionList* regions = pl->regions_at ((jack_nframes_t) floor ( (double)frame * ds->speed()));
for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
add_region_context_items (atv->view, (*i), edit_items);
add_region_context_items (atv->audio_view(), (*i), edit_items);
}
delete regions;
}
@@ -1664,7 +1618,7 @@ Editor::build_track_crossfade_context_menu (jack_nframes_t frame)
AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
if (atv) {
AudioDiskstream* ds;
Diskstream* ds;
Playlist* pl;
AudioPlaylist* apl;
@@ -1678,11 +1632,11 @@ Editor::build_track_crossfade_context_menu (jack_nframes_t frame)
bool many = xfades.size() > 1;
for (AudioPlaylist::Crossfades::iterator i = xfades.begin(); i != xfades.end(); ++i) {
add_crossfade_context_items (atv->view, (*i), edit_items, many);
add_crossfade_context_items (atv->audio_view(), (*i), edit_items, many);
}
for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
add_region_context_items (atv->view, (*i), edit_items);
add_region_context_items (atv->audio_view(), (*i), edit_items);
}
delete regions;
@@ -1748,7 +1702,7 @@ Editor::build_track_selection_context_menu (jack_nframes_t ignored)
}
void
Editor::add_crossfade_context_items (StreamView* view, Crossfade* xfade, Menu_Helpers::MenuList& edit_items, bool many)
Editor::add_crossfade_context_items (AudioStreamView* view, Crossfade* xfade, Menu_Helpers::MenuList& edit_items, bool many)
{
using namespace Menu_Helpers;
Menu *xfade_menu = manage (new Menu);
@@ -1805,7 +1759,7 @@ Editor::xfade_edit_right_region ()
}
void
Editor::add_region_context_items (StreamView* sv, Region* region, Menu_Helpers::MenuList& edit_items)
Editor::add_region_context_items (AudioStreamView* sv, Region* region, Menu_Helpers::MenuList& edit_items)
{
using namespace Menu_Helpers;
Menu *region_menu = manage (new Menu);
@@ -2584,30 +2538,56 @@ void
Editor::setup_toolbar ()
{
string pixmap_path;
const guint32 FUDGE = 18; // Combo's are stupid - they steal space from the entry for the button
/* Mode Buttons (tool selection) */
vector<ToggleButton *> mouse_mode_buttons;
mouse_move_button.add (*(manage (new Image (get_xpm("tool_object.xpm")))));
mouse_move_button.set_relief(Gtk::RELIEF_NONE);
mouse_mode_buttons.push_back (&mouse_move_button);
mouse_select_button.add (*(manage (new Image (get_xpm("tool_range.xpm")))));
mouse_select_button.set_relief(Gtk::RELIEF_NONE);
mouse_mode_buttons.push_back (&mouse_select_button);
mouse_gain_button.add (*(manage (new Image (get_xpm("tool_gain.xpm")))));
mouse_gain_button.set_relief(Gtk::RELIEF_NONE);
mouse_mode_buttons.push_back (&mouse_gain_button);
mouse_zoom_button.add (*(manage (new Image (get_xpm("tool_zoom.xpm")))));
mouse_zoom_button.set_relief(Gtk::RELIEF_NONE);
mouse_mode_buttons.push_back (&mouse_zoom_button);
mouse_timefx_button.add (*(manage (new Image (get_xpm("tool_stretch.xpm")))));
mouse_timefx_button.set_relief(Gtk::RELIEF_NONE);
mouse_mode_buttons.push_back (&mouse_timefx_button);
mouse_audition_button.add (*(manage (new Image (get_xpm("tool_audition.xpm")))));
mouse_audition_button.set_relief(Gtk::RELIEF_NONE);
mouse_mode_buttons.push_back (&mouse_audition_button);
mouse_mode_button_set = new GroupedButtons (mouse_mode_buttons);
mouse_mode_button_table.set_homogeneous (true);
mouse_mode_button_table.set_col_spacings (2);
mouse_mode_button_table.set_row_spacings (2);
mouse_mode_button_table.set_border_width (5);
HBox* mode_box = manage(new HBox);
mode_box->set_border_width (2);
mode_box->set_spacing(4);
mouse_mode_button_box.set_spacing(1);
mouse_mode_button_box.pack_start(mouse_move_button, true, true);
mouse_mode_button_box.pack_start(mouse_select_button, true, true);
mouse_mode_button_box.pack_start(mouse_zoom_button, true, true);
mouse_mode_button_box.pack_start(mouse_gain_button, true, true);
mouse_mode_button_box.pack_start(mouse_timefx_button, true, true);
mouse_mode_button_box.pack_start(mouse_audition_button, true, true);
mouse_mode_button_box.set_homogeneous(true);
mouse_mode_button_table.attach (mouse_move_button, 0, 1, 0, 1);
mouse_mode_button_table.attach (mouse_select_button, 1, 2, 0, 1);
mouse_mode_button_table.attach (mouse_zoom_button, 2, 3, 0, 1);
mouse_mode_button_table.attach (mouse_gain_button, 0, 1, 1, 2);
mouse_mode_button_table.attach (mouse_timefx_button, 1, 2, 1, 2);
mouse_mode_button_table.attach (mouse_audition_button, 2, 3, 1, 2);
edit_mode_selector.set_name ("EditModeSelector");
Gtkmm2ext::set_size_request_to_display_given_text (edit_mode_selector, "Splice Edit", 2+FUDGE, 10);
set_popdown_strings (edit_mode_selector, internationalize (edit_mode_strings));
edit_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::edit_mode_selection_done));
mouse_mode_tearoff = manage (new TearOff (mouse_mode_button_table));
mode_box->pack_start(edit_mode_selector);
mode_box->pack_start(mouse_mode_button_box);
mouse_mode_tearoff = manage (new TearOff (*mode_box));
mouse_mode_tearoff->set_name ("MouseModeBase");
mouse_mode_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
@@ -2626,12 +2606,12 @@ Editor::setup_toolbar ()
mouse_timefx_button.set_name ("MouseModeButton");
mouse_audition_button.set_name ("MouseModeButton");
ARDOUR_UI::instance()->tooltips().set_tip (mouse_move_button, _("select/move objects"));
ARDOUR_UI::instance()->tooltips().set_tip (mouse_select_button, _("select/move ranges"));
ARDOUR_UI::instance()->tooltips().set_tip (mouse_gain_button, _("draw gain automation"));
ARDOUR_UI::instance()->tooltips().set_tip (mouse_zoom_button, _("select zoom range"));
ARDOUR_UI::instance()->tooltips().set_tip (mouse_timefx_button, _("stretch/shrink regions"));
ARDOUR_UI::instance()->tooltips().set_tip (mouse_audition_button, _("listen to specific regions"));
ARDOUR_UI::instance()->tooltips().set_tip (mouse_move_button, _("Select/Move Objects"));
ARDOUR_UI::instance()->tooltips().set_tip (mouse_select_button, _("Select/Move Ranges"));
ARDOUR_UI::instance()->tooltips().set_tip (mouse_gain_button, _("Draw Gain Automation"));
ARDOUR_UI::instance()->tooltips().set_tip (mouse_zoom_button, _("Select Zoom Range"));
ARDOUR_UI::instance()->tooltips().set_tip (mouse_timefx_button, _("Stretch/Shrink Regions"));
ARDOUR_UI::instance()->tooltips().set_tip (mouse_audition_button, _("Listen to Specific Regions"));
mouse_move_button.unset_flags (CAN_FOCUS);
mouse_select_button.unset_flags (CAN_FOCUS);
@@ -2650,160 +2630,82 @@ Editor::setup_toolbar ()
mouse_audition_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseAudition));
// mouse_move_button.set_active (true);
/* automation control */
global_automation_button.set_name ("MouseModeButton");
automation_mode_button.set_name ("MouseModeButton");
automation_box.set_spacing (2);
automation_box.set_border_width (2);
automation_box.pack_start (global_automation_button, false, false);
automation_box.pack_start (automation_mode_button, false, false);
/* Edit mode */
edit_mode_label.set_name ("ToolBarLabel");
edit_mode_selector.set_name ("EditModeSelector");
edit_mode_box.set_spacing (3);
edit_mode_box.set_border_width (3);
/* XXX another disgusting hack because of the way combo boxes size themselves */
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);
edit_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::edit_mode_selection_done));
/* Snap Type */
snap_type_label.set_name ("ToolBarLabel");
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");
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);
set_popdown_strings (snap_mode_selector, internationalize (snap_mode_strings));
/* Zoom */
zoom_box.set_spacing (1);
zoom_box.set_border_width (2);
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_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"));
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");
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);
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_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 */
zoom_box.pack_start (zoom_focus_selector, false, false);
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"));
/* Edit Cursor / Snap */
/* 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.set_spacing (1);
snap_box.set_border_width (2);
this also applies to the various toolbar combos
*/
snap_type_selector.set_name ("SnapTypeSelector");
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_selector.signal_changed().connect (mem_fun(*this, &Editor::snap_type_selection_done));
ARDOUR_UI::instance()->tooltips().set_tip (snap_type_selector, _("Unit to snap cursors and ranges to"));
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);
snap_mode_selector.set_name ("SnapModeSelector");
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_selector.signal_changed().connect (mem_fun(*this, &Editor::snap_mode_selection_done));
HBox* edit_clock_hbox = manage (new HBox());
VBox* edit_clock_vbox = manage (new VBox());
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);
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);
/* Nudge */
HBox* hbox = new HBox;
HBox *nudge_box = manage (new HBox);
nudge_box->set_spacing(1);
nudge_box->set_border_width (2);
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);
VBox *vbox = manage (new VBox);
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_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);
nudge_label.set_name ("ToolBarLabel");
vbox->pack_start (nudge_label, false, false);
vbox->pack_start (*nbox, false, false);
/* Pack everything in... */
hbox->pack_start (*vbox, false, false);
hbox->show_all ();
HBox* hbox = new HBox;
hbox->set_spacing(10);
tools_tearoff = new TearOff (*hbox);
tools_tearoff->set_name ("MouseModeBase");
@@ -2817,11 +2719,18 @@ Editor::setup_toolbar ()
tools_tearoff->Visible.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
&tools_tearoff->tearoff_window(), 0));
toolbar_hbox.set_spacing (8);
toolbar_hbox.set_border_width (2);
toolbar_hbox.set_spacing (10);
toolbar_hbox.set_border_width (1);
toolbar_hbox.pack_start (*tools_tearoff, false, false);
toolbar_hbox.pack_start (*mouse_mode_tearoff, false, false);
toolbar_hbox.pack_start (*tools_tearoff, false, false);
hbox->pack_start (snap_box, false, false);
hbox->pack_start (zoom_box, false, false);
hbox->pack_start (*nudge_box, false, false);
hbox->show_all ();
toolbar_base.set_name ("ToolBarBase");
toolbar_base.add (toolbar_hbox);
@@ -3101,31 +3010,31 @@ Editor::mapover_audio_tracks (slot<void,AudioTimeAxisView&,uint32_t> sl)
}
void
Editor::mapped_set_selected_regionview_from_click (AudioTimeAxisView& atv, uint32_t ignored,
AudioRegionView* basis, vector<AudioRegionView*>* all_equivs)
Editor::mapped_set_selected_regionview_from_click (RouteTimeAxisView& tv, uint32_t ignored,
RegionView* basis, vector<RegionView*>* all_equivs)
{
AudioPlaylist* pl;
vector<AudioRegion*> results;
AudioRegionView* marv;
AudioDiskstream* ds;
Playlist* pl;
vector<Region*> results;
RegionView* marv;
Diskstream* ds;
if ((ds = atv.get_diskstream()) == 0) {
if ((ds = tv.get_diskstream()) == 0) {
/* bus */
return;
}
if (&atv == &basis->get_time_axis_view()) {
if (&tv == &basis->get_time_axis_view()) {
/* looking in same track as the original */
return;
}
if ((pl = ds->playlist()) != 0) {
pl->get_equivalent_regions (basis->region, results);
if ((pl = dynamic_cast<Playlist*>(ds->playlist())) != 0) {
pl->get_equivalent_regions (basis->region(), results);
}
for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
if ((marv = atv.view->find_view (**ir)) != 0) {
for (vector<Region*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
if ((marv = tv.view()->find_view (**ir)) != 0) {
all_equivs->push_back (marv);
}
}
@@ -3134,7 +3043,7 @@ Editor::mapped_set_selected_regionview_from_click (AudioTimeAxisView& atv, uint3
bool
Editor::set_selected_regionview_from_click (bool press, Selection::Operation op, bool no_track_remove)
{
vector<AudioRegionView*> all_equivalent_regions;
vector<RegionView*> all_equivalent_regions;
bool commit = false;
if (!clicked_regionview || !clicked_audio_trackview) {
@@ -3189,7 +3098,7 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op,
commit = true;
}
for (vector<AudioRegionView*>::iterator i = all_equivalent_regions.begin(); i != all_equivalent_regions.end(); ++i) {
for (vector<RegionView*>::iterator i = all_equivalent_regions.begin(); i != all_equivalent_regions.end(); ++i) {
selection->add (*i);
}
}
@@ -3222,58 +3131,58 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op,
last_frame = 0;
first_frame = max_frames;
for (AudioRegionSelection::iterator x = selection->audio_regions.begin(); x != selection->audio_regions.end(); ++x) {
for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
if (&(*x)->get_time_axis_view() == &clicked_regionview->get_time_axis_view()) {
if ((*x)->region.last_frame() > last_frame) {
last_frame = (*x)->region.last_frame();
if ((*x)->region().last_frame() > last_frame) {
last_frame = (*x)->region().last_frame();
}
if ((*x)->region.first_frame() < first_frame) {
first_frame = (*x)->region.first_frame();
if ((*x)->region().first_frame() < first_frame) {
first_frame = (*x)->region().first_frame();
}
}
}
/* 2. figure out the boundaries for our search for new objects */
switch (clicked_regionview->region.coverage (first_frame, last_frame)) {
switch (clicked_regionview->region().coverage (first_frame, last_frame)) {
case OverlapNone:
cerr << "no overlap, first = " << first_frame << " last = " << last_frame << " region = "
<< clicked_regionview->region.first_frame() << " .. " << clicked_regionview->region.last_frame() << endl;
<< clicked_regionview->region().first_frame() << " .. " << clicked_regionview->region().last_frame() << endl;
if (last_frame < clicked_regionview->region.first_frame()) {
if (last_frame < clicked_regionview->region().first_frame()) {
first_frame = last_frame;
last_frame = clicked_regionview->region.last_frame();
last_frame = clicked_regionview->region().last_frame();
} else {
last_frame = first_frame;
first_frame = clicked_regionview->region.first_frame();
first_frame = clicked_regionview->region().first_frame();
}
break;
case OverlapExternal:
cerr << "external overlap, first = " << first_frame << " last = " << last_frame << " region = "
<< clicked_regionview->region.first_frame() << " .. " << clicked_regionview->region.last_frame() << endl;
<< clicked_regionview->region().first_frame() << " .. " << clicked_regionview->region().last_frame() << endl;
if (last_frame < clicked_regionview->region.first_frame()) {
if (last_frame < clicked_regionview->region().first_frame()) {
first_frame = last_frame;
last_frame = clicked_regionview->region.last_frame();
last_frame = clicked_regionview->region().last_frame();
} else {
last_frame = first_frame;
first_frame = clicked_regionview->region.first_frame();
first_frame = clicked_regionview->region().first_frame();
}
break;
case OverlapInternal:
cerr << "internal overlap, first = " << first_frame << " last = " << last_frame << " region = "
<< clicked_regionview->region.first_frame() << " .. " << clicked_regionview->region.last_frame() << endl;
<< clicked_regionview->region().first_frame() << " .. " << clicked_regionview->region().last_frame() << endl;
if (last_frame < clicked_regionview->region.first_frame()) {
if (last_frame < clicked_regionview->region().first_frame()) {
first_frame = last_frame;
last_frame = clicked_regionview->region.last_frame();
last_frame = clicked_regionview->region().last_frame();
} else {
last_frame = first_frame;
first_frame = clicked_regionview->region.first_frame();
first_frame = clicked_regionview->region().first_frame();
}
break;
@@ -3299,18 +3208,18 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op,
/* 3. convert to a vector of audio regions */
vector<AudioRegionView*> audio_regions;
vector<RegionView*> regions;
for (list<Selectable*>::iterator x = results.begin(); x != results.end(); ++x) {
AudioRegionView* arv;
RegionView* arv;
if ((arv = dynamic_cast<AudioRegionView*>(*x)) != 0) {
audio_regions.push_back (arv);
if ((arv = dynamic_cast<RegionView*>(*x)) != 0) {
regions.push_back (arv);
}
}
if (!audio_regions.empty()) {
selection->add (audio_regions);
if (!regions.empty()) {
selection->add (regions);
commit = true;
}
}
@@ -3320,37 +3229,32 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op,
}
void
Editor::set_selected_regionview_from_region_list (Region& r, Selection::Operation op)
Editor::set_selected_regionview_from_region_list (Region& region, Selection::Operation op)
{
vector<AudioRegionView*> all_equivalent_regions;
AudioRegion* region;
if ((region = dynamic_cast<AudioRegion*>(&r)) == 0) {
return;
}
vector<RegionView*> all_equivalent_regions;
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
AudioTimeAxisView* tatv;
RouteTimeAxisView* tatv;
if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
AudioPlaylist* pl;
vector<AudioRegion*> results;
AudioRegionView* marv;
AudioDiskstream* ds;
Playlist* pl;
vector<Region*> results;
RegionView* marv;
Diskstream* ds;
if ((ds = tatv->get_diskstream()) == 0) {
/* bus */
continue;
}
if ((pl = ds->playlist()) != 0) {
pl->get_region_list_equivalent_regions (*region, results);
if ((pl = dynamic_cast<Playlist*>(ds->playlist())) != 0) {
pl->get_region_list_equivalent_regions (region, results);
}
for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
if ((marv = tatv->view->find_view (**ir)) != 0) {
for (vector<Region*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
if ((marv = tatv->view()->find_view (**ir)) != 0) {
all_equivalent_regions.push_back (marv);
}
}
@@ -3379,10 +3283,10 @@ Editor::set_selected_regionview_from_region_list (Region& r, Selection::Operatio
bool
Editor::set_selected_regionview_from_map_event (GdkEventAny* ev, StreamView* sv, Region* r)
{
AudioRegionView* rv;
AudioRegion* ar;
RegionView* rv;
Region* ar;
if ((ar = dynamic_cast<AudioRegion*> (r)) == 0) {
if ((ar = dynamic_cast<Region*> (r)) == 0) {
return TRUE;
}
@@ -3394,7 +3298,7 @@ Editor::set_selected_regionview_from_map_event (GdkEventAny* ev, StreamView* sv,
a single other region.
*/
if (selection->audio_regions.size() > 1) {
if (selection->regions.size() > 1) {
return TRUE;
}
@@ -3559,7 +3463,7 @@ Editor::duplicate_dialog (bool dup_region)
if (sscanf (text.c_str(), "%f", &times) == 1) {
if (dup_region) {
AudioRegionSelection regions;
RegionSelection regions;
regions.add (clicked_regionview);
duplicate_some_regions (regions, times);
} else {
@@ -3610,9 +3514,9 @@ Editor::edit_mode_selection_done ()
string choice = edit_mode_selector.get_active_text();
EditMode mode = Slide;
if (choice == _("Splice")) {
if (choice == _("Splice Edit")) {
mode = Splice;
} else if (choice == _("Slide")) {
} else if (choice == _("Slide Edit")) {
mode = Slide;
}
@@ -3628,18 +3532,18 @@ Editor::snap_type_selection_done ()
string choice = snap_type_selector.get_active_text();
SnapType snaptype = SnapToFrame;
if (choice == _("Beats/3")) {
snaptype = SnapToAThirdBeat;
} else if (choice == _("Beats/4")) {
snaptype = SnapToAQuarterBeat;
} else if (choice == _("Beats/8")) {
snaptype = SnapToAEighthBeat;
} else if (choice == _("Beats/16")) {
snaptype = SnapToASixteenthBeat;
} else if (choice == _("Beats/32")) {
snaptype = SnapToAThirtysecondBeat;
} else if (choice == _("Beats")) {
snaptype = SnapToAThirdBeat;
} else if (choice == _("Beats/4")) {
snaptype = SnapToAQuarterBeat;
} else if (choice == _("Beats/8")) {
snaptype = SnapToAEighthBeat;
} else if (choice == _("Beats/16")) {
snaptype = SnapToASixteenthBeat;
} else if (choice == _("Beats/32")) {
snaptype = SnapToAThirtysecondBeat;
} else if (choice == _("Beats")) {
snaptype = SnapToBeat;
} else if (choice == _("Bars")) {
snaptype = SnapToBar;
@@ -3667,10 +3571,10 @@ Editor::snap_type_selection_done ()
snaptype = SnapToSeconds;
} else if (choice == _("Minutes")) {
snaptype = SnapToMinutes;
} else if (choice == _("None")) {
} else if (choice == _("None")) {
snaptype = SnapToFrame;
}
set_snap_to (snaptype);
}
@@ -3684,9 +3588,9 @@ Editor::snap_mode_selection_done ()
string choice = snap_mode_selector.get_active_text();
SnapMode mode = SnapNormal;
if (choice == _("Normal")) {
if (choice == _("Normal Snap")) {
mode = SnapNormal;
} else if (choice == _("Magnetic")) {
} else if (choice == _("Magnetic Snap")) {
mode = SnapMagnetic;
}
@@ -3703,15 +3607,15 @@ Editor::zoom_focus_selection_done ()
string choice = zoom_focus_selector.get_active_text();
ZoomFocus focus_type = ZoomFocusLeft;
if (choice == _("Left")) {
if (choice == _("Focus Left")) {
focus_type = ZoomFocusLeft;
} else if (choice == _("Right")) {
} else if (choice == _("Focus Right")) {
focus_type = ZoomFocusRight;
} else if (choice == _("Center")) {
} else if (choice == _("Focus Center")) {
focus_type = ZoomFocusCenter;
} else if (choice == _("Playhead")) {
} else if (choice == _("Focus Playhead")) {
focus_type = ZoomFocusPlayhead;
} else if (choice == _("Edit Cursor")) {
} else if (choice == _("Focus Edit Cursor")) {
focus_type = ZoomFocusEdit;
}
@@ -3781,7 +3685,7 @@ void
Editor::region_selection_changed ()
{
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
(*i)->set_selected_regionviews (selection->audio_regions);
(*i)->set_selected_regionviews (selection->regions);
}
}
@@ -4051,8 +3955,8 @@ Editor::playlist_deletion_dialog (Playlist* pl)
bool
Editor::audio_region_selection_covers (jack_nframes_t where)
{
for (AudioRegionSelection::iterator a = selection->audio_regions.begin(); a != selection->audio_regions.end(); ++a) {
if ((*a)->region.covers (where)) {
for (RegionSelection::iterator a = selection->regions.begin(); a != selection->regions.end(); ++a) {
if ((*a)->region().covers (where)) {
return true;
}
}
@@ -4063,10 +3967,10 @@ Editor::audio_region_selection_covers (jack_nframes_t where)
void
Editor::prepare_for_cleanup ()
{
cut_buffer->clear_audio_regions ();
cut_buffer->clear_regions ();
cut_buffer->clear_playlists ();
selection->clear_audio_regions ();
selection->clear_regions ();
selection->clear_playlists ();
}

View File

@@ -69,6 +69,7 @@ namespace ARDOUR {
class AudioDiskstream;
class RouteGroup;
class Playlist;
class AudioPlaylist;
class Region;
class Location;
class TempoSection;
@@ -83,6 +84,7 @@ namespace LADSPA {
}
class TimeAxisView;
class RouteTimeAxisView;
class AudioTimeAxisView;
class AutomationTimeAxisView;
class AudioRegionView;
@@ -100,6 +102,7 @@ class TrackSelection;
class AutomationSelection;
class MixerStrip;
class StreamView;
class AudioStreamView;
class ControlPoint;
#ifdef FFT_ANALYSIS
class AnalysisWindow;
@@ -405,8 +408,8 @@ class Editor : public PublicEditor
TimeAxisView* clicked_trackview;
AudioTimeAxisView* clicked_audio_trackview;
AudioRegionView* clicked_regionview;
AudioRegionView* latest_regionview;
RegionView* clicked_regionview;
RegionView* latest_regionview;
uint32_t clicked_selection;
CrossfadeView* clicked_crossfadeview;
ControlPoint* clicked_control_point;
@@ -416,7 +419,7 @@ class Editor : public PublicEditor
/* functions to be passed to mapover_audio_tracks(), possibly with sigc::bind()-supplied arguments */
void mapped_set_selected_regionview_from_click (AudioTimeAxisView&, uint32_t, AudioRegionView*, vector<AudioRegionView*>*);
void mapped_set_selected_regionview_from_click (RouteTimeAxisView&, uint32_t, RegionView*, vector<RegionView*>*);
void mapped_use_new_playlist (AudioTimeAxisView&, uint32_t);
void mapped_use_copy_playlist (AudioTimeAxisView&, uint32_t);
void mapped_clear_playlist (AudioTimeAxisView&, uint32_t);
@@ -426,7 +429,7 @@ class Editor : public PublicEditor
void button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type);
bool button_release_can_deselect;
void catch_vanishing_audio_regionview (AudioRegionView *);
void catch_vanishing_regionview (RegionView *);
bool set_selected_control_point_from_click (bool press, Selection::Operation op = Selection::Set, bool with_undo = true, bool no_remove=false);
bool set_selected_track_from_click (bool press, Selection::Operation op = Selection::Set, bool with_undo = true, bool no_remove=false);
@@ -434,7 +437,7 @@ class Editor : public PublicEditor
void set_selected_regionview_from_region_list (ARDOUR::Region& region, Selection::Operation op = Selection::Set);
bool set_selected_regionview_from_map_event (GdkEventAny*, StreamView*, ARDOUR::Region*);
void collect_new_region_view (AudioRegionView *);
void collect_new_region_view (RegionView *);
Gtk::Menu track_context_menu;
Gtk::Menu track_region_context_menu;
@@ -455,12 +458,11 @@ class Editor : public PublicEditor
Gtk::Menu* build_track_selection_context_menu (jack_nframes_t);
void add_dstream_context_items (Gtk::Menu_Helpers::MenuList&);
void add_bus_context_items (Gtk::Menu_Helpers::MenuList&);
void add_region_context_items (StreamView*, ARDOUR::Region*, Gtk::Menu_Helpers::MenuList&);
void add_crossfade_context_items (StreamView*, ARDOUR::Crossfade*, Gtk::Menu_Helpers::MenuList&, bool many);
void add_region_context_items (AudioStreamView*, ARDOUR::Region*, Gtk::Menu_Helpers::MenuList&);
void add_crossfade_context_items (AudioStreamView*, ARDOUR::Crossfade*, Gtk::Menu_Helpers::MenuList&, bool many);
void add_selection_context_items (Gtk::Menu_Helpers::MenuList&);
void handle_new_route (boost::shared_ptr<ARDOUR::Route>);
void handle_new_route_p (boost::shared_ptr<ARDOUR::Route>);
void remove_route (TimeAxisView *);
bool route_removal;
@@ -854,7 +856,7 @@ class Editor : public PublicEditor
void lower_region_to_bottom ();
void split_region ();
void split_region_at (jack_nframes_t);
void split_regions_at (jack_nframes_t, AudioRegionSelection&);
void split_regions_at (jack_nframes_t, RegionSelection&);
void crop_region_to_selection ();
void set_a_regions_sync_position (ARDOUR::Region&, jack_nframes_t);
void set_region_sync_from_edit_cursor ();
@@ -867,13 +869,13 @@ class Editor : public PublicEditor
void remove_clicked_region ();
void destroy_clicked_region ();
void edit_region ();
void duplicate_some_regions (AudioRegionSelection&, float times);
void duplicate_some_regions (RegionSelection&, float times);
void duplicate_selection (float times);
void region_fill_selection ();
void region_fill_track ();
void audition_playlist_region_standalone (ARDOUR::AudioRegion&);
void audition_playlist_region_via_route (ARDOUR::AudioRegion&, ARDOUR::Route&);
void audition_playlist_region_standalone (ARDOUR::Region&);
void audition_playlist_region_via_route (ARDOUR::Region&, ARDOUR::Route&);
void split_multichannel_region();
void reverse_region ();
void normalize_region ();
@@ -1020,7 +1022,7 @@ class Editor : public PublicEditor
bool have_pending_keyboard_selection;
jack_nframes_t pending_keyboard_selection_start;
ARDOUR::AudioRegion* select_region_for_operation (int dir, TimeAxisView **tv);
ARDOUR::Region* select_region_for_operation (int dir, TimeAxisView **tv);
void extend_selection_to_end_of_region (bool next);
void extend_selection_to_start_of_region (bool previous);
@@ -1094,7 +1096,7 @@ class Editor : public PublicEditor
void remove_gain_control_point (ArdourCanvas::Item*, GdkEvent*);
void remove_control_point (ArdourCanvas::Item*, GdkEvent*);
void mouse_brush_insert_region (AudioRegionView*, jack_nframes_t pos);
void mouse_brush_insert_region (RegionView*, jack_nframes_t pos);
void brush (jack_nframes_t);
void show_verbose_time_cursor (jack_nframes_t frame, double offset = 0, double xpos=-1, double ypos=-1);
@@ -1112,10 +1114,10 @@ class Editor : public PublicEditor
bool canvas_fade_in_handle_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*);
bool canvas_fade_out_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*);
bool canvas_fade_out_handle_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*);
bool canvas_region_view_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*);
bool canvas_region_view_name_highlight_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*);
bool canvas_region_view_name_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*);
bool canvas_stream_view_event (GdkEvent* event,ArdourCanvas::Item*, AudioTimeAxisView*);
bool canvas_region_view_event (GdkEvent* event,ArdourCanvas::Item*, RegionView*);
bool canvas_region_view_name_highlight_event (GdkEvent* event,ArdourCanvas::Item*, RegionView*);
bool canvas_region_view_name_event (GdkEvent* event,ArdourCanvas::Item*, RegionView*);
bool canvas_stream_view_event (GdkEvent* event,ArdourCanvas::Item*, RouteTimeAxisView*);
bool canvas_marker_event (GdkEvent* event,ArdourCanvas::Item*, Marker*);
bool canvas_zoom_rect_event (GdkEvent* event,ArdourCanvas::Item*);
bool canvas_tempo_marker_event (GdkEvent* event,ArdourCanvas::Item*, TempoMarker*);
@@ -1263,12 +1265,7 @@ class Editor : public PublicEditor
void editor_mixer_button_toggled ();
AudioClock selection_start_clock;
Gtk::Label selection_start_clock_label;
AudioClock selection_end_clock;
Gtk::Label selection_end_clock_label;
AudioClock edit_cursor_clock;
Gtk::Label edit_cursor_clock_label;
AudioClock zoom_range_clock;
Gtk::Button zoom_in_button;
Gtk::Button zoom_out_button;
@@ -1280,8 +1277,8 @@ class Editor : public PublicEditor
Gtk::Table toolbar_selection_clock_table;
Gtk::Label toolbar_selection_cursor_label;
Gtk::Table mouse_mode_button_table;
Gtkmm2ext::TearOff* mouse_mode_tearoff;
Gtk::HBox mouse_mode_button_box;
Gtkmm2ext::TearOff* mouse_mode_tearoff;
Gtk::ToggleButton mouse_select_button;
Gtk::ToggleButton mouse_move_button;
Gtk::ToggleButton mouse_gain_button;
@@ -1299,32 +1296,23 @@ class Editor : public PublicEditor
Gtk::ToggleButton global_automation_button;
Gtk::ComboBoxText edit_mode_selector;
Gtk::Label edit_mode_label;
Gtk::VBox edit_mode_box;
Gtk::VBox edit_mode_box;
void edit_mode_selection_done ();
Gtk::ComboBoxText snap_type_selector;
Gtk::Label snap_type_label;
Gtk::VBox snap_type_box;
Gtk::ComboBoxText snap_mode_selector;
Gtk::HBox snap_box;
void snap_type_selection_done ();
Gtk::ComboBoxText snap_mode_selector;
Gtk::Label snap_mode_label;
Gtk::VBox snap_mode_box;
void snap_mode_selection_done ();
Gtk::ComboBoxText zoom_focus_selector;
Gtk::Label zoom_focus_label;
Gtk::VBox zoom_focus_box;
void zoom_focus_selection_done ();
Gtk::Label zoom_indicator_label;
Gtk::HBox zoom_indicator_box;
Gtk::VBox zoom_indicator_vbox;
Gtk::HBox zoom_box;
void update_zoom_indicator ();
void zoom_adjustment_changed();
@@ -1533,12 +1521,12 @@ class Editor : public PublicEditor
void start_trim (ArdourCanvas::Item*, GdkEvent*);
void point_trim (GdkEvent*);
void trim_motion_callback (ArdourCanvas::Item*, GdkEvent*);
void single_contents_trim (AudioRegionView&, jack_nframes_t, bool, bool, bool);
void single_start_trim (AudioRegionView&, jack_nframes_t, bool, bool);
void single_end_trim (AudioRegionView&, jack_nframes_t, bool, bool);
void single_contents_trim (RegionView&, jack_nframes_t, bool, bool, bool);
void single_start_trim (RegionView&, jack_nframes_t, bool, bool);
void single_end_trim (RegionView&, jack_nframes_t, bool, bool);
void trim_finished_callback (ArdourCanvas::Item*, GdkEvent*);
void thaw_region_after_trim (AudioRegionView& rv);
void thaw_region_after_trim (RegionView& rv);
void trim_region_to_edit_cursor ();
void trim_region_from_edit_cursor ();
@@ -1592,7 +1580,7 @@ class Editor : public PublicEditor
void export_range (jack_nframes_t start, jack_nframes_t end);
void export_range_markers ();
int write_region_selection(AudioRegionSelection&);
int write_region_selection(RegionSelection&);
bool write_region (string path, ARDOUR::AudioRegion&);
void export_region ();
void bounce_region_selection ();
@@ -1600,7 +1588,7 @@ class Editor : public PublicEditor
void external_edit_region ();
int write_audio_selection (TimeSelection&);
bool write_audio_range (ARDOUR::Playlist&, uint32_t channels, list<ARDOUR::AudioRange>&);
bool write_audio_range (ARDOUR::AudioPlaylist&, uint32_t channels, list<ARDOUR::AudioRange>&);
void write_selection ();
@@ -1670,7 +1658,7 @@ class Editor : public PublicEditor
struct TimeStretchDialog : public ArdourDialog {
ARDOUR::Session::TimeStretchRequest request;
Editor& editor;
AudioRegionSelection regions;
RegionSelection regions;
Gtk::ProgressBar progress_bar;
Gtk::ToggleButton quick_button;
Gtk::ToggleButton antialias_button;
@@ -1696,7 +1684,7 @@ class Editor : public PublicEditor
TimeStretchDialog* current_timestretch;
static void* timestretch_thread (void *arg);
int run_timestretch (AudioRegionSelection&, float fraction);
int run_timestretch (RegionSelection&, float fraction);
void do_timestretch (TimeStretchDialog&);
/* editor-mixer strip */
@@ -1775,7 +1763,6 @@ class Editor : public PublicEditor
Gtk::Button nudge_backward_button;
Gtk::HBox nudge_hbox;
Gtk::VBox nudge_vbox;
Gtk::Label nudge_label;
AudioClock nudge_clock;
jack_nframes_t get_nudge_distance (jack_nframes_t pos, jack_nframes_t& next);
@@ -1798,11 +1785,11 @@ class Editor : public PublicEditor
sigc::connection step_timeout;
TimeAxisView* entered_track;
AudioRegionView* entered_regionview;
RegionView* entered_regionview;
bool clear_entered_track;
gint left_track_canvas (GdkEventCrossing*);
void set_entered_track (TimeAxisView*);
void set_entered_regionview (AudioRegionView*);
void set_entered_regionview (RegionView*);
gint left_automation_track ();
bool _new_regionviews_show_envelope;

View File

@@ -316,7 +316,7 @@ Editor::finish_bringing_in_audio (AudioRegion& region, uint32_t in_chans, uint32
case ImportToTrack:
if (track) {
Playlist* playlist = track->disk_stream().playlist();
Playlist* playlist = track->diskstream().playlist();
AudioRegion* copy = new AudioRegion (region);
begin_reversible_command (_("insert sndfile"));
@@ -333,7 +333,7 @@ Editor::finish_bringing_in_audio (AudioRegion& region, uint32_t in_chans, uint32
{
boost::shared_ptr<AudioTrack> at (session->new_audio_track (in_chans, out_chans, Normal));
copy = new AudioRegion (region);
at->disk_stream().playlist()->add_region (*copy, pos);
at->diskstream().playlist()->add_region (*copy, pos);
break;
}
@@ -341,7 +341,7 @@ Editor::finish_bringing_in_audio (AudioRegion& region, uint32_t in_chans, uint32
{
boost::shared_ptr<AudioTrack> at (session->new_audio_track (in_chans, out_chans, Destructive));
copy = new AudioRegion (region);
at->disk_stream().playlist()->add_region (*copy, pos);
at->diskstream().playlist()->add_region (*copy, pos);
break;
}
}

View File

@@ -4,7 +4,7 @@
#include "editor.h"
#include "editing.h"
#include "audio_time_axis.h"
#include "regionview.h"
#include "region_view.h"
#include "selection.h"
using namespace ARDOUR;

View File

@@ -26,8 +26,8 @@
#include "editor.h"
#include "public_editor.h"
#include "regionview.h"
#include "streamview.h"
#include "audio_region_view.h"
#include "audio_streamview.h"
#include "crossfade_view.h"
#include "audio_time_axis.h"
#include "region_gain_line.h"
@@ -212,7 +212,7 @@ Editor::typed_event (ArdourCanvas::Item* item, GdkEvent *event, ItemType type)
}
bool
Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView *rv)
{
gint ret = FALSE;
@@ -251,7 +251,7 @@ Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, Aud
}
bool
Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, AudioTimeAxisView *tv)
Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, RouteTimeAxisView *tv)
{
bool ret = FALSE;
@@ -262,7 +262,7 @@ Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, Aud
clicked_regionview = 0;
clicked_control_point = 0;
clicked_trackview = tv;
clicked_audio_trackview = tv;
clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(tv);
ret = button_press_handler (item, event, StreamItem);
break;
@@ -512,22 +512,25 @@ Editor::canvas_crossfade_view_event (GdkEvent* event, ArdourCanvas::Item* item,
if ((atv = dynamic_cast<AudioTimeAxisView*>(&tv)) != 0) {
if (atv->is_audio_track()) {
AudioPlaylist* pl = atv->get_diskstream()->playlist();
Playlist::RegionList* rl = pl->regions_at (event_frame (event));
if (!rl->empty()) {
DescendingRegionLayerSorter cmp;
rl->sort (cmp);
AudioPlaylist* pl;
if ((pl = dynamic_cast<AudioPlaylist*> (atv->get_diskstream()->playlist())) != 0) {
AudioRegionView* arv = atv->view->find_view (*(dynamic_cast<AudioRegion*> (rl->front())));
Playlist::RegionList* rl = pl->regions_at (event_frame (event));
/* proxy */
delete rl;
if (!rl->empty()) {
DescendingRegionLayerSorter cmp;
rl->sort (cmp);
return canvas_region_view_event (event, arv->get_canvas_group(), arv);
}
RegionView* rv = atv->view()->find_view (*rl->front());
/* proxy */
delete rl;
return canvas_region_view_event (event, rv->get_canvas_group(), rv);
}
}
}
}
@@ -696,7 +699,7 @@ Editor::canvas_selection_end_trim_event (GdkEvent *event, ArdourCanvas::Item* it
bool
Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::Item* item, AudioRegionView* rv)
Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
{
bool ret = false;
@@ -708,20 +711,20 @@ Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::
clicked_control_point = 0;
clicked_trackview = &clicked_regionview->get_time_axis_view();
clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
ret = button_press_handler (item, event, AudioRegionViewNameHighlight);
ret = button_press_handler (item, event, RegionViewNameHighlight);
break;
case GDK_BUTTON_RELEASE:
ret = button_release_handler (item, event, AudioRegionViewNameHighlight);
ret = button_release_handler (item, event, RegionViewNameHighlight);
break;
case GDK_MOTION_NOTIFY:
ret = motion_handler (item, event, AudioRegionViewNameHighlight);
ret = motion_handler (item, event, RegionViewNameHighlight);
break;
case GDK_ENTER_NOTIFY:
ret = enter_handler (item, event, AudioRegionViewNameHighlight);
ret = enter_handler (item, event, RegionViewNameHighlight);
break;
case GDK_LEAVE_NOTIFY:
ret = leave_handler (item, event, AudioRegionViewNameHighlight);
ret = leave_handler (item, event, RegionViewNameHighlight);
break;
default:
@@ -732,7 +735,7 @@ Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::
}
bool
Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView* rv)
Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView* rv)
{
bool ret = false;
@@ -744,20 +747,20 @@ Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item
clicked_control_point = 0;
clicked_trackview = &clicked_regionview->get_time_axis_view();
clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
ret = button_press_handler (item, event, AudioRegionViewName);
ret = button_press_handler (item, event, RegionViewName);
break;
case GDK_BUTTON_RELEASE:
ret = button_release_handler (item, event, AudioRegionViewName);
ret = button_release_handler (item, event, RegionViewName);
break;
case GDK_MOTION_NOTIFY:
ret = motion_handler (item, event, AudioRegionViewName);
ret = motion_handler (item, event, RegionViewName);
break;
case GDK_ENTER_NOTIFY:
ret = enter_handler (item, event, AudioRegionViewName);
ret = enter_handler (item, event, RegionViewName);
break;
case GDK_LEAVE_NOTIFY:
ret = leave_handler (item, event, AudioRegionViewName);
ret = leave_handler (item, event, RegionViewName);
break;
default:

View File

@@ -31,7 +31,7 @@
#include "selection.h"
#include "time_axis_view.h"
#include "audio_time_axis.h"
#include "regionview.h"
#include "audio_region_view.h"
#include <pbd/pthread_utils.h>
#include <ardour/types.h>
@@ -92,12 +92,12 @@ Editor::export_region ()
return;
}
ExportDialog* dialog = new ExportRegionDialog (*this, &clicked_regionview->region);
ExportDialog* dialog = new ExportRegionDialog (*this, &clicked_regionview->region());
dialog->connect_to_session (session);
dialog->set_range (
clicked_regionview->region.first_frame(),
clicked_regionview->region.last_frame());
clicked_regionview->region().first_frame(),
clicked_regionview->region().last_frame());
dialog->start_export();
}
@@ -123,24 +123,26 @@ Editor::export_range_markers ()
}
int
Editor::write_region_selection (AudioRegionSelection& regions)
Editor::write_region_selection (RegionSelection& regions)
{
for (AudioRegionSelection::iterator i = regions.begin(); i != regions.end(); ++i) {
if (write_region ("", (*i)->region) == false) {
return -1;
}
for (RegionSelection::iterator i = regions.begin(); i != regions.end(); ++i) {
AudioRegionView* arv = dynamic_cast<AudioRegionView*>(*i);
if (arv)
if (write_region ("", arv->audio_region()) == false)
return -1;
}
return 0;
}
void
Editor::bounce_region_selection ()
{
for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
AudioRegion& region ((*i)->region);
AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&(*i)->get_time_axis_view());
AudioTrack* track = dynamic_cast<AudioTrack*>(atv->route().get());
Region& region ((*i)->region());
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(&(*i)->get_time_axis_view());
Track* track = dynamic_cast<Track*>(rtv->route().get());
InterThreadInfo itt;
@@ -287,7 +289,7 @@ Editor::write_audio_selection (TimeSelection& ts)
if (atv->is_audio_track()) {
Playlist* playlist = atv->get_diskstream()->playlist();
AudioPlaylist* playlist = dynamic_cast<AudioPlaylist*>(atv->get_diskstream()->playlist());
if (playlist && write_audio_range (*playlist, atv->get_diskstream()->n_channels(), ts) == 0) {
ret = -1;
@@ -300,7 +302,7 @@ Editor::write_audio_selection (TimeSelection& ts)
}
bool
Editor::write_audio_range (Playlist& playlist, uint32_t channels, list<AudioRange>& range)
Editor::write_audio_range (AudioPlaylist& playlist, uint32_t channels, list<AudioRange>& range)
{
AudioFileSource* fs;
const jack_nframes_t chunk_size = 4096;
@@ -435,7 +437,7 @@ Editor::write_selection ()
{
if (!selection->time.empty()) {
write_audio_selection (selection->time);
} else if (!selection->audio_regions.empty()) {
write_region_selection (selection->audio_regions);
} else if (!selection->regions.empty()) {
write_region_selection (selection->regions);
}
}

View File

@@ -23,8 +23,8 @@ enum ItemType {
TempoMarkerItem,
MeterBarItem,
TempoBarItem,
AudioRegionViewNameHighlight,
AudioRegionViewName,
RegionViewNameHighlight,
RegionViewName,
StartSelectionTrimItem,
EndSelectionTrimItem,
AutomationTrackItem,

View File

@@ -22,7 +22,7 @@
#include <ardour/playlist.h>
#include "editor.h"
#include "regionview.h"
#include "region_view.h"
#include "selection.h"
#include "i18n.h"
@@ -81,10 +81,10 @@ Editor::kbd_do_split (GdkEvent* ev)
jack_nframes_t where = event_frame (ev);
if (entered_regionview) {
if (selection->audio_regions.find (entered_regionview) != selection->audio_regions.end()) {
split_regions_at (where, selection->audio_regions);
if (selection->regions.find (entered_regionview) != selection->regions.end()) {
split_regions_at (where, selection->regions);
} else {
AudioRegionSelection s;
RegionSelection s;
s.add (entered_regionview);
split_regions_at (where, s);
}
@@ -102,11 +102,11 @@ Editor::kbd_mute_unmute_region ()
{
if (entered_regionview) {
begin_reversible_command (_("mute region"));
session->add_undo (entered_regionview->region.playlist()->get_memento());
session->add_undo (entered_regionview->region().playlist()->get_memento());
entered_regionview->region.set_muted (!entered_regionview->region.muted());
entered_regionview->region().set_muted (!entered_regionview->region().muted());
session->add_redo_no_execute (entered_regionview->region.playlist()->get_memento());
session->add_redo_no_execute (entered_regionview->region().playlist()->get_memento());
commit_reversible_command();
}
}
@@ -124,7 +124,7 @@ Editor::kbd_do_set_sync_position (GdkEvent* ev)
snap_to (where);
if (entered_regionview) {
set_a_regions_sync_position (entered_regionview->region, where);
set_a_regions_sync_position (entered_regionview->region(), where);
}
}

View File

@@ -30,7 +30,7 @@
#include "ardour_ui.h"
#include "editor.h"
#include "time_axis_view.h"
#include "regionview.h"
#include "region_view.h"
#include "selection.h"
#include "i18n.h"
@@ -66,7 +66,7 @@ Editor::keyboard_selection_begin ()
void
Editor::keyboard_duplicate_region ()
{
if (selection->audio_regions.empty()) {
if (selection->regions.empty()) {
return;
}
@@ -74,9 +74,9 @@ Editor::keyboard_duplicate_region ()
bool was_floating;
if (get_prefix (prefix, was_floating) == 0) {
duplicate_some_regions (selection->audio_regions, prefix);
duplicate_some_regions (selection->regions, prefix);
} else {
duplicate_some_regions (selection->audio_regions, 1);
duplicate_some_regions (selection->regions, 1);
}
}

View File

@@ -714,9 +714,9 @@ Editor::marker_menu_set_from_selection ()
}
}
else {
if (!selection->audio_regions.empty()) {
l->set_start (selection->audio_regions.start());
l->set_end (selection->audio_regions.end_frame());
if (!selection->regions.empty()) {
l->set_start (selection->regions.start());
l->set_end (selection->regions.end_frame());
}
}
}

View File

@@ -270,8 +270,6 @@ Editor::session_going_away ()
group_model->clear ();
edit_cursor_clock.set_session (0);
selection_start_clock.set_session (0);
selection_end_clock.set_session (0);
zoom_range_clock.set_session (0);
nudge_clock.set_session (0);

View File

@@ -18,6 +18,7 @@
$Id$
*/
#include <cassert>
#include <cstdlib>
#include <stdint.h>
#include <cmath>
@@ -32,7 +33,7 @@
#include "editor.h"
#include "time_axis_view.h"
#include "audio_time_axis.h"
#include "regionview.h"
#include "audio_region_view.h"
#include "marker.h"
#include "streamview.h"
#include "region_gain_line.h"
@@ -182,7 +183,7 @@ Editor::set_mouse_mode (MouseMode m, bool force)
show the object (region) selection.
*/
for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
(*i)->set_should_show_selection (true);
}
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
@@ -319,8 +320,8 @@ Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType it
commit = (c1 || c2);
break;
case AudioRegionViewNameHighlight:
case AudioRegionViewName:
case RegionViewNameHighlight:
case RegionViewName:
c1 = set_selected_track_from_click (press, op, true, true);
c2 = set_selected_regionview_from_click (press, op, true);
commit = (c1 || c2);
@@ -521,12 +522,12 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
}
break;
case AudioRegionViewNameHighlight:
case RegionViewNameHighlight:
start_trim (item, event);
return true;
break;
case AudioRegionViewName:
case RegionViewName:
/* rename happens on edit clicks */
start_trim (clicked_regionview->get_name_highlight(), event);
return true;
@@ -692,12 +693,12 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
switch (item_type) {
case AudioRegionViewNameHighlight:
case RegionViewNameHighlight:
start_trim (item, event);
return true;
break;
case AudioRegionViewName:
case RegionViewName:
start_trim (clicked_regionview->get_name_highlight(), event);
return true;
break;
@@ -853,7 +854,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
edit_meter_marker (item);
break;
case AudioRegionViewName:
case RegionViewName:
if (clicked_regionview->name_active()) {
return mouse_rename_region (item, event);
}
@@ -888,8 +889,8 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
break;
case RegionItem:
case AudioRegionViewNameHighlight:
case AudioRegionViewName:
case RegionViewNameHighlight:
case RegionViewName:
popup_track_context_menu (1, event->button.time, item_type, false, where);
break;
@@ -1047,9 +1048,13 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
break;
case MouseGain:
// Gain only makes sense for audio regions
if ( ! dynamic_cast<AudioRegionView*>(clicked_regionview))
break;
switch (item_type) {
case RegionItem:
clicked_regionview->add_gain_point_event (item, event);
dynamic_cast<AudioRegionView*>(clicked_regionview)->add_gain_point_event (item, event);
return true;
break;
@@ -1203,7 +1208,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
}
break;
case AudioRegionViewNameHighlight:
case RegionViewNameHighlight:
if (is_drawable() && mouse_mode == MouseObject) {
track_canvas.get_window()->set_cursor (*trimmer_cursor);
}
@@ -1230,11 +1235,11 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
}
break;
case AudioRegionViewName:
case RegionViewName:
/* when the name is not an active item, the entire name highlight is for trimming */
if (!reinterpret_cast<AudioRegionView *> (item->get_data ("regionview"))->name_active()) {
if (!reinterpret_cast<RegionView *> (item->get_data ("regionview"))->name_active()) {
if (mouse_mode == MouseObject && is_drawable()) {
track_canvas.get_window()->set_cursor (*trimmer_cursor);
}
@@ -1339,7 +1344,7 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
ControlPoint* cp;
Marker *marker;
Location *loc;
AudioRegionView* rv;
RegionView* rv;
bool is_start;
switch (item_type) {
@@ -1361,7 +1366,7 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
hide_verbose_canvas_cursor ();
break;
case AudioRegionViewNameHighlight:
case RegionViewNameHighlight:
case StartSelectionTrimItem:
case EndSelectionTrimItem:
case EditCursorItem:
@@ -1392,9 +1397,9 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
}
break;
case AudioRegionViewName:
case RegionViewName:
/* see enter_handler() for notes */
if (!reinterpret_cast<AudioRegionView *> (item->get_data ("regionview"))->name_active()) {
if (!reinterpret_cast<RegionView *> (item->get_data ("regionview"))->name_active()) {
if (is_drawable() && mouse_mode == MouseObject) {
track_canvas.get_window()->set_cursor (*current_canvas_cursor);
}
@@ -1429,7 +1434,7 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
case FadeInHandleItem:
case FadeOutHandleItem:
rv = static_cast<AudioRegionView*>(item->get_data ("regionview"));
rv = static_cast<RegionView*>(item->get_data ("regionview"));
{
ArdourCanvas::SimpleRect *rect = dynamic_cast<ArdourCanvas::SimpleRect *> (item);
if (rect) {
@@ -1524,7 +1529,7 @@ Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item
case PanAutomationControlPointItem:
case TempoMarkerItem:
case MeterMarkerItem:
case AudioRegionViewNameHighlight:
case RegionViewNameHighlight:
case StartSelectionTrimItem:
case EndSelectionTrimItem:
case SelectionItem:
@@ -1745,7 +1750,7 @@ Editor::start_fade_in_grab (ArdourCanvas::Item* item, GdkEvent* event)
AudioRegionView* arv = static_cast<AudioRegionView*>(drag_info.data);
drag_info.pointer_frame_offset = drag_info.grab_frame - ((jack_nframes_t) arv->region.fade_in().back()->when + arv->region.position());
drag_info.pointer_frame_offset = drag_info.grab_frame - ((jack_nframes_t) arv->audio_region().fade_in().back()->when + arv->region().position());
}
void
@@ -1766,17 +1771,17 @@ Editor::fade_in_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
snap_to (pos);
}
if (pos < (arv->region.position() + 64)) {
if (pos < (arv->region().position() + 64)) {
fade_length = 64; // this should be a minimum defined somewhere
} else if (pos > arv->region.last_frame()) {
fade_length = arv->region.length();
} else if (pos > arv->region().last_frame()) {
fade_length = arv->region().length();
} else {
fade_length = pos - arv->region.position();
fade_length = pos - arv->region().position();
}
arv->reset_fade_in_shape_width (fade_length);
show_verbose_duration_cursor (arv->region.position(), arv->region.position() + fade_length, 10);
show_verbose_duration_cursor (arv->region().position(), arv->region().position() + fade_length, 10);
drag_info.first_move = false;
}
@@ -1801,20 +1806,20 @@ Editor::fade_in_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* even
snap_to (pos);
}
if (pos < (arv->region.position() + 64)) {
if (pos < (arv->region().position() + 64)) {
fade_length = 64; // this should be a minimum defined somewhere
}
else if (pos > arv->region.last_frame()) {
fade_length = arv->region.length();
else if (pos > arv->region().last_frame()) {
fade_length = arv->region().length();
}
else {
fade_length = pos - arv->region.position();
fade_length = pos - arv->region().position();
}
begin_reversible_command (_("change fade in length"));
session->add_undo (arv->region.get_memento());
arv->region.set_fade_in_length (fade_length);
session->add_redo_no_execute (arv->region.get_memento());
session->add_undo (arv->region().get_memento());
arv->audio_region().set_fade_in_length (fade_length);
session->add_redo_no_execute (arv->region().get_memento());
commit_reversible_command ();
fade_in_drag_motion_callback (item, event);
}
@@ -1835,7 +1840,7 @@ Editor::start_fade_out_grab (ArdourCanvas::Item* item, GdkEvent* event)
AudioRegionView* arv = static_cast<AudioRegionView*>(drag_info.data);
drag_info.pointer_frame_offset = drag_info.grab_frame - (arv->region.length() - (jack_nframes_t) arv->region.fade_out().back()->when + arv->region.position());
drag_info.pointer_frame_offset = drag_info.grab_frame - (arv->region().length() - (jack_nframes_t) arv->audio_region().fade_out().back()->when + arv->region().position());
}
void
@@ -1856,19 +1861,19 @@ Editor::fade_out_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event
snap_to (pos);
}
if (pos > (arv->region.last_frame() - 64)) {
if (pos > (arv->region().last_frame() - 64)) {
fade_length = 64; // this should really be a minimum fade defined somewhere
}
else if (pos < arv->region.position()) {
fade_length = arv->region.length();
else if (pos < arv->region().position()) {
fade_length = arv->region().length();
}
else {
fade_length = arv->region.last_frame() - pos;
fade_length = arv->region().last_frame() - pos;
}
arv->reset_fade_out_shape_width (fade_length);
show_verbose_duration_cursor (arv->region.last_frame() - fade_length, arv->region.last_frame(), 10);
show_verbose_duration_cursor (arv->region().last_frame() - fade_length, arv->region().last_frame(), 10);
drag_info.first_move = false;
}
@@ -1893,20 +1898,20 @@ Editor::fade_out_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* eve
snap_to (pos);
}
if (pos > (arv->region.last_frame() - 64)) {
if (pos > (arv->region().last_frame() - 64)) {
fade_length = 64; // this should really be a minimum fade defined somewhere
}
else if (pos < arv->region.position()) {
fade_length = arv->region.length();
else if (pos < arv->region().position()) {
fade_length = arv->region().length();
}
else {
fade_length = arv->region.last_frame() - pos;
fade_length = arv->region().last_frame() - pos;
}
begin_reversible_command (_("change fade out length"));
session->add_undo (arv->region.get_memento());
arv->region.set_fade_out_length (fade_length);
session->add_redo_no_execute (arv->region.get_memento());
session->add_undo (arv->region().get_memento());
arv->audio_region().set_fade_out_length (fade_length);
session->add_redo_no_execute (arv->region().get_memento());
commit_reversible_command ();
fade_out_drag_motion_callback (item, event);
@@ -2551,7 +2556,8 @@ Editor::start_line_grab_from_regionview (ArdourCanvas::Item* item, GdkEvent* eve
{
switch (mouse_mode) {
case MouseGain:
start_line_grab (clicked_regionview->get_gain_line(), event);
assert(dynamic_cast<AudioRegionView*>(clicked_regionview));
start_line_grab (dynamic_cast<AudioRegionView*>(clicked_regionview)->get_gain_line(), event);
break;
default:
break;
@@ -2645,7 +2651,7 @@ Editor::line_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
void
Editor::start_region_grab (ArdourCanvas::Item* item, GdkEvent* event)
{
if (selection->audio_regions.empty() || clicked_regionview == 0) {
if (selection->regions.empty() || clicked_regionview == 0) {
return;
}
@@ -2659,13 +2665,13 @@ Editor::start_region_grab (ArdourCanvas::Item* item, GdkEvent* event)
double speed = 1.0;
TimeAxisView* tvp = clicked_trackview;
AudioTimeAxisView* tv = dynamic_cast<AudioTimeAxisView*>(tvp);
RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp);
if (tv && tv->is_audio_track()) {
speed = tv->get_diskstream()->speed();
}
drag_info.last_frame_position = (jack_nframes_t) (clicked_regionview->region.position() / speed);
drag_info.last_frame_position = (jack_nframes_t) (clicked_regionview->region().position() / speed);
drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
drag_info.last_trackview = &clicked_regionview->get_time_axis_view();
// we want a move threshold
@@ -2679,7 +2685,7 @@ Editor::start_region_grab (ArdourCanvas::Item* item, GdkEvent* event)
void
Editor::start_region_copy_grab (ArdourCanvas::Item* item, GdkEvent* event)
{
if (selection->audio_regions.empty() || clicked_regionview == 0) {
if (selection->regions.empty() || clicked_regionview == 0) {
return;
}
@@ -2690,7 +2696,7 @@ Editor::start_region_copy_grab (ArdourCanvas::Item* item, GdkEvent* event)
start_grab(event);
TimeAxisView* tv = &clicked_regionview->get_time_axis_view();
AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(tv);
RouteTimeAxisView* atv = dynamic_cast<RouteTimeAxisView*>(tv);
double speed = 1.0;
if (atv && atv->is_audio_track()) {
@@ -2698,7 +2704,7 @@ Editor::start_region_copy_grab (ArdourCanvas::Item* item, GdkEvent* event)
}
drag_info.last_trackview = &clicked_regionview->get_time_axis_view();
drag_info.last_frame_position = (jack_nframes_t) (clicked_regionview->region.position() / speed);
drag_info.last_frame_position = (jack_nframes_t) (clicked_regionview->region().position() / speed);
drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
// we want a move threshold
drag_info.want_move_threshold = true;
@@ -2709,7 +2715,7 @@ Editor::start_region_copy_grab (ArdourCanvas::Item* item, GdkEvent* event)
void
Editor::start_region_brush_grab (ArdourCanvas::Item* item, GdkEvent* event)
{
if (selection->audio_regions.empty() || clicked_regionview == 0) {
if (selection->regions.empty() || clicked_regionview == 0) {
return;
}
@@ -2723,13 +2729,13 @@ Editor::start_region_brush_grab (ArdourCanvas::Item* item, GdkEvent* event)
double speed = 1.0;
TimeAxisView* tvp = clicked_trackview;
AudioTimeAxisView* tv = dynamic_cast<AudioTimeAxisView*>(tvp);
RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp);
if (tv && tv->is_audio_track()) {
speed = tv->get_diskstream()->speed();
}
drag_info.last_frame_position = (jack_nframes_t) (clicked_regionview->region.position() / speed);
drag_info.last_frame_position = (jack_nframes_t) (clicked_regionview->region().position() / speed);
drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
drag_info.last_trackview = &clicked_regionview->get_time_axis_view();
// we want a move threshold
@@ -2744,7 +2750,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
{
double x_delta;
double y_delta = 0;
AudioRegionView *rv = reinterpret_cast<AudioRegionView*> (drag_info.data);
RegionView* rv = reinterpret_cast<RegionView*> (drag_info.data);
jack_nframes_t pending_region_position = 0;
int32_t pointer_y_span = 0, canvas_pointer_y_span = 0, original_pointer_order;
int32_t visible_y_high = 0, visible_y_low = 512; //high meaning higher numbered.. not the height on the screen
@@ -2764,18 +2770,18 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
/* duplicate the region(s) */
vector<AudioRegionView*> new_regionviews;
vector<RegionView*> new_regionviews;
set<Playlist*> affected_playlists;
pair<set<Playlist*>::iterator,bool> insert_result;
for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) {
AudioRegionView* rv;
for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) {
RegionView* rv;
rv = (*i);
Playlist* to_playlist = rv->region.playlist();
AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&rv->get_time_axis_view());
Playlist* to_playlist = rv->region().playlist();
RouteTimeAxisView* atv = dynamic_cast<RouteTimeAxisView*>(&rv->get_time_axis_view());
insert_result = affected_playlists.insert (to_playlist);
if (insert_result.second) {
@@ -2784,18 +2790,21 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
latest_regionview = 0;
sigc::connection c = atv->view->AudioRegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
sigc::connection c = atv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
/* create a new region with the same name.
*/
AudioRegion* newregion = new AudioRegion (rv->region);
/* create a new region with the same name. */
// FIXME: ew. need a (virtual) Region::duplicate() or something?
Region* newregion = NULL;
if (dynamic_cast<AudioRegion*>(&rv->region()))
newregion = new AudioRegion (dynamic_cast<AudioRegion&>(rv->region()));
assert(newregion);
/* if the original region was locked, we don't care */
newregion->set_locked (false);
to_playlist->add_region (*newregion, (jack_nframes_t) (rv->region.position() * atv->get_diskstream()->speed()));
to_playlist->add_region (*newregion, (jack_nframes_t) (rv->region().position() * atv->get_diskstream()->speed()));
c.disconnect ();
@@ -2907,16 +2916,15 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
}
}
for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) {
AudioRegionView* rv2;
rv2 = (*i);
for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) {
RegionView* rv2 = (*i);
double ix1, ix2, iy1, iy2;
int32_t n = 0;
rv2->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
rv2->get_canvas_group()->i2w (ix1, iy1);
TimeAxisView* tvp2 = trackview_by_y_position (iy1);
AudioTimeAxisView* atv2 = dynamic_cast<AudioTimeAxisView*>(tvp2);
RouteTimeAxisView* atv2 = dynamic_cast<RouteTimeAxisView*>(tvp2);
if (atv2->order != original_pointer_order) {
/* this isn't the pointer track */
@@ -3011,8 +3019,8 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
pending_region_position = drag_info.current_pointer_frame - drag_info.pointer_frame_offset;
sync_offset = rv->region.sync_offset (sync_dir);
sync_frame = rv->region.adjust_to_sync (pending_region_position);
sync_offset = rv->region().sync_offset (sync_dir);
sync_frame = rv->region().adjust_to_sync (pending_region_position);
/* we snap if the snap modifier is not enabled.
*/
@@ -3031,7 +3039,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
pending_region_position = 0;
}
if (pending_region_position > max_frames - rv->region.length()) {
if (pending_region_position > max_frames - rv->region().length()) {
pending_region_position = drag_info.last_frame_position;
}
@@ -3073,14 +3081,11 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
}
if (x_delta < 0) {
for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) {
for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) {
AudioRegionView* rv2;
rv2 = (*i);
RegionView* rv2 = (*i);
/* if any regionview is at zero, we need to know so we can
stop further leftward motion.
*/
// If any regionview is at zero, we need to know so we can stop further leftward motion.
double ix1, ix2, iy1, iy2;
rv2->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
@@ -3098,12 +3103,11 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
************************************************************/
pair<set<Playlist*>::iterator,bool> insert_result;
const list<AudioRegionView*>& layered_regions = selection->audio_regions.by_layer();
const list<RegionView*>& layered_regions = selection->regions.by_layer();
for (list<AudioRegionView*>::const_iterator i = layered_regions.begin(); i != layered_regions.end(); ++i) {
for (list<RegionView*>::const_iterator i = layered_regions.begin(); i != layered_regions.end(); ++i) {
AudioRegionView* rv;
rv = (*i);
RegionView* rv = (*i);
double ix1, ix2, iy1, iy2;
int32_t temp_pointer_y_span = pointer_y_span;
@@ -3184,8 +3188,8 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
if (-x_delta > ix1) {
x_delta = -ix1;
}
} else if ((x_delta > 0) &&(rv->region.last_frame() > max_frames - x_delta)) {
x_delta = max_frames - rv->region.last_frame();
} else if ((x_delta > 0) &&(rv->region().last_frame() > max_frames - x_delta)) {
x_delta = max_frames - rv->region().last_frame();
}
if (drag_info.first_move) {
@@ -3210,7 +3214,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (&rv->get_time_axis_view());
if (atv && atv->is_audio_track()) {
AudioPlaylist* pl = atv->get_diskstream()->playlist();
AudioPlaylist* pl = dynamic_cast<AudioPlaylist*>(atv->get_diskstream()->playlist());
if (pl) {
/* only freeze and capture state once */
@@ -3246,11 +3250,11 @@ void
Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
{
jack_nframes_t where;
AudioRegionView* rv = reinterpret_cast<AudioRegionView *> (drag_info.data);
RegionView* rv = reinterpret_cast<RegionView *> (drag_info.data);
pair<set<Playlist*>::iterator,bool> insert_result;
bool nocommit = true;
double speed;
AudioTimeAxisView* atv;
RouteTimeAxisView* atv;
bool regionview_y_movement;
bool regionview_x_movement;
@@ -3284,7 +3288,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
speed = atv->get_diskstream()->speed();
}
regionview_x_movement = (drag_info.last_frame_position != (jack_nframes_t) (rv->region.position()/speed));
regionview_x_movement = (drag_info.last_frame_position != (jack_nframes_t) (rv->region().position()/speed));
regionview_y_movement = (drag_info.last_trackview != &rv->get_time_axis_view());
//printf ("last_frame: %s position is %lu %g\n", rv->get_time_axis_view().name().c_str(), drag_info.last_frame_position, speed);
@@ -3294,13 +3298,13 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
/* motion between tracks */
list<AudioRegionView*> new_selection;
list<RegionView*> new_selection;
/* moved to a different audio track. */
for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ) {
for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ) {
AudioRegionView* rv2 = (*i);
RegionView* rv2 = (*i);
/* the region that used to be in the old playlist is not
moved to the new one - we make a copy of it. as a result,
@@ -3317,7 +3321,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
/* first, freeze the target tracks */
for (list<AudioRegionView*>::const_iterator i = new_selection.begin(); i != new_selection.end();i++ ) {
for (list<RegionView*>::const_iterator i = new_selection.begin(); i != new_selection.end();i++ ) {
Playlist* from_playlist;
Playlist* to_playlist;
@@ -3329,7 +3333,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
TimeAxisView* tvp2 = trackview_by_y_position (iy1);
AudioTimeAxisView* atv2 = dynamic_cast<AudioTimeAxisView*>(tvp2);
from_playlist = (*i)->region.playlist();
from_playlist = (*i)->region().playlist();
to_playlist = atv2->playlist();
/* the from_playlist was frozen in the "first_move" case
@@ -3352,7 +3356,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
/* now do it again with the actual operations */
for (list<AudioRegionView*>::const_iterator i = new_selection.begin(); i != new_selection.end();i++ ) {
for (list<RegionView*>::const_iterator i = new_selection.begin(); i != new_selection.end();i++ ) {
Playlist* from_playlist;
Playlist* to_playlist;
@@ -3364,17 +3368,17 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
TimeAxisView* tvp2 = trackview_by_y_position (iy1);
AudioTimeAxisView* atv2 = dynamic_cast<AudioTimeAxisView*>(tvp2);
from_playlist = (*i)->region.playlist();
from_playlist = (*i)->region().playlist();
to_playlist = atv2->playlist();
latest_regionview = 0;
where = (jack_nframes_t) (unit_to_frame (ix1) * speed);
Region* new_region = createRegion ((*i)->region);
Region* new_region = createRegion ((*i)->region());
from_playlist->remove_region (&((*i)->region));
from_playlist->remove_region (&((*i)->region()));
sigc::connection c = atv2->view->AudioRegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
sigc::connection c = atv2->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
to_playlist->add_region (*new_region, where);
c.disconnect ();
@@ -3387,11 +3391,11 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
/* motion within a single track */
for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) {
for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) {
rv = (*i);
if (rv->region.locked()) {
if (rv->region().locked()) {
continue;
}
@@ -3413,14 +3417,14 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
} else {
where = rv->region.position();
where = rv->region().position();
}
rv->get_time_axis_view().reveal_dependent_views (*rv);
/* no need to add an undo here, we did that when we added this playlist to motion_frozen playlists */
rv->region.set_position (where, (void *) this);
rv->region().set_position (where, (void *) this);
}
}
@@ -3454,15 +3458,15 @@ Editor::region_view_item_click (AudioRegionView& rv, GdkEventButton* event)
if (Keyboard::modifier_state_equals (event->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Alt))) {
align_region (rv.region, SyncPoint, (jack_nframes_t) (edit_cursor->current_frame * speed));
align_region (rv.region(), SyncPoint, (jack_nframes_t) (edit_cursor->current_frame * speed));
} else if (Keyboard::modifier_state_equals (event->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
align_region (rv.region, End, (jack_nframes_t) (edit_cursor->current_frame * speed));
align_region (rv.region(), End, (jack_nframes_t) (edit_cursor->current_frame * speed));
} else {
align_region (rv.region, Start, (jack_nframes_t) (edit_cursor->current_frame * speed));
align_region (rv.region(), Start, (jack_nframes_t) (edit_cursor->current_frame * speed));
}
}
}
@@ -3579,7 +3583,7 @@ Editor::show_verbose_duration_cursor (jack_nframes_t start, jack_nframes_t end,
}
void
Editor::collect_new_region_view (AudioRegionView* rv)
Editor::collect_new_region_view (RegionView* rv)
{
latest_regionview = rv;
}
@@ -3612,7 +3616,7 @@ Editor::start_selection_grab (ArdourCanvas::Item* item, GdkEvent* event)
*/
latest_regionview = 0;
sigc::connection c = clicked_audio_trackview->view->AudioRegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
sigc::connection c = clicked_audio_trackview->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
/* A selection grab currently creates two undo/redo operations, one for
creating the new region and another for moving it.
@@ -3647,7 +3651,7 @@ Editor::start_selection_grab (ArdourCanvas::Item* item, GdkEvent* event)
start_grab (event);
drag_info.last_trackview = clicked_trackview;
drag_info.last_frame_position = latest_regionview->region.position();
drag_info.last_frame_position = latest_regionview->region().position();
drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
show_verbose_time_cursor (drag_info.last_frame_position, 10);
@@ -3888,9 +3892,9 @@ Editor::start_trim (ArdourCanvas::Item* item, GdkEvent* event)
speed = tv->get_diskstream()->speed();
}
jack_nframes_t region_start = (jack_nframes_t) (clicked_regionview->region.position() / speed);
jack_nframes_t region_end = (jack_nframes_t) (clicked_regionview->region.last_frame() / speed);
jack_nframes_t region_length = (jack_nframes_t) (clicked_regionview->region.length() / speed);
jack_nframes_t region_start = (jack_nframes_t) (clicked_regionview->region().position() / speed);
jack_nframes_t region_end = (jack_nframes_t) (clicked_regionview->region().last_frame() / speed);
jack_nframes_t region_length = (jack_nframes_t) (clicked_regionview->region().length() / speed);
motion_frozen_playlists.clear();
@@ -3930,7 +3934,7 @@ Editor::start_trim (ArdourCanvas::Item* item, GdkEvent* event)
void
Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
{
AudioRegionView* rv = clicked_regionview;
RegionView* rv = clicked_regionview;
jack_nframes_t frame_delta = 0;
bool left_direction;
bool obey_snap = !Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier());
@@ -3942,7 +3946,7 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
double speed = 1.0;
TimeAxisView* tvp = clicked_trackview;
AudioTimeAxisView* tv = dynamic_cast<AudioTimeAxisView*>(tvp);
RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp);
pair<set<Playlist*>::iterator,bool> insert_result;
if (tv && tv->is_audio_track()) {
@@ -3981,11 +3985,14 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
begin_reversible_command (trim_type);
for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) {
(*i)->region.freeze ();
(*i)->temporarily_hide_envelope ();
for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) {
(*i)->region().freeze ();
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
if (arv)
arv->temporarily_hide_envelope ();
Playlist * pl = (*i)->region.playlist();
Playlist * pl = (*i)->region().playlist();
insert_result = motion_frozen_playlists.insert (pl);
if (insert_result.second) {
session->add_undo (pl->get_memento());
@@ -4001,20 +4008,20 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
switch (trim_op) {
case StartTrim:
if ((left_direction == false) && (drag_info.current_pointer_frame <= rv->region.first_frame()/speed)) {
if ((left_direction == false) && (drag_info.current_pointer_frame <= rv->region().first_frame()/speed)) {
break;
} else {
for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) {
for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) {
single_start_trim (**i, frame_delta, left_direction, obey_snap);
}
break;
}
case EndTrim:
if ((left_direction == true) && (drag_info.current_pointer_frame > (jack_nframes_t) (rv->region.last_frame()/speed))) {
if ((left_direction == true) && (drag_info.current_pointer_frame > (jack_nframes_t) (rv->region().last_frame()/speed))) {
break;
} else {
for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) {
for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) {
single_end_trim (**i, frame_delta, left_direction, obey_snap);
}
break;
@@ -4028,8 +4035,8 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
swap_direction = true;
}
for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin();
i != selection->audio_regions.by_layer().end(); ++i)
for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin();
i != selection->regions.by_layer().end(); ++i)
{
single_contents_trim (**i, frame_delta, left_direction, swap_direction, obey_snap);
}
@@ -4039,10 +4046,10 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
switch (trim_op) {
case StartTrim:
show_verbose_time_cursor((jack_nframes_t) (rv->region.position()/speed), 10);
show_verbose_time_cursor((jack_nframes_t) (rv->region().position()/speed), 10);
break;
case EndTrim:
show_verbose_time_cursor((jack_nframes_t) (rv->region.last_frame()/speed), 10);
show_verbose_time_cursor((jack_nframes_t) (rv->region().last_frame()/speed), 10);
break;
case ContentsTrim:
show_verbose_time_cursor(drag_info.current_pointer_frame, 10);
@@ -4054,9 +4061,9 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
}
void
Editor::single_contents_trim (AudioRegionView& rv, jack_nframes_t frame_delta, bool left_direction, bool swap_direction, bool obey_snap)
Editor::single_contents_trim (RegionView& rv, jack_nframes_t frame_delta, bool left_direction, bool swap_direction, bool obey_snap)
{
Region& region (rv.region);
Region& region (rv.region());
if (region.locked()) {
return;
@@ -4066,7 +4073,7 @@ Editor::single_contents_trim (AudioRegionView& rv, jack_nframes_t frame_delta, b
double speed = 1.0;
TimeAxisView* tvp = clicked_trackview;
AudioTimeAxisView* tv = dynamic_cast<AudioTimeAxisView*>(tvp);
RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp);
if (tv && tv->is_audio_track()) {
speed = tv->get_diskstream()->speed();
@@ -4094,9 +4101,9 @@ Editor::single_contents_trim (AudioRegionView& rv, jack_nframes_t frame_delta, b
}
void
Editor::single_start_trim (AudioRegionView& rv, jack_nframes_t frame_delta, bool left_direction, bool obey_snap)
Editor::single_start_trim (RegionView& rv, jack_nframes_t frame_delta, bool left_direction, bool obey_snap)
{
Region& region (rv.region);
Region& region (rv.region());
if (region.locked()) {
return;
@@ -4128,9 +4135,9 @@ Editor::single_start_trim (AudioRegionView& rv, jack_nframes_t frame_delta, bool
}
void
Editor::single_end_trim (AudioRegionView& rv, jack_nframes_t frame_delta, bool left_direction, bool obey_snap)
Editor::single_end_trim (RegionView& rv, jack_nframes_t frame_delta, bool left_direction, bool obey_snap)
{
Region& region (rv.region);
Region& region (rv.region());
if (region.locked()) {
return;
@@ -4169,8 +4176,8 @@ Editor::trim_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
thaw_region_after_trim (*clicked_regionview);
} else {
for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin();
i != selection->audio_regions.by_layer().end(); ++i)
for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin();
i != selection->regions.by_layer().end(); ++i)
{
thaw_region_after_trim (**i);
}
@@ -4193,7 +4200,7 @@ Editor::trim_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
void
Editor::point_trim (GdkEvent* event)
{
AudioRegionView* rv = clicked_regionview;
RegionView* rv = clicked_regionview;
jack_nframes_t new_bound = drag_info.current_pointer_frame;
if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
@@ -4208,22 +4215,22 @@ Editor::point_trim (GdkEvent* event)
if (rv->get_selected()) {
for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin();
i != selection->audio_regions.by_layer().end(); ++i)
for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin();
i != selection->regions.by_layer().end(); ++i)
{
if (!(*i)->region.locked()) {
session->add_undo ((*i)->region.playlist()->get_memento());
(*i)->region.trim_front (new_bound, this);
session->add_redo_no_execute ((*i)->region.playlist()->get_memento());
if (!(*i)->region().locked()) {
session->add_undo ((*i)->region().playlist()->get_memento());
(*i)->region().trim_front (new_bound, this);
session->add_redo_no_execute ((*i)->region().playlist()->get_memento());
}
}
} else {
if (!rv->region.locked()) {
session->add_undo (rv->region.playlist()->get_memento());
rv->region.trim_front (new_bound, this);
session->add_redo_no_execute (rv->region.playlist()->get_memento());
if (!rv->region().locked()) {
session->add_undo (rv->region().playlist()->get_memento());
rv->region().trim_front (new_bound, this);
session->add_redo_no_execute (rv->region().playlist()->get_memento());
}
}
@@ -4236,21 +4243,21 @@ Editor::point_trim (GdkEvent* event)
if (rv->get_selected()) {
for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i)
for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i)
{
if (!(*i)->region.locked()) {
session->add_undo ((*i)->region.playlist()->get_memento());
(*i)->region.trim_end (new_bound, this);
session->add_redo_no_execute ((*i)->region.playlist()->get_memento());
if (!(*i)->region().locked()) {
session->add_undo ((*i)->region().playlist()->get_memento());
(*i)->region().trim_end (new_bound, this);
session->add_redo_no_execute ((*i)->region().playlist()->get_memento());
}
}
} else {
if (!rv->region.locked()) {
session->add_undo (rv->region.playlist()->get_memento());
rv->region.trim_end (new_bound, this);
session->add_redo_no_execute (rv->region.playlist()->get_memento());
if (!rv->region().locked()) {
session->add_undo (rv->region().playlist()->get_memento());
rv->region().trim_end (new_bound, this);
session->add_redo_no_execute (rv->region().playlist()->get_memento());
}
}
@@ -4263,9 +4270,9 @@ Editor::point_trim (GdkEvent* event)
}
void
Editor::thaw_region_after_trim (AudioRegionView& rv)
Editor::thaw_region_after_trim (RegionView& rv)
{
Region& region (rv.region);
Region& region (rv.region());
if (region.locked()) {
return;
@@ -4274,7 +4281,9 @@ Editor::thaw_region_after_trim (AudioRegionView& rv)
region.thaw (_("trimmed region"));
session->add_redo_no_execute (region.playlist()->get_memento());
rv.unhide_envelope ();
AudioRegionView* arv = dynamic_cast<AudioRegionView*>(&rv);
if (arv)
arv->unhide_envelope ();
}
void
@@ -4664,7 +4673,7 @@ Editor::end_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event)
}
} else {
selection->clear_audio_regions();
selection->clear_regions();
selection->clear_points ();
selection->clear_lines ();
}
@@ -4681,7 +4690,7 @@ Editor::mouse_rename_region (ArdourCanvas::Item* item, GdkEvent* event)
ArdourPrompter prompter (false);
prompter.set_prompt (_("Name for region:"));
prompter.set_initial_text (clicked_regionview->region.name());
prompter.set_initial_text (clicked_regionview->region().name());
prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
prompter.show_all ();
@@ -4690,7 +4699,7 @@ Editor::mouse_rename_region (ArdourCanvas::Item* item, GdkEvent* event)
string str;
prompter.get_result(str);
if (str.length()) {
clicked_regionview->region.set_name (str);
clicked_regionview->region().set_name (str);
}
break;
}
@@ -4712,7 +4721,7 @@ Editor::start_time_fx (ArdourCanvas::Item* item, GdkEvent* event)
void
Editor::time_fx_motion (ArdourCanvas::Item *item, GdkEvent* event)
{
AudioRegionView* rv = clicked_regionview;
RegionView* rv = clicked_regionview;
if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
snap_to (drag_info.current_pointer_frame);
@@ -4722,8 +4731,8 @@ Editor::time_fx_motion (ArdourCanvas::Item *item, GdkEvent* event)
return;
}
if (drag_info.current_pointer_frame > rv->region.position()) {
rv->get_time_axis_view().show_timestretch (rv->region.position(), drag_info.current_pointer_frame);
if (drag_info.current_pointer_frame > rv->region().position()) {
rv->get_time_axis_view().show_timestretch (rv->region().position(), drag_info.current_pointer_frame);
}
drag_info.last_pointer_frame = drag_info.current_pointer_frame;
@@ -4741,21 +4750,25 @@ Editor::end_time_fx (ArdourCanvas::Item* item, GdkEvent* event)
return;
}
jack_nframes_t newlen = drag_info.last_pointer_frame - clicked_regionview->region.position();
float percentage = (float) ((double) newlen - (double) clicked_regionview->region.length()) / ((double) newlen) * 100.0f;
jack_nframes_t newlen = drag_info.last_pointer_frame - clicked_regionview->region().position();
float percentage = (float) ((double) newlen - (double) clicked_regionview->region().length()) / ((double) newlen) * 100.0f;
begin_reversible_command (_("timestretch"));
if (run_timestretch (selection->audio_regions, percentage) == 0) {
if (run_timestretch (selection->regions, percentage) == 0) {
session->commit_reversible_command ();
}
}
void
Editor::mouse_brush_insert_region (AudioRegionView* rv, jack_nframes_t pos)
Editor::mouse_brush_insert_region (RegionView* rv, jack_nframes_t pos)
{
/* no brushing without a useful snap setting */
// FIXME
AudioRegionView* arv = dynamic_cast<AudioRegionView*>(rv);
assert(arv);
switch (snap_mode) {
case SnapMagnetic:
return; /* can't work because it allows region to be placed anywhere */
@@ -4775,11 +4788,11 @@ Editor::mouse_brush_insert_region (AudioRegionView* rv, jack_nframes_t pos)
/* don't brush a copy over the original */
if (pos == rv->region.position()) {
if (pos == rv->region().position()) {
return;
}
AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&rv->get_time_axis_view());
RouteTimeAxisView* atv = dynamic_cast<RouteTimeAxisView*>(&arv->get_time_axis_view());
if (atv == 0 || !atv->is_audio_track()) {
return;
@@ -4789,7 +4802,7 @@ Editor::mouse_brush_insert_region (AudioRegionView* rv, jack_nframes_t pos)
double speed = atv->get_diskstream()->speed();
session->add_undo (playlist->get_memento());
playlist->add_region (*(new AudioRegion (rv->region)), (jack_nframes_t) (pos * speed));
playlist->add_region (*(new AudioRegion (arv->audio_region())), (jack_nframes_t) (pos * speed));
session->add_redo_no_execute (playlist->get_memento());
// playlist is frozen, so we have to update manually

View File

@@ -51,7 +51,7 @@
#include "audio_time_axis.h"
#include "automation_time_axis.h"
#include "streamview.h"
#include "regionview.h"
#include "audio_region_view.h"
#include "rgb_macros.h"
#include "selection_templates.h"
#include "selection.h"
@@ -186,29 +186,31 @@ Editor::split_region ()
void
Editor::split_region_at (jack_nframes_t where)
{
split_regions_at (where, selection->audio_regions);
split_regions_at (where, selection->regions);
}
void
Editor::split_regions_at (jack_nframes_t where, AudioRegionSelection& regions)
Editor::split_regions_at (jack_nframes_t where, RegionSelection& regions)
{
begin_reversible_command (_("split"));
snap_to (where);
for (AudioRegionSelection::iterator a = regions.begin(); a != regions.end(); ) {
for (RegionSelection::iterator a = regions.begin(); a != regions.end(); ) {
AudioRegionSelection::iterator tmp;
RegionSelection::iterator tmp;
tmp = a;
++tmp;
Playlist* pl = (*a)->region.playlist();
Playlist* pl = (*a)->region().playlist();
_new_regionviews_show_envelope = (*a)->envelope_visible();
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*a);
if (arv)
_new_regionviews_show_envelope = arv->envelope_visible();
if (pl) {
session->add_undo (pl->get_memento());
pl->split_region ((*a)->region, where);
pl->split_region ((*a)->region(), where);
session->add_redo_no_execute (pl->get_memento());
}
@@ -230,7 +232,7 @@ Editor::remove_clicked_region ()
begin_reversible_command (_("remove region"));
session->add_undo (playlist->get_memento());
playlist->remove_region (&clicked_regionview->region);
playlist->remove_region (&clicked_regionview->region());
session->add_redo_no_execute (playlist->get_memento());
commit_reversible_command ();
}
@@ -238,7 +240,7 @@ Editor::remove_clicked_region ()
void
Editor::destroy_clicked_region ()
{
int32_t selected = selection->audio_regions.size();
int32_t selected = selection->regions.size();
if (!session || clicked_regionview == 0 && selected == 0) {
return;
@@ -270,29 +272,29 @@ Do you really want to destroy %1 ?"),
if (selected > 0) {
list<Region*> r;
for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
r.push_back (&(*i)->region);
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
r.push_back (&(*i)->region());
}
session->destroy_regions (r);
} else if (clicked_regionview) {
session->destroy_region (&clicked_regionview->region);
session->destroy_region (&clicked_regionview->region());
}
}
AudioRegion *
Region *
Editor::select_region_for_operation (int dir, TimeAxisView **tv)
{
AudioRegionView* rv;
AudioRegion *region;
RegionView* rv;
Region *region;
jack_nframes_t start = 0;
if (selection->time.start () == selection->time.end_frame ()) {
/* no current selection-> is there a selected regionview? */
if (selection->audio_regions.empty()) {
if (selection->regions.empty()) {
return 0;
}
@@ -300,26 +302,26 @@ Editor::select_region_for_operation (int dir, TimeAxisView **tv)
region = 0;
if (!selection->audio_regions.empty()) {
if (!selection->regions.empty()) {
rv = *(selection->audio_regions.begin());
rv = *(selection->regions.begin());
(*tv) = &rv->get_time_axis_view();
region = &rv->region;
region = &rv->region();
} else if (!selection->tracks.empty()) {
(*tv) = selection->tracks.front();
AudioTimeAxisView* atv;
RouteTimeAxisView* rtv;
if ((atv = dynamic_cast<AudioTimeAxisView*> (*tv)) != 0) {
if ((rtv = dynamic_cast<RouteTimeAxisView*> (*tv)) != 0) {
Playlist *pl;
if ((pl = atv->playlist()) == 0) {
if ((pl = rtv->playlist()) == 0) {
return 0;
}
region = dynamic_cast<AudioRegion*> (pl->top_region_at (start));
region = pl->top_region_at (start);
}
}
@@ -391,12 +393,12 @@ Editor::nudge_forward (bool next)
if (!session) return;
if (!selection->audio_regions.empty()) {
if (!selection->regions.empty()) {
begin_reversible_command (_("nudge forward"));
for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
AudioRegion& r ((*i)->region);
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
Region& r ((*i)->region());
distance = get_nudge_distance (r.position(), next_distance);
@@ -425,12 +427,12 @@ Editor::nudge_backward (bool next)
if (!session) return;
if (!selection->audio_regions.empty()) {
if (!selection->regions.empty()) {
begin_reversible_command (_("nudge forward"));
for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
AudioRegion& r ((*i)->region);
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
Region& r ((*i)->region());
distance = get_nudge_distance (r.position(), next_distance);
@@ -469,14 +471,14 @@ Editor::nudge_forward_capture_offset ()
if (!session) return;
if (!selection->audio_regions.empty()) {
if (!selection->regions.empty()) {
begin_reversible_command (_("nudge forward"));
distance = session->worst_output_latency();
for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
AudioRegion& r ((*i)->region);
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
Region& r ((*i)->region());
session->add_undo (r.playlist()->get_memento());
r.set_position (r.position() + distance, this);
@@ -495,14 +497,14 @@ Editor::nudge_backward_capture_offset ()
if (!session) return;
if (!selection->audio_regions.empty()) {
if (!selection->regions.empty()) {
begin_reversible_command (_("nudge forward"));
distance = session->worst_output_latency();
for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
AudioRegion& r ((*i)->region);
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
Region& r ((*i)->region());
session->add_undo (r.playlist()->get_memento());
@@ -782,8 +784,8 @@ Editor::cursor_to_selection_start (Cursor *cursor)
jack_nframes_t pos = 0;
switch (mouse_mode) {
case MouseObject:
if (!selection->audio_regions.empty()) {
pos = selection->audio_regions.start();
if (!selection->regions.empty()) {
pos = selection->regions.start();
}
break;
@@ -811,8 +813,8 @@ Editor::cursor_to_selection_end (Cursor *cursor)
switch (mouse_mode) {
case MouseObject:
if (!selection->audio_regions.empty()) {
pos = selection->audio_regions.end_frame();
if (!selection->regions.empty()) {
pos = selection->regions.end_frame();
}
break;
@@ -1310,12 +1312,12 @@ Editor::add_location_from_playhead_cursor ()
void
Editor::add_location_from_audio_region ()
{
if (selection->audio_regions.empty()) {
if (selection->regions.empty()) {
return;
}
AudioRegionView* rv = *(selection->audio_regions.begin());
Region& region = rv->region;
RegionView* rv = *(selection->regions.begin());
Region& region = rv->region();
Location *location = new Location (region.position(), region.last_frame(), region.name());
session->begin_reversible_command (_("add marker"));
@@ -1442,12 +1444,12 @@ Editor::select_all_within (jack_nframes_t start, jack_nframes_t end, double top,
void
Editor::set_selection_from_audio_region ()
{
if (selection->audio_regions.empty()) {
if (selection->regions.empty()) {
return;
}
AudioRegionView* rv = *(selection->audio_regions.begin());
Region& region = rv->region;
RegionView* rv = *(selection->regions.begin());
Region& region = rv->region();
begin_reversible_command (_("set selection from region"));
selection->set (0, region.position(), region.last_frame());
@@ -1827,13 +1829,13 @@ Editor::insert_region_list_drag (AudioRegion& region, int x, int y)
void
Editor::insert_region_list_selection (float times)
{
AudioTimeAxisView *tv = 0;
RouteTimeAxisView *tv = 0;
Playlist *playlist;
if (clicked_audio_trackview != 0) {
tv = clicked_audio_trackview;
} else if (!selection->tracks.empty()) {
if ((tv = dynamic_cast<AudioTimeAxisView*>(selection->tracks.front())) == 0) {
if ((tv = dynamic_cast<RouteTimeAxisView*>(selection->tracks.front())) == 0) {
return;
}
} else {
@@ -1928,23 +1930,23 @@ Editor::play_selection ()
void
Editor::play_selected_region ()
{
if (!selection->audio_regions.empty()) {
AudioRegionView *rv = *(selection->audio_regions.begin());
if (!selection->regions.empty()) {
RegionView *rv = *(selection->regions.begin());
session->request_bounded_roll (rv->region.position(), rv->region.last_frame());
session->request_bounded_roll (rv->region().position(), rv->region().last_frame());
}
}
void
Editor::loop_selected_region ()
{
if (!selection->audio_regions.empty()) {
AudioRegionView *rv = *(selection->audio_regions.begin());
if (!selection->regions.empty()) {
RegionView *rv = *(selection->regions.begin());
Location* tll;
if ((tll = transport_loop_location()) != 0) {
tll->set (rv->region.position(), rv->region.last_frame());
tll->set (rv->region().position(), rv->region().last_frame());
// enable looping, reposition and start rolling
@@ -1987,10 +1989,10 @@ void
Editor::toggle_region_mute ()
{
if (clicked_regionview) {
clicked_regionview->region.set_muted (!clicked_regionview->region.muted());
} else if (!selection->audio_regions.empty()) {
bool yn = ! (*selection->audio_regions.begin())->region.muted();
selection->foreach_audio_region (&AudioRegion::set_muted, yn);
clicked_regionview->region().set_muted (!clicked_regionview->region().muted());
} else if (!selection->regions.empty()) {
bool yn = ! (*selection->regions.begin())->region().muted();
selection->foreach_region (&Region::set_muted, yn);
}
}
@@ -1998,35 +2000,35 @@ void
Editor::toggle_region_opaque ()
{
if (clicked_regionview) {
clicked_regionview->region.set_opaque (!clicked_regionview->region.opaque());
} else if (!selection->audio_regions.empty()) {
bool yn = ! (*selection->audio_regions.begin())->region.opaque();
selection->foreach_audio_region (&Region::set_opaque, yn);
clicked_regionview->region().set_opaque (!clicked_regionview->region().opaque());
} else if (!selection->regions.empty()) {
bool yn = ! (*selection->regions.begin())->region().opaque();
selection->foreach_region (&Region::set_opaque, yn);
}
}
void
Editor::raise_region ()
{
selection->foreach_audio_region (&Region::raise);
selection->foreach_region (&Region::raise);
}
void
Editor::raise_region_to_top ()
{
selection->foreach_audio_region (&Region::raise_to_top);
selection->foreach_region (&Region::raise_to_top);
}
void
Editor::lower_region ()
{
selection->foreach_audio_region (&Region::lower);
selection->foreach_region (&Region::lower);
}
void
Editor::lower_region_to_bottom ()
{
selection->foreach_audio_region (&Region::lower_to_bottom);
selection->foreach_region (&Region::lower_to_bottom);
}
void
@@ -2047,7 +2049,7 @@ Editor::rename_region ()
Button ok_button (_("OK"));
Button cancel_button (_("Cancel"));
if (selection->audio_regions.empty()) {
if (selection->regions.empty()) {
return;
}
@@ -2078,7 +2080,7 @@ Editor::rename_region ()
Main::run ();
if (region_renamed) {
(*selection->audio_regions.begin())->region.set_name (entry.get_text());
(*selection->regions.begin())->region().set_name (entry.get_text());
redisplay_regions ();
}
}
@@ -2092,7 +2094,7 @@ Editor::rename_region_finished (bool status)
}
void
Editor::audition_playlist_region_via_route (AudioRegion& region, Route& route)
Editor::audition_playlist_region_via_route (Region& region, Route& route)
{
if (session->is_auditioning()) {
session->cancel_audition ();
@@ -2113,14 +2115,14 @@ Editor::audition_playlist_region_via_route (AudioRegion& region, Route& route)
void
Editor::audition_selected_region ()
{
if (!selection->audio_regions.empty()) {
AudioRegionView* rv = *(selection->audio_regions.begin());
session->audition_region (rv->region);
if (!selection->regions.empty()) {
RegionView* rv = *(selection->regions.begin());
session->audition_region (rv->region());
}
}
void
Editor::audition_playlist_region_standalone (AudioRegion& region)
Editor::audition_playlist_region_standalone (Region& region)
{
session->audition_region (region);
}
@@ -2170,7 +2172,6 @@ Editor::region_from_selection ()
jack_nframes_t selection_cnt = end - start + 1;
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
AudioRegion *region;
AudioRegion *current;
Region* current_r;
@@ -2187,7 +2188,9 @@ Editor::region_from_selection ()
continue;
}
if ((current = dynamic_cast<AudioRegion*> (current_r)) != 0) {
current = dynamic_cast<AudioRegion*> (current_r);
// FIXME: audio only
if (current != 0) {
internal_start = start - current->position();
session->region_name (new_name, current->name(), true);
region = new AudioRegion (*current, internal_start, selection_cnt, new_name);
@@ -2237,11 +2240,13 @@ Editor::split_multichannel_region ()
{
vector<AudioRegion*> v;
if (!clicked_regionview || clicked_regionview->region.n_channels() < 2) {
AudioRegionView* clicked_arv = dynamic_cast<AudioRegionView*>(clicked_regionview);
if (!clicked_arv || clicked_arv->audio_region().n_channels() < 2) {
return;
}
clicked_regionview->region.separate_by_channel (*session, v);
clicked_arv->audio_region().separate_by_channel (*session, v);
/* nothing else to do, really */
}
@@ -2419,7 +2424,7 @@ Editor::region_fill_track ()
{
jack_nframes_t end;
if (!session || selection->audio_regions.empty()) {
if (!session || selection->regions.empty()) {
return;
}
@@ -2427,9 +2432,15 @@ Editor::region_fill_track ()
begin_reversible_command (_("region fill"));
for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
Region& region ((*i)->region());
// FIXME
AudioRegion* const ar = dynamic_cast<AudioRegion*>(&region);
if (!ar)
continue;
AudioRegion& region ((*i)->region);
Playlist* pl = region.playlist();
if (end <= region.last_frame()) {
@@ -2443,7 +2454,7 @@ Editor::region_fill_track ()
}
session->add_undo (pl->get_memento());
pl->add_region (*(new AudioRegion (region)), region.last_frame(), times);
pl->add_region (*(new AudioRegion (*ar)), ar->last_frame(), times);
session->add_redo_no_execute (pl->get_memento());
}
@@ -2522,12 +2533,12 @@ Editor::set_region_sync_from_edit_cursor ()
return;
}
if (!clicked_regionview->region.covers (edit_cursor->current_frame)) {
if (!clicked_regionview->region().covers (edit_cursor->current_frame)) {
error << _("Place the edit cursor at the desired sync point") << endmsg;
return;
}
Region& region (clicked_regionview->region);
Region& region (clicked_regionview->region());
begin_reversible_command (_("set sync from edit cursor"));
session->add_undo (region.playlist()->get_memento());
region.set_sync_position (edit_cursor->current_frame);
@@ -2539,7 +2550,7 @@ void
Editor::remove_region_sync ()
{
if (clicked_regionview) {
Region& region (clicked_regionview->region);
Region& region (clicked_regionview->region());
begin_reversible_command (_("remove sync"));
session->add_undo (region.playlist()->get_memento());
region.clear_sync_position ();
@@ -2551,14 +2562,14 @@ Editor::remove_region_sync ()
void
Editor::naturalize ()
{
if (selection->audio_regions.empty()) {
if (selection->regions.empty()) {
return;
}
begin_reversible_command (_("naturalize"));
for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
session->add_undo ((*i)->region.get_memento());
(*i)->region.move_to_natural_position (this);
session->add_redo_no_execute ((*i)->region.get_memento());
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
session->add_undo ((*i)->region().get_memento());
(*i)->region().move_to_natural_position (this);
session->add_redo_no_execute ((*i)->region().get_memento());
}
commit_reversible_command ();
}
@@ -2577,14 +2588,14 @@ Editor::align_relative (RegionPoint what)
struct RegionSortByTime {
bool operator() (const AudioRegionView* a, const AudioRegionView* b) {
return a->region.position() < b->region.position();
return a->region().position() < b->region().position();
}
};
void
Editor::align_selection_relative (RegionPoint point, jack_nframes_t position)
{
if (selection->audio_regions.empty()) {
if (selection->regions.empty()) {
return;
}
@@ -2592,9 +2603,9 @@ Editor::align_selection_relative (RegionPoint point, jack_nframes_t position)
jack_nframes_t pos = 0;
int dir;
list<AudioRegionView*> sorted;
selection->audio_regions.by_position (sorted);
Region& r ((*sorted.begin())->region);
list<RegionView*> sorted;
selection->regions.by_position (sorted);
Region& r ((*sorted.begin())->region());
switch (point) {
case Start:
@@ -2620,9 +2631,9 @@ Editor::align_selection_relative (RegionPoint point, jack_nframes_t position)
begin_reversible_command (_("align selection (relative)"));
for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
Region& region ((*i)->region);
Region& region ((*i)->region());
session->add_undo (region.playlist()->get_memento());
@@ -2642,14 +2653,14 @@ Editor::align_selection_relative (RegionPoint point, jack_nframes_t position)
void
Editor::align_selection (RegionPoint point, jack_nframes_t position)
{
if (selection->audio_regions.empty()) {
if (selection->regions.empty()) {
return;
}
begin_reversible_command (_("align selection"));
for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
align_region_internal ((*i)->region, point, position);
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
align_region_internal ((*i)->region(), point, position);
}
commit_reversible_command ();
@@ -2694,7 +2705,7 @@ Editor::trim_region_to_edit_cursor ()
return;
}
Region& region (clicked_regionview->region);
Region& region (clicked_regionview->region());
float speed = 1.0f;
AudioTimeAxisView *atav;
@@ -2719,7 +2730,7 @@ Editor::trim_region_from_edit_cursor ()
return;
}
Region& region (clicked_regionview->region);
Region& region (clicked_regionview->region());
float speed = 1.0f;
AudioTimeAxisView *atav;
@@ -2890,16 +2901,16 @@ Editor::cut_copy (CutCopyOp op)
switch (current_mouse_mode()) {
case MouseObject:
if (!selection->audio_regions.empty() || !selection->points.empty()) {
if (!selection->regions.empty() || !selection->points.empty()) {
begin_reversible_command (opname + _(" objects"));
if (!selection->audio_regions.empty()) {
if (!selection->regions.empty()) {
cut_copy_regions (op);
if (op == Cut) {
selection->clear_audio_regions ();
selection->clear_regions ();
}
}
@@ -2956,11 +2967,11 @@ Editor::cut_copy_regions (CutCopyOp op)
set<Playlist*> freezelist;
pair<set<Playlist*>::iterator,bool> insert_result;
for (AudioRegionSelection::iterator x = selection->audio_regions.begin(); x != selection->audio_regions.end(); ++x) {
first_position = min ((*x)->region.position(), first_position);
for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
first_position = min ((*x)->region().position(), first_position);
if (op == Cut || op == Clear) {
AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region.playlist());
AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region().playlist());
if (pl) {
insert_result = freezelist.insert (pl);
if (insert_result.second) {
@@ -2971,11 +2982,11 @@ Editor::cut_copy_regions (CutCopyOp op)
}
}
for (AudioRegionSelection::iterator x = selection->audio_regions.begin(); x != selection->audio_regions.end(); ) {
for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ) {
AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region.playlist());
AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region().playlist());
AudioPlaylist* npl;
AudioRegionSelection::iterator tmp;
RegionSelection::iterator tmp;
tmp = x;
++tmp;
@@ -2992,18 +3003,24 @@ Editor::cut_copy_regions (CutCopyOp op)
npl = pi->second;
}
// FIXME
AudioRegion* const ar = dynamic_cast<AudioRegion*>(&(*x)->region());
switch (op) {
case Cut:
npl->add_region (*(new AudioRegion ((*x)->region)), (*x)->region.position() - first_position);
pl->remove_region (&((*x)->region));
if (!ar) break;
npl->add_region (*(new AudioRegion (*ar)), (*x)->region().position() - first_position);
pl->remove_region (&((*x)->region()));
break;
case Copy:
npl->add_region (*(new AudioRegion ((*x)->region)), (*x)->region.position() - first_position);
if (!ar) break;
npl->add_region (*(new AudioRegion (*ar)), (*x)->region().position() - first_position);
break;
case Clear:
pl->remove_region (&((*x)->region));
pl->remove_region (&((*x)->region()));
break;
}
}
@@ -3149,24 +3166,24 @@ Editor::paste_named_selection (float times)
}
void
Editor::duplicate_some_regions (AudioRegionSelection& regions, float times)
Editor::duplicate_some_regions (RegionSelection& regions, float times)
{
Playlist *playlist;
AudioRegionSelection sel = regions; // clear (below) will clear the argument list
RegionSelection sel = regions; // clear (below) will clear the argument list
begin_reversible_command (_("duplicate region"));
selection->clear_audio_regions ();
selection->clear_regions ();
for (AudioRegionSelection::iterator i = sel.begin(); i != sel.end(); ++i) {
for (RegionSelection::iterator i = sel.begin(); i != sel.end(); ++i) {
Region& r ((*i)->region);
Region& r ((*i)->region());
TimeAxisView& tv = (*i)->get_time_axis_view();
AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (&tv);
sigc::connection c = atv->view->AudioRegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
sigc::connection c = atv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
playlist = (*i)->region.playlist();
playlist = (*i)->region().playlist();
session->add_undo (playlist->get_memento());
playlist->duplicate (r, r.last_frame(), times);
session->add_redo_no_execute (playlist->get_memento());
@@ -3336,7 +3353,7 @@ Editor::normalize_region ()
return;
}
if (selection->audio_regions.empty()) {
if (selection->regions.empty()) {
return;
}
@@ -3345,10 +3362,13 @@ Editor::normalize_region ()
track_canvas.get_window()->set_cursor (*wait_cursor);
gdk_flush ();
for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ++r) {
session->add_undo ((*r)->region.get_memento());
(*r)->region.normalize_to (0.0f);
session->add_redo_no_execute ((*r)->region.get_memento());
for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) {
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
if (!arv)
continue;
session->add_undo (arv->region().get_memento());
arv->audio_region().normalize_to (0.0f);
session->add_redo_no_execute (arv->region().get_memento());
}
commit_reversible_command ();
@@ -3363,16 +3383,19 @@ Editor::denormalize_region ()
return;
}
if (selection->audio_regions.empty()) {
if (selection->regions.empty()) {
return;
}
begin_reversible_command ("denormalize");
for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ++r) {
session->add_undo ((*r)->region.get_memento());
(*r)->region.set_scale_amplitude (1.0f);
session->add_redo_no_execute ((*r)->region.get_memento());
for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) {
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
if (!arv)
continue;
session->add_undo (arv->region().get_memento());
arv->audio_region().set_scale_amplitude (1.0f);
session->add_redo_no_execute (arv->region().get_memento());
}
commit_reversible_command ();
@@ -3393,7 +3416,7 @@ Editor::reverse_region ()
void
Editor::apply_filter (AudioFilter& filter, string command)
{
if (selection->audio_regions.empty()) {
if (selection->regions.empty()) {
return;
}
@@ -3402,20 +3425,22 @@ Editor::apply_filter (AudioFilter& filter, string command)
track_canvas.get_window()->set_cursor (*wait_cursor);
gdk_flush ();
for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ) {
for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ) {
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
if (!arv)
continue;
AudioRegion& region ((*r)->region);
Playlist* playlist = region.playlist();
Playlist* playlist = arv->region().playlist();
AudioRegionSelection::iterator tmp;
RegionSelection::iterator tmp;
tmp = r;
++tmp;
if (region.apply (filter) == 0) {
if (arv->audio_region().apply (filter) == 0) {
session->add_undo (playlist->get_memento());
playlist->replace_region (region, *(filter.results.front()), region.position());
playlist->replace_region (arv->region(), *(filter.results.front()), arv->region().position());
session->add_redo_no_execute (playlist->get_memento());
} else {
goto out;
@@ -3425,7 +3450,7 @@ Editor::apply_filter (AudioFilter& filter, string command)
}
commit_reversible_command ();
selection->audio_regions.clear ();
selection->regions.clear ();
out:
track_canvas.get_window()->set_cursor (*current_canvas_cursor);
@@ -3434,8 +3459,8 @@ Editor::apply_filter (AudioFilter& filter, string command)
void
Editor::region_selection_op (void (Region::*pmf)(void))
{
for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
((*i)->region.*pmf)();
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
((*i)->region().*pmf)();
}
}
@@ -3443,16 +3468,16 @@ Editor::region_selection_op (void (Region::*pmf)(void))
void
Editor::region_selection_op (void (Region::*pmf)(void*), void *arg)
{
for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
((*i)->region.*pmf)(arg);
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
((*i)->region().*pmf)(arg);
}
}
void
Editor::region_selection_op (void (Region::*pmf)(bool), bool yn)
{
for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
((*i)->region.*pmf)(yn);
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
((*i)->region().*pmf)(yn);
}
}
@@ -3469,20 +3494,20 @@ Editor::external_edit_region ()
void
Editor::brush (jack_nframes_t pos)
{
AudioRegionSelection sel;
RegionSelection sel;
snap_to (pos);
if (selection->audio_regions.empty()) {
if (selection->regions.empty()) {
/* XXX get selection from region list */
} else {
sel = selection->audio_regions;
sel = selection->regions;
}
if (sel.empty()) {
return;
}
for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
mouse_brush_insert_region ((*i), pos);
}
}
@@ -3490,18 +3515,19 @@ Editor::brush (jack_nframes_t pos)
void
Editor::toggle_gain_envelope_visibility ()
{
for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
(*i)->set_envelope_visible (!(*i)->envelope_visible());
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
if (arv)
arv->set_envelope_visible (!arv->envelope_visible());
}
}
void
Editor::toggle_gain_envelope_active ()
{
for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
AudioRegion* ar = dynamic_cast<AudioRegion*>(&(*i)->region);
if (ar) {
ar->set_envelope_active (true);
}
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
if (arv)
arv->audio_region().set_envelope_active (true);
}
}

View File

@@ -38,16 +38,11 @@ using namespace ARDOUR;
using namespace PBD;
using namespace Gtk;
void
Editor::handle_new_route_p (boost::shared_ptr<Route> route)
{
ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::handle_new_route_p), route));
handle_new_route (route);
}
void
Editor::handle_new_route (boost::shared_ptr<Route> route)
{
ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::handle_new_route), route));
TimeAxisView *tv;
AudioTimeAxisView *atv;
TreeModel::Row parent;

View File

@@ -28,7 +28,7 @@
#include "editor.h"
#include "audio_time_axis.h"
#include "regionview.h"
#include "audio_region_view.h"
#include "region_selection.h"
#include <ardour/session.h>
@@ -100,7 +100,7 @@ Editor::TimeStretchDialog::delete_timestretch_in_progress (GdkEventAny* ev)
}
int
Editor::run_timestretch (AudioRegionSelection& regions, float fraction)
Editor::run_timestretch (RegionSelection& regions, float fraction)
{
pthread_t thread;
@@ -157,39 +157,42 @@ Editor::run_timestretch (AudioRegionSelection& regions, float fraction)
void
Editor::do_timestretch (TimeStretchDialog& dialog)
{
AudioTrack* at;
Track* t;
Playlist* playlist;
AudioRegion* new_region;
Region* new_region;
for (AudioRegionSelection::iterator i = dialog.regions.begin(); i != dialog.regions.end(); ) {
for (RegionSelection::iterator i = dialog.regions.begin(); i != dialog.regions.end(); ) {
AudioRegionView* arv = dynamic_cast<AudioRegionView*>(*i);
if (!arv)
continue;
AudioRegion& aregion ((*i)->region);
TimeAxisView* tv = &(*i)->get_time_axis_view();
AudioTimeAxisView* atv;
AudioRegionSelection::iterator tmp;
AudioRegion& region (arv->audio_region());
TimeAxisView* tv = &(arv->get_time_axis_view());
RouteTimeAxisView* rtv;
RegionSelection::iterator tmp;
cerr << "stretch " << aregion.name() << endl;
cerr << "stretch " << region.name() << endl;
tmp = i;
++tmp;
if ((atv = dynamic_cast<AudioTimeAxisView*> (tv)) == 0) {
if ((rtv = dynamic_cast<RouteTimeAxisView*> (tv)) == 0) {
i = tmp;
continue;
}
if ((at = atv->audio_track()) == 0) {
if ((t = dynamic_cast<Track*> (rtv->route().get())) == 0) {
i = tmp;
continue;
}
if ((playlist = at->disk_stream().playlist()) == 0) {
if ((playlist = t->diskstream().playlist()) == 0) {
i = tmp;
continue;
}
dialog.request.region = &aregion;
dialog.request.region = &region;
if (!dialog.request.running) {
/* we were cancelled */
@@ -204,7 +207,7 @@ Editor::do_timestretch (TimeStretchDialog& dialog)
}
session->add_undo (playlist->get_memento());
playlist->replace_region (aregion, *new_region, aregion.position());
playlist->replace_region (region, *new_region, region.position());
session->add_redo_no_execute (playlist->get_memento());
i = tmp;

View File

@@ -18,6 +18,8 @@
*/
#include <cassert>
#include <pbd/pthread_utils.h>
#include <ardour/audioregion.h>
@@ -26,11 +28,13 @@
#include "i18n.h"
ExportRegionDialog::ExportRegionDialog (PublicEditor& editor, ARDOUR::AudioRegion* region)
ExportRegionDialog::ExportRegionDialog (PublicEditor& editor, ARDOUR::Region* region)
: ExportDialog(editor)
{
audio_region = region;
// FIXME
ARDOUR::AudioRegion* audio_region = dynamic_cast<ARDOUR::AudioRegion*>(region);
assert(audio_region);
do_not_allow_track_and_master_selection();
do_not_allow_channel_count_selection();
}

View File

@@ -27,7 +27,7 @@
class ExportRegionDialog : public ExportDialog
{
public:
ExportRegionDialog (PublicEditor&, ARDOUR::AudioRegion*);
ExportRegionDialog (PublicEditor&, ARDOUR::Region*);
static void* _export_region_thread (void *);
void export_region ();

View File

@@ -290,8 +290,8 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr<Route> rt
_route->panner().Changed.connect (mem_fun(*this, &MixerStrip::connect_to_pan));
if (is_audio_track()) {
audio_track()->diskstream_changed.connect (mem_fun(*this, &MixerStrip::diskstream_changed));
get_diskstream()->speed_changed.connect (mem_fun(*this, &MixerStrip::speed_changed));
audio_track()->DiskstreamChanged.connect (mem_fun(*this, &MixerStrip::diskstream_changed));
get_diskstream()->SpeedChanged.connect (mem_fun(*this, &MixerStrip::speed_changed));
}
_route->name_changed.connect (mem_fun(*this, &RouteUI::name_changed));
@@ -558,11 +558,6 @@ MixerStrip::input_press (GdkEventButton *ev)
case 1:
#if ADVANCED_ROUTE_DISKSTREAM_CONNECTIVITY
if (is_audio_track()) {
citems.push_back (MenuElem (_("Track"), mem_fun(*this, &MixerStrip::select_stream_input)));
}
#endif
citems.push_back (MenuElem (_("Edit"), mem_fun(*this, &MixerStrip::edit_input_configuration)));
citems.push_back (SeparatorElem());
citems.push_back (MenuElem (_("Disconnect"), mem_fun (*(static_cast<RouteUI*>(this)), &RouteUI::disconnect_input)));
@@ -659,42 +654,6 @@ MixerStrip::add_connection_to_output_menu (ARDOUR::Connection* c)
}
}
void
MixerStrip::select_stream_input ()
{
using namespace Menu_Helpers;
Menu *stream_menu = manage (new Menu);
MenuList& items = stream_menu->items();
stream_menu->set_name ("ArdourContextMenu");
Session::AudioDiskstreamList streams = _session.audio_disk_streams();
for (Session::AudioDiskstreamList::iterator i = streams.begin(); i != streams.end(); ++i) {
if (!(*i)->hidden()) {
items.push_back (CheckMenuElem ((*i)->name(), bind (mem_fun(*this, &MixerStrip::stream_input_chosen), *i)));
if (get_diskstream() == *i) {
ignore_toggle = true;
static_cast<CheckMenuItem *> (&items.back())->set_active (true);
ignore_toggle = false;
}
}
}
stream_menu->popup (1, 0);
}
void
MixerStrip::stream_input_chosen (AudioDiskstream *stream)
{
if (is_audio_track()) {
audio_track()->set_diskstream (*stream, this);
}
}
void
MixerStrip::update_diskstream_display ()
{
@@ -785,7 +744,7 @@ MixerStrip::fast_update ()
}
void
MixerStrip::diskstream_changed (void *src)
MixerStrip::diskstream_changed ()
{
Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &MixerStrip::update_diskstream_display));
}
@@ -1181,7 +1140,7 @@ MixerStrip::route_active_changed ()
gpm.set_meter_strip_name ("AudioTrackStripBaseInactive");
}
gpm.set_fader_name ("AudioTrackFader");
} else {
} else { // FIXME: assumed audio bus
if (_route->active()) {
set_name ("AudioBusStripBase");
gpm.set_meter_strip_name ("AudioBusStripBase");

View File

@@ -179,7 +179,7 @@ class MixerStrip : public RouteUI, public Gtk::EventBox
void edit_input_configuration ();
void edit_output_configuration ();
void diskstream_changed (void *src);
void diskstream_changed ();
Gtk::Menu *send_action_menu;
void build_send_action_menu ();

View File

@@ -0,0 +1,19 @@
/* XPM */
static char * tool_audition_xpm[] = {
"16 12 4 1",
" c None",
". c #000000",
"+ c #ECECEC",
"@ c #FFFFFF",
" .. ",
" .+. . ",
" .++. .@. ",
"....+@+... .@. ",
".+++@@+..@. .@.",
".+@@@@+. .@. .@.",
".+@@@@+. .@. .@.",
".+++@@+..@. .@.",
"....+@+... .@. ",
" .++. .@. ",
" .+. . ",
" .. "};

View File

@@ -0,0 +1,18 @@
/* XPM */
static char * tool_gain_xpm[] = {
"16 12 3 1",
" c None",
". c #000000",
"+ c #FFFFFF",
"... ",
".++.. ",
"...++. ",
" ..+. ",
" .+. ",
" .+. ",
" .+. ",
" .+. ",
" .+.. ",
" .++.....",
" ..++++.",
" ....."};

View File

@@ -0,0 +1,18 @@
/* XPM */
static char * tool_object_xpm[] = {
"16 12 3 1",
" c None",
". c #000000",
"+ c #FFFFFF",
" ... ",
" .+. ",
" .+. ",
" .+. ",
" .+..... ",
" .+.+.+... ",
" ...+.+.+.+. ",
" .+.+++++++. ",
" .+++++++++. ",
" ..+++++++.. ",
" ...+++++. ",
" .+++++. "};

View File

@@ -0,0 +1,18 @@
/* XPM */
static char * tool_range_xpm[] = {
"16 12 3 1",
" c None",
". c #000000",
"+ c #FFFFFF",
"... ...",
".+. .. .. .+.",
".+. .+. .+. .+.",
".+..+. .+..+.",
".+.++......++.+.",
".++++++++++++++.",
".+.++......++.+.",
".+..+. .+..+.",
".+. .+. .+. .+.",
".+. .. .. .+.",
".+. .+.",
"... ..."};

View File

@@ -0,0 +1,18 @@
/* XPM */
static char * tool_stretch_xpm[] = {
"16 12 3 1",
" c None",
". c #000000",
"+ c #FFFFFF",
" .. .. ",
" .+. .+. ",
".++..........++.",
"++++++++++++++++",
".++..........++.",
" .+. .+. ",
" .. .. ",
" + + + + ",
" ++ +++ + + +++ ",
"++++++++++++++++",
" ++ + ++ + + ",
" + + + + "};

View File

@@ -0,0 +1,29 @@
/* XPM */
static char * tool_zoom_xpm[] = {
"16 12 14 1",
" c None",
". c #000000",
"+ c #474747",
"@ c #E7E7E7",
"# c #F6F6F6",
"$ c #DCDCDC",
"% c #FFFFFF",
"& c #DFDFDF",
"* c #D7D7D7",
"= c #D6D6D6",
"- c #040404",
"; c #070707",
"> c #060606",
", c #050505",
" ... ",
" +.@#$.+ ",
" .%%%%%. ",
" .&%%%%%*. ",
" .#%%%%%#. ",
" .$%%%%%&. ",
" .%%%%%.+ ",
" +.*#=... ",
" ...+... ",
" -.; ",
" >.- ",
" ,. "};

View File

@@ -0,0 +1,30 @@
/* XPM */
static char * zoom_full_xpm[] = {
"12 12 15 1",
" c None",
". c #000000",
"+ c #474747",
"@ c #E7E7E7",
"# c #F6F6F6",
"$ c #DCDCDC",
"% c #ACACAC",
"& c #FFFFFF",
"* c #DFDFDF",
"= c #D7D7D7",
"- c #D6D6D6",
"; c #040404",
"> c #070707",
", c #060606",
"' c #050505",
" ... ",
" +.@#$.+ ",
" .%&&&%. ",
".*..&..=. ",
".#.&&&.#. ",
".$..&..*. ",
" .%&&&%.+ ",
" +.=#-... ",
" ...+... ",
" ;.> ",
" ,.;",
" '."};

View File

@@ -0,0 +1,29 @@
/* XPM */
static char * zoom_in_xpm[] = {
"12 12 14 1",
" c None",
". c #000000",
"+ c #474747",
"@ c #E7E7E7",
"# c #F6F6F6",
"$ c #DCDCDC",
"% c #FFFFFF",
"& c #DFDFDF",
"* c #D7D7D7",
"= c #D6D6D6",
"- c #040404",
"; c #070707",
"> c #060606",
", c #050505",
" ... ",
" +.@#$.+ ",
" .%%.%%. ",
".&%%.%%*. ",
".#.....#. ",
".$%%.%%&. ",
" .%%.%%.+ ",
" +.*#=... ",
" ...+... ",
" -.; ",
" >.-",
" ,."};

View File

@@ -0,0 +1,29 @@
/* XPM */
static char * zoom_out_xpm[] = {
"12 12 14 1",
" c None",
". c #000000",
"+ c #474747",
"@ c #E7E7E7",
"# c #F6F6F6",
"$ c #DCDCDC",
"% c #FFFFFF",
"& c #DFDFDF",
"* c #D7D7D7",
"= c #D6D6D6",
"- c #040404",
"; c #070707",
"> c #060606",
", c #050505",
" ... ",
" +.@#$.+ ",
" .%%%%%. ",
".&%%%%%*. ",
".#.....#. ",
".$%%%%%&. ",
" .%%%%%.+ ",
" +.*#=... ",
" ...+... ",
" -.; ",
" >.-",
" ,."};

View File

@@ -90,7 +90,7 @@ void
PlaylistSelector::show_for (RouteUI* ruix)
{
vector<const char*> item;
AudioDiskstream* this_ds;
Diskstream* this_ds;
string str;
rui = ruix;
@@ -116,7 +116,7 @@ PlaylistSelector::show_for (RouteUI* ruix)
for (DSPL_Map::iterator x = dspl_map.begin(); x != dspl_map.end(); ++x) {
AudioDiskstream* ds = session->diskstream_by_id (x->first);
Diskstream* ds = session->diskstream_by_id (x->first);
if (ds == 0) {
continue;
@@ -243,7 +243,7 @@ PlaylistSelector::selection_changed ()
return;
}
at->disk_stream().use_playlist (apl);
at->diskstream().use_playlist (apl);
hide ();
}

View File

@@ -29,6 +29,7 @@ namespace ARDOUR {
class Session;
class PluginManager;
class Plugin;
class PluginInfo;
}
class PluginSelector : public ArdourDialog

View File

@@ -39,7 +39,7 @@ class AutomationLine;
class ControlPoint;
class SelectionRect;
class CrossfadeView;
class AudioTimeAxisView;
class RouteTimeAxisView;
class AudioRegionView;
class TempoMarker;
class MeterMarker;
@@ -145,10 +145,10 @@ class PublicEditor : public Gtk::Window, public Stateful {
virtual bool canvas_fade_in_handle_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*) = 0;
virtual bool canvas_fade_out_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*) = 0;
virtual bool canvas_fade_out_handle_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*) = 0;
virtual bool canvas_region_view_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*) = 0;
virtual bool canvas_region_view_name_highlight_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*) = 0;
virtual bool canvas_region_view_name_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*) = 0;
virtual bool canvas_stream_view_event (GdkEvent* event,ArdourCanvas::Item*, AudioTimeAxisView*) = 0;
virtual bool canvas_region_view_event (GdkEvent* event,ArdourCanvas::Item*, RegionView*) = 0;
virtual bool canvas_region_view_name_highlight_event (GdkEvent* event,ArdourCanvas::Item*, RegionView*) = 0;
virtual bool canvas_region_view_name_event (GdkEvent* event,ArdourCanvas::Item*, RegionView*) = 0;
virtual bool canvas_stream_view_event (GdkEvent* event,ArdourCanvas::Item*, RouteTimeAxisView*) = 0;
virtual bool canvas_marker_event (GdkEvent* event,ArdourCanvas::Item*, Marker*) = 0;
virtual bool canvas_zoom_rect_event (GdkEvent* event,ArdourCanvas::Item*) = 0;
virtual bool canvas_tempo_marker_event (GdkEvent* event,ArdourCanvas::Item*, TempoMarker*) = 0;

View File

@@ -2,7 +2,7 @@
#include <ardour/audioregion.h>
#include "region_gain_line.h"
#include "regionview.h"
#include "audio_region_view.h"
#include "utils.h"
#include "time_axis_view.h"
@@ -46,8 +46,8 @@ void
AudioRegionGainLine::start_drag (ControlPoint* cp, float fraction)
{
AutomationLine::start_drag(cp,fraction);
if (!rv.region.envelope_active()) {
trackview.session().add_undo( bind( mem_fun(rv.region, &AudioRegion::set_envelope_active), false) );
if (!rv.audio_region().envelope_active()) {
trackview.session().add_undo( bind( mem_fun(rv.audio_region(), &AudioRegion::set_envelope_active), false) );
}
}
@@ -62,10 +62,10 @@ AudioRegionGainLine::remove_point (ControlPoint& cp)
trackview.editor.current_session()->begin_reversible_command (_("remove control point"));
trackview.editor.current_session()->add_undo (get_memento());
if (!rv.region.envelope_active()) {
trackview.session().add_undo( bind( mem_fun(rv.region, &AudioRegion::set_envelope_active), false) );
trackview.session().add_redo( bind( mem_fun(rv.region, &AudioRegion::set_envelope_active), true) );
rv.region.set_envelope_active(true);
if (!rv.audio_region().envelope_active()) {
trackview.session().add_undo( bind( mem_fun(rv.audio_region(), &AudioRegion::set_envelope_active), false) );
trackview.session().add_redo( bind( mem_fun(rv.audio_region(), &AudioRegion::set_envelope_active), true) );
rv.audio_region().set_envelope_active(true);
}
alist.erase (mr.start, mr.end);
@@ -78,9 +78,9 @@ AudioRegionGainLine::remove_point (ControlPoint& cp)
void
AudioRegionGainLine::end_drag (ControlPoint* cp)
{
if (!rv.region.envelope_active()) {
trackview.session().add_redo( bind( mem_fun(rv.region, &AudioRegion::set_envelope_active), true) );
rv.region.set_envelope_active(true);
if (!rv.audio_region().envelope_active()) {
trackview.session().add_redo( bind( mem_fun(rv.audio_region(), &AudioRegion::set_envelope_active), true) );
rv.audio_region().set_envelope_active(true);
}
AutomationLine::end_drag(cp);
}

View File

@@ -1,8 +1,26 @@
/*
Copyright (C) 2006 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <algorithm>
#include <ardour/audioregion.h>
#include <ardour/region.h>
#include "regionview.h"
#include "region_view.h"
#include "region_selection.h"
using namespace ARDOUR;
@@ -11,7 +29,7 @@ using namespace sigc;
bool
AudioRegionComparator::operator() (const AudioRegionView* a, const AudioRegionView* b) const
RegionComparator::operator() (const RegionView* a, const RegionView* b) const
{
if (a == b) {
return false;
@@ -20,16 +38,16 @@ AudioRegionComparator::operator() (const AudioRegionView* a, const AudioRegionVi
}
}
AudioRegionSelection::AudioRegionSelection ()
RegionSelection::RegionSelection ()
{
_current_start = 0;
_current_end = 0;
}
AudioRegionSelection::AudioRegionSelection (const AudioRegionSelection& other)
RegionSelection::RegionSelection (const RegionSelection& other)
{
for (AudioRegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) {
for (RegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) {
add (*i, false);
}
_current_start = other._current_start;
@@ -38,14 +56,14 @@ AudioRegionSelection::AudioRegionSelection (const AudioRegionSelection& other)
AudioRegionSelection&
AudioRegionSelection::operator= (const AudioRegionSelection& other)
RegionSelection&
RegionSelection::operator= (const RegionSelection& other)
{
if (this != &other) {
clear_all();
for (AudioRegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) {
for (RegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) {
add (*i, false);
}
@@ -57,13 +75,13 @@ AudioRegionSelection::operator= (const AudioRegionSelection& other)
}
void
AudioRegionSelection::clear_all()
RegionSelection::clear_all()
{
clear();
_bylayer.clear();
}
bool AudioRegionSelection::contains (AudioRegionView* rv)
bool RegionSelection::contains (RegionView* rv)
{
if (this->find (rv) != end()) {
return true;
@@ -75,21 +93,21 @@ bool AudioRegionSelection::contains (AudioRegionView* rv)
}
void
AudioRegionSelection::add (AudioRegionView* rv, bool dosort)
RegionSelection::add (RegionView* rv, bool dosort)
{
if (this->find (rv) != end()) {
/* we already have it */
return;
}
rv->AudioRegionViewGoingAway.connect (mem_fun(*this, &AudioRegionSelection::remove_it));
rv->RegionViewGoingAway.connect (mem_fun(*this, &RegionSelection::remove_it));
if (rv->region.first_frame() < _current_start || empty()) {
_current_start = rv->region.first_frame();
if (rv->region().first_frame() < _current_start || empty()) {
_current_start = rv->region().first_frame();
}
if (rv->region.last_frame() > _current_end || empty()) {
_current_end = rv->region.last_frame();
if (rv->region().last_frame() > _current_end || empty()) {
_current_end = rv->region().last_frame();
}
insert (rv);
@@ -100,15 +118,15 @@ AudioRegionSelection::add (AudioRegionView* rv, bool dosort)
}
void
AudioRegionSelection::remove_it (AudioRegionView *rv)
RegionSelection::remove_it (RegionView *rv)
{
remove (rv);
}
bool
AudioRegionSelection::remove (AudioRegionView* rv)
RegionSelection::remove (RegionView* rv)
{
AudioRegionSelection::iterator i;
RegionSelection::iterator i;
if ((i = this->find (rv)) != end()) {
@@ -124,7 +142,7 @@ AudioRegionSelection::remove (AudioRegionView* rv)
} else {
AudioRegion& region ((*i)->region);
Region& region ((*i)->region());
if (region.first_frame() == _current_start) {
@@ -165,15 +183,15 @@ AudioRegionSelection::remove (AudioRegionView* rv)
}
void
AudioRegionSelection::add_to_layer (AudioRegionView * rv)
RegionSelection::add_to_layer (RegionView * rv)
{
// insert it into layer sorted position
list<AudioRegionView*>::iterator i;
list<RegionView*>::iterator i;
for (i = _bylayer.begin(); i != _bylayer.end(); ++i)
{
if (rv->region.layer() < (*i)->region.layer()) {
if (rv->region().layer() < (*i)->region().layer()) {
_bylayer.insert(i, rv);
return;
}
@@ -184,16 +202,16 @@ AudioRegionSelection::add_to_layer (AudioRegionView * rv)
}
struct RegionSortByTime {
bool operator() (const AudioRegionView* a, const AudioRegionView* b) {
return a->region.position() < b->region.position();
bool operator() (const RegionView* a, const RegionView* b) {
return a->region().position() < b->region().position();
}
};
void
AudioRegionSelection::by_position (list<AudioRegionView*>& foo) const
RegionSelection::by_position (list<RegionView*>& foo) const
{
list<AudioRegionView*>::const_iterator i;
list<RegionView*>::const_iterator i;
RegionSortByTime sorter;
for (i = _bylayer.begin(); i != _bylayer.end(); ++i) {

View File

@@ -1,3 +1,21 @@
/*
Copyright (C) 2006 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __ardour_gtk_region_selection_h__
#define __ardour_gtk_region_selection_h__
@@ -9,23 +27,23 @@
using std::list;
using std::set;
class AudioRegionView;
class RegionView;
struct AudioRegionComparator {
bool operator() (const AudioRegionView* a, const AudioRegionView* b) const;
struct RegionComparator {
bool operator() (const RegionView* a, const RegionView* b) const;
};
class AudioRegionSelection : public set<AudioRegionView*, AudioRegionComparator>, public sigc::trackable
class RegionSelection : public set<RegionView*, RegionComparator>, public sigc::trackable
{
public:
AudioRegionSelection();
AudioRegionSelection (const AudioRegionSelection&);
RegionSelection();
RegionSelection (const RegionSelection&);
AudioRegionSelection& operator= (const AudioRegionSelection&);
RegionSelection& operator= (const RegionSelection&);
void add (AudioRegionView*, bool dosort = true);
bool remove (AudioRegionView*);
bool contains (AudioRegionView*);
void add (RegionView*, bool dosort = true);
bool remove (RegionView*);
bool contains (RegionView*);
void clear_all();
@@ -39,18 +57,18 @@ class AudioRegionSelection : public set<AudioRegionView*, AudioRegionComparator>
return _current_end;
}
const list<AudioRegionView *> & by_layer() const { return _bylayer; }
void by_position (list<AudioRegionView*>&) const;
const list<RegionView *> & by_layer() const { return _bylayer; }
void by_position (list<RegionView*>&) const;
private:
void remove_it (AudioRegionView*);
void remove_it (RegionView*);
void add_to_layer (AudioRegionView *);
void add_to_layer (RegionView *);
jack_nframes_t _current_start;
jack_nframes_t _current_end;
list<AudioRegionView *> _bylayer;
list<RegionView *> _bylayer;
};
#endif /* __ardour_gtk_region_selection_h__ */

494
gtk2_ardour/region_view.cc Normal file
View File

@@ -0,0 +1,494 @@
/*
Copyright (C) 2001-2006 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: regionview.cc 691 2006-07-23 12:03:19Z drobilla $
*/
#include <cmath>
#include <cassert>
#include <algorithm>
#include <gtkmm.h>
#include <gtkmm2ext/gtk_ui.h>
#include <ardour/playlist.h>
#include <ardour/audioregion.h>
#include <ardour/audiosource.h>
#include <ardour/audio_diskstream.h>
#include "streamview.h"
#include "region_view.h"
#include "route_time_axis.h"
#include "simplerect.h"
#include "simpleline.h"
#include "waveview.h"
#include "public_editor.h"
#include "region_editor.h"
#include "ghostregion.h"
#include "route_time_axis.h"
#include "utils.h"
#include "rgb_macros.h"
#include "gui_thread.h"
#include "i18n.h"
using namespace sigc;
using namespace ARDOUR;
using namespace PBD;
using namespace Editing;
using namespace ArdourCanvas;
static const int32_t sync_mark_width = 9;
sigc::signal<void,RegionView*> RegionView::RegionViewGoingAway;
RegionView::RegionView (ArdourCanvas::Group* parent,
TimeAxisView& tv,
ARDOUR::Region& r,
double spu,
Gdk::Color& basic_color)
: TimeAxisViewItem (r.name(), *parent, tv, spu, basic_color, r.position(), r.length(),
TimeAxisViewItem::Visibility (TimeAxisViewItem::ShowNameText|
TimeAxisViewItem::ShowNameHighlight|
TimeAxisViewItem::ShowFrame))
, _region (r)
, sync_mark(0)
, no_wave_msg(0)
, editor(0)
, current_visible_sync_position(0.0)
, valid(false)
, _pixel_width(1.0)
, _height(1.0)
, in_destructor(false)
, wait_for_data(false)
{
}
RegionView::RegionView (ArdourCanvas::Group* parent,
TimeAxisView& tv,
ARDOUR::Region& r,
double spu,
Gdk::Color& basic_color,
TimeAxisViewItem::Visibility visibility)
: TimeAxisViewItem (r.name(), *parent, tv, spu, basic_color, r.position(), r.length(), visibility)
, _region (r)
, sync_mark(0)
, no_wave_msg(0)
, editor(0)
, current_visible_sync_position(0.0)
, valid(false)
, _pixel_width(1.0)
, _height(1.0)
, in_destructor(false)
, wait_for_data(false)
{
}
void
RegionView::init (Gdk::Color& basic_color, bool wfd)
{
editor = 0;
valid = true;
in_destructor = false;
_height = 0;
wait_for_data = wfd;
compute_colors (basic_color);
name_highlight->set_data ("regionview", this);
name_text->set_data ("regionview", this);
/* an equilateral triangle */
ArdourCanvas::Points shape;
shape.push_back (Gnome::Art::Point (-((sync_mark_width-1)/2), 1));
shape.push_back (Gnome::Art::Point ((sync_mark_width - 1)/2, 1));
shape.push_back (Gnome::Art::Point (0, sync_mark_width - 1));
shape.push_back (Gnome::Art::Point (-((sync_mark_width-1)/2), 1));
sync_mark = new ArdourCanvas::Polygon (*group);
sync_mark->property_points() = shape;
sync_mark->property_fill_color_rgba() = fill_color;
sync_mark->hide();
reset_width_dependent_items ((double) _region.length() / samples_per_unit);
set_height (trackview.height);
region_muted ();
region_sync_changed ();
region_resized (BoundsChanged);
region_locked ();
_region.StateChanged.connect (mem_fun(*this, &RegionView::region_changed));
group->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_region_view_event), group, this));
name_highlight->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_region_view_name_highlight_event), name_highlight, this));
set_colors ();
ColorChanged.connect (mem_fun (*this, &RegionView::color_handler));
/* XXX sync mark drag? */
}
RegionView::~RegionView ()
{
in_destructor = true;
RegionViewGoingAway (this); /* EMIT_SIGNAL */
for (vector<GhostRegion*>::iterator g = ghosts.begin(); g != ghosts.end(); ++g) {
delete *g;
}
if (editor) {
delete editor;
}
}
gint
RegionView::_lock_toggle (ArdourCanvas::Item* item, GdkEvent* ev, void* arg)
{
switch (ev->type) {
case GDK_BUTTON_RELEASE:
static_cast<RegionView*>(arg)->lock_toggle ();
return TRUE;
break;
default:
break;
}
return FALSE;
}
void
RegionView::lock_toggle ()
{
_region.set_locked (!_region.locked());
}
void
RegionView::region_changed (Change what_changed)
{
ENSURE_GUI_THREAD (bind (mem_fun(*this, &RegionView::region_changed), what_changed));
if (what_changed & BoundsChanged) {
region_resized (what_changed);
region_sync_changed ();
}
if (what_changed & Region::MuteChanged) {
region_muted ();
}
if (what_changed & Region::OpacityChanged) {
region_opacity ();
}
if (what_changed & ARDOUR::NameChanged) {
region_renamed ();
}
if (what_changed & Region::SyncOffsetChanged) {
region_sync_changed ();
}
if (what_changed & Region::LayerChanged) {
region_layered ();
}
if (what_changed & Region::LockChanged) {
region_locked ();
}
}
void
RegionView::region_locked ()
{
/* name will show locked status */
region_renamed ();
}
void
RegionView::region_resized (Change what_changed)
{
double unit_length;
if (what_changed & ARDOUR::PositionChanged) {
set_position (_region.position(), 0);
}
if (what_changed & Change (StartChanged|LengthChanged)) {
set_duration (_region.length(), 0);
unit_length = _region.length() / samples_per_unit;
reset_width_dependent_items (unit_length);
for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
(*i)->set_duration (unit_length);
}
}
}
void
RegionView::reset_width_dependent_items (double pixel_width)
{
TimeAxisViewItem::reset_width_dependent_items (pixel_width);
_pixel_width = pixel_width;
}
void
RegionView::region_layered ()
{
RouteTimeAxisView *rtv = dynamic_cast<RouteTimeAxisView*>(&get_time_axis_view());
assert(rtv);
rtv->view()->region_layered (this);
}
void
RegionView::region_muted ()
{
set_frame_color ();
region_renamed ();
}
void
RegionView::region_opacity ()
{
set_frame_color ();
}
void
RegionView::raise ()
{
_region.raise ();
}
void
RegionView::raise_to_top ()
{
_region.raise_to_top ();
}
void
RegionView::lower ()
{
_region.lower ();
}
void
RegionView::lower_to_bottom ()
{
_region.lower_to_bottom ();
}
bool
RegionView::set_position (jack_nframes_t pos, void* src, double* ignored)
{
double delta;
bool ret;
if (!(ret = TimeAxisViewItem::set_position (pos, this, &delta))) {
return false;
}
if (ignored) {
*ignored = delta;
}
if (delta) {
for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
(*i)->group->move (delta, 0.0);
}
}
return ret;
}
void
RegionView::set_samples_per_unit (gdouble spu)
{
TimeAxisViewItem::set_samples_per_unit (spu);
for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
(*i)->set_samples_per_unit (spu);
(*i)->set_duration (_region.length() / samples_per_unit);
}
region_sync_changed ();
}
bool
RegionView::set_duration (jack_nframes_t frames, void *src)
{
if (!TimeAxisViewItem::set_duration (frames, src)) {
return false;
}
for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
(*i)->set_duration (_region.length() / samples_per_unit);
}
return true;
}
void
RegionView::compute_colors (Gdk::Color& basic_color)
{
TimeAxisViewItem::compute_colors (basic_color);
}
void
RegionView::set_colors ()
{
TimeAxisViewItem::set_colors ();
if (sync_mark) {
sync_mark->property_fill_color_rgba() = fill_color;
}
}
void
RegionView::set_frame_color ()
{
if (_region.opaque()) {
fill_opacity = 180;
} else {
fill_opacity = 100;
}
TimeAxisViewItem::set_frame_color ();
}
void
RegionView::hide_region_editor()
{
if (editor) {
editor->hide_all ();
}
}
void
RegionView::region_renamed ()
{
string str;
if (_region.locked()) {
str += '>';
str += _region.name();
str += '<';
} else {
str = _region.name();
}
if (_region.speed_mismatch (trackview.session().frame_rate())) {
str = string ("*") + str;
}
if (_region.muted()) {
str = string ("!") + str;
}
set_item_name (str, this);
set_name_text (str);
}
void
RegionView::region_sync_changed ()
{
if (sync_mark == 0) {
return;
}
int sync_dir;
jack_nframes_t sync_offset;
sync_offset = _region.sync_offset (sync_dir);
/* this has to handle both a genuine change of position, a change of samples_per_unit,
and a change in the bounds of the _region.
*/
if (sync_offset == 0) {
/* no sync mark - its the start of the region */
sync_mark->hide();
} else {
if ((sync_dir < 0) || ((sync_dir > 0) && (sync_offset > _region.length()))) {
/* no sync mark - its out of the bounds of the region */
sync_mark->hide();
} else {
/* lets do it */
Points points;
//points = sync_mark->property_points().get_value();
double offset = sync_offset / samples_per_unit;
points.push_back (Gnome::Art::Point (offset - ((sync_mark_width-1)/2), 1));
points.push_back (Gnome::Art::Point (offset + ((sync_mark_width-1)/2), 1));
points.push_back (Gnome::Art::Point (offset, sync_mark_width - 1));
points.push_back (Gnome::Art::Point (offset - ((sync_mark_width-1)/2), 1));
sync_mark->property_points().set_value (points);
sync_mark->show();
}
}
}
void
RegionView::move (double x_delta, double y_delta)
{
if (_region.locked() || (x_delta == 0 && y_delta == 0)) {
return;
}
get_canvas_group()->move (x_delta, y_delta);
/* note: ghosts never leave their tracks so y_delta for them is always zero */
for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
(*i)->group->move (x_delta, 0.0);
}
}
void
RegionView::remove_ghost (GhostRegion* ghost)
{
if (in_destructor) {
return;
}
for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
if (*i == ghost) {
ghosts.erase (i);
break;
}
}
}
uint32_t
RegionView::get_fill_color ()
{
return fill_color;
}

140
gtk2_ardour/region_view.h Normal file
View File

@@ -0,0 +1,140 @@
/*
Copyright (C) 2001-2006 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __gtk_ardour_region_view_h__
#define __gtk_ardour_region_view_h__
#include <vector>
#include <libgnomecanvasmm.h>
#include <libgnomecanvasmm/polygon.h>
#include <sigc++/signal.h>
#include <ardour/region.h>
#include "time_axis_view_item.h"
#include "automation_line.h"
#include "enums.h"
#include "waveview.h"
#include "canvas.h"
#include "color.h"
class TimeAxisView;
class RegionEditor;
class GhostRegion;
class AutomationTimeAxisView;
class RegionView : public TimeAxisViewItem
{
public:
RegionView (ArdourCanvas::Group* parent,
TimeAxisView& time_view,
ARDOUR::Region& region,
double samples_per_unit,
Gdk::Color& basic_color);
~RegionView ();
virtual void init (Gdk::Color& base_color, bool wait_for_data);
ARDOUR::Region& region() const { return _region; }
bool is_valid() const { return valid; }
void set_valid (bool yn) { valid = yn; }
virtual void set_height (double) = 0;
virtual void set_samples_per_unit (double);
virtual bool set_duration (jack_nframes_t, void*);
void move (double xdelta, double ydelta);
void raise ();
void raise_to_top ();
void lower ();
void lower_to_bottom ();
bool set_position(jack_nframes_t pos, void* src, double* delta = 0);
virtual void show_region_editor () = 0;
virtual void hide_region_editor();
virtual void region_changed (ARDOUR::Change);
virtual GhostRegion* add_ghost (AutomationTimeAxisView&) = 0;
void remove_ghost (GhostRegion*);
uint32_t get_fill_color ();
virtual void entered () {}
virtual void exited () {}
static sigc::signal<void,RegionView*> RegionViewGoingAway;
sigc::signal<void> GoingAway;
protected:
/** Allows derived types to specify their visibility requirements
* to the TimeAxisViewItem parent class
*/
RegionView (ArdourCanvas::Group *,
TimeAxisView&,
ARDOUR::Region&,
double samples_per_unit,
Gdk::Color& basic_color,
TimeAxisViewItem::Visibility);
virtual void region_resized (ARDOUR::Change);
void region_moved (void *);
virtual void region_muted ();
void region_locked ();
void region_opacity ();
void region_layered ();
void region_renamed ();
void region_sync_changed ();
static gint _lock_toggle (ArdourCanvas::Item*, GdkEvent*, void*);
void lock_toggle ();
virtual void set_colors ();
virtual void compute_colors (Gdk::Color&);
virtual void set_frame_color ();
virtual void reset_width_dependent_items (double pixel_width);
virtual void color_handler (ColorID, uint32_t) {}
ARDOUR::Region& _region;
ArdourCanvas::Polygon* sync_mark; ///< polgyon for sync position
ArdourCanvas::Text* no_wave_msg;
RegionEditor* editor;
vector<ControlPoint *> control_points;
double current_visible_sync_position;
bool valid; ///< see StreamView::redisplay_diskstream()
double _pixel_width;
double _height;
bool in_destructor;
bool wait_for_data;
sigc::connection data_ready_connection;
vector<GhostRegion*> ghosts;
};
#endif /* __gtk_ardour_region_view_h__ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,256 @@
/*
Copyright (C) 2006 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: audio_time_axis.h 664 2006-07-05 19:47:25Z drobilla $
*/
#ifndef __ardour_route_time_axis_h__
#define __ardour_route_time_axis_h__
#include <gtkmm/table.h>
#include <gtkmm/button.h>
#include <gtkmm/box.h>
#include <gtkmm/menu.h>
#include <gtkmm/menuitem.h>
#include <gtkmm/radiomenuitem.h>
#include <gtkmm/checkmenuitem.h>
#include <gtkmm2ext/selector.h>
#include <list>
#include <ardour/types.h>
#include "ardour_dialog.h"
#include "route_ui.h"
#include "enums.h"
#include "time_axis_view.h"
#include "canvas.h"
#include "color.h"
namespace ARDOUR {
class Session;
class Region;
class Diskstream;
class RouteGroup;
class Redirect;
class Insert;
class Location;
class Playlist;
}
class PublicEditor;
class RegionView;
class StreamView;
class Selection;
class RegionSelection;
class Selectable;
class AutomationTimeAxisView;
class AutomationLine;
class RedirectAutomationLine;
class TimeSelection;
class RouteTimeAxisView : public RouteUI, public TimeAxisView
{
public:
RouteTimeAxisView (PublicEditor&, ARDOUR::Session&, boost::shared_ptr<ARDOUR::Route>, ArdourCanvas::Canvas& canvas);
virtual ~RouteTimeAxisView ();
void show_selection (TimeSelection&);
void set_samples_per_unit (double);
void set_height (TimeAxisView::TrackHeight);
void show_timestretch (jack_nframes_t start, jack_nframes_t end);
void hide_timestretch ();
void selection_click (GdkEventButton*);
void set_selected_points (PointSelection&);
void set_selected_regionviews (RegionSelection&);
void get_selectables (jack_nframes_t start, jack_nframes_t end, double top, double bot, list<Selectable *>&);
void get_inverted_selectables (Selection&, list<Selectable*>&);
ARDOUR::Region* find_next_region (jack_nframes_t pos, ARDOUR::RegionPoint, int32_t dir);
/* Editing operations */
bool cut_copy_clear (Selection&, Editing::CutCopyOp);
bool paste (jack_nframes_t, float times, Selection&, size_t nth);
list<TimeAxisView*> get_child_list();
/* The editor calls these when mapping an operation across multiple tracks */
void use_new_playlist (bool prompt);
void use_copy_playlist (bool prompt);
void clear_playlist ();
void build_playlist_menu (Gtk::Menu *);
string name() const;
StreamView* view() const { return _view; }
ARDOUR::RouteGroup* edit_group() const;
ARDOUR::Playlist* playlist() const;
protected:
friend class StreamView;
struct RedirectAutomationNode {
uint32_t what;
Gtk::CheckMenuItem* menu_item;
AutomationTimeAxisView* view;
RouteTimeAxisView& parent;
RedirectAutomationNode (uint32_t w, Gtk::CheckMenuItem* mitem, RouteTimeAxisView& p)
: what (w), menu_item (mitem), view (0), parent (p) {}
~RedirectAutomationNode ();
};
struct RedirectAutomationInfo {
boost::shared_ptr<ARDOUR::Redirect> redirect;
bool valid;
Gtk::Menu* menu;
vector<RedirectAutomationNode*> lines;
RedirectAutomationInfo (boost::shared_ptr<ARDOUR::Redirect> r)
: redirect (r), valid (true), menu (0) {}
~RedirectAutomationInfo ();
};
void diskstream_changed ();
void update_diskstream_display ();
gint edit_click (GdkEventButton *);
void build_redirect_window ();
void redirect_click ();
void redirect_add ();
void redirect_remove ();
void redirect_edit ();
void redirect_relist ();
void redirect_row_selected (gint row, gint col, GdkEvent *ev);
void add_to_redirect_display (ARDOUR::Redirect *);
void redirects_changed (void *);
void add_redirect_to_subplugin_menu (boost::shared_ptr<ARDOUR::Redirect>);
void remove_ran (RedirectAutomationNode* ran);
void redirect_menu_item_toggled (RouteTimeAxisView::RedirectAutomationInfo*,
RouteTimeAxisView::RedirectAutomationNode*);
void redirect_automation_track_hidden (RedirectAutomationNode*,
boost::shared_ptr<ARDOUR::Redirect>);
RedirectAutomationNode*
find_redirect_automation_node (boost::shared_ptr<ARDOUR::Redirect> r, uint32_t);
RedirectAutomationLine*
find_redirect_automation_curve (boost::shared_ptr<ARDOUR::Redirect> r, uint32_t);
void add_redirect_automation_curve (boost::shared_ptr<ARDOUR::Redirect> r, uint32_t);
void add_existing_redirect_automation_curves (boost::shared_ptr<ARDOUR::Redirect>);
void reset_redirect_automation_curves ();
void update_automation_view (ARDOUR::AutomationType);
void take_name_changed (void *);
void route_name_changed (void *);
void name_entry_changed ();
void on_area_realize ();
virtual void label_view ();
void add_edit_group_menu_item (ARDOUR::RouteGroup *, Gtk::RadioMenuItem::Group*);
void set_edit_group_from_menu (ARDOUR::RouteGroup *);
void reset_samples_per_unit ();
void select_track_color();
virtual void build_automation_action_menu ();
virtual void append_extra_display_menu_items () {}
void build_display_menu ();
void align_style_changed ();
void set_align_style (ARDOUR::AlignStyle);
virtual void set_playlist (ARDOUR::Playlist *);
void playlist_click ();
void show_playlist_selector ();
void playlist_changed ();
void playlist_state_changed (ARDOUR::Change);
void playlist_modified ();
void add_playlist_to_playlist_menu (ARDOUR::Playlist*);
void rename_current_playlist ();
void automation_click ();
virtual void show_all_automation ();
virtual void show_existing_automation ();
virtual void hide_all_automation ();
void timestretch (jack_nframes_t start, jack_nframes_t end);
void visual_click ();
void hide_click ();
gint when_displayed (GdkEventAny*);
void speed_changed ();
void map_frozen ();
void color_handler (ColorID, uint32_t);
bool select_me (GdkEventButton*);
void region_view_added (RegionView*);
void add_ghost_to_redirect (RegionView*, AutomationTimeAxisView*);
StreamView* _view;
ArdourCanvas::Canvas& parent_canvas;
bool no_redraw;
Gtk::HBox other_button_hbox;
Gtk::Table button_table;
Gtk::Button redirect_button;
Gtk::Button edit_group_button;
Gtk::Button playlist_button;
Gtk::Button size_button;
Gtk::Button automation_button;
Gtk::Button hide_button;
Gtk::Button visual_button;
Gtk::Menu subplugin_menu;
Gtk::Menu* automation_action_menu;
Gtk::Menu edit_group_menu;
Gtk::RadioMenuItem* align_existing_item;
Gtk::RadioMenuItem* align_capture_item;
Gtk::Menu* playlist_menu;
Gtk::Menu* playlist_action_menu;
Gtk::MenuItem* playlist_item;
ArdourCanvas::SimpleRect* timestretch_rect;
list<RedirectAutomationInfo*> redirect_automation;
vector<RedirectAutomationLine*> redirect_automation_curves;
sigc::connection modified_connection;
sigc::connection state_changed_connection;
};
#endif /* __ardour_route_time_axis_h__ */

View File

@@ -70,14 +70,14 @@ RouteUI::RouteUI (boost::shared_ptr<ARDOUR::Route> rt, ARDOUR::Session& sess, co
mute_button = manage (new BindableToggleButton (_route->mute_control(), m_name ));
solo_button = manage (new BindableToggleButton (_route->solo_control(), s_name ));
if (is_audio_track()) {
boost::shared_ptr<AudioTrack> at = boost::dynamic_pointer_cast<AudioTrack>(_route);
if (is_track()) {
boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
at->disk_stream().record_enable_changed.connect (mem_fun (*this, &RouteUI::route_rec_enable_changed));
t->diskstream().RecordEnableChanged.connect (mem_fun (*this, &RouteUI::route_rec_enable_changed));
_session.RecordStateChanged.connect (mem_fun (*this, &RouteUI::session_rec_enable_changed));
rec_enable_button = manage (new BindableToggleButton (at->rec_enable_control(), r_name ));
rec_enable_button = manage (new BindableToggleButton (t->rec_enable_control(), r_name ));
rec_enable_button->unset_flags (Gtk::CAN_FOCUS);
@@ -268,7 +268,7 @@ RouteUI::solo_release(GdkEventButton* ev)
gint
RouteUI::rec_enable_press(GdkEventButton* ev)
{
if (!ignore_toggle && is_audio_track() && rec_enable_button) {
if (!ignore_toggle && is_track() && rec_enable_button) {
if (ev->button == 2 && Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
// do nothing on midi bind event
@@ -351,7 +351,7 @@ RouteUI::update_mute_display ()
}
void
RouteUI::route_rec_enable_changed (void *src)
RouteUI::route_rec_enable_changed ()
{
Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_rec_display));
}
@@ -694,7 +694,7 @@ RouteUI::remove_this_route ()
vector<string> choices;
string prompt;
if (is_audio_track()) {
if (is_track()) {
prompt = string_compose (_("Do you really want to remove track \"%1\" ?\n\nYou may also lose the playlist used by this track.\n(cannot be undone)"), _route->name());
} else {
prompt = string_compose (_("Do you really want to remove bus \"%1\" ?\n(cannot be undone)"), _route->name());
@@ -869,30 +869,42 @@ RouteUI::disconnect_output ()
_route->disconnect_outputs (this);
}
bool
RouteUI::is_track () const
{
return dynamic_cast<Track*>(_route.get()) != 0;
}
Track*
RouteUI::track() const
{
return dynamic_cast<Track*>(_route.get());
}
bool
RouteUI::is_audio_track () const
{
return dynamic_cast<AudioTrack*>(_route.get()) != 0;
}
AudioDiskstream*
RouteUI::get_diskstream () const
{
boost::shared_ptr<AudioTrack> at;
if ((at = boost::dynamic_pointer_cast<AudioTrack>(_route)) != 0) {
return &at->disk_stream();
} else {
return 0;
}
}
AudioTrack*
RouteUI::audio_track() const
{
return dynamic_cast<AudioTrack*>(_route.get());
}
Diskstream*
RouteUI::get_diskstream () const
{
boost::shared_ptr<Track> t;
if ((t = boost::dynamic_pointer_cast<Track>(_route)) != 0) {
return &t->diskstream();
} else {
return 0;
}
}
string
RouteUI::name() const
{
@@ -917,3 +929,4 @@ RouteUI::map_frozen ()
}
}
}

View File

@@ -26,6 +26,7 @@
#include <pbd/xml++.h>
#include <ardour/ardour.h>
#include <ardour/route.h>
#include <ardour/track.h>
#include "axis_view.h"
@@ -47,11 +48,16 @@ class RouteUI : public virtual AxisView
RouteUI(boost::shared_ptr<ARDOUR::Route>, ARDOUR::Session&, const char*, const char*, const char*);
virtual ~RouteUI();
bool is_track() const;
bool is_audio_track() const;
ARDOUR::AudioDiskstream* get_diskstream() const;
boost::shared_ptr<ARDOUR::Route> route() const { return _route; }
// FIXME: make these return shared_ptr
ARDOUR::Track* track() const;
ARDOUR::AudioTrack* audio_track() const;
ARDOUR::Diskstream* get_diskstream() const;
string name() const;
@@ -89,7 +95,8 @@ class RouteUI : public virtual AxisView
void solo_changed(void*);
void mute_changed(void*);
void route_rec_enable_changed(void*);
virtual void redirects_changed (void *) {}
void route_rec_enable_changed();
void session_rec_enable_changed();
void build_solo_menu (void);

View File

@@ -24,7 +24,7 @@
#include <ardour/playlist.h>
#include "regionview.h"
#include "region_view.h"
#include "selection.h"
#include "selection_templates.h"
#include "time_axis_view.h"
@@ -46,7 +46,7 @@ Selection&
Selection::operator= (const Selection& other)
{
if (&other != this) {
audio_regions = other.audio_regions;
regions = other.regions;
tracks = other.tracks;
time = other.time;
lines = other.lines;
@@ -57,7 +57,7 @@ Selection::operator= (const Selection& other)
bool
operator== (const Selection& a, const Selection& b)
{
return a.audio_regions == b.audio_regions &&
return a.regions == b.regions &&
a.tracks == b.tracks &&
a.time.track == b.time.track &&
a.time.group == b.time.group &&
@@ -71,7 +71,7 @@ void
Selection::clear ()
{
clear_tracks ();
clear_audio_regions ();
clear_regions ();
clear_points ();
clear_lines();
clear_time ();
@@ -83,8 +83,8 @@ void
Selection::dump_region_layers()
{
cerr << "region selection layer dump" << endl;
for (AudioRegionSelection::iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) {
cerr << "layer: " << (int)(*i)->region.layer() << endl;
for (RegionSelection::iterator i = regions.begin(); i != regions.end(); ++i) {
cerr << "layer: " << (int)(*i)->region().layer() << endl;
}
}
@@ -99,10 +99,10 @@ Selection::clear_redirects ()
}
void
Selection::clear_audio_regions ()
Selection::clear_regions ()
{
if (!audio_regions.empty()) {
audio_regions.clear_all ();
if (!regions.empty()) {
regions.clear_all ();
RegionsChanged();
}
}
@@ -196,29 +196,29 @@ Selection::toggle (TimeAxisView* track)
}
void
Selection::toggle (AudioRegionView* r)
Selection::toggle (RegionView* r)
{
AudioRegionSelection::iterator i;
RegionSelection::iterator i;
if ((i = find (audio_regions.begin(), audio_regions.end(), r)) == audio_regions.end()) {
audio_regions.add (r);
if ((i = find (regions.begin(), regions.end(), r)) == regions.end()) {
regions.add (r);
} else {
audio_regions.erase (i);
regions.erase (i);
}
RegionsChanged ();
}
void
Selection::toggle (vector<AudioRegionView*>& r)
Selection::toggle (vector<RegionView*>& r)
{
AudioRegionSelection::iterator i;
RegionSelection::iterator i;
for (vector<AudioRegionView*>::iterator x = r.begin(); x != r.end(); ++x) {
if ((i = find (audio_regions.begin(), audio_regions.end(), (*x))) == audio_regions.end()) {
audio_regions.add ((*x));
for (vector<RegionView*>::iterator x = r.begin(); x != r.end(); ++x) {
if ((i = find (regions.begin(), regions.end(), (*x))) == regions.end()) {
regions.add ((*x));
} else {
audio_regions.erase (i);
regions.erase (i);
}
}
@@ -310,22 +310,22 @@ Selection::add (TimeAxisView* track)
}
void
Selection::add (AudioRegionView* r)
Selection::add (RegionView* r)
{
if (find (audio_regions.begin(), audio_regions.end(), r) == audio_regions.end()) {
audio_regions.add (r);
if (find (regions.begin(), regions.end(), r) == regions.end()) {
regions.add (r);
RegionsChanged ();
}
}
void
Selection::add (vector<AudioRegionView*>& v)
Selection::add (vector<RegionView*>& v)
{
bool changed = false;
for (vector<AudioRegionView*>::iterator i = v.begin(); i != v.end(); ++i) {
if (find (audio_regions.begin(), audio_regions.end(), (*i)) == audio_regions.end()) {
audio_regions.add ((*i));
for (vector<RegionView*>::iterator i = v.begin(); i != v.end(); ++i) {
if (find (regions.begin(), regions.end(), (*i)) == regions.end()) {
regions.add ((*i));
changed = true;
}
}
@@ -451,9 +451,9 @@ Selection::remove (const list<Playlist*>& pllist)
}
void
Selection::remove (AudioRegionView* r)
Selection::remove (RegionView* r)
{
audio_regions.remove (r);
regions.remove (r);
RegionsChanged ();
}
@@ -526,17 +526,16 @@ Selection::set (const list<Playlist*>& pllist)
}
void
Selection::set (AudioRegionView* r)
Selection::set (RegionView* r)
{
clear_audio_regions ();
clear_regions ();
add (r);
}
void
Selection::set (vector<AudioRegionView*>& v)
Selection::set (vector<RegionView*>& v)
{
clear_audio_regions ();
clear_regions ();
// make sure to deselect any automation selections
clear_points();
add (v);
@@ -590,15 +589,15 @@ Selection::selected (TimeAxisView* tv)
}
bool
Selection::selected (AudioRegionView* arv)
Selection::selected (RegionView* rv)
{
return find (audio_regions.begin(), audio_regions.end(), arv) != audio_regions.end();
return find (regions.begin(), regions.end(), rv) != regions.end();
}
bool
Selection::empty ()
{
return audio_regions.empty () &&
return regions.empty () &&
tracks.empty () &&
points.empty () &&
playlists.empty () &&
@@ -612,7 +611,7 @@ Selection::empty ()
void
Selection::set (list<Selectable*>& selectables)
{
clear_audio_regions();
clear_regions();
clear_points ();
add (selectables);
}
@@ -620,14 +619,14 @@ Selection::set (list<Selectable*>& selectables)
void
Selection::add (list<Selectable*>& selectables)
{
AudioRegionView* arv;
RegionView* rv;
AutomationSelectable* as;
vector<AudioRegionView*> arvs;
vector<RegionView*> rvs;
vector<AutomationSelectable*> autos;
for (std::list<Selectable*>::iterator i = selectables.begin(); i != selectables.end(); ++i) {
if ((arv = dynamic_cast<AudioRegionView*> (*i)) != 0) {
arvs.push_back (arv);
if ((rv = dynamic_cast<RegionView*> (*i)) != 0) {
rvs.push_back (rv);
} else if ((as = dynamic_cast<AutomationSelectable*> (*i)) != 0) {
autos.push_back (as);
} else {
@@ -638,8 +637,8 @@ Selection::add (list<Selectable*>& selectables)
}
}
if (!arvs.empty()) {
add (arvs);
if (!rvs.empty()) {
add (rvs);
}
if (!autos.empty()) {

View File

@@ -35,7 +35,7 @@
#include "point_selection.h"
class TimeAxisView;
class AudioRegionView;
class RegionView;
class Selectable;
namespace ARDOUR {
@@ -61,7 +61,7 @@ class Selection : public sigc::trackable
};
TrackSelection tracks;
AudioRegionSelection audio_regions;
RegionSelection regions;
TimeSelection time;
AutomationSelection lines;
PlaylistSelection playlists;
@@ -89,15 +89,15 @@ class Selection : public sigc::trackable
void dump_region_layers();
bool selected (TimeAxisView*);
bool selected (AudioRegionView*);
bool selected (RegionView*);
void set (list<Selectable*>&);
void add (list<Selectable*>&);
void set (TimeAxisView*);
void set (const list<TimeAxisView*>&);
void set (AudioRegionView*);
void set (std::vector<AudioRegionView*>&);
void set (RegionView*);
void set (std::vector<RegionView*>&);
long set (TimeAxisView*, jack_nframes_t, jack_nframes_t);
void set (ARDOUR::AutomationList*);
void set (ARDOUR::Playlist*);
@@ -107,8 +107,8 @@ class Selection : public sigc::trackable
void toggle (TimeAxisView*);
void toggle (const list<TimeAxisView*>&);
void toggle (AudioRegionView*);
void toggle (std::vector<AudioRegionView*>&);
void toggle (RegionView*);
void toggle (std::vector<RegionView*>&);
long toggle (jack_nframes_t, jack_nframes_t);
void toggle (ARDOUR::AutomationList*);
void toggle (ARDOUR::Playlist*);
@@ -117,8 +117,8 @@ class Selection : public sigc::trackable
void add (TimeAxisView*);
void add (const list<TimeAxisView*>&);
void add (AudioRegionView*);
void add (std::vector<AudioRegionView*>&);
void add (RegionView*);
void add (std::vector<RegionView*>&);
long add (jack_nframes_t, jack_nframes_t);
void add (ARDOUR::AutomationList*);
void add (ARDOUR::Playlist*);
@@ -127,7 +127,7 @@ class Selection : public sigc::trackable
void remove (TimeAxisView*);
void remove (const list<TimeAxisView*>&);
void remove (AudioRegionView*);
void remove (RegionView*);
void remove (uint32_t selection_id);
void remove (jack_nframes_t, jack_nframes_t);
void remove (ARDOUR::AutomationList*);
@@ -137,7 +137,7 @@ class Selection : public sigc::trackable
void replace (uint32_t time_index, jack_nframes_t start, jack_nframes_t end);
void clear_audio_regions();
void clear_regions();
void clear_tracks ();
void clear_time();
void clear_lines ();
@@ -145,10 +145,8 @@ class Selection : public sigc::trackable
void clear_redirects ();
void clear_points ();
void foreach_audio_region (void (ARDOUR::AudioRegion::*method)(void));
void foreach_audio_region (void (ARDOUR::Region::*method)(void));
template<class A> void foreach_audio_region (void (ARDOUR::AudioRegion::*method)(A), A arg);
template<class A> void foreach_audio_region (void (ARDOUR::Region::*method)(A), A arg);
void foreach_region (void (ARDOUR::Region::*method)(void));
template<class A> void foreach_region (void (ARDOUR::Region::*method)(A), A arg);
private:
uint32_t next_time_id;

View File

@@ -27,35 +27,21 @@
*/
#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))();
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::AudioRegion::*method)(A), A arg) {
for (AudioRegionSelection::iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) {
((*i)->region.*(method))(arg);
}
}
template<class A> inline void
Selection::foreach_audio_region (void (ARDOUR::Region::*method)(A), A arg) {
for (AudioRegionSelection::iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) {
((*i)->region.*(method))(arg);
Selection::foreach_region (void (ARDOUR::Region::*method)(A), A arg) {
for (RegionSelection::iterator i = regions.begin(); i != regions.end(); ++i) {
((*i)->region().*(method))(arg);
}
}
@@ -64,14 +50,14 @@ Selection::foreach_audio_region (void (ARDOUR::Region::*method)(A), A arg) {
template<class A> inline void
Selection::foreach_route (void (ARDOUR::Route::*method)(A), A arg) {
for (list<ARDOUR::Route*>::iterator i = routes.begin(); i != routes.end(); ++i) {
((*i)->region.*(method))(arg);
((*i)->region().*(method))(arg);
}
}
template<class A1, class A2> inline void
Selection::foreach_route (void (ARDOUR::Route::*method)(A1,A2), A1 arg1, A2 arg2) {
for (list<ARDOUR::Route*>::iterator i = routes.begin(); i != routes.end(); ++i) {
((*i)->region.*(method))(arg1, arg2);
((*i)->region().*(method))(arg1, arg2);
}
}

View File

@@ -1,28 +1,42 @@
/*
Copyright (C) 2001, 2006 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <cmath>
#include <gtkmm.h>
#include <gtkmm2ext/gtk_ui.h>
#include <ardour/audioplaylist.h>
#include <ardour/audioregion.h>
#include <ardour/audiosource.h>
#include <ardour/audio_diskstream.h>
#include <ardour/audio_track.h>
#include <ardour/playlist_templates.h>
#include <ardour/playlist.h>
#include <ardour/region.h>
#include <ardour/source.h>
#include <ardour/diskstream.h>
#include <ardour/track.h>
#include "streamview.h"
#include "regionview.h"
#include "taperegionview.h"
#include "audio_time_axis.h"
#include "region_view.h"
#include "route_time_axis.h"
#include "canvas-waveview.h"
#include "canvas-simplerect.h"
#include "region_selection.h"
#include "selection.h"
#include "public_editor.h"
#include "ardour_ui.h"
#include "crossfade_view.h"
#include "rgb_macros.h"
#include "gui_thread.h"
#include "utils.h"
@@ -32,21 +46,10 @@ using namespace ARDOUR;
using namespace PBD;
using namespace Editing;
StreamView::StreamView (AudioTimeAxisView& tv)
StreamView::StreamView (RouteTimeAxisView& tv)
: _trackview (tv)
{
region_color = _trackview.color();
crossfades_visible = true;
if (tv.is_audio_track()) {
/* TRACK */
//stream_base_color = RGBA_TO_UINT (222,223,218,255);
stream_base_color = color_map[cAudioTrackBase];
} else {
/* BUS */
//stream_base_color = RGBA_TO_UINT (230,226,238,255);
stream_base_color = color_map[cAudioBusBase];
}
/* set_position() will position the group */
@@ -57,26 +60,23 @@ StreamView::StreamView (AudioTimeAxisView& tv)
canvas_rect->property_y1() = 0.0;
canvas_rect->property_x2() = 1000000.0;
canvas_rect->property_y2() = (double) tv.height;
canvas_rect->property_outline_color_rgba() = color_map[cAudioTrackOutline];
canvas_rect->property_outline_what() = (guint32) (0x1|0x2|0x8); // outline ends and bottom
canvas_rect->property_fill_color_rgba() = stream_base_color;
canvas_rect->signal_event().connect (bind (mem_fun (_trackview.editor, &PublicEditor::canvas_stream_view_event), canvas_rect, &_trackview));
_samples_per_unit = _trackview.editor.get_current_zoom();
_amplitude_above_axis = 1.0;
if (_trackview.is_audio_track()) {
_trackview.audio_track()->diskstream_changed.connect (mem_fun (*this, &StreamView::diskstream_changed));
if (_trackview.is_track()) {
_trackview.track()->DiskstreamChanged.connect (mem_fun (*this, &StreamView::diskstream_changed));
_trackview.session().TransportStateChange.connect (mem_fun (*this, &StreamView::transport_changed));
_trackview.get_diskstream()->record_enable_changed.connect (mem_fun (*this, &StreamView::rec_enable_changed));
_trackview.get_diskstream()->RecordEnableChanged.connect (mem_fun (*this, &StreamView::rec_enable_changed));
_trackview.session().RecordStateChanged.connect (mem_fun (*this, &StreamView::sess_rec_enable_changed));
}
rec_updating = false;
rec_active = false;
use_rec_regions = tv.editor.show_waveforms_recording ();
last_rec_peak_frame = 0;
ColorChanged.connect (mem_fun (*this, &StreamView::color_handler));
}
@@ -90,7 +90,7 @@ StreamView::~StreamView ()
void
StreamView::attach ()
{
if (_trackview.is_audio_track()) {
if (_trackview.is_track()) {
display_diskstream (_trackview.get_diskstream());
}
}
@@ -115,13 +115,13 @@ StreamView::set_height (gdouble h)
canvas_rect->property_y2() = h;
for (AudioRegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) {
for (RegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) {
(*i)->set_height (h);
}
for (CrossfadeViewList::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
/*for (CrossfadeViewList::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
(*i)->set_height (h);
}
}*/
for (vector<RecBoxInfo>::iterator i = rec_rects.begin(); i != rec_rects.end(); ++i) {
RecBoxInfo &recbox = (*i);
@@ -134,7 +134,7 @@ StreamView::set_height (gdouble h)
int
StreamView::set_samples_per_unit (gdouble spp)
{
AudioRegionViewList::iterator i;
RegionViewList::iterator i;
if (spp < 1.0) {
return -1;
@@ -146,10 +146,6 @@ StreamView::set_samples_per_unit (gdouble spp)
(*i)->set_samples_per_unit (spp);
}
for (CrossfadeViewList::iterator xi = crossfade_views.begin(); xi != crossfade_views.end(); ++xi) {
(*xi)->set_samples_per_unit (spp);
}
for (vector<RecBoxInfo>::iterator xi = rec_rects.begin(); xi != rec_rects.end(); ++xi) {
RecBoxInfo &recbox = (*xi);
@@ -163,113 +159,24 @@ StreamView::set_samples_per_unit (gdouble spp)
return 0;
}
int
StreamView::set_amplitude_above_axis (gdouble app)
{
AudioRegionViewList::iterator i;
if (app < 1.0) {
return -1;
}
_amplitude_above_axis = app;
for (i = region_views.begin(); i != region_views.end(); ++i) {
(*i)->set_amplitude_above_axis (app);
}
return 0;
}
void
StreamView::add_region_view (Region *r)
{
add_region_view_internal (r, true);
}
void
StreamView::add_region_view_internal (Region *r, bool wait_for_waves)
{
ENSURE_GUI_THREAD (bind (mem_fun (*this, &StreamView::add_region_view), r));
AudioRegion* region = dynamic_cast<AudioRegion*> (r);
if (region == 0) {
return;
}
AudioRegionView *region_view;
list<AudioRegionView *>::iterator i;
for (i = region_views.begin(); i != region_views.end(); ++i) {
if (&(*i)->region == region) {
/* great. we already have a AudioRegionView for this Region. use it again.
*/
(*i)->set_valid (true);
return;
}
}
switch (_trackview.audio_track()->mode()) {
case Normal:
region_view = new AudioRegionView (canvas_group, _trackview, *region,
_samples_per_unit, region_color);
break;
case Destructive:
region_view = new TapeAudioRegionView (canvas_group, _trackview, *region,
_samples_per_unit, region_color);
break;
}
region_view->init (_amplitude_above_axis, region_color, wait_for_waves);
region_views.push_front (region_view);
/* follow global waveform setting */
region_view->set_waveform_visible(_trackview.editor.show_waveforms());
/* catch regionview going away */
region->GoingAway.connect (mem_fun (*this, &StreamView::remove_region_view));
AudioRegionViewAdded (region_view);
}
void
StreamView::remove_region_view (Region *r)
{
ENSURE_GUI_THREAD (bind (mem_fun (*this, &StreamView::remove_region_view), r));
AudioRegion* ar = dynamic_cast<AudioRegion*> (r);
if (ar == 0) {
return;
}
for (list<AudioRegionView *>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
if (&((*i)->region) == ar) {
for (list<RegionView *>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
if (&((*i)->region()) == r) {
delete *i;
region_views.erase (i);
break;
}
}
for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end();) {
list<CrossfadeView*>::iterator tmp;
tmp = i;
++tmp;
if ((*i)->crossfade.involves (*ar)) {
delete *i;
crossfade_views.erase (i);
}
i = tmp;
}
}
void
@@ -282,14 +189,8 @@ StreamView::remove_rec_region (Region *r)
/*NOTREACHED*/
}
AudioRegion* ar = dynamic_cast<AudioRegion*> (r);
if (ar == 0) {
return;
}
for (list<AudioRegion *>::iterator i = rec_regions.begin(); i != rec_regions.end(); ++i) {
if (*i == ar) {
for (list<Region *>::iterator i = rec_regions.begin(); i != rec_regions.end(); ++i) {
if (*i == r) {
rec_regions.erase (i);
break;
}
@@ -299,21 +200,15 @@ StreamView::remove_rec_region (Region *r)
void
StreamView::undisplay_diskstream ()
{
for (AudioRegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) {
delete *i;
}
for (CrossfadeViewList::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
for (RegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) {
delete *i;
}
region_views.clear();
crossfade_views.clear ();
}
void
StreamView::display_diskstream (AudioDiskstream *ds)
StreamView::display_diskstream (Diskstream *ds)
{
playlist_change_connection.disconnect();
playlist_changed (ds);
@@ -325,21 +220,13 @@ StreamView::playlist_modified ()
{
ENSURE_GUI_THREAD (mem_fun (*this, &StreamView::playlist_modified));
/* if the playlist is modified, make sure xfades are on top and all the regionviews are stacked
correctly.
*/
for (AudioRegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) {
for (RegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) {
region_layered (*i);
}
for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
(*i)->get_canvas_group()->raise_to_top();
}
}
void
StreamView::playlist_changed (AudioDiskstream *ds)
StreamView::playlist_changed (Diskstream *ds)
{
ENSURE_GUI_THREAD (bind (mem_fun (*this, &StreamView::playlist_changed), ds));
@@ -362,69 +249,6 @@ StreamView::playlist_changed (AudioDiskstream *ds)
playlist_connections.push_back (ds->playlist()->RegionRemoved.connect (mem_fun (*this, &StreamView::remove_region_view)));
playlist_connections.push_back (ds->playlist()->StateChanged.connect (mem_fun (*this, &StreamView::playlist_state_changed)));
playlist_connections.push_back (ds->playlist()->Modified.connect (mem_fun (*this, &StreamView::playlist_modified)));
playlist_connections.push_back (ds->playlist()->NewCrossfade.connect (mem_fun (*this, &StreamView::add_crossfade)));
}
void
StreamView::add_crossfade (Crossfade *crossfade)
{
AudioRegionView* lview = 0;
AudioRegionView* rview = 0;
ENSURE_GUI_THREAD (bind (mem_fun (*this, &StreamView::add_crossfade), crossfade));
/* first see if we already have a CrossfadeView for this Crossfade */
for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
if (&(*i)->crossfade == crossfade) {
if (!crossfades_visible) {
(*i)->hide();
} else {
(*i)->show ();
}
(*i)->set_valid (true);
return;
}
}
/* create a new one */
for (list<AudioRegionView *>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
if (!lview && &((*i)->region) == &crossfade->out()) {
lview = *i;
}
if (!rview && &((*i)->region) == &crossfade->in()) {
rview = *i;
}
}
CrossfadeView *cv = new CrossfadeView (_trackview.canvas_display,
_trackview,
*crossfade,
_samples_per_unit,
region_color,
*lview, *rview);
crossfade->Invalidated.connect (mem_fun (*this, &StreamView::remove_crossfade));
crossfade_views.push_back (cv);
if (!crossfades_visible) {
cv->hide ();
}
}
void
StreamView::remove_crossfade (Crossfade *xfade)
{
ENSURE_GUI_THREAD (bind (mem_fun (*this, &StreamView::remove_crossfade), xfade));
for (list<CrossfadeView*>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
if (&(*i)->crossfade == xfade) {
delete *i;
crossfade_views.erase (i);
break;
}
}
}
void
@@ -436,64 +260,12 @@ StreamView::playlist_state_changed (Change ignored)
}
void
StreamView::redisplay_diskstream ()
StreamView::diskstream_changed ()
{
list<AudioRegionView *>::iterator i, tmp;
list<CrossfadeView*>::iterator xi, tmpx;
Track *t;
for (i = region_views.begin(); i != region_views.end(); ++i) {
(*i)->set_valid (false);
}
for (xi = crossfade_views.begin(); xi != crossfade_views.end(); ++xi) {
(*xi)->set_valid (false);
if ((*xi)->visible()) {
(*xi)->show ();
}
}
if (_trackview.is_audio_track()) {
_trackview.get_diskstream()->playlist()->foreach_region (this, &StreamView::add_region_view);
_trackview.get_diskstream()->playlist()->foreach_crossfade (this, &StreamView::add_crossfade);
}
for (i = region_views.begin(); i != region_views.end(); ) {
tmp = i;
tmp++;
if (!(*i)->is_valid()) {
delete *i;
region_views.erase (i);
}
i = tmp;
}
for (xi = crossfade_views.begin(); xi != crossfade_views.end();) {
tmpx = xi;
tmpx++;
if (!(*xi)->valid()) {
delete *xi;
crossfade_views.erase (xi);
}
xi = tmpx;
}
/* now fix layering */
playlist_modified ();
}
void
StreamView::diskstream_changed (void *src_ignored)
{
AudioTrack *at;
if ((at = _trackview.audio_track()) != 0) {
AudioDiskstream& ds = at->disk_stream();
if ((t = _trackview.track()) != 0) {
Diskstream& ds = t->diskstream();
/* XXX grrr: when will SigC++ allow me to bind references? */
Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun (*this, &StreamView::display_diskstream), &ds));
} else {
@@ -505,7 +277,7 @@ void
StreamView::apply_color (Gdk::Color& color, ColorTarget target)
{
list<AudioRegionView *>::iterator i;
list<RegionView *>::iterator i;
switch (target) {
case RegionColor:
@@ -525,64 +297,7 @@ StreamView::apply_color (Gdk::Color& color, ColorTarget target)
}
void
StreamView::set_show_waveforms (bool yn)
{
for (list<AudioRegionView *>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
(*i)->set_waveform_visible (yn);
}
}
void
StreamView::set_selected_regionviews (AudioRegionSelection& regions)
{
bool selected;
// cerr << _trackview.name() << " (selected = " << regions.size() << ")" << endl;
for (list<AudioRegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
selected = false;
for (AudioRegionSelection::iterator ii = regions.begin(); ii != regions.end(); ++ii) {
if (*i == *ii) {
selected = true;
}
}
// cerr << "\tregion " << (*i)->region.name() << " selected = " << selected << endl;
(*i)->set_selected (selected);
}
}
void
StreamView::get_selectables (jack_nframes_t start, jack_nframes_t end, list<Selectable*>& results)
{
for (list<AudioRegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
if ((*i)->region.coverage(start, end) != OverlapNone) {
results.push_back (*i);
}
}
}
void
StreamView::get_inverted_selectables (Selection& sel, list<Selectable*>& results)
{
for (list<AudioRegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
if (!sel.audio_regions.contains (*i)) {
results.push_back (*i);
}
}
}
void
StreamView::set_waveform_shape (WaveformShape shape)
{
for (AudioRegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) {
(*i)->set_waveform_shape (shape);
}
}
void
StreamView::region_layered (AudioRegionView* rv)
StreamView::region_layered (RegionView* rv)
{
rv->get_canvas_group()->lower_to_bottom();
@@ -590,11 +305,11 @@ StreamView::region_layered (AudioRegionView* rv)
get events - the parent group does instead ...
*/
rv->get_canvas_group()->raise (rv->region.layer() + 1);
rv->get_canvas_group()->raise (rv->region().layer() + 1);
}
void
StreamView::rec_enable_changed (void *src)
StreamView::rec_enable_changed ()
{
Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &StreamView::setup_rec_box));
}
@@ -611,161 +326,6 @@ StreamView::transport_changed()
Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &StreamView::setup_rec_box));
}
void
StreamView::setup_rec_box ()
{
// cerr << _trackview.name() << " streamview SRB\n";
if (_trackview.session().transport_rolling()) {
// cerr << "\trolling\n";
if (!rec_active &&
_trackview.session().record_status() == Session::Recording &&
_trackview.get_diskstream()->record_enabled()) {
if (_trackview.audio_track()->mode() == Normal && use_rec_regions && rec_regions.size() == rec_rects.size()) {
/* add a new region, but don't bother if they set use_rec_regions mid-record */
AudioRegion::SourceList sources;
for (list<sigc::connection>::iterator prc = peak_ready_connections.begin(); prc != peak_ready_connections.end(); ++prc) {
(*prc).disconnect();
}
peak_ready_connections.clear();
for (uint32_t n=0; n < _trackview.get_diskstream()->n_channels(); ++n) {
AudioSource *src = (AudioSource *) _trackview.get_diskstream()->write_source (n);
if (src) {
sources.push_back (src);
peak_ready_connections.push_back (src->PeakRangeReady.connect (bind (mem_fun (*this, &StreamView::rec_peak_range_ready), src)));
}
}
// handle multi
jack_nframes_t start = 0;
if (rec_regions.size() > 0) {
start = rec_regions.back()->start() + _trackview.get_diskstream()->get_captured_frames(rec_regions.size()-1);
}
AudioRegion * region = new AudioRegion(sources, start, 1 , "", 0, (Region::Flag)(Region::DefaultFlags | Region::DoNotSaveState), false);
region->set_position (_trackview.session().transport_frame(), this);
rec_regions.push_back (region);
/* catch it if it goes away */
region->GoingAway.connect (mem_fun (*this, &StreamView::remove_rec_region));
/* we add the region later */
}
/* start a new rec box */
AudioTrack* at;
at = _trackview.audio_track(); /* we know what it is already */
AudioDiskstream& ds = at->disk_stream();
jack_nframes_t frame_pos = ds.current_capture_start ();
gdouble xstart = _trackview.editor.frame_to_pixel (frame_pos);
gdouble xend;
uint32_t fill_color;
switch (_trackview.audio_track()->mode()) {
case Normal:
xend = xstart;
fill_color = color_map[cRecordingRectFill];
break;
case Destructive:
xend = xstart + 2;
fill_color = color_map[cRecordingRectFill];
/* make the recording rect translucent to allow
the user to see the peak data coming in, etc.
*/
fill_color = UINT_RGBA_CHANGE_A (fill_color, 120);
break;
}
ArdourCanvas::SimpleRect * rec_rect = new Gnome::Canvas::SimpleRect (*canvas_group);
rec_rect->property_x1() = xstart;
rec_rect->property_y1() = 1.0;
rec_rect->property_x2() = xend;
rec_rect->property_y2() = (double) _trackview.height - 1;
rec_rect->property_outline_color_rgba() = color_map[cRecordingRectOutline];
rec_rect->property_fill_color_rgba() = fill_color;
RecBoxInfo recbox;
recbox.rectangle = rec_rect;
recbox.start = _trackview.session().transport_frame();
recbox.length = 0;
rec_rects.push_back (recbox);
screen_update_connection.disconnect();
screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (mem_fun (*this, &StreamView::update_rec_box));
rec_updating = true;
rec_active = true;
} else if (rec_active &&
(_trackview.session().record_status() != Session::Recording ||
!_trackview.get_diskstream()->record_enabled())) {
screen_update_connection.disconnect();
rec_active = false;
rec_updating = false;
}
} else {
// cerr << "\tNOT rolling, rec_rects = " << rec_rects.size() << " rec_regions = " << rec_regions.size() << endl;
if (!rec_rects.empty() || !rec_regions.empty()) {
/* disconnect rapid update */
screen_update_connection.disconnect();
for (list<sigc::connection>::iterator prc = peak_ready_connections.begin(); prc != peak_ready_connections.end(); ++prc) {
(*prc).disconnect();
}
peak_ready_connections.clear();
rec_updating = false;
rec_active = false;
last_rec_peak_frame = 0;
/* remove temp regions */
for (list<AudioRegion*>::iterator iter=rec_regions.begin(); iter != rec_regions.end(); )
{
list<AudioRegion*>::iterator tmp;
tmp = iter;
++tmp;
/* this will trigger the remove_region_view */
delete *iter;
iter = tmp;
}
rec_regions.clear();
// cerr << "\tclear " << rec_rects.size() << " rec rects\n";
/* transport stopped, clear boxes */
for (vector<RecBoxInfo>::iterator iter=rec_rects.begin(); iter != rec_rects.end(); ++iter) {
RecBoxInfo &rect = (*iter);
delete rect.rectangle;
}
rec_rects.clear();
}
}
}
void
StreamView::update_rec_box ()
{
@@ -776,7 +336,7 @@ StreamView::update_rec_box ()
double xstart;
double xend;
switch (_trackview.audio_track()->mode()) {
switch (_trackview.track()->mode()) {
case Normal:
rect.length = at - rect.start;
xstart = _trackview.editor.frame_to_pixel (rect.start);
@@ -795,12 +355,12 @@ StreamView::update_rec_box ()
}
}
AudioRegionView*
StreamView::find_view (const AudioRegion& region)
RegionView*
StreamView::find_view (const Region& region)
{
for (list<AudioRegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
for (list<RegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
if (&(*i)->region == &region) {
if (&(*i)->region() == &region) {
return *i;
}
}
@@ -808,172 +368,51 @@ StreamView::find_view (const AudioRegion& region)
}
void
StreamView::foreach_regionview (sigc::slot<void,AudioRegionView*> slot)
StreamView::foreach_regionview (sigc::slot<void,RegionView*> slot)
{
for (list<AudioRegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
for (list<RegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
slot (*i);
}
}
void
StreamView::foreach_crossfadeview (void (CrossfadeView::*pmf)(void))
StreamView::set_selected_regionviews (RegionSelection& regions)
{
for (list<CrossfadeView*>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
((*i)->*pmf) ();
}
}
bool selected;
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;
// 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;
}
AudioRegion * region = (*iter);
jack_nframes_t origlen = region->length();
}
// cerr << "\tregion " << (*i)->region().name() << " selected = " << selected << endl;
(*i)->set_selected (selected);
}
}
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
StreamView::get_selectables (jack_nframes_t start, jack_nframes_t end, list<Selectable*>& results)
{
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::show_all_xfades ()
StreamView::get_inverted_selectables (Selection& sel, list<Selectable*>& results)
{
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)
{
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 (!sel.regions.contains (*i)) {
results.push_back (*i);
}
}
}
void
StreamView::reveal_xfades_involving (AudioRegionView& rv)
{
for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
if ((*i)->crossfade.involves (rv.region) && (*i)->visible()) {
(*i)->show ();
}
}
}
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;
}
}

View File

@@ -1,5 +1,5 @@
/*
Copyright (C) 2001 Paul Davis
Copyright (C) 2001, 2006 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -14,8 +14,6 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id$
*/
#ifndef __ardour_streamview_h__
@@ -37,141 +35,117 @@ namespace Gdk {
namespace ARDOUR {
class Route;
class AudioDiskstream;
class Diskstream;
class Crossfade;
class PeakData;
class AudioRegion;
class Region;
class Source;
}
struct RecBoxInfo {
ArdourCanvas::SimpleRect* rectangle;
jack_nframes_t start;
jack_nframes_t length;
ArdourCanvas::SimpleRect* rectangle;
jack_nframes_t start;
jack_nframes_t length;
};
class PublicEditor;
class Selectable;
class AudioTimeAxisView;
class AudioRegionView;
class AudioRegionSelection;
class RouteTimeAxisView;
class RegionView;
class RegionSelection;
class CrossfadeView;
class Selection;
class StreamView : public sigc::trackable
{
public:
StreamView (AudioTimeAxisView&);
~StreamView ();
public:
virtual ~StreamView ();
void set_waveform_shape (WaveformShape);
RouteTimeAxisView& trackview() { return _trackview; }
AudioTimeAxisView& trackview() { return _trackview; }
void attach ();
void set_zoom_all();
int set_height (gdouble);
int set_position (gdouble x, gdouble y);
virtual int set_height (gdouble);
int set_samples_per_unit (gdouble spp);
gdouble get_samples_per_unit () { return _samples_per_unit; }
int set_amplitude_above_axis (gdouble app);
gdouble get_amplitude_above_axis () { return _amplitude_above_axis; }
void set_show_waveforms (bool yn);
void set_show_waveforms_recording (bool yn) { use_rec_regions = yn; }
virtual int set_samples_per_unit (gdouble spp);
gdouble get_samples_per_unit () { return _samples_per_unit; }
ArdourCanvas::Item* canvas_item() { return canvas_group; }
sigc::signal<void,AudioRegionView*> AudioRegionViewAdded;
enum ColorTarget {
RegionColor,
StreamBaseColor
};
void apply_color (Gdk::Color&, ColorTarget t);
void set_selected_regionviews (AudioRegionSelection&);
Gdk::Color get_region_color () const { return region_color; }
void apply_color (Gdk::Color&, ColorTarget t);
RegionView* find_view (const ARDOUR::Region&);
void foreach_regionview (sigc::slot<void,RegionView*> slot);
void set_selected_regionviews (RegionSelection&);
void get_selectables (jack_nframes_t start, jack_nframes_t end, list<Selectable* >&);
void get_inverted_selectables (Selection&, list<Selectable* >& results);
Gdk::Color get_region_color () const { return region_color; }
void foreach_regionview (sigc::slot<void,AudioRegionView*> slot);
void foreach_crossfadeview (void (CrossfadeView::*pmf)(void));
void attach ();
void add_region_view (ARDOUR::Region*);
void region_layered (RegionView*);
void region_layered (AudioRegionView*);
sigc::signal<void,RegionView*> RegionViewAdded;
protected:
StreamView (RouteTimeAxisView&);
AudioRegionView* find_view (const ARDOUR::AudioRegion&);
//private: (FIXME?)
void show_all_xfades ();
void hide_all_xfades ();
void hide_xfades_involving (AudioRegionView&);
void reveal_xfades_involving (AudioRegionView&);
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;
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*);
private:
AudioTimeAxisView& _trackview;
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;
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;
sigc::connection screen_update_connection;
vector<RecBoxInfo> rec_rects;
list<ARDOUR::Region* > rec_regions;
bool rec_updating;
bool rec_active;
bool use_rec_regions;
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? */
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__ */

View File

@@ -30,7 +30,7 @@
#include <ardour/audiosource.h>
#include <ardour/audio_diskstream.h>
#include "taperegionview.h"
#include "tape_region_view.h"
#include "audio_time_axis.h"
#include "gui_thread.h"
@@ -42,12 +42,14 @@ using namespace PBD;
using namespace Editing;
using namespace ArdourCanvas;
const TimeAxisViewItem::Visibility TapeAudioRegionView::default_tape_visibility = TimeAxisViewItem::Visibility (TimeAxisViewItem::ShowNameHighlight|
TimeAxisViewItem::ShowFrame|
TimeAxisViewItem::HideFrameRight|
TimeAxisViewItem::FullWidthNameHighlight);
const TimeAxisViewItem::Visibility TapeAudioRegionView::default_tape_visibility
= TimeAxisViewItem::Visibility (
TimeAxisViewItem::ShowNameHighlight |
TimeAxisViewItem::ShowFrame |
TimeAxisViewItem::HideFrameRight |
TimeAxisViewItem::FullWidthNameHighlight);
TapeAudioRegionView::TapeAudioRegionView (ArdourCanvas::Group *parent, AudioTimeAxisView &tv,
TapeAudioRegionView::TapeAudioRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &tv,
AudioRegion& r,
double spu,
Gdk::Color& basic_color)
@@ -59,58 +61,14 @@ TapeAudioRegionView::TapeAudioRegionView (ArdourCanvas::Group *parent, AudioTime
}
void
TapeAudioRegionView::init (double amplitude_above_axis, Gdk::Color& basic_color, bool wfw)
TapeAudioRegionView::init (Gdk::Color& basic_color, bool wfw)
{
XMLNode *node;
editor = 0;
valid = true;
in_destructor = false;
_amplitude_above_axis = amplitude_above_axis;
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));
AudioRegionView::init(basic_color, wfw);
/* every time the wave data changes and peaks are ready, redraw */
for (uint32_t n = 0; n < region.n_channels(); ++n) {
region.source(n).PeaksReady.connect (bind (mem_fun(*this, &TapeAudioRegionView::update), n));
for (uint32_t n = 0; n < audio_region().n_channels(); ++n) {
audio_region().source(n).PeaksReady.connect (bind (mem_fun(*this, &TapeAudioRegionView::update), n));
}
}
@@ -132,7 +90,7 @@ TapeAudioRegionView::update (uint32_t n)
/* this triggers a cache invalidation and redraw in the waveview */
waves[n]->property_data_src() = &region;
waves[n]->property_data_src() = &_region;
}
void

View File

@@ -23,20 +23,20 @@
#include <vector>
#include "regionview.h"
#include "audio_region_view.h"
class TapeAudioRegionView : public AudioRegionView
{
public:
TapeAudioRegionView (ArdourCanvas::Group *,
AudioTimeAxisView&,
RouteTimeAxisView&,
ARDOUR::AudioRegion&,
double initial_samples_per_unit,
Gdk::Color& base_color);
~TapeAudioRegionView ();
protected:
void init (double amplitude_above_axis, Gdk::Color& base_color, bool wait_for_waves);
void init (Gdk::Color& base_color, bool wait_for_waves);
void set_frame_color ();
void update (uint32_t n);

View File

@@ -54,7 +54,7 @@ namespace Gtk {
}
class PublicEditor;
class AudioRegionSelection;
class RegionSelection;
class TimeSelection;
class PointSelection;
class TimeAxisViewItem;
@@ -183,7 +183,7 @@ class TimeAxisView : public virtual AxisView
virtual bool cut_copy_clear (Selection&, Editing::CutCopyOp) { return false; }
virtual bool paste (jack_nframes_t, float times, Selection&, size_t nth) { return false; }
virtual void set_selected_regionviews (AudioRegionSelection&) {}
virtual void set_selected_regionviews (RegionSelection&) {}
virtual void set_selected_points (PointSelection&) {}
virtual ARDOUR::Region* find_next_region (jack_nframes_t pos, ARDOUR::RegionPoint, int32_t dir) {

View File

@@ -255,7 +255,7 @@ VisualTimeAxis::set_time_axis_color(Gdk::Color c)
}
void
VisualTimeAxis::set_selected_regionviews (AudioRegionSelection& regions)
VisualTimeAxis::set_selected_regionviews (RegionSelection& regions)
{
// Not handled by purely visual TimeAxis
}

View File

@@ -42,7 +42,7 @@ class ImageFrameView;
class ImageFrameTimeAxisView;
class MarkersTimeAxisView;
class TimeSelection;
class AudioRegionSelection;
class RegionSelection;
class MarkerTimeAxis;
class TimeAxisViewStrip;
@@ -105,7 +105,7 @@ class VisualTimeAxis : public TimeAxisView
/**
* Not implemented
*/
virtual void set_selected_regionviews(AudioRegionSelection&) ;
virtual void set_selected_regionviews(RegionSelection&) ;
//---------------------------------------------------------------------------------//

View File

@@ -27,9 +27,11 @@ ardour.Append(POTFILE = domain + '.pot')
ardour.Append(CPPPATH = '#libs/surfaces/control_protocol')
ardour_files=Split("""
diskstream.cc
audio_diskstream.cc
audio_library.cc
audio_playlist.cc
track.cc
audio_track.cc
audioengine.cc
audiofilesource.cc

View File

@@ -1,5 +1,5 @@
/*
Copyright (C) 2000 Paul Davis
Copyright (C) 2000-2006 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -14,12 +14,10 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: diskstream.h 579 2006-06-12 19:56:37Z essej $
*/
#ifndef __ardour_diskstream_h__
#define __ardour_diskstream_h__
#ifndef __ardour_audio_diskstream_h__
#define __ardour_audio_diskstream_h__
#include <sigc++/signal.h>
@@ -42,6 +40,8 @@
#include <ardour/route.h>
#include <ardour/port.h>
#include <ardour/utils.h>
#include <ardour/diskstream.h>
#include <ardour/audioplaylist.h>
struct tm;
@@ -54,53 +54,20 @@ class AudioPlaylist;
class AudioFileSource;
class IO;
class AudioDiskstream : public Stateful, public sigc::trackable
class AudioDiskstream : public Diskstream
{
public:
enum Flag {
Recordable = 0x1,
Hidden = 0x2,
Destructive = 0x4
};
AudioDiskstream (Session &, const string& name, Flag f = Recordable);
AudioDiskstream (Session &, const string& name, Diskstream::Flag f = Recordable);
AudioDiskstream (Session &, const XMLNode&);
string name() const { return _name; }
ARDOUR::IO* io() const { return _io; }
void set_io (ARDOUR::IO& io);
const PBD::ID& id() const { return _id; }
// FIXME
AudioDiskstream& ref() { _refcnt++; return *this; }
void unref() { if (_refcnt) _refcnt--; if (_refcnt == 0) delete this; }
uint32_t refcnt() const { return _refcnt; }
float playback_buffer_load() const;
float capture_buffer_load() const;
void set_flag (Flag f) {
_flags |= f;
}
void unset_flag (Flag f) {
_flags &= ~f;
}
AlignStyle alignment_style() const { return _alignment_style; }
void set_align_style (AlignStyle);
void set_persistent_align_style (AlignStyle);
bool hidden() const { return _flags & Hidden; }
bool recordable() const { return _flags & Recordable; }
bool destructive() const { return _flags & Destructive; }
void set_destructive (bool yn);
jack_nframes_t roll_delay() const { return _roll_delay; }
void set_roll_delay (jack_nframes_t);
int set_name (string str, void* src);
string input_source (uint32_t n=0) const {
if (n < channels.size()) {
return channels[n].source ? channels[n].source->name() : "";
@@ -113,14 +80,7 @@ class AudioDiskstream : public Stateful, public sigc::trackable
if (n < channels.size()) return channels[n].source; return 0;
}
void set_record_enabled (bool yn, void *src);
bool record_enabled() const { return g_atomic_int_get (&_record_enabled); }
void punch_in ();
void punch_out ();
bool reversed() const { return _actual_speed < 0.0f; }
double speed() const { return _visible_speed; }
void set_speed (double);
void set_record_enabled (bool yn);
float peak_power(uint32_t n=0) {
float x = channels[n].peak_power;
@@ -131,14 +91,13 @@ class AudioDiskstream : public Stateful, public sigc::trackable
return minus_infinity();
}
}
AudioPlaylist* audio_playlist () { return dynamic_cast<AudioPlaylist*>(_playlist); }
int use_playlist (AudioPlaylist *);
int use_playlist (Playlist *);
int use_new_playlist ();
int use_copy_playlist ();
void start_scrub (jack_nframes_t where);
void end_scrub ();
Sample *playback_buffer (uint32_t n=0) {
if (n < channels.size())
return channels[n].current_playback_buffer;
@@ -151,51 +110,23 @@ class AudioDiskstream : public Stateful, public sigc::trackable
return 0;
}
AudioPlaylist *playlist () { return _playlist; }
AudioFileSource *write_source (uint32_t n=0) {
if (n < channels.size())
return channels[n].write_source;
return 0;
}
jack_nframes_t current_capture_start() const { return capture_start_frame; }
jack_nframes_t current_capture_end() const { return capture_start_frame + capture_captured; }
jack_nframes_t get_capture_start_frame (uint32_t n=0);
jack_nframes_t get_captured_frames (uint32_t n=0);
uint32_t n_channels() { return _n_channels; }
int add_channel ();
int remove_channel ();
static void set_disk_io_chunk_frames (uint32_t n) {
disk_io_chunk_frames = n;
}
static jack_nframes_t disk_io_frames() { return disk_io_chunk_frames; }
sigc::signal<void,void*> record_enable_changed;
sigc::signal<void> speed_changed;
sigc::signal<void,void*> reverse_changed;
sigc::signal<void> PlaylistChanged;
sigc::signal<void> AlignmentStyleChanged;
static sigc::signal<void> DiskOverrun;
static sigc::signal<void> DiskUnderrun;
static sigc::signal<void,AudioDiskstream*> AudioDiskstreamCreated; // XXX use a ref with sigc2
static sigc::signal<void,list<AudioFileSource*>*> DeleteSources;
/* stateful */
XMLNode& get_state(void);
int set_state(const XMLNode& node);
int set_state(const XMLNode& node);
void monitor_input (bool);
jack_nframes_t capture_offset() const { return _capture_offset; }
void set_capture_offset ();
static void swap_by_ptr (Sample *first, Sample *last) {
while (first < last) {
Sample tmp = *first;
@@ -212,19 +143,7 @@ class AudioDiskstream : public Stateful, public sigc::trackable
}
}
bool slaved() const { return _slaved; }
void set_slaved(bool yn) { _slaved = yn; }
int set_loop (Location *loc);
sigc::signal<void,Location *> LoopSet;
std::list<Region*>& last_capture_regions () {
return _last_capture_regions;
}
void handle_input_change (IOChange, void *src);
const PBD::ID& id() const { return _id; }
std::list<Region*>& last_capture_regions () { return _last_capture_regions; }
XMLNode* deprecated_io_node;
@@ -236,9 +155,8 @@ class AudioDiskstream : public Stateful, public sigc::trackable
while they are called.
*/
void set_pending_overwrite (bool);
void set_pending_overwrite(bool);
int overwrite_existing_buffers ();
void reverse_scrub_buffer (bool to_forward);
void set_block_size (jack_nframes_t);
int internal_playback_seek (jack_nframes_t distance);
int can_internal_playback_seek (jack_nframes_t distance);
@@ -246,9 +164,6 @@ class AudioDiskstream : public Stateful, public sigc::trackable
void reset_write_sources (bool, bool force = false);
void non_realtime_input_change ();
uint32_t read_data_count() const { return _read_data_count; }
uint32_t write_data_count() const { return _write_data_count; }
protected:
friend class Auditioner;
int seek (jack_nframes_t which_sample, bool complete_refill = false);
@@ -256,38 +171,23 @@ class AudioDiskstream : public Stateful, public sigc::trackable
protected:
friend class AudioTrack;
void prepare ();
int process (jack_nframes_t transport_frame, jack_nframes_t nframes, jack_nframes_t offset, bool can_record, bool rec_monitors_input);
bool commit (jack_nframes_t nframes);
void recover (); /* called if commit will not be called, but process was */
private:
/* use unref() to destroy a diskstream */
~AudioDiskstream();
enum TransitionType {
CaptureStart = 0,
CaptureEnd
};
struct CaptureTransition {
TransitionType type;
// the start or end file frame pos
jack_nframes_t capture_val;
};
struct ChannelInfo {
Sample *playback_wrap_buffer;
Sample *capture_wrap_buffer;
Sample *speed_buffer;
float peak_power;
float peak_power;
AudioFileSource *fades_source;
AudioFileSource *fades_source;
AudioFileSource *write_source;
Port *source;
@@ -309,129 +209,30 @@ class AudioDiskstream : public Stateful, public sigc::trackable
jack_nframes_t curr_capture_cnt;
};
typedef vector<ChannelInfo> ChannelList;
string _name;
ARDOUR::Session& _session;
ARDOUR::IO* _io;
ChannelList channels;
uint32_t _n_channels;
PBD::ID _id;
mutable gint _record_enabled;
AudioPlaylist* _playlist;
double _visible_speed;
double _actual_speed;
/* items needed for speed change logic */
bool _buffer_reallocation_required;
bool _seek_required;
/* 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); }
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;
int do_refill_with_alloc();
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;
/* XXX fix this redundancy ... */
void playlist_changed (Change);
void playlist_modified ();
void playlist_deleted (Playlist*);
void session_controls_changed (Session::ControlType);
int read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, char * workbuf,
jack_nframes_t& start, jack_nframes_t cnt,
ChannelInfo& channel_info, int channel, bool reversed);
void finish_capture (bool rec_monitors_input);
void clean_up_capture (struct tm&, time_t, bool abort);
void transport_stopped (struct tm&, time_t, bool abort);
struct CaptureInfo {
uint32_t start;
uint32_t frames;
};
vector<CaptureInfo*> capture_info;
Glib::Mutex capture_info_lock;
void init (Flag);
void init (Diskstream::Flag);
void init_channel (ChannelInfo &chan);
void destroy_channel (ChannelInfo &chan);
static jack_nframes_t disk_io_chunk_frames;
int use_new_write_source (uint32_t n=0);
int use_new_fade_source (uint32_t n=0);
int find_and_use_playlist (const string&);
void allocate_temporary_buffers ();
unsigned char _flags;
int create_input_port ();
int connect_input_port ();
int seek_unlocked (jack_nframes_t which_sample);
int ports_created ();
bool realtime_set_speed (double, bool global_change);
void non_realtime_set_speed ();
std::list<Region*> _last_capture_regions;
std::vector<AudioFileSource*> capturing_sources;
int use_pending_capture_data (XMLNode& node);
void get_input_sources ();
@@ -439,10 +240,29 @@ class AudioDiskstream : public Stateful, public sigc::trackable
void set_align_style_from_io();
void setup_destructive_playlist ();
void use_destructive_playlist ();
void engage_record_enable (void* src);
void disengage_record_enable (void* src);
void engage_record_enable ();
void disengage_record_enable ();
// Working buffers for do_refill (butler thread)
static void allocate_working_buffers();
static void free_working_buffers();
static size_t _working_buffers_size;
static Sample* _mixdown_buffer;
static gain_t* _gain_buffer;
static char* _conversion_buffer;
// Uh, /really/ private? (death to friend classes)
int _do_refill (Sample *mixdown_buffer, float *gain_buffer, char *workbuf);
std::vector<AudioFileSource*> capturing_sources;
typedef vector<ChannelInfo> ChannelList;
ChannelList channels;
};
} // namespace ARDOUR
#endif /* __ardour_diskstream_h__ */
#endif /* __ardour_audio_diskstream_h__ */

View File

@@ -21,7 +21,7 @@
#ifndef __ardour_audio_track_h__
#define __ardour_audio_track_h__
#include <ardour/route.h>
#include <ardour/track.h>
namespace ARDOUR {
@@ -30,76 +30,38 @@ class AudioDiskstream;
class AudioPlaylist;
class RouteGroup;
class AudioTrack : public Route
class AudioTrack : public Track
{
public:
AudioTrack (Session&, string name, Route::Flag f = Route::Flag (0), TrackMode m = Normal);
AudioTrack (Session&, const XMLNode&);
~AudioTrack ();
int 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 set_name (string str, void *src);
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);
int roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame,
AudioDiskstream& audio_diskstream() const;
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 ();
bool can_record() const { return true; }
void set_record_enable (bool yn, void *src);
AudioDiskstream& disk_stream() const { return *diskstream; }
int set_diskstream (AudioDiskstream&, void *);
int use_diskstream (string name);
int use_diskstream (const PBD::ID& id);
TrackMode mode() const { return _mode; }
void set_mode (TrackMode m);
sigc::signal<void> ModeChanged;
jack_nframes_t update_total_latency();
void set_latency_delay (jack_nframes_t);
int export_stuff (vector<Sample*>& buffers, char * workbuf, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t end_frame);
sigc::signal<void,void*> diskstream_changed;
enum FreezeState {
NoFreeze,
Frozen,
UnFrozen
};
FreezeState freeze_state() const;
sigc::signal<void> FreezeChange;
void freeze (InterThreadInfo&);
void unfreeze ();
void bounce (InterThreadInfo&);
void bounce_range (jack_nframes_t start, jack_nframes_t end, InterThreadInfo&);
XMLNode& get_state();
XMLNode& get_template();
int set_state(const XMLNode& node);
PBD::Controllable& rec_enable_control() {
return _rec_enable_control;
}
bool record_enabled() const;
void set_meter_point (MeterPoint, void* src);
protected:
AudioDiskstream *diskstream;
MeterPoint _saved_meter_point;
TrackMode _mode;
XMLNode& state (bool full);
void passthru_silence (jack_nframes_t start_frame, jack_nframes_t end_frame,
@@ -107,59 +69,12 @@ class AudioTrack : public Route
bool meter);
uint32_t n_process_buffers ();
private:
struct FreezeRecordInsertInfo {
FreezeRecordInsertInfo(XMLNode& st, boost::shared_ptr<Insert> ins)
: state (st), insert (ins) {}
XMLNode state;
boost::shared_ptr<Insert> insert;
PBD::ID id;
UndoAction memento;
};
struct FreezeRecord {
FreezeRecord() {
playlist = 0;
have_mementos = false;
}
~FreezeRecord();
AudioPlaylist* playlist;
vector<FreezeRecordInsertInfo*> insert_info;
bool have_mementos;
FreezeState state;
};
FreezeRecord _freeze_record;
XMLNode* pending_state;
void diskstream_record_enable_changed (void *src);
void diskstream_input_channel_changed (void *src);
void input_change_handler (void *src);
sigc::connection recenable_connection;
sigc::connection ic_connection;
int deprecated_use_diskstream_connections ();
int set_diskstream (AudioDiskstream&, void *);
int deprecated_use_diskstream_connections ();
void set_state_part_two ();
void set_state_part_three ();
struct RecEnableControllable : public PBD::Controllable {
RecEnableControllable (AudioTrack&);
void set_value (float);
float get_value (void) const;
AudioTrack& track;
};
RecEnableControllable _rec_enable_control;
bool _destructive;
};
} // namespace ARDOUR

View File

@@ -34,6 +34,7 @@
#include <ardour/ardour.h>
#include <jack/jack.h>
#include <jack/transport.h>
#include <ardour/types.h>
namespace ARDOUR {
@@ -104,8 +105,8 @@ class AudioEngine : public sigc::trackable
virtual const char *what() const throw() { return "could not connect to engine backend"; }
};
Port *register_audio_input_port (const std::string& portname);
Port *register_audio_output_port (const std::string& portname);
Port *register_input_port (DataType type, const std::string& portname);
Port *register_output_port (DataType type, const std::string& portname);
int unregister_port (Port *);
int connect (const std::string& source, const std::string& destination);

View File

@@ -77,9 +77,6 @@ class AudioPlaylist : public ARDOUR::Playlist
bool destroy_region (Region*);
void get_equivalent_regions (const AudioRegion&, std::vector<AudioRegion*>&);
void get_region_list_equivalent_regions (const AudioRegion&, std::vector<AudioRegion*>&);
void drop_all_states ();
protected:

View File

@@ -27,8 +27,9 @@
#include <pbd/undo.h>
#include <ardour/ardour.h>
#include <ardour/gain.h>
#include <ardour/region.h>
#include <ardour/gain.h>
#include <ardour/logcurve.h>
#include <ardour/export.h>
class XMLNode;
@@ -43,14 +44,14 @@ class AudioSource;
struct AudioRegionState : public RegionState
{
AudioRegionState (std::string why);
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;
Curve _fade_in;
Curve _fade_out;
Curve _envelope;
gain_t _scale_amplitude;
uint32_t _fade_in_disabled;
uint32_t _fade_out_disabled;
};
class AudioRegion : public Region
@@ -75,11 +76,7 @@ class AudioRegion : public Region
AudioRegion (SourceList &, const XMLNode&);
~AudioRegion();
bool region_list_equivalent (const AudioRegion&) const ;
bool source_equivalent (const AudioRegion&) const;
bool equivalent (const AudioRegion&) const;
bool size_equivalent (const AudioRegion&) const;
bool overlap_equivalent (const AudioRegion&) const;
bool source_equivalent (const Region&) const;
bool speed_mismatch (float) const;
@@ -96,7 +93,7 @@ class AudioRegion : public Region
vector<string> master_source_names();
bool envelope_active () const { return _flags & Region::EnvelopeActive; }
bool fade_in_active () const { return _flags & Region::FadeIn; }
bool fade_in_active () const { return _flags & Region::FadeIn; }
bool fade_out_active () const { return _flags & Region::FadeOut; }
bool captured() const { return !(_flags & (Region::Flag (Region::Import|Region::External))); }
@@ -104,20 +101,21 @@ class AudioRegion : public Region
Curve& fade_out() { return _fade_out; }
Curve& envelope() { return _envelope; }
jack_nframes_t read_peaks (PeakData *buf, jack_nframes_t npeaks, jack_nframes_t offset, jack_nframes_t cnt, uint32_t chan_n=0, double samples_per_unit= 1.0) const;
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 master_read_at (Sample *buf, Sample *mixdown_buffer,
float *gain_buffer, char * workbuf, jack_nframes_t position, jack_nframes_t cnt, uint32_t chan_n=0) const;
virtual jack_nframes_t read_at (Sample *buf, Sample *mixdown_buf,
float *gain_buf, char * workbuf, jack_nframes_t position, jack_nframes_t cnt,
uint32_t chan_n = 0,
jack_nframes_t read_frames = 0,
jack_nframes_t skip_frames = 0) const;
jack_nframes_t master_read_at (Sample *buf, Sample *mixdown_buf,
float *gain_buf, char * workbuf,
jack_nframes_t position, jack_nframes_t cnt, uint32_t chan_n=0) const;
XMLNode& state (bool);
XMLNode& get_state ();
int set_state (const XMLNode&);
static void set_default_fade (float steepness, jack_nframes_t len);
@@ -144,10 +142,6 @@ class AudioRegion : public Region
int separate_by_channel (ARDOUR::Session&, vector<AudioRegion*>&) const;
uint32_t read_data_count() const { return _read_data_count; }
ARDOUR::Playlist* playlist() const { return _playlist; }
UndoAction get_memento() const;
/* filter */
@@ -171,20 +165,6 @@ class AudioRegion : public Region
friend class Playlist;
private:
SourceList sources;
SourceList master_sources; /* used when timefx are applied, so
we can always use the original
source.
*/
mutable Curve _fade_in;
FadeShape _fade_in_shape;
mutable Curve _fade_out;
FadeShape _fade_out_shape;
mutable Curve _envelope;
gain_t _scale_amplitude;
uint32_t _fade_in_disabled;
uint32_t _fade_out_disabled;
void set_default_fades ();
void set_default_fade_in ();
void set_default_fade_out ();
@@ -196,10 +176,6 @@ class AudioRegion : public Region
void recompute_gain_at_end ();
void recompute_gain_at_start ();
bool copied() const { return _flags & Copied; }
void maybe_uncopy ();
void rename_after_first_edit ();
jack_nframes_t _read_at (const SourceList&, Sample *buf, Sample *mixdown_buffer,
float *gain_buffer, char * workbuf, jack_nframes_t position, jack_nframes_t cnt,
uint32_t chan_n = 0,
@@ -216,6 +192,21 @@ class AudioRegion : public Region
void envelope_changed (Change);
void source_deleted (Source*);
SourceList sources;
/** Used when timefx are applied, so we can always use the original source. */
SourceList master_sources;
mutable Curve _fade_in;
FadeShape _fade_in_shape;
mutable Curve _fade_out;
FadeShape _fade_out_shape;
mutable Curve _envelope;
gain_t _scale_amplitude;
uint32_t _fade_in_disabled;
uint32_t _fade_out_disabled;
};
} /* namespace ARDOUR */

144
libs/ardour/ardour/buffer.h Normal file
View File

@@ -0,0 +1,144 @@
/*
Copyright (C) 2006 Paul Davis
Written by Dave Robillard, 2006
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option)
any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __ardour_buffer_h__
#define __ardour_buffer_h__
#define _XOPEN_SOURCE 600
#include <cstdlib> // for posix_memalign
#include <cassert>
#include <ardour/types.h>
#include <jack/jack.h>
namespace ARDOUR {
/* Yes, this is a bit of a mess right now. I'll clean it up when everything
* using it works out.. */
/** A buffer of recordable/playable data.
*
* This is a datatype-agnostic base class for all buffers (there are no
* methods to actually access the data). This provides a way for code that
* doesn't care about the data type to still deal with buffers (which is
* why the base class can't be a template).
*
* To actually read/write buffer contents, use the appropriate derived class.
*/
class Buffer
{
public:
Buffer(DataType type, size_t capacity)
: _type(type), _capacity(capacity), _size(0)
{}
virtual ~Buffer() {}
/** Maximum capacity of buffer.
* Note in some cases the entire buffer may not contain valid data, use size. */
size_t capacity() const { return _capacity; }
/** Amount of valid data in buffer. Use this over capacity almost always. */
size_t size() const { return _size; }
/** Type of this buffer.
* Based on this you can static cast a Buffer* to the desired type. */
virtual DataType type() const { return _type; }
/** Jack type (eg JACK_DEFAULT_AUDIO_TYPE) */
const char* jack_type() const { return type_to_jack_type(type()); }
/** String type as saved in session XML files (eg "audio" or "midi") */
const char* type_string() const { return type_to_string(type()); }
/* The below static methods need to be separate from the above methods
* because the conversion is needed in places where there's no Buffer.
* These should probably live somewhere else...
*/
static const char* type_to_jack_type(DataType t) {
switch (t) {
case AUDIO: return JACK_DEFAULT_AUDIO_TYPE;
case MIDI: return JACK_DEFAULT_MIDI_TYPE;
default: return "";
}
}
static const char* type_to_string(DataType t) {
switch (t) {
case AUDIO: return "audio";
case MIDI: return "midi";
default: return "unknown"; // reeeally shouldn't ever happen
}
}
/** Used for loading from XML (route default types etc) */
static DataType type_from_string(const string& str) {
if (str == "audio")
return AUDIO;
else if (str == "midi")
return MIDI;
else
return NIL;
}
protected:
DataType _type;
size_t _capacity;
size_t _size;
};
/* Inside every class with a type in it's name is a template waiting to get out... */
/** Buffer containing 32-bit floating point (audio) data. */
class AudioBuffer : public Buffer
{
public:
AudioBuffer(size_t capacity)
: Buffer(AUDIO, capacity)
, _data(NULL)
{
_size = capacity; // For audio buffers, size = capacity (always)
#ifdef NO_POSIX_MEMALIGN
b = (Sample *) malloc(sizeof(Sample) * capacity);
#else
posix_memalign((void**)_data, 16, sizeof(Sample) * capacity);
#endif
assert(_data);
memset(_data, 0, sizeof(Sample) * capacity);
}
const Sample* data() const { return _data; }
Sample* data() { return _data; }
private:
// These are undefined (prevent copies)
AudioBuffer(const AudioBuffer& copy);
AudioBuffer& operator=(const AudioBuffer& copy);
Sample* const _data; ///< Actual buffer contents
};
} // namespace ARDOUR
#endif // __ardour_buffer_h__

View File

@@ -0,0 +1,319 @@
/*
Copyright (C) 2000-2006 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: diskstream.h 579 2006-06-12 19:56:37Z essej $
*/
#ifndef __ardour_diskstream_h__
#define __ardour_diskstream_h__
#include <sigc++/signal.h>
#include <cmath>
#include <string>
#include <queue>
#include <map>
#include <vector>
#include <time.h>
#include <pbd/fastlog.h>
#include <pbd/ringbufferNPT.h>
#include <pbd/stateful.h>
#include <ardour/ardour.h>
#include <ardour/configuration.h>
#include <ardour/session.h>
#include <ardour/route_group.h>
#include <ardour/route.h>
#include <ardour/port.h>
#include <ardour/utils.h>
struct tm;
namespace ARDOUR {
class AudioEngine;
class Send;
class Session;
class Playlist;
class IO;
class Diskstream : public Stateful, public sigc::trackable
{
public:
enum Flag {
Recordable = 0x1,
Hidden = 0x2,
Destructive = 0x4
};
string name () const { return _name; }
virtual int set_name (string str);
ARDOUR::IO* io() const { return _io; }
void set_io (ARDOUR::IO& io);
virtual Diskstream& ref() { _refcnt++; return *this; }
void unref() { if (_refcnt) _refcnt--; if (_refcnt == 0) delete this; }
uint32_t refcnt() const { return _refcnt; }
virtual float playback_buffer_load() const = 0;
virtual float capture_buffer_load() const = 0;
void set_flag (Flag f) { _flags |= f; }
void unset_flag (Flag f) { _flags &= ~f; }
AlignStyle alignment_style() const { return _alignment_style; }
void set_align_style (AlignStyle);
void set_persistent_align_style (AlignStyle a) { _persistent_alignment_style = a; }
jack_nframes_t roll_delay() const { return _roll_delay; }
void set_roll_delay (jack_nframes_t);
bool record_enabled() const { return g_atomic_int_get (&_record_enabled); }
virtual void set_record_enabled (bool yn) = 0;
bool destructive() const { return _flags & Destructive; }
virtual void set_destructive (bool yn);
const PBD::ID& id() const { return _id; }
bool hidden() const { return _flags & Hidden; }
bool recordable() const { return _flags & Recordable; }
bool reversed() const { return _actual_speed < 0.0f; }
double speed() const { return _visible_speed; }
virtual void punch_in() {}
virtual void punch_out() {}
void set_speed (double);
void non_realtime_set_speed ();
Playlist* playlist () { return _playlist; }
virtual int use_playlist (Playlist *);
virtual int use_new_playlist () = 0;
virtual int use_copy_playlist () = 0;
jack_nframes_t current_capture_start() const { return capture_start_frame; }
jack_nframes_t current_capture_end() const { return capture_start_frame + capture_captured; }
jack_nframes_t get_capture_start_frame (uint32_t n=0);
jack_nframes_t get_captured_frames (uint32_t n=0);
uint32_t n_channels() { return _n_channels; }
static jack_nframes_t disk_io_frames() { return disk_io_chunk_frames; }
static void set_disk_io_chunk_frames (uint32_t n) { disk_io_chunk_frames = n; }
/* Stateful */
virtual XMLNode& get_state(void) = 0;
virtual int set_state(const XMLNode& node) = 0;
// FIXME: makes sense for all diskstream types?
virtual void monitor_input (bool) {}
jack_nframes_t capture_offset() const { return _capture_offset; }
virtual void set_capture_offset ();
bool slaved() const { return _slaved; }
void set_slaved(bool yn) { _slaved = yn; }
int set_loop (Location *loc);
std::list<Region*>& last_capture_regions () { return _last_capture_regions; }
void handle_input_change (IOChange, void *src);
sigc::signal<void> RecordEnableChanged;
sigc::signal<void> SpeedChanged;
sigc::signal<void> ReverseChanged;
sigc::signal<void> PlaylistChanged;
sigc::signal<void> AlignmentStyleChanged;
sigc::signal<void,Location *> LoopSet;
static sigc::signal<void> DiskOverrun;
static sigc::signal<void> DiskUnderrun;
static sigc::signal<void,Diskstream*> DiskstreamCreated; // XXX use a ref with sigc2
static sigc::signal<void,list<Source*>*> DeleteSources;
protected:
friend class Session;
Diskstream (Session &, const string& name, Flag f = Recordable);
Diskstream (Session &, const XMLNode&);
/* the Session is the only point of access for these because they require
* that the Session is "inactive" while they are called.
*/
virtual void set_pending_overwrite (bool) = 0;
virtual int overwrite_existing_buffers () = 0;
virtual void set_block_size (jack_nframes_t) = 0;
virtual int internal_playback_seek (jack_nframes_t distance) = 0;
virtual int can_internal_playback_seek (jack_nframes_t distance) = 0;
virtual int rename_write_sources () = 0;
virtual void reset_write_sources (bool, bool force = false) = 0;
virtual void non_realtime_input_change () = 0;
uint32_t read_data_count() const { return _read_data_count; }
uint32_t write_data_count() const { return _write_data_count; }
protected:
friend class Auditioner;
virtual int seek (jack_nframes_t which_sample, bool complete_refill = false) = 0;
protected:
friend class Track;
virtual void prepare ();
virtual int process (jack_nframes_t transport_frame, jack_nframes_t nframes, jack_nframes_t offset, bool can_record, bool rec_monitors_input) = 0;
virtual bool commit (jack_nframes_t nframes) = 0;
virtual void recover (); /* called if commit will not be called, but process was */
//private:
/** Use unref() to destroy a diskstream */
virtual ~Diskstream();
enum TransitionType {
CaptureStart = 0,
CaptureEnd
};
struct CaptureTransition {
TransitionType type;
jack_nframes_t capture_val; ///< The start or end file frame position
};
/* The two central butler operations */
virtual int do_flush (Session::RunContext context, bool force = false) = 0;
virtual int do_refill () = 0;
/** For non-butler contexts (allocates temporary working buffers) */
virtual int do_refill_with_alloc() = 0;
/* XXX fix this redundancy ... */
virtual void playlist_changed (Change);
virtual void playlist_modified ();
virtual void playlist_deleted (Playlist*);
virtual void finish_capture (bool rec_monitors_input) = 0;
virtual void transport_stopped (struct tm&, time_t, bool abort) = 0;
struct CaptureInfo {
uint32_t start;
uint32_t frames;
};
virtual void init (Flag);
virtual int use_new_write_source (uint32_t n=0) = 0;
virtual int find_and_use_playlist (const string&) = 0;
virtual void allocate_temporary_buffers () = 0;
virtual bool realtime_set_speed (double, bool global_change);
std::list<Region*> _last_capture_regions;
virtual int use_pending_capture_data (XMLNode& node) = 0;
virtual void get_input_sources () = 0;
virtual void check_record_status (jack_nframes_t transport_frame, jack_nframes_t nframes, bool can_record) = 0;
virtual void set_align_style_from_io() {}
virtual void setup_destructive_playlist () = 0;
virtual void use_destructive_playlist () = 0;
static jack_nframes_t disk_io_chunk_frames;
vector<CaptureInfo*> capture_info;
Glib::Mutex capture_info_lock;
uint32_t i_am_the_modifier;
string _name;
ARDOUR::Session& _session;
ARDOUR::IO* _io;
uint32_t _n_channels;
PBD::ID _id;
Playlist* _playlist;
mutable gint _record_enabled;
double _visible_speed;
double _actual_speed;
/* items needed for speed change logic */
bool _buffer_reallocation_required;
bool _seek_required;
bool force_refill;
jack_nframes_t capture_start_frame;
jack_nframes_t capture_captured;
bool was_recording;
jack_nframes_t adjust_capture_position;
jack_nframes_t _capture_offset;
jack_nframes_t _roll_delay;
jack_nframes_t first_recordable_frame;
jack_nframes_t last_recordable_frame;
int last_possibly_recording;
AlignStyle _alignment_style;
bool _scrubbing;
bool _slaved;
bool _processed;
Location* loop_location;
jack_nframes_t overwrite_frame;
off_t overwrite_offset;
bool pending_overwrite;
bool overwrite_queued;
IOChange input_change_pending;
jack_nframes_t wrap_buffer_size;
jack_nframes_t speed_buffer_size;
uint64_t last_phase;
uint64_t phi;
jack_nframes_t file_frame;
jack_nframes_t playback_sample;
jack_nframes_t playback_distance;
uint32_t _read_data_count;
uint32_t _write_data_count;
bool in_set_state;
AlignStyle _persistent_alignment_style;
bool first_input_change;
Glib::Mutex state_lock;
jack_nframes_t scrub_start;
jack_nframes_t scrub_buffer_size;
jack_nframes_t scrub_offset;
uint32_t _refcnt;
sigc::connection ports_created_c;
sigc::connection plmod_connection;
sigc::connection plstate_connection;
sigc::connection plgone_connection;
unsigned char _flags;
};
}; /* namespace ARDOUR */
#endif /* __ardour_diskstream_h__ */

View File

@@ -38,6 +38,7 @@
#include <ardour/utils.h>
#include <ardour/state_manager.h>
#include <ardour/curve.h>
#include <ardour/types.h>
using std::string;
using std::vector;
@@ -52,6 +53,11 @@ class Port;
class Connection;
class Panner;
/** A collection of input and output ports with connections.
*
* An IO can contain ports of varying types, making routes/inserts/etc with
* varied combinations of types (eg MIDI and audio) possible.
*/
class IO : public Stateful, public ARDOUR::StateManager
{
@@ -60,7 +66,8 @@ class IO : public Stateful, public ARDOUR::StateManager
IO (Session&, string name,
int input_min = -1, int input_max = -1,
int output_min = -1, int output_max = -1);
int output_min = -1, int output_max = -1,
DataType default_type = AUDIO);
virtual ~IO();
@@ -74,25 +81,29 @@ class IO : public Stateful, public ARDOUR::StateManager
void set_output_minimum (int n);
void set_output_maximum (int n);
DataType default_type() const { return _default_type; }
const string& name() const { return _name; }
virtual int set_name (string str, void *src);
virtual void silence (jack_nframes_t, jack_nframes_t offset);
// These should be moved in to a separate object that manipulates an IO
void pan (vector<Sample*>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset, gain_t gain_coeff);
void pan_automated (vector<Sample*>& bufs, uint32_t nbufs, jack_nframes_t start_frame, jack_nframes_t end_frame,
jack_nframes_t nframes, jack_nframes_t offset);
void collect_input (vector<Sample*>&, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset);
void deliver_output (vector<Sample *>&, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset);
void deliver_output_no_pan (vector<Sample *>&, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset);
void deliver_output (vector<Sample*>&, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset);
void deliver_output_no_pan (vector<Sample*>&, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset);
void just_meter_input (jack_nframes_t start_frame, jack_nframes_t end_frame,
jack_nframes_t nframes, jack_nframes_t offset);
virtual uint32_t n_process_buffers () { return 0; }
virtual void set_gain (gain_t g, void *src);
void inc_gain (gain_t delta, void *src);
gain_t gain () const { return _desired_gain; }
void inc_gain (gain_t delta, void *src);
gain_t gain () const { return _desired_gain; }
virtual gain_t effective_gain () const;
Panner& panner() { return *_panner; }
@@ -105,8 +116,8 @@ class IO : public Stateful, public ARDOUR::StateManager
Connection *input_connection() const { return _input_connection; }
Connection *output_connection() const { return _output_connection; }
int add_input_port (string source, void *src);
int add_output_port (string destination, void *src);
int add_input_port (string source, void *src, DataType type = NIL);
int add_output_port (string destination, void *src, DataType type = NIL);
int remove_input_port (Port *, void *src);
int remove_output_port (Port *, void *src);
@@ -273,6 +284,7 @@ public:
PBD::ID _id;
bool no_panner_reset;
XMLNode* deferred_state;
DataType _default_type;
virtual void set_deferred_state() {}

View File

@@ -54,7 +54,6 @@ class Playlist : public Stateful, public StateManager {
Playlist (const Playlist&, string name, bool hidden = false);
Playlist (const Playlist&, jack_nframes_t start, jack_nframes_t cnt, string name, bool hidden = false);
virtual jack_nframes_t read (Sample *dst, Sample *mixdown, float *gain_buffer, char * workbuf, jack_nframes_t start, jack_nframes_t cnt, uint32_t chan_n=0) = 0;
virtual void clear (bool with_delete = false, bool with_save = true);
virtual void dump () const;
virtual UndoAction get_memento() const = 0;
@@ -81,6 +80,8 @@ class Playlist : public Stateful, public StateManager {
void add_region (const Region&, jack_nframes_t position, float times = 1, bool with_save = true);
void remove_region (Region *);
void get_equivalent_regions (const Region&, std::vector<Region*>&);
void get_region_list_equivalent_regions (const Region&, std::vector<Region*>&);
void replace_region (Region& old, Region& newr, jack_nframes_t pos);
void split_region (Region&, jack_nframes_t position);
void partition (jack_nframes_t start, jack_nframes_t end, bool just_top_level);
@@ -108,16 +109,15 @@ class Playlist : public Stateful, public StateManager {
int set_state (const XMLNode&);
XMLNode& get_template ();
sigc::signal<void,Region *> RegionAdded;
sigc::signal<void,Region *> RegionRemoved;
sigc::signal<void,Region *> RegionAdded;
sigc::signal<void,Region *> RegionRemoved;
sigc::signal<void,Playlist*,bool> InUse;
sigc::signal<void> Modified;
sigc::signal<void> NameChanged;
sigc::signal<void> LengthChanged;
sigc::signal<void> LayeringChanged;
sigc::signal<void,Playlist *> GoingAway;
sigc::signal<void> StatePushed;
sigc::signal<void> Modified;
sigc::signal<void> NameChanged;
sigc::signal<void> LengthChanged;
sigc::signal<void> LayeringChanged;
sigc::signal<void,Playlist *> GoingAway;
sigc::signal<void> StatePushed;
static sigc::signal<void,Playlist*> PlaylistCreated;

View File

@@ -33,24 +33,24 @@ class AudioEngine;
class Port : public sigc::trackable {
public:
virtual ~Port() {
free (port);
free (_port);
}
Sample *get_buffer (jack_nframes_t nframes) {
if (_flags & JackPortIsOutput) {
return _buffer;
} else {
return (Sample *) jack_port_get_buffer (port, nframes);
return (Sample *) jack_port_get_buffer (_port, nframes);
}
}
void reset_buffer () {
if (_flags & JackPortIsOutput) {
_buffer = (Sample *) jack_port_get_buffer (port, 0);
_buffer = (Sample *) jack_port_get_buffer (_port, 0);
} else {
_buffer = 0; /* catch illegal attempts to use it */
}
silent = false;
_silent = false;
}
std::string name() {
@@ -58,7 +58,7 @@ class Port : public sigc::trackable {
}
std::string short_name() {
return jack_port_short_name (port);
return jack_port_short_name (_port);
}
int set_name (std::string str);
@@ -68,7 +68,7 @@ class Port : public sigc::trackable {
}
bool is_mine (jack_client_t *client) {
return jack_port_is_mine (client, port);
return jack_port_is_mine (client, _port);
}
const char* type() const {
@@ -76,21 +76,21 @@ class Port : public sigc::trackable {
}
int connected () const {
return jack_port_connected (port);
return jack_port_connected (_port);
}
bool connected_to (const std::string& portname) const {
return jack_port_connected_to (port, portname.c_str());
return jack_port_connected_to (_port, portname.c_str());
}
const char ** get_connections () const {
return jack_port_get_connections (port);
return jack_port_get_connections (_port);
}
void reset_overs () {
_short_overs = 0;
_long_overs = 0;
overlen = 0;
_overlen = 0;
}
void reset_peak_meter () {
@@ -103,18 +103,18 @@ class Port : public sigc::trackable {
}
void enable_metering() {
metering++;
_metering++;
}
void disable_metering () {
if (metering) { metering--; }
if (_metering) { _metering--; }
}
float peak_db() const { return _peak_db; }
float peak_db() const { return _peak_db; }
jack_default_audio_sample_t peak() const { return _peak; }
uint32_t short_overs () const { return _short_overs; }
uint32_t long_overs () const { return _long_overs; }
uint32_t long_overs () const { return _long_overs; }
static void set_short_over_length (jack_nframes_t);
static void set_long_over_length (jack_nframes_t);
@@ -128,7 +128,7 @@ class Port : public sigc::trackable {
}
bool monitoring_input () const {
return jack_port_monitoring_input (port);
return jack_port_monitoring_input (_port);
}
bool can_monitor () const {
@@ -136,30 +136,29 @@ class Port : public sigc::trackable {
}
void ensure_monitor_input (bool yn) {
jack_port_request_monitor (port, yn);
jack_port_request_monitor (_port, yn);
}
void request_monitor_input (bool yn) {
jack_port_request_monitor (port, yn);
jack_port_request_monitor (_port, yn);
}
jack_nframes_t latency () const {
return jack_port_get_latency (port);
return jack_port_get_latency (_port);
}
void set_latency (jack_nframes_t nframes) {
jack_port_set_latency (port, nframes);
jack_port_set_latency (_port, nframes);
}
sigc::signal<void,bool> MonitorInputChanged;
sigc::signal<void,bool> ClockSyncChanged;
bool is_silent() const { return silent; }
bool is_silent() const { return _silent; }
/** Assumes that the port is an audio output port */
void silence (jack_nframes_t nframes, jack_nframes_t offset) {
/* assumes that the port is an output port */
if (!silent) {
if (!_silent) {
memset (_buffer + offset, 0, sizeof (Sample) * nframes);
if (offset == 0) {
/* XXX this isn't really true, but i am not sure
@@ -167,13 +166,13 @@ class Port : public sigc::trackable {
want to set it true when the entire port
buffer has been overrwritten.
*/
silent = true;
_silent = true;
}
}
}
void mark_silence (bool yn) {
silent = yn;
_silent = yn;
}
private:
@@ -184,7 +183,7 @@ class Port : public sigc::trackable {
/* engine isn't supposed to below here */
Sample *_buffer;
Sample *_buffer;
/* cache these 3 from JACK so that we can
access them for reconnecting.
@@ -194,18 +193,18 @@ class Port : public sigc::trackable {
std::string _type;
std::string _name;
bool last_monitor : 1;
bool silent : 1;
jack_port_t *port;
jack_nframes_t overlen;
jack_default_audio_sample_t _peak;
float _peak_db;
uint32_t _short_overs;
uint32_t _long_overs;
unsigned short metering;
bool _last_monitor : 1;
bool _silent : 1;
jack_port_t *_port;
jack_nframes_t _overlen;
jack_default_audio_sample_t _peak;
float _peak_db;
uint32_t _short_overs;
uint32_t _long_overs;
unsigned short _metering;
static jack_nframes_t long_over_length;
static jack_nframes_t short_over_length;
static jack_nframes_t _long_over_length;
static jack_nframes_t _short_over_length;
};
} // namespace ARDOUR

View File

@@ -24,7 +24,6 @@
#include <pbd/undo.h>
#include <ardour/ardour.h>
#include <ardour/logcurve.h>
#include <ardour/state_manager.h>
class XMLNode;
@@ -36,22 +35,22 @@ class Source;
enum RegionEditState {
EditChangesNothing = 0,
EditChangesName = 1,
EditChangesID = 2
EditChangesName = 1,
EditChangesID = 2
};
struct RegionState : public StateManager::State {
struct RegionState : public StateManager::State
{
RegionState (std::string why) : StateManager::State (why) {}
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;
jack_nframes_t _start;
jack_nframes_t _length;
jack_nframes_t _position;
uint32_t _flags;
jack_nframes_t _sync_position;
layer_t _layer;
string _name;
mutable RegionEditState _first_edit;
};
class Region : public Stateful, public StateManager
@@ -95,7 +94,7 @@ class Region : public Stateful, public StateManager
Region (const Region&, jack_nframes_t start, jack_nframes_t length, const string& name, layer_t = 0, Flag flags = DefaultFlags);
Region (const Region&);
Region (const XMLNode&);
~Region();
virtual ~Region();
const PBD::ID& id() const { return _id; }
@@ -105,9 +104,10 @@ class Region : public Stateful, public StateManager
void set_name (string str);
jack_nframes_t position () const { return _position; }
jack_nframes_t start () const { return _start; }
jack_nframes_t length() const { return _length; }
layer_t layer () const { return _layer; }
jack_nframes_t start () const { return _start; }
jack_nframes_t length() const { return _length; }
layer_t layer () const { return _layer; }
jack_nframes_t sync_offset(int& dir) const;
jack_nframes_t sync_position() const;
@@ -118,14 +118,13 @@ class Region : public Stateful, public StateManager
jack_nframes_t first_frame() const { return _position; }
jack_nframes_t last_frame() const { return _position + _length - 1; }
bool hidden() const { return _flags & Hidden; }
bool muted() const { return _flags & Muted; }
bool opaque () const { return _flags & Opaque; }
bool envelope_active () const { return _flags & EnvelopeActive; }
bool locked() const { return _flags & Locked; }
bool automatic() const { return _flags & Automatic; }
bool hidden() const { return _flags & Hidden; }
bool muted() const { return _flags & Muted; }
bool opaque () const { return _flags & Opaque; }
bool locked() const { return _flags & Locked; }
bool automatic() const { return _flags & Automatic; }
bool whole_file() const { return _flags & WholeFile ; }
Flag flags() const { return _flags; }
Flag flags() const { return _flags; }
virtual bool should_save_state () const { return !(_flags & DoNotSaveState); };
@@ -139,12 +138,14 @@ class Region : public Stateful, public StateManager
OverlapType coverage (jack_nframes_t start, jack_nframes_t end) const {
return ARDOUR::coverage (_position, _position + _length - 1, start, end);
}
virtual jack_nframes_t read_at (Sample *buf, Sample *mixdown_buffer,
float *gain_buffer, char * workbuf, jack_nframes_t position, jack_nframes_t cnt,
uint32_t chan_n = 0,
jack_nframes_t read_frames = 0,
jack_nframes_t skip_frames = 0) const = 0;
bool equivalent (const Region&) const;
bool size_equivalent (const Region&) const;
bool overlap_equivalent (const Region&) const;
bool region_list_equivalent (const Region&) const;
virtual bool source_equivalent (const Region&) const = 0;
virtual bool speed_mismatch (float) const = 0;
/* EDITING OPERATIONS */
@@ -173,7 +174,6 @@ class Region : public Stateful, public StateManager
void set_hidden (bool yn);
void set_muted (bool yn);
void set_opaque (bool yn);
void set_envelope_active (bool yn);
void set_locked (bool yn);
virtual uint32_t read_data_count() const { return _read_data_count; }
@@ -189,9 +189,9 @@ class Region : public Stateful, public StateManager
/* serialization */
XMLNode& get_state ();
virtual XMLNode& state (bool);
XMLNode& get_state ();
int set_state (const XMLNode&);
virtual int set_state (const XMLNode&);
sigc::signal<void,Region*> GoingAway;
@@ -211,23 +211,6 @@ class Region : public Stateful, public StateManager
void set_last_layer_op (uint64_t when);
protected:
jack_nframes_t _start;
jack_nframes_t _length;
jack_nframes_t _position;
Flag _flags;
jack_nframes_t _sync_position;
layer_t _layer;
string _name;
mutable RegionEditState _first_edit;
int _frozen;
Glib::Mutex lock;
PBD::ID _id;
ARDOUR::Playlist* _playlist;
mutable uint32_t _read_data_count; // modified in read()
Change pending_changed;
uint64_t _last_layer_op; // timestamp
XMLNode& get_short_state (); /* used only by Session */
/* state management */
@@ -251,6 +234,23 @@ class Region : public Stateful, public StateManager
virtual bool verify_length (jack_nframes_t) = 0;
virtual void recompute_at_start () = 0;
virtual void recompute_at_end () = 0;
jack_nframes_t _start;
jack_nframes_t _length;
jack_nframes_t _position;
Flag _flags;
jack_nframes_t _sync_position;
layer_t _layer;
string _name;
mutable RegionEditState _first_edit;
int _frozen;
Glib::Mutex lock;
PBD::ID _id;
ARDOUR::Playlist* _playlist;
mutable uint32_t _read_data_count; // modified in read()
Change pending_changed;
uint64_t _last_layer_op; // timestamp
};
} /* namespace ARDOUR */

View File

@@ -40,6 +40,7 @@
#include <ardour/io.h>
#include <ardour/session.h>
#include <ardour/redirect.h>
#include <ardour/types.h>
namespace ARDOUR {
@@ -68,7 +69,9 @@ class Route : public IO
};
Route (Session&, std::string name, int input_min, int input_max, int output_min, int output_max, Flag flags = Flag(0));
Route (Session&, std::string name, int input_min, int input_max, int output_min, int output_max,
Flag flags = Flag(0), DataType default_type = AUDIO);
Route (Session&, const XMLNode&);
virtual ~Route();

View File

@@ -35,6 +35,7 @@ using std::list;
namespace ARDOUR {
class Route;
class Track;
class AudioTrack;
class Session;
@@ -90,7 +91,7 @@ class RouteGroup : public Stateful, public sigc::trackable {
/* to use these, #include <ardour/route_group_specialized.h> */
template<class T> void apply (void (AudioTrack::*func)(T, void *), T val, void *src);
template<class T> void apply (void (Track::*func)(T, void *), T val, void *src);
/* fills at_set with all members of the group that are AudioTracks */

View File

@@ -7,11 +7,11 @@
namespace ARDOUR {
template<class T> void
RouteGroup::apply (void (AudioTrack::*func)(T, void *), T val, void *src)
RouteGroup::apply (void (Track::*func)(T, void *), T val, void *src)
{
for (list<Route *>::iterator i = routes.begin(); i != routes.end(); i++) {
AudioTrack *at;
if ((at = dynamic_cast<AudioTrack*>(*i)) != 0) {
Track *at;
if ((at = dynamic_cast<Track*>(*i)) != 0) {
(at->*func)(val, this);
}
}

View File

@@ -66,6 +66,7 @@ namespace ARDOUR {
class Port;
class AudioEngine;
class Slave;
class Diskstream;
class AudioDiskstream;
class Route;
class AuxInput;
@@ -157,17 +158,17 @@ class Session : public sigc::trackable, public Stateful
Clear
};
Type type;
Action action;
jack_nframes_t action_frame;
jack_nframes_t target_frame;
float speed;
Type type;
Action action;
jack_nframes_t action_frame;
jack_nframes_t target_frame;
float speed;
union {
void* ptr;
bool yes_or_no;
Session::SlaveSource slave;
Route* route;
void* ptr;
bool yes_or_no;
Session::SlaveSource slave;
Route* route;
};
list<AudioRange> audio_range;
@@ -269,30 +270,18 @@ class Session : public sigc::trackable, public Stateful
vector<Sample*>& get_silent_buffers (uint32_t howmany);
vector<Sample*>& get_send_buffers () { return _send_buffers; }
AudioDiskstream *diskstream_by_id (const PBD::ID& id);
AudioDiskstream *diskstream_by_name (string name);
Diskstream* diskstream_by_id (const PBD::ID& id);
Diskstream* diskstream_by_name (string name);
bool have_captured() const { return _have_captured; }
void refill_all_diskstream_buffers ();
uint32_t diskstream_buffer_size() const { return dstream_buffer_size; }
/* XXX fix required here when we get new diskstream types *, but
not sure of the direction to take this in until then.
*/
uint32_t get_next_diskstream_id() const { return n_audio_diskstreams(); }
uint32_t n_audio_diskstreams() const;
uint32_t get_next_diskstream_id() const { return n_diskstreams(); }
uint32_t n_diskstreams() const;
typedef list<AudioDiskstream *> AudioDiskstreamList;
Session::AudioDiskstreamList audio_disk_streams() const {
Glib::RWLock::ReaderLock lm (diskstream_lock);
return audio_diskstreams; /* XXX yes, force a copy */
}
void foreach_audio_diskstream (void (AudioDiskstream::*func)(void));
template<class T> void foreach_audio_diskstream (T *obj, void (T::*func)(AudioDiskstream&));
typedef list<Diskstream *> DiskstreamList;
typedef std::list<boost::shared_ptr<Route> > RouteList;
@@ -356,7 +345,7 @@ class Session : public sigc::trackable, public Stateful
sigc::signal<void> HaltOnXrun;
sigc::signal<void,boost::shared_ptr<Route> > RouteAdded;
sigc::signal<void,AudioDiskstream*> AudioDiskstreamAdded;
sigc::signal<void,Diskstream*> DiskstreamAdded; // FIXME: make a shared_ptr
void request_roll ();
void request_bounded_roll (jack_nframes_t start, jack_nframes_t end);
@@ -368,15 +357,14 @@ class Session : public sigc::trackable, public Stateful
void goto_start () { request_locate (start_location->start(), false); }
void use_rf_shuttle_speed ();
void request_transport_speed (float speed);
void request_overwrite_buffer (AudioDiskstream*);
void request_diskstream_speed (AudioDiskstream&, float speed);
void request_overwrite_buffer (Diskstream*);
void request_diskstream_speed (Diskstream&, float speed);
void request_input_change_handling ();
bool locate_pending() const { return static_cast<bool>(post_transport_work&PostTransportLocate); }
bool transport_locked () const;
int wipe ();
int wipe_diskstream (AudioDiskstream *);
int remove_region_from_region_list (Region&);
@@ -553,9 +541,6 @@ class Session : public sigc::trackable, public Stateful
void resort_routes ();
void resort_routes_using (boost::shared_ptr<RouteList>);
void resort_routes_proxy (void* src) {
resort_routes ();
}
AudioEngine &engine() { return _engine; };
@@ -636,7 +621,7 @@ class Session : public sigc::trackable, public Stateful
string path_from_region_name (string name, string identifier);
AudioRegion* find_whole_file_parent (AudioRegion&);
void find_equivalent_playlist_regions (AudioRegion&, std::vector<AudioRegion*>& result);
void find_equivalent_playlist_regions (Region&, std::vector<Region*>& result);
AudioRegion *XMLRegionFactory (const XMLNode&, bool full);
@@ -713,8 +698,6 @@ class Session : public sigc::trackable, public Stateful
sigc::signal<void,Playlist*> PlaylistAdded;
sigc::signal<void,Playlist*> PlaylistRemoved;
Playlist *get_playlist (string name);
uint32_t n_playlists() const;
template<class T> void foreach_playlist (T *obj, void (T::*func)(Playlist *));
@@ -739,7 +722,7 @@ class Session : public sigc::trackable, public Stateful
boost::shared_ptr<Auditioner> the_auditioner() { return auditioner; }
void audition_playlist ();
void audition_region (AudioRegion&);
void audition_region (Region&);
void cancel_audition ();
bool is_auditioning () const;
@@ -980,7 +963,7 @@ class Session : public sigc::trackable, public Stateful
void set_frame_rate (jack_nframes_t nframes);
protected:
friend class AudioDiskstream;
friend class Diskstream;
void stop_butler ();
void wait_till_butler_finished();
@@ -1442,12 +1425,12 @@ class Session : public sigc::trackable, public Stateful
bool waiting_to_start;
void set_auto_loop (bool yn);
void overwrite_some_buffers (AudioDiskstream*);
void overwrite_some_buffers (Diskstream*);
void flush_all_redirects ();
void locate (jack_nframes_t, bool with_roll, bool with_flush, bool with_loop=false);
void start_locate (jack_nframes_t, bool with_roll, bool with_flush, bool with_loop=false);
void force_locate (jack_nframes_t frame, bool with_roll = false);
void set_diskstream_speed (AudioDiskstream*, float speed);
void set_diskstream_speed (Diskstream*, float speed);
void set_transport_speed (float speed, bool abort = false);
void stop_transport (bool abort = false);
void start_transport ();
@@ -1478,10 +1461,10 @@ class Session : public sigc::trackable, public Stateful
/* disk-streams */
AudioDiskstreamList audio_diskstreams;
DiskstreamList diskstreams;
mutable Glib::RWLock diskstream_lock;
uint32_t dstream_buffer_size;
void add_diskstream (AudioDiskstream*);
void add_diskstream (Diskstream*);
int load_diskstreams (const XMLNode&);
/* routes stuff */
@@ -1549,7 +1532,7 @@ class Session : public sigc::trackable, public Stateful
Playlist *XMLPlaylistFactory (const XMLNode&);
void playlist_length_changed (Playlist *);
void diskstream_playlist_changed (AudioDiskstream *);
void diskstream_playlist_changed (Diskstream *);
/* NAMED SELECTIONS */

View File

@@ -1,42 +0,0 @@
/*
Copyright (C) 2002 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id$
*/
#ifndef __ardour_session_diskstream_h__
#define __ardour_session_diskstream_h__
#include <ardour/session.h>
#include <ardour/audio_diskstream.h>
namespace ARDOUR {
template<class T> void
Session::foreach_audio_diskstream (T *obj, void (T::*func)(AudioDiskstream&))
{
Glib::RWLock::ReaderLock lm (diskstream_lock);
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); i++) {
if (!(*i)->hidden()) {
(obj->*func) (**i);
}
}
}
} /* namespace */
#endif /* __ardour_session_diskstream_h__ */

158
libs/ardour/ardour/track.h Normal file
View File

@@ -0,0 +1,158 @@
/*
Copyright (C) 2006 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __ardour_track_h__
#define __ardour_track_h__
#include <ardour/route.h>
namespace ARDOUR {
class Session;
class Diskstream;
class Playlist;
class RouteGroup;
class Track : public Route
{
public:
Track (Session&, string name, Route::Flag f = Route::Flag (0), TrackMode m = Normal, DataType default_type = AUDIO);
virtual ~Track ();
int set_name (string str, void *src);
virtual int roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame,
jack_nframes_t offset, int declick, bool can_record, bool rec_monitors_input) = 0;
virtual int no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame,
jack_nframes_t offset, bool state_changing, bool can_record, bool rec_monitors_input) = 0;
virtual int silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame,
jack_nframes_t offset, bool can_record, bool rec_monitors_input) = 0;
void toggle_monitor_input ();
bool can_record() const { return true; }
Diskstream& diskstream() const { return *_diskstream; }
virtual int use_diskstream (string name) = 0;
virtual int use_diskstream (const PBD::ID& id) = 0;
TrackMode mode() const { return _mode; }
void set_mode (TrackMode m);
jack_nframes_t update_total_latency();
void set_latency_delay (jack_nframes_t);
enum FreezeState {
NoFreeze,
Frozen,
UnFrozen
};
FreezeState freeze_state() const;
virtual void freeze (InterThreadInfo&) = 0;
virtual void unfreeze () = 0;
virtual void bounce (InterThreadInfo&) = 0;
virtual void bounce_range (jack_nframes_t start, jack_nframes_t end, InterThreadInfo&) = 0;
XMLNode& get_state();
XMLNode& get_template();
virtual int set_state(const XMLNode& node) = 0;
PBD::Controllable& rec_enable_control() { return _rec_enable_control; }
bool record_enabled() const;
void set_record_enable (bool yn, void *src);
void set_meter_point (MeterPoint, void* src);
sigc::signal<void> ModeChanged;
sigc::signal<void> DiskstreamChanged;
sigc::signal<void> FreezeChange;
protected:
Track (Session& sess, const XMLNode& node, DataType default_type = AUDIO);
virtual XMLNode& state (bool full) = 0;
virtual void passthru_silence (jack_nframes_t start_frame, jack_nframes_t end_frame,
jack_nframes_t nframes, jack_nframes_t offset, int declick, bool meter) = 0;
virtual uint32_t n_process_buffers () = 0;
Diskstream *_diskstream;
MeterPoint _saved_meter_point;
TrackMode _mode;
//private: (FIXME)
struct FreezeRecordInsertInfo {
FreezeRecordInsertInfo(XMLNode& st, boost::shared_ptr<Insert> ins)
: state (st), insert (ins) {}
XMLNode state;
boost::shared_ptr<Insert> insert;
PBD::ID id;
UndoAction memento;
};
struct FreezeRecord {
FreezeRecord()
: playlist(0)
, have_mementos(false)
{}
~FreezeRecord();
Playlist* playlist;
vector<FreezeRecordInsertInfo*> insert_info;
bool have_mementos;
FreezeState state;
};
struct RecEnableControllable : public PBD::Controllable {
RecEnableControllable (Track&);
void set_value (float);
float get_value (void) const;
Track& track;
};
//virtual void diskstream_record_enable_changed (void *src) = 0;
//virtual void diskstream_input_channel_changed (void *src) = 0;
//virtual void input_change_handler (void *src) = 0;
virtual void set_state_part_two () = 0;
FreezeRecord _freeze_record;
XMLNode* pending_state;
sigc::connection recenable_connection;
sigc::connection ic_connection;
RecEnableControllable _rec_enable_control;
bool _destructive;
};
}; /* namespace ARDOUR*/
#endif /* __ardour_track_h__ */

View File

@@ -243,6 +243,12 @@ namespace ARDOUR {
PeakDatum min;
PeakDatum max;
};
enum DataType {
NIL = 0,
AUDIO,
MIDI
};
}
std::istream& operator>>(std::istream& o, ARDOUR::SampleFormat& sf);

View File

@@ -1,5 +1,5 @@
/*
Copyright (C) 2000-2003 Paul Davis
Copyright (C) 2000-2006 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -14,8 +14,6 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: diskstream.cc 567 2006-06-07 14:54:12Z trutkin $
*/
#include <fstream>
@@ -23,6 +21,7 @@
#include <unistd.h>
#include <cmath>
#include <cerrno>
#include <cassert>
#include <string>
#include <climits>
#include <fcntl.h>
@@ -55,32 +54,30 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
jack_nframes_t AudioDiskstream::disk_io_chunk_frames;
size_t AudioDiskstream::_working_buffers_size = 0;
Sample* AudioDiskstream::_mixdown_buffer = 0;
gain_t* AudioDiskstream::_gain_buffer = 0;
char* AudioDiskstream::_conversion_buffer = 0;
sigc::signal<void,AudioDiskstream*> AudioDiskstream::AudioDiskstreamCreated;
sigc::signal<void,list<AudioFileSource*>*> AudioDiskstream::DeleteSources;
sigc::signal<void> AudioDiskstream::DiskOverrun;
sigc::signal<void> AudioDiskstream::DiskUnderrun;
AudioDiskstream::AudioDiskstream (Session &sess, const string &name, Flag flag)
: _name (name),
_session (sess)
AudioDiskstream::AudioDiskstream (Session &sess, const string &name, Diskstream::Flag flag)
: Diskstream(sess, name, flag)
, deprecated_io_node(NULL)
{
/* prevent any write sources from being created */
in_set_state = true;
init (flag);
init(flag);
use_new_playlist ();
in_set_state = false;
AudioDiskstreamCreated (this); /* EMIT SIGNAL */
DiskstreamCreated (this); /* EMIT SIGNAL */
}
AudioDiskstream::AudioDiskstream (Session& sess, const XMLNode& node)
: _session (sess)
: Diskstream(sess, node)
, deprecated_io_node(NULL)
{
in_set_state = true;
init (Recordable);
@@ -96,7 +93,7 @@ AudioDiskstream::AudioDiskstream (Session& sess, const XMLNode& node)
use_destructive_playlist ();
}
AudioDiskstreamCreated (this); /* EMIT SIGNAL */
DiskstreamCreated (this); /* EMIT SIGNAL */
}
void
@@ -129,43 +126,9 @@ AudioDiskstream::init_channel (ChannelInfo &chan)
void
AudioDiskstream::init (Flag f)
AudioDiskstream::init (Diskstream::Flag f)
{
_refcnt = 0;
_flags = f;
_io = 0;
_alignment_style = ExistingMaterial;
_persistent_alignment_style = ExistingMaterial;
first_input_change = true;
_playlist = 0;
i_am_the_modifier = 0;
g_atomic_int_set (&_record_enabled, 0);
was_recording = false;
capture_start_frame = 0;
capture_captured = 0;
_visible_speed = 1.0f;
_actual_speed = 1.0f;
_buffer_reallocation_required = false;
_seek_required = false;
first_recordable_frame = max_frames;
last_recordable_frame = max_frames;
_roll_delay = 0;
_capture_offset = 0;
_processed = false;
_slaved = false;
adjust_capture_position = 0;
last_possibly_recording = 0;
loop_location = 0;
wrap_buffer_size = 0;
speed_buffer_size = 0;
last_phase = 0;
phi = (uint64_t) (0x1000000);
file_frame = 0;
playback_sample = 0;
playback_distance = 0;
_read_data_count = 0;
_write_data_count = 0;
deprecated_io_node = 0;
Diskstream::init(f);
/* there are no channels at this point, so these
two calls just get speed_buffer_size and wrap_buffer
@@ -175,13 +138,8 @@ AudioDiskstream::init (Flag f)
set_block_size (_session.get_block_size());
allocate_temporary_buffers ();
pending_overwrite = false;
overwrite_frame = 0;
overwrite_queued = false;
input_change_pending = NoChange;
add_channel ();
_n_channels = 1;
assert(_n_channels == 1);
}
void
@@ -215,26 +173,33 @@ AudioDiskstream::~AudioDiskstream ()
{
Glib::Mutex::Lock lm (state_lock);
if (_playlist) {
_playlist->unref ();
}
for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan)
destroy_channel((*chan));
}
channels.clear();
}
void
AudioDiskstream::handle_input_change (IOChange change, void *src)
AudioDiskstream::allocate_working_buffers()
{
Glib::Mutex::Lock lm (state_lock);
assert(disk_io_frames() > 0);
if (!(input_change_pending & change)) {
input_change_pending = IOChange (input_change_pending|change);
_session.request_input_change_handling ();
}
_working_buffers_size = disk_io_frames();
_mixdown_buffer = new Sample[_working_buffers_size];
_gain_buffer = new gain_t[_working_buffers_size];
_conversion_buffer = new char[_working_buffers_size * 4];
}
void
AudioDiskstream::free_working_buffers()
{
delete _mixdown_buffer;
delete _gain_buffer;
delete _conversion_buffer;
_working_buffers_size = 0;
_mixdown_buffer = 0;
_gain_buffer = 0;
_conversion_buffer = 0;
}
void
@@ -332,9 +297,9 @@ AudioDiskstream::find_and_use_playlist (const string& name)
Playlist* pl;
AudioPlaylist* playlist;
if ((pl = _session.get_playlist (name)) == 0) {
error << string_compose(_("AudioDiskstream: Session doesn't know about a Playlist called \"%1\""), name) << endmsg;
return -1;
if ((pl = _session.playlist_by_name (name)) == 0) {
playlist = new AudioPlaylist(_session, name);
pl = playlist;
}
if ((playlist = dynamic_cast<AudioPlaylist*> (pl)) == 0) {
@@ -346,57 +311,15 @@ AudioDiskstream::find_and_use_playlist (const string& name)
}
int
AudioDiskstream::use_playlist (AudioPlaylist* playlist)
AudioDiskstream::use_playlist (Playlist* playlist)
{
{
Glib::Mutex::Lock lm (state_lock);
assert(dynamic_cast<AudioPlaylist*>(playlist));
if (playlist == _playlist) {
return 0;
}
plstate_connection.disconnect();
plmod_connection.disconnect ();
plgone_connection.disconnect ();
if (_playlist) {
_playlist->unref();
}
_playlist = playlist;
_playlist->ref();
if (!in_set_state && recordable()) {
reset_write_sources (false);
}
plstate_connection = _playlist->StateChanged.connect (mem_fun (*this, &AudioDiskstream::playlist_changed));
plmod_connection = _playlist->Modified.connect (mem_fun (*this, &AudioDiskstream::playlist_modified));
plgone_connection = _playlist->GoingAway.connect (mem_fun (*this, &AudioDiskstream::playlist_deleted));
}
if (!overwrite_queued) {
_session.request_overwrite_buffer (this);
overwrite_queued = true;
}
PlaylistChanged (); /* EMIT SIGNAL */
_session.set_dirty ();
Diskstream::use_playlist(playlist);
return 0;
}
void
AudioDiskstream::playlist_deleted (Playlist* pl)
{
/* this catches an ordering issue with session destruction. playlists
are destroyed before diskstreams. we have to invalidate any handles
we have to the playlist.
*/
_playlist = 0;
}
int
AudioDiskstream::use_new_playlist ()
{
@@ -424,6 +347,8 @@ AudioDiskstream::use_new_playlist ()
int
AudioDiskstream::use_copy_playlist ()
{
assert(audio_playlist());
if (destructive()) {
return 0;
}
@@ -438,7 +363,7 @@ AudioDiskstream::use_copy_playlist ()
newname = Playlist::bump_name (_playlist->name(), _session);
if ((playlist = new AudioPlaylist (*_playlist, newname)) != 0) {
if ((playlist = new AudioPlaylist (*audio_playlist(), newname)) != 0) {
playlist->set_orig_diskstream_id (id());
return use_playlist (playlist);
} else {
@@ -488,110 +413,13 @@ AudioDiskstream::use_destructive_playlist ()
for (n = 0, chan = channels.begin(); chan != channels.end(); ++chan, ++n) {
(*chan).write_source = dynamic_cast<AudioFileSource*>(&region->source (n));
assert((*chan).write_source);
(*chan).write_source->set_allow_remove_if_empty (false);
}
/* the source list will never be reset for a destructive track */
}
void
AudioDiskstream::set_io (IO& io)
{
_io = &io;
set_align_style_from_io ();
}
int
AudioDiskstream::set_name (string str, void *src)
{
if (str != _name) {
_playlist->set_name (str);
_name = str;
if (!in_set_state && recordable()) {
/* rename existing capture files so that they have the correct name */
return rename_write_sources ();
} else {
return -1;
}
}
return 0;
}
void
AudioDiskstream::set_speed (double sp)
{
_session.request_diskstream_speed (*this, sp);
/* to force a rebuffering at the right place */
playlist_modified();
}
bool
AudioDiskstream::realtime_set_speed (double sp, bool global)
{
bool changed = false;
double new_speed = sp * _session.transport_speed();
if (_visible_speed != sp) {
_visible_speed = sp;
changed = true;
}
if (new_speed != _actual_speed) {
jack_nframes_t required_wrap_size = (jack_nframes_t) floor (_session.get_block_size() *
fabs (new_speed)) + 1;
if (required_wrap_size > wrap_buffer_size) {
_buffer_reallocation_required = true;
}
_actual_speed = new_speed;
phi = (uint64_t) (0x1000000 * fabs(_actual_speed));
}
if (changed) {
if (!global) {
_seek_required = true;
}
speed_changed (); /* EMIT SIGNAL */
}
return _buffer_reallocation_required || _seek_required;
}
void
AudioDiskstream::non_realtime_set_speed ()
{
if (_buffer_reallocation_required)
{
Glib::Mutex::Lock lm (state_lock);
allocate_temporary_buffers ();
_buffer_reallocation_required = false;
}
if (_seek_required) {
if (speed() != 1.0f || speed() != -1.0f) {
seek ((jack_nframes_t) (_session.transport_frame() * (double) speed()), true);
}
else {
seek (_session.transport_frame(), true);
}
_seek_required = false;
}
}
void
AudioDiskstream::prepare ()
{
_processed = false;
playback_distance = 0;
}
void
AudioDiskstream::check_record_status (jack_nframes_t transport_frame, jack_nframes_t nframes, bool can_record)
{
@@ -755,7 +583,7 @@ AudioDiskstream::process (jack_nframes_t transport_frame, jack_nframes_t nframes
returns a non-zero value, in which case, ::commit should not be called.
*/
// If we can't take the state lock return.
// If we can't take the state lock return.
if (!state_lock.trylock()) {
return 1;
}
@@ -1011,13 +839,6 @@ AudioDiskstream::process (jack_nframes_t transport_frame, jack_nframes_t nframes
return ret;
}
void
AudioDiskstream::recover ()
{
state_lock.unlock();
_processed = false;
}
bool
AudioDiskstream::commit (jack_nframes_t nframes)
{
@@ -1156,16 +977,16 @@ AudioDiskstream::seek (jack_nframes_t frame, bool complete_refill)
/* can't rec-enable in destructive mode if transport is before start */
if (destructive() && record_enabled() && frame < _session.current_start_frame()) {
disengage_record_enable (this);
disengage_record_enable ();
}
playback_sample = frame;
file_frame = frame;
if (complete_refill) {
while ((ret = do_refill (0, 0, 0)) > 0);
while ((ret = do_refill_with_alloc ()) > 0) ;
} else {
ret = do_refill (0, 0, 0);
ret = do_refill_with_alloc ();
}
return ret;
@@ -1257,7 +1078,7 @@ AudioDiskstream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer,
this_read = min(cnt,this_read);
if (_playlist->read (buf+offset, mixdown_buffer, gain_buffer, workbuf, start, this_read, channel) != this_read) {
if (audio_playlist()->read (buf+offset, mixdown_buffer, gain_buffer, workbuf, start, this_read, channel) != this_read) {
error << string_compose(_("AudioDiskstream %1: cannot read %2 from playlist at frame %3"), _id, this_read,
start) << endmsg;
return -1;
@@ -1291,14 +1112,27 @@ AudioDiskstream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer,
}
int
AudioDiskstream::do_refill (Sample* mixdown_buffer, float* gain_buffer, char * workbuf)
AudioDiskstream::do_refill_with_alloc()
{
Sample* mix_buf = new Sample[disk_io_chunk_frames];
float* gain_buf = new float[disk_io_chunk_frames];
char* work_buf = new char[disk_io_chunk_frames * 4];
int ret = _do_refill(mix_buf, gain_buf, work_buf);
delete [] mix_buf;
delete [] gain_buf;
delete [] work_buf;
return ret;
}
int
AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer, char * workbuf)
{
int32_t ret = 0;
jack_nframes_t to_read;
RingBufferNPT<Sample>::rw_vector vector;
bool free_mixdown;
bool free_gain;
bool free_workbuf;
bool reversed = (_visible_speed * _session.transport_speed()) < 0.0f;
jack_nframes_t total_space;
jack_nframes_t zero_fill;
@@ -1306,6 +1140,10 @@ AudioDiskstream::do_refill (Sample* mixdown_buffer, float* gain_buffer, char * w
ChannelList::iterator i;
jack_nframes_t ts;
assert(mixdown_buffer);
assert(gain_buffer);
assert(workbuf);
channels.front().playback_buf->get_write_vector (&vector);
if ((total_space = vector.len[0] + vector.len[1]) == 0) {
@@ -1412,33 +1250,6 @@ AudioDiskstream::do_refill (Sample* mixdown_buffer, float* gain_buffer, char * w
zero_fill = 0;
}
}
/* Please note: the code to allocate buffers isn't run
during normal butler thread operation. Its there
for other times when we need to call do_refill()
from somewhere other than the butler thread.
*/
if (mixdown_buffer == 0) {
mixdown_buffer = new Sample[disk_io_chunk_frames];
free_mixdown = true;
} else {
free_mixdown = false;
}
if (gain_buffer == 0) {
gain_buffer = new float[disk_io_chunk_frames];
free_gain = true;
} else {
free_gain = false;
}
if (workbuf == 0) {
workbuf = new char[disk_io_chunk_frames * 4];
free_workbuf = true;
} else {
free_workbuf = false;
}
jack_nframes_t file_frame_tmp = 0;
@@ -1507,37 +1318,30 @@ AudioDiskstream::do_refill (Sample* mixdown_buffer, float* gain_buffer, char * w
file_frame = file_frame_tmp;
out:
if (free_mixdown) {
delete [] mixdown_buffer;
}
if (free_gain) {
delete [] gain_buffer;
}
if (free_workbuf) {
delete [] workbuf;
}
return ret;
}
/** Flush pending data to disk.
*
* Important note: this function will write *AT MOST* disk_io_chunk_frames
* of data to disk. it will never write more than that. If it writes that
* much and there is more than that waiting to be written, it will return 1,
* otherwise 0 on success or -1 on failure.
*
* If there is less than disk_io_chunk_frames to be written, no data will be
* written at all unless @a force_flush is true.
*/
int
AudioDiskstream::do_flush (char * workbuf, bool force_flush)
AudioDiskstream::do_flush (Session::RunContext context, bool force_flush)
{
char* workbuf = _session.conversion_buffer(context);
uint32_t to_write;
int32_t ret = 0;
RingBufferNPT<Sample>::rw_vector vector;
RingBufferNPT<CaptureTransition>::rw_vector transvec;
jack_nframes_t total;
/* important note: this function will write *AT MOST*
disk_io_chunk_frames of data to disk. it will never
write more than that. if its writes that much and there
is more than that waiting to be written, it will return 1,
otherwise 0 on success or -1 on failure.
if there is less than disk_io_chunk_frames to be written,
no data will be written at all unless `force_flush' is true.
*/
_write_data_count = 0;
@@ -1552,7 +1356,6 @@ AudioDiskstream::do_flush (char * workbuf, bool force_flush)
goto out;
}
/* if there are 2+ chunks of disk i/o possible for
this track, let the caller know so that it can arrange
for us to be called again, ASAP.
@@ -1656,21 +1459,6 @@ AudioDiskstream::do_flush (char * workbuf, bool force_flush)
return ret;
}
void
AudioDiskstream::playlist_changed (Change ignored)
{
playlist_modified ();
}
void
AudioDiskstream::playlist_modified ()
{
if (!i_am_the_modifier && !overwrite_queued) {
_session.request_overwrite_buffer (this);
overwrite_queued = true;
}
}
void
AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_capture)
{
@@ -1684,7 +1472,6 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca
ChannelList::iterator chan;
vector<CaptureInfo*>::iterator ci;
uint32_t n = 0;
list<AudioFileSource*>* deletion_list;
bool mark_write_completed = false;
finish_capture (true);
@@ -1694,7 +1481,7 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca
*/
while (more_work && !err) {
switch (do_flush ( _session.conversion_buffer(Session::TransportContext), true)) {
switch (do_flush (Session::TransportContext, true)) {
case 0:
more_work = false;
break;
@@ -1717,7 +1504,7 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca
ChannelList::iterator chan;
deletion_list = new list<AudioFileSource*>;
list<Source*>* deletion_list = new list<Source*>;
for ( chan = channels.begin(); chan != channels.end(); ++chan) {
@@ -1904,7 +1691,7 @@ AudioDiskstream::finish_capture (bool rec_monitors_input)
}
void
AudioDiskstream::set_record_enabled (bool yn, void* src)
AudioDiskstream::set_record_enabled (bool yn)
{
if (!recordable() || !_session.record_enabling_legal()) {
return;
@@ -1931,17 +1718,17 @@ AudioDiskstream::set_record_enabled (bool yn, void* src)
if (record_enabled() != yn) {
if (yn) {
engage_record_enable (src);
engage_record_enable ();
} else {
disengage_record_enable (src);
disengage_record_enable ();
}
}
}
void
AudioDiskstream::engage_record_enable (void* src)
AudioDiskstream::engage_record_enable ()
{
bool rolling = _session.transport_speed() != 0.0f;
bool rolling = _session.transport_speed() != 0.0f;
g_atomic_int_set (&_record_enabled, 1);
capturing_sources.clear ();
@@ -1958,11 +1745,11 @@ AudioDiskstream::engage_record_enable (void* src)
}
}
record_enable_changed (src); /* EMIT SIGNAL */
RecordEnableChanged (); /* EMIT SIGNAL */
}
void
AudioDiskstream::disengage_record_enable (void* src)
AudioDiskstream::disengage_record_enable ()
{
g_atomic_int_set (&_record_enabled, 0);
if (Config->get_use_hardware_monitoring()) {
@@ -1973,7 +1760,7 @@ AudioDiskstream::disengage_record_enable (void* src)
}
}
capturing_sources.clear ();
record_enable_changed (src); /* EMIT SIGNAL */
RecordEnableChanged (); /* EMIT SIGNAL */
}
@@ -1981,7 +1768,7 @@ XMLNode&
AudioDiskstream::get_state ()
{
XMLNode* node = new XMLNode ("AudioDiskstream");
char buf[64];
char buf[64] = "";
LocaleGuard lg (X_("POSIX"));
snprintf (buf, sizeof(buf), "0x%x", _flags);
@@ -2080,8 +1867,7 @@ AudioDiskstream::set_state (const XMLNode& node)
}
// create necessary extra channels
// we are always constructed with one
// and we always need one
// we are always constructed with one and we always need one
if (nchans > _n_channels) {
@@ -2311,23 +2097,6 @@ AudioDiskstream::monitor_input (bool yn)
}
}
void
AudioDiskstream::set_capture_offset ()
{
if (_io == 0) {
/* can't capture, so forget it */
return;
}
_capture_offset = _io->input_latency();
}
void
AudioDiskstream::set_persistent_align_style (AlignStyle a)
{
_persistent_alignment_style = a;
}
void
AudioDiskstream::set_align_style_from_io ()
{
@@ -2353,20 +2122,6 @@ AudioDiskstream::set_align_style_from_io ()
}
}
void
AudioDiskstream::set_align_style (AlignStyle a)
{
if (record_enabled() && _session.actively_recording()) {
return;
}
if (a != _alignment_style) {
_alignment_style = a;
AlignmentStyleChanged ();
}
}
int
AudioDiskstream::add_channel ()
{
@@ -2417,58 +2172,6 @@ AudioDiskstream::capture_buffer_load () const
(double) channels.front().capture_buf->bufsize());
}
int
AudioDiskstream::set_loop (Location *location)
{
if (location) {
if (location->start() >= location->end()) {
error << string_compose(_("Location \"%1\" not valid for track loop (start >= end)"), location->name()) << endl;
return -1;
}
}
loop_location = location;
LoopSet (location); /* EMIT SIGNAL */
return 0;
}
jack_nframes_t
AudioDiskstream::get_capture_start_frame (uint32_t n)
{
Glib::Mutex::Lock lm (capture_info_lock);
if (capture_info.size() > n) {
return capture_info[n]->start;
}
else {
return capture_start_frame;
}
}
jack_nframes_t
AudioDiskstream::get_captured_frames (uint32_t n)
{
Glib::Mutex::Lock lm (capture_info_lock);
if (capture_info.size() > n) {
return capture_info[n]->frames;
}
else {
return capture_captured;
}
}
void
AudioDiskstream::punch_in ()
{
}
void
AudioDiskstream::punch_out ()
{
}
int
AudioDiskstream::use_pending_capture_data (XMLNode& node)
{
@@ -2564,22 +2267,3 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node)
return 0;
}
void
AudioDiskstream::set_roll_delay (jack_nframes_t nframes)
{
_roll_delay = nframes;
}
void
AudioDiskstream::set_destructive (bool yn)
{
if (yn != destructive()) {
reset_write_sources (true, true);
if (yn) {
_flags |= Destructive;
} else {
_flags &= ~Destructive;
}
}
}

View File

@@ -243,16 +243,18 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, ch
for (vector<uint32_t>::iterator l = relevant_layers.begin(); l != relevant_layers.end(); ++l) {
// FIXME: Should be vector<AudioRegion*>
vector<Region*>& r (relevant_regions[*l]);
vector<Crossfade*>& x (relevant_xfades[*l]);
for (vector<Region*>::iterator i = r.begin(); i != r.end(); ++i) {
(*i)->read_at (buf, mixdown_buffer, gain_buffer, workbuf, start, cnt, chan_n, read_frames, skip_frames);
_read_data_count += (*i)->read_data_count();
AudioRegion* const ar = dynamic_cast<AudioRegion*>(*i);
assert(ar);
ar->read_at (buf, mixdown_buffer, gain_buffer, workbuf, start, cnt, chan_n, read_frames, skip_frames);
_read_data_count += ar->read_data_count();
}
for (vector<Crossfade*>::iterator i = x.begin(); i != x.end(); ++i) {
(*i)->read_at (buf, mixdown_buffer, gain_buffer, workbuf, start, cnt, chan_n);
/* don't JACK up _read_data_count, since its the same data as we just
@@ -880,38 +882,6 @@ AudioPlaylist::crossfade_changed (Change ignored)
notify_modified ();
}
void
AudioPlaylist::get_equivalent_regions (const AudioRegion& other, vector<AudioRegion*>& results)
{
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
AudioRegion* ar = dynamic_cast<AudioRegion*> (*i);
if (ar) {
if (Config->get_use_overlap_equivalency()) {
if (ar->overlap_equivalent (other)) {
results.push_back (ar);
} else if (ar->equivalent (other)) {
results.push_back (ar);
}
}
}
}
}
void
AudioPlaylist::get_region_list_equivalent_regions (const AudioRegion& other, vector<AudioRegion*>& results)
{
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
AudioRegion* ar = dynamic_cast<AudioRegion*> (*i);
if (ar && ar->region_list_equivalent (other)) {
results.push_back (ar);
}
}
}
bool
AudioPlaylist::region_changed (Change what_changed, Region* region)
{

View File

@@ -41,9 +41,7 @@ using namespace ARDOUR;
using namespace PBD;
AudioTrack::AudioTrack (Session& sess, string name, Route::Flag flag, TrackMode mode)
: Route (sess, name, 1, -1, -1, -1, flag),
diskstream (0),
_rec_enable_control (*this)
: Track (sess, name, flag, mode)
{
AudioDiskstream::Flag dflags = AudioDiskstream::Flag (0);
@@ -59,45 +57,34 @@ AudioTrack::AudioTrack (Session& sess, string name, Route::Flag flag, TrackMode
AudioDiskstream* ds = new AudioDiskstream (_session, name, dflags);
_declickable = true;
_freeze_record.state = NoFreeze;
_saved_meter_point = _meter_point;
_mode = mode;
set_diskstream (*ds, this);
}
AudioTrack::AudioTrack (Session& sess, const XMLNode& node)
: Route (sess, "to be renamed", 0, 0, -1, -1),
diskstream (0),
_rec_enable_control (*this)
: Track (sess, node)
{
_freeze_record.state = NoFreeze;
set_state (node);
_declickable = true;
_saved_meter_point = _meter_point;
}
AudioTrack::~AudioTrack ()
{
if (diskstream) {
diskstream->unref();
}
}
int
AudioTrack::deprecated_use_diskstream_connections ()
{
if (diskstream->deprecated_io_node == 0) {
AudioDiskstream& diskstream = audio_diskstream();
if (diskstream.deprecated_io_node == 0) {
return 0;
}
const XMLProperty* prop;
XMLNode& node (*diskstream->deprecated_io_node);
XMLNode& node (*diskstream.deprecated_io_node);
/* don't do this more than once. */
diskstream->deprecated_io_node = 0;
diskstream.deprecated_io_node = 0;
set_input_minimum (-1);
set_input_maximum (-1);
@@ -140,15 +127,15 @@ AudioTrack::deprecated_use_diskstream_connections ()
int
AudioTrack::set_diskstream (AudioDiskstream& ds, void *src)
{
if (diskstream) {
diskstream->unref();
if (_diskstream) {
_diskstream->unref();
}
diskstream = &ds.ref();
diskstream->set_io (*this);
diskstream->set_destructive (_mode == Destructive);
_diskstream = &ds.ref();
_diskstream->set_io (*this);
_diskstream->set_destructive (_mode == Destructive);
if (diskstream->deprecated_io_node) {
if (audio_diskstream().deprecated_io_node) {
if (!connecting_legal) {
ConnectingLegal.connect (mem_fun (*this, &AudioTrack::deprecated_use_diskstream_connections));
@@ -157,13 +144,13 @@ AudioTrack::set_diskstream (AudioDiskstream& ds, void *src)
}
}
diskstream->set_record_enabled (false, this);
diskstream->monitor_input (false);
_diskstream->set_record_enabled (false);
_diskstream->monitor_input (false);
ic_connection.disconnect();
ic_connection = input_changed.connect (mem_fun (*diskstream, &AudioDiskstream::handle_input_change));
ic_connection = input_changed.connect (mem_fun (*_diskstream, &Diskstream::handle_input_change));
diskstream_changed (src); /* EMIT SIGNAL */
DiskstreamChanged (); /* EMIT SIGNAL */
return 0;
}
@@ -173,8 +160,8 @@ AudioTrack::use_diskstream (string name)
{
AudioDiskstream *dstream;
if ((dstream = _session.diskstream_by_name (name)) == 0) {
error << string_compose(_("AudioTrack: diskstream \"%1\" not known by session"), name) << endmsg;
if ((dstream = dynamic_cast<AudioDiskstream*>(_session.diskstream_by_name (name))) == 0) {
error << string_compose(_("AudioTrack: audio diskstream \"%1\" not known by session"), name) << endmsg;
return -1;
}
@@ -186,53 +173,18 @@ AudioTrack::use_diskstream (const PBD::ID& id)
{
AudioDiskstream *dstream;
if ((dstream = _session.diskstream_by_id (id)) == 0) {
error << string_compose(_("AudioTrack: diskstream \"%1\" not known by session"), id) << endmsg;
if ((dstream = dynamic_cast<AudioDiskstream*>(_session.diskstream_by_id (id))) == 0) {
error << string_compose(_("AudioTrack: audio diskstream \"%1\" not known by session"), id) << endmsg;
return -1;
}
return set_diskstream (*dstream, this);
}
bool
AudioTrack::record_enabled () const
AudioDiskstream&
AudioTrack::audio_diskstream() 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)
{
Route::set_meter_point (p, src);
return *dynamic_cast<AudioDiskstream*>(_diskstream);
}
int
@@ -306,18 +258,6 @@ AudioTrack::set_state (const XMLNode& node)
return 0;
}
XMLNode&
AudioTrack::get_template ()
{
return state (false);
}
XMLNode&
AudioTrack::get_state ()
{
return state (true);
}
XMLNode&
AudioTrack::state(bool full_state)
{
@@ -348,7 +288,7 @@ AudioTrack::state(bool full_state)
/* Alignment: act as a proxy for the diskstream */
XMLNode* align_node = new XMLNode (X_("alignment"));
switch (diskstream->alignment_style()) {
switch (_diskstream->alignment_style()) {
case ExistingMaterial:
snprintf (buf, sizeof (buf), X_("existing"));
break;
@@ -379,7 +319,7 @@ AudioTrack::state(bool full_state)
diskstream.
*/
diskstream->id().print (buf);
_diskstream->id().print (buf);
root.add_property ("diskstream-id", buf);
return root;
@@ -451,9 +391,9 @@ AudioTrack::set_state_part_two ()
if ((prop = fnode->property (X_("style"))) != 0) {
if (prop->value() == "existing") {
diskstream->set_persistent_align_style (ExistingMaterial);
_diskstream->set_persistent_align_style (ExistingMaterial);
} else if (prop->value() == "capture") {
diskstream->set_persistent_align_style (CaptureTime);
_diskstream->set_persistent_align_style (CaptureTime);
}
}
}
@@ -463,7 +403,7 @@ AudioTrack::set_state_part_two ()
uint32_t
AudioTrack::n_process_buffers ()
{
return max ((uint32_t) diskstream->n_channels(), redirect_max_outs);
return max ((uint32_t) _diskstream->n_channels(), redirect_max_outs);
}
void
@@ -494,7 +434,7 @@ AudioTrack::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nf
return 0;
}
diskstream->check_record_status (start_frame, nframes, can_record);
audio_diskstream().check_record_status (start_frame, nframes, can_record);
bool send_silence;
@@ -513,7 +453,7 @@ AudioTrack::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nf
send_silence = true;
}
} else {
if (diskstream->record_enabled()) {
if (_diskstream->record_enabled()) {
if (Config->get_use_sw_monitoring()) {
send_silence = false;
} else {
@@ -561,7 +501,8 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
Sample* b;
Sample* tmpb;
jack_nframes_t transport_frame;
AudioDiskstream& diskstream = audio_diskstream();
{
Glib::RWLock::ReaderLock lm (redirect_lock, Glib::TRY_LOCK);
if (lm.locked()) {
@@ -587,13 +528,13 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
playback distance to zero, thus causing diskstream::commit
to do nothing.
*/
return diskstream->process (transport_frame, 0, 0, can_record, rec_monitors_input);
return diskstream.process (transport_frame, 0, 0, can_record, rec_monitors_input);
}
_silent = false;
apply_gain_automation = false;
if ((dret = diskstream->process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) {
if ((dret = diskstream.process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) {
silence (nframes, offset);
@@ -606,7 +547,7 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
just_meter_input (start_frame, end_frame, nframes, offset);
}
if (diskstream->record_enabled() && !can_record && !_session.get_auto_input()) {
if (diskstream.record_enabled() && !can_record && !_session.get_auto_input()) {
/* not actually recording, but we want to hear the input material anyway,
at least potentially (depending on monitoring options)
@@ -614,7 +555,7 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
passthru (start_frame, end_frame, nframes, offset, 0, true);
} else if ((b = diskstream->playback_buffer(0)) != 0) {
} else if ((b = diskstream.playback_buffer(0)) != 0) {
/*
XXX is it true that the earlier test on n_outputs()
@@ -636,8 +577,8 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
for (i = 0, n = 1; i < limit; ++i, ++n) {
memcpy (bufs[i], b, sizeof (Sample) * nframes);
if (n < diskstream->n_channels()) {
tmpb = diskstream->playback_buffer(n);
if (n < diskstream.n_channels()) {
tmpb = diskstream.playback_buffer(n);
if (tmpb!=0) {
b = tmpb;
}
@@ -646,7 +587,7 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
/* don't waste time with automation if we're recording or we've just stopped (yes it can happen) */
if (!diskstream->record_enabled() && _session.transport_rolling()) {
if (!diskstream.record_enabled() && _session.transport_rolling()) {
Glib::Mutex::Lock am (automation_lock, Glib::TRY_LOCK);
if (am.locked() && gain_automation_playback()) {
@@ -682,37 +623,7 @@ AudioTrack::silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jac
silence (nframes, offset);
return diskstream->process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input);
}
void
AudioTrack::toggle_monitor_input ()
{
for (vector<Port*>::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
(*i)->request_monitor_input(!(*i)->monitoring_input());
}
}
int
AudioTrack::set_name (string str, void *src)
{
int ret;
if (record_enabled() && _session.actively_recording()) {
/* this messes things up if done while recording */
return -1;
}
if (diskstream->set_name (str, src)) {
return -1;
}
/* save state so that the statefile fully reflects any filename changes */
if ((ret = IO::set_name (str, src)) == 0) {
_session.save_state ("");
}
return ret;
return audio_diskstream().process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input);
}
int
@@ -726,10 +637,15 @@ AudioTrack::export_stuff (vector<Sample*>& buffers, char * workbuf, uint32_t nbu
gain_t this_gain = _gain;
vector<Sample*>::iterator bi;
Sample * b;
AudioDiskstream& diskstream = audio_diskstream();
Glib::RWLock::ReaderLock rlock (redirect_lock);
if (diskstream->playlist()->read (buffers[0], mix_buffer, gain_buffer, workbuf, start, nframes) != nframes) {
// FIXME
AudioPlaylist* const apl = dynamic_cast<AudioPlaylist*>(diskstream.playlist());
assert(apl);
if (apl->read (buffers[0], mix_buffer, gain_buffer, workbuf, start, nframes) != nframes) {
return -1;
}
@@ -738,8 +654,8 @@ AudioTrack::export_stuff (vector<Sample*>& buffers, char * workbuf, uint32_t nbu
b = buffers[0];
++bi;
for (; bi != buffers.end(); ++bi, ++n) {
if (n < diskstream->n_channels()) {
if (diskstream->playlist()->read ((*bi), mix_buffer, gain_buffer, workbuf, start, nframes, n) != nframes) {
if (n < diskstream.n_channels()) {
if (apl->read ((*bi), mix_buffer, gain_buffer, workbuf, start, nframes, n) != nframes) {
return -1;
}
b = (*bi);
@@ -811,29 +727,6 @@ AudioTrack::export_stuff (vector<Sample*>& buffers, char * workbuf, uint32_t nbu
return 0;
}
void
AudioTrack::set_latency_delay (jack_nframes_t longest_session_latency)
{
Route::set_latency_delay (longest_session_latency);
diskstream->set_roll_delay (_roll_delay);
}
jack_nframes_t
AudioTrack::update_total_latency ()
{
_own_latency = 0;
for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
if ((*i)->active ()) {
_own_latency += (*i)->latency ();
}
}
set_port_latency (_own_latency);
return _own_latency;
}
void
AudioTrack::bounce (InterThreadInfo& itt)
{
@@ -858,8 +751,9 @@ AudioTrack::freeze (InterThreadInfo& itt)
string dir;
AudioRegion* region;
string region_name;
AudioDiskstream& diskstream = audio_diskstream();
if ((_freeze_record.playlist = diskstream->playlist()) == 0) {
if ((_freeze_record.playlist = dynamic_cast<AudioPlaylist*>(diskstream.playlist())) == 0) {
return;
}
@@ -881,7 +775,7 @@ AudioTrack::freeze (InterThreadInfo& itt)
}
if (n == (UINT_MAX-1)) {
error << string_compose (X_("There Are too many frozen versions of playlist \"%1\""
error << string_compose (X_("There are too many frozen versions of playlist \"%1\""
" to create another one"), _freeze_record.playlist->name())
<< endmsg;
return;
@@ -927,13 +821,13 @@ AudioTrack::freeze (InterThreadInfo& itt)
(AudioRegion::Flag) (AudioRegion::WholeFile|AudioRegion::DefaultFlags),
false);
new_playlist->set_orig_diskstream_id (diskstream->id());
new_playlist->set_orig_diskstream_id (diskstream.id());
new_playlist->add_region (*region, 0);
new_playlist->set_frozen (true);
region->set_locked (true);
diskstream->use_playlist (dynamic_cast<AudioPlaylist*>(new_playlist));
diskstream->set_record_enabled (false, this);
diskstream.use_playlist (dynamic_cast<AudioPlaylist*>(new_playlist));
diskstream.set_record_enabled (false);
_freeze_record.state = Frozen;
FreezeChange(); /* EMIT SIGNAL */
@@ -943,7 +837,7 @@ void
AudioTrack::unfreeze ()
{
if (_freeze_record.playlist) {
diskstream->use_playlist (_freeze_record.playlist);
audio_diskstream().use_playlist (_freeze_record.playlist);
if (_freeze_record.have_mementos) {
@@ -971,46 +865,3 @@ AudioTrack::unfreeze ()
FreezeChange (); /* EMIT SIGNAL */
}
AudioTrack::FreezeRecord::~FreezeRecord ()
{
for (vector<FreezeRecordInsertInfo*>::iterator i = insert_info.begin(); i != insert_info.end(); ++i) {
delete *i;
}
}
AudioTrack::FreezeState
AudioTrack::freeze_state() const
{
return _freeze_record.state;
}
AudioTrack::RecEnableControllable::RecEnableControllable (AudioTrack& s)
: track (s)
{
}
void
AudioTrack::RecEnableControllable::set_value (float val)
{
bool bval = ((val >= 0.5f) ? true: false);
track.set_record_enable (bval, this);
}
float
AudioTrack::RecEnableControllable::get_value (void) const
{
if (track.record_enabled()) { return 1.0f; }
return 0.0f;
}
void
AudioTrack::set_mode (TrackMode m)
{
if (diskstream) {
if (_mode != m) {
_mode = m;
diskstream->set_destructive (m == Destructive);
ModeChanged();
}
}
}

View File

@@ -26,6 +26,7 @@
#include <pbd/pthread_utils.h>
#include <ardour/audioengine.h>
#include <ardour/buffer.h>
#include <ardour/port.h>
#include <ardour/session.h>
#include <ardour/cycle_timer.h>
@@ -42,8 +43,8 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
jack_nframes_t Port::short_over_length = 2;
jack_nframes_t Port::long_over_length = 10;
jack_nframes_t Port::_short_over_length = 2;
jack_nframes_t Port::_long_over_length = 10;
AudioEngine::AudioEngine (string client_name)
{
@@ -274,8 +275,8 @@ AudioEngine::process_callback (jack_nframes_t nframes)
Port *port = (*i);
bool x;
if (port->last_monitor != (x = port->monitoring_input ())) {
port->last_monitor = x;
if (port->_last_monitor != (x = port->monitoring_input ())) {
port->_last_monitor = x;
/* XXX I think this is dangerous, due to
a likely mutex in the signal handlers ...
*/
@@ -388,18 +389,19 @@ AudioEngine::remove_session ()
}
Port *
AudioEngine::register_audio_input_port (const string& portname)
AudioEngine::register_input_port (DataType type, const string& portname)
{
if (!_running) {
if (!_has_run) {
fatal << _("register audio input port called before engine was started") << endmsg;
fatal << _("register input port called before engine was started") << endmsg;
/*NOTREACHED*/
} else {
return 0;
}
}
jack_port_t *p = jack_port_register (_jack, portname.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
jack_port_t *p = jack_port_register (_jack, portname.c_str(),
Buffer::type_to_jack_type(type), JackPortIsInput, 0);
if (p) {
@@ -419,11 +421,11 @@ AudioEngine::register_audio_input_port (const string& portname)
}
Port *
AudioEngine::register_audio_output_port (const string& portname)
AudioEngine::register_output_port (DataType type, const string& portname)
{
if (!_running) {
if (!_has_run) {
fatal << _("register audio output port called before engine was started") << endmsg;
fatal << _("register output port called before engine was started") << endmsg;
/*NOTREACHED*/
} else {
return 0;
@@ -432,7 +434,8 @@ AudioEngine::register_audio_output_port (const string& portname)
jack_port_t *p;
if ((p = jack_port_register (_jack, portname.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)) != 0) {
if ((p = jack_port_register (_jack, portname.c_str(),
Buffer::type_to_jack_type(type), JackPortIsOutput, 0)) != 0) {
Port *newport = new Port (p);
ports.insert (ports.begin(), newport);
return newport;
@@ -446,6 +449,7 @@ AudioEngine::register_audio_output_port (const string& portname)
return 0;
}
int
AudioEngine::unregister_port (Port *port)
{
@@ -458,7 +462,7 @@ AudioEngine::unregister_port (Port *port)
if (port) {
int ret = jack_port_unregister (_jack, port->port);
int ret = jack_port_unregister (_jack, port->_port);
if (ret == 0) {
@@ -549,7 +553,7 @@ AudioEngine::disconnect (Port *port)
}
}
int ret = jack_port_disconnect (_jack, port->port);
int ret = jack_port_disconnect (_jack, port->_port);
if (ret == 0) {
remove_connections_for (port);
@@ -699,7 +703,6 @@ AudioEngine::n_physical_inputs () const
}
string
AudioEngine::get_nth_physical (uint32_t n, int flag)
{
const char ** ports;
@@ -747,7 +750,7 @@ AudioEngine::get_port_total_latency (const Port& port)
}
}
return jack_port_get_total_latency (_jack, port.port);
return jack_port_get_total_latency (_jack, port._port);
}
void
@@ -825,7 +828,7 @@ AudioEngine::remove_all_ports ()
if (_jack) {
for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) {
jack_port_unregister (_jack, (*i)->port);
jack_port_unregister (_jack, (*i)->_port);
}
}
@@ -948,7 +951,7 @@ AudioEngine::reconnect_to_jack ()
short_name = long_name.substr (long_name.find_last_of (':') + 1);
if (((*i)->port = jack_port_register (_jack, short_name.c_str(), (*i)->type(), (*i)->flags(), 0)) == 0) {
if (((*i)->_port = jack_port_register (_jack, short_name.c_str(), (*i)->type(), (*i)->flags(), 0)) == 0) {
error << string_compose (_("could not reregister %1"), (*i)->name()) << endmsg;
break;
} else {
@@ -963,7 +966,7 @@ AudioEngine::reconnect_to_jack ()
if (i != ports.end()) {
for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) {
jack_port_unregister (_jack, (*i)->port);
jack_port_unregister (_jack, (*i)->_port);
}
return -1;
}

View File

@@ -48,13 +48,13 @@ using namespace ARDOUR;
/* a Session will reset these to its chosen defaults by calling AudioRegion::set_default_fade() */
Change AudioRegion::FadeInChanged = ARDOUR::new_change();
Change AudioRegion::FadeOutChanged = ARDOUR::new_change();
Change AudioRegion::FadeInActiveChanged = ARDOUR::new_change();
Change AudioRegion::FadeOutActiveChanged = ARDOUR::new_change();
Change AudioRegion::FadeInChanged = ARDOUR::new_change();
Change AudioRegion::FadeOutChanged = ARDOUR::new_change();
Change AudioRegion::FadeInActiveChanged = ARDOUR::new_change();
Change AudioRegion::FadeOutActiveChanged = ARDOUR::new_change();
Change AudioRegion::EnvelopeActiveChanged = ARDOUR::new_change();
Change AudioRegion::ScaleAmplitudeChanged = ARDOUR::new_change();
Change AudioRegion::EnvelopeChanged = ARDOUR::new_change();
Change AudioRegion::EnvelopeChanged = ARDOUR::new_change();
AudioRegionState::AudioRegionState (string why)
: RegionState (why),
@@ -633,12 +633,6 @@ AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buff
return to_read;
}
XMLNode&
AudioRegion::get_state ()
{
return state (true);
}
XMLNode&
AudioRegion::state (bool full)
{
@@ -1139,24 +1133,22 @@ AudioRegion::master_source_names ()
}
bool
AudioRegion::region_list_equivalent (const AudioRegion& other) const
AudioRegion::source_equivalent (const Region& o) const
{
return size_equivalent (other) && source_equivalent (other) && _name == other._name;
}
const AudioRegion* other = dynamic_cast<const AudioRegion*>(&o);
if (!other)
return false;
bool
AudioRegion::source_equivalent (const AudioRegion& other) const
{
SourceList::const_iterator i;
SourceList::const_iterator io;
for (i = sources.begin(), io = other.sources.begin(); i != sources.end() && io != other.sources.end(); ++i, ++io) {
for (i = sources.begin(), io = other->sources.begin(); i != sources.end() && io != other->sources.end(); ++i, ++io) {
if ((*i)->id() != (*io)->id()) {
return false;
}
}
for (i = master_sources.begin(), io = other.master_sources.begin(); i != master_sources.end() && io != other.master_sources.end(); ++i, ++io) {
for (i = master_sources.begin(), io = other->master_sources.begin(); i != master_sources.end() && io != other->master_sources.end(); ++i, ++io) {
if ((*i)->id() != (*io)->id()) {
return false;
}
@@ -1165,27 +1157,6 @@ AudioRegion::source_equivalent (const AudioRegion& other) const
return true;
}
bool
AudioRegion::overlap_equivalent (const AudioRegion& other) const
{
return coverage (other.first_frame(), other.last_frame()) != OverlapNone;
}
bool
AudioRegion::equivalent (const AudioRegion& other) const
{
return _start == other._start &&
_position == other._position &&
_length == other._length;
}
bool
AudioRegion::size_equivalent (const AudioRegion& other) const
{
return _start == other._start &&
_length == other._length;
}
int
AudioRegion::apply (AudioFilter& filter)
{

View File

@@ -44,12 +44,12 @@ Auditioner::Auditioner (Session& s)
defer_pan_reset ();
if (left.length()) {
add_output_port (left, this);
add_output_port (left, this, AUDIO);
}
if (right.length()) {
disk_stream().add_channel();
add_output_port (right, this);
audio_diskstream().add_channel();
add_output_port (right, this, AUDIO);
}
allow_pan_reset ();
@@ -67,8 +67,12 @@ Auditioner::~Auditioner ()
AudioPlaylist&
Auditioner::prepare_playlist ()
{
diskstream->playlist()->clear (false, false);
return *diskstream->playlist();
// FIXME auditioner is still audio-only
AudioPlaylist* const apl = dynamic_cast<AudioPlaylist*>(_diskstream->playlist());
assert(apl);
apl->clear (false, false);
return *apl;
}
void
@@ -82,13 +86,13 @@ Auditioner::audition_current_playlist ()
}
Glib::Mutex::Lock lm (lock);
diskstream->seek (0);
length = diskstream->playlist()->get_maximum_extent();
_diskstream->seek (0);
length = _diskstream->playlist()->get_maximum_extent();
current_frame = 0;
/* force a panner reset now that we have all channels */
_panner->reset (n_outputs(), diskstream->n_channels());
_panner->reset (n_outputs(), _diskstream->n_channels());
g_atomic_int_set (&_active, 1);
}
@@ -108,23 +112,23 @@ Auditioner::audition_region (AudioRegion& region)
the_region = new AudioRegion (region);
the_region->set_position (0, this);
diskstream->playlist()->clear (true, false);
diskstream->playlist()->add_region (*the_region, 0, 1, false);
_diskstream->playlist()->clear (true, false);
_diskstream->playlist()->add_region (*the_region, 0, 1, false);
while (diskstream->n_channels() < the_region->n_channels()) {
diskstream->add_channel ();
while (_diskstream->n_channels() < the_region->n_channels()) {
audio_diskstream().add_channel ();
}
while (diskstream->n_channels() > the_region->n_channels()) {
diskstream->remove_channel ();
while (_diskstream->n_channels() > the_region->n_channels()) {
audio_diskstream().remove_channel ();
}
/* force a panner reset now that we have all channels */
_panner->reset (n_outputs(), diskstream->n_channels());
_panner->reset (n_outputs(), _diskstream->n_channels());
length = the_region->length();
diskstream->seek (0);
_diskstream->seek (0);
current_frame = 0;
g_atomic_int_set (&_active, 1);
}
@@ -143,14 +147,14 @@ Auditioner::play_audition (jack_nframes_t nframes)
this_nframes = min (nframes, length - current_frame);
diskstream->prepare ();
_diskstream->prepare ();
if ((ret = roll (this_nframes, current_frame, current_frame + nframes, 0, false, false, false)) != 0) {
silence (nframes, 0);
return ret;
}
need_butler = diskstream->commit (this_nframes);
need_butler = _diskstream->commit (this_nframes);
current_frame += this_nframes;
if (current_frame >= length) {

401
libs/ardour/diskstream.cc Normal file
View File

@@ -0,0 +1,401 @@
/*
Copyright (C) 2000-2006 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: diskstream.cc 567 2006-06-07 14:54:12Z trutkin $
*/
#include <fstream>
#include <cstdio>
#include <unistd.h>
#include <cmath>
#include <cerrno>
#include <string>
#include <climits>
#include <fcntl.h>
#include <cstdlib>
#include <ctime>
#include <sys/stat.h>
#include <sys/mman.h>
#include <pbd/error.h>
#include <pbd/basename.h>
#include <glibmm/thread.h>
#include <pbd/xml++.h>
#include <ardour/ardour.h>
#include <ardour/audioengine.h>
#include <ardour/diskstream.h>
#include <ardour/utils.h>
#include <ardour/configuration.h>
#include <ardour/audiofilesource.h>
#include <ardour/destructive_filesource.h>
#include <ardour/send.h>
#include <ardour/playlist.h>
#include <ardour/cycle_timer.h>
#include <ardour/region.h>
#include "i18n.h"
#include <locale.h>
using namespace std;
using namespace ARDOUR;
using namespace PBD;
jack_nframes_t Diskstream::disk_io_chunk_frames = 0;
sigc::signal<void,Diskstream*> Diskstream::DiskstreamCreated;
sigc::signal<void,list<Source*>*> Diskstream::DeleteSources;
sigc::signal<void> Diskstream::DiskOverrun;
sigc::signal<void> Diskstream::DiskUnderrun;
Diskstream::Diskstream (Session &sess, const string &name, Flag flag)
: _name (name)
, _session (sess)
, _playlist(NULL)
{
init (flag);
}
Diskstream::Diskstream (Session& sess, const XMLNode& node)
: _session (sess)
, _playlist(NULL)
{
init (Recordable);
}
void
Diskstream::init (Flag f)
{
_refcnt = 0;
_flags = f;
_io = 0;
_alignment_style = ExistingMaterial;
_persistent_alignment_style = ExistingMaterial;
first_input_change = true;
i_am_the_modifier = 0;
g_atomic_int_set (&_record_enabled, 0);
was_recording = false;
capture_start_frame = 0;
capture_captured = 0;
_visible_speed = 1.0f;
_actual_speed = 1.0f;
_buffer_reallocation_required = false;
_seek_required = false;
first_recordable_frame = max_frames;
last_recordable_frame = max_frames;
_roll_delay = 0;
_capture_offset = 0;
_processed = false;
_slaved = false;
adjust_capture_position = 0;
last_possibly_recording = 0;
loop_location = 0;
wrap_buffer_size = 0;
speed_buffer_size = 0;
last_phase = 0;
phi = (uint64_t) (0x1000000);
file_frame = 0;
playback_sample = 0;
playback_distance = 0;
_read_data_count = 0;
_write_data_count = 0;
pending_overwrite = false;
overwrite_frame = 0;
overwrite_queued = false;
input_change_pending = NoChange;
_n_channels = 0;
}
Diskstream::~Diskstream ()
{
// Taken by derived class destrctors.. should assure locked here somehow?
//Glib::Mutex::Lock lm (state_lock);
if (_playlist)
_playlist->unref ();
}
void
Diskstream::set_io (IO& io)
{
_io = &io;
set_align_style_from_io ();
}
void
Diskstream::handle_input_change (IOChange change, void *src)
{
Glib::Mutex::Lock lm (state_lock);
if (!(input_change_pending & change)) {
input_change_pending = IOChange (input_change_pending|change);
_session.request_input_change_handling ();
}
}
void
Diskstream::non_realtime_set_speed ()
{
if (_buffer_reallocation_required)
{
Glib::Mutex::Lock lm (state_lock);
allocate_temporary_buffers ();
_buffer_reallocation_required = false;
}
if (_seek_required) {
if (speed() != 1.0f || speed() != -1.0f) {
seek ((jack_nframes_t) (_session.transport_frame() * (double) speed()), true);
}
else {
seek (_session.transport_frame(), true);
}
_seek_required = false;
}
}
bool
Diskstream::realtime_set_speed (double sp, bool global)
{
bool changed = false;
double new_speed = sp * _session.transport_speed();
if (_visible_speed != sp) {
_visible_speed = sp;
changed = true;
}
if (new_speed != _actual_speed) {
jack_nframes_t required_wrap_size = (jack_nframes_t) floor (_session.get_block_size() *
fabs (new_speed)) + 1;
if (required_wrap_size > wrap_buffer_size) {
_buffer_reallocation_required = true;
}
_actual_speed = new_speed;
phi = (uint64_t) (0x1000000 * fabs(_actual_speed));
}
if (changed) {
if (!global) {
_seek_required = true;
}
SpeedChanged (); /* EMIT SIGNAL */
}
return _buffer_reallocation_required || _seek_required;
}
void
Diskstream::prepare ()
{
_processed = false;
playback_distance = 0;
}
void
Diskstream::recover ()
{
state_lock.unlock();
_processed = false;
}
void
Diskstream::set_capture_offset ()
{
if (_io == 0) {
/* can't capture, so forget it */
return;
}
_capture_offset = _io->input_latency();
}
void
Diskstream::set_align_style (AlignStyle a)
{
if (record_enabled() && _session.actively_recording()) {
return;
}
if (a != _alignment_style) {
_alignment_style = a;
AlignmentStyleChanged ();
}
}
int
Diskstream::set_loop (Location *location)
{
if (location) {
if (location->start() >= location->end()) {
error << string_compose(_("Location \"%1\" not valid for track loop (start >= end)"), location->name()) << endl;
return -1;
}
}
loop_location = location;
LoopSet (location); /* EMIT SIGNAL */
return 0;
}
jack_nframes_t
Diskstream::get_capture_start_frame (uint32_t n)
{
Glib::Mutex::Lock lm (capture_info_lock);
if (capture_info.size() > n) {
return capture_info[n]->start;
}
else {
return capture_start_frame;
}
}
jack_nframes_t
Diskstream::get_captured_frames (uint32_t n)
{
Glib::Mutex::Lock lm (capture_info_lock);
if (capture_info.size() > n) {
return capture_info[n]->frames;
}
else {
return capture_captured;
}
}
void
Diskstream::set_roll_delay (jack_nframes_t nframes)
{
_roll_delay = nframes;
}
void
Diskstream::set_speed (double sp)
{
_session.request_diskstream_speed (*this, sp);
/* to force a rebuffering at the right place */
playlist_modified();
}
int
Diskstream::use_playlist (Playlist* playlist)
{
{
Glib::Mutex::Lock lm (state_lock);
if (playlist == _playlist) {
return 0;
}
plstate_connection.disconnect();
plmod_connection.disconnect ();
plgone_connection.disconnect ();
if (_playlist) {
_playlist->unref();
}
_playlist = playlist;
_playlist->ref();
if (!in_set_state && recordable()) {
reset_write_sources (false);
}
plstate_connection = _playlist->StateChanged.connect (mem_fun (*this, &Diskstream::playlist_changed));
plmod_connection = _playlist->Modified.connect (mem_fun (*this, &Diskstream::playlist_modified));
plgone_connection = _playlist->GoingAway.connect (mem_fun (*this, &Diskstream::playlist_deleted));
}
if (!overwrite_queued) {
_session.request_overwrite_buffer (this);
overwrite_queued = true;
}
PlaylistChanged (); /* EMIT SIGNAL */
_session.set_dirty ();
return 0;
}
void
Diskstream::playlist_changed (Change ignored)
{
playlist_modified ();
}
void
Diskstream::playlist_modified ()
{
if (!i_am_the_modifier && !overwrite_queued) {
_session.request_overwrite_buffer (this);
overwrite_queued = true;
}
}
void
Diskstream::playlist_deleted (Playlist* pl)
{
/* this catches an ordering issue with session destruction. playlists
are destroyed before diskstreams. we have to invalidate any handles
we have to the playlist.
*/
_playlist = 0;
}
int
Diskstream::set_name (string str)
{
if (str != _name) {
assert(playlist());
playlist()->set_name (str);
_name = str;
if (!in_set_state && recordable()) {
/* rename existing capture files so that they have the correct name */
return rename_write_sources ();
} else {
return -1;
}
}
return 0;
}
void
Diskstream::set_destructive (bool yn)
{
if (yn != destructive()) {
reset_write_sources (true, true);
if (yn) {
_flags |= Destructive;
} else {
_flags &= ~Destructive;
}
}
}

View File

@@ -97,11 +97,15 @@ static bool sort_ports_by_name (Port* a, Port* b)
}
/** @param default_type The type of port that will be created by ensure_io
* and friends if no type is explicitly requested (to avoid breakage).
*/
IO::IO (Session& s, string name,
int input_min, int input_max, int output_min, int output_max)
int input_min, int input_max, int output_min, int output_max,
DataType default_type)
: _session (s),
_name (name),
_default_type(default_type),
_gain_control (*this),
_gain_automation_curve (0.0, 2.0, 1.0),
_input_minimum (input_min),
@@ -781,11 +785,20 @@ IO::remove_output_port (Port* port, void* src)
return -1;
}
/** Add an output port.
*
* @param destination Name of input port to connect new port to.
* @param src Source for emitted ConfigurationChanged signal.
* @param type Data type of port. Default value (NIL) will use this IO's default type.
*/
int
IO::add_output_port (string destination, void* src)
IO::add_output_port (string destination, void* src, DataType type)
{
Port* our_port;
char buf[64];
char name[64];
if (type == NIL)
type = _default_type;
{
Glib::Mutex::Lock em(_session.engine().process_lock());
@@ -799,14 +812,15 @@ IO::add_output_port (string destination, void* src)
/* Create a new output port */
// FIXME: naming scheme for differently typed ports?
if (_output_maximum == 1) {
snprintf (buf, sizeof (buf), _("%s/out"), _name.c_str());
snprintf (name, sizeof (name), _("%s/out"), _name.c_str());
} else {
snprintf (buf, sizeof (buf), _("%s/out %u"), _name.c_str(), find_output_port_hole());
snprintf (name, sizeof (name), _("%s/out %u"), _name.c_str(), find_output_port_hole());
}
if ((our_port = _session.engine().register_audio_output_port (buf)) == 0) {
error << string_compose(_("IO: cannot register output port %1"), buf) << endmsg;
if ((our_port = _session.engine().register_output_port (type, name)) == 0) {
error << string_compose(_("IO: cannot register output port %1"), name) << endmsg;
return -1;
}
@@ -882,11 +896,21 @@ IO::remove_input_port (Port* port, void* src)
return -1;
}
/** Add an input port.
*
* @param type Data type of port. The appropriate Jack port type, and @ref Port will be created.
* @param destination Name of input port to connect new port to.
* @param src Source for emitted ConfigurationChanged signal.
*/
int
IO::add_input_port (string source, void* src)
IO::add_input_port (string source, void* src, DataType type)
{
Port* our_port;
char buf[64];
char name[64];
if (type == NIL)
type = _default_type;
{
Glib::Mutex::Lock em (_session.engine().process_lock());
@@ -900,14 +924,15 @@ IO::add_input_port (string source, void* src)
/* Create a new input port */
// FIXME: naming scheme for differently typed ports?
if (_input_maximum == 1) {
snprintf (buf, sizeof (buf), _("%s/in"), _name.c_str());
snprintf (name, sizeof (name), _("%s/in"), _name.c_str());
} else {
snprintf (buf, sizeof (buf), _("%s/in %u"), _name.c_str(), find_input_port_hole());
snprintf (name, sizeof (name), _("%s/in %u"), _name.c_str(), find_input_port_hole());
}
if ((our_port = _session.engine().register_audio_input_port (buf)) == 0) {
error << string_compose(_("IO: cannot register input port %1"), buf) << endmsg;
if ((our_port = _session.engine().register_input_port (type, name)) == 0) {
error << string_compose(_("IO: cannot register input port %1"), name) << endmsg;
return -1;
}
@@ -1001,7 +1026,7 @@ IO::ensure_inputs_locked (uint32_t n, bool clear, void* src)
char buf[64];
/* Create a new input port */
/* Create a new input port (of the default type) */
if (_input_maximum == 1) {
snprintf (buf, sizeof (buf), _("%s/in"), _name.c_str());
@@ -1012,7 +1037,7 @@ IO::ensure_inputs_locked (uint32_t n, bool clear, void* src)
try {
if ((input_port = _session.engine().register_audio_input_port (buf)) == 0) {
if ((input_port = _session.engine().register_input_port (_default_type, buf)) == 0) {
error << string_compose(_("IO: cannot register input port %1"), buf) << endmsg;
return -1;
}
@@ -1101,7 +1126,7 @@ IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src)
out_changed = true;
}
/* create any necessary new ports */
/* create any necessary new ports (of the default type) */
while (_ninputs < nin) {
@@ -1117,7 +1142,7 @@ IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src)
}
try {
if ((port = _session.engine().register_audio_input_port (buf)) == 0) {
if ((port = _session.engine().register_input_port (_default_type, buf)) == 0) {
error << string_compose(_("IO: cannot register input port %1"), buf) << endmsg;
return -1;
}
@@ -1150,7 +1175,7 @@ IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src)
}
try {
if ((port = _session.engine().register_audio_output_port (buf)) == 0) {
if ((port = _session.engine().register_output_port (_default_type, buf)) == 0) {
error << string_compose(_("IO: cannot register output port %1"), buf) << endmsg;
return -1;
}
@@ -1275,7 +1300,7 @@ IO::ensure_outputs_locked (uint32_t n, bool clear, void* src)
snprintf (buf, sizeof (buf), _("%s/out %u"), _name.c_str(), find_output_port_hole());
}
if ((output_port = _session.engine().register_audio_output_port (buf)) == 0) {
if ((output_port = _session.engine().register_output_port (_default_type, buf)) == 0) {
error << string_compose(_("IO: cannot register output port %1"), buf) << endmsg;
return -1;
}

View File

@@ -598,6 +598,31 @@ Playlist::remove_region_internal (Region *region, bool delay_sort)
return -1;
}
void
Playlist::get_equivalent_regions (const Region& other, vector<Region*>& results)
{
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
if (Config->get_use_overlap_equivalency()) {
if ((*i)->overlap_equivalent (other)) {
results.push_back ((*i));
} else if ((*i)->equivalent (other)) {
results.push_back ((*i));
}
}
}
}
void
Playlist::get_region_list_equivalent_regions (const Region& other, vector<Region*>& results)
{
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
if ((*i) && (*i)->region_list_equivalent (other)) {
results.push_back (*i);
}
}
}
void
Playlist::partition (jack_nframes_t start, jack_nframes_t end, bool just_top_level)
{

View File

@@ -24,15 +24,15 @@ using namespace ARDOUR;
using namespace std;
Port::Port (jack_port_t *p)
: port (p)
: _port (p)
{
if (port == 0) {
if (_port == 0) {
throw failed_constructor();
}
_flags = JackPortFlags (jack_port_flags (port));
_type = jack_port_type (port);
_name = jack_port_name (port);
_flags = JackPortFlags (jack_port_flags (_port));
_type = jack_port_type (_port);
_name = jack_port_name (_port);
reset ();
}
@@ -42,9 +42,9 @@ Port::reset ()
{
reset_buffer ();
last_monitor = false;
silent = false;
metering = 0;
_last_monitor = false;
_silent = false;
_metering = 0;
reset_meters ();
}
@@ -54,7 +54,7 @@ Port::set_name (string str)
{
int ret;
if ((ret = jack_port_set_name (port, str.c_str())) == 0) {
if ((ret = jack_port_set_name (_port, str.c_str())) == 0) {
_name = str;
}

View File

@@ -39,13 +39,13 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
Change Region::FadeChanged = ARDOUR::new_change ();
Change Region::FadeChanged = ARDOUR::new_change ();
Change Region::SyncOffsetChanged = ARDOUR::new_change ();
Change Region::MuteChanged = ARDOUR::new_change ();
Change Region::OpacityChanged = ARDOUR::new_change ();
Change Region::LockChanged = ARDOUR::new_change ();
Change Region::LayerChanged = ARDOUR::new_change ();
Change Region::HiddenChanged = ARDOUR::new_change ();
Change Region::MuteChanged = ARDOUR::new_change ();
Change Region::OpacityChanged = ARDOUR::new_change ();
Change Region::LockChanged = ARDOUR::new_change ();
Change Region::LayerChanged = ARDOUR::new_change ();
Change Region::HiddenChanged = ARDOUR::new_change ();
sigc::signal<void,Region *> Region::CheckNewRegion;
@@ -990,3 +990,30 @@ Region::set_last_layer_op (uint64_t when)
{
_last_layer_op = when;
}
bool
Region::overlap_equivalent (const Region& other) const
{
return coverage (other.first_frame(), other.last_frame()) != OverlapNone;
}
bool
Region::equivalent (const Region& other) const
{
return _start == other._start &&
_position == other._position &&
_length == other._length;
}
bool
Region::size_equivalent (const Region& other) const
{
return _start == other._start &&
_length == other._length;
}
bool
Region::region_list_equivalent (const Region& other) const
{
return size_equivalent (other) && source_equivalent (other) && _name == other._name;
}

View File

@@ -20,11 +20,13 @@
#include <cmath>
#include <fstream>
#include <cassert>
#include <sigc++/bind.h>
#include <pbd/xml++.h>
#include <ardour/timestamps.h>
#include <ardour/buffer.h>
#include <ardour/audioengine.h>
#include <ardour/route.h>
#include <ardour/insert.h>
@@ -50,8 +52,8 @@ using namespace PBD;
uint32_t Route::order_key_cnt = 0;
Route::Route (Session& sess, string name, int input_min, int input_max, int output_min, int output_max, Flag flg)
: IO (sess, name, input_min, input_max, output_min, output_max),
Route::Route (Session& sess, string name, int input_min, int input_max, int output_min, int output_max, Flag flg, DataType default_type)
: IO (sess, name, input_min, input_max, output_min, output_max, default_type),
_flags (flg),
_solo_control (*this, ToggleControllable::SoloControl),
_mute_control (*this, ToggleControllable::MuteControl)
@@ -1330,6 +1332,9 @@ Route::state(bool full_state)
snprintf (buf, sizeof (buf), "0x%x", _flags);
node->add_property("flags", buf);
}
node->add_property("default-type", Buffer::type_to_string(_default_type));
node->add_property("active", _active?"yes":"no");
node->add_property("muted", _muted?"yes":"no");
node->add_property("soloed", _soloed?"yes":"no");
@@ -1503,6 +1508,11 @@ Route::set_state (const XMLNode& node)
} else {
_flags = Flag (0);
}
if ((prop = node.property ("default-type")) != 0) {
_default_type = Buffer::type_from_string(prop->value());
assert(_default_type != NIL);
}
if ((prop = node.property ("phase-invert")) != 0) {
set_phase_invert(prop->value()=="yes"?true:false, this);

View File

@@ -397,6 +397,8 @@ Session::~Session ()
delete [] (i->second);
}
AudioDiskstream::free_working_buffers();
#undef TRACK_DESTRUCTION
#ifdef TRACK_DESTRUCTION
cerr << "delete named selections\n";
@@ -440,10 +442,10 @@ Session::~Session ()
}
#ifdef TRACK_DESTRUCTION
cerr << "delete audio_diskstreams\n";
cerr << "delete diskstreams\n";
#endif /* TRACK_DESTRUCTION */
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ) {
AudioDiskstreamList::iterator tmp;
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ) {
DiskstreamList::iterator tmp;
tmp = i;
++tmp;
@@ -860,7 +862,7 @@ Session::playlist_length_changed (Playlist* pl)
}
void
Session::diskstream_playlist_changed (AudioDiskstream* dstream)
Session::diskstream_playlist_changed (Diskstream* dstream)
{
Playlist *playlist;
@@ -940,7 +942,7 @@ Session::set_auto_input (bool yn)
The rarity and short potential lock duration makes this "OK"
*/
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if ((*i)->record_enabled ()) {
//cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (!auto_input);
@@ -958,7 +960,7 @@ Session::reset_input_monitor_state ()
{
if (transport_rolling()) {
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if ((*i)->record_enabled ()) {
//cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (Config->get_use_hardware_monitoring() && !auto_input);
@@ -966,7 +968,7 @@ Session::reset_input_monitor_state ()
}
} else {
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if ((*i)->record_enabled ()) {
//cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (Config->get_use_hardware_monitoring());
@@ -1047,7 +1049,7 @@ Session::auto_loop_changed (Location* location)
}
else if (seamless_loop && !loop_changing) {
// schedule a locate-roll to refill the audio_diskstreams at the
// schedule a locate-roll to refill the diskstreams at the
// previous loop end
loop_changing = true;
@@ -1244,7 +1246,7 @@ Session::enable_record ()
*/
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if ((*i)->record_enabled ()) {
(*i)->monitor_input (true);
}
@@ -1279,7 +1281,7 @@ Session::disable_record (bool rt_context, bool force)
*/
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if ((*i)->record_enabled ()) {
(*i)->monitor_input (false);
}
@@ -1306,7 +1308,7 @@ Session::step_back_from_record ()
*/
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if (auto_input && (*i)->record_enabled ()) {
//cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (false);
@@ -1476,7 +1478,7 @@ Session::set_block_size (jack_nframes_t nframes)
(*i)->set_block_size (nframes);
}
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
(*i)->set_block_size (nframes);
}
@@ -1760,7 +1762,7 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
track->set_control_outs (cports);
}
track->diskstream_changed.connect (mem_fun (this, &Session::resort_routes_proxy));
track->DiskstreamChanged.connect (mem_fun (this, &Session::resort_routes));
add_route (track);
@@ -1805,7 +1807,7 @@ Session::new_audio_route (int input_channels, int output_channels)
} while (n < (UINT_MAX-1));
try {
shared_ptr<Route> bus (new Route (*this, bus_name, -1, -1, -1, -1));
shared_ptr<Route> bus (new Route (*this, bus_name, -1, -1, -1, -1, Route::Flag(0), AUDIO));
if (bus->ensure_io (input_channels, output_channels, false, this)) {
error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
@@ -1858,7 +1860,7 @@ Session::new_audio_route (int input_channels, int output_channels)
}
catch (failed_constructor &err) {
error << _("Session: could not create new route.") << endmsg;
error << _("Session: could not create new audio route.") << endmsg;
return shared_ptr<Route> ((Route*) 0);
}
}
@@ -1893,14 +1895,14 @@ Session::add_route (shared_ptr<Route> route)
}
void
Session::add_diskstream (AudioDiskstream* dstream)
Session::add_diskstream (Diskstream* dstream)
{
/* need to do this in case we're rolling at the time, to prevent false underruns */
dstream->do_refill(0, 0, 0);
dstream->do_refill_with_alloc();
{
Glib::RWLock::WriterLock lm (diskstream_lock);
audio_diskstreams.push_back (dstream);
diskstreams.push_back (dstream);
}
/* take a reference to the diskstream, preventing it from
@@ -1920,7 +1922,7 @@ Session::add_diskstream (AudioDiskstream* dstream)
set_dirty();
save_state (_current_snapshot_name);
AudioDiskstreamAdded (dstream); /* EMIT SIGNAL */
DiskstreamAdded (dstream); /* EMIT SIGNAL */
}
void
@@ -1957,18 +1959,19 @@ Session::remove_route (shared_ptr<Route> route)
/* writer goes out of scope, forces route list update */
}
// FIXME: audio specific
AudioTrack* at;
AudioDiskstream* ds = 0;
if ((at = dynamic_cast<AudioTrack*>(route.get())) != 0) {
ds = &at->disk_stream();
ds = &at->audio_diskstream();
}
if (ds) {
{
Glib::RWLock::WriterLock lm (diskstream_lock);
audio_diskstreams.remove (ds);
diskstreams.remove (ds);
}
ds->unref ();
@@ -2261,7 +2264,7 @@ Session::get_maximum_extent () const
ensure atomicity.
*/
for (AudioDiskstreamList::const_iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::const_iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
Playlist* pl = (*i)->playlist();
if ((me = pl->get_maximum_extent()) > max) {
max = me;
@@ -2271,12 +2274,12 @@ Session::get_maximum_extent () const
return max;
}
AudioDiskstream *
Diskstream *
Session::diskstream_by_name (string name)
{
Glib::RWLock::ReaderLock lm (diskstream_lock);
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if ((*i)->name() == name) {
return* i;
}
@@ -2285,12 +2288,12 @@ Session::diskstream_by_name (string name)
return 0;
}
AudioDiskstream *
Diskstream *
Session::diskstream_by_id (const PBD::ID& id)
{
Glib::RWLock::ReaderLock lm (diskstream_lock);
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if ((*i)->id() == id) {
return *i;
}
@@ -2555,18 +2558,10 @@ Session::find_whole_file_parent (AudioRegion& child)
}
void
Session::find_equivalent_playlist_regions (AudioRegion& region, vector<AudioRegion*>& result)
Session::find_equivalent_playlist_regions (Region& region, vector<Region*>& result)
{
for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
AudioPlaylist* pl;
if ((pl = dynamic_cast<AudioPlaylist*>(*i)) == 0) {
continue;
}
pl->get_region_list_equivalent_regions (region, result);
}
for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i)
(*i)->get_region_list_equivalent_regions (region, result);
}
int
@@ -2618,7 +2613,7 @@ Session::remove_last_capture ()
Glib::RWLock::ReaderLock lm (diskstream_lock);
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
list<Region*>& l = (*i)->last_capture_regions();
if (!l.empty()) {
@@ -2925,18 +2920,6 @@ Session::create_audio_source_for_session (AudioDiskstream& ds, uint32_t chan, bo
/* Playlist management */
Playlist *
Session::get_playlist (string name)
{
Playlist* ret = 0;
if ((ret = playlist_by_name (name)) == 0) {
ret = new AudioPlaylist (*this, name);
}
return ret;
}
Playlist *
Session::playlist_by_name (string name)
{
@@ -3066,11 +3049,14 @@ Session::audition_playlist ()
}
void
Session::audition_region (AudioRegion& r)
Session::audition_region (Region& r)
{
Event* ev = new Event (Event::Audition, Event::Add, Event::Immediate, 0, 0.0);
ev->set_ptr (&r);
queue_event (ev);
AudioRegion* ar = dynamic_cast<AudioRegion*>(&r);
if (ar) {
Event* ev = new Event (Event::Audition, Event::Add, Event::Immediate, 0, 0.0);
ev->set_ptr (ar);
queue_event (ev);
}
}
void
@@ -3155,12 +3141,12 @@ Session::set_all_mute (bool yn)
}
uint32_t
Session::n_audio_diskstreams () const
Session::n_diskstreams () const
{
Glib::RWLock::ReaderLock lm (diskstream_lock);
uint32_t n = 0;
for (AudioDiskstreamList::const_iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::const_iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if (!(*i)->hidden()) {
n++;
}
@@ -3168,17 +3154,6 @@ Session::n_audio_diskstreams () const
return n;
}
void
Session::foreach_audio_diskstream (void (AudioDiskstream::*func)(void))
{
Glib::RWLock::ReaderLock lm (diskstream_lock);
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
if (!(*i)->hidden()) {
((*i)->*func)();
}
}
}
void
Session::graph_reordered ()
{
@@ -3198,7 +3173,7 @@ Session::graph_reordered ()
reflect any changes in latencies within the graph.
*/
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
(*i)->set_capture_offset ();
}
}
@@ -3481,7 +3456,7 @@ Session::reset_native_file_format ()
//RWLockMonitor lm1 (route_lock, true, __LINE__, __FILE__);
Glib::RWLock::ReaderLock lm2 (diskstream_lock);
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
(*i)->reset_write_sources (false);
}
}
@@ -3592,7 +3567,7 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf
/* call tree *MUST* hold route_lock */
if ((playlist = track.disk_stream().playlist()) == 0) {
if ((playlist = track.diskstream().playlist()) == 0) {
goto out;
}
@@ -3602,7 +3577,7 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf
goto out;
}
nchans = track.disk_stream().n_channels();
nchans = track.audio_diskstream().n_channels();
dir = discover_best_sound_dir ();

Some files were not shown because too many files have changed in this diff Show More