diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2008-12-12 14:43:24 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2008-12-12 14:43:24 +0000 |
commit | bc89fe0147c04b67141936d109c00dfd4d69cc4b (patch) | |
tree | 544ff450c40fe1f43853a8420228a26f27f1eafb /libs/ardour | |
parent | 30daaebaa2d90d6b0e8673143ccc3cacd7bd1753 (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')
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; |