summaryrefslogtreecommitdiff
path: root/libs/ardour
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2008-12-12 14:43:24 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2008-12-12 14:43:24 +0000
commitbc89fe0147c04b67141936d109c00dfd4d69cc4b (patch)
tree544ff450c40fe1f43853a8420228a26f27f1eafb /libs/ardour
parent30daaebaa2d90d6b0e8673143ccc3cacd7bd1753 (diff)
most of the 2.X->3.0 commit (up to rev 4299) except for gtk2_ardour/editor_canvas.cc; builds and runs and does a few specific things but expect it to be buggy for a while yet
git-svn-id: svn://localhost/ardour2/branches/3.0@4313 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/ardour')
-rw-r--r--libs/ardour/analyser.cc2
-rw-r--r--libs/ardour/ardour/audio_buffer.h13
-rw-r--r--libs/ardour/ardour/audioregion.h19
-rw-r--r--libs/ardour/ardour/automation_control.h4
-rw-r--r--libs/ardour/ardour/automation_list.h4
-rw-r--r--libs/ardour/ardour/configuration_vars.h2
-rw-r--r--libs/ardour/ardour/osc.h23
-rw-r--r--libs/ardour/ardour/region.h6
-rw-r--r--libs/ardour/ardour/region_factory.h5
-rw-r--r--libs/ardour/ardour/route.h5
-rw-r--r--libs/ardour/ardour/session.h23
-rw-r--r--libs/ardour/ardour/slave.h1
-rw-r--r--libs/ardour/ardour/svn_revision.h4
-rw-r--r--libs/ardour/ardour/track.h3
-rw-r--r--libs/ardour/audio_track.cc89
-rw-r--r--libs/ardour/audio_unit.cc11
-rw-r--r--libs/ardour/audioengine.cc6
-rw-r--r--libs/ardour/audioregion.cc143
-rw-r--r--libs/ardour/coreaudiosource.cc100
-rw-r--r--libs/ardour/crossfade.cc59
-rw-r--r--libs/ardour/export_channel_configuration.cc3
-rw-r--r--libs/ardour/globals.cc6
-rw-r--r--libs/ardour/import.cc17
-rw-r--r--libs/ardour/io.cc6
-rw-r--r--libs/ardour/mtc_slave.cc13
-rw-r--r--libs/ardour/osc.cc91
-rw-r--r--libs/ardour/panner.cc15
-rw-r--r--libs/ardour/plugin_manager.cc4
-rw-r--r--libs/ardour/rb_effect.cc4
-rw-r--r--libs/ardour/region.cc152
-rw-r--r--libs/ardour/region_factory.cc31
-rw-r--r--libs/ardour/reverse.cc5
-rw-r--r--libs/ardour/route.cc81
-rw-r--r--libs/ardour/send.cc37
-rw-r--r--libs/ardour/session.cc140
-rw-r--r--libs/ardour/session_butler.cc2
-rw-r--r--libs/ardour/session_export.cc1
-rw-r--r--libs/ardour/session_midi.cc5
-rw-r--r--libs/ardour/session_process.cc13
-rw-r--r--libs/ardour/session_state.cc20
-rw-r--r--libs/ardour/session_transport.cc13
-rw-r--r--libs/ardour/sndfileimportable.cc1
-rw-r--r--libs/ardour/sndfilesource.cc9
-rw-r--r--libs/ardour/source_factory.cc2
-rw-r--r--libs/ardour/utils.cc2
45 files changed, 965 insertions, 230 deletions
diff --git a/libs/ardour/analyser.cc b/libs/ardour/analyser.cc
index 2e14c74b86..28eeeb190c 100644
--- a/libs/ardour/analyser.cc
+++ b/libs/ardour/analyser.cc
@@ -75,7 +75,7 @@ Analyser::queue_source_for_analysis (boost::shared_ptr<Source> src, bool force)
void
Analyser::work ()
{
- PBD::ThreadCreated (pthread_self(), string ("analyser-") + to_string (pthread_self(), std::dec));
+ PBD::notify_gui_about_thread_creation (pthread_self(), string ("analyser-") + to_string (pthread_self(), std::dec));
while (true) {
analysis_queue_lock.lock ();
diff --git a/libs/ardour/ardour/audio_buffer.h b/libs/ardour/ardour/audio_buffer.h
index 71eaf60ade..9a41e8e093 100644
--- a/libs/ardour/ardour/audio_buffer.h
+++ b/libs/ardour/ardour/audio_buffer.h
@@ -78,6 +78,19 @@ public:
_silent = ( (src.silent() && _silent) || (_silent && gain_coeff == 0) );
}
+
+ /** Accumulate (add) @a len frames FROM THE START OF @a src into self at @a offset
+ * scaling by @a gain_coeff */
+ void accumulate_with_gain_from(const Sample* src_raw, nframes_t len, nframes_t offset, gain_t gain_coeff) {
+ assert(_capacity > 0);
+ assert(offset + len <= _capacity);
+
+ Sample* const dst_raw = _data + offset;
+
+ mix_buffers_with_gain (dst_raw, src_raw, len, gain_coeff);
+
+ _silent = (_silent && gain_coeff == 0);
+ }
void apply_gain(gain_t gain, nframes_t len, nframes_t offset=0) {
apply_gain_to_buffer (_data + offset, len, gain);
diff --git a/libs/ardour/ardour/audioregion.h b/libs/ardour/ardour/audioregion.h
index b8cde44b77..5ebe22e312 100644
--- a/libs/ardour/ardour/audioregion.h
+++ b/libs/ardour/ardour/audioregion.h
@@ -56,6 +56,10 @@ class AudioRegion : public Region
~AudioRegion();
+ void copy_settings (boost::shared_ptr<const AudioRegion>);
+
+ bool source_equivalent (boost::shared_ptr<const Region>) const;
+
bool speed_mismatch (float) const;
boost::shared_ptr<AudioSource> audio_source (uint32_t n=0) const;
@@ -78,8 +82,17 @@ class AudioRegion : public Region
uint32_t chan_n=0, double samples_per_unit= 1.0) const;
/* Readable interface */
+
+ enum ReadOps {
+ ReadOpsNone = 0x0,
+ ReadOpsOwnAutomation = 0x1,
+ ReadOpsOwnScaling = 0x2,
+ ReadOpsCount = 0x4,
+ ReadOpsFades = 0x8
+ };
virtual nframes64_t read (Sample*, nframes64_t pos, nframes64_t cnt, int channel) const;
+ virtual nframes64_t read_with_ops (Sample*, nframes64_t pos, nframes64_t cnt, int channel, ReadOps rops) const;
virtual nframes64_t readable_length() const { return length(); }
virtual nframes_t read_at (Sample *buf, Sample *mixdown_buf,
@@ -151,11 +164,14 @@ class AudioRegion : public Region
private:
friend class RegionFactory;
+ friend class Crossfade;
AudioRegion (boost::shared_ptr<AudioSource>, nframes_t start, nframes_t length);
AudioRegion (boost::shared_ptr<AudioSource>, nframes_t start, nframes_t length, const string& name, layer_t = 0, Region::Flag flags = Region::DefaultFlags);
AudioRegion (const SourceList &, nframes_t start, nframes_t length, const string& name, layer_t = 0, Region::Flag flags = Region::DefaultFlags);
AudioRegion (boost::shared_ptr<const AudioRegion>, nframes_t start, nframes_t length, const string& name, layer_t = 0, Region::Flag flags = Region::DefaultFlags);
+ AudioRegion (boost::shared_ptr<const AudioRegion>, const SourceList&, nframes_t length, const string& name, layer_t = 0, Region::Flag flags = Region::DefaultFlags);
+ AudioRegion (boost::shared_ptr<const AudioRegion>);
AudioRegion (boost::shared_ptr<AudioSource>, const XMLNode&);
AudioRegion (SourceList &, const XMLNode&);
@@ -174,7 +190,7 @@ class AudioRegion : public Region
uint32_t chan_n = 0,
nframes_t read_frames = 0,
nframes_t skip_frames = 0,
- bool raw = false) const;
+ ReadOps readops = ReadOps (~0)) const;
void recompute_at_start ();
void recompute_at_end ();
@@ -201,7 +217,6 @@ class AudioRegion : public Region
/* default constructor for derived (compound) types */
AudioRegion (Session& s, nframes_t, nframes_t, std::string name);
- AudioRegion (boost::shared_ptr<const AudioRegion>);
int set_live_state (const XMLNode&, Change&, bool send);
};
diff --git a/libs/ardour/ardour/automation_control.h b/libs/ardour/ardour/automation_control.h
index db481b2f99..4cb6d1a79a 100644
--- a/libs/ardour/ardour/automation_control.h
+++ b/libs/ardour/ardour/automation_control.h
@@ -59,6 +59,10 @@ public:
return ((ARDOUR::AutomationList*)_list.get())->automation_state();
}
+ inline void set_automation_state(AutoState as) {
+ return ((ARDOUR::AutomationList*)_list.get())->set_automation_state(as);
+ }
+
inline void start_touch() {
return ((ARDOUR::AutomationList*)_list.get())->start_touch();
}
diff --git a/libs/ardour/ardour/automation_list.h b/libs/ardour/ardour/automation_list.h
index d5aff74ab9..923967448c 100644
--- a/libs/ardour/ardour/automation_list.h
+++ b/libs/ardour/ardour/automation_list.h
@@ -42,12 +42,12 @@ class AutomationList : public PBD::StatefulDestructible, public Evoral::ControlL
public:
AutomationList (Evoral::Parameter id);
AutomationList (const XMLNode&, Evoral::Parameter id);
+ AutomationList (const AutomationList&);
+ AutomationList (const AutomationList&, double start, double end);
~AutomationList();
virtual boost::shared_ptr<Evoral::ControlList> create(Evoral::Parameter id);
- AutomationList (const AutomationList&);
- AutomationList (const AutomationList&, double start, double end);
AutomationList& operator= (const AutomationList&);
bool operator== (const AutomationList&);
diff --git a/libs/ardour/ardour/configuration_vars.h b/libs/ardour/ardour/configuration_vars.h
index 5565e20401..bbf766d877 100644
--- a/libs/ardour/ardour/configuration_vars.h
+++ b/libs/ardour/ardour/configuration_vars.h
@@ -95,6 +95,7 @@ CONFIG_VARIABLE (bool, solo_latched, "solo-latched", true)
CONFIG_VARIABLE (bool, latched_record_enable, "latched-record-enable", false)
CONFIG_VARIABLE (bool, all_safe, "all-safe", false)
CONFIG_VARIABLE (bool, show_solo_mutes, "show-solo-mutes", false)
+CONFIG_VARIABLE (bool, solo_mute_override, "solo-mute-override", false)
CONFIG_VARIABLE (bool, tape_machine_mode, "tape-machine-mode", false)
/* click */
@@ -161,6 +162,7 @@ CONFIG_VARIABLE (uint32_t, periodic_safety_backup_interval, "periodic-safety-bac
CONFIG_VARIABLE (float, automation_interval, "automation-interval", 50)
CONFIG_VARIABLE (bool, sync_all_route_ordering, "sync-all-route-ordering", true)
CONFIG_VARIABLE (bool, only_copy_imported_files, "only-copy-imported-files", true)
+CONFIG_VARIABLE (bool, new_plugins_active, "new-plugins-active", true)
CONFIG_VARIABLE (std::string, keyboard_layout, "keyboard-layout", "ansi")
CONFIG_VARIABLE (std::string, default_bindings, "default-bindings", "ardour")
CONFIG_VARIABLE (bool, default_narrow_ms, "default-narrow_ms", false)
diff --git a/libs/ardour/ardour/osc.h b/libs/ardour/ardour/osc.h
index d7c2f4bd85..33759feb91 100644
--- a/libs/ardour/ardour/osc.h
+++ b/libs/ardour/ardour/osc.h
@@ -120,6 +120,29 @@ class OSC : public BasicUI, public sigc::trackable
PATH_CALLBACK1(set_transport_speed,f,);
PATH_CALLBACK1(access_action,s,&);
+
+#define PATH_CALLBACK2(name,arg1type,arg2type) \
+ static int _ ## name (const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data) { \
+ return static_cast<OSC*>(user_data)->cb_ ## name (path, types, argv, argc, data); \
+ } \
+ int cb_ ## name (const char *path, const char *types, lo_arg **argv, int argc, void *data) { \
+ if (argc > 1) { \
+ name (argv[0]->arg1type, argv[1]->arg2type); \
+ } \
+ return 0; \
+ }
+
+ PATH_CALLBACK2(route_mute,i,i);
+ PATH_CALLBACK2(route_solo,i,i);
+ PATH_CALLBACK2(route_recenable,i,i);
+ PATH_CALLBACK2(route_set_gain_abs,i,f);
+ PATH_CALLBACK2(route_set_gain_dB,i,f);
+
+ int route_mute (int rid, int yn);
+ int route_solo (int rid, int yn);
+ int route_recenable (int rid, int yn);
+ int route_set_gain_abs (int rid, float level);
+ int route_set_gain_dB (int rid, float dB);
};
}
diff --git a/libs/ardour/ardour/region.h b/libs/ardour/ardour/region.h
index d3c8341623..66f5d2be35 100644
--- a/libs/ardour/ardour/region.h
+++ b/libs/ardour/ardour/region.h
@@ -131,8 +131,9 @@ class Region
nframes_t sync_offset(int& dir) const;
nframes_t sync_position() const;
+ nframes_t sync_point () const;
- nframes_t adjust_to_sync (nframes_t);
+ nframes_t adjust_to_sync (nframes_t) const;
/* first_frame() is an alias; last_frame() just hides some math */
@@ -264,6 +265,7 @@ class Region
const string& name, DataType type, layer_t = 0, Flag flags = DefaultFlags);
Region (boost::shared_ptr<const Region>, nframes_t start, nframes_t length, const string& name, layer_t = 0, Flag flags = DefaultFlags);
+ Region (boost::shared_ptr<const Region>, nframes_t length, const string& name, layer_t = 0, Flag flags = DefaultFlags);
Region (boost::shared_ptr<const Region>);
Region (boost::shared_ptr<Source> src, const XMLNode&);
Region (const SourceList& srcs, const XMLNode&);
@@ -271,6 +273,8 @@ class Region
Region (Session& s, nframes_t start, nframes_t length, const string& name, DataType, layer_t = 0, Flag flags = DefaultFlags);
protected:
+ void copy_stuff (boost::shared_ptr<const Region>, nframes_t start, nframes_t length, const string& name, layer_t, Flag flags);
+
XMLNode& get_short_state (); /* used only by Session */
void send_change (Change);
diff --git a/libs/ardour/ardour/region_factory.h b/libs/ardour/ardour/region_factory.h
index 12437ba998..b88f3b225a 100644
--- a/libs/ardour/ardour/region_factory.h
+++ b/libs/ardour/ardour/region_factory.h
@@ -48,11 +48,12 @@ class RegionFactory {
*/
static boost::shared_ptr<Region> create (boost::shared_ptr<Region>, nframes_t start,
- nframes_t length, std::string name,
+ nframes_t length, const std::string& name,
layer_t = 0, Region::Flag flags = Region::DefaultFlags, bool announce = true);
static boost::shared_ptr<Region> create (boost::shared_ptr<AudioRegion>, nframes_t start,
- nframes_t length, std::string name,
+ nframes_t length, const std::string& name,
layer_t = 0, Region::Flag flags = Region::DefaultFlags, bool announce = true);
+ static boost::shared_ptr<Region> create (boost::shared_ptr<Region>, const SourceList&, const string& name, layer_t = 0, Region::Flag flags = Region::DefaultFlags, bool announce = true);
static boost::shared_ptr<Region> create (boost::shared_ptr<Source>, nframes_t start, nframes_t length, const string& name, layer_t = 0, Region::Flag flags = Region::DefaultFlags, bool announce = true);
static boost::shared_ptr<Region> create (const SourceList &, nframes_t start, nframes_t length, const string& name, layer_t = 0, Region::Flag flags = Region::DefaultFlags, bool announce = true);
static boost::shared_ptr<Region> create (Session&, XMLNode&, bool);
diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h
index f963d3b2cf..28d15b7090 100644
--- a/libs/ardour/ardour/route.h
+++ b/libs/ardour/ardour/route.h
@@ -107,6 +107,8 @@ class Route : public IO
/* end of vfunc-based API */
+ void shift (nframes64_t, nframes64_t);
+
/* override IO::set_gain() to provide group control */
void set_gain (gain_t val, void *src);
@@ -117,7 +119,7 @@ class Route : public IO
void set_solo_safe (bool yn, void *src);
bool solo_safe() const { return _solo_safe; }
-
+
void set_mute (bool yn, void *src);
bool muted() const { return _muted; }
bool solo_muted() const { return desired_solo_gain == 0.0; }
@@ -262,6 +264,7 @@ class Route : public IO
protected:
friend class Session;
+ void catch_up_on_solo_mute_override ();
void set_solo_mute (bool yn);
void set_block_size (nframes_t nframes);
bool has_external_redirects() const;
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index 017a78a015..16db305f94 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -413,6 +413,10 @@ class Session : public PBD::StatefulDestructible
double frames_per_smpte_frame() const { return _frames_per_smpte_frame; }
nframes_t smpte_frames_per_hour() const { return _smpte_frames_per_hour; }
+ MIDI::byte get_mtc_smpte_bits() const {
+ return mtc_smpte_bits; /* encoding of SMTPE type for MTC */
+ }
+
float smpte_frames_per_second() const;
bool smpte_drop_frames() const;
@@ -610,6 +614,7 @@ class Session : public PBD::StatefulDestructible
string doing_what;
/* control info */
+ uint32_t total;
SrcQuality quality;
volatile bool freeze;
std::vector<Glib::ustring> paths;
@@ -617,7 +622,6 @@ class Session : public PBD::StatefulDestructible
/* result */
SourceList sources;
-
};
void import_audiofiles (import_status&);
@@ -964,6 +968,10 @@ class Session : public PBD::StatefulDestructible
void add_controllable (boost::shared_ptr<PBD::Controllable>);
void remove_controllable (PBD::Controllable*);
+ /* metadata */
+
+ SessionMetadata & metadata () { return *_metadata; }
+
protected:
friend class AudioEngine;
void set_block_size (nframes_t nframes);
@@ -1457,6 +1465,7 @@ class Session : public PBD::StatefulDestructible
void route_mute_changed (void *src);
void route_solo_changed (void *src, boost::weak_ptr<Route>);
void catch_up_on_solo ();
+ void catch_up_on_solo_mute_override ();
void update_route_solo_state ();
void modify_solo_mute (bool, bool);
void strip_portname_for_solo (string& portname);
@@ -1701,6 +1710,12 @@ class Session : public PBD::StatefulDestructible
uint32_t n_physical_outputs;
uint32_t n_physical_inputs;
+ uint32_t n_physical_audio_outputs;
+ uint32_t n_physical_audio_inputs;
+
+ uint32_t n_physical_midi_outputs;
+ uint32_t n_physical_midi_inputs;
+
int find_all_sources (std::string path, std::set<std::string>& result);
int find_all_sources_across_snapshots (std::set<std::string>& result, bool exclude_this_snapshot);
@@ -1728,8 +1743,10 @@ class Session : public PBD::StatefulDestructible
/* Metadata */
SessionMetadata * _metadata;
- public:
- SessionMetadata & metadata () { return *_metadata; }
+
+ /* used in ::audible_frame() */
+
+ mutable bool have_looped;
};
} // namespace ARDOUR
diff --git a/libs/ardour/ardour/slave.h b/libs/ardour/ardour/slave.h
index ff8f48cd38..ffeacd3017 100644
--- a/libs/ardour/ardour/slave.h
+++ b/libs/ardour/ardour/slave.h
@@ -186,6 +186,7 @@ class MTC_Slave : public Slave, public sigc::trackable {
SafeTime current;
nframes_t mtc_frame; /* current time */
nframes_t last_inbound_frame; /* when we got it; audio clocked */
+ MIDI::byte last_mtc_fps_byte;
float mtc_speed;
nframes_t first_mtc_frame;
diff --git a/libs/ardour/ardour/svn_revision.h b/libs/ardour/ardour/svn_revision.h
index a44b97b5da..6c11d55e50 100644
--- a/libs/ardour/ardour/svn_revision.h
+++ b/libs/ardour/ardour/svn_revision.h
@@ -1,6 +1,8 @@
#ifndef __ardour_svn_revision_h__
#define __ardour_svn_revision_h__
+
namespace ARDOUR {
-extern const char* svn_revision;
+ extern const char* svn_revision;
}
+
#endif
diff --git a/libs/ardour/ardour/track.h b/libs/ardour/ardour/track.h
index fedd83ba68..b524c5d587 100644
--- a/libs/ardour/ardour/track.h
+++ b/libs/ardour/ardour/track.h
@@ -124,6 +124,9 @@ class Track : public Route
vector<FreezeRecordProcessorInfo*> processor_info;
bool have_mementos;
FreezeState state;
+ gain_t gain;
+ AutoState gain_automation_state;
+ AutoState pan_automation_state;
};
struct RecEnableControllable : public PBD::Controllable {
diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc
index d30899caf8..816f08cbd5 100644
--- a/libs/ardour/audio_track.cc
+++ b/libs/ardour/audio_track.cc
@@ -586,19 +586,74 @@ AudioTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
/* copy the diskstream data to all output buffers */
-
- const size_t limit = n_process_buffers().n_audio();
- BufferSet& bufs = _session.get_scratch_buffers (n_process_buffers());
-
+
+ size_t limit = n_process_buffers().n_audio();
+ BufferSet& bufs = _session.get_scratch_buffers ();
+ const size_t blimit = bufs.count().n_audio();
+
uint32_t n;
uint32_t i;
- for (i = 0, n = 1; i < limit; ++i, ++n) {
- memcpy (bufs.get_audio(i).data(), b, sizeof (Sample) * nframes);
- if (n < diskstream->n_channels().n_audio()) {
- tmpb = diskstream->playback_buffer(n);
- if (tmpb!=0) {
- b = tmpb;
+ if (limit > blimit) {
+
+ /* example case: auditioner configured for stereo output,
+ but loaded with an 8 channel file. there are only
+ 2 passthrough buffers, but n_process_buffers() will
+ return 8.
+
+ arbitrary decision: map all channels in the diskstream
+ to the outputs available.
+ */
+
+ float scaling = limit/blimit;
+
+ for (i = 0, n = 1; i < blimit; ++i, ++n) {
+
+ /* first time through just copy a channel into
+ the output buffer.
+ */
+
+ Sample* bb = bufs.get_audio (i).data();
+
+ for (nframes_t xx = 0; xx < nframes; ++xx) {
+ bb[xx] = b[xx] * scaling;
+ }
+
+ if (n < diskstream->n_channels().n_audio()) {
+ tmpb = diskstream->playback_buffer(n);
+ if (tmpb!=0) {
+ b = tmpb;
+ }
+ }
+ }
+
+ for (;i < limit; ++i, ++n) {
+
+ /* for all remaining channels, sum with existing
+ data in the output buffers
+ */
+
+ bufs.get_audio (i%blimit).accumulate_with_gain_from (b, nframes, 0, scaling);
+
+ if (n < diskstream->n_channels().n_audio()) {
+ tmpb = diskstream->playback_buffer(n);
+ if (tmpb!=0) {
+ b = tmpb;
+ }
+ }
+
+ }
+
+ limit = blimit;
+
+ } else {
+ for (i = 0, n = 1; i < limit; ++i, ++n) {
+ memcpy (bufs.get_audio (i).data(), b, sizeof (Sample) * nframes);
+ if (n < diskstream->n_channels().n_audio()) {
+ tmpb = diskstream->playback_buffer(n);
+ if (tmpb!=0) {
+ b = tmpb;
+ }
}
}
}
@@ -830,6 +885,11 @@ AudioTrack::freeze (InterThreadInfo& itt)
}
new_playlist = PlaylistFactory::create (DataType::AUDIO, _session, new_playlist_name, false);
+
+ _freeze_record.gain = _gain;
+ _freeze_record.gain_automation_state = _gain_control->automation_state();
+ _freeze_record.pan_automation_state = _panner->automation_state();
+
region_name = new_playlist_name;
/* create a new region from all filesources, keep it private */
@@ -847,6 +907,12 @@ AudioTrack::freeze (InterThreadInfo& itt)
diskstream->use_playlist (boost::dynamic_pointer_cast<AudioPlaylist>(new_playlist));
diskstream->set_record_enabled (false);
+ /* reset stuff that has already been accounted for in the freeze process */
+
+ set_gain (1.0, this);
+ _gain_control->set_automation_state (Off);
+ _panner->set_automation_state (Off);
+
_freeze_record.state = Frozen;
FreezeChange(); /* EMIT SIGNAL */
}
@@ -877,6 +943,9 @@ AudioTrack::unfreeze ()
}
_freeze_record.playlist.reset ();
+ set_gain (_freeze_record.gain, this);
+ _gain_control->set_automation_state (_freeze_record.gain_automation_state);
+ _panner->set_automation_state (_freeze_record.pan_automation_state);
}
_freeze_record.state = UnFrozen;
diff --git a/libs/ardour/audio_unit.cc b/libs/ardour/audio_unit.cc
index 9c7ea0f13f..16d5e390f8 100644
--- a/libs/ardour/audio_unit.cc
+++ b/libs/ardour/audio_unit.cc
@@ -103,7 +103,15 @@ AUPlugin::~AUPlugin ()
void
AUPlugin::init ()
{
- OSErr err = CAAudioUnit::Open (*(comp.get()), *unit);
+ OSErr err;
+
+ try {
+ err = CAAudioUnit::Open (*(comp.get()), *unit);
+ } catch (...) {
+ error << _("Exception thrown during AudioUnit plugin loading - plugin ignored") << endmsg;
+ cerr << _("Exception thrown during AudioUnit plugin loading - plugin ignored") << endl;
+ throw failed_constructor();
+ }
if (err != noErr) {
error << _("AudioUnit: Could not convert CAComponent to CAAudioUnit") << endmsg;
@@ -1090,6 +1098,7 @@ AUPluginInfo::cached_io_configuration (const std::string& unique_id,
} catch (...) {
warning << string_compose (_("Could not load AU plugin %1 - ignored"), name) << endmsg;
+ cerr << string_compose (_("Could not load AU plugin %1 - ignored"), name) << endl;
return false;
}
diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc
index 788017555a..8b5d4ba42c 100644
--- a/libs/ardour/audioengine.cc
+++ b/libs/ardour/audioengine.cc
@@ -132,7 +132,7 @@ _thread_init_callback (void *arg)
knows about it.
*/
- PBD::ThreadCreatedWithRequestSize (pthread_self(), X_("Audioengine"), 4096);
+ PBD::notify_gui_about_thread_creation (pthread_self(), X_("Audioengine"), 4096);
MIDI::JACK_MidiPort::set_process_thread (pthread_self());
}
@@ -922,8 +922,6 @@ AudioEngine::halted (void *arg)
ae->_buffer_size = 0;
ae->_frame_rate = 0;
- cerr << "!!! HALTED !!!\n";
-
if (was_running) {
ae->Halted(); /* EMIT SIGNAL */
}
@@ -1318,7 +1316,7 @@ AudioEngine::reconnect_to_jack ()
if (Config->get_jack_time_master()) {
jack_set_timebase_callback (_jack, 0, _jack_timebase_callback, this);
- }
+ }
if (jack_activate (_jack) == 0) {
_running = true;
diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc
index c5c04bc33d..5d4748c2d4 100644
--- a/libs/ardour/audioregion.cc
+++ b/libs/ardour/audioregion.cc
@@ -133,9 +133,9 @@ AudioRegion::AudioRegion (const SourceList& srcs, nframes_t start, nframes_t len
AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, nframes_t offset, nframes_t length, const string& name, layer_t layer, Flag flags)
: Region (other, offset, length, name, layer, flags)
, _automatable(other->session())
- , _fade_in (new AutomationList(Evoral::Parameter(FadeInAutomation)))
- , _fade_out (new AutomationList(Evoral::Parameter(FadeOutAutomation)))
- , _envelope (new AutomationList(Evoral::Parameter(EnvelopeAutomation)))
+ , _fade_in (new AutomationList(*other->_fade_in, offset, offset + length))
+ , _fade_out (new AutomationList(*other->_fade_out, offset, offset + length))
+ , _envelope (new AutomationList(*other->_envelope, offset, offset + length))
{
set<boost::shared_ptr<Source> > unique_srcs;
@@ -185,17 +185,48 @@ AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, nframes_t
AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other)
: Region (other)
- , _automatable(other->session())
- , _fade_in (new AutomationList(Evoral::Parameter(FadeInAutomation)))
- , _fade_out (new AutomationList(Evoral::Parameter(FadeOutAutomation)))
- , _envelope (new AutomationList(Evoral::Parameter(EnvelopeAutomation)))
+ , _automatable (other->session())
+ , _fade_in (new AutomationList (*other->_fade_in))
+ , _fade_out (new AutomationList (*other->_fade_out))
+ , _envelope (new AutomationList (*other->_envelope))
{
assert(_type == DataType::AUDIO);
_scale_amplitude = other->_scale_amplitude;
- _envelope = other->_envelope;
set_default_fades ();
-
+
+ listen_to_my_curves ();
+ listen_to_my_sources ();
+}
+
+AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, const SourceList& srcs,
+ nframes_t length, const string& name, layer_t layer, Flag flags)
+ : Region (other, length, name, layer, flags)
+ , _automatable (other->session())
+ , _fade_in (new AutomationList (*other->_fade_in))
+ , _fade_out (new AutomationList (*other->_fade_out))
+ , _envelope (new AutomationList (*other->_envelope))
+{
+ /* make-a-sort-of-copy-with-different-sources constructor (used by audio filter) */
+
+ set<boost::shared_ptr<AudioSource> > unique_srcs;
+
+ for (SourceList::const_iterator i=srcs.begin(); i != srcs.end(); ++i) {
+
+ _sources.push_back (*i);
+ _master_sources.push_back (*i);
+
+ boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> ((*i));
+ if (afs) {
+ afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
+ }
+ }
+
+ _scale_amplitude = other->_scale_amplitude;
+
+ _fade_in_disabled = 0;
+ _fade_out_disabled = 0;
+
listen_to_my_curves ();
listen_to_my_sources ();
}
@@ -296,19 +327,25 @@ AudioRegion::read_peaks (PeakData *buf, nframes_t npeaks, nframes_t offset, nfra
}
nframes64_t
-AudioRegion::read (Sample* buf, nframes64_t position, nframes64_t cnt, int channel) const
+AudioRegion::read (Sample* buf, nframes64_t timeline_position, nframes64_t cnt, int channel) const
{
/* raw read, no fades, no gain, nada */
- return _read_at (_sources, _length, buf, 0, 0, _position + position, cnt, channel, 0, 0, true);
+ return _read_at (_sources, _length, buf, 0, 0, _position + timeline_position, cnt, channel, 0, 0, ReadOps (0));
+}
+
+nframes64_t
+AudioRegion::read_with_ops (Sample* buf, nframes64_t file_position, nframes64_t cnt, int channel, ReadOps rops) const
+{
+ return _read_at (_sources, _length, buf, 0, 0, file_position, cnt, channel, 0, 0, rops);
}
nframes_t
-AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nframes_t position,
+AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nframes_t file_position,
nframes_t cnt,
uint32_t chan_n, nframes_t read_frames, nframes_t skip_frames) const
{
/* regular diskstream/butler read complete with fades etc */
- return _read_at (_sources, _length, buf, mixdown_buffer, gain_buffer, position, cnt, chan_n, read_frames, skip_frames, false);
+ return _read_at (_sources, _length, buf, mixdown_buffer, gain_buffer, file_position, cnt, chan_n, read_frames, skip_frames, ReadOps (~0));
}
nframes_t
@@ -325,11 +362,12 @@ AudioRegion::_read_at (const SourceList& srcs, nframes_t limit,
uint32_t chan_n,
nframes_t read_frames,
nframes_t skip_frames,
- bool raw) const
+ ReadOps rops) const
{
nframes_t internal_offset;
nframes_t buf_offset;
nframes_t to_read;
+ bool raw = (rops == ReadOpsNone);
if (muted() && !raw) {
return 0; /* read nothing */
@@ -361,7 +399,7 @@ AudioRegion::_read_at (const SourceList& srcs, nframes_t limit,
mixdown_buffer += buf_offset;
}
- if (!raw) {
+ if (rops & ReadOpsCount) {
_read_data_count = 0;
}
@@ -372,7 +410,7 @@ AudioRegion::_read_at (const SourceList& srcs, nframes_t limit,
return 0; /* "read nothing" */
}
- if (!raw) {
+ if (rops & ReadOpsCount) {
_read_data_count += src->read_data_count();
}
@@ -383,18 +421,12 @@ AudioRegion::_read_at (const SourceList& srcs, nframes_t limit,
*/
memset (mixdown_buffer, 0, sizeof (Sample) * cnt);
-
- /* no fades required */
-
- if (!raw) {
- goto merge;
- }
}
- /* fade in */
-
- if (!raw) {
+ if (rops & ReadOpsFades) {
+ /* fade in */
+
if ((_flags & FadeIn) && Config->get_use_region_fades()) {
nframes_t fade_in_length = (nframes_t) _fade_in->back()->when;
@@ -407,6 +439,7 @@ AudioRegion::_read_at (const SourceList& srcs, nframes_t limit,
fi_limit = min (to_read, fade_in_length - internal_offset);
+
_fade_in->curve().get_vector (internal_offset, internal_offset+fi_limit, gain_buffer, fi_limit);
for (nframes_t n = 0; n < fi_limit; ++n) {
@@ -422,12 +455,12 @@ AudioRegion::_read_at (const SourceList& srcs, nframes_t limit,
/* see if some part of this read is within the fade out */
/* ................. >| REGION
- limit
+ limit
{ } FADE
fade_out_length
^
- limit - fade_out_length
+ limit - fade_out_length
|--------------|
^internal_offset
^internal_offset + to_read
@@ -457,39 +490,43 @@ AudioRegion::_read_at (const SourceList& srcs, nframes_t limit,
}
}
+ }
- /* Regular gain curves */
-
- if (envelope_active()) {
- _envelope->curve().get_vector (internal_offset, internal_offset + to_read, gain_buffer, to_read);
+ /* Regular gain curves and scaling */
+
+ if ((rops & ReadOpsOwnAutomation) && envelope_active()) {
+ _envelope->curve().get_vector (internal_offset, internal_offset + to_read, gain_buffer, to_read);
- if (_scale_amplitude != 1.0f) {
- for (nframes_t n = 0; n < to_read; ++n) {
- mixdown_buffer[n] *= gain_buffer[n] * _scale_amplitude;
- }
- } else {
- for (nframes_t n = 0; n < to_read; ++n) {
- mixdown_buffer[n] *= gain_buffer[n];
- }
+ if ((rops & ReadOpsOwnScaling) && _scale_amplitude != 1.0f) {
+ for (nframes_t n = 0; n < to_read; ++n) {
+ mixdown_buffer[n] *= gain_buffer[n] * _scale_amplitude;
}
- } else if (_scale_amplitude != 1.0f) {
- apply_gain_to_buffer (mixdown_buffer, to_read, _scale_amplitude);
+ } else {
+ for (nframes_t n = 0; n < to_read; ++n) {
+ mixdown_buffer[n] *= gain_buffer[n];
+ }
+ }
+ } else if ((rops & ReadOpsOwnScaling) && _scale_amplitude != 1.0f) {
+
+ // XXX this should be using what in 2.0 would have been:
+ // Session::apply_gain_to_buffer (mixdown_buffer, to_read, _scale_amplitude);
+
+ for (nframes_t n = 0; n < to_read; ++n) {
+ mixdown_buffer[n] *= _scale_amplitude;
}
+ }
- merge:
+ if (!opaque()) {
- if (!opaque()) {
-
- /* gack. the things we do for users.
- */
-
- buf += buf_offset;
+ /* gack. the things we do for users.
+ */
+
+ buf += buf_offset;
- for (nframes_t n = 0; n < to_read; ++n) {
- buf[n] += mixdown_buffer[n];
- }
- }
- }
+ for (nframes_t n = 0; n < to_read; ++n) {
+ buf[n] += mixdown_buffer[n];
+ }
+ }
return to_read;
}
diff --git a/libs/ardour/coreaudiosource.cc b/libs/ardour/coreaudiosource.cc
index 4383f1a696..a6aceb7842 100644
--- a/libs/ardour/coreaudiosource.cc
+++ b/libs/ardour/coreaudiosource.cc
@@ -19,6 +19,8 @@
*/
#include <algorithm>
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
#include <pbd/error.h>
#include <ardour/coreaudiosource.h>
@@ -256,7 +258,103 @@ CoreAudioSource::get_soundfile_info (string path, SoundFileInfo& _info, string&
goto out;
}
- _info.format_name = CFStringRefToStdString(name);
+ _info.format_name = "";
+
+ if (absd.mFormatID == kAudioFormatLinearPCM) {
+ if (absd.mFormatFlags & kAudioFormatFlagIsBigEndian) {
+ _info.format_name += "big-endian";
+ } else {
+ _info.format_name += "little-endian";
+ }
+
+ char buf[32];
+ snprintf (buf, sizeof (buf), " %" PRIu32 " bit", absd.mBitsPerChannel);
+ _info.format_name += buf;
+ _info.format_name += '\n';
+
+ if (absd.mFormatFlags & kAudioFormatFlagIsFloat) {
+ _info.format_name += "float";
+ } else {
+ if (absd.mFormatFlags & kAudioFormatFlagIsSignedInteger) {
+ _info.format_name += "signed";
+ } else {
+ _info.format_name += "unsigned";
+ }
+ /* integer is typical, do not show it */
+ }
+
+ if (_info.channels > 1) {
+ if (absd.mFormatFlags & kAudioFormatFlagIsNonInterleaved) {
+ _info.format_name += " noninterleaved";
+ }
+ /* interleaved is the normal case, do not show it */
+ }
+
+ _info.format_name += ' ';
+ }
+
+ switch (absd.mFormatID) {
+ case kAudioFormatLinearPCM:
+ _info.format_name += "PCM";
+ break;
+
+ case kAudioFormatAC3:
+ _info.format_name += "AC3";
+ break;
+
+ case kAudioFormat60958AC3:
+ _info.format_name += "60958 AC3";
+ break;
+
+ case kAudioFormatMPEGLayer1:
+ _info.format_name += "MPEG-1";
+ break;
+
+ case kAudioFormatMPEGLayer2:
+ _info.format_name += "MPEG-2";
+ break;
+
+ case kAudioFormatMPEGLayer3:
+ _info.format_name += "MPEG-3";
+ break;
+
+ case kAudioFormatAppleIMA4:
+ _info.format_name += "IMA-4";
+ break;
+
+ case kAudioFormatMPEG4AAC:
+ _info.format_name += "AAC";
+ break;
+
+ case kAudioFormatMPEG4CELP:
+ _info.format_name += "CELP";
+ break;
+
+ case kAudioFormatMPEG4HVXC:
+ _info.format_name += "HVXC";
+ break;
+
+ case kAudioFormatMPEG4TwinVQ:
+ _info.format_name += "TwinVQ";
+ break;
+
+ /* these really shouldn't show up, but we should do something
+ somewhere else to make sure that doesn't happen. until
+ that is guaranteed, print something anyway.
+ */
+
+ case kAudioFormatTimeCode:
+ _info.format_name += "timecode";
+ break;
+
+ case kAudioFormatMIDIStream:
+ _info.format_name += "MIDI";
+ break;
+
+ case kAudioFormatParameterValueStream:
+ _info.format_name += "parameter values";
+ break;
+ }
// XXX it would be nice to find a way to get this information if it exists
diff --git a/libs/ardour/crossfade.cc b/libs/ardour/crossfade.cc
index 05ea7765f0..3a7b525db6 100644
--- a/libs/ardour/crossfade.cc
+++ b/libs/ardour/crossfade.cc
@@ -217,22 +217,57 @@ Crossfade::initialize ()
_fade_out.freeze ();
_fade_out.clear ();
- _fade_out.add (0.0, 1.0);
- _fade_out.add ((_length * 0.1), 0.99);
- _fade_out.add ((_length * 0.2), 0.97);
- _fade_out.add ((_length * 0.8), 0.03);
- _fade_out.add ((_length * 0.9), 0.01);
- _fade_out.add (_length, 0.0);
+
+#define EQUAL_POWER_MINUS_3DB
+#ifdef EQUAL_POWER_MINUS_3DB
+
+ _fade_out.add ((_length * 0.000000), 1.000000);
+ _fade_out.add ((_length * 0.166667), 0.948859);
+ _fade_out.add ((_length * 0.333333), 0.851507);
+ _fade_out.add ((_length * 0.500000), 0.707946);
+ _fade_out.add ((_length * 0.666667), 0.518174);
+ _fade_out.add ((_length * 0.833333), 0.282192);
+ _fade_out.add ((_length * 1.000000), 0.000000);
+
+#else // EQUAL_POWER_MINUS_6DB
+
+ _fade_out.add ((_length * 0.000000), 1.000000);
+ _fade_out.add ((_length * 0.166667), 0.833033);
+ _fade_out.add ((_length * 0.333333), 0.666186);
+ _fade_out.add ((_length * 0.500000), 0.499459);
+ _fade_out.add ((_length * 0.666667), 0.332853);
+ _fade_out.add ((_length * 0.833333), 0.166366);
+ _fade_out.add ((_length * 1.000000), 0.000000);
+#endif
+
_fade_out.thaw ();
_fade_in.freeze ();
_fade_in.clear ();
- _fade_in.add (0.0, 0.0);
- _fade_in.add ((_length * 0.1), 0.01);
- _fade_in.add ((_length * 0.2), 0.03);
- _fade_in.add ((_length * 0.8), 0.97);
- _fade_in.add ((_length * 0.9), 0.99);
- _fade_in.add (_length, 1.0);
+
+#define EQUAL_POWER_MINUS_3DB
+#ifdef EQUAL_POWER_MINUS_3DB
+
+ _fade_in.add ((_length * 0.000000), 0.000000);
+ _fade_in.add ((_length * 0.166667), 0.282192);
+ _fade_in.add ((_length * 0.333333), 0.518174);
+ _fade_in.add ((_length * 0.500000), 0.707946);
+ _fade_in.add ((_length * 0.666667), 0.851507);
+ _fade_in.add ((_length * 0.833333), 0.948859);
+ _fade_in.add ((_length * 1.000000), 1.000000);
+
+#else // EQUAL_POWER_MINUS_SIX_DB
+
+ _fade_in.add ((_length * 0.000000), 0.000000);
+ _fade_in.add ((_length * 0.166667), 0.166366);
+ _fade_in.add ((_length * 0.333333), 0.332853);
+ _fade_in.add ((_length * 0.500000), 0.499459);
+ _fade_in.add ((_length * 0.666667), 0.666186);
+ _fade_in.add ((_length * 0.833333), 0.833033);
+ _fade_in.add ((_length * 1.000000), 1.000000);
+
+#endif
+
_fade_in.thaw ();
overlap_type = _in->coverage (_out->position(), _out->last_frame());
diff --git a/libs/ardour/export_channel_configuration.cc b/libs/ardour/export_channel_configuration.cc
index a2a289737c..c8db1a6b0d 100644
--- a/libs/ardour/export_channel_configuration.cc
+++ b/libs/ardour/export_channel_configuration.cc
@@ -174,8 +174,7 @@ ExportChannelConfiguration::write_file ()
void *
ExportChannelConfiguration::_write_files (void *arg)
{
-
- PBD::ThreadCreated (pthread_self(), "Export post-processing");
+ notify_gui_about_thread_creation (pthread_self(), "Export post-processing");
// cc can be trated like 'this'
WriterThread & cc (*((WriterThread *) arg));
diff --git a/libs/ardour/globals.cc b/libs/ardour/globals.cc
index 04b4543b71..8be2e3b8b6 100644
--- a/libs/ardour/globals.cc
+++ b/libs/ardour/globals.cc
@@ -128,6 +128,7 @@ setup_osc ()
return 0;
}
}
+
#endif
int
@@ -204,16 +205,17 @@ ARDOUR::setup_midi ()
<< endmsg;
return 0;
}
+
if (default_mtc_port == 0) {
warning << string_compose (_("No MTC support (MIDI port \"%1\" not available)"), Config->get_mtc_port_name())
<< endmsg;
- }
+ }
if (default_midi_port == 0) {
warning << string_compose (_("No MIDI parameter support (MIDI port \"%1\" not available)"), Config->get_midi_port_name())
<< endmsg;
- }
+ }
if (default_midi_clock_port == 0) {
warning << string_compose (_("No MIDI Clock support (MIDI port \"%1\" not available)"), Config->get_midi_clock_port_name())
diff --git a/libs/ardour/import.cc b/libs/ardour/import.cc
index 3f6e60af33..6b3871c814 100644
--- a/libs/ardour/import.cc
+++ b/libs/ardour/import.cc
@@ -56,8 +56,10 @@
#include <ardour/tempo.h>
#ifdef HAVE_COREAUDIO
+#ifdef USE_COREAUDIO_FOR_FILE_IO
#include <ardour/caimportable.h>
#endif
+#endif
#include "i18n.h"
@@ -69,11 +71,13 @@ static boost::shared_ptr<ImportableSource>
open_importable_source (const string& path, nframes_t samplerate, ARDOUR::SrcQuality quality)
{
#ifdef HAVE_COREAUDIO
+#ifdef USE_COREAUDIO_FOR_FILE_IO
/* see if we can use CoreAudio to handle the IO */
try {
- boost::shared_ptr<CAImportableSource> source(new CAImportableSource(path));
+ CAImportableSource* src = new CAImportableSource(path);
+ boost::shared_ptr<CAImportableSource> source (src);
if (source->samplerate() == samplerate) {
return source;
@@ -87,8 +91,8 @@ open_importable_source (const string& path, nframes_t samplerate, ARDOUR::SrcQua
catch (...) {
/* fall back to SndFile */
-
#endif
+#endif
try {
boost::shared_ptr<SndFileImportableSource> source(new SndFileImportableSource(path));
@@ -96,7 +100,7 @@ open_importable_source (const string& path, nframes_t samplerate, ARDOUR::SrcQua
if (source->samplerate() == samplerate) {
return source;
}
-
+
/* rewrap as a resampled source */
return boost::shared_ptr<ImportableSource>(new ResampledImportableSource(source, samplerate, quality));
@@ -107,8 +111,10 @@ open_importable_source (const string& path, nframes_t samplerate, ARDOUR::SrcQua
}
#ifdef HAVE_COREAUDIO
+#ifdef USE_COREAUDIO_FOR_FILE_IO
}
#endif
+#endif
}
static std::string
@@ -437,7 +443,7 @@ Session::import_audiofiles (import_status& status)
if (source) { // audio
status.doing_what = compose_status_message (*p, source->samplerate(),
- frame_rate(), cnt, status.paths.size());
+ frame_rate(), cnt, status.total);
write_audio_data_to_new_files (source.get(), status, newfiles);
} else if (smf_reader.get()) { // midi
status.doing_what = string_compose(_("loading MIDI file %1"), *p);
@@ -479,8 +485,7 @@ Session::import_audiofiles (import_status& status)
save_state (_name);
- std::copy (all_new_sources.begin(), all_new_sources.end(),
- std::back_inserter(status.sources));
+ std::copy (all_new_sources.begin(), all_new_sources.end(), std::back_inserter(status.sources));
} else {
// this can throw...but it seems very unlikely
std::for_each (all_new_sources.begin(), all_new_sources.end(), remove_file_source);
diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc
index e245712fee..66023f1f4d 100644
--- a/libs/ardour/io.cc
+++ b/libs/ardour/io.cc
@@ -2331,8 +2331,9 @@ void
IO::set_gain (gain_t val, void *src)
{
// max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
- if (val > 1.99526231f)
+ if (val > 1.99526231f) {
val = 1.99526231f;
+ }
if (src != _gain_control.get()) {
_gain_control->set_value(val);
@@ -2347,7 +2348,7 @@ IO::set_gain (gain_t val, void *src)
}
if (_session.transport_stopped()) {
- _gain = val;
+ // _gain = val;
}
/*
@@ -2541,7 +2542,6 @@ IO::set_active (bool yn)
active_changed(); /* EMIT SIGNAL */
}
-
AudioPort*
IO::audio_input(uint32_t n) const
{
diff --git a/libs/ardour/mtc_slave.cc b/libs/ardour/mtc_slave.cc
index 0a0fbc1529..1a8cd589da 100644
--- a/libs/ardour/mtc_slave.cc
+++ b/libs/ardour/mtc_slave.cc
@@ -16,7 +16,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
+#include <iostream>
#include <errno.h>
#include <poll.h>
#include <sys/types.h>
@@ -43,6 +43,8 @@ MTC_Slave::MTC_Slave (Session& s, MIDI::Port& p)
{
can_notify_on_unknown_rate = true;
+ last_mtc_fps_byte = session.get_mtc_smpte_bits ();
+
rebind (p);
reset ();
}
@@ -96,6 +98,8 @@ MTC_Slave::update_mtc_time (const byte *msg, bool was_full)
smpte.seconds = msg[1];
smpte.frames = msg[0];
+ last_mtc_fps_byte = msg[4];
+
switch (msg[4]) {
case MTC_24_FPS:
smpte.rate = 24;
@@ -120,7 +124,9 @@ MTC_Slave::update_mtc_time (const byte *msg, bool was_full)
default:
/* throttle error messages about unknown MTC rates */
if (can_notify_on_unknown_rate) {
- error << _("Unknown rate/drop value in incoming MTC stream, session values used instead") << endmsg;
+ error << string_compose (_("Unknown rate/drop value %1 in incoming MTC stream, session values used instead"),
+ (int) msg[4])
+ << endmsg;
can_notify_on_unknown_rate = false;
}
smpte.rate = session.smpte_frames_per_second();
@@ -170,8 +176,9 @@ MTC_Slave::update_mtc_time (const byte *msg, bool was_full)
void
MTC_Slave::handle_locate (const MIDI::byte* mmc_tc)
{
- MIDI::byte mtc[4];
+ MIDI::byte mtc[5];
+ mtc[4] = last_mtc_fps_byte;
mtc[3] = mmc_tc[0] & 0xf; /* hrs only */
mtc[2] = mmc_tc[1];
mtc[1] = mmc_tc[2];
diff --git a/libs/ardour/osc.cc b/libs/ardour/osc.cc
index 0c58040ad6..ffd2df63be 100644
--- a/libs/ardour/osc.cc
+++ b/libs/ardour/osc.cc
@@ -32,11 +32,13 @@
#include <pbd/pthread_utils.h>
#include <pbd/file_utils.h>
+#include <pbd/filesystem.h>
#include <ardour/osc.h>
#include <ardour/session.h>
#include <ardour/route.h>
#include <ardour/audio_track.h>
+#include <ardour/dB.h>
#include <ardour/filesystem_paths.h>
#include "i18n.h"
@@ -107,10 +109,10 @@ OSC::start ()
cerr << "OSC @ " << get_server_url () << endl;
- sys::path url_file;
+ PBD::sys::path url_file;
if (find_file_in_search_path (ardour_search_path() + system_config_search_path(),
- "osc_url", url_file)) {
+ "osc_url", url_file)) {
_osc_url_file = url_file.to_string();
ofstream urlfile;
urlfile.open(_osc_url_file.c_str(), ios::trunc);
@@ -154,9 +156,9 @@ OSC::stop ()
unlink(_osc_unix_socket_path.c_str());
}
- if (! _osc_url_file.empty() ) {
- unlink(_osc_url_file.c_str() );
- }
+ if (! _osc_url_file.empty() ) {
+ unlink(_osc_url_file.c_str() );
+ }
return 0;
}
@@ -204,6 +206,12 @@ OSC::register_callbacks()
REGISTER_CALLBACK (serv, "/ardour/rec_enable_toggle", "", rec_enable_toggle);
REGISTER_CALLBACK (serv, "/ardour/toggle_all_rec_enables", "", toggle_all_rec_enables);
+ REGISTER_CALLBACK (serv, "/ardour/routes/mute", "ii", route_mute);
+ REGISTER_CALLBACK (serv, "/ardour/routes/solo", "ii", route_solo);
+ REGISTER_CALLBACK (serv, "/ardour/routes/recenable", "ii", route_recenable);
+ REGISTER_CALLBACK (serv, "/ardour/routes/gainabs", "if", route_set_gain_abs);
+ REGISTER_CALLBACK (serv, "/ardour/routes/gaindB", "if", route_set_gain_dB);
+
#if 0
REGISTER_CALLBACK (serv, "/ardour/*/#current_value", "", current_value);
REGISTER_CALLBACK (serv, "/ardour/set", "", set);
@@ -310,7 +318,7 @@ OSC::get_unix_server_url()
void *
OSC::_osc_receiver(void * arg)
{
- PBD::ThreadCreated (pthread_self(), X_("OSC"));
+ PBD::notify_gui_about_thread_creation (pthread_self(), X_("OSC"));
static_cast<OSC*> (arg)->osc_receiver();
return 0;
@@ -378,7 +386,7 @@ OSC::osc_receiver()
if (pfd[i].revents & POLLIN)
{
// this invokes callbacks
- //cerr << "invoking recv on " << pfd[i].fd << endl;
+ // cerr << "invoking recv on " << pfd[i].fd << endl;
lo_server_recv(srvs[i]);
}
}
@@ -390,7 +398,7 @@ OSC::osc_receiver()
if (_osc_server) {
int fd = lo_server_get_socket_fd(_osc_server);
if (fd >=0) {
- // hack around
+ // hack around
close(fd);
}
lo_server_free (_osc_server);
@@ -500,3 +508,70 @@ OSC::current_value (const char *path, const char *types, lo_arg **argv, int argc
#endif
return 0;
}
+
+int
+OSC::route_mute (int rid, int yn)
+{
+ if (!session) return -1;
+
+ boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
+
+ if (r) {
+ r->set_mute (yn, this);
+ }
+ return 0;
+}
+
+int
+OSC::route_solo (int rid, int yn)
+{
+ if (!session) return -1;
+
+ boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
+
+ if (r) {
+ r->set_solo (yn, this);
+ }
+ return 0;
+}
+
+int
+OSC::route_recenable (int rid, int yn)
+{
+ if (!session) return -1;
+
+ boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
+
+ if (r) {
+ r->set_record_enable (yn, this);
+ }
+ return 0;
+}
+
+int
+OSC::route_set_gain_abs (int rid, float level)
+{
+ if (!session) return -1;
+
+ boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
+
+ if (r) {
+ r->set_gain (level, this);
+ }
+
+ return 0;
+}
+
+int
+OSC::route_set_gain_dB (int rid, float dB)
+{
+ if (!session) return -1;
+
+ boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
+
+ if (r) {
+ r->set_gain (dB_to_coefficient (dB), this);
+ }
+
+ return 0;
+}
diff --git a/libs/ardour/panner.cc b/libs/ardour/panner.cc
index fe0a792b6b..04c744b880 100644
--- a/libs/ardour/panner.cc
+++ b/libs/ardour/panner.cc
@@ -749,10 +749,14 @@ Panner::reset (uint32_t nouts, uint32_t npans)
{
uint32_t n;
bool changed = false;
+ bool do_not_and_did_not_need_panning = ((nouts < 2) && (outputs.size() < 2));
- //configure_io( ChanCount( DataType::AUDIO, nout ), ChanCount( DataType::AUDIO, nin ) )
-
- if (nouts < 2 || (nouts == outputs.size() && npans == _streampanners.size())) {
+ /* if new and old config don't need panning, or if
+ the config hasn't changed, we're done.
+ */
+
+ if (do_not_and_did_not_need_panning ||
+ ((nouts == outputs.size()) && (npans == _streampanners.size()))) {
return;
}
@@ -770,6 +774,10 @@ Panner::reset (uint32_t nouts, uint32_t npans)
changed = true;
}
+ if (nouts < 2) {
+ goto send_changed;
+ }
+
switch (nouts) {
case 0:
break;
@@ -871,6 +879,7 @@ Panner::reset (uint32_t nouts, uint32_t npans)
}
}
+ send_changed:
if (changed) {
Changed (); /* EMIT SIGNAL */
}
diff --git a/libs/ardour/plugin_manager.cc b/libs/ardour/plugin_manager.cc
index 0b5a14bf56..8dd1a7abb0 100644
--- a/libs/ardour/plugin_manager.cc
+++ b/libs/ardour/plugin_manager.cc
@@ -130,6 +130,8 @@ PluginManager::PluginManager ()
_lv2_world = new LV2World();
#endif
+ BootMessage (_("Discovering Plugins"));
+
refresh ();
}
@@ -632,7 +634,7 @@ PluginManager::add_favorite (PluginType t, string id)
{
FavoritePlugin fp (t, id);
pair<FavoritePluginList::iterator,bool> res = favorites.insert (fp);
- cerr << "Added " << t << " " << id << " success ? " << res.second << endl;
+ //cerr << "Added " << t << " " << id << " success ? " << res.second << endl;
}
void
diff --git a/libs/ardour/rb_effect.cc b/libs/ardour/rb_effect.cc
index d0a8a3abbf..a1dce0497f 100644
--- a/libs/ardour/rb_effect.cc
+++ b/libs/ardour/rb_effect.cc
@@ -206,7 +206,7 @@ RBEffect::run (boost::shared_ptr<Region> r)
while (pos < read_duration && !tsr.cancel) {
nframes_t this_read = 0;
-
+
for (uint32_t i = 0; i < channels; ++i) {
this_read = 0;
@@ -229,7 +229,7 @@ RBEffect::run (boost::shared_ptr<Region> r)
if (this_read != this_time) {
error << string_compose
(_("tempoize: error reading data from %1 at %2 (wanted %3, got %4)"),
- region->name(), pos + region->position(), this_time, this_read) << endmsg;
+ region->name(), this_position, this_time, this_read) << endmsg;
goto out;
}
}
diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc
index 982eb3e023..6375527664 100644
--- a/libs/ardour/region.cc
+++ b/libs/ardour/region.cc
@@ -38,6 +38,7 @@
#include <ardour/tempo.h>
#include <ardour/region_factory.h>
#include <ardour/filter.h>
+#include <ardour/profile.h>
#include "i18n.h"
@@ -153,50 +154,90 @@ Region::Region (const SourceList& srcs, nframes_t start, nframes_t length, const
/** Create a new Region from part of an existing one */
Region::Region (boost::shared_ptr<const Region> other, nframes_t offset, nframes_t length, const string& name, layer_t layer, Flag flags)
: SessionObject(other->session(), name)
- , _type(other->data_type())
- , _flags(Flag(flags & ~(Locked|PositionLocked|WholeFile|Hidden)))
- , _start(other->_start + offset)
- , _length(length)
- , _position(0)
- , _last_position(0)
- , _positional_lock_style(other->_positional_lock_style)
- , _sync_position(_start)
- , _layer(layer)
- , _first_edit(EditChangesNothing)
- , _frozen(0)
- , _ancestral_start (other->_ancestral_start + offset)
- , _ancestral_length (length)
- , _stretch (other->_stretch)
- , _shift (other->_shift)
- , _valid_transients(false)
- , _read_data_count(0)
- , _pending_changed(Change (0))
- , _last_layer_op(0)
+ , _type (other->data_type())
+
{
- if (other->_sync_position < offset)
- _sync_position = other->_sync_position;
+ _start = other->_start + offset;
+ copy_stuff (other, offset, length, name, layer, flags);
- set<boost::shared_ptr<Source> > unique_srcs;
+ /* if the other region had a distinct sync point
+ set, then continue to use it as best we can.
+ otherwise, reset sync point back to start.
+ */
- for (SourceList::const_iterator i= other->_sources.begin(); i != other->_sources.end(); ++i) {
- _sources.push_back (*i);
- (*i)->GoingAway.connect (bind (mem_fun (*this, &Region::source_deleted), (*i)));
- unique_srcs.insert (*i);
- }
-
- if (other->_sync_position < offset) {
- _sync_position = other->_sync_position;
+ if (other->flags() & SyncMarked) {
+ if (other->_sync_position < _start) {
+ _flags = Flag (_flags & ~SyncMarked);
+ _sync_position = _start;
+ } else {
+ _sync_position = other->_sync_position;
+ }
+ } else {
+ _flags = Flag (_flags & ~SyncMarked);
+ _sync_position = _start;
}
+ if (Profile->get_sae()) {
+ /* reset sync point to start if its ended up
+ outside region bounds.
+ */
- for (SourceList::const_iterator i = other->_master_sources.begin(); i != other->_master_sources.end(); ++i) {
- if (unique_srcs.find (*i) == unique_srcs.end()) {
- (*i)->GoingAway.connect (bind (mem_fun (*this, &Region::source_deleted), (*i)));
+ if (_sync_position < _start || _sync_position >= _start + _length) {
+ _flags = Flag (_flags & ~SyncMarked);
+ _sync_position = _start;
}
- _master_sources.push_back (*i);
}
+}
+
+Region::Region (boost::shared_ptr<const Region> other, nframes_t length, const string& name, layer_t layer, Flag flags)
+ : SessionObject(other->session(), name)
+ , _type (other->data_type())
+{
+ /* create a new Region exactly like another but starting at 0 in its sources */
+
+ _start = 0;
+ copy_stuff (other, 0, length, name, layer, flags);
+
+ /* sync pos is relative to start of file. our start-in-file is now zero,
+ so set our sync position to whatever the the difference between
+ _start and _sync_pos was in the other region.
+
+ result is that our new sync pos points to the same point in our source(s)
+ as the sync in the other region did in its source(s).
+
+ since we start at zero in our source(s), it is not possible to use a sync point that
+ is before the start. reset it to _start if that was true in the other region.
+ */
- assert(_sources.size() > 0);
+ if (other->flags() & SyncMarked) {
+ if (other->_start < other->_sync_position) {
+ /* sync pos was after the start point of the other region */
+ _sync_position = other->_sync_position - other->_start;
+ } else {
+ /* sync pos was before the start point of the other region. not possible here. */
+ _flags = Flag (_flags & ~SyncMarked);
+ _sync_position = _start;
+ }
+ } else {
+ _flags = Flag (_flags & ~SyncMarked);
+ _sync_position = _start;
+ }
+
+ if (Profile->get_sae()) {
+ /* reset sync point to start if its ended up
+ outside region bounds.
+ */
+
+ if (_sync_position < _start || _sync_position >= _start + _length) {
+ _flags = Flag (_flags & ~SyncMarked);
+ _sync_position = _start;
+ }
+ }
+
+ /* reset a couple of things that copy_stuff() gets wrong in this particular case */
+
+ _positional_lock_style = other->_positional_lock_style;
+ _first_edit = other->_first_edit;
}
/** Pure copy constructor */
@@ -337,6 +378,31 @@ Region::~Region ()
}
void
+Region::copy_stuff (boost::shared_ptr<const Region> other, nframes_t offset, nframes_t length, const string& name, layer_t layer, Flag flags)
+{
+ _frozen = 0;
+ _pending_changed = Change (0);
+ _read_data_count = 0;
+ _valid_transients = false;
+
+ _length = length;
+ _last_length = length;
+ _sync_position = other->_sync_position;
+ _ancestral_start = other->_ancestral_start;
+ _ancestral_length = other->_ancestral_length;
+ _stretch = other->_stretch;
+ _shift = other->_shift;
+ _name = name;
+ _last_position = 0;
+ _position = 0;
+ _layer = layer;
+ _flags = Flag (flags & ~(Locked|WholeFile|Hidden));
+ _first_edit = EditChangesNothing;
+ _last_layer_op = 0;
+ _positional_lock_style = AudioTime;
+}
+
+void
Region::set_playlist (boost::weak_ptr<Playlist> wpl)
{
boost::shared_ptr<Playlist> old_playlist = (_playlist.lock());
@@ -982,7 +1048,7 @@ Region::sync_offset (int& dir) const
}
nframes_t
-Region::adjust_to_sync (nframes_t pos)
+Region::adjust_to_sync (nframes_t pos) const
{
int sync_dir;
nframes_t offset = sync_offset (sync_dir);
@@ -1245,16 +1311,26 @@ Region::set_live_state (const XMLNode& node, Change& what_changed, bool send)
if ((prop = node.property ("stretch")) != 0) {
_stretch = atof (prop->value());
- if( _stretch == 0.0 )
+
+ /* fix problem with old sessions corrupted by an impossible
+ value for _stretch
+ */
+ if (_stretch == 0.0) {
_stretch = 1.0;
+ }
} else {
_stretch = 1.0;
}
if ((prop = node.property ("shift")) != 0) {
_shift = atof (prop->value());
- if( _shift == 0.0 )
+
+ /* fix problem with old sessions corrupted by an impossible
+ value for _shift
+ */
+ if (_shift == 0.0) {
_shift = 1.0;
+ }
} else {
_shift = 1.0;
}
diff --git a/libs/ardour/region_factory.cc b/libs/ardour/region_factory.cc
index 88925a7f16..742a65962e 100644
--- a/libs/ardour/region_factory.cc
+++ b/libs/ardour/region_factory.cc
@@ -37,7 +37,7 @@ sigc::signal<void,boost::shared_ptr<Region> > RegionFactory::CheckNewRegion;
boost::shared_ptr<Region>
RegionFactory::create (boost::shared_ptr<Region> region, nframes_t start,
- nframes_t length, std::string name,
+ nframes_t length, const std::string& name,
layer_t layer, Region::Flag flags, bool announce)
{
boost::shared_ptr<const AudioRegion> other_a;
@@ -91,13 +91,40 @@ RegionFactory::create (boost::shared_ptr<const Region> region)
boost::shared_ptr<Region>
RegionFactory::create (boost::shared_ptr<AudioRegion> region, nframes_t start,
- nframes_t length, std::string name,
+ nframes_t length, const std::string& name,
layer_t layer, Region::Flag flags, bool announce)
{
return create (boost::static_pointer_cast<Region> (region), start, length, name, layer, flags, announce);
}
boost::shared_ptr<Region>
+RegionFactory::create (boost::shared_ptr<Region> region, const SourceList& srcs,
+ const std::string& name, layer_t layer, Region::Flag flags, bool announce)
+
+{
+ boost::shared_ptr<const AudioRegion> other;
+
+ /* used by AudioFilter when constructing a new region that is intended to have nearly
+ identical settings to an original, but using different sources.
+ */
+
+ if ((other = boost::dynamic_pointer_cast<AudioRegion>(region)) != 0) {
+ AudioRegion* ar = new AudioRegion (other, srcs, srcs.front()->length(), name, layer, flags);
+ boost::shared_ptr<AudioRegion> arp (ar);
+ boost::shared_ptr<Region> ret (boost::static_pointer_cast<Region> (arp));
+ if (announce) {
+ CheckNewRegion (ret);
+ }
+ return ret;
+ } else {
+ fatal << _("programming error: RegionFactory::create() called with unknown Region type")
+ << endmsg;
+ /*NOTREACHED*/
+ return boost::shared_ptr<Region>();
+ }
+}
+
+boost::shared_ptr<Region>
RegionFactory::create (Session& session, XMLNode& node, bool yn)
{
boost::shared_ptr<Region> r = session.XMLRegionFactory (node, yn);
diff --git a/libs/ardour/reverse.cc b/libs/ardour/reverse.cc
index 02ec2924b0..9c15b1e4d9 100644
--- a/libs/ardour/reverse.cc
+++ b/libs/ardour/reverse.cc
@@ -70,6 +70,7 @@ Reverse::run (boost::shared_ptr<Region> r)
}
fpos = max (fstart, (fstart + region->length() - blocksize));
+
buf = new Sample[blocksize];
to_read = blocksize;
@@ -81,7 +82,7 @@ Reverse::run (boost::shared_ptr<Region> r)
for (n = 0, si = nsrcs.begin(); n < region->n_channels(); ++n, ++si) {
- /* read it in */
+ /* read it in directly from the source */
if (region->audio_source (n)->read (buf, fpos, to_read) != to_read) {
goto out;
@@ -92,7 +93,7 @@ Reverse::run (boost::shared_ptr<Region> r)
for (nframes_t i = 0; i < to_read/2; ++i) {
swap (buf[i],buf[to_read-1-i]);
}
-
+
/* write it out */
boost::shared_ptr<AudioSource> asrc(boost::dynamic_pointer_cast<AudioSource>(*si));
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index 5d1a26d3d0..96f26a515c 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -25,6 +25,7 @@
#include <pbd/xml++.h>
#include <pbd/enumwriter.h>
#include <pbd/stacktrace.h>
+#include <pbd/memento_command.h>
#include <ardour/timestamps.h>
#include <ardour/audioengine.h>
@@ -1087,6 +1088,31 @@ Route::set_solo (bool yn, void *src)
_soloed = yn;
solo_changed (src); /* EMIT SIGNAL */
_solo_control->Changed (); /* EMIT SIGNAL */
+ }
+
+ catch_up_on_solo_mute_override ();
+}
+
+void
+Route::catch_up_on_solo_mute_override ()
+{
+ if (Config->get_solo_model() != InverseMute) {
+ return;
+ }
+
+ {
+
+ Glib::Mutex::Lock lm (declick_lock);
+
+ if (_muted) {
+ if (Config->get_solo_mute_override()) {
+ desired_mute_gain = (_soloed?1.0:0.0);
+ } else {
+ desired_mute_gain = 0.0;
+ }
+ } else {
+ desired_mute_gain = 1.0;
+ }
}
}
@@ -1126,7 +1152,12 @@ Route::set_mute (bool yn, void *src)
_mute_control->Changed (); /* EMIT SIGNAL */
Glib::Mutex::Lock lm (declick_lock);
- desired_mute_gain = (yn?0.0f:1.0f);
+
+ if (_soloed && Config->get_solo_mute_override()){
+ desired_mute_gain = 1.0f;
+ } else {
+ desired_mute_gain = (yn?0.0f:1.0f);
+ }
}
}
@@ -1234,7 +1265,6 @@ Route::add_processors (const ProcessorList& others, ProcessorStreams* err)
return -1;
}
- (*i)->activate ();
(*i)->ActiveChanged.connect (bind (mem_fun (_session, &Session::update_latency_compensation), false, false));
}
@@ -3089,3 +3119,50 @@ Route::set_pending_declick (int declick)
}
+/** Shift automation forwards from a particular place, thereby inserting time.
+ * Adds undo commands for any shifts that are performed.
+ *
+ * @param pos Position to start shifting from.
+ * @param frames Amount to shift forwards by.
+ */
+
+void
+Route::shift (nframes64_t pos, nframes64_t frames)
+{
+#ifdef THIS_NEEDS_FIXING_FOR_V3
+
+ /* gain automation */
+ XMLNode &before = _gain_control->get_state ();
+ _gain_control->shift (pos, frames);
+ XMLNode &after = _gain_control->get_state ();
+ _session.add_command (new MementoCommand<AutomationList> (_gain_automation_curve, &before, &after));
+
+ /* pan automation */
+ for (std::vector<StreamPanner*>::iterator i = _panner->begin (); i != _panner->end (); ++i) {
+ Curve & c = (*i)->automation ();
+ XMLNode &before = c.get_state ();
+ c.shift (pos, frames);
+ XMLNode &after = c.get_state ();
+ _session.add_command (new MementoCommand<AutomationList> (c, &before, &after));
+ }
+
+ /* redirect automation */
+ {
+ Glib::RWLock::ReaderLock lm (redirect_lock);
+ for (RedirectList::iterator i = _redirects.begin (); i != _redirects.end (); ++i) {
+
+ set<uint32_t> a;
+ (*i)->what_has_automation (a);
+
+ for (set<uint32_t>::const_iterator j = a.begin (); j != a.end (); ++j) {
+ AutomationList & al = (*i)->automation_list (*j);
+ XMLNode &before = al.get_state ();
+ al.shift (pos, frames);
+ XMLNode &after = al.get_state ();
+ _session.add_command (new MementoCommand<AutomationList> (al, &before, &after));
+ }
+ }
+ }
+#endif
+
+}
diff --git a/libs/ardour/send.cc b/libs/ardour/send.cc
index 034bed77c3..58352a5dfe 100644
--- a/libs/ardour/send.cc
+++ b/libs/ardour/send.cc
@@ -27,6 +27,8 @@
#include <ardour/audio_port.h>
#include <ardour/buffer_set.h>
#include <ardour/meter.h>
+#include <ardour/panner.h>
+
#include "i18n.h"
using namespace ARDOUR;
@@ -55,6 +57,41 @@ Send::Send (const Send& other)
: IOProcessor (other._session, string_compose (_("send %1"), (bitslot = other._session.next_send_id()) + 1), other.placement())
{
_metering = false;
+
+ expected_inputs.set (DataType::AUDIO, 0);
+
+#ifdef THIS_NEEDS_FIXING_FOR_V3
+
+ /* set up the same outputs, and connect them to the same places */
+
+ _io->no_panner_reset = true;
+
+ for (uint32_t i = 0; i < other.n_outputs (); ++i) {
+ add_output_port ("", 0);
+ Port* p = other.output (i);
+ if (p) {
+ /* this is what the other send's output is connected to */
+ const char **connections = p->get_connections ();
+ if (connections) {
+ for (uint32_t c = 0; connections[c]; ++c) {
+ connect_output (output (i), connections [c], 0);
+ }
+ }
+ }
+ }
+
+ /* setup panner */
+
+ _io->no_panner_reset = false;
+
+ /* copy state */
+
+ XMLNode& other_state (const_cast<Send*>(&other)->_panner->get_state());
+ _panner->set_state (other_state);
+
+ delete &other_state;
+#endif
+
ProcessorCreated (this); /* EMIT SIGNAL */
}
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index 14ef0e1ac5..875b317936 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -123,23 +123,31 @@ Session::Session (AudioEngine &eng,
_scratch_buffers(new BufferSet()),
_silent_buffers(new BufferSet()),
_mix_buffers(new BufferSet()),
+ mmc (0),
_mmc_port (default_mmc_port),
_mtc_port (default_mtc_port),
_midi_port (default_midi_port),
_midi_clock_port (default_midi_clock_port),
_session_dir (new SessionDirectory(fullpath)),
pending_events (2048),
+ state_tree (0),
+ butler_mixdown_buffer (0),
+ butler_gain_buffer (0),
post_transport_work((PostTransportWork)0),
_send_smpte_update (false),
- midi_requests (128),
+ midi_thread (pthread_t (0)),
+ midi_requests (128), // the size of this should match the midi request pool size
diskstreams (new DiskstreamList),
routes (new RouteList),
auditioner ((Auditioner*) 0),
_total_free_4k_blocks (0),
_bundle_xml_node (0),
_click_io ((IO*) 0),
+ click_data (0),
+ click_emphasis_data (0),
main_outs (0),
_metadata (new SessionMetadata())
+
{
bool new_session;
@@ -196,21 +204,30 @@ Session::Session (AudioEngine &eng,
_scratch_buffers(new BufferSet()),
_silent_buffers(new BufferSet()),
_mix_buffers(new BufferSet()),
+ mmc (0),
_mmc_port (default_mmc_port),
_mtc_port (default_mtc_port),
_midi_port (default_midi_port),
_midi_clock_port (default_midi_clock_port),
_session_dir ( new SessionDirectory(fullpath)),
pending_events (2048),
+ state_tree (0),
+ butler_mixdown_buffer (0),
+ butler_gain_buffer (0),
post_transport_work((PostTransportWork)0),
_send_smpte_update (false),
+ midi_thread (pthread_t (0)),
midi_requests (16),
diskstreams (new DiskstreamList),
routes (new RouteList),
+ auditioner ((Auditioner *) 0),
_total_free_4k_blocks (0),
_bundle_xml_node (0),
- main_outs (0)
-
+ _click_io ((IO *) 0),
+ click_data (0),
+ click_emphasis_data (0),
+ main_outs (0),
+ _metadata (new SessionMetadata())
{
bool new_session;
@@ -316,18 +333,16 @@ Session::destroy ()
/* clear state tree so that no references to objects are held any more */
- if (state_tree) {
- delete state_tree;
- }
+ delete state_tree;
terminate_butler_thread ();
//terminate_midi_thread ();
- if (click_data && click_data != default_click) {
+ if (click_data != default_click) {
delete [] click_data;
}
- if (click_emphasis_data && click_emphasis_data != default_click_emphasis) {
+ if (click_emphasis_data != default_click_emphasis) {
delete [] click_emphasis_data;
}
@@ -471,19 +486,12 @@ Session::destroy ()
i = tmp;
}
- if (butler_mixdown_buffer) {
- delete [] butler_mixdown_buffer;
- }
-
- if (butler_gain_buffer) {
- delete [] butler_gain_buffer;
- }
+ delete [] butler_mixdown_buffer;
+ delete [] butler_gain_buffer;
Crossfade::set_buffer_size (0);
- if (mmc) {
- delete mmc;
- }
+ delete mmc;
}
void
@@ -1213,6 +1221,10 @@ Session::audible_frame () const
nframes_t offset;
nframes_t tf;
+ if (_transport_speed == 0.0f && non_realtime_work_pending()) {
+ return last_stop_frame;
+ }
+
/* the first of these two possible settings for "offset"
mean that the audible frame is stationary until
audio emerges from the latency compensation
@@ -1241,24 +1253,43 @@ Session::audible_frame () const
} else {
tf = _transport_frame;
}
-
- if (_transport_speed == 0) {
- return tf;
- }
-
- if (tf < offset) {
- return 0;
- }
-
+
ret = tf;
if (!non_realtime_work_pending()) {
/* MOVING */
- /* take latency into account */
+ /* check to see if we have passed the first guaranteed
+ audible frame past our last stopping position. if not,
+ the return that last stopping point because in terms
+ of audible frames, we have not moved yet.
+ */
+
+ if (_transport_speed > 0.0f) {
+
+ if (!play_loop || !have_looped) {
+ if (tf < last_stop_frame + offset) {
+ return last_stop_frame;
+
+ }
+ }
+
+
+ /* forwards */
+ ret -= offset;
+
+ } else if (_transport_speed < 0.0f) {
- ret -= offset;
+ /* XXX wot? no backward looping? */
+
+ if (tf > last_stop_frame - offset) {
+ return last_stop_frame;
+ } else {
+ /* backwards */
+ ret += offset;
+ }
+ }
}
return ret;
@@ -1875,6 +1906,10 @@ Session::new_audio_route (int input_channels, int output_channels, uint32_t how_
_engine.get_physical_outputs (DataType::AUDIO, physoutputs);
_engine.get_physical_inputs (DataType::AUDIO, physinputs);
+
+ n_physical_audio_outputs = physoutputs.size();
+ n_physical_audio_inputs = physinputs.size();
+
control_id = ntracks() + nbusses() + 1;
while (how_many) {
@@ -1900,21 +1935,24 @@ Session::new_audio_route (int input_channels, int output_channels, uint32_t how_
goto failure;
}
- for (uint32_t x = 0; n_physical_inputs && x < bus->n_inputs().n_audio(); ++x) {
- port = "";
+ /*
+ for (uint32_t x = 0; n_physical_audio_inputs && x < bus->n_inputs(); ++x) {
+
+ port = "";
+
if (Config->get_input_auto_connect() & AutoConnectPhysical) {
- port = physinputs[((n+x)%n_physical_inputs)];
- }
-
+ port = physinputs[((n+x)%n_physical_audio_inputs)];
+ }
+
if (port.length() && bus->connect_input (bus->input (x), port, this)) {
break;
}
}
+ */
- for (uint32_t x = 0; x < bus->n_outputs().n_audio(); ++x) {
-
+ for (uint32_t x = 0; n_physical_audio_outputs && x < bus->n_outputs().n_audio(); ++x) {
port = "";
if (Config->get_output_auto_connect() & AutoConnectPhysical) {
@@ -2240,8 +2278,6 @@ Session::update_route_solo_state ()
bool is_track = false;
bool signal = false;
- /* caller must hold RouteLock */
-
/* this is where we actually implement solo by changing
the solo mute setting of each track.
*/
@@ -2341,7 +2377,24 @@ Session::catch_up_on_solo ()
has.
*/
update_route_solo_state();
-}
+}
+
+void
+Session::catch_up_on_solo_mute_override ()
+{
+ if (Config->get_solo_model() != InverseMute) {
+ return;
+ }
+
+ /* this is called whenever the param solo-mute-override is
+ changed.
+ */
+ shared_ptr<RouteList> r = routes.reader ();
+
+ for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+ (*i)->catch_up_on_solo_mute_override ();
+ }
+}
shared_ptr<Route>
Session::route_by_name (string name)
@@ -4220,8 +4273,13 @@ Session::get_silent_buffers (ChanCount count)
BufferSet&
Session::get_scratch_buffers (ChanCount count)
{
- assert(_scratch_buffers->available() >= count);
- _scratch_buffers->set_count(count);
+ if (count != ChanCount::ZERO) {
+ assert(_scratch_buffers->available() >= count);
+ _scratch_buffers->set_count(count);
+ } else {
+ _scratch_buffers->set_count (_scratch_buffers->available());
+ }
+
return *_scratch_buffers;
}
diff --git a/libs/ardour/session_butler.cc b/libs/ardour/session_butler.cc
index 02f8569a3d..5fe7a92d3d 100644
--- a/libs/ardour/session_butler.cc
+++ b/libs/ardour/session_butler.cc
@@ -162,7 +162,7 @@ Session::wait_till_butler_finished ()
void *
Session::_butler_thread_work (void* arg)
{
- PBD::ThreadCreated (pthread_self(), X_("Butler"));
+ PBD::notify_gui_about_thread_creation (pthread_self(), X_("Butler"));
return ((Session *) arg)->butler_thread_work ();
return 0;
}
diff --git a/libs/ardour/session_export.cc b/libs/ardour/session_export.cc
index 2e19041b9c..90ad257d3b 100644
--- a/libs/ardour/session_export.cc
+++ b/libs/ardour/session_export.cc
@@ -60,6 +60,7 @@ Session::get_export_status ()
return export_status;
}
+
int
Session::pre_export ()
{
diff --git a/libs/ardour/session_midi.cc b/libs/ardour/session_midi.cc
index 64903f24a2..b85df5b714 100644
--- a/libs/ardour/session_midi.cc
+++ b/libs/ardour/session_midi.cc
@@ -1120,7 +1120,7 @@ Session::midi_thread_work ()
bool restart;
vector<MIDI::Port*> ports;
- PBD::ThreadCreatedWithRequestSize (pthread_self(), X_("MIDI"), 2048);
+ PBD::notify_gui_about_thread_creation (pthread_self(), X_("MIDI"), 2048);
memset (&rtparam, 0, sizeof (rtparam));
rtparam.sched_priority = 9; /* XXX should be relative to audio (JACK) thread */
@@ -1145,6 +1145,7 @@ Session::midi_thread_work ()
pfd[nfds].fd = _mmc_port->selectable();
pfd[nfds].events = POLLIN|POLLHUP|POLLERR;
ports[nfds] = _mmc_port;
+ //cerr << "MIDI port " << nfds << " = MMC @ " << _mmc_port << endl;
nfds++;
}
@@ -1157,6 +1158,7 @@ Session::midi_thread_work ()
pfd[nfds].fd = _mtc_port->selectable();
pfd[nfds].events = POLLIN|POLLHUP|POLLERR;
ports[nfds] = _mtc_port;
+ //cerr << "MIDI port " << nfds << " = MTC @ " << _mtc_port << endl;
nfds++;
}
@@ -1175,6 +1177,7 @@ Session::midi_thread_work ()
pfd[nfds].fd = _midi_port->selectable();
pfd[nfds].events = POLLIN|POLLHUP|POLLERR;
ports[nfds] = _midi_port;
+ // cerr << "MIDI port " << nfds << " = MIDI @ " << _midi_port << endl;
nfds++;
}
diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc
index 3b81092a96..c2e78df643 100644
--- a/libs/ardour/session_process.cc
+++ b/libs/ardour/session_process.cc
@@ -677,12 +677,13 @@ Session::follow_slave (nframes_t nframes, nframes_t offset)
#if 0
cerr << "adjust using " << delta
- << " towards " << adjusted_speed
- << " ratio = " << adjusted_speed / slave_speed
- << " current = " << _transport_speed
- << " slave @ " << slave_speed
- << endl;
-#endif
+ << " towards " << adjusted_speed
+ << " ratio = " << adjusted_speed / slave_speed
+ << " current = " << _transport_speed
+ << " slave @ " << slave_speed
+ << endl;
+#endif
+
request_transport_speed (adjusted_speed);
#if 1
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index b1a494584a..cb4a9e5813 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -165,6 +165,7 @@ Session::first_stage_init (string fullpath, string snapshot_name)
g_atomic_int_set (&_record_status, Disabled);
loop_changing = false;
play_loop = false;
+ have_looped = false;
_last_roll_location = 0;
_last_record_location = 0;
pending_locate_frame = 0;
@@ -172,7 +173,6 @@ Session::first_stage_init (string fullpath, string snapshot_name)
pending_locate_flush = false;
audio_dstream_buffer_size = 0;
midi_dstream_buffer_size = 0;
- state_tree = 0;
state_was_pending = false;
set_next_event ();
outbound_mtc_smpte_frame = 0;
@@ -187,9 +187,6 @@ Session::first_stage_init (string fullpath, string snapshot_name)
_state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
_slave = 0;
- butler_mixdown_buffer = 0;
- butler_gain_buffer = 0;
- mmc = 0;
session_send_mmc = false;
session_send_mtc = false;
post_transport_work = PostTransportWork (0);
@@ -227,8 +224,6 @@ Session::first_stage_init (string fullpath, string snapshot_name)
waveforms for clicks.
*/
- click_data = 0;
- click_emphasis_data = 0;
click_length = 0;
click_emphasis_length = 0;
_clicking = false;
@@ -362,6 +357,8 @@ Session::second_stage_init (bool new_session)
MidiClockTicker::instance().set_session(*this);
MIDI::Name::MidiPatchManager::instance().set_session(*this);
+ /* initial program change will be delivered later; see ::config_changed() */
+
BootMessage (_("Reset Control Protocols"));
ControlProtocolManager::instance().set_session (*this);
@@ -3272,6 +3269,17 @@ Session::config_changed (const char* parameter_name)
_mmc_port->midimsg (buf, sizeof (buf), 0);
}
+ } else if (PARAM_IS ("initial-program-change")) {
+
+ if (_mmc_port && Config->get_initial_program_change() >= 0) {
+ MIDI::byte* buf = new MIDI::byte[2];
+
+ buf[0] = MIDI::program; // channel zero by default
+ buf[1] = (Config->get_initial_program_change() & 0x7f);
+ // deliver_midi (_mmc_port, buf, 2);
+ }
+ } else if (PARAM_IS ("solo-mute-override")) {
+ catch_up_on_solo_mute_override ();
}
set_dirty ();
diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc
index 7f574d4811..5612429d0d 100644
--- a/libs/ardour/session_transport.cc
+++ b/libs/ardour/session_transport.cc
@@ -212,8 +212,7 @@ Session::butler_transport_work ()
}
if (post_transport_work & PostTransportReverse) {
-
-
+
clear_clicks();
cumulative_rf_motion = 0;
reset_rf_scale (0);
@@ -449,6 +448,12 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
_requested_return_frame = -1;
}
+ have_looped = false;
+
+ send_full_time_code (0);
+ deliver_mmc (MIDI::MachineControl::cmdStop, 0);
+ deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
+
if (did_record) {
/* XXX its a little odd that we're doing this here
@@ -779,7 +784,7 @@ Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool w
}
}
}
-
+ have_looped = true;
TransportLooped(); // EMIT SIGNAL
}
}
@@ -886,6 +891,7 @@ Session::set_transport_speed (float speed, bool abort)
if ((_transport_speed && speed * _transport_speed < 0.0f) || (_last_transport_speed * speed < 0.0f) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
+ last_stop_frame = _transport_frame;
}
_last_transport_speed = _transport_speed;
@@ -951,6 +957,7 @@ void
Session::start_transport ()
{
_last_roll_location = _transport_frame;
+ have_looped = false;
/* if record status is Enabled, move it to Recording. if its
already Recording, move it to Disabled.
diff --git a/libs/ardour/sndfileimportable.cc b/libs/ardour/sndfileimportable.cc
index eb0e8a8afb..5cd00a8e96 100644
--- a/libs/ardour/sndfileimportable.cc
+++ b/libs/ardour/sndfileimportable.cc
@@ -1,5 +1,6 @@
#include <ardour/sndfileimportable.h>
#include <sndfile.h>
+#include <iostream>
using namespace ARDOUR;
using namespace std;
diff --git a/libs/ardour/sndfilesource.cc b/libs/ardour/sndfilesource.cc
index 097f0c235d..6a4b5e325d 100644
--- a/libs/ardour/sndfilesource.cc
+++ b/libs/ardour/sndfilesource.cc
@@ -317,7 +317,12 @@ SndFileSource::read_unlocked (Sample *dst, nframes_t start, nframes_t cnt) const
if (_info.channels == 1) {
nframes_t ret = sf_read_float (sf, dst, file_cnt);
- _read_data_count = cnt * sizeof(float);
+ _read_data_count = ret * sizeof(float);
+ if (ret != file_cnt) {
+ char errbuf[256];
+ sf_error_str (0, errbuf, sizeof (errbuf) - 1);
+ cerr << string_compose(_("SndFileSource: @ %1 could not read %2 within %3 (%4) (len = %5)"), start, file_cnt, _name.substr (1), errbuf, _length) << endl;
+ }
return ret;
}
}
@@ -381,7 +386,7 @@ SndFileSource::nondestructive_write_unlocked (Sample *data, nframes_t cnt)
}
_write_data_count = cnt;
-
+
return cnt;
}
diff --git a/libs/ardour/source_factory.cc b/libs/ardour/source_factory.cc
index 0b7c0f3d9e..4ada6b766c 100644
--- a/libs/ardour/source_factory.cc
+++ b/libs/ardour/source_factory.cc
@@ -52,7 +52,7 @@ std::list<boost::weak_ptr<AudioSource> > SourceFactory::files_with_peaks;
static void
peak_thread_work ()
{
- PBD::ThreadCreated (pthread_self(), string ("peakbuilder-") + to_string (pthread_self(), std::dec));
+ PBD::notify_gui_about_thread_creation (pthread_self(), string ("peakbuilder-") + to_string (pthread_self(), std::dec));
while (true) {
diff --git a/libs/ardour/utils.cc b/libs/ardour/utils.cc
index c598a3d279..18194678ed 100644
--- a/libs/ardour/utils.cc
+++ b/libs/ardour/utils.cc
@@ -282,7 +282,7 @@ compute_equal_power_fades (nframes_t nframes, float* in, float* out)
{
double step;
- step = 1.0/nframes;
+ step = 1.0/(nframes-1);
in[0] = 0.0f;