From ab6f1ed9bafa869648b6e94ee5186ff317b32c3e Mon Sep 17 00:00:00 2001 From: David Robillard Date: Thu, 10 Aug 2006 01:22:45 +0000 Subject: Merged with trunk R776 git-svn-id: svn://localhost/ardour2/branches/midi@777 d708f5d6-7413-0410-9779-e7cbd77b26cf --- libs/ardour/SConscript | 4 + libs/ardour/ardour/ardour.h | 2 +- libs/ardour/ardour/audio_unit.h | 76 ++++++- libs/ardour/ardour/automation_event.h | 8 +- libs/ardour/ardour/ladspa_plugin.h | 15 +- libs/ardour/ardour/location.h | 6 + libs/ardour/ardour/playlist.h | 3 + libs/ardour/ardour/plugin.h | 30 +-- libs/ardour/ardour/plugin_manager.h | 12 +- libs/ardour/ardour/route.h | 2 +- libs/ardour/ardour/session.h | 75 +++++-- libs/ardour/ardour/state_manager.h | 2 + libs/ardour/ardour/tempo.h | 3 + libs/ardour/ardour/track.h | 2 +- libs/ardour/ardour/vst_plugin.h | 11 +- libs/ardour/audio_diskstream.cc | 6 +- libs/ardour/audio_unit.cc | 388 ++++++++++++++++++++++++++++------ libs/ardour/automation_event.cc | 14 ++ libs/ardour/globals.cc | 6 +- libs/ardour/insert.cc | 26 +-- libs/ardour/io.cc | 2 +- libs/ardour/ladspa_plugin.cc | 25 ++- libs/ardour/plugin.cc | 42 ++++ libs/ardour/plugin_manager.cc | 96 +-------- libs/ardour/session.cc | 4 + libs/ardour/session_command.cc | 101 +++++++++ libs/ardour/session_state.cc | 70 ++++-- libs/ardour/session_transport.cc | 8 +- libs/ardour/state_manager.cc | 3 + libs/ardour/track.cc | 21 +- libs/ardour/vst_plugin.cc | 30 +++ 31 files changed, 851 insertions(+), 242 deletions(-) create mode 100644 libs/ardour/session_command.cc (limited to 'libs/ardour') diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript index fc94a13888..feb93ec293 100644 --- a/libs/ardour/SConscript +++ b/libs/ardour/SConscript @@ -83,6 +83,7 @@ send.cc session.cc session_butler.cc session_click.cc +session_command.cc session_events.cc session_export.cc session_midi.cc @@ -215,6 +216,9 @@ ardour.Merge ([ if ardour['LIBLO']: ardour.Merge ([ libraries['lo'] ]) +if ardour['COREAUDIO']: + ardour.Merge ([ libraries['appleutility'] ]) + ardour.VersionBuild(['version.cc', 'ardour/version.h'], 'SConscript') def SharedAsmObjectEmitter(target, source, env): diff --git a/libs/ardour/ardour/ardour.h b/libs/ardour/ardour/ardour.h index ba92416339..c138cbf32f 100644 --- a/libs/ardour/ardour/ardour.h +++ b/libs/ardour/ardour/ardour.h @@ -45,7 +45,7 @@ namespace ARDOUR { static const jack_nframes_t max_frames = JACK_MAX_FRAMES; - int init (AudioEngine&, bool with_vst, bool try_optimization); + int init (AudioEngine& engine, bool with_vst, bool try_optimization); int cleanup (); diff --git a/libs/ardour/ardour/audio_unit.h b/libs/ardour/ardour/audio_unit.h index ec437109a4..1c8d6cbc2d 100644 --- a/libs/ardour/ardour/audio_unit.h +++ b/libs/ardour/ardour/audio_unit.h @@ -21,36 +21,93 @@ #ifndef __ardour_audio_unit_h__ #define __ardour_audio_unit_h__ +#include + #include +#include +#include +#include #include #include -struct ComponentDescription; +class CAComponent; +class CAAudioUnit; +class CAComponentDescription; +struct AudioBufferList; namespace ARDOUR { +class AudioEngine; +class Session; + class AUPlugin : public ARDOUR::Plugin { public: - AUPlugin (AudioEngine& engine, Session& session) : Plugin(engine, session) {}; - virtual ~AUPlugin () {}; + AUPlugin (AudioEngine& engine, Session& session, CAComponent* comp); + virtual ~AUPlugin (); + + uint32_t unique_id () const; + const char * label () const; + const char * name () const { return _info->name.c_str(); } + const char * maker () const; + uint32_t parameter_count () const; + float default_value (uint32_t port); + jack_nframes_t latency () const; + void set_parameter (uint32_t which, float val); + float get_parameter (uint32_t which) const; + + int get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const; + uint32_t nth_parameter (uint32_t which, bool& ok) const; + void activate (); + void deactivate (); + void set_block_size (jack_nframes_t nframes); + + int connect_and_run (vector& bufs, uint32_t maxbuf, int32_t& in, int32_t& out, jack_nframes_t nframes, jack_nframes_t offset); + std::set automatable() const; + void store_state (ARDOUR::PluginState&); + void restore_state (ARDOUR::PluginState&); + string describe_parameter (uint32_t); + string state_node_name () const { return "audiounit"; } + void print_parameter (uint32_t, char*, uint32_t len) const; + + bool parameter_is_audio (uint32_t) const; + bool parameter_is_control (uint32_t) const; + bool parameter_is_input (uint32_t) const; + bool parameter_is_output (uint32_t) const; + + XMLNode& get_state(); + int set_state(const XMLNode& node); + + bool save_preset (string name); + bool load_preset (const string preset_label); + std::vector get_presets (); + + bool has_editor () const; + + private: + CAComponent* comp; + CAAudioUnit* unit; + + AudioBufferList* in_list; + AudioBufferList* out_list; + + std::vector > parameter_map; }; class AUPluginInfo : public PluginInfo { - public: - typedef boost::shared_ptr CompDescPtr; - + public: AUPluginInfo () { }; - ~AUPluginInfo () { }; + ~AUPluginInfo (); - CompDescPtr desc; + CAComponentDescription* desc; static PluginInfoList discover (); + PluginPtr load (Session& session); private: - friend class PluginManager; + static std::string get_name (CAComponentDescription&); }; typedef boost::shared_ptr AUPluginInfoPtr; @@ -58,4 +115,3 @@ typedef boost::shared_ptr AUPluginInfoPtr; } // namespace ARDOUR #endif // __ardour_audio_unit_h__ - diff --git a/libs/ardour/ardour/automation_event.h b/libs/ardour/ardour/automation_event.h index 78daa531dd..5864de73c6 100644 --- a/libs/ardour/ardour/automation_event.h +++ b/libs/ardour/ardour/automation_event.h @@ -51,7 +51,7 @@ struct ControlEvent { }; -class AutomationList : public StateManager +class AutomationList : public StateManager, public Stateful { public: typedef std::list AutomationEventList; @@ -153,6 +153,11 @@ class AutomationList : public StateManager virtual void store_state (XMLNode& node) const; virtual void load_state (const XMLNode&); + XMLNode &get_state(void); + int set_state (const XMLNode &s); + + PBD::ID id() { return _id; } + void set_max_xval (double); double get_max_xval() const { return max_xval; } @@ -179,6 +184,7 @@ class AutomationList : public StateManager }; protected: + PBD::ID _id; struct State : public ARDOUR::StateManager::State { AutomationEventList events; diff --git a/libs/ardour/ardour/ladspa_plugin.h b/libs/ardour/ardour/ladspa_plugin.h index e4aba93ef6..99fc884898 100644 --- a/libs/ardour/ardour/ladspa_plugin.h +++ b/libs/ardour/ardour/ladspa_plugin.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2000 Paul Davis + Copyright (C) 2000-2006 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -137,6 +137,17 @@ class LadspaPlugin : public ARDOUR::Plugin void run (jack_nframes_t nsamples); void latency_compute_run (); }; -} + +class LadspaPluginInfo : public PluginInfo { + public: + LadspaPluginInfo () { }; + ~LadspaPluginInfo () { }; + + PluginPtr load (Session& session); +}; + +typedef boost::shared_ptr LadspaPluginInfoPtr; + +} // namespace ARDOUR #endif /* __ardour_ladspa_plugin_h__ */ diff --git a/libs/ardour/ardour/location.h b/libs/ardour/ardour/location.h index 30c02a80a1..ff953d1d78 100644 --- a/libs/ardour/ardour/location.h +++ b/libs/ardour/ardour/location.h @@ -119,7 +119,10 @@ class Location : public Stateful, public sigc::trackable XMLNode& get_state (void); int set_state (const XMLNode&); + PBD::ID id() { return _id; } + private: + PBD::ID _id; string _name; jack_nframes_t _start; jack_nframes_t _end; @@ -145,6 +148,7 @@ class Locations : public Stateful, public StateManager XMLNode& get_state (void); int set_state (const XMLNode&); + PBD::ID id() { return _id; } Location* auto_loop_location () const; Location* auto_punch_location () const; @@ -197,6 +201,8 @@ class Locations : public Stateful, public StateManager Change restore_state (StateManager::State&); StateManager::State* state_factory (std::string why) const; + + PBD::ID _id; }; } // namespace ARDOUR diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h index 9fb5b0eb2b..b389258860 100644 --- a/libs/ardour/ardour/playlist.h +++ b/libs/ardour/ardour/playlist.h @@ -76,6 +76,7 @@ class Playlist : public Stateful, public StateManager { EditMode get_edit_mode() const { return _edit_mode; } void set_edit_mode (EditMode); + PBD::ID id() { return _id; } /* Editing operations */ void add_region (const Region&, jack_nframes_t position, float times = 1, bool with_save = true); @@ -273,6 +274,8 @@ class Playlist : public Stateful, public StateManager { void unset_freeze_child (Playlist*); void timestamp_layer_op (Region&); + + PBD::ID _id; }; } /* namespace ARDOUR */ diff --git a/libs/ardour/ardour/plugin.h b/libs/ardour/ardour/plugin.h index 86666c19af..6b11a975ca 100644 --- a/libs/ardour/ardour/plugin.h +++ b/libs/ardour/ardour/plugin.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2000 Paul Davis + Copyright (C) 2000-2006 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,8 +18,8 @@ $Id$ */ -#ifndef __ardour_ladspa_h__ -#define __ardour_ladspa_h__ +#ifndef __ardour_plugin_h__ +#define __ardour_plugin_h__ #include #include @@ -46,6 +46,9 @@ namespace ARDOUR { class AudioEngine; class Session; +class Plugin; +typedef boost::shared_ptr PluginPtr; + class PluginInfo { public: enum Type { @@ -54,11 +57,12 @@ class PluginInfo { VST }; - PluginInfo () { }; + PluginInfo () { } PluginInfo (const PluginInfo &o) : name(o.name), n_inputs(o.n_inputs), n_outputs(o.n_outputs), unique_id(o.unique_id), path (o.path), index(o.index) {} - ~PluginInfo () { }; + virtual ~PluginInfo () { } + string name; string category; uint32_t n_inputs; @@ -67,7 +71,9 @@ class PluginInfo { long unique_id; - private: + virtual PluginPtr load (Session& session) = 0; + + protected: friend class PluginManager; string path; uint32_t index; @@ -82,7 +88,7 @@ class Plugin : public Stateful, public sigc::trackable public: Plugin (ARDOUR::AudioEngine&, ARDOUR::Session&); Plugin (const Plugin&); - ~Plugin (); + virtual ~Plugin (); struct ParameterDescriptor { @@ -143,8 +149,8 @@ class Plugin : public Stateful, public sigc::trackable PBD::Controllable *get_nth_control (uint32_t); - PluginInfo & get_info() { return _info; } - void set_info (const PluginInfo &inf) { _info = inf; } + PluginInfoPtr get_info() { return _info; } + void set_info (const PluginInfoPtr inf) { _info = inf; } ARDOUR::AudioEngine& engine() const { return _engine; } ARDOUR::Session& session() const { return _session; } @@ -155,7 +161,7 @@ class Plugin : public Stateful, public sigc::trackable protected: ARDOUR::AudioEngine& _engine; ARDOUR::Session& _session; - PluginInfo _info; + PluginInfoPtr _info; uint32_t _cycles; map presets; bool save_preset(string name, string domain /* vst, ladspa etc. */); @@ -181,9 +187,7 @@ class Plugin : public Stateful, public sigc::trackable vector controls; }; -/* this is actually defined in plugin_manager.cc */ - -boost::shared_ptr find_plugin(ARDOUR::Session&, string name, long unique_id, PluginInfo::Type); +PluginPtr find_plugin(ARDOUR::Session&, string name, long unique_id, PluginInfo::Type); } // namespace ARDOUR diff --git a/libs/ardour/ardour/plugin_manager.h b/libs/ardour/ardour/plugin_manager.h index 8543ad5285..8e6c0bd1c7 100644 --- a/libs/ardour/ardour/plugin_manager.h +++ b/libs/ardour/ardour/plugin_manager.h @@ -5,42 +5,34 @@ #include #include -#include - #include #include #include namespace ARDOUR { -class PluginInfo; class Plugin; class Session; class AudioEngine; class PluginManager { public: - PluginManager (ARDOUR::AudioEngine&); + PluginManager (); ~PluginManager (); ARDOUR::PluginInfoList &vst_plugin_info () { return _vst_plugin_info; } ARDOUR::PluginInfoList &ladspa_plugin_info () { return _ladspa_plugin_info; } - ARDOUR::PluginInfoList &au_plugin_info () { return _au_plugin_info; } void refresh (); int add_ladspa_directory (std::string dirpath); int add_vst_directory (std::string dirpath); - boost::shared_ptr load (ARDOUR::Session& s, PluginInfoPtr info); - static PluginManager* the_manager() { return _manager; } private: - ARDOUR::AudioEngine& _engine; ARDOUR::PluginInfoList _vst_plugin_info; ARDOUR::PluginInfoList _ladspa_plugin_info; - ARDOUR::PluginInfoList _au_plugin_info; std::map rdf_type; std::string ladspa_path; @@ -60,8 +52,6 @@ class PluginManager { int ladspa_discover_from_path (std::string path); int ladspa_discover (std::string path); - int au_discover (); - std::string get_ladspa_category (uint32_t id); static PluginManager* _manager; // singleton diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index 8271c1cf6a..d1db818e40 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -97,7 +97,7 @@ class Route : public IO virtual int silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset, bool can_record, bool rec_monitors_input); virtual void toggle_monitor_input (); - virtual bool can_record() const { return false; } + virtual bool can_record() { return false; } virtual void set_record_enable (bool yn, void *src) {} virtual bool record_enabled() const { return false; } virtual void handle_transport_stopped (bool abort, bool did_locate, bool flush_redirects); diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index d39807be3f..6eb025f076 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -489,6 +489,7 @@ class Session : public sigc::trackable, public Stateful int save_state (string snapshot_name, bool pending = false); int restore_state (string snapshot_name); int save_template (string template_name); + int save_history (); static int rename_template (string old_name, string new_name); @@ -501,7 +502,7 @@ class Session : public sigc::trackable, public Stateful static vector* possible_states(string path); XMLNode& get_state(); - int set_state(const XMLNode& node); + int set_state(const XMLNode& node); // not idempotent XMLNode& get_template(); void add_instant_xml (XMLNode&, const std::string& dir); @@ -844,23 +845,65 @@ class Session : public sigc::trackable, public Stateful string next_undo() const { return history.next_undo(); } string next_redo() const { return history.next_redo(); } - void begin_reversible_command (string cmd_name, UndoAction *private_undo = 0); - void commit_reversible_command (UndoAction* private_redo = 0); + void begin_reversible_command (string cmd_name); + void commit_reversible_command (Command* cmd = 0); - void add_undo (const UndoAction& ua) { - current_cmd.add_undo (ua); - } - void add_redo (const UndoAction& ua) { - current_cmd.add_redo (ua); - } - void add_redo_no_execute (const UndoAction& ua) { - current_cmd.add_redo_no_execute (ua); + void add_command (Command *const cmd) { + current_trans.add_command (cmd); } - UndoAction global_solo_memento (void *src); - UndoAction global_mute_memento (void *src); - UndoAction global_record_enable_memento (void *src); - UndoAction global_metering_memento (void *src); + // these commands are implemented in libs/ardour/session_command.cc + class GlobalSoloStateCommand : public Command + { + GlobalRouteBooleanState before, after; + Session &sess; + void *src; + public: + GlobalSoloStateCommand(Session &, void *src); + void operator()(); + void undo(); + XMLNode &get_state(); + void mark(); + }; + + class GlobalMuteStateCommand : public Command + { + GlobalRouteBooleanState before, after; + Session &sess; + void *src; + public: + GlobalMuteStateCommand(Session &, void *src); + void operator()(); + void undo(); + XMLNode &get_state(); + void mark(); + }; + + class GlobalRecordEnableStateCommand : public Command + { + GlobalRouteBooleanState before, after; + Session &sess; + void *src; + public: + GlobalRecordEnableStateCommand(Session &, void *src); + void operator()(); + void undo(); + XMLNode &get_state(); + void mark(); + }; + + class GlobalMeteringStateCommand : public Command + { + GlobalRouteMeterState before, after; + Session &sess; + void *src; + public: + GlobalMeteringStateCommand(Session &, void *src); + void operator()(); + void undo(); + XMLNode &get_state(); + void mark(); + }; /* edit mode */ @@ -1635,7 +1678,7 @@ class Session : public sigc::trackable, public Stateful void reverse_diskstream_buffers (); UndoHistory history; - UndoCommand current_cmd; + UndoTransaction current_trans; GlobalRouteBooleanState get_global_route_boolean (bool (Route::*method)(void) const); GlobalRouteMeterState get_global_route_metering (); diff --git a/libs/ardour/ardour/state_manager.h b/libs/ardour/ardour/state_manager.h index 19ee2e624a..99bfcfc3ce 100644 --- a/libs/ardour/ardour/state_manager.h +++ b/libs/ardour/ardour/state_manager.h @@ -35,6 +35,8 @@ class StateManager : public sigc::trackable state_id_t _current_state_id; + virtual bool should_save_state () const { return true; } + static void prohibit_save (); static void allow_save (const char* why, bool dosave); diff --git a/libs/ardour/ardour/tempo.h b/libs/ardour/ardour/tempo.h index db06894607..bfd3e429c3 100644 --- a/libs/ardour/ardour/tempo.h +++ b/libs/ardour/ardour/tempo.h @@ -238,6 +238,7 @@ class TempoMap : public Stateful, public StateManager { XMLNode& get_state (void); int set_state (const XMLNode&); + PBD::ID id() { return _id; } void dump (std::ostream&) const; void clear (); @@ -315,6 +316,8 @@ class TempoMap : public Stateful, public StateManager { void save_state (std::string why); + PBD::ID _id; + }; }; /* namespace ARDOUR */ diff --git a/libs/ardour/ardour/track.h b/libs/ardour/ardour/track.h index f16e9d29d9..4e2af5c80e 100644 --- a/libs/ardour/ardour/track.h +++ b/libs/ardour/ardour/track.h @@ -48,7 +48,7 @@ class Track : public Route void toggle_monitor_input (); - bool can_record() const { return true; } + virtual bool can_record(); Diskstream& diskstream() const { return *_diskstream; } diff --git a/libs/ardour/ardour/vst_plugin.h b/libs/ardour/ardour/vst_plugin.h index 3cb10d1779..5253da7b0a 100644 --- a/libs/ardour/ardour/vst_plugin.h +++ b/libs/ardour/ardour/vst_plugin.h @@ -104,6 +104,15 @@ class VSTPlugin : public ARDOUR::Plugin bool been_resumed; }; -} +class VSTPluginInfo : public PluginInfo +{ + public: + VSTPluginInfo () {} + ~VSTPluginInfo () {} + + PluginPtr load (Session& session); +}; + +} // namespace ARDOUR #endif /* __ardour_vst_plugin_h__ */ diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index 7f0cb55821..7d2a2103bb 100644 --- a/libs/ardour/audio_diskstream.cc +++ b/libs/ardour/audio_diskstream.cc @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -1594,7 +1595,7 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca // cerr << _name << ": there are " << capture_info.size() << " capture_info records\n"; - _session.add_undo (_playlist->get_memento()); + XMLNode &before = _playlist->get_state(); _playlist->freeze (); for (buffer_position = channels[0].write_source->last_capture_start_frame(), ci = capture_info.begin(); ci != capture_info.end(); ++ci) { @@ -1625,7 +1626,8 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca } _playlist->thaw (); - _session.add_redo_no_execute (_playlist->get_memento()); + XMLNode &after = _playlist->get_state(); + _session.add_command (new MementoCommand(*_playlist, before, after)); } mark_write_completed = true; diff --git a/libs/ardour/audio_unit.cc b/libs/ardour/audio_unit.cc index 52cfc187af..25c8aeb53b 100644 --- a/libs/ardour/audio_unit.cc +++ b/libs/ardour/audio_unit.cc @@ -18,95 +18,361 @@ */ +#include +#include + +#include #include +#include #include +#include + #include #include +#include "i18n.h" + +using namespace std; +using namespace PBD; using namespace ARDOUR; -PluginInfoList -AUPluginInfo::discover () +AUPlugin::AUPlugin (AudioEngine& engine, Session& session, CAComponent* _comp) + : + Plugin (engine, session), + comp (_comp), + unit (new CAAudioUnit) +{ + OSErr err = CAAudioUnit::Open (*comp, *unit); + if (err != noErr) { + error << _("AudioUnit: Could not convert CAComponent to CAAudioUnit") << endmsg; + delete unit; + delete comp; + throw failed_constructor (); + } + + unit->Initialize (); +} + +AUPlugin::~AUPlugin () { - PluginInfoList plugs; + if (unit) { + unit->Uninitialize (); + delete unit; + } + + if (comp) { + delete comp; + } + + if (in_list) { + delete in_list; + } + + if (out_list) { + delete out_list; + } +} + +AUPluginInfo::~AUPluginInfo () +{ + if (desc) { + delete desc; + } +} - int numTypes = 2; // this magic number was retrieved from the apple AUHost example. +uint32_t +AUPlugin::unique_id () const +{ + return 0; +} - ComponentDescription desc; - desc.componentFlags = 0; - desc.componentFlagsMask = 0; - desc.componentSubType = 0; - desc.componentManufacturer = 0; +const char * +AUPlugin::label () const +{ + return "AUPlugin label"; +} - vector vCompDescs; +const char * +AUPlugin::maker () const +{ + return "AUplugin maker"; +} - for (int i = 0; i < numTypes; ++i) { - if (i == 1) { - desc.componentType = kAudioUnitType_MusicEffect; - } else { - desc.componentType = kAudioUnitType_Effect; - } +uint32_t +AUPlugin::parameter_count () const +{ + return 0; +} + +float +AUPlugin::default_value (uint32_t port) +{ + // AudioUnits don't have default values. Maybe presets though? + return 0; +} + +jack_nframes_t +AUPlugin::latency () const +{ + return unit->Latency (); +} + +void +AUPlugin::set_parameter (uint32_t which, float val) +{ + unit->SetParameter (parameter_map[which].first, parameter_map[which].second, 0, val); +} + +float +AUPlugin::get_parameter (uint32_t which) const +{ + float outValue = 0.0; + + unit->GetParameter(parameter_map[which].first, parameter_map[which].second, 0, outValue); + + return outValue; +} + +int +AUPlugin::get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const +{ + return -1; +} + +uint32_t +AUPlugin::nth_parameter (uint32_t which, bool& ok) const +{ + return 0; +} + +void +AUPlugin::activate () +{ + unit->GlobalReset (); +} + +void +AUPlugin::deactivate () +{ + // not needed. GlobalReset () takes care of it. +} - Component comp = 0; +void +AUPlugin::set_block_size (jack_nframes_t nframes) +{ + +} + +int +AUPlugin::connect_and_run (vector& bufs, uint32_t maxbuf, int32_t& in, int32_t& out, jack_nframes_t nframes, jack_nframes_t offset) +{ + AudioUnitRenderActionFlags flags = 0; + AudioTimeStamp ts; + + AudioBufferList abl; + abl.mNumberBuffers = 1; + abl.mBuffers[0].mNumberChannels = 1; + abl.mBuffers[0].mDataByteSize = nframes * sizeof(Sample); + abl.mBuffers[0].mData = &bufs[0]; + + + unit->Render (&flags, &ts, 0, 0, &abl); + + return 0; +} + +set +AUPlugin::automatable() const +{ + set automates; + + return automates; +} - comp = FindNextComponent (NULL, &desc); - while (comp != NULL) { - ComponentDescription temp; - GetComponentInfo (comp, &temp, NULL, NULL, NULL); - vCompDescs.push_back(temp); - comp = FindNextComponent (comp, &desc); +void +AUPlugin::store_state (ARDOUR::PluginState&) +{ + +} + +void +AUPlugin::restore_state (ARDOUR::PluginState&) +{ + +} + +string +AUPlugin::describe_parameter (uint32_t) +{ + return ""; +} + +void +AUPlugin::print_parameter (uint32_t, char*, uint32_t len) const +{ + +} + +bool +AUPlugin::parameter_is_audio (uint32_t) const +{ + return false; +} + +bool +AUPlugin::parameter_is_control (uint32_t) const +{ + return false; +} + +bool +AUPlugin::parameter_is_input (uint32_t) const +{ + return false; +} + +bool +AUPlugin::parameter_is_output (uint32_t) const +{ + return false; +} + +XMLNode& +AUPlugin::get_state() +{ + XMLNode* root = new XMLNode (state_node_name()); + + return *root; +} + +int +AUPlugin::set_state(const XMLNode& node) +{ + return -1; +} + +bool +AUPlugin::save_preset (string name) +{ + return false; +} + +bool +AUPlugin::load_preset (const string preset_label) +{ + return false; +} + +vector +AUPlugin::get_presets () +{ + vector presets; + + return presets; +} + +bool +AUPlugin::has_editor () const +{ + return false; +} + +PluginPtr +AUPluginInfo::load (Session& session) +{ + try { + PluginPtr plugin; + + CAComponent* comp = new CAComponent(*desc); + + if (!comp->IsValid()) { + error << ("AudioUnit: not a valid Component") << endmsg; + } else { + plugin.reset (new AUPlugin (session.engine(), session, comp)); } + + plugin->set_info(PluginInfoPtr(new AUPluginInfo(*this))); + return plugin; } - for (unsigned int i = 0; i < vCompDescs.size(); ++i) { - - // the following large block is just for determining the name of the plugin. - CFStringRef itemName = NULL; - // Marc Poirier -style item name - Component auComponent = FindNextComponent (0, &(vCompDescs[i])); - if (auComponent != NULL) { - ComponentDescription dummydesc; - Handle nameHandle = NewHandle(sizeof(void*)); - if (nameHandle != NULL) { - OSErr err = GetComponentInfo(auComponent, &dummydesc, nameHandle, NULL, NULL); - if (err == noErr) { - ConstStr255Param nameString = (ConstStr255Param) (*nameHandle); - if (nameString != NULL) { - itemName = CFStringCreateWithPascalString(kCFAllocatorDefault, nameString, CFStringGetSystemEncoding()); - } - } - DisposeHandle(nameHandle); - } - } + catch (failed_constructor &err) { + return PluginPtr ((Plugin*) 0); + } +} - // if Marc-style fails, do the original way - if (itemName == NULL) { - CFStringRef compTypeString = UTCreateStringForOSType(vCompDescs[i].componentType); - CFStringRef compSubTypeString = UTCreateStringForOSType(vCompDescs[i].componentSubType); - CFStringRef compManufacturerString = UTCreateStringForOSType(vCompDescs[i].componentManufacturer); - - itemName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ - %@ - %@"), - compTypeString, compManufacturerString, compSubTypeString); - - if (compTypeString != NULL) - CFRelease(compTypeString); - if (compSubTypeString != NULL) - CFRelease(compSubTypeString); - if (compManufacturerString != NULL) - CFRelease(compManufacturerString); - } - string realname = CFStringRefToStdString(itemName); +PluginInfoList +AUPluginInfo::discover () +{ + PluginInfoList plugs; + + CAComponentDescription desc; + desc.componentFlags = 0; + desc.componentFlagsMask = 0; + desc.componentSubType = 0; + desc.componentManufacturer = 0; + desc.componentType = kAudioUnitType_Effect; + + Component comp = 0; + comp = FindNextComponent (NULL, &desc); + while (comp != NULL) { + CAComponentDescription temp; + GetComponentInfo (comp, &temp, NULL, NULL, NULL); + AUPluginInfoPtr plug(new AUPluginInfo); - plug->name = realname; + plug->name = AUPluginInfo::get_name (temp); plug->type = PluginInfo::AudioUnit; plug->n_inputs = 0; plug->n_outputs = 0; plug->category = "AudioUnit"; + plug->desc = new CAComponentDescription(temp); plugs.push_back(plug); + + comp = FindNextComponent (comp, &desc); } return plugs; } + +string +AUPluginInfo::get_name (CAComponentDescription& comp_desc) +{ + CFStringRef itemName = NULL; + // Marc Poirier -style item name + CAComponent auComponent (comp_desc); + if (auComponent.IsValid()) { + CAComponentDescription dummydesc; + Handle nameHandle = NewHandle(sizeof(void*)); + if (nameHandle != NULL) { + OSErr err = GetComponentInfo(auComponent.Comp(), &dummydesc, nameHandle, NULL, NULL); + if (err == noErr) { + ConstStr255Param nameString = (ConstStr255Param) (*nameHandle); + if (nameString != NULL) { + itemName = CFStringCreateWithPascalString(kCFAllocatorDefault, nameString, CFStringGetSystemEncoding()); + } + } + DisposeHandle(nameHandle); + } + } + + // if Marc-style fails, do the original way + if (itemName == NULL) { + CFStringRef compTypeString = UTCreateStringForOSType(comp_desc.componentType); + CFStringRef compSubTypeString = UTCreateStringForOSType(comp_desc.componentSubType); + CFStringRef compManufacturerString = UTCreateStringForOSType(comp_desc.componentManufacturer); + + itemName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ - %@ - %@"), + compTypeString, compManufacturerString, compSubTypeString); + + if (compTypeString != NULL) + CFRelease(compTypeString); + if (compSubTypeString != NULL) + CFRelease(compSubTypeString); + if (compManufacturerString != NULL) + CFRelease(compManufacturerString); + } + + return CFStringRefToStdString(itemName); +} diff --git a/libs/ardour/automation_event.cc b/libs/ardour/automation_event.cc index 63492b375b..dc1767d1e7 100644 --- a/libs/ardour/automation_event.cc +++ b/libs/ardour/automation_event.cc @@ -1246,3 +1246,17 @@ AutomationList::load_state (const XMLNode& node) add (x, y); } } + +XMLNode &AutomationList::get_state () +{ + XMLNode *node = new XMLNode("AutomationList"); + store_state(*node); + return *node; +} + +int AutomationList::set_state(const XMLNode &s) +{ + load_state(s); + return 0; +} + diff --git a/libs/ardour/globals.cc b/libs/ardour/globals.cc index 4eafbbe9a1..6f3b772ece 100644 --- a/libs/ardour/globals.cc +++ b/libs/ardour/globals.cc @@ -193,9 +193,9 @@ setup_midi (AudioEngine& engine ) } int -ARDOUR::init (AudioEngine& engine, bool use_vst, bool try_optimization) +ARDOUR::init (ARDOUR::AudioEngine& engine, bool use_vst, bool try_optimization) { - bool generic_mix_functions = true; + bool generic_mix_functions = true; (void) bindtextdomain(PACKAGE, LOCALEDIR); @@ -303,7 +303,7 @@ ARDOUR::init (AudioEngine& engine, bool use_vst, bool try_optimization) } /* singleton - first object is "it" */ - new PluginManager (engine); + new PluginManager (); /* singleton - first object is "it" */ new ControlProtocolManager (); diff --git a/libs/ardour/insert.cc b/libs/ardour/insert.cc index 11b1e25a74..a057fef931 100644 --- a/libs/ardour/insert.cc +++ b/libs/ardour/insert.cc @@ -186,25 +186,25 @@ PluginInsert::auto_state_changed (uint32_t which) uint32_t PluginInsert::output_streams() const { - return _plugins[0]->get_info().n_outputs * _plugins.size(); + return _plugins[0]->get_info()->n_outputs * _plugins.size(); } uint32_t PluginInsert::input_streams() const { - return _plugins[0]->get_info().n_inputs * _plugins.size(); + return _plugins[0]->get_info()->n_inputs * _plugins.size(); } uint32_t PluginInsert::natural_output_streams() const { - return _plugins[0]->get_info().n_outputs; + return _plugins[0]->get_info()->n_outputs; } uint32_t PluginInsert::natural_input_streams() const { - return _plugins[0]->get_info().n_inputs; + return _plugins[0]->get_info()->n_inputs; } bool @@ -214,7 +214,7 @@ PluginInsert::is_generator() const a specific "instrument" flag, for example. */ - return _plugins[0]->get_info().n_inputs == 0; + return _plugins[0]->get_info()->n_inputs == 0; } void @@ -350,7 +350,7 @@ PluginInsert::silence (jack_nframes_t nframes, jack_nframes_t offset) if (active()) { for (vector >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) { - n = (*i) -> get_info().n_inputs; + n = (*i) -> get_info()->n_inputs; (*i)->connect_and_run (_session.get_silent_buffers (n), n, in_index, out_index, nframes, offset); } } @@ -367,8 +367,8 @@ PluginInsert::run (vector& bufs, uint32_t nbufs, jack_nframes_t nframe connect_and_run (bufs, nbufs, nframes, offset, false); } } else { - uint32_t in = _plugins[0]->get_info().n_inputs; - uint32_t out = _plugins[0]->get_info().n_outputs; + uint32_t in = _plugins[0]->get_info()->n_inputs; + uint32_t out = _plugins[0]->get_info()->n_outputs; if (out > in) { @@ -524,7 +524,7 @@ PluginInsert::plugin_factory (boost::shared_ptr other) int32_t PluginInsert::compute_output_streams (int32_t cnt) const { - return _plugins[0]->get_info().n_outputs * cnt; + return _plugins[0]->get_info()->n_outputs * cnt; } int32_t @@ -536,8 +536,8 @@ PluginInsert::configure_io (int32_t magic, int32_t in, int32_t out) int32_t PluginInsert::can_support_input_configuration (int32_t in) const { - int32_t outputs = _plugins[0]->get_info().n_outputs; - int32_t inputs = _plugins[0]->get_info().n_inputs; + int32_t outputs = _plugins[0]->get_info()->n_outputs; + int32_t inputs = _plugins[0]->get_info()->n_inputs; if (inputs == 0) { @@ -591,7 +591,7 @@ PluginInsert::state (bool full) node->add_property("id", string(buf)); if (_plugins[0]->state_node_name() == "ladspa") { char buf[32]; - snprintf (buf, sizeof (buf), "%ld", _plugins[0]->get_info().unique_id); + snprintf (buf, sizeof (buf), "%ld", _plugins[0]->get_info()->unique_id); node->add_property("unique-id", string(buf)); } node->add_property("count", string_compose("%1", _plugins.size())); @@ -761,7 +761,7 @@ PluginInsert::set_state(const XMLNode& node) } // The name of the PluginInsert comes from the plugin, nothing else - set_name(plugin->get_info().name,this); + set_name(plugin->get_info()->name,this); return 0; } diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc index 2dfd735a6b..4d2d26f801 100644 --- a/libs/ardour/io.cc +++ b/libs/ardour/io.cc @@ -170,7 +170,7 @@ IO::silence (jack_nframes_t nframes, jack_nframes_t offset) void IO::apply_declick (vector& bufs, uint32_t nbufs, jack_nframes_t nframes, gain_t initial, gain_t target, bool invert_polarity) { - jack_nframes_t declick = min ((jack_nframes_t)4096, nframes); + jack_nframes_t declick = min ((jack_nframes_t)128, nframes); gain_t delta; Sample *buffer; double fractional_shift; diff --git a/libs/ardour/ladspa_plugin.cc b/libs/ardour/ladspa_plugin.cc index fa19a682e7..6b773b9e0b 100644 --- a/libs/ardour/ladspa_plugin.cc +++ b/libs/ardour/ladspa_plugin.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2000-2002 Paul Davis + Copyright (C) 2000-2006 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -641,3 +641,26 @@ LadspaPlugin::latency_compute_run () run (bufsize); deactivate (); } + +PluginPtr +LadspaPluginInfo::load (Session& session) +{ + try { + PluginPtr plugin; + void *module; + + if ((module = dlopen (path.c_str(), RTLD_NOW)) == 0) { + error << string_compose(_("LADSPA: cannot load module from \"%1\""), path) << endmsg; + error << dlerror() << endmsg; + } else { + plugin.reset (new LadspaPlugin (module, session.engine(), session, index, session.frame_rate())); + } + + plugin->set_info(PluginInfoPtr(new LadspaPluginInfo(*this))); + return plugin; + } + + catch (failed_constructor &err) { + return PluginPtr ((Plugin*) 0); + } +} diff --git a/libs/ardour/plugin.cc b/libs/ardour/plugin.cc index 6763e7f508..8ea95b8903 100644 --- a/libs/ardour/plugin.cc +++ b/libs/ardour/plugin.cc @@ -39,6 +39,8 @@ #include #include #include +#include +#include #include @@ -240,3 +242,43 @@ Plugin::save_preset (string name, string domain) return true; } + +PluginPtr +ARDOUR::find_plugin(Session& session, string name, long unique_id, PluginInfo::Type type) +{ + PluginManager *mgr = PluginManager::the_manager(); + PluginInfoList plugs; + + switch (type) { + case PluginInfo::LADSPA: + plugs = mgr->ladspa_plugin_info(); + break; + +#ifdef VST_SUPPORT + case PluginInfo::VST: + plugs = mgr->vst_plugin_info(); + unique_id = 0; // VST plugins don't have a unique id. + break; +#endif + +#ifdef HAVE_COREAUDIO + case PluginInfo::AudioUnit: + plugs = AUPluginInfo::discover (); + unique_id = 0; // Neither do AU. + break; +#endif + + default: + return PluginPtr ((Plugin *) 0); + } + + PluginInfoList::iterator i; + for (i = plugs.begin(); i != plugs.end(); ++i) { + if ((name == "" || (*i)->name == name) && + (unique_id == 0 || (*i)->unique_id == unique_id)) { + return (*i)->load (session); + } + } + + return PluginPtr ((Plugin*) 0); +} diff --git a/libs/ardour/plugin_manager.cc b/libs/ardour/plugin_manager.cc index 06a944189a..2a753617e8 100644 --- a/libs/ardour/plugin_manager.cc +++ b/libs/ardour/plugin_manager.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2000-2004 Paul Davis + Copyright (C) 2000-2006 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -36,8 +36,10 @@ #include #include #include + +#ifdef VST_SUPPORT #include -#include +#endif #include #include @@ -49,8 +51,7 @@ using namespace PBD; PluginManager* PluginManager::_manager = 0; -PluginManager::PluginManager (AudioEngine& e) - : _engine (e) +PluginManager::PluginManager () { char* s; string lrdf_path; @@ -97,10 +98,6 @@ PluginManager::refresh () vst_refresh (); } #endif // VST_SUPPORT - -#ifdef HAVE_COREAUDIO - _au_plugin_info = AUPluginInfo::discover (); -#endif // HAVE_COREAUDIO } void @@ -250,7 +247,7 @@ PluginManager::ladspa_discover (string path) break; } - PluginInfoPtr info(new PluginInfo); + PluginInfoPtr info(new LadspaPluginInfo); info->name = descriptor->Name; info->category = get_ladspa_category(descriptor->UniqueID); info->path = path; @@ -280,85 +277,6 @@ PluginManager::ladspa_discover (string path) return 0; } -boost::shared_ptr -PluginManager::load (Session& session, PluginInfoPtr info) -{ - void *module; - - try { - boost::shared_ptr plugin; - - if (info->type == PluginInfo::VST) { - -#ifdef VST_SUPPORT - if (Config->get_use_vst()) { - FSTHandle* handle; - - if ((handle = fst_load (info->path.c_str())) == 0) { - error << string_compose(_("VST: cannot load module from \"%1\""), info->path) << endmsg; - } else { - plugin.reset (new VSTPlugin (_engine, session, handle)); - } - } else { - error << _("You asked ardour to not use any VST plugins") << endmsg; - } -#else // !VST_SUPPORT - error << _("This version of ardour has no support for VST plugins") << endmsg; - return boost::shared_ptr ((Plugin*) 0); -#endif // !VST_SUPPORT - - } else { - - if ((module = dlopen (info->path.c_str(), RTLD_NOW)) == 0) { - error << string_compose(_("LADSPA: cannot load module from \"%1\""), info->path) << endmsg; - error << dlerror() << endmsg; - } else { - plugin.reset (new LadspaPlugin (module, _engine, session, info->index, session.frame_rate())); - } - } - - plugin->set_info(*info); - return plugin; - } - - catch (failed_constructor &err) { - return boost::shared_ptr ((Plugin*) 0); - } -} - -boost::shared_ptr -ARDOUR::find_plugin(Session& session, string name, long unique_id, PluginInfo::Type type) -{ - PluginManager *mgr = PluginManager::the_manager(); - PluginInfoList* plugs = 0; - - switch (type) { - case PluginInfo::LADSPA: - plugs = &mgr->ladspa_plugin_info(); - break; - case PluginInfo::VST: - plugs = &mgr->vst_plugin_info(); - unique_id = 0; // VST plugins don't have a unique id. - break; - case PluginInfo::AudioUnit: - plugs = &mgr->au_plugin_info(); - unique_id = 0; - break; - default: - return boost::shared_ptr ((Plugin *) 0); - } - - PluginInfoList::iterator i; - for (i = plugs->begin(); i != plugs->end(); ++i) { - if ((name == "" || (*i)->name == name) && - (unique_id == 0 || (*i)->unique_id == unique_id)) { - return mgr->load (session, *i); - } - } - - return boost::shared_ptr ((Plugin*) 0); -} - string PluginManager::get_ladspa_category (uint32_t plugin_id) { @@ -464,7 +382,7 @@ PluginManager::vst_discover (string path) << endl; } - PluginInfoPtr info(new PluginInfo); + PluginInfoPtr info(new VSTPluginInfo); /* what a goddam joke freeware VST is */ diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 902da43d91..bfcb69572a 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -1023,6 +1023,7 @@ Session::auto_punch_start_changed (Location* location) if (get_record_enabled() && get_punch_in()) { /* capture start has been changed, so save new pending state */ save_state ("", true); + save_history(); } } @@ -1344,6 +1345,7 @@ Session::maybe_enable_record () */ save_state ("", true); + save_history(); if (_transport_speed) { if (!punch_in) { @@ -2131,6 +2133,7 @@ Session::add_diskstream (Diskstream* dstream) set_dirty(); save_state (_current_snapshot_name); + save_history(); DiskstreamAdded (dstream); /* EMIT SIGNAL */ } @@ -2882,6 +2885,7 @@ Session::remove_source (Source* source) */ save_state (_current_snapshot_name); + save_history(); } SourceRemoved(source); /* EMIT SIGNAL */ diff --git a/libs/ardour/session_command.cc b/libs/ardour/session_command.cc new file mode 100644 index 0000000000..9a43de55de --- /dev/null +++ b/libs/ardour/session_command.cc @@ -0,0 +1,101 @@ +#include +#include + +namespace ARDOUR { +// solo +Session::GlobalSoloStateCommand::GlobalSoloStateCommand(Session &sess, void *src) + : sess(sess), src(src) +{ + after = before = sess.get_global_route_boolean(&Route::soloed); +} +void Session::GlobalSoloStateCommand::mark() +{ + after = sess.get_global_route_boolean(&Route::soloed); +} +void Session::GlobalSoloStateCommand::operator()() +{ + sess.set_global_solo(after, src); +} +void Session::GlobalSoloStateCommand::undo() +{ + sess.set_global_solo(before, src); +} +XMLNode &Session::GlobalSoloStateCommand::get_state() +{ + XMLNode *node = new XMLNode("GlobalSoloStateCommand"); + return *node; +} + +// mute +Session::GlobalMuteStateCommand::GlobalMuteStateCommand(Session &sess, void *src) + : sess(sess), src(src) +{ + after = before = sess.get_global_route_boolean(&Route::muted); +} +void Session::GlobalMuteStateCommand::mark() +{ + after = sess.get_global_route_boolean(&Route::muted); +} +void Session::GlobalMuteStateCommand::operator()() +{ + sess.set_global_mute(after, src); +} +void Session::GlobalMuteStateCommand::undo() +{ + sess.set_global_mute(before, src); +} +XMLNode &Session::GlobalMuteStateCommand::get_state() +{ + XMLNode *node = new XMLNode("GlobalMuteStateCommand"); + return *node; +} + +// record enable +Session::GlobalRecordEnableStateCommand::GlobalRecordEnableStateCommand(Session &sess, void *src) + : sess(sess), src(src) +{ + after = before = sess.get_global_route_boolean(&Route::record_enabled); +} +void Session::GlobalRecordEnableStateCommand::mark() +{ + after = sess.get_global_route_boolean(&Route::record_enabled); +} +void Session::GlobalRecordEnableStateCommand::operator()() +{ + sess.set_global_record_enable(after, src); +} +void Session::GlobalRecordEnableStateCommand::undo() +{ + sess.set_global_record_enable(before, src); +} +XMLNode &Session::GlobalRecordEnableStateCommand::get_state() +{ + XMLNode *node = new XMLNode("GlobalRecordEnableStateCommand"); + return *node; +} + +// metering +Session::GlobalMeteringStateCommand::GlobalMeteringStateCommand(Session &sess, void *src) + : sess(sess), src(src) +{ + after = before = sess.get_global_route_metering(); +} +void Session::GlobalMeteringStateCommand::mark() +{ + after = sess.get_global_route_metering(); +} +void Session::GlobalMeteringStateCommand::operator()() +{ + sess.set_global_route_metering(after, src); +} +void Session::GlobalMeteringStateCommand::undo() +{ + sess.set_global_route_metering(before, src); +} +XMLNode &Session::GlobalMeteringStateCommand::get_state() +{ + XMLNode *node = new XMLNode("GlobalMeteringStateCommand"); + return *node; +} + +} // namespace ARDOUR diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 8d11fd3b3f..bb319511b7 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -611,6 +611,7 @@ Session::create (bool& new_session, string* mix_template, jack_nframes_t initial _state_of_the_state = Clean; if (save_state (_current_snapshot_name)) { + save_history(); return -1; } } @@ -1697,6 +1698,7 @@ Session::set_state (const XMLNode& node) if (state_was_pending) { save_state (_current_snapshot_name); + save_history(); remove_pending_capture_state (); state_was_pending = false; } @@ -2498,6 +2500,7 @@ void Session::auto_save() { save_state (_current_snapshot_name); + save_history(); } RouteGroup * @@ -2590,29 +2593,25 @@ Session::set_meter_falloff (float val) void -Session::begin_reversible_command (string name, UndoAction* private_undo) +Session::begin_reversible_command (string name) { - current_cmd.clear (); - current_cmd.set_name (name); - - if (private_undo) { - current_cmd.add_undo (*private_undo); - } + current_trans.clear (); + current_trans.set_name (name); } void -Session::commit_reversible_command (UndoAction* private_redo) +Session::commit_reversible_command (Command *cmd) { struct timeval now; - if (private_redo) { - current_cmd.add_redo_no_execute (*private_redo); + if (cmd) { + current_trans.add_command (cmd); } gettimeofday (&now, 0); - current_cmd.set_timestamp (now); + current_trans.set_timestamp (now); - history.add (current_cmd); + history.add (current_trans); } Session::GlobalRouteBooleanState @@ -2691,6 +2690,7 @@ Session::set_global_record_enable (GlobalRouteBooleanState s, void* src) set_global_route_boolean (s, &Route::set_record_enable, src); } +#if 0 UndoAction Session::global_mute_memento (void* src) { @@ -2714,6 +2714,7 @@ Session::global_record_enable_memento (void* src) { return sigc::bind (mem_fun (*this, &Session::set_global_record_enable), get_global_route_boolean (&Route::record_enabled), src); } +#endif static bool template_filter (const string &str, void *arg) @@ -3301,3 +3302,48 @@ Session::add_instant_xml (XMLNode& node, const std::string& dir) Stateful::add_instant_xml (node, dir); Config->add_instant_xml (node, get_user_ardour_path()); } + + +int +Session::save_history () +{ + XMLTree tree; + string xml_path; + string bak_path; + + tree.set_root (&history.get_state()); + + xml_path = _path + _current_snapshot_name + ".history"; + + bak_path = xml_path + ".bak"; + + if ((access (xml_path.c_str(), F_OK) == 0) && + (rename (xml_path.c_str(), bak_path.c_str()))) + { + error << _("could not backup old history file, current history not saved.") << endmsg; + return -1; + } + + if (!tree.write (xml_path)) + { + error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg; + + /* don't leave a corrupt file lying around if it is + * possible to fix. + */ + + if (unlink (xml_path.c_str())) + { + error << string_compose (_("could not remove corrupt history file %1"), xml_path) << endmsg; + } else { + if (rename (bak_path.c_str(), xml_path.c_str())) + { + error << string_compose (_("could not restore history file from backup %1"), bak_path) << endmsg; + } + } + + return -1; + } + + return 0; +} diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index bff8ae5955..592f9c86c6 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -325,8 +326,10 @@ Session::non_realtime_stop (bool abort) } if (change_end) { - add_undo (sigc::retype_return(sigc::bind (mem_fun (*loc, &Location::set_end), loc->end()))); - add_redo (sigc::retype_return(sigc::bind (mem_fun (*loc, &Location::set_end), _transport_frame))); + XMLNode &before = loc->get_state(); + loc->set_end(_transport_frame); + XMLNode &after = loc->get_state(); + add_command (new MementoCommand(*loc, before, after)); } _end_location_is_free = false; @@ -410,6 +413,7 @@ Session::non_realtime_stop (bool abort) if ((post_transport_work & PostTransportLocate) && get_record_enabled()) { /* capture start has been changed, so save pending state */ save_state ("", true); + save_history(); } /* always try to get rid of this */ diff --git a/libs/ardour/state_manager.cc b/libs/ardour/state_manager.cc index bcffe381c3..153773ed30 100644 --- a/libs/ardour/state_manager.cc +++ b/libs/ardour/state_manager.cc @@ -72,6 +72,9 @@ StateManager::use_state (state_id_t id) void StateManager::save_state (std::string why) { + if (!should_save_state()) + return; + if (!_allow_save) { SaveAllowed.connect (mem_fun (*this, &StateManager::save_state)); return; diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc index 3b3b705a87..f81ef9de4d 100644 --- a/libs/ardour/track.cc +++ b/libs/ardour/track.cc @@ -31,6 +31,7 @@ #include #include #include +#include #include "i18n.h" @@ -146,6 +147,18 @@ Track::record_enabled () const { return _diskstream->record_enabled (); } + +bool +Track::can_record() +{ + bool will_record = true; + for (size_t i = 0; i < _inputs.size() && will_record; i++) { + if (!_inputs[i]->connected()) + will_record = false; + } + + return will_record; +} void Track::set_record_enable (bool yn, void *src) @@ -159,8 +172,13 @@ Track::set_record_enable (bool yn, void *src) return; } - /* keep track of the meter point as it was before we rec-enabled */ + // Do not set rec enabled if the track can't record. + if (yn && !can_record()) { + error << string_compose( _("Can not arm track '%1'. Check the input connections"), name() ) << endmsg; + return; + } + /* keep track of the meter point as it was before we rec-enabled */ if (!_diskstream->record_enabled()) { _saved_meter_point = _meter_point; } @@ -206,6 +224,7 @@ Track::set_name (string str, void *src) if ((ret = IO::set_name (str, src)) == 0) { _session.save_state (""); + _session.save_history(); } return ret; } diff --git a/libs/ardour/vst_plugin.cc b/libs/ardour/vst_plugin.cc index 352b887e13..4c09ba3440 100644 --- a/libs/ardour/vst_plugin.cc +++ b/libs/ardour/vst_plugin.cc @@ -479,3 +479,33 @@ VSTPlugin::print_parameter (uint32_t param, char *buf, uint32_t len) const memmove (buf, first_nonws, strlen (buf) - (first_nonws - buf) + 1); } + +PluginPtr +VSTPluginInfo::load (Session& session) +{ + try { + PluginPtr plugin; + + if (Config->get_use_vst()) { + FSTHandle* handle; + + handle = fst_load(path.c_str()); + + if ( (int)handle == -1) { + error << string_compose(_("VST: cannot load module from \"%1\""), path) << endmsg; + } else { + plugin.reset (new VSTPlugin (session.engine(), session, handle)); + } + } else { + error << _("You asked ardour to not use any VST plugins") << endmsg; + return PluginPtr ((Plugin*) 0); + } + + plugin->set_info(PluginInfoPtr(new VSTPluginInfo(*this))); + return plugin; + } + + catch (failed_constructor &err) { + return PluginPtr ((Plugin*) 0); + } +} -- cgit v1.2.3