diff options
Diffstat (limited to 'libs/ardour/ardour')
77 files changed, 11131 insertions, 0 deletions
diff --git a/libs/ardour/ardour/.cvsignore b/libs/ardour/ardour/.cvsignore new file mode 100644 index 0000000000..67020331ba --- /dev/null +++ b/libs/ardour/ardour/.cvsignore @@ -0,0 +1 @@ +version.h diff --git a/libs/ardour/ardour/ardour.h b/libs/ardour/ardour/ardour.h new file mode 100644 index 0000000000..31bd22590e --- /dev/null +++ b/libs/ardour/ardour/ardour.h @@ -0,0 +1,80 @@ +/* + Copyright (C) 1999 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_ardour_h__ +#define __ardour_ardour_h__ + +#include <limits.h> +#include <string> +#include <signal.h> + +#include <pbd/error.h> +#include <pbd/lockmonitor.h> +#include <pbd/failed_constructor.h> + +#include <ardour/configuration.h> +#include <ardour/types.h> + +using namespace PBD; + +namespace MIDI { + class MachineControl; + class Port; +} + +namespace ARDOUR { + + class AudioEngine; + + static const jack_nframes_t max_frames = JACK_MAX_FRAMES; + + int init (AudioEngine&, bool with_vst, bool try_optimization, void (*sighandler)(int,siginfo_t*,void*) = 0); + int cleanup (); + std::string find_config_file (std::string name); + std::string find_data_file (std::string name); + + const layer_t max_layer = UCHAR_MAX; + + id_t new_id(); + + Change new_change (); + + extern Change StartChanged; + extern Change LengthChanged; + extern Change PositionChanged; + extern Change NameChanged; + extern Change BoundsChanged; + + struct LocaleGuard { + LocaleGuard (const char*); + ~LocaleGuard (); + const char* old; + }; + +}; + +/* how do we make these be within the Ardour namespace? */ + +extern MIDI::Port* default_mmc_port; +extern MIDI::Port* default_mtc_port; +extern MIDI::Port* default_midi_port; + +#endif /* __ardour_ardour_h__ */ + diff --git a/libs/ardour/ardour/audio_library.h b/libs/ardour/ardour/audio_library.h new file mode 100644 index 0000000000..3aab3993b9 --- /dev/null +++ b/libs/ardour/ardour/audio_library.h @@ -0,0 +1,90 @@ +/* + Copyright (C) 2003 Paul Davis + Author: Taybin Rutkin + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_audio_library_h__ +#define __ardour_audio_library_h__ + +#include <list> +#include <string> +#include <map> + +#include <sigc++/signal.h> + +using std::list; +using std::string; +using std::map; + +namespace ARDOUR { + +class AudioLibrary +{ + public: + AudioLibrary (); + ~AudioLibrary (); + + // add_group returns the URI of the created group + string add_group (string group, string parent_uri = ""); + void remove_group (string uri); + void get_groups (list<string>& groups, string parent_uri = ""); + + // add_member returns the URI of the created group + string add_member (string member, string parent_uri = ""); + void remove_member (string uri); + void get_members (list<string>& members, string parent_uri = ""); + string get_member_filename (string uri); + + void search_members_and (list<string>& results, + const map<string,string>& fields); + void search_members_or (list<string>& results, + const map<string,string>& fields); + + void add_field (string field); + void get_fields (list<string>& fields); + void remove_field (string field); + string get_field (string uri, string field); + void set_field (string uri, string field, string literal); + + string get_label (string uri); + void set_label (string uri, string label); + + sigc::signal<void, string, string> added_group; // group, parent + sigc::signal<void, string, string> added_member;// member, parent + sigc::signal<void, string> removed_group; + sigc::signal<void, string> removed_member; + sigc::signal<void> fields_changed; + + private: + void save_changes (); + string field_uri (string name); + + bool is_rdf_type (string uri, string type); + void remove_uri (string uri); + + string src; + + void initialize_db(); +}; + +extern AudioLibrary* Library; + +} // ARDOUR namespace + +#endif // __ardour_audio_library_h__ diff --git a/libs/ardour/ardour/audio_track.h b/libs/ardour/ardour/audio_track.h new file mode 100644 index 0000000000..e7ba315e45 --- /dev/null +++ b/libs/ardour/ardour/audio_track.h @@ -0,0 +1,162 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_audio_track_h__ +#define __ardour_audio_track_h__ + +#include <ardour/route.h> + +namespace ARDOUR { + +class Session; +class DiskStream; +class AudioPlaylist; + +class AudioTrack : public Route +{ + public: + AudioTrack (Session&, string name, Route::Flag f = Route::Flag (0)); + AudioTrack (Session&, const XMLNode&); + ~AudioTrack (); + + int set_name (string str, void *src); + + int roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, + + jack_nframes_t offset, int declick, bool can_record, bool rec_monitors_input); + int no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, + jack_nframes_t offset, bool state_changing, bool can_record, bool rec_monitors_input); + int silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, + jack_nframes_t offset, bool can_record, bool rec_monitors_input); + + void toggle_monitor_input (); + + bool can_record() const { return true; } + void set_record_enable (bool yn, void *src); + + DiskStream& disk_stream() const { return *diskstream; } + int set_diskstream (DiskStream&, void *); + int use_diskstream (string name); + int use_diskstream (id_t id); + + jack_nframes_t update_total_latency(); + void set_latency_delay (jack_nframes_t); + + int export_stuff (vector<Sample*>& buffers, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t end_frame); + + sigc::signal<void,void*> diskstream_changed; + + enum FreezeState { + NoFreeze, + Frozen, + UnFrozen + }; + + FreezeState freeze_state() const; + + sigc::signal<void> FreezeChange; + + void freeze (InterThreadInfo&); + void unfreeze (); + + void bounce (InterThreadInfo&); + void bounce_range (jack_nframes_t start, jack_nframes_t end, InterThreadInfo&); + + XMLNode& get_state(); + int set_state(const XMLNode& node); + + MIDI::Controllable& midi_rec_enable_control() { + return _midi_rec_enable_control; + } + + void reset_midi_control (MIDI::Port*, bool); + void send_all_midi_feedback (); + + bool record_enabled() const; + void set_meter_point (MeterPoint, void* src); + + protected: + DiskStream *diskstream; + MeterPoint _saved_meter_point; + + void passthru_silence (jack_nframes_t start_frame, jack_nframes_t end_frame, + jack_nframes_t nframes, jack_nframes_t offset, int declick, + bool meter); + + uint32_t n_process_buffers (); + + private: + struct FreezeRecordInsertInfo { + FreezeRecordInsertInfo(XMLNode& st) + : state (st), insert (0) {} + + XMLNode state; + Insert* insert; + id_t id; + UndoAction memento; + }; + + struct FreezeRecord { + FreezeRecord() { + playlist = 0; + have_mementos = false; + } + + ~FreezeRecord(); + + AudioPlaylist* playlist; + vector<FreezeRecordInsertInfo*> insert_info; + bool have_mementos; + FreezeState state; + }; + + FreezeRecord _freeze_record; + XMLNode* pending_state; + + void diskstream_record_enable_changed (void *src); + void diskstream_input_channel_changed (void *src); + + void input_change_handler (void *src); + + sigc::connection recenable_connection; + sigc::connection ic_connection; + + XMLNode& state(bool); + + int deprecated_use_diskstream_connections (); + void set_state_part_two (); + void set_state_part_three (); + + struct MIDIRecEnableControl : public MIDI::Controllable { + MIDIRecEnableControl (AudioTrack&, MIDI::Port *); + void set_value (float); + void send_feedback (bool); + MIDI::byte* write_feedback (MIDI::byte* buf, int32_t& bufsize, bool val, bool force = false); + AudioTrack& track; + bool setting; + bool last_written; + }; + + MIDIRecEnableControl _midi_rec_enable_control; +}; + +}; /* namespace ARDOUR*/ + +#endif /* __ardour_audio_track_h__ */ diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h new file mode 100644 index 0000000000..d349f5bae5 --- /dev/null +++ b/libs/ardour/ardour/audioengine.h @@ -0,0 +1,242 @@ +/* + Copyright (C) 2002-2004 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_audioengine_h__ +#define __ardour_audioengine_h__ + +#include <list> +#include <set> +#include <cmath> +#include <exception> +#include <string> + +#include <sigc++/signal.h> +#include <pthread.h> +#include <ardour/ardour.h> +#include <jack/jack.h> +#include <jack/transport.h> + +namespace ARDOUR { + +class Session; +class Port; + +class AudioEngine : public sigc::trackable +{ + public: + AudioEngine (std::string client_name); + virtual ~AudioEngine (); + + jack_client_t* jack() const { return _jack; } + bool connected() const { return _jack != 0; } + + std::string client_name() const { return jack_client_name; } + + int reconnect_to_jack (); + int disconnect_from_jack(); + + bool will_reconnect_at_halt (); + void set_reconnect_at_halt (bool); + + int stop (); + int start (); + bool running() const { return _running; } + + PBD::NonBlockingLock& process_lock() { return _process_lock; } + + jack_nframes_t frame_rate(); + jack_nframes_t frames_per_cycle(); + + int usecs_per_cycle () const { return _usecs_per_cycle; } + + jack_nframes_t frames_since_cycle_start () { + if (!_running || !_jack) return 0; + return jack_frames_since_cycle_start (_jack); + } + jack_nframes_t frame_time () { + if (!_running || !_jack) return 0; + return jack_frame_time (_jack); + } + + jack_nframes_t transport_frame () const { + if (!_running || !_jack) return 0; + return jack_get_current_transport_frame (_jack); + } + + int request_buffer_size (jack_nframes_t); + + jack_nframes_t set_monitor_check_interval (jack_nframes_t); + + float get_cpu_load() { + if (!_running || !_jack) return 0; + return jack_cpu_load (_jack); + } + + void set_session (Session *); + void remove_session (); + + class PortRegistrationFailure : public std::exception { + public: + virtual const char *what() const throw() { return "failed port registration"; } + }; + + class NoBackendAvailable : public std::exception { + public: + virtual const char *what() const throw() { return "could not connect to engine backend"; } + }; + + Port *register_audio_input_port (const string& portname); + Port *register_audio_output_port (const string& portname); + int unregister_port (Port *); + + int connect (const string& source, const string& destination); + int disconnect (const string& source, const string& destination); + int disconnect (Port *); + + const char ** get_ports (const string& port_name_pattern, const string& type_name_pattern, uint32_t flags); + + uint32_t n_physical_outputs () const; + uint32_t n_physical_inputs () const; + + string get_nth_physical_output (uint32_t n) { + return get_nth_physical (n, JackPortIsInput); + } + + string get_nth_physical_input (uint32_t n) { + return get_nth_physical (n, JackPortIsOutput); + } + + jack_nframes_t get_port_total_latency (const Port&); + void update_total_latencies (); + + /* the caller may not delete the object pointed to by + the return value + */ + + Port *get_port_by_name (const string& name, bool keep = true); + + enum TransportState { + TransportStopped = JackTransportStopped, + TransportRolling = JackTransportRolling, + TransportLooping = JackTransportLooping, + TransportStarting = JackTransportStarting + }; + + void transport_start (); + void transport_stop (); + void transport_locate (jack_nframes_t); + TransportState transport_state (); + + int reset_timebase (); + + /* start/stop freewheeling */ + + int freewheel (bool onoff); + bool freewheeling() const { return _freewheeling; } + + /* this signal is sent for every process() cycle while freewheeling. + the regular process() call to session->process() is not made. + */ + + sigc::signal<int,jack_nframes_t> Freewheel; + + sigc::signal<void> Xrun; + + /* this signal is if JACK notifies us of a graph order event */ + + sigc::signal<void> GraphReordered; + + /* this signal is emitted if the sample rate changes */ + + sigc::signal<void,jack_nframes_t> SampleRateChanged; + + /* this signal is sent if JACK ever disconnects us */ + + sigc::signal<void> Halted; + + /* these two are emitted when the engine itself is + started and stopped + */ + + sigc::signal<void> Running; + sigc::signal<void> Stopped; + + std::string make_port_name_relative (std::string); + std::string make_port_name_non_relative (std::string); + + private: + ARDOUR::Session *session; + jack_client_t *_jack; + std::string jack_client_name; + PBD::NonBlockingLock port_lock; + PBD::NonBlockingLock _process_lock; + PBD::Lock session_remove_lock; + pthread_cond_t session_removed; + bool session_remove_pending; + bool _running; + bool _has_run; + jack_nframes_t _buffer_size; + jack_nframes_t _frame_rate; + jack_nframes_t monitor_check_interval; + jack_nframes_t last_monitor_check; + jack_nframes_t _processed_frames; + bool _freewheeling; + bool _freewheel_thread_registered; + sigc::slot<int,jack_nframes_t> freewheel_action; + bool reconnect_on_halt; + int _usecs_per_cycle; + + typedef std::set<Port*> Ports; + Ports ports; + + int process_callback (jack_nframes_t nframes); + void remove_all_ports (); + + typedef std::pair<std::string,std::string> PortConnection; + typedef std::list<PortConnection> PortConnections; + + PortConnections port_connections; + void remove_connections_for (Port*); + + string get_nth_physical (uint32_t which, int flags); + + static int _xrun_callback (void *arg); + static int _graph_order_callback (void *arg); + static int _process_callback (jack_nframes_t nframes, void *arg); + static int _sample_rate_callback (jack_nframes_t nframes, void *arg); + static int _bufsize_callback (jack_nframes_t nframes, void *arg); + static void _jack_timebase_callback (jack_transport_state_t, jack_nframes_t, jack_position_t*, int, void*); + static int _jack_sync_callback (jack_transport_state_t, jack_position_t*, void *arg); + static void _freewheel_callback (int , void *arg); + + void jack_timebase_callback (jack_transport_state_t, jack_nframes_t, jack_position_t*, int); + int jack_sync_callback (jack_transport_state_t, jack_position_t*); + int jack_bufsize_callback (jack_nframes_t); + int jack_sample_rate_callback (jack_nframes_t); + + static void halted (void *); + static void meter (Port *port, jack_nframes_t nframes); + + int connect_to_jack (std::string client_name); +}; + +}; /* namespace ARDOUR */ + +#endif /* __ardour_audioengine_h__ */ diff --git a/libs/ardour/ardour/audiofilter.h b/libs/ardour/ardour/audiofilter.h new file mode 100644 index 0000000000..d0fc275cf6 --- /dev/null +++ b/libs/ardour/ardour/audiofilter.h @@ -0,0 +1,53 @@ +/* + Copyright (C) 2004 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_audiofilter_h__ +#define __ardour_audiofilter_h__ + +#include <vector> +#include <ardour/audioregion.h> + +namespace ARDOUR { + +class AudioRegion; +class Session; +class FileSource; + +class AudioFilter { + + public: + AudioFilter (ARDOUR::Session& s) + : session (s){} + virtual ~AudioFilter() {} + + + virtual int run (ARDOUR::AudioRegion&) = 0; + std::vector<ARDOUR::AudioRegion*> results; + + protected: + ARDOUR::Session& session; + + int make_new_sources (ARDOUR::AudioRegion&, ARDOUR::AudioRegion::SourceList&); + int finish (ARDOUR::AudioRegion&, ARDOUR::AudioRegion::SourceList&); +}; + +} /* namespace */ + +#endif /* __ardour_audiofilter_h__ */ diff --git a/libs/ardour/ardour/audioplaylist.h b/libs/ardour/ardour/audioplaylist.h new file mode 100644 index 0000000000..26cce91b12 --- /dev/null +++ b/libs/ardour/ardour/audioplaylist.h @@ -0,0 +1,121 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_audio_playlist_h__ +#define __ardour_audio_playlist_h__ + +#include <vector> +#include <list> + +#include <ardour/ardour.h> +#include <ardour/playlist.h> + +namespace ARDOUR { + +class Session; +class Region; +class AudioRegion; +class Source; + +class AudioPlaylist : public ARDOUR::Playlist +{ + public: + typedef std::list<Crossfade*> Crossfades; + + private: + + struct State : public ARDOUR::StateManager::State { + RegionList regions; + std::list<UndoAction> region_states; + + Crossfades crossfades; + std::list<UndoAction> crossfade_states; + + State (std::string why) : ARDOUR::StateManager::State (why) {} + ~State (); + }; + + public: + AudioPlaylist (Session&, const XMLNode&, bool hidden = false); + AudioPlaylist (Session&, string name, bool hidden = false); + AudioPlaylist (const AudioPlaylist&, string name, bool hidden = false); + AudioPlaylist (const AudioPlaylist&, jack_nframes_t start, jack_nframes_t cnt, string name, bool hidden = false); + + void clear (bool with_delete = false, bool with_save = true); + + jack_nframes_t read (Sample *dst, Sample *mixdown, float *gain_buffer, jack_nframes_t start, jack_nframes_t cnt, uint32_t chan_n=0); + + int set_state (const XMLNode&); + UndoAction get_memento() const; + + sigc::signal<void,Crossfade *> NewCrossfade; + + template<class T> void foreach_crossfade (T *t, void (T::*func)(Crossfade *)); + void crossfades_at (jack_nframes_t frame, Crossfades&); + + template<class T> void apply_to_history (T& obj, void (T::*method)(const ARDOUR::StateManager::StateMap&, state_id_t)) { + RegionLock rlock (this); + (obj.*method) (states, _current_state_id); + } + + bool destroy_region (Region*); + + void get_equivalent_regions (const AudioRegion&, std::vector<AudioRegion*>&); + void get_region_list_equivalent_regions (const AudioRegion&, std::vector<AudioRegion*>&); + + void drop_all_states (); + + protected: + + /* state management */ + + StateManager::State* state_factory (std::string) const; + Change restore_state (StateManager::State&); + void send_state_change (Change); + + /* playlist "callbacks" */ + void notify_crossfade_added (Crossfade *); + void flush_notifications (); + + void refresh_dependents (Region& region); + void check_dependents (Region& region, bool norefresh); + void remove_dependents (Region& region); + + protected: + ~AudioPlaylist (); /* public should use unref() */ + + private: + Crossfades _crossfades; + Crossfades _pending_xfade_adds; + + void crossfade_invalidated (Crossfade*); + XMLNode& state (bool full_state); + void dump () const; + + bool region_changed (Change, Region*); + void crossfade_changed (Change); + void add_crossfade (Crossfade&); +}; + +} /* namespace ARDOUR */ + +#endif /* __ardour_audio_playlist_h__ */ + + diff --git a/libs/ardour/ardour/audioregion.h b/libs/ardour/ardour/audioregion.h new file mode 100644 index 0000000000..44159f73f5 --- /dev/null +++ b/libs/ardour/ardour/audioregion.h @@ -0,0 +1,229 @@ +/* + Copyright (C) 2000-2001 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_audio_region_h__ +#define __ardour_audio_region_h__ + +#include <vector> + +#include <pbd/fastlog.h> +#include <pbd/undo.h> + +#include <ardour/ardour.h> +#include <ardour/source.h> +#include <ardour/gain.h> +#include <ardour/region.h> +#include <ardour/export.h> + +class XMLNode; + +namespace ARDOUR { + +class Route; +class Playlist; +class Session; +class AudioFilter; + +struct AudioRegionState : public RegionState +{ + AudioRegionState (std::string why); + + Curve _fade_in; + Curve _fade_out; + Curve _envelope; + gain_t _scale_amplitude; + uint32_t _fade_in_disabled; + uint32_t _fade_out_disabled; +}; + +class AudioRegion : public Region +{ + public: + typedef vector<Source *> SourceList; + + static Change FadeInChanged; + static Change FadeOutChanged; + static Change FadeInActiveChanged; + static Change FadeOutActiveChanged; + static Change EnvelopeActiveChanged; + static Change ScaleAmplitudeChanged; + static Change EnvelopeChanged; + + AudioRegion (Source&, jack_nframes_t start, jack_nframes_t length, bool announce = true); + AudioRegion (Source&, jack_nframes_t start, jack_nframes_t length, const string& name, layer_t = 0, Region::Flag flags = Region::DefaultFlags, bool announce = true); + AudioRegion (SourceList &, jack_nframes_t start, jack_nframes_t length, const string& name, layer_t = 0, Region::Flag flags = Region::DefaultFlags, bool announce = true); + AudioRegion (const AudioRegion&, jack_nframes_t start, jack_nframes_t length, const string& name, layer_t = 0, Region::Flag flags = Region::DefaultFlags, bool announce = true); + AudioRegion (const AudioRegion&); + AudioRegion (Source&, const XMLNode&); + AudioRegion (SourceList &, const XMLNode&); + ~AudioRegion(); + + bool region_list_equivalent (const AudioRegion&); + bool source_equivalent (const AudioRegion&); + bool equivalent (const AudioRegion&); + bool size_equivalent (const AudioRegion&); + + void lock_sources (); + void unlock_sources (); + Source& source (uint32_t n=0) const { if (n < sources.size()) return *sources[n]; else return *sources[0]; } + + void set_scale_amplitude (gain_t); + gain_t scale_amplitude() const { return _scale_amplitude; } + + void normalize_to (float target_in_dB = 0.0f); + + uint32_t n_channels() { return sources.size(); } + vector<string> master_source_names(); + + bool envelope_active () const { return _flags & Region::EnvelopeActive; } + bool fade_in_active () const { return _flags & Region::FadeIn; } + bool fade_out_active () const { return _flags & Region::FadeOut; } + bool captured() const { return !(_flags & (Region::Flag (Region::Import|Region::External))); } + + Curve& fade_in() { return _fade_in; } + Curve& fade_out() { return _fade_out; } + Curve& envelope() { return _envelope; } + + jack_nframes_t read_peaks (PeakData *buf, jack_nframes_t npeaks, jack_nframes_t offset, jack_nframes_t cnt, uint32_t chan_n=0, double samples_per_unit= 1.0) const; + + virtual jack_nframes_t read_at (Sample *buf, Sample *mixdown_buffer, + float *gain_buffer, jack_nframes_t position, jack_nframes_t cnt, + uint32_t chan_n = 0, + jack_nframes_t read_frames = 0, + jack_nframes_t skip_frames = 0) const; + + jack_nframes_t master_read_at (Sample *buf, Sample *mixdown_buffer, + float *gain_buffer, jack_nframes_t position, jack_nframes_t cnt, uint32_t chan_n=0) const; + + + XMLNode& state (bool); + XMLNode& get_state (); + int set_state (const XMLNode&); + + static void set_default_fade (float steepness, jack_nframes_t len); + + enum FadeShape { + Linear, + Fast, + Slow, + LogA, + LogB, + + }; + + void set_fade_in_active (bool yn); + void set_fade_in_shape (FadeShape); + void set_fade_in_length (jack_nframes_t); + void set_fade_in (FadeShape, jack_nframes_t); + + void set_fade_out_active (bool yn); + void set_fade_out_shape (FadeShape); + void set_fade_out_length (jack_nframes_t); + void set_fade_out (FadeShape, jack_nframes_t); + + void set_envelope_active (bool yn); + + int separate_by_channel (ARDOUR::Session&, vector<AudioRegion*>&) const; + + uint32_t read_data_count() const { return _read_data_count; } + + ARDOUR::Playlist* playlist() const { return _playlist; } + + UndoAction get_memento() const; + + /* filter */ + + int apply (AudioFilter&); + + /* export */ + + int exportme (ARDOUR::Session&, ARDOUR::AudioExportSpecification&); + + Region* get_parent(); + + /* xfade/fade interactions */ + + void suspend_fade_in (); + void suspend_fade_out (); + void resume_fade_in (); + void resume_fade_out (); + + private: + friend class Playlist; + + private: + SourceList sources; + SourceList master_sources; /* used when timefx are applied, so + we can always use the original + source. + */ + mutable Curve _fade_in; + FadeShape _fade_in_shape; + mutable Curve _fade_out; + FadeShape _fade_out_shape; + mutable Curve _envelope; + gain_t _scale_amplitude; + uint32_t _fade_in_disabled; + uint32_t _fade_out_disabled; + + void set_default_fades (); + void set_default_fade_in (); + void set_default_fade_out (); + void set_default_envelope (); + + StateManager::State* state_factory (std::string why) const; + Change restore_state (StateManager::State&); + + void recompute_gain_at_end (); + void recompute_gain_at_start (); + + bool copied() const { return _flags & Copied; } + void maybe_uncopy (); + void rename_after_first_edit (); + + jack_nframes_t _read_at (const SourceList&, Sample *buf, Sample *mixdown_buffer, + float *gain_buffer, jack_nframes_t position, jack_nframes_t cnt, + uint32_t chan_n = 0, + jack_nframes_t read_frames = 0, + jack_nframes_t skip_frames = 0) const; + + bool verify_start (jack_nframes_t position); + bool verify_length (jack_nframes_t position); + bool verify_start_mutable (jack_nframes_t& start); + bool verify_start_and_length (jack_nframes_t start, jack_nframes_t length); + void recompute_at_start (); + void recompute_at_end (); + + void envelope_changed (Change); + + void source_deleted (Source*); +}; + +} /* namespace ARDOUR */ + +/* access from C objects */ + +extern "C" { + int region_read_peaks_from_c (void *arg, uint32_t npeaks, uint32_t start, uint32_t length, intptr_t data, uint32_t n_chan, double samples_per_unit); + uint32_t region_length_from_c (void *arg); + uint32_t sourcefile_length_from_c (void *arg); +} + +#endif /* __ardour_audio_region_h__ */ diff --git a/libs/ardour/ardour/auditioner.h b/libs/ardour/ardour/auditioner.h new file mode 100644 index 0000000000..b79620eaa2 --- /dev/null +++ b/libs/ardour/ardour/auditioner.h @@ -0,0 +1,73 @@ +/* + Copyright (C) 2001 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_auditioner_h__ +#define __ardour_auditioner_h__ + +#include <string> +#include <pthread.h> + +#include <pbd/lockmonitor.h> +#include <pbd/atomic.h> + +#include <ardour/ardour.h> +#include <ardour/audio_track.h> + +namespace ARDOUR { + +class Session; +class AudioRegion; +class AudioPlaylist; + +class Auditioner : public AudioTrack +{ + public: + Auditioner (Session&); + ~Auditioner (); + + void audition_region (AudioRegion&); + + ARDOUR::AudioPlaylist& prepare_playlist (); + void audition_current_playlist (); + + int play_audition (jack_nframes_t nframes); + + void cancel_audition () { + atomic_set (&_active, 0); + } + + bool active() const { return atomic_read (&_active); } + + private: + AudioRegion *the_region; + jack_nframes_t current_frame; + atomic_t _active; + PBD::Lock lock; + jack_nframes_t length; + + void drop_ports (); + static void *_drop_ports (void *); + void actually_drop_ports (); + void output_changed (IOChange, void*); +}; + +}; /* namespace ARDOUR */ + +#endif /* __ardour_auditioner_h__ */ diff --git a/libs/ardour/ardour/automation_event.h b/libs/ardour/ardour/automation_event.h new file mode 100644 index 0000000000..562a424cc7 --- /dev/null +++ b/libs/ardour/ardour/automation_event.h @@ -0,0 +1,247 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_automation_event_h__ +#define __ardour_automation_event_h__ + +#include <stdint.h> +#include <list> +#include <cmath> + +#include <sigc++/signal.h> +#include <pbd/lockmonitor.h> +#include <pbd/undo.h> +#include <pbd/xml++.h> +#include <ardour/ardour.h> +#include <ardour/state_manager.h> + +namespace ARDOUR { + +struct ControlEvent { + double when; + double value; + + ControlEvent (double w, double v) + : when (w), value (v) { } + ControlEvent (const ControlEvent& other) + : when (other.when), value (other.value) {} + + virtual ~ControlEvent() {} + +// bool operator==(const ControlEvent& other) { +// return value == other.value && when == other.when; +// } + +}; + +class AutomationList : public StateManager +{ + public: + typedef std::list<ControlEvent*> AutomationEventList; + typedef AutomationEventList::iterator iterator; + typedef AutomationEventList::const_iterator const_iterator; + + AutomationList(double default_value, bool no_state = false); + ~AutomationList(); + + AutomationList (const AutomationList&); + AutomationList (const AutomationList&, double start, double end); + AutomationList& operator= (const AutomationList&); + bool operator== (const AutomationList&); + + void freeze(); + void thaw (); + + AutomationEventList::size_type size() const { return events.size(); } + bool empty() const { return events.empty(); } + + void reset_default (double val) { + default_value = val; + } + + void clear (); + void x_scale (double factor); + bool extend_to (double); + + void reposition_for_rt_add (double when); + void rt_add (double when, double value); + iterator add (double when, double value, iterator, bool ignore_mode = false); + void add (double when, double value, bool for_loading = false); + + void erase_range (double start, double end); + void erase (iterator); + void erase (iterator, iterator); + void move_range (iterator start, iterator end, double, double); + void modify (iterator, double, double); + + AutomationList* cut (double, double); + AutomationList* copy (double, double); + void clear (double, double); + + AutomationList* cut (iterator, iterator); + AutomationList* copy (iterator, iterator); + void clear (iterator, iterator); + + bool paste (AutomationList&, double position, float times); + + void set_automation_state (AutoState); + AutoState automation_state() const { return _state; } + sigc::signal<void> automation_style_changed; + + void set_automation_style (AutoStyle m); + AutoStyle automation_style() const { return _style; } + sigc::signal<void> automation_state_changed; + + bool automation_playback() { + return (_state & Play) || ((_state & Touch) && !_touching); + } + bool automation_write () { + return (_state & Write) || ((_state & Touch) && _touching); + } + + void start_touch (); + void stop_touch (); + bool touching() const { return _touching; } + + void set_yrange (double min, double max) { + min_yval = min; + max_yval = max; + } + + double get_max_y() const { return max_yval; } + double get_min_y() const { return min_yval; } + + void truncate_end (double length); + void truncate_start (double length); + + iterator begin() { return events.begin(); } + iterator end() { return events.end(); } + + ControlEvent* back() { return events.back(); } + ControlEvent* front() { return events.front(); } + + const_iterator const_begin() const { return events.begin(); } + const_iterator const_end() const { return events.end(); } + + std::pair<AutomationList::iterator,AutomationList::iterator> control_points_adjacent (double when); + + template<class T> void apply_to_points (T& obj, void (T::*method)(const AutomationList&)) { + LockMonitor lm (lock, __LINE__, __FILE__); + (obj.*method)(*this); + } + + UndoAction get_memento () const; + + virtual void store_state (XMLNode& node) const; + virtual void load_state (const XMLNode&); + + void set_max_xval (double); + double get_max_xval() const { return max_xval; } + + double eval (double where) { + LockMonitor lm (lock, __LINE__, __FILE__); + return unlocked_eval (where); + } + + double rt_safe_eval (double where, bool& ok) { + + TentativeLockMonitor lm (lock, __LINE__, __FILE__); + + if ((ok = lm.locked())) { + return unlocked_eval (where); + } else { + return 0.0; + } + } + + struct TimeComparator { + bool operator() (const ControlEvent* a, const ControlEvent* b) { + return a->when < b->when; + } + }; + + protected: + struct State : public ARDOUR::StateManager::State { + AutomationEventList events; + + State (std::string why) : ARDOUR::StateManager::State (why) {} + }; + + AutomationEventList events; + mutable PBD::NonBlockingLock lock; + bool _frozen; + bool changed_when_thawed; + bool _dirty; + + struct LookupCache { + double left; /* leftmost x coordinate used when finding "range" */ + std::pair<AutomationList::iterator,AutomationList::iterator> range; + }; + + LookupCache lookup_cache; + + AutoState _state; + AutoStyle _style; + bool _touching; + bool _new_touch; + double max_xval; + double min_yval; + double max_yval; + double default_value; + bool no_state; + + iterator rt_insertion_point; + double rt_pos; + + void maybe_signal_changed (); + void mark_dirty (); + void _x_scale (double factor); + + /* called by type-specific unlocked_eval() to handle + common case of 0, 1 or 2 control points. + */ + + double shared_eval (double x); + + /* called by shared_eval() to handle any case of + 3 or more control points. + */ + + virtual double multipoint_eval (double x); + + /* called by locked entry point and various private + locations where we already hold the lock. + */ + + virtual double unlocked_eval (double where); + + Change restore_state (StateManager::State&); + StateManager::State* state_factory (std::string why) const; + + virtual ControlEvent* point_factory (double,double) const; + virtual ControlEvent* point_factory (const ControlEvent&) const; + + + AutomationList* cut_copy_clear (double, double, int op); +}; + +} // namespace + +#endif /* __ardour_automation_event_h__ */ diff --git a/libs/ardour/ardour/click.h b/libs/ardour/ardour/click.h new file mode 100644 index 0000000000..71214978a5 --- /dev/null +++ b/libs/ardour/ardour/click.h @@ -0,0 +1,46 @@ +/* + Copyright (C) 2004 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_click_h__ +#define __ardour_click_h__ + +#include <ardour/io.h> + +namespace ARDOUR { + +class ClickIO : public IO +{ + public: + ClickIO (Session& s, const string& name, + + int input_min = -1, int input_max = -1, + + int output_min = -1, int output_max = -1) + : IO (s, name, input_min, input_max, output_min, output_max) {} + + ~ClickIO() {} + + protected: + uint32_t pans_required () const { return 1; } +}; + +}; /* namespace ARDOUR */ + +#endif /*__ardour_click_h__ */ diff --git a/libs/ardour/ardour/config.h b/libs/ardour/ardour/config.h new file mode 100644 index 0000000000..45bf2bac6d --- /dev/null +++ b/libs/ardour/ardour/config.h @@ -0,0 +1,57 @@ +/* config.h. Generated automatically by configure. */ +/* config.h.in. Generated automatically from configure.in by autoheader. */ + +/* Define if you don't have vprintf but do have _doprnt. */ +/* #undef HAVE_DOPRNT */ + +/* Define if you have the vprintf function. */ +/* #undef HAVE_VPRINTF */ + +/* Define if you have the ANSI C header files. */ +/* #undef STDC_HEADERS */ + +/* Define if your <sys/time.h> declares struct tm. */ +/* #undef TM_IN_SYS_TIME */ + +/* Define if you have the regcomp function. */ +/* #undef HAVE_REGCOMP */ + +/* Define if you have the strerror function. */ +/* #undef HAVE_STRERROR */ + +/* Define if you have the <dirent.h> header file. */ +#define HAVE_DIRENT_H 1 + +/* Define if you have the <fcntl.h> header file. */ +#define HAVE_FCNTL_H 1 + +/* Define if you have the <ladspa.h> header file. */ +#define HAVE_LADSPA_H 1 + +/* Define if you have the <limits.h> header file. */ +#define HAVE_LIMITS_H 1 + +/* Define if you have the <ndir.h> header file. */ +/* #undef HAVE_NDIR_H */ + +/* Define if you have the <sys/dir.h> header file. */ +/* #undef HAVE_SYS_DIR_H */ + +/* Define if you have the <sys/ndir.h> header file. */ +/* #undef HAVE_SYS_NDIR_H */ + +/* Define if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define if you have the gdbm library (-lgdbm). */ +#define HAVE_LIBGDBM 1 + +/* Define if you have the sndfile library (-lsndfile). */ +#define HAVE_LIBSNDFILE 1 + +/* Name of package */ +#define PACKAGE "ardour" + +/* Version number of package */ +#define VERSION "0.107.3" + diff --git a/libs/ardour/ardour/configuration.h b/libs/ardour/ardour/configuration.h new file mode 100644 index 0000000000..0c42027646 --- /dev/null +++ b/libs/ardour/ardour/configuration.h @@ -0,0 +1,253 @@ +/* + Copyright (C) 1999 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_configuration_h__ +#define __ardour_configuration_h__ + +#include <map> + +#include <sys/types.h> +#include <string> + +#include <ardour/types.h> +#include <ardour/stateful.h> + +using std::string; + +class XMLNode; + +namespace ARDOUR { + +class Configuration : public Stateful +{ + public: + Configuration(); + virtual ~Configuration(); + + struct MidiPortDescriptor { + string tag; + string device; + string type; + string mode; + + MidiPortDescriptor (const XMLNode&); + XMLNode& get_state(); + }; + + std::map<string,MidiPortDescriptor *> midi_ports; + + int load_state (); + int save_state (); + + XMLNode& option_node (const string &, const string &); + + int set_state (const XMLNode&); + XMLNode& get_state (void); + + XMLNode * get_keys() const; + void set_keys(XMLNode *); + + void set_use_vst (bool yn); + bool get_use_vst(); + + bool get_trace_midi_input (); + void set_trace_midi_input (bool); + + bool get_trace_midi_output (); + void set_trace_midi_output (bool); + + string get_raid_path(); + void set_raid_path(string); + + uint32_t get_minimum_disk_io(); + void set_minimum_disk_io(uint32_t); + + float get_track_buffer(); + void set_track_buffer(float); + + bool does_hiding_groups_deactivates_groups(); + void set_hiding_groups_deactivates_groups(bool); + + string get_auditioner_output_left(); + void set_auditioner_output_left(string); + + string get_auditioner_output_right(); + void set_auditioner_output_right(string); + + bool get_mute_affects_pre_fader(); + void set_mute_affects_pre_fader (bool); + + bool get_mute_affects_post_fader(); + void set_mute_affects_post_fader (bool); + + bool get_mute_affects_control_outs (); + void set_mute_affects_control_outs (bool); + + bool get_mute_affects_main_outs (); + void set_mute_affects_main_outs (bool); + + bool get_solo_latch (); + void set_solo_latch (bool); + + uint32_t get_disk_choice_space_threshold(); + void set_disk_choice_space_threshold (uint32_t); + + string get_mmc_port_name(); + void set_mmc_port_name(string); + + string get_mtc_port_name(); + void set_mtc_port_name(string); + + string get_midi_port_name(); + void set_midi_port_name(string); + + bool get_use_hardware_monitoring(); + void set_use_hardware_monitoring(bool); + + bool get_jack_time_master(); + void set_jack_time_master(bool); + + bool get_native_format_is_bwf(); + void set_native_format_is_bwf(bool); + + bool get_plugins_stop_with_transport(); + void set_plugins_stop_with_transport(bool); + + bool get_no_sw_monitoring(); + void set_no_sw_monitoring(bool); + + bool get_stop_recording_on_xrun(); + void set_stop_recording_on_xrun(bool); + + bool get_verify_remove_last_capture(); + void set_verify_remove_last_capture(bool); + + bool get_stop_at_session_end(); + void set_stop_at_session_end(bool); + + bool get_seamless_looping(); + void set_seamless_looping(bool); + + bool get_auto_xfade(); + void set_auto_xfade (bool); + + bool get_no_new_session_dialog(); + void set_no_new_session_dialog(bool); + + uint32_t get_timecode_skip_limit (); + void set_timecode_skip_limit (uint32_t); + + bool get_timecode_source_is_synced (); + void set_timecode_source_is_synced (bool); + + string get_user_ardour_path (); + string get_system_ardour_path (); + + gain_t get_quieten_at_speed (); + void set_quieten_at_speed (gain_t); + + private: + void set_defaults (); + string get_system_path(); + string get_user_path(); + + /* this is subject to wordexp, so we need + to keep the original (user-entered) form + around. e.g. ~/blah-> /home/foo/blah + */ + + string raid_path; + bool raid_path_is_user; + string orig_raid_path; + + uint32_t minimum_disk_io_bytes; + bool minimum_disk_io_bytes_is_user; + float track_buffer_seconds; + bool track_buffer_seconds_is_user; + bool hiding_groups_deactivates_groups; + bool hiding_groups_deactivates_groups_is_user; + string auditioner_output_left; + bool auditioner_output_left_is_user; + string auditioner_output_right; + bool auditioner_output_right_is_user; + bool mute_affects_pre_fader; + bool mute_affects_pre_fader_is_user; + bool mute_affects_post_fader; + bool mute_affects_post_fader_is_user; + bool mute_affects_control_outs; + bool mute_affects_control_outs_is_user; + bool mute_affects_main_outs; + bool mute_affects_main_outs_is_user; + bool solo_latch; + bool solo_latch_is_user; + uint32_t disk_choice_space_threshold; + bool disk_choice_space_threshold_is_user; + string mtc_port_name; + bool mtc_port_name_is_user; + string mmc_port_name; + bool mmc_port_name_is_user; + string midi_port_name; + bool midi_port_name_is_user; + bool use_hardware_monitoring; + bool use_hardware_monitoring_is_user; + bool be_jack_time_master; + bool be_jack_time_master_is_user; + bool native_format_is_bwf; + bool native_format_is_bwf_is_user; + bool trace_midi_input; + bool trace_midi_input_is_user; + bool trace_midi_output; + bool trace_midi_output_is_user; + bool plugins_stop_with_transport; + bool plugins_stop_with_transport_is_user; + bool no_sw_monitoring; + bool no_sw_monitoring_is_user; + bool stop_recording_on_xrun; + bool stop_recording_on_xrun_is_user; + bool verify_remove_last_capture; + bool verify_remove_last_capture_is_user; + bool stop_at_session_end; + bool stop_at_session_end_is_user; + bool seamless_looping; + bool seamless_looping_is_user; + bool auto_xfade; + bool auto_xfade_is_user; + bool no_new_session_dialog; + bool no_new_session_dialog_is_user; + uint32_t timecode_skip_limit; + bool timecode_skip_limit_is_user; + bool timecode_source_is_synced; + bool timecode_source_is_synced_is_user; + bool use_vst; /* always per-user */ + bool quieten_at_speed; + bool quieten_at_speed_is_user; + + XMLNode *key_node; + bool user_configuration; + + XMLNode& state (bool user_only); +}; + +extern Configuration *Config; +extern gain_t speed_quietning; /* see comment in configuration.cc */ + +}; /* namespace ARDOUR */ + +#endif /* __ardour_configuration_h__ */ diff --git a/libs/ardour/ardour/connection.h b/libs/ardour/ardour/connection.h new file mode 100644 index 0000000000..b33af9cb21 --- /dev/null +++ b/libs/ardour/ardour/connection.h @@ -0,0 +1,94 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_connection_h__ +#define __ardour_connection_h__ + +#include <vector> +#include <string> +#include <sigc++/signal.h> +#include <pbd/lockmonitor.h> +#include <ardour/stateful.h> + +using std::vector; +using std::string; + +namespace ARDOUR { + +class Connection : public Stateful, public sigc::trackable { + public: + Connection (string name, bool sdep = false) : _name (name), _sysdep(sdep) {} + ~Connection() {} + + typedef vector<string> PortList; + + void set_name (string name, void *src); + string name() const { return _name; } + + bool system_dependent() const { return _sysdep; } + + uint32_t nports () const { return _ports.size(); } + const PortList& port_connections (int port) const; + + void add_connection (int port, string portname); + void remove_connection (int port, string portname); + + void add_port (); + void remove_port (int port); + void clear (); + + sigc::signal<void,void*> NameChanged; + sigc::signal<void> ConfigurationChanged; + sigc::signal<void,int> ConnectionsChanged; + + bool operator==(const Connection& other) const; + + XMLNode& get_state (void); + int set_state (const XMLNode&); + + protected: + Connection (const XMLNode&); + + private: + mutable PBD::Lock port_lock; + vector<PortList> _ports; + string _name; + bool _sysdep; + + int set_connections (const string& str); + int parse_io_string (const string& str, vector<string>& ports); +}; + +class InputConnection : public Connection { + public: + InputConnection (string name, bool sdep = false) : Connection (name, sdep) {} + InputConnection (const XMLNode&); +}; + +class OutputConnection : public Connection { + public: + OutputConnection (string name, bool sdep = false) : Connection (name, sdep) {} + OutputConnection (const XMLNode&); +}; + +} + +#endif /* __ardour_connection_h__ */ + diff --git a/libs/ardour/ardour/constsource.h b/libs/ardour/ardour/constsource.h new file mode 100644 index 0000000000..d000afb347 --- /dev/null +++ b/libs/ardour/ardour/constsource.h @@ -0,0 +1,60 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __playlist_const_buffer_h__ +#define __playlist_const_buffer_h__ + +#include <string> +#include <cstdlib> + +#include "edl.h" + +namespace EDL { + +class ConstSource : public Source { + public: + ConstSource (const gchar *id) { + _type = Source::Const; + value = strtod (id, 0); + strncpy (idstr, id, 15); + idstr[15] = '\0'; + } + + const gchar * const id() { return idstr; } + + uint32_t length() { return ~0U; } + + uint32_t read (Source::Data *dst, uint32_t start, uint32_t cnt) { + uint32_t n = cnt; + while (n--) *dst++ = value; + return cnt; + } + void peak (guint8 *max, guint8 *min, uint32_t start, uint32_t cnt) { + *max = *min = (guint8) value; + } + + private: + Source::Data value; + gchar idstr[16]; +}; + +}; /* namespace EDL */ + +#endif /* __playlist_const_buffer_h__ */ diff --git a/libs/ardour/ardour/crossfade.h b/libs/ardour/ardour/crossfade.h new file mode 100644 index 0000000000..419b980a83 --- /dev/null +++ b/libs/ardour/ardour/crossfade.h @@ -0,0 +1,182 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_overlap_h__ +#define __ardour_overlap_h__ + +#include <vector> +#include <algorithm> + +#include <sigc++/signal.h> + +#include <pbd/undo.h> + +#include <ardour/ardour.h> +#include <ardour/curve.h> +#include <ardour/audioregion.h> +#include <ardour/state_manager.h> +#include <ardour/crossfade_compare.h> + +namespace ARDOUR { + +class AudioRegion; +class Playlist; + +struct CrossfadeState : public StateManager::State { + CrossfadeState (std::string reason) : StateManager::State (reason) {} + + UndoAction fade_in_memento; + UndoAction fade_out_memento; + jack_nframes_t position; + jack_nframes_t length; + AnchorPoint anchor_point; + bool follow_overlap; + bool active; +}; + +class Crossfade : public Stateful, public StateManager +{ + public: + + class NoCrossfadeHere: std::exception { + public: + virtual const char *what() const throw() { return "no crossfade should be constructed here"; } + }; + + /* constructor for "fixed" xfades at each end of an internal overlap */ + + Crossfade (ARDOUR::AudioRegion& in, ARDOUR::AudioRegion& out, + jack_nframes_t position, + jack_nframes_t initial_length, + AnchorPoint); + + /* constructor for xfade between two regions that are overlapped in any way + except the "internal" case. + */ + + Crossfade (ARDOUR::AudioRegion& in, ARDOUR::AudioRegion& out, CrossfadeModel, bool active); + + /* the usual XML constructor */ + + Crossfade (const ARDOUR::Playlist&, XMLNode&); + virtual ~Crossfade(); + + bool operator== (const ARDOUR::Crossfade&); + + XMLNode& get_state (void); + int set_state (const XMLNode&); + + ARDOUR::AudioRegion& in() const { return *_in; } + ARDOUR::AudioRegion& out() const { return *_out; } + + jack_nframes_t read_at (Sample *buf, Sample *mixdown_buffer, + float *gain_buffer, jack_nframes_t position, jack_nframes_t cnt, + uint32_t chan_n, + jack_nframes_t read_frames = 0, + jack_nframes_t skip_frames = 0); + + bool refresh (); + + uint32_t upper_layer () const { + return std::max (_in->layer(), _out->layer()); + } + + uint32_t lower_layer () const { + return std::min (_in->layer(), _out->layer()); + } + + bool involves (ARDOUR::AudioRegion& region) const { + return _in == ®ion || _out == ®ion; + } + + bool involves (ARDOUR::AudioRegion& a, ARDOUR::AudioRegion& b) const { + return (_in == &a && _out == &b) || (_in == &b && _out == &a); + } + + jack_nframes_t length() const { return _length; } + jack_nframes_t overlap_length() const; + jack_nframes_t position() const { return _position; } + + sigc::signal<void,Crossfade*> Invalidated; + sigc::signal<void> GoingAway; + + bool covers (jack_nframes_t frame) const { + return _position <= frame && frame < _position + _length; + } + + OverlapType coverage (jack_nframes_t start, jack_nframes_t end) const; + + UndoAction get_memento() const; + + static void set_buffer_size (jack_nframes_t); + + bool active () const { return _active; } + void set_active (bool yn); + + bool following_overlap() const { return _follow_overlap; } + bool can_follow_overlap() const; + void set_follow_overlap (bool yn); + + Curve& fade_in() { return _fade_in; } + Curve& fade_out() { return _fade_out; } + + jack_nframes_t set_length (jack_nframes_t); + + static jack_nframes_t short_xfade_length() { return _short_xfade_length; } + static void set_short_xfade_length (jack_nframes_t n); + + static Change ActiveChanged; + + private: + friend struct CrossfadeComparePtr; + + static jack_nframes_t _short_xfade_length; + + ARDOUR::AudioRegion* _in; + ARDOUR::AudioRegion* _out; + bool _active; + bool _in_update; + OverlapType overlap_type; + jack_nframes_t _length; + jack_nframes_t _position; + AnchorPoint _anchor_point; + bool _follow_overlap; + bool _fixed; + Curve _fade_in; + Curve _fade_out; + + static Sample* crossfade_buffer_out; + static Sample* crossfade_buffer_in; + + void initialize (); + int compute (ARDOUR::AudioRegion&, ARDOUR::AudioRegion&, CrossfadeModel); + bool update (bool force); + + StateManager::State* state_factory (std::string why) const; + Change restore_state (StateManager::State&); + + void member_changed (ARDOUR::Change); + +}; + + +} // namespace ARDOUR + +#endif /* __ardour_overlap_h__ */ diff --git a/libs/ardour/ardour/crossfade_compare.h b/libs/ardour/ardour/crossfade_compare.h new file mode 100644 index 0000000000..2ecf79c04c --- /dev/null +++ b/libs/ardour/ardour/crossfade_compare.h @@ -0,0 +1,43 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_crossfade_compare_h__ +#define __ardour_crossfade_compare_h__ + +/* this exists so that playlist.h doesn't have to include crossfade.h + */ + +namespace ARDOUR { + +class Crossfade; + +struct CrossfadeComparePtr { + bool operator() (const Crossfade *a, const Crossfade *b) const; +}; + +enum AnchorPoint { + StartOfIn, + EndOfIn, + EndOfOut +}; + +} + +#endif /* __ardour_crossfade_compare_h__ */ diff --git a/libs/ardour/ardour/curve.h b/libs/ardour/ardour/curve.h new file mode 100644 index 0000000000..1c6a4c5bc4 --- /dev/null +++ b/libs/ardour/ardour/curve.h @@ -0,0 +1,86 @@ +/* + Copyright (C) 2001-2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_curve_h__ +#define __ardour_curve_h__ + +#include <sys/types.h> +#include <sigc++/signal.h> +#include <pbd/lockmonitor.h> +#include <pbd/undo.h> +#include <list> +#include <algorithm> +#include <pthread.h> +#include <ardour/automation_event.h> + +namespace ARDOUR { + +struct CurvePoint : public ControlEvent +{ + double coeff[4]; + + CurvePoint (double w, double v) + : ControlEvent (w, v) { + + coeff[0] = coeff[1] = coeff[2] = coeff[3] = 0.0; + } + + ~CurvePoint() {} +}; + +class Curve : public AutomationList +{ + public: + Curve (double min_yval, double max_yval, double defaultvalue, bool nostate = false); + ~Curve (); + Curve (const Curve& other); + Curve (const Curve& other, double start, double end); + + bool rt_safe_get_vector (double x0, double x1, float *arg, int32_t veclen); + void get_vector (double x0, double x1, float *arg, int32_t veclen); + + AutomationEventList::iterator closest_control_point_before (double xval); + AutomationEventList::iterator closest_control_point_after (double xval); + + void solve (); + + protected: + ControlEvent* point_factory (double,double) const; + ControlEvent* point_factory (const ControlEvent&) const; + + Change restore_state (StateManager::State&); + + private: + AutomationList::iterator last_bound; + + double unlocked_eval (double where); + double multipoint_eval (double x); + + void _get_vector (double x0, double x1, float *arg, int32_t veclen); + +}; + +}; /* namespace ARDOUR */ + +extern "C" { + void curve_get_vector_from_c (void *arg, double, double, float*, int32_t); +} + +#endif /* __ardour_curve_h__ */ diff --git a/libs/ardour/ardour/cycle_timer.h b/libs/ardour/ardour/cycle_timer.h new file mode 100644 index 0000000000..1ec7c74903 --- /dev/null +++ b/libs/ardour/ardour/cycle_timer.h @@ -0,0 +1,53 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_cycle_timer_h__ +#define __ardour_cycle_timer_h__ + +#include <string> +#include <cstdio> + +#include <ardour/cycles.h> + +using std::string; + +class CycleTimer { + private: + static float cycles_per_usec; + uint32_t long entry; + uint32_t long exit; + string _name; + + public: + CycleTimer(string name) : _name (name){ + if (cycles_per_usec == 0) { + cycles_per_usec = get_mhz (); + } + entry = get_cycles(); + } + ~CycleTimer() { + exit = get_cycles(); + printf ("%s: %.9f usecs (%lu-%lu)\n", _name.c_str(), (float) (exit - entry) / cycles_per_usec, entry, exit); + } + + static float get_mhz (); +}; + +#endif /* __ardour_cycle_timer_h__ */ diff --git a/libs/ardour/ardour/cycles.h b/libs/ardour/ardour/cycles.h new file mode 100644 index 0000000000..f194988da9 --- /dev/null +++ b/libs/ardour/ardour/cycles.h @@ -0,0 +1,221 @@ +/* + Copyright (C) 2001 Paul Davis + Code derived from various headers from the Linux kernel + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_cycles_h__ +#define __ardour_cycles_h__ + +#include <stdint.h> + +#if defined(__i386__) || defined(__x86_64__) + +/* + * Standard way to access the cycle counter on i586+ CPUs. + * Currently only used on SMP. + * + * If you really have a SMP machine with i486 chips or older, + * compile for that, and this will just always return zero. + * That's ok, it just means that the nicer scheduling heuristics + * won't work for you. + * + * We only use the low 32 bits, and we'd simply better make sure + * that we reschedule before that wraps. Scheduling at least every + * four billion cycles just basically sounds like a good idea, + * regardless of how fast the machine is. + */ +typedef uint64_t cycles_t; + +extern cycles_t cacheflush_time; + +#define rdtscll(val) \ + __asm__ __volatile__("rdtsc" : "=A" (val)) + +static inline cycles_t get_cycles (void) +{ + uint32_t long ret; + + rdtscll(ret); + return ret; +} + +#elif defined(__powerpc__) + +#define CPU_FTR_601 0x00000100 + +typedef uint32_t cycles_t; + +/* + * For the "cycle" counter we use the timebase lower half. + * Currently only used on SMP. + */ + +extern cycles_t cacheflush_time; + +static inline cycles_t get_cycles(void) +{ + cycles_t ret = 0; + + __asm__ __volatile__( + "98: mftb %0\n" + "99:\n" + ".section __ftr_fixup,\"a\"\n" + " .long %1\n" + " .long 0\n" + " .long 98b\n" + " .long 99b\n" + ".previous" + : "=r" (ret) : "i" (CPU_FTR_601)); + return ret; +} + +#elif defined(__ia64__) +/* ia64 */ + +typedef uint32_t cycles_t; +static inline cycles_t +get_cycles (void) +{ + cycles_t ret; + __asm__ __volatile__ ("mov %0=ar.itc" : "=r"(ret)); + return ret; +} + +#elif defined(__alpha__) +/* alpha */ + +/* + * Standard way to access the cycle counter. + * Currently only used on SMP for scheduling. + * + * Only the low 32 bits are available as a continuously counting entity. + * But this only means we'll force a reschedule every 8 seconds or so, + * which isn't an evil thing. + */ + +typedef uint32_t cycles_t; +static inline cycles_t get_cycles (void) +{ + cycles_t ret; + __asm__ __volatile__ ("rpcc %0" : "=r"(ret)); + return ret; +} + +#elif defined(__s390__) +/* s390 */ + +typedef uint32_t long cycles_t; +static inline cycles_t get_cycles(void) +{ + cycles_t cycles; + __asm__("stck 0(%0)" : : "a" (&(cycles)) : "memory", "cc"); + return cycles >> 2; +} + +#elif defined(__hppa__) +/* hppa/parisc */ + +#define mfctl(reg) ({ \ + uint32_t cr; \ + __asm__ __volatile__( \ + "mfctl " #reg ",%0" : \ + "=r" (cr) \ + ); \ + cr; \ +}) + +typedef uint32_t cycles_t; +static inline cycles_t get_cycles (void) +{ + return mfctl(16); +} + +#elif defined(__mips__) +/* mips/mipsel */ + +/* + * Standard way to access the cycle counter. + * Currently only used on SMP for scheduling. + * + * Only the low 32 bits are available as a continuously counting entity. + * But this only means we'll force a reschedule every 8 seconds or so, + * which isn't an evil thing. + * + * We know that all SMP capable CPUs have cycle counters. + */ + +#define __read_32bit_c0_register(source, sel) \ +({ int __res; \ + if (sel == 0) \ + __asm__ __volatile__( \ + "mfc0\t%0, " #source "\n\t" \ + : "=r" (__res)); \ + else \ + __asm__ __volatile__( \ + ".set\tmips32\n\t" \ + "mfc0\t%0, " #source ", " #sel "\n\t" \ + ".set\tmips0\n\t" \ + : "=r" (__res)); \ + __res; \ +}) + +/* #define CP0_COUNT $9 */ +#define read_c0_count() __read_32bit_c0_register($9, 0) + +typedef uint32_t cycles_t; +static inline cycles_t get_cycles (void) +{ + return read_c0_count(); +} + +/* begin mach */ +#elif defined(__APPLE__) +#include <CoreAudio/CoreAudioTypes.h> +#include <CoreAudio/HostTime.h> +typedef UInt64 cycles_t; +static inline cycles_t get_cycles (void) +{ + UInt64 time = AudioGetCurrentHostTime(); + return AudioConvertHostTimeToNanos(time); +} +/* end mach */ + +#else + +/* debian: sparc, arm, m68k */ + +#warning You are compiling libardour on a platform for which ardour/cycles.h needs work + +#include <sys/time.h> + +typedef long cycles_t; + +extern cycles_t cacheflush_time; + +static inline cycles_t get_cycles(void) +{ + struct timeval tv; + gettimeofday (&tv, NULL); + + return tv.tv_usec; +} + +#endif + +#endif /* __ardour_cycles_h__ */ diff --git a/libs/ardour/ardour/dB.h b/libs/ardour/ardour/dB.h new file mode 100644 index 0000000000..703de6fb1a --- /dev/null +++ b/libs/ardour/ardour/dB.h @@ -0,0 +1,34 @@ +/* + Copyright (C) 2001 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_dB_h__ +#define __ardour_dB_h__ + +#include <pbd/fastlog.h> + +static inline float dB_to_coefficient (float dB) { + return dB > -318.8f ? pow (10.0f, dB * 0.05f) : 0.0f; +} + +static inline float coefficient_to_dB (float coeff) { + return 20.0f * fast_log10 (coeff); +} + +#endif /* __ardour_dB_h__ */ diff --git a/libs/ardour/ardour/diskstream.h b/libs/ardour/ardour/diskstream.h new file mode 100644 index 0000000000..9028f0d9e0 --- /dev/null +++ b/libs/ardour/ardour/diskstream.h @@ -0,0 +1,433 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_diskstream_h__ +#define __ardour_diskstream_h__ + +#include <sigc++/signal.h> + +#include <cmath> +#include <string> +#include <queue> +#include <map> +#include <vector> + +#include <time.h> + +#include <pbd/fastlog.h> +#include <pbd/ringbufferNPT.h> +#include <pbd/atomic.h> + +#include <ardour/ardour.h> +#include <ardour/configuration.h> +#include <ardour/session.h> +#include <ardour/route_group.h> +#include <ardour/route.h> +#include <ardour/port.h> +#include <ardour/utils.h> +#include <ardour/stateful.h> + +struct tm; + +namespace ARDOUR { + +class AudioEngine; +class Send; +class Session; +class AudioPlaylist; +class FileSource; +class IO; + +class DiskStream : public Stateful, public sigc::trackable +{ + public: + enum Flag { + Recordable = 0x1, + Hidden = 0x2 + }; + + DiskStream (Session &, const string& name, Flag f = Recordable); + DiskStream (Session &, const XMLNode&); + + string name() const { return _name; } + + ARDOUR::IO* io() const { return _io; } + void set_io (ARDOUR::IO& io); + + DiskStream& ref() { _refcnt++; return *this; } + void unref() { if (_refcnt) _refcnt--; if (_refcnt == 0) delete this; } + uint32_t refcnt() const { return _refcnt; } + + float playback_buffer_load() const; + float capture_buffer_load() const; + + void set_flag (Flag f) { + _flags |= f; + } + + void unset_flag (Flag f) { + _flags &= ~f; + } + + AlignStyle alignment_style() const { return _alignment_style; } + void set_align_style (AlignStyle); + void set_persistent_align_style (AlignStyle); + + bool hidden() const { return _flags & Hidden; } + bool recordable() const { return _flags & Recordable; } + + jack_nframes_t roll_delay() const { return _roll_delay; } + void set_roll_delay (jack_nframes_t); + + void set_name (string str, void* src); + + string input_source (uint32_t n=0) const { + if (n < channels.size()) { + return channels[n].source ? channels[n].source->name() : ""; + } else { + return ""; + } + } + + Port *input_source_port (uint32_t n=0) const { + if (n < channels.size()) return channels[n].source; return 0; + } + + void set_record_enabled (bool yn, void *src); + bool record_enabled() const { return atomic_read (&_record_enabled); } + void punch_in (); + void punch_out (); + + bool reversed() const { return _actual_speed < 0.0f; } + float speed() const { return _visible_speed; } + void set_speed (float); + + float peak_power(uint32_t n=0) { + float x = channels[n].peak_power; + channels[n].peak_power = 0.0f; + if (x > 0.0f) { + return 20.0f * fast_log10(x); + } else { + return minus_infinity(); + } + } + + int use_playlist (AudioPlaylist *); + int use_new_playlist (); + int use_copy_playlist (); + + void start_scrub (jack_nframes_t where); + void end_scrub (); + + Sample *playback_buffer (uint32_t n=0) { + if (n < channels.size()) + return channels[n].current_playback_buffer; + return 0; + } + + Sample *capture_buffer (uint32_t n=0) { + if (n < channels.size()) + return channels[n].current_capture_buffer; + return 0; + } + + AudioPlaylist *playlist () { return _playlist; } + + FileSource *fades_source (uint32_t n=0) { + if (n < channels.size()) + return channels[n].fades_source; + return 0; + } + FileSource *write_source (uint32_t n=0) { + if (n < channels.size()) + return channels[n].write_source; + return 0; + } + + jack_nframes_t current_capture_start() const { return capture_start_frame; } + jack_nframes_t current_capture_end() const { return capture_start_frame + capture_captured; } + jack_nframes_t get_capture_start_frame (uint32_t n=0); + jack_nframes_t get_captured_frames (uint32_t n=0); + + uint32_t n_channels() { return _n_channels; } + + int add_channel (); + int remove_channel (); + + static void set_disk_io_chunk_frames (uint32_t n) { + disk_io_chunk_frames = n; + } + + static jack_nframes_t disk_io_frames() { return disk_io_chunk_frames; } + + sigc::signal<void,void*> record_enable_changed; + sigc::signal<void> speed_changed; + sigc::signal<void,void*> reverse_changed; + sigc::signal<void> PlaylistChanged; + sigc::signal<void> AlignmentStyleChanged; + + static sigc::signal<void> DiskOverrun; + static sigc::signal<void> DiskUnderrun; + static sigc::signal<void,DiskStream*> DiskStreamCreated; // XXX use a ref with sigc2 + static sigc::signal<void,DiskStream*> CannotRecordNoInput; // XXX use a ref with sigc2 + static sigc::signal<void,list<Source*>*> DeleteSources; + + /* stateful */ + + XMLNode& get_state(void); + int set_state(const XMLNode& node); + + void monitor_input (bool); + + jack_nframes_t capture_offset() const { return _capture_offset; } + void set_capture_offset (); + + static void swap_by_ptr (Sample *first, Sample *last) { + while (first < last) { + Sample tmp = *first; + *first++ = *last; + *last-- = tmp; + } + } + + static void swap_by_ptr (Sample *first, Sample *last, jack_nframes_t n) { + while (n--) { + Sample tmp = *first; + *first++ = *last; + *last-- = tmp; + } + } + + bool slaved() const { return _slaved; } + void set_slaved(bool yn) { _slaved = yn; } + + int set_loop (Location *loc); + sigc::signal<void,Location *> LoopSet; + + std::list<Region*>& last_capture_regions () { + return _last_capture_regions; + } + + void handle_input_change (IOChange, void *src); + + id_t id() const { return _id; } + + XMLNode* deprecated_io_node; + + protected: + friend class Session; + + /* the Session is the only point of access for these + because they require that the Session is "inactive" + while they are called. + */ + + void set_pending_overwrite (bool); + int overwrite_existing_buffers (); + void reverse_scrub_buffer (bool to_forward); + void set_block_size (jack_nframes_t); + int internal_playback_seek (jack_nframes_t distance); + int can_internal_playback_seek (jack_nframes_t distance); + void reset_write_sources (bool); + void non_realtime_input_change (); + + uint32_t read_data_count() const { return _read_data_count; } + uint32_t write_data_count() const { return _write_data_count; } + + protected: + friend class Auditioner; + int seek (jack_nframes_t which_sample, bool complete_refill = false); + + protected: + friend class AudioTrack; + + void prepare (); + int process (jack_nframes_t transport_frame, jack_nframes_t nframes, jack_nframes_t offset, bool can_record, bool rec_monitors_input); + bool commit (jack_nframes_t nframes); + void recover (); /* called if commit will not be called, but process was */ + + private: + + /* use unref() to destroy a diskstream */ + + ~DiskStream(); + + struct ChannelInfo { + + Sample *playback_wrap_buffer; + Sample *capture_wrap_buffer; + Sample *speed_buffer; + + float peak_power; + + FileSource *fades_source; + FileSource *write_source; + + Port *source; + Sample *current_capture_buffer; + Sample *current_playback_buffer; + + RingBufferNPT<Sample> *playback_buf; + RingBufferNPT<Sample> *capture_buf; + + Sample* scrub_buffer; + Sample* scrub_forward_buffer; + Sample* scrub_reverse_buffer; + + RingBufferNPT<Sample>::rw_vector playback_vector; + RingBufferNPT<Sample>::rw_vector capture_vector; + }; + + typedef vector<ChannelInfo> ChannelList; + + string _name; + ARDOUR::Session& _session; + ARDOUR::IO* _io; + ChannelList channels; + uint32_t _n_channels; + id_t _id; + + atomic_t _record_enabled; + bool rec_monitoring_off_for_roll; + AudioPlaylist* _playlist; + float _visible_speed; + float _actual_speed; + /* items needed for speed change logic */ + bool _buffer_reallocation_required; + bool _seek_required; + + bool force_refill; + jack_nframes_t capture_start_frame; + jack_nframes_t capture_captured; + bool was_recording; + jack_nframes_t adjust_capture_position; + jack_nframes_t _capture_offset; + jack_nframes_t _roll_delay; + jack_nframes_t first_recordable_frame; + jack_nframes_t last_recordable_frame; + int last_possibly_recording; + AlignStyle _alignment_style; + bool _scrubbing; + bool _slaved; + bool _processed; + Location* loop_location; + jack_nframes_t overwrite_frame; + off_t overwrite_offset; + bool pending_overwrite; + bool overwrite_queued; + IOChange input_change_pending; + jack_nframes_t wrap_buffer_size; + jack_nframes_t speed_buffer_size; + + uint64_t last_phase; + uint64_t phi; + + jack_nframes_t file_frame; + jack_nframes_t playback_sample; + jack_nframes_t playback_distance; + + uint32_t _read_data_count; + uint32_t _write_data_count; + + bool in_set_state; + AlignStyle _persistent_alignment_style; + bool first_input_change; + + PBD::NonBlockingLock state_lock; + + jack_nframes_t scrub_start; + jack_nframes_t scrub_buffer_size; + jack_nframes_t scrub_offset; + uint32_t _refcnt; + + sigc::connection ports_created_c; + sigc::connection plmod_connection; + sigc::connection plstate_connection; + sigc::connection plgone_connection; + + /* the two central butler operations */ + + int do_flush (bool force = false); + int do_refill (Sample *mixdown_buffer, float *gain_buffer); + + int read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, jack_nframes_t& start, jack_nframes_t cnt, + ChannelInfo& channel_info, int channel, bool reversed); + + uint32_t i_am_the_modifier; + + /* XXX fix this redundancy ... */ + + void playlist_changed (Change); + void playlist_modified (); + void playlist_deleted (Playlist*); + void session_controls_changed (Session::ControlType); + + void finish_capture (bool rec_monitors_input); + void clean_up_capture (struct tm&, time_t, bool abort); + void transport_stopped (struct tm&, time_t, bool abort); + + struct CaptureInfo { + uint32_t start; + uint32_t frames; + }; + + vector<CaptureInfo*> capture_info; + PBD::Lock capture_info_lock; + + void init (Flag); + + void init_channel (ChannelInfo &chan); + void destroy_channel (ChannelInfo &chan); + + static jack_nframes_t disk_io_chunk_frames; + + int use_new_write_source (uint32_t n=0); + int use_new_fade_source (uint32_t n=0); + + int find_and_use_playlist (const string&); + + void allocate_temporary_buffers (); + + unsigned char _flags; + + int create_input_port (); + int connect_input_port (); + int seek_unlocked (jack_nframes_t which_sample); + + int ports_created (); + + bool realtime_set_speed (float, bool global_change); + void non_realtime_set_speed (); + + std::list<Region*> _last_capture_regions; + std::vector<FileSource*> capturing_sources; + int use_pending_capture_data (XMLNode& node); + + void get_input_sources (); + + void check_record_status (jack_nframes_t transport_frame, jack_nframes_t nframes, bool can_record); + + void set_align_style_from_io(); + +}; + +}; /* namespace ARDOUR */ + +#endif /* __ardour_diskstream_h__ */ diff --git a/libs/ardour/ardour/export.h b/libs/ardour/ardour/export.h new file mode 100644 index 0000000000..9a6da1592b --- /dev/null +++ b/libs/ardour/ardour/export.h @@ -0,0 +1,88 @@ +#ifndef __ardour_export_h__ +#define __ardour_export_h__ + +#include <map> +#include <vector> +#include <string> + +#include <sigc++/signal.h> + +#include <sndfile.h> +#include <samplerate.h> + +#include <ardour/ardour.h> +#include <ardour/gdither.h> + +using std::map; +using std::vector; +using std::string; +using std::pair; + +namespace ARDOUR +{ + class Port; + + typedef pair<Port *, uint32_t> PortChannelPair; + typedef map<uint32_t, vector<PortChannelPair> > AudioExportPortMap; + + struct AudioExportSpecification : public SF_INFO, public sigc::trackable { + + AudioExportSpecification(); + ~AudioExportSpecification (); + + void init (); + void clear (); + + + int prepare (jack_nframes_t blocksize, jack_nframes_t frame_rate); + + int process (jack_nframes_t nframes); + + /* set by the user */ + + string path; + jack_nframes_t sample_rate; + + int src_quality; + SNDFILE* out; + uint32_t channels; + AudioExportPortMap port_map; + jack_nframes_t start_frame; + jack_nframes_t end_frame; + GDitherType dither_type; + bool do_freewheel; + + /* used exclusively during export */ + + jack_nframes_t frame_rate; + GDither dither; + float* dataF; + float* dataF2; + float* leftoverF; + jack_nframes_t leftover_frames; + jack_nframes_t max_leftover_frames; + void* output_data; + jack_nframes_t out_samples_max; + uint32_t sample_bytes; + uint32_t data_width; + + jack_nframes_t total_frames; + SF_INFO sfinfo; + SRC_DATA src_data; + SRC_STATE* src_state; + jack_nframes_t pos; + + sigc::connection freewheel_connection; + + /* shared between UI thread and audio thread */ + + float progress; /* audio thread sets this */ + bool stop; /* UI sets this */ + bool running; /* audio thread sets to false when export is done */ + + int status; + + }; +}; + +#endif /* __ardour_export_h__ */ diff --git a/libs/ardour/ardour/filesource.h b/libs/ardour/ardour/filesource.h new file mode 100644 index 0000000000..2c24d87793 --- /dev/null +++ b/libs/ardour/ardour/filesource.h @@ -0,0 +1,163 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __playlist_file_buffer_h__ +#define __playlist_file_buffer_h__ + +// darwin supports 64 by default and doesn't provide wrapper functions. +#if defined (__APPLE__) +typedef off_t off64_t; +#define open64 open +#define close64 close +#define lseek64 lseek +#define pread64 pread +#define pwrite64 pwrite +#endif + +#include <vector> +#include <string> + +#include <ardour/source.h> + +struct tm; + +using std::string; + +namespace ARDOUR { + +class FileSource : public Source { + public: + FileSource (string path, jack_nframes_t rate, bool repair_first = false); + FileSource (const XMLNode&, jack_nframes_t rate); + ~FileSource (); + + jack_nframes_t length() const { return _length; } + jack_nframes_t read (Sample *dst, jack_nframes_t start, jack_nframes_t cnt) const; + jack_nframes_t write (Sample *src, jack_nframes_t cnt); + void mark_for_remove(); + string peak_path(string audio_path); + string old_peak_path(string audio_path); + string path() const { return _path; } + + int update_header (jack_nframes_t when, struct tm&, time_t); + + int move_to_trash (const string trash_dir_name); + + static bool is_empty (string path); + void mark_streaming_write_completed (); + + void mark_take (string); + string take_id() const { return _take_id; } + + static void set_bwf_country_code (string x); + static void set_bwf_organization_code (string x); + static void set_bwf_serial_number (int); + + static void set_search_path (string); + + private: + int fd; + string _path; + bool remove_at_unref; + bool is_bwf; + off64_t data_offset; + string _take_id; + + static char bwf_country_code[3]; + static char bwf_organization_code[4]; + static char bwf_serial_number[13]; + + struct GenericChunk { + char id[4]; + int32_t size; + }; + + struct WAVEChunk : public GenericChunk { + char text[4]; /* wave pseudo-chunk id "WAVE" */ + }; + + struct FMTChunk : public GenericChunk { + int16_t formatTag; /* format tag; currently pcm */ + int16_t nChannels; /* number of channels */ + uint32_t nSamplesPerSec; /* sample rate in hz */ + int32_t nAvgBytesPerSec; /* average bytes per second */ + int16_t nBlockAlign; /* number of bytes per sample */ + int16_t nBitsPerSample; /* number of bits in a sample */ + }; + + struct BroadcastChunk : public GenericChunk { + char description[256]; + char originator[32]; + char originator_reference[32]; + char origination_date[10]; + char origination_time[8]; + int32_t time_reference_low; + int32_t time_reference_high; + int16_t version; /* 1.0 because we have umid and 190 bytes of "reserved" */ + char umid[64]; + char reserved[190]; + /* we don't treat coding history as part of the struct */ + }; + + struct ChunkInfo { + string name; + uint32_t size; + off64_t offset; + + ChunkInfo (string s, uint32_t sz, off64_t o) + : name (s), size (sz), offset (o) {} + }; + + vector<ChunkInfo> chunk_info; + + struct { + WAVEChunk wave; + FMTChunk format; + GenericChunk data; + BroadcastChunk bext; + vector<string> coding_history; + } header; + + int init (string, bool must_exist, jack_nframes_t); + jack_nframes_t read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_t cnt) const; + + int discover_chunks (bool silent); + ChunkInfo* lookup_chunk (string name); + + int write_header (); + int read_header (bool silent); + + int check_header (jack_nframes_t rate, bool silent); + int fill_header (jack_nframes_t rate); + + int read_broadcast_data (ChunkInfo&); + void compute_header_size (); + + static const int32_t wave_header_size = sizeof (WAVEChunk) + sizeof (FMTChunk) + sizeof (GenericChunk); + static const int32_t bwf_header_size = wave_header_size + sizeof (BroadcastChunk); + + static string search_path; + + int repair (string, jack_nframes_t); +}; + +} + +#endif /* __playlist_file_buffer_h__ */ diff --git a/libs/ardour/ardour/gain.h b/libs/ardour/ardour/gain.h new file mode 100644 index 0000000000..3bd2d3be61 --- /dev/null +++ b/libs/ardour/ardour/gain.h @@ -0,0 +1,44 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_gain_h__ +#define __ardour_gain_h__ + +#include "ardour.h" +#include "curve.h" + +namespace ARDOUR { + +struct Gain : public Curve { + + Gain(); + Gain (const Gain&); + Gain& operator= (const Gain&); + + static void fill_linear_fade_in (Gain& curve, jack_nframes_t frames); + static void fill_linear_volume_fade_in (Gain& curve, jack_nframes_t frames); + static void fill_linear_fade_out (Gain& curve, jack_nframes_t frames); + static void fill_linear_volume_fade_out (Gain& curve, jack_nframes_t frames); + +}; + +} /* namespace ARDOUR */ + +#endif /* __ardour_gain_h__ */ diff --git a/libs/ardour/ardour/gdither.h b/libs/ardour/ardour/gdither.h new file mode 100644 index 0000000000..51343b13c4 --- /dev/null +++ b/libs/ardour/ardour/gdither.h @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2002 Steve Harris <steve@plugin.org.uk> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id$ + */ + +#ifndef GDITHER_H +#define GDITHER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "gdither_types.h" + +/* Create and initialise a state structure, takes a dither type, a number of + * channels and a bit depth as input + * + * The Dither type is one of + * + * GDitherNone - straight nearest neighbour rounding. Theres no pressing + * reason to do this at 8 or 16 bit, but you might want to at 24, for some + * reason. At the lest it will save you writing int->float conversion code, + * which is arder than it sounds. + * + * GDitherRect - mathematically most accurate, lowest noise floor, but not + * that good for audio. It is the fastest though. + * + * GDitherTri - a happy medium between Rectangular and Shaped, reasonable + * noise floor, not too obvious, quite fast. + * + * GDitherShaped - should have the least audible impact, but has the highest + * noise floor, fairly CPU intensive. Not advisible if your going to apply + * any frequency manipulation afterwards. + * + * channels, sets the number of channels in the output data, output data will + * be written interleaved into the area given to gdither_run(). Set to 1 + * if you are not working with interleaved buffers. + * + * bit depth, sets the bit width of the output sample data, it can be one of: + * + * GDither8bit - 8 bit unsiged + * GDither16bit - 16 bit signed + * GDither32bit - 24+bits in upper bits of a 32 bit word + * GDitherFloat - IEEE floating point (32bits) + * GDitherDouble - Double precision IEEE floating point (64bits) + * + * dither_depth, set the number of bits before the signal will be truncated to, + * eg. 16 will produce an output stream with 16bits-worth of signal. Setting to + * zero or greater than the width of the output format will dither to the + * maximum precision allowed by the output format. + */ +GDither gdither_new(GDitherType type, uint32_t channels, + + GDitherSize bit_depth, int dither_depth); + +/* Frees memory used by gdither_new. + */ +void gdither_free(GDither s); + +/* Applies dithering to the supplied signal. + * + * channel is the channel number you are processing (0 - channles-1), length is + * the length of the input, in samples, x is the input samples (float), y is + * where the output samples will be written, it should have the approaprate + * type for the chosen bit depth + */ +void gdither_runf(GDither s, uint32_t channel, uint32_t length, + float *x, void *y); + +/* see gdither_runf, vut input argument is double format */ +void gdither_run(GDither s, uint32_t channel, uint32_t length, + double *x, void *y); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libs/ardour/ardour/gdither_types.h b/libs/ardour/ardour/gdither_types.h new file mode 100644 index 0000000000..46feb55fbc --- /dev/null +++ b/libs/ardour/ardour/gdither_types.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2002 Steve Harris <steve@plugin.org.uk> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id$ + */ + +#ifndef GDITHER_TYPES_H +#define GDITHER_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + GDitherNone = 0, + GDitherRect, + GDitherTri, + GDitherShaped +} GDitherType; + +typedef enum { + GDither8bit = 8, + GDither16bit = 16, + GDither32bit = 32, + GDitherFloat = 25, + GDitherDouble = 54 +} GDitherSize; + +typedef void *GDither; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libs/ardour/ardour/gdither_types_internal.h b/libs/ardour/ardour/gdither_types_internal.h new file mode 100644 index 0000000000..55d5792833 --- /dev/null +++ b/libs/ardour/ardour/gdither_types_internal.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2002 Steve Harris <steve@plugin.org.uk> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id$ + */ + +#ifndef GDITHER_TYPES_H +#define GDITHER_TYPES_H + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define GDITHER_SH_BUF_SIZE 8 +#define GDITHER_SH_BUF_MASK 7 + +/* this must agree with whats in gdither_types.h */ +typedef enum { + GDitherNone = 0, + GDitherRect, + GDitherTri, + GDitherShaped +} GDitherType; + +typedef enum { + GDither8bit = 8, + GDither16bit = 16, + GDither32bit = 32, + GDitherFloat = 25, + GDitherDouble = 54 +} GDitherSize; + +typedef struct { + uint32_t phase; + float buffer[GDITHER_SH_BUF_SIZE]; +} GDitherShapedState; + +typedef struct GDither_s { + GDitherType type; + uint32_t channels; + uint32_t bit_depth; + uint32_t dither_depth; + float scale; + uint32_t post_scale; + float post_scale_fp; + float bias; + + int clamp_u; + + int clamp_l; + float *tri_state; + GDitherShapedState *shaped_state; +} *GDither; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libs/ardour/ardour/history.h b/libs/ardour/ardour/history.h new file mode 100644 index 0000000000..91a89d5ac2 --- /dev/null +++ b/libs/ardour/ardour/history.h @@ -0,0 +1,153 @@ +/* + Copyright (C) 2001 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_history_h__ +#define __ardour_history_h__ + +#include <list> +#include <sigc++/signal.h> + +template<class T> +//struct History : public SigC::Object +struct History : public sigc::trackable +{ + typedef list<T *> StateList; + + StateList states; + StateList::iterator current; + + History() { current = states.end(); } + ~History() { states.erase (states.begin(), states.end()); } + + sigc::signal<void> CurrentChanged; + + void clear () { + for (StateList::iterator i = states.begin(); i != states.end(); i++) { + delete *i; + } + states.clear (); + current = states.end(); + CurrentChanged(); + } + + void push (T *state) { + /* remove any "undone" history above the current location + in the history, before pushing new state. + */ + if (current != states.begin() && current != states.end()) { + states.erase (states.begin(), current); + } + current = states.insert (states.begin(), state); + CurrentChanged (); + } + + T *top() { + if (current != states.end()) { + return *current; + } else { + return 0; + } + } + + T *pop (bool remove) { + if (current == states.end()) { + return 0; + } + + if (current == states.begin()) { + return *current; + } + + current--; + T *state = *current; + + if (remove) { + states.erase (current); + } + + CurrentChanged (); + return state; + } + + T *earlier (uint32_t n) { + StateList::iterator i; + + if (current == states.end()) { + return 0; + } + + if (n == 0) { + return *current; + } + + /* the list is in LIFO order, so move toward the end to go "earlier" */ + + for (i = current; n && i != states.end(); i++, n--); + + if (i == states.end()) { + return 0; + } else { + current = i; + CurrentChanged (); + return *i; + } + } + + T *later (uint32_t n) { + StateList::iterator i; + + if (current == states.end()) { + return 0; + } + + if (n == 0) { + return *current; + } + + /* the list is in LIFO order, so move toward the beginning to go "later" */ + + for (i = current; n && i != states.begin(); i--, n--); + if (i != current) { + current = i; + CurrentChanged(); + } + return *i; + } + + T *nth (uint32_t n) { + StateList::iterator i; + + for (i = states.begin(); n && i != states.end(); n--, i++); + + if (i != states.end()) { + if (i != current) { + current = i; + CurrentChanged (); + } + return *i; + } else { + return 0; + } + } + +}; + +#endif /* __ardour_history_h__ */ + diff --git a/libs/ardour/ardour/insert.h b/libs/ardour/ardour/insert.h new file mode 100644 index 0000000000..803e16497d --- /dev/null +++ b/libs/ardour/ardour/insert.h @@ -0,0 +1,183 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_insert_h__ +#define __ardour_insert_h__ + +#include <vector> +#include <string> +#include <exception> + +#include <sigc++/signal.h> +#include <ardour/ardour.h> +#include <ardour/redirect.h> +#include <ardour/plugin_state.h> + +class XMLNode; + +namespace MIDI { + class Port; +} + +namespace ARDOUR { + +class Session; +class Plugin; +class Route; + +class Insert : public Redirect +{ + public: + Insert(Session& s, Placement p); + Insert(Session& s, string name, Placement p); + + Insert(Session& s, Placement p, int imin, int imax, int omin, int omax); + + virtual ~Insert() { } + + virtual void run (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset) = 0; + virtual void activate () {} + virtual void deactivate () {} + + virtual int32_t can_support_input_configuration (int32_t in) const = 0; + virtual int32_t configure_io (int32_t magic, int32_t in, int32_t out) = 0; + virtual int32_t compute_output_streams (int32_t cnt) const = 0; +}; + +class PortInsert : public Insert +{ + public: + PortInsert (Session&, Placement); + PortInsert (Session&, const XMLNode&); + PortInsert (const PortInsert&); + ~PortInsert (); + + XMLNode& state(bool full); + XMLNode& get_state(void); + int set_state(const XMLNode&); + + void init (); + void run (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset); + + jack_nframes_t latency(); + + uint32_t output_streams() const; + uint32_t input_streams() const; + + int32_t can_support_input_configuration (int32_t) const; + int32_t configure_io (int32_t magic, int32_t in, int32_t out); + int32_t compute_output_streams (int32_t cnt) const; +}; + +struct PluginInsertState : public RedirectState +{ + PluginInsertState (std::string why) + : RedirectState (why) {} + ~PluginInsertState() {} + + PluginState plugin_state; +}; + +class PluginInsert : public Insert +{ + public: + PluginInsert (Session&, Plugin&, Placement); + PluginInsert (Session&, const XMLNode&); + PluginInsert (const PluginInsert&); + ~PluginInsert (); + + static const string port_automation_node_name; + + XMLNode& state(bool); + XMLNode& get_state(void); + int set_state(const XMLNode&); + + StateManager::State* state_factory (std::string why) const; + Change restore_state (StateManager::State&); + + void run (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset); + void silence (jack_nframes_t nframes, jack_nframes_t offset); + void activate (); + void deactivate (); + + void set_block_size (jack_nframes_t nframes); + + uint32_t output_streams() const; + uint32_t input_streams() const; + uint32_t natural_output_streams() const; + uint32_t natural_input_streams() const; + + int set_count (uint32_t num); + uint32_t get_count () const { return _plugins.size(); } + + int32_t can_support_input_configuration (int32_t) const; + int32_t configure_io (int32_t magic, int32_t in, int32_t out); + int32_t compute_output_streams (int32_t cnt) const; + + bool is_generator() const; + + void reset_midi_control (MIDI::Port*, bool); + void send_all_midi_feedback (); + + void set_parameter (uint32_t port, float val); + + AutoState get_port_automation_state (uint32_t port); + void set_port_automation_state (uint32_t port, AutoState); + void protect_automation (); + + float default_parameter_value (uint32_t which); + + Plugin& plugin(uint32_t num=0) const { + if (num < _plugins.size()) { + return *_plugins[num]; + } else { + return *_plugins[0]; // we always have one + } + } + + string describe_parameter (uint32_t); + + jack_nframes_t latency(); + + void transport_stopped (jack_nframes_t now); + void automation_snapshot (jack_nframes_t now); + + protected: + void store_state (PluginInsertState&) const; + + private: + + void parameter_changed (uint32_t, float); + + vector<Plugin*> _plugins; + void automation_run (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset); + void connect_and_run (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset, bool with_auto, jack_nframes_t now = 0); + + void init (); + void set_automatable (); + void auto_state_changed (uint32_t which); + void automation_list_creation_callback (uint32_t, AutomationList&); + + Plugin* plugin_factory (Plugin&); +}; + +}; /* namespace ARDOUR */ + +#endif /* __ardour_insert_h__ */ diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h new file mode 100644 index 0000000000..c67473dcc0 --- /dev/null +++ b/libs/ardour/ardour/io.h @@ -0,0 +1,408 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_io_h__ +#define __ardour_io_h__ + +#include <string> +#include <vector> +#include <cmath> +#include <sigc++/signal.h> +#include <jack/jack.h> + +#include <pbd/lockmonitor.h> +#include <pbd/fastlog.h> +#include <pbd/undo.h> +#include <pbd/atomic.h> +#include <midi++/controllable.h> + +#include <ardour/ardour.h> +#include <ardour/stateful.h> +#include <ardour/utils.h> +#include <ardour/state_manager.h> +#include <ardour/curve.h> + +using std::string; +using std::vector; + +class XMLNode; + +namespace ARDOUR { + +class Session; +class AudioEngine; +class Port; +class Connection; +class Panner; + +class IO : public Stateful, public ARDOUR::StateManager +{ + + public: + static const string state_node_name; + + IO (Session&, string name, + int input_min = -1, int input_max = -1, + int output_min = -1, int output_max = -1); + + virtual ~IO(); + + int input_minimum() const { return _input_minimum; } + int input_maximum() const { return _input_maximum; } + int output_minimum() const { return _output_minimum; } + int output_maximum() const { return _output_maximum; } + + void set_input_minimum (int n); + void set_input_maximum (int n); + void set_output_minimum (int n); + void set_output_maximum (int n); + + const string& name() const { return _name; } + virtual int set_name (string str, void *src); + + virtual void silence (jack_nframes_t, jack_nframes_t offset); + + void pan (vector<Sample*>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset, gain_t gain_coeff); + void pan_automated (vector<Sample*>& bufs, uint32_t nbufs, jack_nframes_t start_frame, jack_nframes_t end_frame, + jack_nframes_t nframes, jack_nframes_t offset); + void collect_input (vector<Sample*>&, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset); + void deliver_output (vector<Sample *>&, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset); + void deliver_output_no_pan (vector<Sample *>&, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset); + void just_meter_input (jack_nframes_t start_frame, jack_nframes_t end_frame, + jack_nframes_t nframes, jack_nframes_t offset); + + virtual uint32_t n_process_buffers () { return 0; } + + virtual void set_gain (gain_t g, void *src); + void inc_gain (gain_t delta, void *src); + gain_t gain () const { return _desired_gain; } + virtual gain_t effective_gain () const; + + Panner& panner() { return *_panner; } + + int ensure_io (uint32_t, uint32_t, bool clear, void *src); + + int use_input_connection (Connection&, void *src); + int use_output_connection (Connection&, void *src); + + Connection *input_connection() const { return _input_connection; } + Connection *output_connection() const { return _output_connection; } + + int add_input_port (string source, void *src); + int add_output_port (string destination, void *src); + + int remove_input_port (Port *, void *src); + int remove_output_port (Port *, void *src); + + int set_input (Port *, void *src); + + int connect_input (Port *our_port, string other_port, void *src); + int connect_output (Port *our_port, string other_port, void *src); + + int disconnect_input (Port *our_port, string other_port, void *src); + int disconnect_output (Port *our_port, string other_port, void *src); + + int disconnect_inputs (void *src); + int disconnect_outputs (void *src); + + jack_nframes_t output_latency() const; + jack_nframes_t input_latency() const; + void set_port_latency (jack_nframes_t); + + Port *output (uint32_t n) const { + if (n < _noutputs) { + return _outputs[n]; + } else { + return 0; + } + } + + Port *input (uint32_t n) const { + if (n < _ninputs) { + return _inputs[n]; + } else { + return 0; + } + } + + uint32_t n_inputs () const { return _ninputs; } + uint32_t n_outputs () const { return _noutputs; } + + sigc::signal<void,IOChange,void*> input_changed; + sigc::signal<void,IOChange,void*> output_changed; + + sigc::signal<void,void*> gain_changed; + sigc::signal<void,void*> name_changed; + + virtual XMLNode& state (bool full); + XMLNode& get_state (void); + int set_state (const XMLNode&); + + virtual UndoAction get_memento() const; + + + static int disable_connecting (void); + + static int enable_connecting (void); + + static int disable_ports (void); + + static int enable_ports (void); + + static int disable_panners (void); + + static int reset_panners (void); + + static sigc::signal<int> PortsLegal; + static sigc::signal<int> PannersLegal; + static sigc::signal<int> ConnectingLegal; + static sigc::signal<void,uint32_t> MoreOutputs; + static sigc::signal<int> PortsCreated; + + /* MIDI control */ + + void set_midi_to_gain_function (gain_t (*function)(double val)) { + _midi_gain_control.midi_to_gain = function; + } + + void set_gain_to_midi_function (double (*function)(gain_t gain)) { + _midi_gain_control.gain_to_midi = function; + } + + MIDI::Controllable& midi_gain_control() { + return _midi_gain_control; + } + + virtual void reset_midi_control (MIDI::Port*, bool on); + + virtual void send_all_midi_feedback (); + virtual MIDI::byte* write_midi_feedback (MIDI::byte*, int32_t& bufsize); + + /* Peak metering */ + + float peak_input_power (uint32_t n) { + if (n < std::max(_ninputs, _noutputs)) { + float x = _stored_peak_power[n]; + if(x > 0.0) { + return 20 * fast_log10(x); + } else { + return minus_infinity(); + } + } else { + return minus_infinity(); + } + } + + static sigc::signal<void> GrabPeakPower; + + /* automation */ + + void clear_automation (); + + bool gain_automation_recording() const { + return (_gain_automation_curve.automation_state() & (Write|Touch)); + } + + bool gain_automation_playback() const { + return (_gain_automation_curve.automation_state() & Play) || + ((_gain_automation_curve.automation_state() & Touch) && + !_gain_automation_curve.touching()); + } + + virtual void set_gain_automation_state (AutoState); + AutoState gain_automation_state() const { return _gain_automation_curve.automation_state(); } + sigc::signal<void> gain_automation_state_changed; + + virtual void set_gain_automation_style (AutoStyle); + AutoStyle gain_automation_style () const { return _gain_automation_curve.automation_style(); } + sigc::signal<void> gain_automation_style_changed; + + static void set_automation_interval (jack_nframes_t frames) { + _automation_interval = frames; + } + + static jack_nframes_t automation_interval() { + return _automation_interval; + } + + virtual void transport_stopped (jack_nframes_t now); + virtual void automation_snapshot (jack_nframes_t now); + + ARDOUR::Curve& gain_automation_curve () { return _gain_automation_curve; } + + void start_gain_touch (); + void end_gain_touch (); + + void start_pan_touch (uint32_t which); + void end_pan_touch (uint32_t which); + + id_t id() const { return _id; } + + void defer_pan_reset (); + void allow_pan_reset (); + + /* the session calls this for master outs before + anyone else. controls outs too, at some point. + */ + + XMLNode *pending_state_node; + int ports_became_legal (); + + private: + mutable PBD::Lock io_lock; + + protected: + Session& _session; + Panner* _panner; + gain_t _gain; + gain_t _effective_gain; + gain_t _desired_gain; + PBD::NonBlockingLock declick_lock; + vector<Port*> _outputs; + vector<Port*> _inputs; + vector<float> _peak_power; + vector<float> _stored_peak_power; + string _name; + Connection* _input_connection; + Connection* _output_connection; + id_t _id; + bool no_panner_reset; + XMLNode* deferred_state; + + virtual void set_deferred_state() {} + + void reset_peak_meters(); + void reset_panner (); + + virtual uint32_t pans_required() const { return _ninputs; } + + static void apply_declick (vector<Sample*>&, uint32_t nbufs, jack_nframes_t nframes, + gain_t initial, gain_t target, bool invert_polarity); + + struct MIDIGainControl : public MIDI::Controllable { + MIDIGainControl (IO&, MIDI::Port *); + void set_value (float); + + void send_feedback (gain_t); + MIDI::byte* write_feedback (MIDI::byte* buf, int32_t& bufsize, gain_t val, bool force = false); + + IO& io; + bool setting; + MIDI::byte last_written; + + gain_t (*midi_to_gain) (double val); + double (*gain_to_midi) (gain_t gain); + }; + + MIDIGainControl _midi_gain_control; + + /* state management */ + + Change restore_state (State&); + StateManager::State* state_factory (std::string why) const; + void send_state_changed(); + + bool get_midi_node_info (XMLNode * node, MIDI::eventType & ev, MIDI::channel_t & chan, MIDI::byte & additional); + bool set_midi_node_info (XMLNode * node, MIDI::eventType ev, MIDI::channel_t chan, MIDI::byte additional); + + /* automation */ + + jack_nframes_t last_automation_snapshot; + static jack_nframes_t _automation_interval; + + AutoState _gain_automation_state; + AutoStyle _gain_automation_style; + + bool apply_gain_automation; + Curve _gain_automation_curve; + + int save_automation (const string&); + int load_automation (const string&); + + PBD::NonBlockingLock automation_lock; + + /* AudioTrack::deprecated_use_diskstream_connections() needs these */ + + int set_inputs (const string& str); + int set_outputs (const string& str); + + static bool connecting_legal; + static bool ports_legal; + + private: + + uint32_t _ninputs; + uint32_t _noutputs; + + /* are these the best variable names ever, or what? */ + + sigc::connection input_connection_configuration_connection; + sigc::connection output_connection_configuration_connection; + sigc::connection input_connection_connection_connection; + sigc::connection output_connection_connection_connection; + + static bool panners_legal; + + int connecting_became_legal (); + int panners_became_legal (); + sigc::connection connection_legal_c; + sigc::connection port_legal_c; + sigc::connection panner_legal_c; + + int _input_minimum; + int _input_maximum; + int _output_minimum; + int _output_maximum; + + + static int parse_io_string (const string&, vector<string>& chns); + + static int parse_gain_string (const string&, vector<string>& chns); + + int set_sources (vector<string>&, void *src, bool add); + int set_destinations (vector<string>&, void *src, bool add); + + int ensure_inputs (uint32_t, bool clear, bool lockit, void *src); + int ensure_outputs (uint32_t, bool clear, bool lockit, void *src); + + void drop_input_connection (); + void drop_output_connection (); + + void input_connection_configuration_changed (); + void input_connection_connection_changed (int); + void output_connection_configuration_changed (); + void output_connection_connection_changed (int); + + int create_ports (const XMLNode&); + int make_connections (const XMLNode&); + + void setup_peak_meters (); + void grab_peak_power (); + + bool ensure_inputs_locked (uint32_t, bool clear, void *src); + bool ensure_outputs_locked (uint32_t, bool clear, void *src); + + int32_t find_input_port_hole (); + int32_t find_output_port_hole (); +}; + +}; /* namespace ARDOUR */ + +#endif /*__ardour_io_h__ */ diff --git a/libs/ardour/ardour/ladspa.h b/libs/ardour/ardour/ladspa.h new file mode 100644 index 0000000000..e552f35bb5 --- /dev/null +++ b/libs/ardour/ardour/ladspa.h @@ -0,0 +1,606 @@ +/* ladspa.h + + Linux Audio Developer's Simple Plugin API Version 1.1[LGPL]. + Copyright (C) 2000-2002 Richard W.E. Furse, Paul Barton-Davis, + Stefan Westerfeld. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. */ + +#ifndef LADSPA_INCLUDED +#define LADSPA_INCLUDED + +#define LADSPA_VERSION "1.1" +#define LADSPA_VERSION_MAJOR 1 +#define LADSPA_VERSION_MINOR 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/*****************************************************************************/ + +/* Overview: + + There is a large number of synthesis packages in use or development + on the Linux platform at this time. This API (`The Linux Audio + Developer's Simple Plugin API') attempts to give programmers the + ability to write simple `plugin' audio processors in C/C++ and link + them dynamically (`plug') into a range of these packages (`hosts'). + It should be possible for any host and any plugin to communicate + completely through this interface. + + This API is deliberately short and simple. To achieve compatibility + with a range of promising Linux sound synthesis packages it + attempts to find the `greatest common divisor' in their logical + behaviour. Having said this, certain limiting decisions are + implicit, notably the use of a fixed type (LADSPA_Data) for all + data transfer and absence of a parameterised `initialisation' + phase. See below for the LADSPA_Data typedef. + + Plugins are expected to distinguish between control and audio + data. Plugins have `ports' that are inputs or outputs for audio or + control data and each plugin is `run' for a `block' corresponding + to a short time interval measured in samples. Audio data is + communicated using arrays of LADSPA_Data, allowing a block of audio + to be processed by the plugin in a single pass. Control data is + communicated using single LADSPA_Data values. Control data has a + single value at the start of a call to the `run()' or `run_adding()' + function, and may be considered to remain this value for its + duration. The plugin may assume that all its input and output ports + have been connected to the relevant data location (see the + `connect_port()' function below) before it is asked to run. + + Plugins will reside in shared object files suitable for dynamic + linking by dlopen() and family. The file will provide a number of + `plugin types' that can be used to instantiate actual plugins + (sometimes known as `plugin instances') that can be connected + together to perform tasks. + + This API contains very limited error-handling. */ + +/*****************************************************************************/ + +/* Fundamental data type passed in and out of plugin. This data type + is used to communicate audio samples and control values. It is + assumed that the plugin will work sensibly given any numeric input + value although it may have a preferred range (see hints below). + + For audio it is generally assumed that 1.0f is the `0dB' reference + amplitude and is a `normal' signal level. */ + +typedef float LADSPA_Data; + +/*****************************************************************************/ + +/* Special Plugin Properties: + + Optional features of the plugin type are encapsulated in the + LADSPA_Properties type. This is assembled by ORing individual + properties together. */ + + +typedef int LADSPA_Properties; + +/* Property LADSPA_PROPERTY_REALTIME indicates that the plugin has a + real-time dependency (e.g. listens to a MIDI device) and so its + output must not be cached or subject to significant latency. */ +#define LADSPA_PROPERTY_REALTIME 0x1 + +/* Property LADSPA_PROPERTY_INPLACE_BROKEN indicates that the plugin + may cease to work correctly if the host elects to use the same data + location for both input and output (see connect_port()). This + should be avoided as enabling this flag makes it impossible for + hosts to use the plugin to process audio `in-place.' */ +#define LADSPA_PROPERTY_INPLACE_BROKEN 0x2 + +/* Property LADSPA_PROPERTY_HARD_RT_CAPABLE indicates that the plugin + is capable of running not only in a conventional host but also in a + `hard real-time' environment. To qualify for this the plugin must + satisfy all of the following: + + (1) The plugin must not use malloc(), free() or other heap memory + management within its run() or run_adding() functions. All new + memory used in run() must be managed via the stack. These + restrictions only apply to the run() function. + + (2) The plugin will not attempt to make use of any library + functions with the exceptions of functions in the ANSI standard C + and C maths libraries, which the host is expected to provide. + + (3) The plugin will not access files, devices, pipes, sockets, IPC + or any other mechanism that might result in process or thread + blocking. + + (4) The plugin will take an amount of time to execute a run() or + run_adding() call approximately of form (A+B*SampleCount) where A + and B depend on the machine and host in use. This amount of time + may not depend on input signals or plugin state. The host is left + the responsibility to perform timings to estimate upper bounds for + A and B. */ +#define LADSPA_PROPERTY_HARD_RT_CAPABLE 0x4 + +#define LADSPA_IS_REALTIME(x) ((x) & LADSPA_PROPERTY_REALTIME) +#define LADSPA_IS_INPLACE_BROKEN(x) ((x) & LADSPA_PROPERTY_INPLACE_BROKEN) +#define LADSPA_IS_HARD_RT_CAPABLE(x) ((x) & LADSPA_PROPERTY_HARD_RT_CAPABLE) + +/*****************************************************************************/ + +/* Plugin Ports: + + Plugins have `ports' that are inputs or outputs for audio or + data. Ports can communicate arrays of LADSPA_Data (for audio + inputs/outputs) or single LADSPA_Data values (for control + input/outputs). This information is encapsulated in the + LADSPA_PortDescriptor type which is assembled by ORing individual + properties together. + + Note that a port must be an input or an output port but not both + and that a port must be a control or audio port but not both. */ + + +typedef int LADSPA_PortDescriptor; + +/* Property LADSPA_PORT_INPUT indicates that the port is an input. */ +#define LADSPA_PORT_INPUT 0x1 + +/* Property LADSPA_PORT_OUTPUT indicates that the port is an output. */ +#define LADSPA_PORT_OUTPUT 0x2 + +/* Property LADSPA_PORT_CONTROL indicates that the port is a control + port. */ +#define LADSPA_PORT_CONTROL 0x4 + +/* Property LADSPA_PORT_AUDIO indicates that the port is a audio + port. */ +#define LADSPA_PORT_AUDIO 0x8 + +#define LADSPA_IS_PORT_INPUT(x) ((x) & LADSPA_PORT_INPUT) +#define LADSPA_IS_PORT_OUTPUT(x) ((x) & LADSPA_PORT_OUTPUT) +#define LADSPA_IS_PORT_CONTROL(x) ((x) & LADSPA_PORT_CONTROL) +#define LADSPA_IS_PORT_AUDIO(x) ((x) & LADSPA_PORT_AUDIO) + +/*****************************************************************************/ + +/* Plugin Port Range Hints: + + The host may wish to provide a representation of data entering or + leaving a plugin (e.g. to generate a GUI automatically). To make + this more meaningful, the plugin should provide `hints' to the host + describing the usual values taken by the data. + + Note that these are only hints. The host may ignore them and the + plugin must not assume that data supplied to it is meaningful. If + the plugin receives invalid input data it is expected to continue + to run without failure and, where possible, produce a sensible + output (e.g. a high-pass filter given a negative cutoff frequency + might switch to an all-pass mode). + + Hints are meaningful for all input and output ports but hints for + input control ports are expected to be particularly useful. + + More hint information is encapsulated in the + LADSPA_PortRangeHintDescriptor type which is assembled by ORing + individual hint types together. Hints may require further + LowerBound and UpperBound information. + + All the hint information for a particular port is aggregated in the + LADSPA_PortRangeHint structure. */ + + +typedef int LADSPA_PortRangeHintDescriptor; + +/* Hint LADSPA_HINT_BOUNDED_BELOW indicates that the LowerBound field + of the LADSPA_PortRangeHint should be considered meaningful. The + value in this field should be considered the (inclusive) lower + bound of the valid range. If LADSPA_HINT_SAMPLE_RATE is also + specified then the value of LowerBound should be multiplied by the + sample rate. */ +#define LADSPA_HINT_BOUNDED_BELOW 0x1 + +/* Hint LADSPA_HINT_BOUNDED_ABOVE indicates that the UpperBound field + of the LADSPA_PortRangeHint should be considered meaningful. The + value in this field should be considered the (inclusive) upper + bound of the valid range. If LADSPA_HINT_SAMPLE_RATE is also + specified then the value of UpperBound should be multiplied by the + sample rate. */ +#define LADSPA_HINT_BOUNDED_ABOVE 0x2 + +/* Hint LADSPA_HINT_TOGGLED indicates that the data item should be + considered a Boolean toggle. Data less than or equal to zero should + be considered `off' or `false,' and data above zero should be + considered `on' or `true.' LADSPA_HINT_TOGGLED may not be used in + conjunction with any other hint except LADSPA_HINT_DEFAULT_0 or + LADSPA_HINT_DEFAULT_1. */ +#define LADSPA_HINT_TOGGLED 0x4 + +/* Hint LADSPA_HINT_SAMPLE_RATE indicates that any bounds specified + should be interpreted as multiples of the sample rate. For + instance, a frequency range from 0Hz to the Nyquist frequency (half + the sample rate) could be requested by this hint in conjunction + with LowerBound = 0 and UpperBound = 0.5. Hosts that support bounds + at all must support this hint to retain meaning. */ +#define LADSPA_HINT_SAMPLE_RATE 0x8 + +/* Hint LADSPA_HINT_LOGARITHMIC indicates that it is likely that the + user will find it more intuitive to view values using a logarithmic + scale. This is particularly useful for frequencies and gains. */ +#define LADSPA_HINT_LOGARITHMIC 0x10 + +/* Hint LADSPA_HINT_INTEGER indicates that a user interface would + probably wish to provide a stepped control taking only integer + values. Any bounds set should be slightly wider than the actual + integer range required to avoid floating point rounding errors. For + instance, the integer set {0,1,2,3} might be described as [-0.1, + 3.1]. */ +#define LADSPA_HINT_INTEGER 0x20 + +/* The various LADSPA_HINT_HAS_DEFAULT_* hints indicate a `normal' + value for the port that is sensible as a default. For instance, + this value is suitable for use as an initial value in a user + interface or as a value the host might assign to a control port + when the user has not provided one. Defaults are encoded using a + mask so only one default may be specified for a port. Some of the + hints make use of lower and upper bounds, in which case the + relevant bound or bounds must be available and + LADSPA_HINT_SAMPLE_RATE must be applied as usual. The resulting + default must be rounded if LADSPA_HINT_INTEGER is present. Default + values were introduced in LADSPA v1.1. */ +#define LADSPA_HINT_DEFAULT_MASK 0x3C0 + +/* This default values indicates that no default is provided. */ +#define LADSPA_HINT_DEFAULT_NONE 0x0 + +/* This default hint indicates that the suggested lower bound for the + port should be used. */ +#define LADSPA_HINT_DEFAULT_MINIMUM 0x40 + +/* This default hint indicates that a low value between the suggested + lower and upper bounds should be chosen. For ports with + LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.75 + + log(upper) * 0.25). Otherwise, this should be (lower * 0.75 + upper + * 0.25). */ +#define LADSPA_HINT_DEFAULT_LOW 0x80 + +/* This default hint indicates that a middle value between the + suggested lower and upper bounds should be chosen. For ports with + LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.5 + + log(upper) * 0.5). Otherwise, this should be (lower * 0.5 + upper * + 0.5). */ +#define LADSPA_HINT_DEFAULT_MIDDLE 0xC0 + +/* This default hint indicates that a high value between the suggested + lower and upper bounds should be chosen. For ports with + LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.25 + + log(upper) * 0.75). Otherwise, this should be (lower * 0.25 + upper + * 0.75). */ +#define LADSPA_HINT_DEFAULT_HIGH 0x100 + +/* This default hint indicates that the suggested upper bound for the + port should be used. */ +#define LADSPA_HINT_DEFAULT_MAXIMUM 0x140 + +/* This default hint indicates that the number 0 should be used. Note + that this default may be used in conjunction with + LADSPA_HINT_TOGGLED. */ +#define LADSPA_HINT_DEFAULT_0 0x200 + +/* This default hint indicates that the number 1 should be used. Note + that this default may be used in conjunction with + LADSPA_HINT_TOGGLED. */ +#define LADSPA_HINT_DEFAULT_1 0x240 + +/* This default hint indicates that the number 100 should be used. */ +#define LADSPA_HINT_DEFAULT_100 0x280 + +/* This default hint indicates that the Hz frequency of `concert A' + should be used. This will be 440 unless the host uses an unusual + tuning convention, in which case it may be within a few Hz. */ +#define LADSPA_HINT_DEFAULT_440 0x2C0 + +#define LADSPA_IS_HINT_BOUNDED_BELOW(x) ((x) & LADSPA_HINT_BOUNDED_BELOW) +#define LADSPA_IS_HINT_BOUNDED_ABOVE(x) ((x) & LADSPA_HINT_BOUNDED_ABOVE) +#define LADSPA_IS_HINT_TOGGLED(x) ((x) & LADSPA_HINT_TOGGLED) +#define LADSPA_IS_HINT_SAMPLE_RATE(x) ((x) & LADSPA_HINT_SAMPLE_RATE) +#define LADSPA_IS_HINT_LOGARITHMIC(x) ((x) & LADSPA_HINT_LOGARITHMIC) +#define LADSPA_IS_HINT_INTEGER(x) ((x) & LADSPA_HINT_INTEGER) + +#define LADSPA_IS_HINT_HAS_DEFAULT(x) ((x) & LADSPA_HINT_DEFAULT_MASK) +#define LADSPA_IS_HINT_DEFAULT_MINIMUM(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_MINIMUM) +#define LADSPA_IS_HINT_DEFAULT_LOW(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_LOW) +#define LADSPA_IS_HINT_DEFAULT_MIDDLE(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_MIDDLE) +#define LADSPA_IS_HINT_DEFAULT_HIGH(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_HIGH) +#define LADSPA_IS_HINT_DEFAULT_MAXIMUM(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_MAXIMUM) +#define LADSPA_IS_HINT_DEFAULT_0(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_0) +#define LADSPA_IS_HINT_DEFAULT_1(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_1) +#define LADSPA_IS_HINT_DEFAULT_100(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_100) +#define LADSPA_IS_HINT_DEFAULT_440(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_440) + +typedef struct _LADSPA_PortRangeHint { + + /* Hints about the port. */ + LADSPA_PortRangeHintDescriptor HintDescriptor; + + /* Meaningful when hint LADSPA_HINT_BOUNDED_BELOW is active. When + LADSPA_HINT_SAMPLE_RATE is also active then this value should be + multiplied by the relevant sample rate. */ + LADSPA_Data LowerBound; + + /* Meaningful when hint LADSPA_HINT_BOUNDED_ABOVE is active. When + LADSPA_HINT_SAMPLE_RATE is also active then this value should be + multiplied by the relevant sample rate. */ + LADSPA_Data UpperBound; + +} LADSPA_PortRangeHint; + +/*****************************************************************************/ + +/* Plugin Handles: + + This plugin handle indicates a particular instance of the plugin + concerned. It is valid to compare this to NULL (0 for C++) but + otherwise the host should not attempt to interpret it. The plugin + may use it to reference internal instance data. */ + +typedef void * LADSPA_Handle; + +/*****************************************************************************/ + +/* Descriptor for a Type of Plugin: + + This structure is used to describe a plugin type. It provides a + number of functions to examine the type, instantiate it, link it to + buffers and workspaces and to run it. */ + +typedef struct _LADSPA_Descriptor { + + /* This numeric identifier indicates the plugin type + uniquely. Plugin programmers may reserve ranges of IDs from a + central body to avoid clashes. Hosts may assume that IDs are + below 0x1000000. */ + unsigned long UniqueID; + + /* This identifier can be used as a unique, case-sensitive + identifier for the plugin type within the plugin file. Plugin + types should be identified by file and label rather than by index + or plugin name, which may be changed in new plugin + versions. Labels must not contain white-space characters. */ + const char * Label; + + /* This indicates a number of properties of the plugin. */ + LADSPA_Properties Properties; + + /* This member points to the null-terminated name of the plugin + (e.g. "Sine Oscillator"). */ + const char * Name; + + /* This member points to the null-terminated string indicating the + maker of the plugin. This can be an empty string but not NULL. */ + const char * Maker; + + /* This member points to the null-terminated string indicating any + copyright applying to the plugin. If no Copyright applies the + string "None" should be used. */ + const char * Copyright; + + /* This indicates the number of ports (input AND output) present on + the plugin. */ + unsigned long PortCount; + + /* This member indicates an array of port descriptors. Valid indices + vary from 0 to PortCount-1. */ + const LADSPA_PortDescriptor * PortDescriptors; + + /* This member indicates an array of null-terminated strings + describing ports (e.g. "Frequency (Hz)"). Valid indices vary from + 0 to PortCount-1. */ + const char * const * PortNames; + + /* This member indicates an array of range hints for each port (see + above). Valid indices vary from 0 to PortCount-1. */ + const LADSPA_PortRangeHint * PortRangeHints; + + /* This may be used by the plugin developer to pass any custom + implementation data into an instantiate call. It must not be used + or interpreted by the host. It is expected that most plugin + writers will not use this facility as LADSPA_Handle should be + used to hold instance data. */ + void * ImplementationData; + + /* This member is a function pointer that instantiates a plugin. A + handle is returned indicating the new plugin instance. The + instantiation function accepts a sample rate as a parameter. The + plugin descriptor from which this instantiate function was found + must also be passed. This function must return NULL if + instantiation fails. + + Note that instance initialisation should generally occur in + activate() rather than here. */ + LADSPA_Handle (*instantiate)(const struct _LADSPA_Descriptor * Descriptor, + unsigned long SampleRate); + + /* This member is a function pointer that connects a port on an + instantiated plugin to a memory location at which a block of data + for the port will be read/written. The data location is expected + to be an array of LADSPA_Data for audio ports or a single + LADSPA_Data value for control ports. Memory issues will be + managed by the host. The plugin must read/write the data at these + locations every time run() or run_adding() is called and the data + present at the time of this connection call should not be + considered meaningful. + + connect_port() may be called more than once for a plugin instance + to allow the host to change the buffers that the plugin is + reading or writing. These calls may be made before or after + activate() or deactivate() calls. + + connect_port() must be called at least once for each port before + run() or run_adding() is called. When working with blocks of + LADSPA_Data the plugin should pay careful attention to the block + size passed to the run function as the block allocated may only + just be large enough to contain the block of samples. + + Plugin writers should be aware that the host may elect to use the + same buffer for more than one port and even use the same buffer + for both input and output (see LADSPA_PROPERTY_INPLACE_BROKEN). + However, overlapped buffers or use of a single buffer for both + audio and control data may result in unexpected behaviour. */ + void (*connect_port)(LADSPA_Handle Instance, + unsigned long Port, + LADSPA_Data * DataLocation); + + /* This member is a function pointer that initialises a plugin + instance and activates it for use. This is separated from + instantiate() to aid real-time support and so that hosts can + reinitialise a plugin instance by calling deactivate() and then + activate(). In this case the plugin instance must reset all state + information dependent on the history of the plugin instance + except for any data locations provided by connect_port() and any + gain set by set_run_adding_gain(). If there is nothing for + activate() to do then the plugin writer may provide a NULL rather + than an empty function. + + When present, hosts must call this function once before run() (or + run_adding()) is called for the first time. This call should be + made as close to the run() call as possible and indicates to + real-time plugins that they are now live. Plugins should not rely + on a prompt call to run() after activate(). activate() may not be + called again unless deactivate() is called first. Note that + connect_port() may be called before or after a call to + activate(). */ + void (*activate)(LADSPA_Handle Instance); + + /* This method is a function pointer that runs an instance of a + plugin for a block. Two parameters are required: the first is a + handle to the particular instance to be run and the second + indicates the block size (in samples) for which the plugin + instance may run. + + Note that if an activate() function exists then it must be called + before run() or run_adding(). If deactivate() is called for a + plugin instance then the plugin instance may not be reused until + activate() has been called again. + + If the plugin has the property LADSPA_PROPERTY_HARD_RT_CAPABLE + then there are various things that the plugin should not do + within the run() or run_adding() functions (see above). */ + void (*run)(LADSPA_Handle Instance, + unsigned long SampleCount); + + /* This method is a function pointer that runs an instance of a + plugin for a block. This has identical behaviour to run() except + in the way data is output from the plugin. When run() is used, + values are written directly to the memory areas associated with + the output ports. However when run_adding() is called, values + must be added to the values already present in the memory + areas. Furthermore, output values written must be scaled by the + current gain set by set_run_adding_gain() (see below) before + addition. + + run_adding() is optional. When it is not provided by a plugin, + this function pointer must be set to NULL. When it is provided, + the function set_run_adding_gain() must be provided also. */ + void (*run_adding)(LADSPA_Handle Instance, + unsigned long SampleCount); + + /* This method is a function pointer that sets the output gain for + use when run_adding() is called (see above). If this function is + never called the gain is assumed to default to 1. Gain + information should be retained when activate() or deactivate() + are called. + + This function should be provided by the plugin if and only if the + run_adding() function is provided. When it is absent this + function pointer must be set to NULL. */ + void (*set_run_adding_gain)(LADSPA_Handle Instance, + LADSPA_Data Gain); + + /* This is the counterpart to activate() (see above). If there is + nothing for deactivate() to do then the plugin writer may provide + a NULL rather than an empty function. + + Hosts must deactivate all activated units after they have been + run() (or run_adding()) for the last time. This call should be + made as close to the last run() call as possible and indicates to + real-time plugins that they are no longer live. Plugins should + not rely on prompt deactivation. Note that connect_port() may be + called before or after a call to deactivate(). + + Deactivation is not similar to pausing as the plugin instance + will be reinitialised when activate() is called to reuse it. */ + void (*deactivate)(LADSPA_Handle Instance); + + /* Once an instance of a plugin has been finished with it can be + deleted using the following function. The instance handle passed + ceases to be valid after this call. + + If activate() was called for a plugin instance then a + corresponding call to deactivate() must be made before cleanup() + is called. */ + void (*cleanup)(LADSPA_Handle Instance); + +} LADSPA_Descriptor; + +/**********************************************************************/ + +/* Accessing a Plugin: */ + +/* The exact mechanism by which plugins are loaded is host-dependent, + however all most hosts will need to know is the name of shared + object file containing the plugin types. To allow multiple hosts to + share plugin types, hosts may wish to check for environment + variable LADSPA_PATH. If present, this should contain a + colon-separated path indicating directories that should be searched + (in order) when loading plugin types. + + A plugin programmer must include a function called + "ladspa_descriptor" with the following function prototype within + the shared object file. This function will have C-style linkage (if + you are using C++ this is taken care of by the `extern "C"' clause + at the top of the file). + + A host will find the plugin shared object file by one means or + another, find the ladspa_descriptor() function, call it, and + proceed from there. + + Plugin types are accessed by index (not ID) using values from 0 + upwards. Out of range indexes must result in this function + returning NULL, so the plugin count can be determined by checking + for the least index that results in NULL being returned. */ + +const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index); + +/* Datatype corresponding to the ladspa_descriptor() function. */ +typedef const LADSPA_Descriptor * +(*LADSPA_Descriptor_Function)(unsigned long Index); + +/**********************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* LADSPA_INCLUDED */ + +/* EOF */ diff --git a/libs/ardour/ardour/ladspa_plugin.h b/libs/ardour/ardour/ladspa_plugin.h new file mode 100644 index 0000000000..2451953ce5 --- /dev/null +++ b/libs/ardour/ardour/ladspa_plugin.h @@ -0,0 +1,142 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_ladspa_plugin_h__ +#define __ardour_ladspa_plugin_h__ + +#include <list> +#include <set> +#include <vector> +#include <string> +#include <dlfcn.h> + +#include <midi++/controllable.h> +#include <sigc++/signal.h> + +#include <jack/types.h> +#include <ardour/ladspa.h> +#include <ardour/stateful.h> +#include <ardour/plugin_state.h> +#include <ardour/plugin.h> +#include <ardour/ladspa_plugin.h> + +using std::string; +using std::vector; +using std::list; + +namespace ARDOUR { +class AudioEngine; +class Session; + +class LadspaPlugin : public ARDOUR::Plugin +{ + public: + LadspaPlugin (void *module, ARDOUR::AudioEngine&, ARDOUR::Session&, uint32_t index, jack_nframes_t sample_rate); + LadspaPlugin (const LadspaPlugin &); + ~LadspaPlugin (); + + /* Plugin interface */ + + uint32_t unique_id() const { return descriptor->UniqueID; } + const char * label() const { return descriptor->Label; } + const char * name() const { return descriptor->Name; } + const char * maker() const { return descriptor->Maker; } + uint32_t parameter_count() const { return descriptor->PortCount; } + float default_value (uint32_t port); + jack_nframes_t latency() const; + void set_parameter (uint32_t port, float val); + float get_parameter (uint32_t port) const; + int get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const; + std::set<uint32_t> automatable() const; + uint32_t nth_parameter (uint32_t port, bool& ok) const; + void activate () { + if (descriptor->activate) { + descriptor->activate (handle); + } + was_activated = true; + } + void deactivate () { + if (descriptor->deactivate) + descriptor->deactivate (handle); + } + void cleanup () { + if (was_activated && descriptor->cleanup) { + descriptor->cleanup (handle); + } + } + void set_block_size (jack_nframes_t nframes) {} + + int connect_and_run (vector<Sample*>& bufs, uint32_t maxbuf, int32_t& in, int32_t& out, jack_nframes_t nframes, jack_nframes_t offset); + void store_state (ARDOUR::PluginState&); + void restore_state (ARDOUR::PluginState&); + string describe_parameter (uint32_t); + string state_node_name() const { return "ladspa"; } + 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; + bool parameter_is_toggled(uint32_t) const; + + XMLNode& get_state(); + int set_state(const XMLNode& node); + bool save_preset(string name); + + bool has_editor() const { return false; } + + int require_output_streams (uint32_t); + + /* LADSPA extras */ + + LADSPA_Properties properties() const { return descriptor->Properties; } + uint32_t index() const { return _index; } + const char * copyright() const { return descriptor->Copyright; } + LADSPA_PortDescriptor port_descriptor(uint32_t i) const { return descriptor->PortDescriptors[i]; } + const LADSPA_PortRangeHint * port_range_hints() const { return descriptor->PortRangeHints; } + const char * const * port_names() const { return descriptor->PortNames; } + void set_gain (float gain) { + descriptor->set_run_adding_gain (handle, gain); + } + void run_adding (uint32_t nsamples) { + descriptor->run_adding (handle, nsamples); + } + void connect_port (uint32_t port, float *ptr) { + descriptor->connect_port (handle, port, ptr); + } + + private: + void *module; + const LADSPA_Descriptor *descriptor; + LADSPA_Handle handle; + jack_nframes_t sample_rate; + LADSPA_Data *control_data; + LADSPA_Data *shadow_data; + LADSPA_Data *latency_control_port; + uint32_t _index; + bool was_activated; + + void init (void *mod, uint32_t index, jack_nframes_t rate); + void run (jack_nframes_t nsamples); + void latency_compute_run (); +}; +} + +#endif /* __ardour_ladspa_plugin_h__ */ diff --git a/libs/ardour/ardour/location.h b/libs/ardour/ardour/location.h new file mode 100644 index 0000000000..1da67c78da --- /dev/null +++ b/libs/ardour/ardour/location.h @@ -0,0 +1,193 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_location_h__ +#define __ardour_location_h__ + +#include <string> +#include <list> +#include <iostream> +#include <map> + +#include <sys/types.h> +#include <pthread.h> +#include <sigc++/signal.h> + +#include <pbd/lockmonitor.h> +#include <pbd/undo.h> + +#include "ardour.h" +#include "stateful.h" +#include "state_manager.h" + +using std::string; + +namespace ARDOUR { + +class Location : public Stateful, public sigc::trackable +{ + public: + enum Flags { + IsMark = 0x1, + IsAutoPunch = 0x2, + IsAutoLoop = 0x4, + IsHidden = 0x8, + IsCDMarker = 0x10, + IsEnd = 0x20 + }; + + Location (jack_nframes_t sample_start, + jack_nframes_t sample_end, + const string &name, + Flags bits = Flags(0)) + + : _name (name), + _start (sample_start), + _end (sample_end), + _flags (bits) { } + + Location () { + _start = 0; + _end = 0; + _flags = 0; + } + + Location (const Location& other); + Location* operator= (const Location& other); + + jack_nframes_t start() { return _start; } + jack_nframes_t end() { return _end; } + jack_nframes_t length() { return _end - _start; } + + int set_start (jack_nframes_t s); + int set_end (jack_nframes_t e); + int set (jack_nframes_t start, jack_nframes_t end); + + const string& name() { return _name; } + void set_name (const string &str) { _name = str; name_changed(this); } + + void set_auto_punch (bool yn, void *src); + void set_auto_loop (bool yn, void *src); + void set_hidden (bool yn, void *src); + void set_cd (bool yn, void *src); + void set_is_end (bool yn, void* src); + + bool is_auto_punch () { return _flags & IsAutoPunch; } + bool is_auto_loop () { return _flags & IsAutoLoop; } + bool is_mark () { return _flags & IsMark; } + bool is_hidden () { return _flags & IsHidden; } + bool is_cd_marker () { return _flags & IsCDMarker; } + bool is_end() { return _flags & IsEnd; } + + sigc::signal<void,Location*> name_changed; + sigc::signal<void,Location*> end_changed; + sigc::signal<void,Location*> start_changed; + + sigc::signal<void,Location*,void*> FlagsChanged; + + /* this is sent only when both start&end change at the same time */ + + sigc::signal<void,Location*> changed; + + /* CD Track / CD-Text info */ + + std::map<string, string> cd_info; + XMLNode& cd_info_node (const string &, const string &); + + XMLNode& get_state (void); + int set_state (const XMLNode&); + + private: + string _name; + jack_nframes_t _start; + jack_nframes_t _end; + uint32_t _flags; + + void set_mark (bool yn); + bool set_flag_internal (bool yn, Flags flag); +}; + +class Locations : public Stateful, public StateManager +{ + public: + typedef std::list<Location *> LocationList; + + Locations (); + ~Locations (); + + void add (Location *, bool make_current = false); + void remove (Location *); + void clear (); + void clear_markers (); + void clear_ranges (); + + XMLNode& get_state (void); + int set_state (const XMLNode&); + + Location* auto_loop_location () const; + Location* auto_punch_location () const; + Location* end_location() const; + + int set_current (Location *, bool want_lock = true); + Location *current () const { return current_location; } + + Location *first_location_before (jack_nframes_t); + Location *first_location_after (jack_nframes_t); + + sigc::signal<void,Location*> current_changed; + sigc::signal<void> changed; + sigc::signal<void,Location*> added; + sigc::signal<void,Location*> removed; + + template<class T> void apply (T& obj, void (T::*method)(LocationList&)) { + LockMonitor lm (lock, __LINE__, __FILE__); + (obj.*method)(locations); + } + + template<class T1, class T2> void apply (T1& obj, void (T1::*method)(LocationList&, T2& arg), T2& arg) { + LockMonitor lm (lock, __LINE__, __FILE__); + (obj.*method)(locations, arg); + } + + UndoAction get_memento () const; + + private: + + struct State : public ARDOUR::StateManager::State { + LocationList locations; + LocationList states; + + State (std::string why) : ARDOUR::StateManager::State (why) {} + }; + + LocationList locations; + Location *current_location; + PBD::Lock lock; + + int set_current_unlocked (Location *); + void location_changed (Location*); + + Change restore_state (StateManager::State&); + StateManager::State* state_factory (std::string why) const; +}; + +}; /* namespace ARDOUR */ + +#endif /* __ardour_location_h__ */ diff --git a/libs/ardour/ardour/logcurve.h b/libs/ardour/ardour/logcurve.h new file mode 100644 index 0000000000..84911b0369 --- /dev/null +++ b/libs/ardour/ardour/logcurve.h @@ -0,0 +1,133 @@ +/* + Copyright (C) 2001 Steve Harris & Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_logcurve_h__ +#define __ardour_logcurve_h__ + +#include <pbd/fastlog.h> +#include <pbd/lockmonitor.h> + +namespace ARDOUR { + +class LogCurve { + public: + LogCurve (float steepness = 0.2, uint32_t len = 0) { + l = len; + S = steepness; + a = log(S); + b = 1.0f / log(1.0f + (1.0f / S)); + } + + bool operator== (const LogCurve& other) const { + return S == other.S && l == other.l; + } + + bool operator!= (const LogCurve& other) const { + return S != other.S || l != other.l; + } + + float value (float frac) const { + return (fast_log(frac + S) - a) * b; + } + + float value (uint32_t pos) const { + return (fast_log(((float) pos/l) + S) - a) * b; + } + + float invert_value (float frac) const { + return (a - fast_log(frac + S)) * b; + } + + float invert_value (uint32_t pos) const { + return (a - fast_log(((float) pos/l) + S)) * b; + } + + void fill (float *vec, uint32_t veclen, bool invert) const { + float dx = 1.0f/veclen; + float x; + uint32_t i; + + if (!invert) { + + vec[0] = 0.0; + vec[veclen-1] = 1.0; + + for (i = 1, x = 0; i < veclen - 1; x += dx, i++) { + vec[i] = value (x); + } + + } else { + + vec[0] = 1.0; + vec[veclen-1] = 0.0; + + for (i = veclen-2, x = 0.0f; i > 0; x += dx, i--) { + vec[i] = value (x); + } + } + } + + float steepness() const { return S; } + uint32_t length() const { return l; } + + void set_steepness (float steepness) { + S = steepness; + a = log(S); + b = 1.0f / log(1.0f + (1.0f / S)); + } + void set_length (uint32_t len) { l = len; } + + mutable PBD::NonBlockingLock lock; + + protected: + float a; + float b; + float S; + uint32_t l; +}; + +class LogCurveIn : public LogCurve +{ + public: + LogCurveIn (float steepness = 0.2, uint32_t len = 0) + : LogCurve (steepness, len) {} + + float value (float frac) const { + return (fast_log(frac + S) - a) * b; + } + + float value (uint32_t pos) const { + return (fast_log(((float) pos/l) + S) - a) * b; + } +}; + +class LogCurveOut : public LogCurve +{ + public: + LogCurveOut (float steepness = 0.2, uint32_t len = 0) + : LogCurve (steepness, len) {} + +}; + +}; /* namespace ARDOUR */ + +#endif /* __ardour_logcurve_h__ */ + + diff --git a/libs/ardour/ardour/mix.h b/libs/ardour/ardour/mix.h new file mode 100644 index 0000000000..b351e3ef17 --- /dev/null +++ b/libs/ardour/ardour/mix.h @@ -0,0 +1,74 @@ +/* + Copyright (C) 2005 Sampo Savolainen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ +#ifndef __ardour_mix_h__ +#define __ardour_mix_h__ + +#include <ardour/types.h> +#include <ardour/utils.h> +#include <ardour/io.h> + +#if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS) + +extern "C" { +/* SSE functions */ + float x86_sse_compute_peak (ARDOUR::Sample *buf, jack_nframes_t nsamples, float current); + + void x86_sse_apply_gain_to_buffer (ARDOUR::Sample *buf, jack_nframes_t nframes, float gain); + + void x86_sse_mix_buffers_with_gain (ARDOUR::Sample *dst, ARDOUR::Sample *src, jack_nframes_t nframes, float gain); + + void x86_sse_mix_buffers_no_gain (ARDOUR::Sample *dst, ARDOUR::Sample *src, jack_nframes_t nframes); +} + +/* debug wrappers for SSE functions */ + +float debug_compute_peak (ARDOUR::Sample *buf, jack_nframes_t nsamples, float current); + +void debug_apply_gain_to_buffer (ARDOUR::Sample *buf, jack_nframes_t nframes, float gain); + +void debug_mix_buffers_with_gain (ARDOUR::Sample *dst, ARDOUR::Sample *src, jack_nframes_t nframes, float gain); + +void debug_mix_buffers_no_gain (ARDOUR::Sample *dst, ARDOUR::Sample *src, jack_nframes_t nframes); + +#endif + +#if defined (__APPLE__) + +float veclib_compute_peak (ARDOUR::Sample *buf, jack_nframes_t nsamples, float current); + +void veclib_apply_gain_to_buffer (ARDOUR::Sample *buf, jack_nframes_t nframes, float gain); + +void veclib_mix_buffers_with_gain (ARDOUR::Sample *dst, ARDOUR::Sample *src, jack_nframes_t nframes, float gain); + +void veclib_mix_buffers_no_gain (ARDOUR::Sample *dst, ARDOUR::Sample *src, jack_nframes_t nframes); + +#endif + +/* non-optimized functions */ + +float compute_peak (ARDOUR::Sample *buf, jack_nframes_t nsamples, float current); + +void apply_gain_to_buffer (ARDOUR::Sample *buf, jack_nframes_t nframes, float gain); + +void mix_buffers_with_gain (ARDOUR::Sample *dst, ARDOUR::Sample *src, jack_nframes_t nframes, float gain); + +void mix_buffers_no_gain (ARDOUR::Sample *dst, ARDOUR::Sample *src, jack_nframes_t nframes); + +#endif /* __ardour_mix_h__ */ diff --git a/libs/ardour/ardour/named_selection.h b/libs/ardour/ardour/named_selection.h new file mode 100644 index 0000000000..91bb816181 --- /dev/null +++ b/libs/ardour/ardour/named_selection.h @@ -0,0 +1,55 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_named_selection_h__ +#define __ardour_named_selection_h__ + +#include <string> +#include <list> + +#include <ardour/stateful.h> + +class XMLNode; + +namespace ARDOUR +{ +class Session; +class Playlist; + +struct NamedSelection : public Stateful +{ + NamedSelection (std::string, std::list<Playlist*>&); + NamedSelection (Session&, const XMLNode&); + virtual ~NamedSelection (); + + std::string name; + std::list<Playlist*> playlists; + + XMLNode& get_state (void); + + int set_state (const XMLNode&); + + static sigc::signal<void,NamedSelection*> NamedSelectionCreated; +}; + +}/* namespace ARDOUR */ + +#endif /* __ardour_named_selection_h__ */ + diff --git a/libs/ardour/ardour/noise.h b/libs/ardour/ardour/noise.h new file mode 100644 index 0000000000..b06b02399b --- /dev/null +++ b/libs/ardour/ardour/noise.h @@ -0,0 +1,19 @@ +#ifndef NOISE_H +#define NOISE_H + +/* Can be overrriden with any code that produces whitenoise between 0.0f and + * 1.0f, eg (random() / (float)RAND_MAX) should be a good source of noise, but + * its expensive */ +#ifndef GDITHER_NOISE +#define GDITHER_NOISE gdither_noise() +#endif + +inline static float gdither_noise() +{ + static uint32_t rnd = 23232323; + rnd = (rnd * 196314165) + 907633515; + + return rnd * 2.3283064365387e-10f; +} + +#endif diff --git a/libs/ardour/ardour/panner.h b/libs/ardour/ardour/panner.h new file mode 100644 index 0000000000..806f350e03 --- /dev/null +++ b/libs/ardour/ardour/panner.h @@ -0,0 +1,331 @@ +/* + Copyright (C) 2004 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_panner_h__ +#define __ardour_panner_h__ + +#include <cmath> +#include <vector> +#include <string> +#include <iostream> +#include <sigc++/signal.h> + +#include <midi++/controllable.h> + +#include <ardour/types.h> +#include <ardour/stateful.h> +#include <ardour/curve.h> + +using std::istream; +using std::ostream; + +namespace ARDOUR { + +class Session; +class Panner; + +class StreamPanner : public sigc::trackable, public Stateful +{ + public: + StreamPanner (Panner& p); + ~StreamPanner (); + + void set_muted (bool yn); + bool muted() const { return _muted; } + + void set_position (float x, bool link_call = false); + void set_position (float x, float y, bool link_call = false); + void set_position (float x, float y, float z, bool link_call = false); + + void get_position (float& xpos) const { xpos = x; } + void get_position (float& xpos, float& ypos) const { xpos = x; ypos = y; } + void get_position (float& xpos, float& ypos, float& zpos) const { xpos = x; ypos = y; zpos = z; } + + void get_effective_position (float& xpos) const { xpos = effective_x; } + void get_effective_position (float& xpos, float& ypos) const { xpos = effective_x; ypos = effective_y; } + void get_effective_position (float& xpos, float& ypos, float& zpos) const { xpos = effective_x; ypos = effective_y; zpos = effective_z; } + + /* the basic panner API */ + + virtual void distribute (Sample* src, Sample** obufs, gain_t gain_coeff, jack_nframes_t nframes) = 0; + virtual void distribute_automated (Sample* src, Sample** obufs, + jack_nframes_t start, jack_nframes_t end, jack_nframes_t nframes, pan_t** buffers) = 0; + + /* automation */ + + virtual void snapshot (jack_nframes_t now) = 0; + virtual void transport_stopped (jack_nframes_t frame) = 0; + virtual void set_automation_state (AutoState) = 0; + virtual void set_automation_style (AutoStyle) = 0; + + /* MIDI control */ + + struct MIDIControl : public MIDI::Controllable { + MIDIControl (StreamPanner&, MIDI::Port *); + void set_value (float); + void send_feedback (gain_t); + MIDI::byte* write_feedback (MIDI::byte* buf, int32_t& bufsize, gain_t val, bool force = false); + + pan_t (*midi_to_pan)(double val); + double (*pan_to_midi)(pan_t p); + + StreamPanner& sp; + bool setting; + gain_t last_written; + }; + + MIDIControl& midi_control() { return _midi_control; } + void reset_midi_control (MIDI::Port *, bool); + + /* XXX this is wrong. for multi-dimensional panners, there + must surely be more than 1 automation curve. + */ + + virtual Curve& automation() = 0; + + + virtual int load (istream&, string path, uint32_t&) = 0; + + virtual int save (ostream&) const = 0; + + sigc::signal<void> Changed; /* for position */ + sigc::signal<void> StateChanged; /* for mute */ + + int set_state (const XMLNode&); + virtual XMLNode& state (bool full_state) = 0; + + Panner & get_parent() { return parent; } + + protected: + friend class Panner; + Panner& parent; + + float x; + float y; + float z; + + /* these are for automation. they store the last value + used by the most recent process() cycle. + */ + + float effective_x; + float effective_y; + float effective_z; + + bool _muted; + MIDIControl _midi_control; + + void add_state (XMLNode&); + bool get_midi_node_info (XMLNode * node, MIDI::eventType & ev, MIDI::channel_t & chan, MIDI::byte & additional); + bool set_midi_node_info (XMLNode * node, MIDI::eventType ev, MIDI::channel_t chan, MIDI::byte additional); + + virtual void update () = 0; +}; + +class BaseStereoPanner : public StreamPanner +{ + public: + BaseStereoPanner (Panner&); + ~BaseStereoPanner (); + + /* this class just leaves the pan law itself to be defined + by the update(), distribute_automated() + methods. derived classes also need a factory method + and a type name. See EqualPowerStereoPanner as an example. + */ + + void distribute (Sample* src, Sample** obufs, gain_t gain_coeff, jack_nframes_t nframes); + + int load (istream&, string path, uint32_t&); + int save (ostream&) const; + void snapshot (jack_nframes_t now); + void transport_stopped (jack_nframes_t frame); + void set_automation_state (AutoState); + void set_automation_style (AutoStyle); + + Curve& automation() { return _automation; } + + protected: + float left; + float right; + float desired_left; + float desired_right; + float left_interp; + float right_interp; + + Curve _automation; +}; + +class EqualPowerStereoPanner : public BaseStereoPanner +{ + public: + EqualPowerStereoPanner (Panner&); + ~EqualPowerStereoPanner (); + + void distribute_automated (Sample* src, Sample** obufs, + jack_nframes_t start, jack_nframes_t end, jack_nframes_t nframes, pan_t** buffers); + + void get_current_coefficients (pan_t*) const; + void get_desired_coefficients (pan_t*) const; + + static StreamPanner* factory (Panner&); + static string name; + + XMLNode& state (bool full_state); + XMLNode& get_state (void); + int set_state (const XMLNode&); + + private: + void update (); +}; + +class Multi2dPanner : public StreamPanner +{ + public: + Multi2dPanner (Panner& parent); + ~Multi2dPanner (); + + void snapshot (jack_nframes_t now); + void transport_stopped (jack_nframes_t frame); + void set_automation_state (AutoState); + void set_automation_style (AutoStyle); + + /* XXX this is wrong. for multi-dimensional panners, there + must surely be more than 1 automation curve. + */ + + Curve& automation() { return _automation; } + + void distribute (Sample* src, Sample** obufs, gain_t gain_coeff, jack_nframes_t nframes); + void distribute_automated (Sample* src, Sample** obufs, + jack_nframes_t start, jack_nframes_t end, jack_nframes_t nframes, pan_t** buffers); + + int load (istream&, string path, uint32_t&); + int save (ostream&) const; + + static StreamPanner* factory (Panner&); + static string name; + + XMLNode& state (bool full_state); + XMLNode& get_state (void); + int set_state (const XMLNode&); + + private: + Curve _automation; + void update (); +}; + +class Panner : public std::vector<StreamPanner*>, public Stateful, public sigc::trackable +{ + public: + struct Output { + float x; + float y; + pan_t current_pan; + pan_t desired_pan; + + Output (float xp, float yp) + : x (xp), y (yp), current_pan (0.0f), desired_pan (0.f) {} + + }; + + Panner (string name, Session&); + virtual ~Panner (); + + void set_name (string); + + bool bypassed() const { return _bypassed; } + void set_bypassed (bool yn); + + StreamPanner* add (); + void remove (uint32_t which); + void clear (); + void reset (uint32_t noutputs, uint32_t npans); + + void snapshot (jack_nframes_t now); + void transport_stopped (jack_nframes_t frame); + + void clear_automation (); + + void set_automation_state (AutoState); + AutoState automation_state() const; + void set_automation_style (AutoStyle); + AutoStyle automation_style() const; + bool touching() const; + + int load (); + int save () const; + + XMLNode& get_state (void); + XMLNode& state (bool full); + int set_state (const XMLNode&); + + sigc::signal<void> Changed; + + static bool equivalent (pan_t a, pan_t b) { + return fabsf (a - b) < 0.002; // about 1 degree of arc for a stereo panner + } + + void move_output (uint32_t, float x, float y); + uint32_t nouts() const { return outputs.size(); } + Output& output (uint32_t n) { return outputs[n]; } + + std::vector<Output> outputs; + Session& session() const { return _session; } + + void reset_midi_control (MIDI::Port *, bool); + void send_all_midi_feedback (); + MIDI::byte* write_midi_feedback (MIDI::byte*, int32_t& bufsize); + + enum LinkDirection { + SameDirection, + OppositeDirection + }; + + LinkDirection link_direction() const { return _link_direction; } + void set_link_direction (LinkDirection); + + bool linked() const { return _linked; } + void set_linked (bool yn); + + sigc::signal<void> LinkStateChanged; + sigc::signal<void> StateChanged; /* for bypass */ + + /* only StreamPanner should call these */ + + void set_position (float x, StreamPanner& orig); + void set_position (float x, float y, StreamPanner& orig); + void set_position (float x, float y, float z, StreamPanner& orig); + + private: + + string automation_path; + Session& _session; + uint32_t current_outs; + bool _linked; + bool _bypassed; + LinkDirection _link_direction; + + static float current_automation_version_number; +}; + +}; /* namespace ARDOUR */ + +#endif /*__ardour_panner_h__ */ diff --git a/libs/ardour/ardour/peak.h b/libs/ardour/ardour/peak.h new file mode 100644 index 0000000000..d08357024b --- /dev/null +++ b/libs/ardour/ardour/peak.h @@ -0,0 +1,17 @@ +#ifndef __ardour_peak_h__ +#define __ardour_peak_h__ + +#include <cmath> +#include <ardour/types.h> +#include <ardour/utils.h> + +static inline float +compute_peak (ARDOUR::Sample *buf, jack_nframes_t nsamples, float current) +{ + for (jack_nframes_t i = 0; i < nsamples; ++i) { + current = f_max (current, fabsf (buf[i])); + } + return current; +} + +#endif /* __ardour_peak_h__ */ diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h new file mode 100644 index 0000000000..a5451c30d5 --- /dev/null +++ b/libs/ardour/ardour/playlist.h @@ -0,0 +1,278 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_playlist_h__ +#define __ardour_playlist_h__ + +#include <string> +#include <set> +#include <map> +#include <list> + +#include <sys/stat.h> + +#include <sigc++/signal.h> +#include <pbd/atomic.h> +#include <pbd/undo.h> + +#include <ardour/ardour.h> +#include <ardour/crossfade_compare.h> +#include <ardour/location.h> +#include <ardour/stateful.h> +#include <ardour/source.h> +#include <ardour/state_manager.h> + +namespace ARDOUR { + +class Session; +class Region; + +class Playlist : public Stateful, public StateManager { + public: + typedef list<Region*> RegionList; + + Playlist (Session&, const XMLNode&, bool hidden = false); + Playlist (Session&, string name, bool hidden = false); + Playlist (const Playlist&, string name, bool hidden = false); + Playlist (const Playlist&, jack_nframes_t start, jack_nframes_t cnt, string name, bool hidden = false); + + virtual jack_nframes_t read (Sample *dst, Sample *mixdown, float *gain_buffer, jack_nframes_t start, jack_nframes_t cnt, uint32_t chan_n=0) = 0; + virtual void clear (bool with_delete = false, bool with_save = true); + virtual void dump () const; + virtual UndoAction get_memento() const = 0; + + void ref(); + void unref(); + uint32_t refcnt() const { return _refcnt; } + + const string& name() const { return _name; } + void set_name (const string& str); + + bool frozen() const { return _frozen; } + void set_frozen (bool yn); + + bool hidden() const { return _hidden; } + bool empty() const; + jack_nframes_t get_maximum_extent () const; + layer_t top_layer() const; + + EditMode get_edit_mode() const { return _edit_mode; } + void set_edit_mode (EditMode); + + /* Editing operations */ + + void add_region (const Region&, jack_nframes_t position, float times = 1, bool with_save = true); + void remove_region (Region *); + void replace_region (Region& old, Region& newr, jack_nframes_t pos); + void split_region (Region&, jack_nframes_t position); + void partition (jack_nframes_t start, jack_nframes_t end, bool just_top_level); + void duplicate (Region&, jack_nframes_t position, float times); + void nudge_after (jack_nframes_t start, jack_nframes_t distance, bool forwards); + + Region* find_region (id_t) const; + + Playlist* cut (list<AudioRange>&, bool result_is_hidden = true); + Playlist* copy (list<AudioRange>&, bool result_is_hidden = true); + int paste (Playlist&, jack_nframes_t position, float times); + + uint32_t read_data_count() { return _read_data_count; } + + RegionList* regions_at (jack_nframes_t frame); + RegionList* regions_touched (jack_nframes_t start, jack_nframes_t end); + Region* top_region_at (jack_nframes_t frame); + + Region* find_next_region (jack_nframes_t frame, RegionPoint point, int dir); + + template<class T> void foreach_region (T *t, void (T::*func)(Region *, void *), void *arg); + template<class T> void foreach_region (T *t, void (T::*func)(Region *)); + + XMLNode& get_state (); + int set_state (const XMLNode&); + XMLNode& get_template (); + + sigc::signal<void,Region *> RegionAdded; + sigc::signal<void,Region *> RegionRemoved; + + sigc::signal<void,Playlist*,bool> InUse; + sigc::signal<void> Modified; + sigc::signal<void> NameChanged; + sigc::signal<void> LengthChanged; + sigc::signal<void> LayeringChanged; + sigc::signal<void,Playlist *> GoingAway; + sigc::signal<void> StatePushed; + + static sigc::signal<void,Playlist*> PlaylistCreated; + + static string bump_name (string old_name, Session&); + static string bump_name_once (string old_name); + + void freeze (); + void thaw (); + + void raise_region (Region&); + void lower_region (Region&); + void raise_region_to_top (Region&); + void lower_region_to_bottom (Region&); + + uint32_t read_data_count() const { return _read_data_count; } + + Session& session() { return _session; } + + id_t get_orig_diskstream_id () const { return _orig_diskstream_id; } + void set_orig_diskstream_id (id_t did) { _orig_diskstream_id = did; } + + /* destructive editing */ + + virtual bool destroy_region (Region *) = 0; + + protected: + friend class Session; + virtual ~Playlist (); /* members of the public use unref() */ + + protected: + struct RegionLock { + RegionLock (Playlist *pl, bool do_block_notify = true) : playlist (pl), block_notify (do_block_notify) { + playlist->region_lock.lock(); + if (block_notify) { + playlist->delay_notifications(); + } + } + ~RegionLock() { + playlist->region_lock.unlock(); + if (block_notify) { + playlist->release_notifications (); + } + } + Playlist *playlist; + bool block_notify; + }; + + friend class RegionLock; + + RegionList regions; + string _name; + Session& _session; + atomic_t block_notifications; + atomic_t ignore_state_changes; + mutable PBD::NonBlockingLock region_lock; + RegionList pending_removals; + RegionList pending_adds; + RegionList pending_bounds; + bool pending_modified; + bool pending_length; + bool save_on_thaw; + string last_save_reason; + bool in_set_state; + bool _hidden; + bool _splicing; + bool _nudging; + uint32_t _refcnt; + EditMode _edit_mode; + bool in_flush; + bool in_partition; + bool _frozen; + uint32_t subcnt; + uint32_t _read_data_count; + id_t _orig_diskstream_id; + uint64_t layer_op_counter; + jack_nframes_t freeze_length; + + void init (bool hide); + + bool holding_state () const { + return atomic_read (&block_notifications) != 0 || + atomic_read (&ignore_state_changes) != 0; + } + + /* prevent the compiler from ever generating these */ + + Playlist (const Playlist&); + Playlist (Playlist&); + + void delay_notifications (); + void release_notifications (); + virtual void flush_notifications (); + + void notify_region_removed (Region *); + void notify_region_added (Region *); + void notify_length_changed (); + void notify_layering_changed (); + void notify_modified (); + void notify_state_changed (Change); + + void mark_session_dirty(); + + void region_changed_proxy (Change, Region*); + virtual bool region_changed (Change, Region*); + + void region_bounds_changed (Change, Region *); + void region_deleted (Region *); + + void sort_regions (); + + void possibly_splice (); + void possibly_splice_unlocked(); + void core_splice (); + void splice_locked (); + void splice_unlocked (); + + virtual void check_dependents (Region& region, bool norefresh) {} + virtual void refresh_dependents (Region& region) {} + virtual void remove_dependents (Region& region) {} + + virtual XMLNode& state (bool); + + /* override state_manager::save_state so we can check in_set_state() */ + + void save_state (std::string why); + void maybe_save_state (std::string why); + + void add_region_internal (Region *, jack_nframes_t position, bool delay_sort = false); + + int remove_region_internal (Region *, bool delay_sort = false); + RegionList *find_regions_at (jack_nframes_t frame); + void copy_regions (RegionList&) const; + void partition_internal (jack_nframes_t start, jack_nframes_t end, bool cutting, RegionList& thawlist); + + jack_nframes_t _get_maximum_extent() const; + + Playlist* cut_copy (Playlist* (Playlist::*pmf)(jack_nframes_t, jack_nframes_t, bool), + list<AudioRange>& ranges, bool result_is_hidden); + Playlist *cut (jack_nframes_t start, jack_nframes_t cnt, bool result_is_hidden); + Playlist *copy (jack_nframes_t start, jack_nframes_t cnt, bool result_is_hidden); + + + int move_region_to_layer (layer_t, Region& r, int dir); + void relayer (); + + static Playlist* copyPlaylist (const Playlist&, jack_nframes_t start, jack_nframes_t length, + string name, bool result_is_hidden); + + void unset_freeze_parent (Playlist*); + void unset_freeze_child (Playlist*); + + void timestamp_layer_op (Region&); +}; + +} /* namespace ARDOUR */ + +#endif /* __ardour_playlist_h__ */ + + diff --git a/libs/ardour/ardour/playlist_templates.h b/libs/ardour/ardour/playlist_templates.h new file mode 100644 index 0000000000..d3d682b8c5 --- /dev/null +++ b/libs/ardour/ardour/playlist_templates.h @@ -0,0 +1,49 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_playlist_templates_h__ +#define __ardour_playlist_templates_h__ + +namespace ARDOUR { + +template<class T> void AudioPlaylist::foreach_crossfade (T *t, void (T::*func)(Crossfade *)) { + RegionLock rlock (this, false); + for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); i++) { + (t->*func) (*i); + } +} + +template<class T> void Playlist::foreach_region (T *t, void (T::*func)(Region *, void *), void *arg) { + RegionLock rlock (this, false); + for (RegionList::iterator i = regions.begin(); i != regions.end(); i++) { + (t->*func) ((*i), arg); + } + } + +template<class T> void Playlist::foreach_region (T *t, void (T::*func)(Region *)) { + RegionLock rlock (this, false); + for (RegionList::const_iterator i = regions.begin(); i != regions.end(); i++) { + (t->*func) (*i); + } +} + +} + +#endif /* __ardour_playlist_templates_h__ */ diff --git a/libs/ardour/ardour/plugin.h b/libs/ardour/ardour/plugin.h new file mode 100644 index 0000000000..8839393b72 --- /dev/null +++ b/libs/ardour/ardour/plugin.h @@ -0,0 +1,194 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_ladspa_h__ +#define __ardour_ladspa_h__ + +#include <midi++/controllable.h> +#include <sigc++/signal.h> + +#include <jack/types.h> +#include <ardour/types.h> +#include <ardour/stateful.h> +#include <ardour/plugin_state.h> +#include <ardour/cycles.h> + +#include <list> +#include <vector> +#include <set> +#include <map> + +using std::string; +using std::vector; +using std::list; +using std::set; +using std::map; + +namespace ARDOUR { + +class AudioEngine; +class Session; + +class PluginInfo { + public: + enum Type { + LADSPA, + VST + }; + + PluginInfo () { }; + PluginInfo (const PluginInfo &o) + : name(o.name), n_inputs(o.n_inputs), n_outputs(o.n_outputs), + path (o.path), index(o.index) {} + ~PluginInfo () { }; + string name; + string category; + uint32_t n_inputs; + uint32_t n_outputs; + Type type; + + private: + friend class PluginManager; + string path; + uint32_t index; +}; + +class Plugin : public Stateful, public sigc::trackable + +{ + public: + Plugin (ARDOUR::AudioEngine&, ARDOUR::Session&); + Plugin (const Plugin&); + ~Plugin (); + + struct ParameterDescriptor { + + /* essentially a union of LADSPA and VST info */ + + bool integer_step; + bool toggled; + bool logarithmic; + bool sr_dependent; + string label; + float lower; + float upper; + float step; + float smallstep; + float largestep; + + bool min_unbound; + bool max_unbound; + }; + + virtual uint32_t unique_id() const = 0; + virtual const char * label() const = 0; + virtual const char * name() const = 0; + virtual const char * maker() const = 0; + virtual uint32_t parameter_count () const = 0; + virtual float default_value (uint32_t port) = 0; + virtual jack_nframes_t latency() const = 0; + virtual void set_parameter (uint32_t which, float val) = 0; + virtual float get_parameter(uint32_t which) const = 0; + + virtual int get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const = 0; + virtual uint32_t nth_parameter (uint32_t which, bool& ok) const = 0; + virtual void activate () = 0; + virtual void deactivate () = 0; + virtual void set_block_size (jack_nframes_t nframes) = 0; + + virtual int connect_and_run (vector<Sample*>& bufs, uint32_t maxbuf, int32_t& in, int32_t& out, jack_nframes_t nframes, jack_nframes_t offset) = 0; + virtual std::set<uint32_t> automatable() const = 0; + virtual void store_state (ARDOUR::PluginState&) = 0; + virtual void restore_state (ARDOUR::PluginState&) = 0; + virtual string describe_parameter (uint32_t) = 0; + virtual string state_node_name() const = 0; + virtual void print_parameter (uint32_t, char*, uint32_t len) const = 0; + + virtual bool parameter_is_audio(uint32_t) const = 0; + virtual bool parameter_is_control(uint32_t) const = 0; + virtual bool parameter_is_input(uint32_t) const = 0; + virtual bool parameter_is_output(uint32_t) const = 0; + + virtual bool save_preset(string name) = 0; + virtual bool load_preset (const string preset_label); + virtual list<string> get_presets(); + + virtual bool has_editor() const = 0; + + sigc::signal<void,uint32_t,float> ParameterChanged; + sigc::signal<void,Plugin *> GoingAway; + + void reset_midi_control (MIDI::Port*, bool); + void send_all_midi_feedback (); + MIDI::byte* write_midi_feedback (MIDI::byte*, int32_t& bufsize); + MIDI::Controllable *get_nth_midi_control (uint32_t); + + PluginInfo & get_info() { return _info; } + void set_info (const PluginInfo &inf) { _info = inf; } + + ARDOUR::AudioEngine& engine() const { return _engine; } + ARDOUR::Session& session() const { return _session; } + + void set_cycles (uint32_t c) { _cycles = c; } + cycles_t cycles() const { return _cycles; } + + protected: + ARDOUR::AudioEngine& _engine; + ARDOUR::Session& _session; + PluginInfo _info; + uint32_t _cycles; + map<string,string> presets; + bool save_preset(string name, string domain /* vst, ladspa etc. */); + + void setup_midi_controls (); + + + struct MIDIPortControl : public MIDI::Controllable { + MIDIPortControl (Plugin&, uint32_t abs_port_id, MIDI::Port *, + float lower, float upper, bool toggled, bool logarithmic); + + void set_value (float); + void send_feedback (float); + MIDI::byte* write_feedback (MIDI::byte* buf, int32_t& bufsize, float val, bool force = false); + + Plugin& plugin; + uint32_t absolute_port; + float upper; + float lower; + float range; + bool toggled; + bool logarithmic; + + bool setting; + float last_written; + }; + + vector<MIDIPortControl*> midi_controls; + + +}; + +/* this is actually defined in plugin_manager.cc */ + +Plugin * find_plugin(ARDOUR::Session&, string name, PluginInfo::Type); + +} // namespace ARDOUR + +#endif /* __ardour_plugin_h__ */ diff --git a/libs/ardour/ardour/plugin_manager.h b/libs/ardour/ardour/plugin_manager.h new file mode 100644 index 0000000000..1a07c67c8d --- /dev/null +++ b/libs/ardour/ardour/plugin_manager.h @@ -0,0 +1,63 @@ +#ifndef __ardour_plugin_manager_h__ +#define __ardour_plugin_manager_h__ + +#include <list> +#include <map> +#include <string> + +#include <ardour/types.h> + +namespace ARDOUR { + +class PluginInfo; +class Plugin; +class Session; +class AudioEngine; + +class PluginManager { + public: + PluginManager (ARDOUR::AudioEngine&); + ~PluginManager (); + + std::list<PluginInfo*> &vst_plugin_info () { return _vst_plugin_info; } + std::list<PluginInfo*> &ladspa_plugin_info () { return _ladspa_plugin_info; } + void refresh (); + + int add_ladspa_directory (std::string dirpath); + int add_vst_directory (std::string dirpath); + + Plugin *load (ARDOUR::Session& s, PluginInfo* info); + + static PluginManager* the_manager() { return _manager; } + + private: + ARDOUR::AudioEngine& _engine; + std::list<PluginInfo*> _vst_plugin_info; + std::list<PluginInfo*> _ladspa_plugin_info; + std::map<uint32_t, std::string> rdf_type; + + std::string ladspa_path; + std::string vst_path; + + void ladspa_refresh (); + void vst_refresh (); + + void add_lrdf_data (const std::string &path); + void add_ladspa_presets (); + void add_vst_presets (); + void add_presets (std::string domain); + + int vst_discover_from_path (std::string path); + int vst_discover (std::string path); + + int ladspa_discover_from_path (std::string path); + int ladspa_discover (std::string path); + + std::string get_ladspa_category (uint32_t id); + + static PluginManager* _manager; // singleton +}; + +} /* namespace ARDOUR */ + +#endif /* __ardour_plugin_manager_h__ */ diff --git a/libs/ardour/ardour/plugin_state.h b/libs/ardour/ardour/plugin_state.h new file mode 100644 index 0000000000..bd499e2b90 --- /dev/null +++ b/libs/ardour/ardour/plugin_state.h @@ -0,0 +1,14 @@ +#ifndef __ardour_plugin_state_h__ +#define __ardour_plugin_state_h__ + +#include <map> + +namespace ARDOUR { + +struct PluginState { + std::map<uint32_t,float> parameters; +}; + +} + +#endif /* __ardour_plugin_state_h__ */ diff --git a/libs/ardour/ardour/port.h b/libs/ardour/ardour/port.h new file mode 100644 index 0000000000..e5edcf72ac --- /dev/null +++ b/libs/ardour/ardour/port.h @@ -0,0 +1,213 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_port_h__ +#define __ardour_port_h__ + +#include <sigc++/signal.h> +#include <pbd/failed_constructor.h> +#include <ardour/ardour.h> +#include <jack/jack.h> + +namespace ARDOUR { + +class AudioEngine; + +class Port : public sigc::trackable { + public: + virtual ~Port() { + free (port); + } + + Sample *get_buffer (jack_nframes_t nframes) { + if (_flags & JackPortIsOutput) { + return _buffer; + } else { + return (Sample *) jack_port_get_buffer (port, nframes); + } + } + + void reset_buffer () { + if (_flags & JackPortIsOutput) { + _buffer = (Sample *) jack_port_get_buffer (port, 0); + } else { + _buffer = 0; /* catch illegal attempts to use it */ + } + silent = false; + } + + string name() { + return _name; + } + + string short_name() { + return jack_port_short_name (port); + } + + int set_name (string str); + + JackPortFlags flags() const { + return _flags; + } + + bool is_mine (jack_client_t *client) { + return jack_port_is_mine (client, port); + } + + const char* type() const { + return _type.c_str(); + } + + int connected () const { + return jack_port_connected (port); + } + + bool connected_to (const string& portname) const { + return jack_port_connected_to (port, portname.c_str()); + } + + const char ** get_connections () const { + return jack_port_get_connections (port); + } + + void reset_overs () { + _short_overs = 0; + _long_overs = 0; + overlen = 0; + } + + void reset_peak_meter () { + _peak = 0; + } + + void reset_meters () { + reset_peak_meter (); + reset_overs (); + } + + void enable_metering() { + metering++; + } + + void disable_metering () { + if (metering) { metering--; } + } + + float peak_db() const { return _peak_db; } + jack_default_audio_sample_t peak() const { return _peak; } + + uint32_t short_overs () const { return _short_overs; } + uint32_t long_overs () const { return _long_overs; } + + static void set_short_over_length (jack_nframes_t); + static void set_long_over_length (jack_nframes_t); + + bool receives_input() const { + return _flags & JackPortIsInput; + } + + bool sends_output () const { + return _flags & JackPortIsOutput; + } + + bool monitoring_input () const { + return jack_port_monitoring_input (port); + } + + bool can_monitor () const { + return _flags & JackPortCanMonitor; + } + + void ensure_monitor_input (bool yn) { + jack_port_request_monitor (port, yn); + } + + void request_monitor_input (bool yn) { + jack_port_request_monitor (port, yn); + } + + jack_nframes_t latency () const { + return jack_port_get_latency (port); + } + + void set_latency (jack_nframes_t nframes) { + jack_port_set_latency (port, nframes); + } + + sigc::signal<void,bool> MonitorInputChanged; + sigc::signal<void,bool> ClockSyncChanged; + + bool is_silent() const { return silent; } + + void silence (jack_nframes_t nframes, jack_nframes_t offset) { + /* assumes that the port is an output port */ + + if (!silent) { + memset (_buffer + offset, 0, sizeof (Sample) * nframes); + if (offset == 0) { + /* XXX this isn't really true, but i am not sure + how to set this correctly. we really just + want to set it true when the entire port + buffer has been overrwritten. + */ + silent = true; + } + } + } + + void mark_silence (bool yn) { + silent = yn; + } + + private: + friend class AudioEngine; + + Port (jack_port_t *port); + void reset (); + + /* engine isn't supposed to below here */ + + Sample *_buffer; + + /* cache these 3 from JACK so that we can + access them for reconnecting. + */ + + JackPortFlags _flags; + string _type; + string _name; + + bool last_monitor : 1; + bool silent : 1; + jack_port_t *port; + jack_nframes_t overlen; + jack_default_audio_sample_t _peak; + float _peak_db; + uint32_t _short_overs; + uint32_t _long_overs; + unsigned short metering; + + static jack_nframes_t long_over_length; + static jack_nframes_t short_over_length; +}; + +}; /* namespace ARDOUR */ + +#endif /* __ardour_port_h__ */ diff --git a/libs/ardour/ardour/recent_sessions.h b/libs/ardour/ardour/recent_sessions.h new file mode 100644 index 0000000000..9b1beea4af --- /dev/null +++ b/libs/ardour/ardour/recent_sessions.h @@ -0,0 +1,39 @@ +/* + Copyright (C) 2004 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __ardour_recent_sessions_h__ +#define __ardour_recent_sessions__h__ + +#include <deque> +#include <utility> +#include <string> + +using std::deque; +using std::pair; +using std::string; + +namespace ARDOUR { + typedef deque<pair<string,string> > RecentSessions; + + int read_recent_sessions (RecentSessions& rs); + int store_recent_sessions (string name, string path); + int write_recent_sessions (RecentSessions& rs); +}; // namespace ARDOUR + +#endif // __ardour_recent_sessions_h__ diff --git a/libs/ardour/ardour/redirect.h b/libs/ardour/ardour/redirect.h new file mode 100644 index 0000000000..fc7de9d814 --- /dev/null +++ b/libs/ardour/ardour/redirect.h @@ -0,0 +1,153 @@ +/* + Copyright (C) 2001 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_redirect_h__ +#define __ardour_redirect_h__ + +#include <string> +#include <vector> +#include <set> +#include <map> +#include <sigc++/signal.h> + +#include <pbd/lockmonitor.h> +#include <pbd/undo.h> + +#include <ardour/ardour.h> +#include <ardour/io.h> +#include <ardour/automation_event.h> + +using std::map; +using std::set; +using std::string; +using std::vector; + +class XMLNode; + +namespace ARDOUR { + +class Session; + +struct RedirectState : public StateManager::State { + RedirectState (string why) + : StateManager::State (why) {} + ~RedirectState () {} + + bool active; +}; + +class Redirect : public IO +{ + public: + static const string state_node_name; + + Redirect (Session&, const string& name, Placement, + int input_min = -1, int input_max = -1, int output_min = -1, int output_max = -1); + Redirect (const Redirect&); + virtual ~Redirect (); + + static Redirect *clone (const Redirect&); + + bool active () const { return _active; } + void set_active (bool yn, void *src); + + virtual uint32_t output_streams() const { return n_outputs(); } + virtual uint32_t input_streams () const { return n_inputs(); } + virtual uint32_t natural_output_streams() const { return n_outputs(); } + virtual uint32_t natural_input_streams () const { return n_inputs(); } + + uint32_t sort_key() const { return _sort_key; } + void set_sort_key (uint32_t sk,void *src) { _sort_key = sk; sort_key_changed (this, src); } + + Placement placement() const { return _placement; } + void set_placement (Placement, void *src); + + virtual void run (vector<Sample *>& ibufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset) = 0; + virtual void activate () = 0; + virtual void deactivate () = 0; + virtual jack_nframes_t latency() { return 0; } + + virtual void set_block_size (jack_nframes_t nframes) {} + + sigc::signal<void,Redirect*,void*> active_changed; + sigc::signal<void,Redirect*,void*> sort_key_changed; + sigc::signal<void,Redirect*,void*> placement_changed; + sigc::signal<void,Redirect*,bool> AutomationPlaybackChanged; + sigc::signal<void,Redirect*,uint32_t> AutomationChanged; + sigc::signal<void,Redirect*> GoingAway; + + static sigc::signal<void,Redirect*> RedirectCreated; + + XMLNode& state (bool full); + XMLNode& get_state (void); + int set_state (const XMLNode&); + + StateManager::State* state_factory (string why) const; + Change restore_state (StateManager::State&); + + void *get_gui () const { return _gui; } + void set_gui (void *p) { _gui = p; } + + virtual string describe_parameter (uint32_t which); + virtual float default_parameter_value (uint32_t which) { + return 1.0f; + } + + int load_automation (string path); + int save_automation (string path); + + void what_has_automation (set<uint32_t>&) const; + void what_has_visible_automation (set<uint32_t>&) const; + const set<uint32_t>& what_can_be_automated () const { return can_automate_list; } + + void mark_automation_visible (uint32_t, bool); + + AutomationList& automation_list (uint32_t); + bool find_next_event (jack_nframes_t, jack_nframes_t, ControlEvent&) const; + + virtual void transport_stopped (jack_nframes_t frame) {}; + + protected: + void set_placement (const string&, void *src); + + /* children may use this stuff as they see fit */ + + map<uint32_t,AutomationList*> parameter_automation; + set<uint32_t> visible_parameter_automation; + + mutable PBD::NonBlockingLock _automation_lock; + + void can_automate (uint32_t); + set<uint32_t> can_automate_list; + + void store_state (RedirectState&) const; + + virtual void automation_list_creation_callback (uint32_t, AutomationList&) {} + + private: + bool _active; + Placement _placement; + uint32_t _sort_key; + void* _gui; /* generic, we don't know or care what this is */ +}; + +}; /* namespace ARDOUR */ + +#endif /* __ardour_redirect_h__ */ diff --git a/libs/ardour/ardour/region.h b/libs/ardour/ardour/region.h new file mode 100644 index 0000000000..e067f56f44 --- /dev/null +++ b/libs/ardour/ardour/region.h @@ -0,0 +1,259 @@ +/* + Copyright (C) 2000-2001 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_region_h__ +#define __ardour_region_h__ + +#include <pbd/undo.h> + +#include <ardour/ardour.h> +#include <ardour/logcurve.h> +#include <ardour/state_manager.h> + +class XMLNode; + +namespace ARDOUR { + +class Playlist; +class Source; + +enum RegionEditState { + EditChangesNothing = 0, + EditChangesName = 1, + EditChangesID = 2 +}; + +struct RegionState : public StateManager::State { + + RegionState (std::string why) : StateManager::State (why) {} + + jack_nframes_t _start; + jack_nframes_t _length; + jack_nframes_t _position; + uint32_t _flags; + jack_nframes_t _sync_position; + layer_t _layer; + string _name; + mutable RegionEditState _first_edit; +}; + +class Region : public Stateful, public StateManager +{ + public: + enum Flag { + Muted = 0x1, + Opaque = 0x2, + EnvelopeActive = 0x4, + DefaultFadeIn = 0x8, + DefaultFadeOut = 0x10, + Locked = 0x20, + Automatic = 0x40, + WholeFile = 0x80, + FadeIn = 0x100, + FadeOut = 0x200, + Copied = 0x400, + Import = 0x800, + External = 0x1000, + SyncMarked = 0x2000, + LeftOfSplit = 0x4000, + RightOfSplit = 0x8000, + Hidden = 0x10000, + DoNotSaveState = 0x20000, + // + range_guarantoor = USHRT_MAX + }; + + static const Flag DefaultFlags = Flag (Opaque|DefaultFadeIn|DefaultFadeOut|FadeIn|FadeOut); + + static Change FadeChanged; + static Change SyncOffsetChanged; + static Change MuteChanged; + static Change OpacityChanged; + static Change LockChanged; + static Change LayerChanged; + static Change HiddenChanged; + + Region (jack_nframes_t start, jack_nframes_t length, + const string& name, layer_t = 0, Flag flags = DefaultFlags); + Region (const Region&, jack_nframes_t start, jack_nframes_t length, const string& name, layer_t = 0, Flag flags = DefaultFlags); + Region (const Region&); + Region (const XMLNode&); + ~Region(); + + ARDOUR::id_t id() const { return _id; } + + /* Note: changing the name of a Region does not constitute an edit */ + + string name() const { return _name; } + void set_name (string str); + + jack_nframes_t position () const { return _position; } + jack_nframes_t start () const { return _start; } + jack_nframes_t length() const { return _length; } + layer_t layer () const { return _layer; } + jack_nframes_t sync_offset(int& dir) const; + jack_nframes_t sync_position() const; + + jack_nframes_t adjust_to_sync (jack_nframes_t); + + /* first_frame() is an alias; last_frame() just hides some math */ + + jack_nframes_t first_frame() const { return _position; } + jack_nframes_t last_frame() const { return _position + _length - 1; } + + bool hidden() const { return _flags & Hidden; } + bool muted() const { return _flags & Muted; } + bool opaque () const { return _flags & Opaque; } + bool envelope_active () const { return _flags & EnvelopeActive; } + bool locked() const { return _flags & Locked; } + bool automatic() const { return _flags & Automatic; } + bool whole_file() const { return _flags & WholeFile ; } + Flag flags() const { return _flags; } + + virtual bool should_save_state () const { return !(_flags & DoNotSaveState); }; + + void freeze (); + void thaw (const string& why); + + bool covers (jack_nframes_t frame) const { + return _position <= frame && frame < _position + _length; + } + + OverlapType coverage (jack_nframes_t start, jack_nframes_t end) const { + return ARDOUR::coverage (_position, _position + _length - 1, start, end); + } + + virtual jack_nframes_t read_at (Sample *buf, Sample *mixdown_buffer, + float *gain_buffer, jack_nframes_t position, jack_nframes_t cnt, + uint32_t chan_n = 0, + jack_nframes_t read_frames = 0, + jack_nframes_t skip_frames = 0) const = 0; + + /* EDITING OPERATIONS */ + + void set_length (jack_nframes_t, void *src); + void set_start (jack_nframes_t, void *src); + void set_position (jack_nframes_t, void *src); + void set_position_on_top (jack_nframes_t, void *src); + void special_set_position (jack_nframes_t); + void nudge_position (long, void *src); + + void move_to_natural_position (void *src); + + void trim_start (jack_nframes_t new_position, void *src); + void trim_front (jack_nframes_t new_position, void *src); + void trim_end (jack_nframes_t new_position, void *src); + void trim_to (jack_nframes_t position, jack_nframes_t length, void *src); + + void set_layer (layer_t l); /* ONLY Playlist can call this */ + void raise (); + void lower (); + void raise_to_top (); + void lower_to_bottom (); + + void set_sync_position (jack_nframes_t n); + void clear_sync_position (); + void set_hidden (bool yn); + void set_muted (bool yn); + void set_opaque (bool yn); + void set_envelope_active (bool yn); + void set_locked (bool yn); + + virtual uint32_t read_data_count() const { return _read_data_count; } + + ARDOUR::Playlist* playlist() const { return _playlist; } + + virtual UndoAction get_memento() const = 0; + + void set_playlist (ARDOUR::Playlist*); + + virtual void lock_sources () {} + virtual void unlock_sources () {} + + /* serialization */ + + virtual XMLNode& state (bool); + XMLNode& get_state (); + int set_state (const XMLNode&); + + sigc::signal<void,Region*> GoingAway; + + /* This is emitted only when a new id is assigned. Therefore, + in a pure Region copy, it will not be emitted. + + It must be emitted by derived classes, not Region + itself, to permit dynamic_cast<> to be used to + infer the type of Region. + */ + + static sigc::signal<void,Region*> CheckNewRegion; + + virtual Region* get_parent() = 0; + + uint64_t last_layer_op() const { return _last_layer_op; } + void set_last_layer_op (uint64_t when); + + protected: + + jack_nframes_t _start; + jack_nframes_t _length; + jack_nframes_t _position; + Flag _flags; + jack_nframes_t _sync_position; + layer_t _layer; + string _name; + mutable RegionEditState _first_edit; + int _frozen; + PBD::Lock lock; + ARDOUR::id_t _id; + ARDOUR::Playlist* _playlist; + mutable uint32_t _read_data_count; // modified in read() + Change pending_changed; + uint64_t _last_layer_op; // timestamp + + XMLNode& get_short_state (); /* used only by Session */ + + /* state management */ + + void send_change (Change); + void send_state_changed (); + + /* derived classes need these during their own state management calls */ + + void store_state (RegionState&) const; + Change restore_and_return_flags (RegionState&); + + void trim_to_internal (jack_nframes_t position, jack_nframes_t length, void *src); + + bool copied() const { return _flags & Copied; } + void maybe_uncopy (); + void first_edit (); + + virtual bool verify_start (jack_nframes_t) = 0; + virtual bool verify_start_and_length (jack_nframes_t, jack_nframes_t) = 0; + virtual bool verify_start_mutable (jack_nframes_t&_start) = 0; + virtual bool verify_length (jack_nframes_t) = 0; + virtual void recompute_at_start () = 0; + virtual void recompute_at_end () = 0; +}; + +} /* namespace ARDOUR */ + +#endif /* __ardour_region_h__ */ diff --git a/libs/ardour/ardour/region_factory.h b/libs/ardour/ardour/region_factory.h new file mode 100644 index 0000000000..f72c0a52d8 --- /dev/null +++ b/libs/ardour/ardour/region_factory.h @@ -0,0 +1,22 @@ +#ifndef __ardour_region_factory_h__ +#define __ardour_region_factory_h__ + +#include <ardour/types.h> +#include <ardour/region.h> + +class XMLNode; + +namespace ARDOUR { + +class Session; + +Region* createRegion (const Region&, jack_nframes_t start, + jack_nframes_t length, std::string name, + layer_t = 0, Region::Flag flags = Region::DefaultFlags); +// Region* createRegion (const Region&, std::string name); +Region* createRegion (const Region&); +Region* createRegion (Session&, XMLNode&, bool); + +} + +#endif /* __ardour_region_factory_h__ */ diff --git a/libs/ardour/ardour/reverse.h b/libs/ardour/ardour/reverse.h new file mode 100644 index 0000000000..05ea8a1353 --- /dev/null +++ b/libs/ardour/ardour/reverse.h @@ -0,0 +1,38 @@ +/* + Copyright (C) 2004 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_reverse_h__ +#define __ardour_reverse_h__ + +#include <ardour/audiofilter.h> + +namespace ARDOUR { + +class Reverse : public AudioFilter { + public: + Reverse (ARDOUR::Session&); + ~Reverse (); + + int run (ARDOUR::AudioRegion&); +}; + +} /* namespace */ + +#endif /* __ardour_reverse_h__ */ diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h new file mode 100644 index 0000000000..8f4028c99f --- /dev/null +++ b/libs/ardour/ardour/route.h @@ -0,0 +1,359 @@ +/* + Copyright (C) 2000-2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_route_h__ +#define __ardour_route_h__ + +#include <cmath> +#include <list> +#include <set> +#include <map> +#include <string> + +#include <pthread.h> + +#include <pbd/atomic.h> +#include <pbd/fastlog.h> +#include <pbd/lockmonitor.h> +#include <pbd/xml++.h> +#include <pbd/undo.h> +#include <midi++/controllable.h> + +#include <ardour/ardour.h> +#include <ardour/stateful.h> +#include <ardour/io.h> +#include <ardour/session.h> +#include <ardour/redirect.h> + +namespace ARDOUR { + +class Insert; +class Send; +class RouteGroup; + +enum mute_type { + PRE_FADER = 0x1, + POST_FADER = 0x2, + CONTROL_OUTS = 0x4, + MAIN_OUTS = 0x8 +}; + +class Route : public IO +{ + private: + typedef list<Redirect *> RedirectList; + + public: + + enum Flag { + Hidden = 0x1, + MasterOut = 0x2, + ControlOut = 0x4, + }; + + + Route (Session&, std::string name, int input_min, int input_max, int output_min, int output_max, Flag flags = Flag(0)); + Route (Session&, const XMLNode&); + virtual ~Route(); + + std::string comment() { return _comment; } + void set_comment (std::string str, void *src); + + long order_key(std::string name) const; + void set_order_key (std::string name, long n); + + bool hidden() const { return _flags & Hidden; } + bool master() const { return _flags & MasterOut; } + bool control() const { return _flags & ControlOut; } + + /* these are the core of the API of a Route. see the protected sections as well */ + + + virtual int roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, + jack_nframes_t offset, int declick, bool can_record, bool rec_monitors_input); + + virtual int no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, + jack_nframes_t offset, bool state_changing, bool can_record, bool rec_monitors_input); + + 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 void set_record_enable (bool yn, void *src) {} + virtual bool record_enabled() const { return false; } + virtual void transport_stopped (bool abort, bool did_locate, bool flush_redirects); + virtual void set_pending_declick (int); + + /* end of vfunc-based API */ + + /* override IO::set_gain() to provide group control */ + + void set_gain (gain_t val, void *src); + void inc_gain (gain_t delta, void *src); + + bool active() const { return _active; } + void set_active (bool yn); + + void set_solo (bool yn, void *src); + bool soloed() const { return _soloed; } + + 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; } + + void set_mute_config (mute_type, bool, void *src); + bool get_mute_config (mute_type); + + void set_phase_invert (bool yn, void *src); + bool phase_invert() const { return _phase_invert; } + + void set_edit_group (RouteGroup *, void *); + RouteGroup *edit_group () { return _edit_group; } + + void set_mix_group (RouteGroup *, void *); + RouteGroup *mix_group () { return _mix_group; } + + virtual void set_meter_point (MeterPoint, void *src); + MeterPoint meter_point() const { return _meter_point; } + + /* Redirects */ + + void flush_redirects (); + + template<class T> void foreach_redirect (T *obj, void (T::*func)(Redirect *)) { + LockMonitor lm (redirect_lock, __LINE__, __FILE__); + for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) { + (obj->*func) (*i); + } + } + + Redirect *nth_redirect (uint32_t n) { + LockMonitor lm (redirect_lock, __LINE__, __FILE__); + RedirectList::iterator i; + for (i = _redirects.begin(); i != _redirects.end() && n; ++i, --n); + if (i == _redirects.end()) { + return 0; + } else { + return *i; + } + } + + uint32_t max_redirect_outs () const { return redirect_max_outs; } + + int add_redirect (Redirect *, void *src, uint32_t* err_streams = 0); + int add_redirects (const RedirectList&, void *src, uint32_t* err_streams = 0); + int remove_redirect (Redirect *, void *src, uint32_t* err_streams = 0); + int copy_redirects (const Route&, Placement, uint32_t* err_streams = 0); + int sort_redirects (uint32_t* err_streams = 0); + + void clear_redirects (void *src); + void all_redirects_flip(); + void all_redirects_active (bool state); + + virtual jack_nframes_t update_total_latency(); + jack_nframes_t signal_latency() const { return _own_latency; } + virtual void set_latency_delay (jack_nframes_t); + + sigc::signal<void,void*> solo_changed; + sigc::signal<void,void*> solo_safe_changed; + sigc::signal<void,void*> comment_changed; + sigc::signal<void,void*> mute_changed; + sigc::signal<void,void*> pre_fader_changed; + sigc::signal<void,void*> post_fader_changed; + sigc::signal<void,void*> control_outs_changed; + sigc::signal<void,void*> main_outs_changed; + sigc::signal<void,void*> redirects_changed; + sigc::signal<void,void*> record_enable_changed; + sigc::signal<void,void*> edit_group_changed; + sigc::signal<void,void*> mix_group_changed; + sigc::signal<void> active_changed; + sigc::signal<void,void*> meter_change; + + sigc::signal<void> GoingAway; + + /* gui's call this for their own purposes. */ + + sigc::signal<void,std::string,void*> gui_changed; + + /* stateful */ + + XMLNode& get_state(); + int set_state(const XMLNode& node); + XMLNode& get_template(); + + sigc::signal<void,void*> SelectedChanged; + + /* undo */ + + UndoAction get_memento() const; + void set_state (state_id_t); + + int set_control_outs (const vector<std::string>& ports); + IO* control_outs() { return _control_outs; } + + bool feeds (Route *); + set<Route *> fed_by; + + struct MIDIToggleControl : public MIDI::Controllable { + enum ToggleType { + MuteControl = 0, + SoloControl + }; + + MIDIToggleControl (Route&, ToggleType, MIDI::Port *); + void set_value (float); + void send_feedback (bool); + MIDI::byte* write_feedback (MIDI::byte* buf, int32_t& bufsize, bool val, bool force = false); + + Route& route; + ToggleType type; + bool setting; + bool last_written; + }; + + MIDI::Controllable& midi_solo_control() { + return _midi_solo_control; + } + MIDI::Controllable& midi_mute_control() { + return _midi_mute_control; + } + + virtual void reset_midi_control (MIDI::Port*, bool); + virtual void send_all_midi_feedback (); + virtual MIDI::byte* write_midi_feedback (MIDI::byte*, int32_t& bufsize); + + void automation_snapshot (jack_nframes_t now); + + void protect_automation (); + + protected: + friend class Session; + + void set_solo_mute (bool yn); + void set_block_size (jack_nframes_t nframes); + bool has_external_redirects() const; + void curve_reallocate (); + + protected: + unsigned char _flags; + + /* tight cache-line access here is more important than sheer speed of + access. + */ + + bool _muted : 1; + bool _soloed : 1; + bool _solo_muted : 1; + bool _solo_safe : 1; + bool _phase_invert : 1; + bool _recordable : 1; + bool _active : 1; + bool _mute_affects_pre_fader : 1; + bool _mute_affects_post_fader : 1; + bool _mute_affects_control_outs : 1; + bool _mute_affects_main_outs : 1; + bool _silent : 1; + bool _declickable : 1; + int _pending_declick; + + MeterPoint _meter_point; + + gain_t solo_gain; + gain_t mute_gain; + gain_t desired_solo_gain; + gain_t desired_mute_gain; + + jack_nframes_t check_initial_delay (jack_nframes_t, jack_nframes_t&, jack_nframes_t&); + + jack_nframes_t _initial_delay; + jack_nframes_t _roll_delay; + jack_nframes_t _own_latency; + RedirectList _redirects; + PBD::NonBlockingLock redirect_lock; + IO *_control_outs; + PBD::NonBlockingLock control_outs_lock; + RouteGroup *_edit_group; + RouteGroup *_mix_group; + std::string _comment; + bool _have_internal_generator; + + MIDIToggleControl _midi_solo_control; + MIDIToggleControl _midi_mute_control; + + void passthru (jack_nframes_t start_frame, jack_nframes_t end_frame, + jack_nframes_t nframes, jack_nframes_t offset, int declick, bool meter_inputs); + + void process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs, + jack_nframes_t start_frame, jack_nframes_t end_frame, + jack_nframes_t nframes, jack_nframes_t offset, bool with_redirects, int declick, + bool meter); + + protected: + /* for derived classes */ + + virtual XMLNode& state(bool); + + void silence (jack_nframes_t nframes, jack_nframes_t offset); + sigc::connection input_signal_connection; + + state_id_t _current_state_id; + uint32_t redirect_max_outs; + + uint32_t pans_required() const; + uint32_t n_process_buffers (); + + private: + void init (); + + static uint32_t order_key_cnt; + typedef std::map<std::string,long> OrderKeys; + OrderKeys order_keys; + + void input_change_handler (IOChange, void *src); + void output_change_handler (IOChange, void *src); + + bool legal_redirect (Redirect&); + int reset_plugin_counts (uint32_t*); /* locked */ + int _reset_plugin_counts (uint32_t*); /* unlocked */ + + /* plugin count handling */ + + struct InsertCount { + ARDOUR::Insert& insert; + int32_t cnt; + int32_t in; + int32_t out; + + InsertCount (ARDOUR::Insert& ins) : insert (ins), cnt (-1) {} + }; + + int32_t apply_some_plugin_counts (std::list<InsertCount>& iclist); + int32_t check_some_plugin_counts (std::list<InsertCount>& iclist, int32_t required_inputs, uint32_t* err_streams); + + void set_deferred_state (); + void add_redirect_from_xml (const XMLNode&); + void redirect_active_proxy (Redirect*, void*); +}; + +}; /* namespace ARDOUR*/ + +#endif /* __ardour_route_h__ */ diff --git a/libs/ardour/ardour/route_group.h b/libs/ardour/ardour/route_group.h new file mode 100644 index 0000000000..910500ccf8 --- /dev/null +++ b/libs/ardour/ardour/route_group.h @@ -0,0 +1,111 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_route_group_h__ +#define __ardour_route_group_h__ + +#include <list> +#include <string> +#include <stdint.h> +#include <sigc++/signal.h> +#include <ardour/stateful.h> +#include <ardour/types.h> + +using std::string; +using std::list; + +namespace ARDOUR { + +class Route; +class AudioTrack; + +class RouteGroup : public Stateful, public sigc::trackable { + public: + enum Flag { + Relative = 0x1, + Active = 0x2, + Hidden = 0x4, + }; + + RouteGroup(const string &n, Flag f = Flag(0)) : _name (n), _flags (f) {} + + const string& name() { return _name; } + + bool is_active () const { return _flags & Active; } + bool is_relative () const { return _flags & Relative; } + bool is_hidden () const { return _flags & Hidden; } + bool empty() const {return routes.empty();} + + gain_t get_max_factor(gain_t factor); + gain_t get_min_factor(gain_t factor); + + int size() { return routes.size();} + ARDOUR::Route * first () const { return *routes.begin();} + + void set_active (bool yn, void *src); + void set_relative (bool yn, void *src); + void set_hidden (bool yn, void *src); + + + int add (Route *); + + int remove (Route *); + + template<class T> void apply (void (Route::*func)(T, void *), T val, void *src) { + for (list<Route *>::iterator i = routes.begin(); i != routes.end(); i++) { + ((*i)->*func)(val, this); + } + } + + template<class T> void foreach_route (T *obj, void (T::*func)(Route&)) { + for (list<Route *>::iterator i = routes.begin(); i != routes.end(); i++) { + (obj->*func)(**i); + } + } + + /* to use these, #include <ardour/route_group_specialized.h> */ + + template<class T> void apply (void (AudioTrack::*func)(T, void *), T val, void *src); + + void clear () { + routes.clear (); + changed(); + } + + const list<Route*>& route_list() { return routes; } + + sigc::signal<void> changed; + sigc::signal<void,void*> FlagsChanged; + + XMLNode& get_state (void); + + int set_state (const XMLNode&); + + private: + list<Route *> routes; + string _name; + uint32_t _flags; + + void remove_when_going_away (Route*); +}; + +} /* namespace */ + +#endif /* __ardour_route_group_h__ */ diff --git a/libs/ardour/ardour/route_group_specialized.h b/libs/ardour/ardour/route_group_specialized.h new file mode 100644 index 0000000000..32c627eb7a --- /dev/null +++ b/libs/ardour/ardour/route_group_specialized.h @@ -0,0 +1,22 @@ +#ifndef __ardour_route_group_specialized_h__ +#define __ardour_route_group_specialized_h__ + +#include <ardour/route_group.h> +#include <ardour/audio_track.h> + +namespace ARDOUR { + +template<class T> void +RouteGroup::apply (void (AudioTrack::*func)(T, void *), T val, void *src) +{ + for (list<Route *>::iterator i = routes.begin(); i != routes.end(); i++) { + AudioTrack *at; + if ((at = dynamic_cast<AudioTrack*>(*i)) != 0) { + (at->*func)(val, this); + } + } +} + +} /* namespace ARDOUR */ + +#endif /* __ardour_route_group_specialized_h__ */ diff --git a/libs/ardour/ardour/send.h b/libs/ardour/ardour/send.h new file mode 100644 index 0000000000..a94318f2a5 --- /dev/null +++ b/libs/ardour/ardour/send.h @@ -0,0 +1,63 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_send_h__ +#define __ardour_send_h__ + +#include <sigc++/signal.h> +#include <string> + +#include <ardour/ardour.h> +#include <ardour/audioengine.h> + +#include "io.h" +#include "stateful.h" +#include "redirect.h" + +namespace ARDOUR { + +class Send : public Redirect { + public: + Send (Session&, Placement); + Send (Session&, const XMLNode&); + Send (const Send&); + ~Send (); + + void run (vector<Sample *> &bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset); + void activate() {} + void deactivate () {} + + void set_metering (bool yn); + + XMLNode& state(bool full); + XMLNode& get_state(void); + int set_state(const XMLNode& node); + + uint32_t pans_required() const { return expected_inputs; } + void expect_inputs (uint32_t); + + private: + bool _metering; + uint32_t expected_inputs; +}; + +}; /* namespace ARDOUR */ + +#endif /* __ardour_send_h__ */ diff --git a/libs/ardour/ardour/seqsource.h b/libs/ardour/ardour/seqsource.h new file mode 100644 index 0000000000..7e38d27915 --- /dev/null +++ b/libs/ardour/ardour/seqsource.h @@ -0,0 +1,55 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __playlist_seqsource_h__ +#define __playlist_seqsource_h__ + +#include <string> + +#include "edl.h" + +namespace EDL { + +class PlaylistSource : public Source { + public: + PlaylistSource (Playlist&); + ~PlaylistSource (); + + const gchar * const id() { return playlist.name().c_str(); } + uint32_t length() { return playlist.length(); } + uint32_t read (Source::Data *dst, uint32_t start, uint32_t cnt) { + return playlist.read (dst, start, cnt, false); + } + uint32_t write (Source::Data *src, uint32_t where, uint32_t cnt) { + return playlist.write (src, where, cnt); + } + +// int read_peaks (peak_data_t *, uint32_t npeaks, uint32_t start, uint32_t cnt); +// int build_peak (uint32_t first_frame, uint32_t cnt); + + protected: + + private: + Playlist& playlist; +}; + +}; /* namespace EDL */ + +#endif /* __playlist_seqsource_h__ */ diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h new file mode 100644 index 0000000000..b58b0a926b --- /dev/null +++ b/libs/ardour/ardour/session.h @@ -0,0 +1,1754 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_session_h__ +#define __ardour_session_h__ + +#include <string> +#if __GNUC__ >= 3 +#include <ext/slist> +using __gnu_cxx::slist; +#else +#include <slist.h> +#endif +#include <map> +#include <vector> +#include <set> +#include <stack> +#include <stdint.h> + +#include <sndfile.h> + +#include <pbd/error.h> +#include <pbd/atomic.h> +#include <pbd/lockmonitor.h> +#include <pbd/undo.h> +#include <pbd/pool.h> + +#include <midi++/types.h> +#include <midi++/mmc.h> + +#include <ardour/ardour.h> +#include <ardour/configuration.h> +#include <ardour/location.h> +#include <ardour/stateful.h> +#include <ardour/gain.h> +#include <ardour/io.h> + +class XMLTree; +class XMLNode; +class AEffect; + +namespace MIDI { + class Port; +} + +namespace ARDOUR { + +class Port; +class AudioEngine; +class Slave; +class DiskStream; +class Route; +class AuxInput; +class Source; +class FileSource; +class Auditioner; +class Insert; +class Send; +class Redirect; +class PortInsert; +class PluginInsert; +class Connection; +class TempoMap; +class AudioTrack; +class NamedSelection; +class AudioRegion; +class Region; +class Playlist; +class VSTPlugin; + +struct AudioExportSpecification; +struct RouteGroup; + +using std::vector; +using std::string; +using std::list; +using std::map; +using std::set; + +class Session : public sigc::trackable, public Stateful + +{ + private: + typedef std::pair<Route*,bool> RouteBooleanState; + typedef vector<RouteBooleanState> GlobalRouteBooleanState; + typedef std::pair<Route*,MeterPoint> RouteMeterState; + typedef vector<RouteMeterState> GlobalRouteMeterState; + + public: + enum RecordState { + Disabled = 0, + Enabled = 1, + Recording = 2 + }; + + enum SlaveSource { + None = 0, + MTC, + JACK, + }; + + enum AutoConnectOption { + AutoConnectPhysical = 0x1, + AutoConnectMaster = 0x2 + }; + + struct Event { + enum Type { + SetTransportSpeed, + SetDiskstreamSpeed, + Locate, + LocateRoll, + SetLoop, + PunchIn, + PunchOut, + RangeStop, + RangeLocate, + Overwrite, + SetSlaveSource, + Audition, + InputConfigurationChange, + SetAudioRange, + SetPlayRange, + + /* only one of each of these events + can be queued at any one time + */ + + StopOnce, + AutoLoop, + }; + + enum Action { + Add, + Remove, + Replace, + Clear + }; + + Type type; + Action action; + jack_nframes_t action_frame; + jack_nframes_t target_frame; + float speed; + + union { + void* ptr; + bool yes_or_no; + Session::SlaveSource slave; + }; + + list<AudioRange> audio_range; + list<MusicRange> music_range; + + Event(Type t, Action a, jack_nframes_t when, jack_nframes_t where, float spd, bool yn = false) + : type (t), + action (a), + action_frame (when), + target_frame (where), + speed (spd), + yes_or_no (yn) {} + + void set_ptr (void* p) { + ptr = p; + } + + bool before (const Event& other) const { + return action_frame < other.action_frame; + } + + bool after (const Event& other) const { + return action_frame > other.action_frame; + } + + static bool compare (const Event *e1, const Event *e2) { + return e1->before (*e2); + } + + void *operator new (size_t ignored) { + return pool.alloc (); + } + + void operator delete(void *ptr, size_t size) { + pool.release (ptr); + } + + static const jack_nframes_t Immediate = 0; + + private: + static MultiAllocSingleReleasePool pool; + }; + + /* creating from an XML file */ + + Session (AudioEngine&, + string fullpath, + string snapshot_name, + string* mix_template = 0); + + /* creating a new Session */ + + Session (AudioEngine&, + string fullpath, + string snapshot_name, + AutoConnectOption input_auto_connect, + AutoConnectOption output_auto_connect, + uint32_t control_out_channels, + uint32_t master_out_channels, + uint32_t n_physical_in, + uint32_t n_physical_out, + jack_nframes_t initial_length); + + virtual ~Session (); + + + static int find_session (string str, string& path, string& snapshot, bool& isnew); + + string path() const { return _path; } + string name() const { return _name; } + string snap_name() const { return _current_snapshot_name; } + + void set_snap_name (); + + void set_dirty (); + void set_clean (); + bool dirty() const { return _state_of_the_state & Dirty; } + sigc::signal<void> DirtyChanged; + + string sound_dir () const; + string peak_dir () const; + string dead_sound_dir () const; + string automation_dir () const; + + static string template_path (); + static string template_dir (); + static void get_template_list (list<string>&); + + static string peak_path_from_audio_path (string); + static string old_peak_path_from_audio_path (string); + + void process (jack_nframes_t nframes); + + vector<Sample*>& get_passthru_buffers() { return _passthru_buffers; } + vector<Sample*>& get_silent_buffers (uint32_t howmany); + + DiskStream *diskstream_by_id (id_t id); + DiskStream *diskstream_by_name (string name); + + bool have_captured() const { return _have_captured; } + + void refill_all_diskstream_buffers (); + uint32_t diskstream_buffer_size() const { return dstream_buffer_size; } + uint32_t get_next_diskstream_id() const { return n_diskstreams(); } + uint32_t n_diskstreams() const; + + typedef list<DiskStream *> DiskStreamList; + + Session::DiskStreamList disk_streams() const { + LockMonitor lm (diskstream_lock, __LINE__, __FILE__); + return diskstreams; /* XXX yes, force a copy */ + } + + void foreach_diskstream (void (DiskStream::*func)(void)); + template<class T> void foreach_diskstream (T *obj, void (T::*func)(DiskStream&)); + + typedef slist<Route *> RouteList; + + RouteList get_routes() const { + LockMonitor rlock (route_lock, __LINE__, __FILE__); + return routes; /* XXX yes, force a copy */ + } + + uint32_t nroutes() const { return routes.size(); } + uint32_t ntracks () const; + uint32_t nbusses () const; + + struct RoutePublicOrderSorter { + bool operator() (Route *, Route *b); + }; + + template<class T> void foreach_route (T *obj, void (T::*func)(Route&)); + template<class T> void foreach_route (T *obj, void (T::*func)(Route*)); + template<class T, class A> void foreach_route (T *obj, void (T::*func)(Route&, A), A arg); + + Route *route_by_name (string); + + bool route_name_unique (string) const; + + bool get_record_enabled() const { + return (record_status () >= Enabled); + } + + RecordState record_status() const { + return (RecordState) atomic_read (&_record_status); + } + + bool actively_recording () { + return record_status() == Recording; + } + + bool record_enabling_legal () const; + void maybe_enable_record (); + void disable_record (); + void step_back_from_record (); + + sigc::signal<void> going_away; + + /* Proxy signal for region hidden changes */ + + sigc::signal<void,Region*> RegionHiddenChange; + + /* Emitted when all i/o connections are complete */ + + sigc::signal<void> IOConnectionsComplete; + + /* Record status signals */ + + sigc::signal<void> RecordEnabled; + sigc::signal<void> RecordDisabled; + + /* Transport mechanism signals */ + + sigc::signal<void> TransportStateChange; /* generic */ + sigc::signal<void,jack_nframes_t> PositionChanged; /* sent after any non-sequential motion */ + sigc::signal<void> DurationChanged; + sigc::signal<void> HaltOnXrun; + + sigc::signal<void,Route*> RouteAdded; + sigc::signal<void,DiskStream*> DiskStreamAdded; + + void request_roll (); + void request_bounded_roll (jack_nframes_t start, jack_nframes_t end); + void request_stop (bool abort = false); + void request_locate (jack_nframes_t frame, bool with_roll = false); + void request_auto_loop (bool yn); + jack_nframes_t last_transport_start() const { return _last_roll_location; } + void goto_end () { request_locate (end_location->start(), false);} + void goto_start () { request_locate (0, false); } + void use_rf_shuttle_speed (); + void request_transport_speed (float speed); + void request_overwrite_buffer (DiskStream*); + void request_diskstream_speed (DiskStream&, float speed); + void request_input_change_handling (); + + int wipe (); + int wipe_diskstream (DiskStream *); + + int remove_region_from_region_list (Region&); + + jack_nframes_t current_end_frame() const { return end_location->start(); } + jack_nframes_t frame_rate() const { return _current_frame_rate; } + double frames_per_smpte_frame() const { return _frames_per_smpte_frame; } + jack_nframes_t frames_per_hour() const { return _frames_per_hour; } + jack_nframes_t smpte_frames_per_hour() const { return _smpte_frames_per_hour; } + + /* Locations */ + + Locations *locations() { return &_locations; } + + sigc::signal<void,Location*> auto_loop_location_changed; + sigc::signal<void,Location*> auto_punch_location_changed; + sigc::signal<void> locations_modified; + + void set_auto_punch_location (Location *); + void set_auto_loop_location (Location *); + + + enum ControlType { + AutoPlay, + AutoLoop, + AutoReturn, + AutoInput, + PunchIn, + PunchOut, + SendMTC, + MMCControl, + Live, + RecordingPlugins, + CrossFadesActive, + SendMMC, + SlaveType, + Clicking, + EditingMode, + PlayRange, + AlignChoice, + SeamlessLoop, + MidiFeedback, + MidiControl + }; + + sigc::signal<void,ControlType> ControlChanged; + + void set_auto_play (bool yn); + void set_auto_return (bool yn); + void set_auto_input (bool yn); + void set_input_auto_connect (bool yn); + void set_output_auto_connect (AutoConnectOption); + void set_punch_in (bool yn); + void set_punch_out (bool yn); + void set_send_mtc (bool yn); + void set_send_mmc (bool yn); + void set_mmc_control (bool yn); + void set_midi_feedback (bool yn); + void set_midi_control (bool yn); + void set_recording_plugins (bool yn); + void set_crossfades_active (bool yn); + void set_seamless_loop (bool yn); + + bool get_auto_play () const { return auto_play; } + bool get_auto_input () const { return auto_input; } + bool get_auto_loop () const { return auto_loop; } + bool get_seamless_loop () const { return seamless_loop; } + bool get_punch_in () const { return punch_in; } + bool get_punch_out () const { return punch_out; } + bool get_all_safe () const { return all_safe; } + bool get_auto_return () const { return auto_return; } + bool get_send_mtc () const; + bool get_send_mmc () const; + bool get_mmc_control () const; + bool get_midi_feedback () const; + bool get_midi_control () const; + bool get_recording_plugins () const { return recording_plugins; } + bool get_crossfades_active () const { return crossfades_active; } + + AutoConnectOption get_input_auto_connect () const { return input_auto_connect; } + AutoConnectOption get_output_auto_connect () const { return output_auto_connect; } + + enum LayerModel { + LaterHigher, + MoveAddHigher, + AddHigher + }; + + void set_layer_model (LayerModel); + LayerModel get_layer_model () const { return layer_model; } + + sigc::signal<void> LayerModelChanged; + + void set_xfade_model (CrossfadeModel); + CrossfadeModel get_xfade_model () const { return xfade_model; } + + void set_align_style (AlignStyle); + AlignStyle get_align_style () const { return align_style; } + + void add_event (jack_nframes_t action_frame, Event::Type type, jack_nframes_t target_frame = 0); + void remove_event (jack_nframes_t frame, Event::Type type); + void clear_events (Event::Type type); + + jack_nframes_t get_block_size() const { return current_block_size; } + jack_nframes_t worst_output_latency () const { return _worst_output_latency; } + jack_nframes_t worst_input_latency () const { return _worst_input_latency; } + jack_nframes_t worst_track_latency () const { return _worst_track_latency; } + + int save_state (string snapshot_name, bool pending = false); + int restore_state (string snapshot_name); + int save_template (string template_name); + + static int rename_template (string old_name, string new_name); + + static int delete_template (string name); + + sigc::signal<void,string> StateSaved; + sigc::signal<void> StateReady; + + vector<string*>* possible_states() const; + static vector<string*>* possible_states(string path); + + XMLNode& get_state(); + int set_state(const XMLNode& node); + XMLNode& get_template(); + + void add_instant_xml (XMLNode&, const std::string& dir); + + void swap_configuration(Configuration** new_config); + void copy_configuration(Configuration* new_config); + + enum StateOfTheState { + Clean = 0x0, + Dirty = 0x1, + CannotSave = 0x2, + Deletion = 0x4, + InitialConnecting = 0x8, + Loading = 0x10, + InCleanup = 0x20 + }; + + StateOfTheState state_of_the_state() const { return _state_of_the_state; } + + RouteGroup* add_edit_group (string); + RouteGroup* add_mix_group (string); + + RouteGroup *mix_group_by_name (string); + RouteGroup *edit_group_by_name (string); + + sigc::signal<void,RouteGroup*> edit_group_added; + sigc::signal<void,RouteGroup*> mix_group_added; + + template<class T> void foreach_edit_group (T *obj, void (T::*func)(RouteGroup *)) { + list<RouteGroup *>::iterator i; + for (i = edit_groups.begin(); i != edit_groups.end(); i++) { + (obj->*func)(*i); + } + } + + template<class T> void foreach_mix_group (T *obj, void (T::*func)(RouteGroup *)) { + list<RouteGroup *>::iterator i; + for (i = mix_groups.begin(); i != mix_groups.end(); i++) { + (obj->*func)(*i); + } + } + + /* fundamental operations. duh. */ + + + AudioTrack *new_audio_track (int input_channels, int output_channels); + + Route *new_audio_route (int input_channels, int output_channels); + + void remove_route (Route&); + void resort_routes (void *src); + + AudioEngine &engine() { return _engine; }; + + /* configuration. there should really be accessors/mutators + for these + */ + + float meter_hold () { return _meter_hold; } + void set_meter_hold (float); + sigc::signal<void> MeterHoldChanged; + + float meter_falloff () { return _meter_falloff; } + void set_meter_falloff (float); + sigc::signal<void> MeterFalloffChanged; + + int32_t max_level; + int32_t min_level; + string click_emphasis_sound; + string click_sound; + bool click_requested; + jack_nframes_t over_length_short; + jack_nframes_t over_length_long; + bool send_midi_timecode; + bool send_midi_machine_control; + float shuttle_speed_factor; + float shuttle_speed_threshold; + float rf_speed; + float smpte_frames_per_second; + bool smpte_drop_frames; + AnyTime preroll; + AnyTime postroll; + + /* Time */ + + jack_nframes_t transport_frame () const {return _transport_frame; } + jack_nframes_t audible_frame () const; + + int set_smpte_type (float fps, bool drop_frames); + + void bbt_time (jack_nframes_t when, BBT_Time&); + + ARDOUR::smpte_wrap_t smpte_increment( SMPTE_Time& smpte ) const; + ARDOUR::smpte_wrap_t smpte_decrement( SMPTE_Time& smpte ) const; + ARDOUR::smpte_wrap_t smpte_increment_subframes( SMPTE_Time& smpte ) const; + ARDOUR::smpte_wrap_t smpte_decrement_subframes( SMPTE_Time& smpte ) const; + ARDOUR::smpte_wrap_t smpte_increment_seconds( SMPTE_Time& smpte ) const; + ARDOUR::smpte_wrap_t smpte_increment_minutes( SMPTE_Time& smpte ) const; + ARDOUR::smpte_wrap_t smpte_increment_hours( SMPTE_Time& smpte ) const; + void smpte_frames_floor( SMPTE_Time& smpte ) const; + void smpte_seconds_floor( SMPTE_Time& smpte ) const; + void smpte_minutes_floor( SMPTE_Time& smpte ) const; + void smpte_hours_floor( SMPTE_Time& smpte ) const; + void smpte_to_sample( SMPTE_Time& smpte, jack_nframes_t& sample, bool use_offset, bool use_subframes ) const; + void sample_to_smpte( jack_nframes_t sample, SMPTE_Time& smpte, bool use_offset, bool use_subframes ) const; + void smpte_time (SMPTE_Time &); + void smpte_time (jack_nframes_t when, SMPTE_Time&); + void smpte_time_subframes (jack_nframes_t when, SMPTE_Time&); + + void smpte_duration (jack_nframes_t, SMPTE_Time&) const; + void smpte_duration_string (char *, jack_nframes_t) const; + + void set_smpte_offset (jack_nframes_t); + jack_nframes_t smpte_offset () const { return _smpte_offset; } + void set_smpte_offset_negative (bool); + bool smpte_offset_negative () const { return _smpte_offset_negative; } + + jack_nframes_t convert_to_frames_at (jack_nframes_t position, AnyTime&); + + sigc::signal<void> SMPTEOffsetChanged; + sigc::signal<void> SMPTETypeChanged; + + void request_slave_source (SlaveSource, jack_nframes_t pos = 0); + SlaveSource slave_source() const { return _slave_type; } + bool synced_to_jack() const { return _slave_type == JACK; } + float transport_speed() const { return _transport_speed; } + bool transport_stopped() const { return _transport_speed == 0.0f; } + bool transport_rolling() const { return _transport_speed != 0.0f; } + + int jack_slave_sync (jack_nframes_t); + + TempoMap& tempo_map() { return *_tempo_map; } + + /* region info */ + + sigc::signal<void,AudioRegion *> AudioRegionAdded; + sigc::signal<void,AudioRegion *> AudioRegionRemoved; + + int region_name (string& result, string base = string(""), bool newlevel = false) const; + string new_region_name (string); + string path_from_region_name (string name, string identifier); + + AudioRegion* find_whole_file_parent (AudioRegion&); + void find_equivalent_playlist_regions (AudioRegion&, std::vector<AudioRegion*>& result); + + AudioRegion *XMLRegionFactory (const XMLNode&, bool full); + + template<class T> void foreach_audio_region (T *obj, void (T::*func)(AudioRegion *)); + + /* source management */ + + struct import_status : public InterThreadInfo { + string doing_what; + + /* control info */ + bool multichan; + bool sample_convert; + volatile bool freeze; + string pathname; + }; + + int import_audiofile (import_status&); + bool sample_rate_convert (import_status&, string infile, string& outfile); + string build_tmp_convert_name (string file); + + Session::SlaveSource post_export_slave; + jack_nframes_t post_export_position; + + int start_audio_export (ARDOUR::AudioExportSpecification&); + int stop_audio_export (ARDOUR::AudioExportSpecification&); + + void add_source (Source *); + int remove_file_source (FileSource&); + + struct cleanup_report { + vector<string> paths; + int32_t space; + }; + + int cleanup_sources (cleanup_report&); + int cleanup_trash_sources (cleanup_report&); + + int destroy_region (Region*); + int destroy_regions (list<Region*>); + + int remove_last_capture (); + + /* handlers should return -1 for "stop cleanup", 0 for + "yes, delete this playlist" and 1 for "no, don't delete + this playlist. + */ + + sigc::signal<int,ARDOUR::Playlist*> AskAboutPlaylistDeletion; + + + /* handlers should return !0 for use pending state, 0 for + ignore it. + */ + + static sigc::signal<int> AskAboutPendingState; + + sigc::signal<void,Source *> SourceAdded; + sigc::signal<void,Source *> SourceRemoved; + + FileSource *create_file_source (ARDOUR::DiskStream&, int32_t chan); + Source *get_source (ARDOUR::id_t); + + /* playlist management */ + + Playlist* playlist_by_name (string name); + void add_playlist (Playlist *); + sigc::signal<void,Playlist*> PlaylistAdded; + sigc::signal<void,Playlist*> PlaylistRemoved; + + Playlist *get_playlist (string name); + + uint32_t n_playlists() const; + + template<class T> void foreach_playlist (T *obj, void (T::*func)(Playlist *)); + + /* named selections */ + + NamedSelection* named_selection_by_name (string name); + void add_named_selection (NamedSelection *); + void remove_named_selection (NamedSelection *); + + template<class T> void foreach_named_selection (T& obj, void (T::*func)(NamedSelection&)); + sigc::signal<void> NamedSelectionAdded; + sigc::signal<void> NamedSelectionRemoved; + + /* fade curves */ + + float get_default_fade_length () const { return default_fade_msecs; } + float get_default_fade_steepness () const { return default_fade_steepness; } + void set_default_fade (float steepness, float msecs); + + /* auditioning */ + + Auditioner& the_auditioner() { return *auditioner; } + void audition_playlist (); + void audition_region (AudioRegion&); + void cancel_audition (); + bool is_auditioning () const; + + sigc::signal<void,bool> AuditionActive; + + /* flattening stuff */ + + int write_one_track (AudioTrack&, jack_nframes_t start, jack_nframes_t cnt, bool overwrite, vector<Source*>&, + InterThreadInfo& wot); + int freeze (InterThreadInfo&); + + /* session-wide solo/mute/rec-enable */ + + enum SoloModel { + InverseMute, + SoloBus + }; + + bool soloing() const { return currently_soloing; } + + SoloModel solo_model() const { return _solo_model; } + void set_solo_model (SoloModel); + + bool solo_latched() const { return _solo_latched; } + void set_solo_latched (bool yn); + + void set_all_solo (bool); + void set_all_mute (bool); + + sigc::signal<void,bool> SoloActive; + + void record_disenable_all (); + void record_enable_all (); + + /* control/master out */ + + IO* control_out() const { return _control_out; } + IO* master_out() const { return _master_out; } + + /* insert/send management */ + + uint32_t n_port_inserts() const { return _port_inserts.size(); } + uint32_t n_plugin_inserts() const { return _plugin_inserts.size(); } + uint32_t n_sends() const { return _sends.size(); } + + string next_send_name(); + string next_insert_name(); + + /* s/w "RAID" management */ + + jack_nframes_t available_capture_duration(); + + /* I/O Connections */ + + template<class T> void foreach_connection (T *obj, void (T::*func)(Connection *)); + void add_connection (Connection *); + void remove_connection (Connection *); + Connection *connection_by_name (string) const; + + sigc::signal<void,Connection *> ConnectionAdded; + sigc::signal<void,Connection *> ConnectionRemoved; + + /* MIDI */ + + int set_mtc_port (string port_tag); + int set_mmc_port (string port_tag); + int set_midi_port (string port_tag); + MIDI::Port *mtc_port() const { return _mtc_port; } + MIDI::Port *mmc_port() const { return _mmc_port; } + MIDI::Port *midi_port() const { return _midi_port; } + + sigc::signal<void> MTC_PortChanged; + sigc::signal<void> MMC_PortChanged; + sigc::signal<void> MIDI_PortChanged; + + void set_trace_midi_input (bool, MIDI::Port* port = 0); + void set_trace_midi_output (bool, MIDI::Port* port = 0); + + bool get_trace_midi_input(MIDI::Port *port = 0); + bool get_trace_midi_output(MIDI::Port *port = 0); + + void send_midi_message (MIDI::Port * port, MIDI::eventType ev, MIDI::channel_t, MIDI::EventTwoBytes); + void send_all_midi_feedback (); + + void deliver_midi (MIDI::Port*, MIDI::byte*, int32_t size); + + /* Scrubbing */ + + void start_scrub (jack_nframes_t where); + void stop_scrub (); + void set_scrub_speed (float); + jack_nframes_t scrub_buffer_size() const; + sigc::signal<void> ScrubReady; + + /* History (for editors, mixers, UIs etc.) */ + + void undo (uint32_t n) { + history.undo (n); + } + void redo (uint32_t n) { + history.redo (n); + } + + uint32_t undo_depth() const { return history.undo_depth(); } + uint32_t redo_depth() const { return history.redo_depth(); } + 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 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); + } + + 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); + + /* edit mode */ + + void set_edit_mode (EditMode); + EditMode get_edit_mode () const { return _edit_mode; } + + /* clicking */ + + IO& click_io() { return *_click_io; } + void set_clicking (bool yn); + bool get_clicking() const; + + void set_click_sound (string path); + void set_click_emphasis_sound (string path); + + /* tempo FX */ + + struct TimeStretchRequest { + ARDOUR::AudioRegion* region; + float fraction; /* session: read ; GUI: write */ + float progress; /* session: write ; GUI: read */ + bool running; /* read/write */ + bool quick_seek; /* GUI: write */ + bool antialias; /* GUI: write */ + + TimeStretchRequest () : region (0) {} + }; + + AudioRegion* tempoize_region (TimeStretchRequest&); + + string raid_path() const; + void set_raid_path(string); + + /* need to call this whenever we change native file formats */ + + void reset_native_file_format(); + + /* disk, buffer loads */ + + uint32_t playback_load (); + uint32_t capture_load (); + uint32_t playback_load_min (); + uint32_t capture_load_min (); + + void reset_playback_load_min (); + void reset_capture_load_min (); + + float read_data_rate () const; + float write_data_rate () const; + + /* ranges */ + + void set_audio_range (list<AudioRange>&); + void set_music_range (list<MusicRange>&); + + void request_play_range (bool yn); + bool get_play_range () const { return _play_range; } + + /* favorite dirs */ + typedef vector<string> FavoriteDirs; + + static int read_favorite_dirs (FavoriteDirs&); + + static int write_favorite_dirs (FavoriteDirs&); + + /* file suffixes */ + + static const char* template_suffix() { return _template_suffix; } + static const char* statefile_suffix() { return _statefile_suffix; } + static const char* pending_suffix() { return _pending_suffix; } + + /* buffers for gain and pan */ + + gain_t* gain_automation_buffer () const { return _gain_automation_buffer; } + pan_t** pan_automation_buffer() const { return _pan_automation_buffer; } + + /* VST support */ + + static long vst_callback (AEffect* effect, + long opcode, + long index, + long value, + void* ptr, + float opt); + + typedef float (*compute_peak_t) (Sample *, jack_nframes_t, float); + typedef void (*apply_gain_to_buffer_t) (Sample *, jack_nframes_t, float); + typedef void (*mix_buffers_with_gain_t) (Sample *, Sample *, jack_nframes_t, float); + typedef void (*mix_buffers_no_gain_t) (Sample *, Sample *, jack_nframes_t); + + static compute_peak_t compute_peak; + static apply_gain_to_buffer_t apply_gain_to_buffer; + static mix_buffers_with_gain_t mix_buffers_with_gain; + static mix_buffers_no_gain_t mix_buffers_no_gain; + + protected: + friend class AudioEngine; + void set_block_size (jack_nframes_t nframes); + void set_frame_rate (jack_nframes_t nframes); + + protected: + friend class DiskStream; + void stop_butler (); + void wait_till_butler_finished(); + + protected: + friend class Route; + void schedule_curve_reallocation (); + void update_latency_compensation (bool, bool); + + private: + int create (bool& new_session, string* mix_template, jack_nframes_t initial_length); + + static const char* _template_suffix; + static const char* _statefile_suffix; + static const char* _pending_suffix; + + enum SubState { + PendingDeclickIn = 0x1, + PendingDeclickOut = 0x2, + StopPendingCapture = 0x4, + AutoReturning = 0x10, + PendingLocate = 0x20, + PendingSetLoop = 0x40 + }; + + /* stuff used in process() should be close together to + maximise cache hits + */ + + typedef void (Session::*process_function_type)(jack_nframes_t); + + AudioEngine &_engine; + atomic_t processing_prohibited; + process_function_type process_function; + process_function_type last_process_function; + jack_nframes_t _current_frame_rate; + int transport_sub_state; + atomic_t _record_status; + jack_nframes_t _transport_frame; + Location* end_location; + Slave *_slave; + SlaveSource _slave_type; + float _transport_speed; + volatile float _desired_transport_speed; + float _last_transport_speed; + jack_nframes_t _last_slave_transport_frame; + jack_nframes_t maximum_output_latency; + jack_nframes_t last_stop_frame; + vector<Sample *> _passthru_buffers; + vector<Sample *> _silent_buffers; + jack_nframes_t current_block_size; + jack_nframes_t _worst_output_latency; + jack_nframes_t _worst_input_latency; + jack_nframes_t _worst_track_latency; + bool _have_captured; + float _meter_hold; + float _meter_falloff; + bool _end_location_is_free; + + void set_worst_io_latencies (bool take_lock); + void set_worst_io_latencies_x (IOChange asifwecare, void *ignored) { + set_worst_io_latencies (true); + } + + void update_latency_compensation_proxy (void* ignored); + + void ensure_passthru_buffers (uint32_t howmany); + + void process_scrub (jack_nframes_t); + void process_without_events (jack_nframes_t); + void process_with_events (jack_nframes_t); + void process_audition (jack_nframes_t); + int process_export (jack_nframes_t, ARDOUR::AudioExportSpecification*); + + /* slave tracking */ + + static const int delta_accumulator_size = 25; + int delta_accumulator_cnt; + long delta_accumulator[delta_accumulator_size]; + long average_slave_delta; + int average_dir; + bool have_first_delta_accumulator; + + enum SlaveState { + Stopped, + Waiting, + Running + }; + + SlaveState slave_state; + jack_nframes_t slave_wait_end; + + void reset_slave_state (); + bool follow_slave (jack_nframes_t, jack_nframes_t); + + bool _exporting; + int prepare_to_export (ARDOUR::AudioExportSpecification&); + + void prepare_diskstreams (); + void commit_diskstreams (jack_nframes_t, bool& session_requires_butler); + int process_routes (jack_nframes_t, jack_nframes_t); + int silent_process_routes (jack_nframes_t, jack_nframes_t); + + bool get_rec_monitors_input () { + if (actively_recording()) { + return true; + } else { + if (auto_input) { + return false; + } else { + return true; + } + } + } + + int get_transport_declick_required () { + + if (transport_sub_state & PendingDeclickIn) { + transport_sub_state &= ~PendingDeclickIn; + return 1; + } else if (transport_sub_state & PendingDeclickOut) { + return -1; + } else { + return 0; + } + } + + bool maybe_stop (jack_nframes_t limit) { + if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) { + stop_transport (); + return true; + } + return false; + } + + void check_declick_out (); + + MIDI::MachineControl* mmc; + MIDI::Port* _mmc_port; + MIDI::Port* _mtc_port; + MIDI::Port* _midi_port; + string _path; + string _name; + bool recording_plugins; + + /* toggles */ + + bool auto_play; + bool punch_in; + bool punch_out; + bool auto_loop; + bool seamless_loop; + bool loop_changing; + jack_nframes_t last_loopend; + bool auto_input; + bool crossfades_active; + bool all_safe; + bool auto_return; + bool monitor_in; + bool send_mtc; + bool send_mmc; + bool mmc_control; + bool midi_feedback; + bool midi_control; + + RingBuffer<Event*> pending_events; + + void hookup_io (); + void when_engine_running (); + sigc::connection first_time_running; + void graph_reordered (); + + string _current_snapshot_name; + + XMLTree* state_tree; + bool state_was_pending; + StateOfTheState _state_of_the_state; + + void auto_save(); + int load_options (const XMLNode&); + XMLNode& get_options () const; + int load_state (string snapshot_name); + + jack_nframes_t _last_roll_location; + jack_nframes_t _last_record_location; + bool pending_locate_roll; + jack_nframes_t pending_locate_frame; + + bool pending_locate_flush; + bool pending_abort; + bool pending_auto_loop; + + Sample* butler_mixdown_buffer; + float* butler_gain_buffer; + pthread_t butler_thread; + PBD::NonBlockingLock butler_request_lock; + pthread_cond_t butler_paused; + bool butler_should_run; + atomic_t butler_should_do_transport_work; + int butler_request_pipe[2]; + + struct ButlerRequest { + enum Type { + Wake, + Run, + Pause, + Quit + }; + }; + + enum PostTransportWork { + PostTransportStop = 0x1, + PostTransportDisableRecord = 0x2, + PostTransportPosition = 0x8, + PostTransportDidRecord = 0x20, + PostTransportDuration = 0x40, + PostTransportLocate = 0x80, + PostTransportRoll = 0x200, + PostTransportAbort = 0x800, + PostTransportOverWrite = 0x1000, + PostTransportSpeed = 0x2000, + PostTransportAudition = 0x4000, + PostTransportScrub = 0x8000, + PostTransportReverse = 0x10000, + PostTransportInputChange = 0x20000, + PostTransportCurveRealloc = 0x40000 + }; + + static const PostTransportWork ProcessCannotProceedMask = + PostTransportWork (PostTransportInputChange| + PostTransportSpeed| + PostTransportReverse| + PostTransportCurveRealloc| + PostTransportScrub| + PostTransportAudition| + PostTransportLocate| + PostTransportStop); + + PostTransportWork post_transport_work; + + void summon_butler (); + void schedule_butler_transport_work (); + int start_butler_thread (); + void terminate_butler_thread (); + static void *_butler_thread_work (void *arg); + void* butler_thread_work (); + + uint32_t cumulative_rf_motion; + uint32_t rf_scale; + + void set_rf_speed (float speed); + void reset_rf_scale (jack_nframes_t frames_moved); + + Locations _locations; + void locations_changed (); + void locations_added (Location*); + void handle_locations_changed (Locations::LocationList&); + + sigc::connection auto_punch_start_changed_connection; + sigc::connection auto_punch_end_changed_connection; + sigc::connection auto_punch_changed_connection; + void auto_punch_start_changed (Location *); + void auto_punch_end_changed (Location *); + void auto_punch_changed (Location *); + + sigc::connection auto_loop_start_changed_connection; + sigc::connection auto_loop_end_changed_connection; + sigc::connection auto_loop_changed_connection; + void auto_loop_changed (Location *); + + typedef list<Event *> Events; + Events events; + Events immediate_events; + Events::iterator next_event; + + /* there can only ever be one of each of these */ + + Event *auto_loop_event; + Event *punch_out_event; + Event *punch_in_event; + + /* events */ + + void dump_events () const; + void queue_event (Event *ev); + void merge_event (Event*); + void replace_event (Event::Type, jack_nframes_t action_frame, jack_nframes_t target = 0); + bool _replace_event (Event*); + bool _remove_event (Event *); + void _clear_event_type (Event::Type); + + void first_stage_init (string path, string snapshot_name); + int second_stage_init (bool new_tracks); + void find_current_end (); + void remove_empty_sounds (); + + void setup_midi_control (); + int midi_read (MIDI::Port *); + + void enable_record (); + + void increment_transport_position (uint32_t val) { + if (max_frames - val < _transport_frame) { + _transport_frame = max_frames; + } else { + _transport_frame += val; + } + } + + void decrement_transport_position (uint32_t val) { + if (val < _transport_frame) { + _transport_frame -= val; + } else { + _transport_frame = 0; + } + } + + void post_transport_motion (); + static void *session_loader_thread (void *arg); + + void *do_work(); + + void set_next_event (); + void process_event (Event *); + + /* MIDI Machine Control */ + + void deliver_mmc (MIDI::MachineControl::Command, jack_nframes_t); + void deliver_midi_message (MIDI::Port * port, MIDI::eventType ev, MIDI::channel_t, MIDI::EventTwoBytes); + void deliver_data (MIDI::Port* port, MIDI::byte*, int32_t size); + + void spp_start (MIDI::Parser&); + void spp_continue (MIDI::Parser&); + void spp_stop (MIDI::Parser&); + + void mmc_deferred_play (MIDI::MachineControl &); + void mmc_stop (MIDI::MachineControl &); + void mmc_step (MIDI::MachineControl &, int); + void mmc_pause (MIDI::MachineControl &); + void mmc_record_pause (MIDI::MachineControl &); + void mmc_record_strobe (MIDI::MachineControl &); + void mmc_record_exit (MIDI::MachineControl &); + void mmc_track_record_status (MIDI::MachineControl &, + uint32_t track, bool enabled); + void mmc_fast_forward (MIDI::MachineControl &); + void mmc_rewind (MIDI::MachineControl &); + void mmc_locate (MIDI::MachineControl &, const MIDI::byte *); + void mmc_shuttle (MIDI::MachineControl &mmc, float speed, bool forw); + void mmc_record_enable (MIDI::MachineControl &mmc, size_t track, bool enabled); + + struct timeval last_mmc_step; + double step_speed; + + typedef sigc::slot<bool> MidiTimeoutCallback; + typedef list<MidiTimeoutCallback> MidiTimeoutList; + + MidiTimeoutList midi_timeouts; + bool mmc_step_timeout (); + + MIDI::byte mmc_buffer[32]; + MIDI::byte mtc_msg[16]; + MIDI::byte mtc_smpte_bits; /* encoding of SMTPE type for MTC */ + MIDI::byte midi_msg[16]; + jack_nframes_t outbound_mtc_smpte_frame; + SMPTE_Time transmitting_smpte_time; + int next_quarter_frame_to_send; + + double _frames_per_smpte_frame; /* has to be floating point because of drop frame */ + jack_nframes_t _frames_per_hour; + jack_nframes_t _smpte_frames_per_hour; + jack_nframes_t _smpte_offset; + bool _smpte_offset_negative; + + /* cache the most-recently requested time conversions. + this helps when we have multiple clocks showing the + same time (e.g. the transport frame) + */ + + bool last_smpte_valid; + jack_nframes_t last_smpte_when; + SMPTE_Time last_smpte; + + int send_full_time_code (); + int send_midi_time_code (); + + void send_full_time_code_in_another_thread (); + void send_midi_time_code_in_another_thread (); + void send_time_code_in_another_thread (bool full); + void send_mmc_in_another_thread (MIDI::MachineControl::Command, jack_nframes_t frame = 0); + + /* Feedback */ + + typedef sigc::slot<int> FeedbackFunctionPtr; + static void* _feedback_thread_work (void *); + void* feedback_thread_work (); + int feedback_generic_midi_function (); + std::list<FeedbackFunctionPtr> feedback_functions; + int active_feedback; + int feedback_request_pipe[2]; + pthread_t feedback_thread; + + struct FeedbackRequest { + enum Type { + Start, + Stop, + Quit + }; + }; + + int init_feedback(); + int start_feedback (); + int stop_feedback (); + void terminate_feedback (); + int poke_feedback (FeedbackRequest::Type); + + jack_nframes_t adjust_apparent_position (jack_nframes_t frames); + + void reset_record_status (); + + int no_roll (jack_nframes_t nframes, jack_nframes_t offset); + + bool non_realtime_work_pending() const { return static_cast<bool>(post_transport_work); } + bool process_can_proceed() const { return !(post_transport_work & ProcessCannotProceedMask); } + + struct MIDIRequest { + + enum Type { + SendFullMTC, + SendMTC, + SendMMC, + PortChange, + SendMessage, + Deliver, + Quit + }; + + Type type; + MIDI::MachineControl::Command mmc_cmd; + jack_nframes_t locate_frame; + + // for SendMessage type + + MIDI::Port * port; + MIDI::channel_t chan; + union { + MIDI::EventTwoBytes data; + MIDI::byte* buf; + }; + + union { + MIDI::eventType ev; + int32_t size; + }; + + MIDIRequest () {} + + void *operator new(size_t ignored) { + return pool.alloc (); + }; + + void operator delete(void *ptr, size_t size) { + pool.release (ptr); + } + + private: + static MultiAllocSingleReleasePool pool; + }; + + PBD::Lock midi_lock; + pthread_t midi_thread; + int midi_request_pipe[2]; + atomic_t butler_active; + RingBuffer<MIDIRequest*> midi_requests; + + int start_midi_thread (); + void terminate_midi_thread (); + void poke_midi_thread (); + static void *_midi_thread_work (void *arg); + void midi_thread_work (); + void change_midi_ports (); + int use_config_midi_ports (); + + bool waiting_to_start; + + void set_auto_loop (bool yn); + void overwrite_some_buffers (DiskStream*); + void flush_all_redirects (); + void locate (jack_nframes_t, bool with_roll, bool with_flush, bool with_loop=false); + void start_locate (jack_nframes_t, bool with_roll, bool with_flush, bool with_loop=false); + void force_locate (jack_nframes_t frame, bool with_roll = false); + void set_diskstream_speed (DiskStream*, float speed); + void set_transport_speed (float speed, bool abort = false); + void stop_transport (bool abort = false); + void start_transport (); + void actually_start_transport (); + void realtime_stop (bool abort); + void non_realtime_start_scrub (); + void non_realtime_set_speed (); + void non_realtime_stop (bool abort); + void non_realtime_overwrite (); + void non_realtime_buffer_fill (); + void butler_transport_work (); + void post_transport (); + void engine_halted (); + void xrun_recovery (); + + TempoMap *_tempo_map; + void tempo_map_changed (Change); + + /* edit/mix groups */ + + int load_route_groups (const XMLNode&, bool is_edit); + int load_edit_groups (const XMLNode&); + int load_mix_groups (const XMLNode&); + + + list<RouteGroup *> edit_groups; + list<RouteGroup *> mix_groups; + + /* disk-streams */ + + DiskStreamList diskstreams; + mutable PBD::Lock diskstream_lock; + uint32_t dstream_buffer_size; + void add_diskstream (DiskStream*); + int load_diskstreams (const XMLNode&); + + /* routes stuff */ + + RouteList routes; + mutable PBD::NonBlockingLock route_lock; + void add_route (Route*); + + int load_routes (const XMLNode&); + Route* XMLRouteFactory (const XMLNode&); + + /* mixer stuff */ + + bool _solo_latched; + SoloModel _solo_model; + bool solo_update_disabled; + bool currently_soloing; + + void route_mute_changed (void *src); + void route_solo_changed (void *src, Route *); + void catch_up_on_solo (); + void update_route_solo_state (); + void modify_solo_mute (bool, bool); + void strip_portname_for_solo (string& portname); + + /* REGION MANAGEMENT */ + + mutable PBD::Lock region_lock; + typedef map<ARDOUR::id_t,AudioRegion *> AudioRegionList; + AudioRegionList audio_regions; + + void region_renamed (Region *); + void region_changed (Change, Region *); + void add_region (Region *); + void remove_region (Region *); + + int load_regions (const XMLNode& node); + + /* SOURCES */ + + mutable PBD::Lock source_lock; + typedef std::map<id_t, Source *> SourceList; + + SourceList sources; + + int load_sources (const XMLNode& node); + XMLNode& get_sources_as_xml (); + + void remove_source (Source *); + + Source *XMLSourceFactory (const XMLNode&); + + /* PLAYLISTS */ + + mutable PBD::Lock playlist_lock; + typedef set<Playlist *> PlaylistList; + PlaylistList playlists; + PlaylistList unused_playlists; + + int load_playlists (const XMLNode&); + int load_unused_playlists (const XMLNode&); + void remove_playlist (Playlist *); + void track_playlist (Playlist *, bool); + + Playlist *playlist_factory (string name); + Playlist *XMLPlaylistFactory (const XMLNode&); + + void playlist_length_changed (Playlist *); + void diskstream_playlist_changed (DiskStream *); + + /* NAMED SELECTIONS */ + + mutable PBD::Lock named_selection_lock; + typedef set<NamedSelection *> NamedSelectionList; + NamedSelectionList named_selections; + + int load_named_selections (const XMLNode&); + + NamedSelection *named_selection_factory (string name); + NamedSelection *XMLNamedSelectionFactory (const XMLNode&); + + /* DEFAULT FADE CURVES */ + + float default_fade_steepness; + float default_fade_msecs; + + /* AUDITIONING */ + + Auditioner *auditioner; + void set_audition (AudioRegion*); + void non_realtime_set_audition (); + AudioRegion *pending_audition_region; + + /* EXPORT */ + + /* FLATTEN */ + + int flatten_one_track (AudioTrack&, jack_nframes_t start, jack_nframes_t cnt); + + /* INSERT AND SEND MANAGEMENT */ + + slist<PortInsert *> _port_inserts; + slist<PluginInsert *> _plugin_inserts; + slist<Send *> _sends; + uint32_t send_cnt; + uint32_t insert_cnt; + + void add_redirect (Redirect *); + void remove_redirect (Redirect *); + + /* S/W RAID */ + + struct space_and_path { + uint32_t blocks; /* 4kB blocks */ + string path; + + space_and_path() { + blocks = 0; + } + }; + + struct space_and_path_ascending_cmp { + bool operator() (space_and_path a, space_and_path b) { + return a.blocks > b.blocks; + } + }; + + void setup_raid_path (string path); + + vector<space_and_path> session_dirs; + vector<space_and_path>::iterator last_rr_session_dir; + uint32_t _total_free_4k_blocks; + PBD::Lock space_lock; + + static const char* sound_dir_name; + static const char* dead_sound_dir_name; + static const char* peak_dir_name; + + string discover_best_sound_dir (); + int ensure_sound_dir (string, string&); + void refresh_disk_space (); + + atomic_t _playback_load; + atomic_t _capture_load; + atomic_t _playback_load_min; + atomic_t _capture_load_min; + + /* I/O Connections */ + + typedef list<Connection *> ConnectionList; + mutable PBD::Lock connection_lock; + ConnectionList _connections; + int load_connections (const XMLNode&); + + int set_slave_source (SlaveSource, jack_nframes_t); + + void reverse_diskstream_buffers (); + + UndoHistory history; + UndoCommand current_cmd; + + GlobalRouteBooleanState get_global_route_boolean (bool (Route::*method)(void) const); + GlobalRouteMeterState get_global_route_metering (); + + void set_global_route_boolean (GlobalRouteBooleanState s, void (Route::*method)(bool, void*), void *arg); + void set_global_route_metering (GlobalRouteMeterState s, void *arg); + + void set_global_mute (GlobalRouteBooleanState s, void *src); + void set_global_solo (GlobalRouteBooleanState s, void *src); + void set_global_record_enable (GlobalRouteBooleanState s, void *src); + + void jack_timebase_callback (jack_transport_state_t, jack_nframes_t, jack_position_t*, int); + int jack_sync_callback (jack_transport_state_t, jack_position_t*); + void record_enable_change_all (bool yn); + + XMLNode& state(bool); + + /* click track */ + + struct Click { + jack_nframes_t start; + jack_nframes_t duration; + jack_nframes_t offset; + const Sample *data; + + Click (jack_nframes_t s, jack_nframes_t d, const Sample *b) + : start (s), duration (d), data (b) { offset = 0; } + + void *operator new(size_t ignored) { + return pool.alloc (); + }; + + void operator delete(void *ptr, size_t size) { + pool.release (ptr); + } + + private: + static Pool pool; + }; + + typedef list<Click*> Clicks; + + Clicks clicks; + bool _clicking; + IO* _click_io; + Sample* click_data; + Sample* click_emphasis_data; + jack_nframes_t click_length; + jack_nframes_t click_emphasis_length; + + static const Sample default_click[]; + static const jack_nframes_t default_click_length; + static const Sample default_click_emphasis[]; + static const jack_nframes_t default_click_emphasis_length; + + Click *get_click(); + void setup_click_sounds (int which); + void clear_clicks (); + void click (jack_nframes_t start, jack_nframes_t nframes, jack_nframes_t offset); + + vector<Route*> master_outs; + + EditMode _edit_mode; + EditMode pending_edit_mode; + + /* range playback */ + + list<AudioRange> current_audio_range; + bool _play_range; + void set_play_range (bool yn); + void setup_auto_play (); + + /* main outs */ + uint32_t main_outs; + + IO* _master_out; + IO* _control_out; + + AutoConnectOption input_auto_connect; + AutoConnectOption output_auto_connect; + + AlignStyle align_style; + + gain_t* _gain_automation_buffer; + pan_t** _pan_automation_buffer; + void allocate_pan_automation_buffers (jack_nframes_t nframes, uint32_t howmany, bool force); + uint32_t _npan_buffers; + + /* VST support */ + + long _vst_callback (VSTPlugin*, + long opcode, + long index, + long value, + void* ptr, + float opt); + + /* number of hardware audio ports we're using, + based on max (requested,available) + */ + + uint32_t n_physical_outputs; + uint32_t n_physical_inputs; + + void remove_pending_capture_state (); + + 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); + + LayerModel layer_model; + CrossfadeModel xfade_model; +}; + +}; /* namespace ARDOUR */ + +#endif /* __ardour_session_h__ */ diff --git a/libs/ardour/ardour/session_connection.h b/libs/ardour/ardour/session_connection.h new file mode 100644 index 0000000000..caa20ed387 --- /dev/null +++ b/libs/ardour/ardour/session_connection.h @@ -0,0 +1,40 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_session_connection_h__ +#define __ardour_session_connection_h__ + +#include <ardour/session.h> +#include <ardour/connection.h> + +namespace ARDOUR { + +template<class T> void +Session::foreach_connection (T *obj, void (T::*func)(Connection *)) +{ + LockMonitor lm (connection_lock, __LINE__, __FILE__); + for (ConnectionList::iterator i = _connections.begin(); i != _connections.end(); i++) { + (obj->*func) (*i); + } +} + +} /* namespace */ + +#endif /* __ardour_session_connection_h__ */ diff --git a/libs/ardour/ardour/session_diskstream.h b/libs/ardour/ardour/session_diskstream.h new file mode 100644 index 0000000000..55c79f549f --- /dev/null +++ b/libs/ardour/ardour/session_diskstream.h @@ -0,0 +1,42 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_session_diskstream_h__ +#define __ardour_session_diskstream_h__ + +#include <ardour/session.h> +#include <ardour/diskstream.h> + +namespace ARDOUR { + +template<class T> void +Session::foreach_diskstream (T *obj, void (T::*func)(DiskStream&)) +{ + LockMonitor lm (diskstream_lock, __LINE__, __FILE__); + for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); i++) { + if (!(*i)->hidden()) { + (obj->*func) (**i); + } + } +} + +} /* namespace */ + +#endif /* __ardour_session_diskstream_h__ */ diff --git a/libs/ardour/ardour/session_playlist.h b/libs/ardour/ardour/session_playlist.h new file mode 100644 index 0000000000..925a60182a --- /dev/null +++ b/libs/ardour/ardour/session_playlist.h @@ -0,0 +1,47 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_session_playlist_h__ +#define __ardour_session_playlist_h__ + +#include <ardour/session.h> +#include <ardour/playlist.h> + +namespace ARDOUR { + +template<class T> void +Session::foreach_playlist (T *obj, void (T::*func)(Playlist *)) +{ + LockMonitor lm (playlist_lock, __LINE__, __FILE__); + for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); i++) { + if (!(*i)->hidden()) { + (obj->*func) (*i); + } + } + for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); i++) { + if (!(*i)->hidden()) { + (obj->*func) (*i); + } + } +} + +} /* namespace */ + +#endif /* __ardour_session_playlist_h__ */ diff --git a/libs/ardour/ardour/session_region.h b/libs/ardour/ardour/session_region.h new file mode 100644 index 0000000000..16580d8e73 --- /dev/null +++ b/libs/ardour/ardour/session_region.h @@ -0,0 +1,19 @@ +#ifndef __ardour_session_region_h__ +#define __ardour_session_region_h__ + +#include <ardour/session.h> +#include <ardour/audioregion.h> + +namespace ARDOUR { + +template<class T> void Session::foreach_audio_region (T *obj, void (T::*func)(AudioRegion *)) +{ + LockMonitor lm (region_lock, __LINE__, __FILE__); + for (AudioRegionList::iterator i = audio_regions.begin(); i != audio_regions.end(); i++) { + (obj->*func) ((*i).second); + } +} + +} + +#endif /* __ardour_session_region_h__ */ diff --git a/libs/ardour/ardour/session_route.h b/libs/ardour/ardour/session_route.h new file mode 100644 index 0000000000..0b126531dc --- /dev/null +++ b/libs/ardour/ardour/session_route.h @@ -0,0 +1,89 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_session_route_h__ +#define __ardour_session_route_h__ + +#include <iostream> + +#include <pbd/lockmonitor.h> +#include <ardour/session.h> +#include <ardour/route.h> + +namespace ARDOUR { + +template<class T> void +Session::foreach_route (T *obj, void (T::*func)(Route&)) +{ + RouteList public_order; + + { + LockMonitor lm (route_lock, __LINE__, __FILE__); + public_order = routes; + } + + RoutePublicOrderSorter cmp; + public_order.sort (cmp); + + for (RouteList::iterator i = public_order.begin(); i != public_order.end(); i++) { + (obj->*func) (**i); + } +} + +template<class T> void +Session::foreach_route (T *obj, void (T::*func)(Route*)) +{ + RouteList public_order; + + { + LockMonitor lm (route_lock, __LINE__, __FILE__); + public_order = routes; + } + + RoutePublicOrderSorter cmp; + public_order.sort (cmp); + + for (RouteList::iterator i = public_order.begin(); i != public_order.end(); i++) { + (obj->*func) (*i); + } +} + + +template<class T, class A> void +Session::foreach_route (T *obj, void (T::*func)(Route&, A), A arg1) +{ + RouteList public_order; + + { + LockMonitor lm (route_lock, __LINE__, __FILE__); + public_order = routes; + } + + RoutePublicOrderSorter cmp; + public_order.sort (cmp); + + for (RouteList::iterator i = public_order.begin(); i != public_order.end(); i++) { + (obj->*func) (**i, arg1); + } +} + +} /* namespace */ + +#endif /* __ardour_session_route_h__ */ diff --git a/libs/ardour/ardour/session_selection.h b/libs/ardour/ardour/session_selection.h new file mode 100644 index 0000000000..a1dd31d7ff --- /dev/null +++ b/libs/ardour/ardour/session_selection.h @@ -0,0 +1,40 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_session_named_selection_h__ +#define __ardour_session_named_selection_h__ + +#include <ardour/session.h> +#include <ardour/named_selection.h> + +namespace ARDOUR { + +template<class T> void +Session::foreach_named_selection (T& obj, void (T::*func)(NamedSelection&)) +{ + LockMonitor lm (named_selection_lock, __LINE__, __FILE__); + for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); i++) { + (obj.*func) (**i); + } +} + +} /* namespace */ + +#endif /* __ardour_session_named_selection_h__ */ diff --git a/libs/ardour/ardour/silentsource.h b/libs/ardour/ardour/silentsource.h new file mode 100644 index 0000000000..0079e5f103 --- /dev/null +++ b/libs/ardour/ardour/silentsource.h @@ -0,0 +1,56 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __playlist_const_buffer_h__ +#define __playlist_const_buffer_h__ + +#include <string> +#include <cstdlib> + +#include "source.h" + +namespace ARDOUR { + +class SilentSource : public Source { + public: + SilentSource () { + _name = "Silent Source"; + } + + static bool is_silent_source (const string& name) { + return name == "Silent Source"; + } + + jack_nframes_t length() { return ~0U; } + + jack_nframes_t read (Source::Data *dst, jack_nframes_t start, jack_nframes_t cnt) { + jack_nframes_t n = cnt; + while (n--) *dst++ = 0; + return cnt; + } + + void peak (guint8 *max, guint8 *min, jack_nframes_t start, jack_nframes_t cnt) { + *max = *min = 0; + } +}; + +} + +#endif /* __playlist_const_buffer_h__ */ diff --git a/libs/ardour/ardour/slave.h b/libs/ardour/ardour/slave.h new file mode 100644 index 0000000000..90e63aed83 --- /dev/null +++ b/libs/ardour/ardour/slave.h @@ -0,0 +1,151 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_slave_h__ +#define __ardour_slave_h__ + +#include <vector> + +#include <jack/jack.h> + +#include <pthread.h> +#include <sigc++/signal.h> +#include <ardour/ardour.h> +#include <midi++/parser.h> +#include <midi++/types.h> + +namespace MIDI { + class Port; +} + +namespace ARDOUR { +class Session; + +class Slave { + public: + Slave() { } + virtual ~Slave() {} + + virtual bool speed_and_position (float&, jack_nframes_t&) = 0; + virtual bool locked() const = 0; + virtual bool ok() const = 0; + virtual bool starting() const { return false; } + virtual jack_nframes_t resolution() const = 0; + virtual bool requires_seekahead () const = 0; +}; + + +class MTC_Slave : public Slave, public sigc::trackable { + public: + MTC_Slave (Session&, MIDI::Port&); + ~MTC_Slave (); + + void rebind (MIDI::Port&); + bool speed_and_position (float&, jack_nframes_t&); + + bool locked() const; + bool ok() const; + void handle_locate (const MIDI::byte*); + + jack_nframes_t resolution() const; + bool requires_seekahead () const { return true; } + + private: + Session& session; + MIDI::Port* port; + std::vector<sigc::connection> connections; + + struct SafeTime { + + + int guard1; + //SMPTE_Time mtc; + jack_nframes_t position; + jack_nframes_t timestamp; + int guard2; + + SafeTime() { + guard1 = 0; + guard2 = 0; + timestamp = 0; + } + }; + + SafeTime current; + jack_nframes_t mtc_frame; /* current time */ + jack_nframes_t last_inbound_frame; /* when we got it; audio clocked */ + + float mtc_speed; + jack_nframes_t first_mtc_frame; + jack_nframes_t first_mtc_time; + + static const int32_t accumulator_size = 128; + float accumulator[accumulator_size]; + int32_t accumulator_index; + bool have_first_accumulated_speed; + + void reset (); + void update_mtc_qtr (MIDI::Parser&); + void update_mtc_time (const MIDI::byte *, bool); + void update_mtc_status (MIDI::Parser::MTC_Status); + void read_current (SafeTime *) const; +}; + +class ADAT_Slave : public Slave +{ + public: + ADAT_Slave () {} + ~ADAT_Slave () {} + + bool speed_and_position (float& speed, jack_nframes_t& pos) { + speed = 0; + pos = 0; + return false; + } + + bool locked() const { return false; } + bool ok() const { return false; } + jack_nframes_t resolution() const { return 1; } + bool requires_seekahead () const { return true; } +}; + +class JACK_Slave : public Slave +{ + public: + JACK_Slave (jack_client_t*); + ~JACK_Slave (); + + bool speed_and_position (float& speed, jack_nframes_t& pos); + + bool starting() const { return _starting; } + bool locked() const; + bool ok() const; + jack_nframes_t resolution() const { return 1; } + bool requires_seekahead () const { return false; } + + private: + jack_client_t* jack; + float speed; + bool _starting; +}; + +} /* namespace */ + +#endif /* __ardour_slave_h__ */ diff --git a/libs/ardour/ardour/sndfile_helpers.h b/libs/ardour/ardour/sndfile_helpers.h new file mode 100644 index 0000000000..5bb4937410 --- /dev/null +++ b/libs/ardour/ardour/sndfile_helpers.h @@ -0,0 +1,37 @@ +#ifndef __sndfile_helpers_h__ +#define __sndfile_helpers_h__ + +#include <string> +#include <sndfile.h> + +using std::string; + +// Use this define when initializing arrarys for use in sndfile_*_format() +#define SNDFILE_STR_LENGTH 32 + +#define SNDFILE_HEADER_FORMATS 7 +extern const char * const sndfile_header_formats_strings[SNDFILE_HEADER_FORMATS+1]; + +extern int sndfile_header_formats[SNDFILE_HEADER_FORMATS]; + +#define SNDFILE_BITDEPTH_FORMATS 5 +extern const char * const sndfile_bitdepth_formats_strings[SNDFILE_BITDEPTH_FORMATS+1]; + +extern int sndfile_bitdepth_formats[SNDFILE_BITDEPTH_FORMATS]; + +#define SNDFILE_ENDIAN_FORMATS 2 +extern const char * const sndfile_endian_formats_strings[SNDFILE_ENDIAN_FORMATS+1]; + +extern int sndfile_endian_formats[SNDFILE_ENDIAN_FORMATS]; + +int sndfile_bitdepth_format_from_string(string); +int sndfile_header_format_from_string(string); +int sndfile_endian_format_from_string(string); + +int sndfile_data_width (int format); + +// It'd be nice if libsndfile did this for us +string sndfile_major_format(int); +string sndfile_minor_format(int); + +#endif /* __sndfile_helpers_h__ */ diff --git a/libs/ardour/ardour/sndfilesource.h b/libs/ardour/ardour/sndfilesource.h new file mode 100644 index 0000000000..7f9712b7ec --- /dev/null +++ b/libs/ardour/ardour/sndfilesource.h @@ -0,0 +1,63 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __playlist_snd_file_buffer_h__ +#define __playlist_snd_file_buffer_h__ + +#include <sndfile.h> + +#include <ardour/source.h> + +namespace ARDOUR { + +class SndFileSource : public Source { + public: + SndFileSource (const string& path_plus_channel, bool build_peak = true); + SndFileSource (const XMLNode&); + ~SndFileSource (); + + jack_nframes_t length() const { return _info.frames; } + jack_nframes_t read (Sample *dst, jack_nframes_t start, jack_nframes_t cnt) const; + void mark_for_remove() {} // we never remove external sndfiles + string peak_path(string audio_path); + string old_peak_path(string audio_path); + string path() const { return _path; } + + static void set_peak_dir (string dir) { peak_dir = dir; } + + private: + static string peak_dir; + + SNDFILE *sf; + SF_INFO _info; + uint16_t channel; + mutable float *tmpbuf; + mutable jack_nframes_t tmpbufsize; + mutable PBD::Lock _tmpbuf_lock; + string _path; + + void init (const string &str, bool build_peak); + jack_nframes_t read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_t cnt) const; +}; + +}; /* namespace EDL */ + +#endif /* __playlist_snd_file_buffer_h__ */ + diff --git a/libs/ardour/ardour/soundseq.h b/libs/ardour/ardour/soundseq.h new file mode 100644 index 0000000000..4a318e9750 --- /dev/null +++ b/libs/ardour/ardour/soundseq.h @@ -0,0 +1,54 @@ +/* + Copyright (C) 2001 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __soundseq_h__ +#define __soundseq_h__ + +#include "edl.h" + +namespace ARDOUR { + +typedef gint16 peak_datum; + +struct peak_data_t { + peak_datum min; + peak_datum max; +}; + +const uint32_t frames_per_peak = 2048; + +class Sound : public EDL::Piece { + public: + int peak (peak_data_t& pk, uint32_t start, uint32_t cnt); + int read_peaks (peak_data_t *, uint32_t npeaks, uint32_t start, uint32_t cnt); + int build_peak (uint32_t first_frame, uint32_t cnt); +}; + +class SoundPlaylist : public EDL::Playlist { + public: + int read_peaks (peak_data_t *, uint32_t npeaks, uint32_t start, uint32_t cnt); +}; + +} /* namespace ARDOUR */ + +#endif /* __soundseq_h__ */ + + + diff --git a/libs/ardour/ardour/source.h b/libs/ardour/ardour/source.h new file mode 100644 index 0000000000..a6138f8239 --- /dev/null +++ b/libs/ardour/ardour/source.h @@ -0,0 +1,182 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_source_h__ +#define __ardour_source_h__ + +#include <list> +#include <vector> +#include <string> + +#include <time.h> + +#include <sigc++/signal.h> + +#include <ardour/ardour.h> +#include <ardour/stateful.h> +#include <pbd/xml++.h> + +using std::list; +using std::vector; +using std::string; + +namespace ARDOUR { + +struct PeakData { + typedef Sample PeakDatum; + + PeakDatum min; + PeakDatum max; +}; + +const jack_nframes_t frames_per_peak = 256; + +class Source : public Stateful, public sigc::trackable +{ + public: + Source (bool announce=true); + Source (const XMLNode&); + virtual ~Source (); + + const string& name() const { return _name; } + ARDOUR::id_t id() const { return _id; } + + /* returns the number of items in this `source' */ + + virtual jack_nframes_t length() const { + return _length; + } + + virtual jack_nframes_t read (Sample *dst, jack_nframes_t start, jack_nframes_t cnt) const { + return 0; + } + + virtual jack_nframes_t write (Sample *src, jack_nframes_t cnt) { + return 0; + } + + uint32_t use_cnt() const { return _use_cnt; } + void use (); + void release (); + + virtual void mark_for_remove() = 0; + virtual void mark_streaming_write_completed () {} + + time_t timestamp() const { return _timestamp; } + void stamp (time_t when) { _timestamp = when; } + + void set_captured_for (string str) { _captured_for = str; } + string captured_for() const { return _captured_for; } + + uint32_t read_data_count() const { return _read_data_count; } + uint32_t write_data_count() const { return _write_data_count; } + + int read_peaks (PeakData *peaks, jack_nframes_t npeaks, jack_nframes_t start, jack_nframes_t cnt, double samples_per_unit) const; + int build_peaks (); + bool peaks_ready (sigc::slot<void>) const; + + static sigc::signal<void,Source*> SourceCreated; + + sigc::signal<void,Source *> GoingAway; + mutable sigc::signal<void> PeaksReady; + mutable sigc::signal<void,jack_nframes_t,jack_nframes_t> PeakRangeReady; + + XMLNode& get_state (); + int set_state (const XMLNode&); + + + static int start_peak_thread (); + static void stop_peak_thread (); + + static void set_build_missing_peakfiles (bool yn) { + _build_missing_peakfiles = yn; + } + static void set_build_peakfiles (bool yn) { + _build_peakfiles = yn; + } + + protected: + static bool _build_missing_peakfiles; + static bool _build_peakfiles; + + string _name; + uint32_t _use_cnt; + bool _peaks_built; + mutable PBD::Lock _lock; + jack_nframes_t _length; + bool next_peak_clear_should_notify; + string peakpath; + int peakfile; /* fd */ + time_t _timestamp; + string _captured_for; + + mutable uint32_t _read_data_count; // modified in read() + mutable uint32_t _write_data_count; // modified in write() + + int initialize_peakfile (bool newfile, string path); + void build_peaks_from_scratch (); + + int do_build_peak (jack_nframes_t, jack_nframes_t); + virtual jack_nframes_t read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_t cnt) const = 0; + virtual string peak_path(string audio_path) = 0; + virtual string old_peak_path(string audio_path) = 0; + + static pthread_t peak_thread; + static bool have_peak_thread; + static void* peak_thread_work(void*); + + static int peak_request_pipe[2]; + + struct PeakRequest { + enum Type { + Build, + Quit + }; + }; + + static vector<Source*> pending_peak_sources; + static PBD::Lock pending_peak_sources_lock; + + static void queue_for_peaks (Source&); + static void clear_queue_for_peaks (); + + struct PeakBuildRecord { + jack_nframes_t frame; + jack_nframes_t cnt; + + PeakBuildRecord (jack_nframes_t f, jack_nframes_t c) + : frame (f), cnt (c) {} + PeakBuildRecord (const PeakBuildRecord& other) { + frame = other.frame; + cnt = other.cnt; + } + }; + + list<Source::PeakBuildRecord *> pending_peak_builds; + + private: + ARDOUR::id_t _id; + + bool Source::file_changed (string path); +}; + +} + +#endif /* __ardour_source_h__ */ diff --git a/libs/ardour/ardour/spline.h b/libs/ardour/ardour/spline.h new file mode 100644 index 0000000000..de1ece6edb --- /dev/null +++ b/libs/ardour/ardour/spline.h @@ -0,0 +1,90 @@ +/* This code is based upon work that bore the legend: + * + * Copyright (C) 1997 David Mosberger + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __ardour_spline_h__ +#define __ardour_spline_h__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _spline Spline; +typedef struct _spline_point SplinePoint; + +struct _spline_point +{ + float x; + float y; +}; + +Spline *spline_new (void); +void spline_free (Spline *); + +void spline_set (Spline *, uint32_t n, SplinePoint *); +void spline_add (Spline *, uint32_t n, SplinePoint *); +void spline_solve (Spline *); +float spline_eval (Spline *, float val); +void spline_fill (Spline *, float x0, float x1, float *vec, uint32_t veclen); +float spline_get_max_x (Spline *); +float spline_get_min_x (Spline *); + +struct _spline +{ + float *deriv2; + float *x; + float *y; + float max_x; + float min_x; + SplinePoint *points; + uint32_t npoints; + uint32_t space; + +#ifdef __cplusplus + + void set (uint32_t n, SplinePoint *points) { + spline_set (this, n, points); + } + + void add (uint32_t n, SplinePoint *points) { + spline_add (this, n, points); + } + + void solve () { + spline_solve (this); + } + + float eval (float val) { + return spline_eval (this, val); + } + + void fill (float x0, float x1, float *vec, uint32_t veclen) { + spline_fill (this, x0, x1, vec, veclen); + } + +#endif /* __cplusplus */ + +}; + + +#ifdef __cplusplus +} +#endif + +#endif /* __ardour_spline_h__ */ diff --git a/libs/ardour/ardour/state_manager.h b/libs/ardour/ardour/state_manager.h new file mode 100644 index 0000000000..9dc2ea66ad --- /dev/null +++ b/libs/ardour/ardour/state_manager.h @@ -0,0 +1,48 @@ +#ifndef __ardour_state_manager_h__ +#define __ardour_state_manager_h__ + +#include <list> +#include <string> + +#include <sigc++/signal.h> + +#include <ardour/ardour.h> + +namespace ARDOUR { + +typedef uint32_t state_id_t; + + + class StateManager : virtual public sigc::trackable +{ + public: + struct State { + std::string operation; + State (std::string why) : operation (why) {} + virtual ~State() {} + }; + + typedef std::list<State*> StateMap; + + StateManager (); + virtual ~StateManager (); + + virtual void drop_all_states (); + virtual void use_state (state_id_t); + virtual void save_state (std::string why); + + sigc::signal<void,Change> StateChanged; + + state_id_t _current_state_id; + + protected: + StateMap states; + + virtual Change restore_state (State&) = 0; + virtual State* state_factory (std::string why) const = 0; + virtual void send_state_changed (Change); +}; + +} // namespace ARDOUR + +#endif /* __ardour_state_manager_h__ */ diff --git a/libs/ardour/ardour/stateful.h b/libs/ardour/ardour/stateful.h new file mode 100644 index 0000000000..4f4cb20b39 --- /dev/null +++ b/libs/ardour/ardour/stateful.h @@ -0,0 +1,51 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_stateful_h__ +#define __ardour_stateful_h__ + +#include <string> + +class XMLNode; + +class Stateful { + public: + Stateful(); + virtual ~Stateful(); + + virtual XMLNode& get_state (void) = 0; + + virtual int set_state (const XMLNode&) = 0; + + /* Extra XML nodes */ + + void add_extra_xml (XMLNode&); + XMLNode *extra_xml (const std::string& str); + + virtual void add_instant_xml (XMLNode&, const std::string& dir); + XMLNode *instant_xml (const std::string& str, const std::string& dir); + + protected: + XMLNode *_extra_xml; + XMLNode *_instant_xml; +}; + +#endif /* __ardour_stateful_h__ */ + diff --git a/libs/ardour/ardour/tempo.h b/libs/ardour/ardour/tempo.h new file mode 100644 index 0000000000..2f04f603e7 --- /dev/null +++ b/libs/ardour/ardour/tempo.h @@ -0,0 +1,323 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_tempo_h__ +#define __ardour_tempo_h__ + +#include <list> +#include <string> +#include <vector> +#include <cmath> +#include <pthread.h> +#include <pbd/lockmonitor.h> +#include <pbd/undo.h> +#include <sigc++/signal.h> + +#include <ardour/ardour.h> +#include <ardour/stateful.h> +#include <ardour/state_manager.h> + +class XMLNode; + +using std::list; +using std::vector; + +namespace ARDOUR { + +class Tempo { + public: + Tempo (double bpm) + : _beats_per_minute (bpm) {} + Tempo (const Tempo& other) { + _beats_per_minute = other._beats_per_minute; + } + void operator= (const Tempo& other) { + if (&other != this) { + _beats_per_minute = other._beats_per_minute; + } + } + + double beats_per_minute () const { return _beats_per_minute; } + double frames_per_beat (jack_nframes_t sr) const { + return ((60.0 * sr) / _beats_per_minute); + } + + protected: + double _beats_per_minute; +}; + +class Meter { + public: + static const double ticks_per_beat; + + Meter (double bpb, double bt) + : _beats_per_bar (bpb), _note_type (bt) {} + Meter (const Meter& other) { + _beats_per_bar = other._beats_per_bar; + _note_type = other._note_type; + } + void operator= (const Meter& other) { + if (&other != this) { + _beats_per_bar = other._beats_per_bar; + _note_type = other._note_type; + } + } + + double beats_per_bar () const { return _beats_per_bar; } + double note_divisor() const { return _note_type; } + + double frames_per_bar (const Tempo&, jack_nframes_t sr) const; + + protected: + + /* this is the number of beats in a bar. it is a real value + because there are musical traditions on our planet + that do not limit themselves to integral numbers of beats + per bar. + */ + + double _beats_per_bar; + + /* this is the type of "note" that a beat represents. for example, + 4.0 would be a quarter (crotchet) note, 8.0 would be an eighth + (quaver) note, etc. + */ + + double _note_type; +}; + +class MetricSection { + public: + MetricSection (const BBT_Time& start) + : _start (start), _frame (0), _movable (true) {} + virtual ~MetricSection() {} + + const BBT_Time& start() const { return _start; } + const jack_nframes_t frame() const { return _frame; } + + void set_movable (bool yn) { _movable = yn; } + bool movable() const { return _movable; } + + virtual void set_frame (jack_nframes_t f) { + _frame = f; + }; + + virtual void set_start (const BBT_Time& w) { + _start = w; + } + + /* MeterSections are not stateful in the full sense, + but we do want them to control their own + XML state information. + */ + + virtual XMLNode& get_state() const = 0; + + private: + BBT_Time _start; + jack_nframes_t _frame; + bool _movable; +}; + +class MeterSection : public MetricSection, public Meter { + public: + MeterSection (const BBT_Time& start, double bpb, double note_type) + : MetricSection (start), Meter (bpb, note_type) {} + MeterSection (const XMLNode&); + + static const string xml_state_node_name; + + XMLNode& get_state() const; +}; + +class TempoSection : public MetricSection, public Tempo { + public: + TempoSection (const BBT_Time& start, double qpm) + : MetricSection (start), Tempo (qpm) {} + TempoSection (const XMLNode&); + + static const string xml_state_node_name; + + XMLNode& get_state() const; +}; + +typedef list<MetricSection*> Metrics; + +class TempoMapState : public StateManager::State { + public: + TempoMapState (std::string why) + : StateManager::State (why) { + metrics = new Metrics; + } + + Metrics *metrics; +}; + +class TempoMap : public Stateful, public StateManager { + public: + + TempoMap (jack_nframes_t frame_rate); + ~TempoMap(); + + /* measure-based stuff */ + + enum BBTPointType { + Bar, + Beat, + }; + + struct BBTPoint { + BBTPointType type; + jack_nframes_t frame; + const Meter* meter; + const Tempo* tempo; + uint32_t bar; + uint32_t beat; + + BBTPoint (const Meter& m, const Tempo& t, jack_nframes_t f, BBTPointType ty, uint32_t b, uint32_t e) + : type (ty), frame (f), meter (&m), tempo (&t), bar (b), beat (e) {} + }; + + typedef vector<BBTPoint> BBTPointList; + + template<class T> void apply_with_metrics (T& obj, void (T::*method)(const Metrics&)) { + LockMonitor lm (lock, __LINE__, __FILE__); + (obj.*method)(*metrics); + } + + BBTPointList *get_points (jack_nframes_t start, jack_nframes_t end) const; + + void bbt_time (jack_nframes_t when, BBT_Time&) const; + jack_nframes_t frame_time (const BBT_Time&) const; + jack_nframes_t bbt_duration_at (jack_nframes_t, const BBT_Time&, int dir) const; + + static const Tempo& default_tempo() { return _default_tempo; } + static const Meter& default_meter() { return _default_meter; } + + const Tempo& tempo_at (jack_nframes_t); + const Meter& meter_at (jack_nframes_t); + + void add_tempo(const Tempo&, BBT_Time where); + void add_meter(const Meter&, BBT_Time where); + + void move_tempo (TempoSection&, const BBT_Time& to); + void move_meter (MeterSection&, const BBT_Time& to); + + void remove_tempo(const TempoSection&); + void remove_meter(const MeterSection&); + + void replace_tempo (TempoSection& existing, const Tempo& replacement); + void replace_meter (MeterSection& existing, const Meter& replacement); + + + jack_nframes_t round_to_bar (jack_nframes_t frame, int dir); + + jack_nframes_t round_to_beat (jack_nframes_t frame, int dir); + + jack_nframes_t round_to_beat_subdivision (jack_nframes_t fr, int sub_num); + + jack_nframes_t round_to_tick (jack_nframes_t frame, int dir); + + void set_length (jack_nframes_t frames); + + XMLNode& get_state (void); + int set_state (const XMLNode&); + + void dump (std::ostream&) const; + void clear (); + + UndoAction get_memento() const; + + /* this is a helper class that we use to be able to keep + track of which meter *AND* tempo are in effect at + a given point in time. + */ + + class Metric { + public: + Metric (const Meter& m, const Tempo& t) : _meter (&m), _tempo (&t), _frame (0) {} + + void set_tempo (const Tempo& t) { _tempo = &t; } + void set_meter (const Meter& m) { _meter = &m; } + void set_frame (jack_nframes_t f) { _frame = f; } + void set_start (const BBT_Time& t) { _start = t; } + + const Meter& meter() const { return *_meter; } + const Tempo& tempo() const { return *_tempo; } + jack_nframes_t frame() const { return _frame; } + const BBT_Time& start() const { return _start; } + + private: + const Meter* _meter; + const Tempo* _tempo; + jack_nframes_t _frame; + BBT_Time _start; + + }; + + Metric metric_at (BBT_Time bbt) const; + Metric metric_at (jack_nframes_t) const; + void bbt_time_with_metric (jack_nframes_t, BBT_Time&, const Metric&) const; + + private: + static Tempo _default_tempo; + static Meter _default_meter; + + Metrics *metrics; + jack_nframes_t _frame_rate; + jack_nframes_t last_bbt_when; + bool last_bbt_valid; + BBT_Time last_bbt; + mutable PBD::Lock lock; + + void timestamp_metrics (); + + + jack_nframes_t round_to_type (jack_nframes_t fr, int dir, BBTPointType); + + jack_nframes_t frame_time_unlocked (const BBT_Time&) const; + + void bbt_time_unlocked (jack_nframes_t, BBT_Time&) const; + + jack_nframes_t bbt_duration_at_unlocked (const BBT_Time& when, const BBT_Time& bbt, int dir) const; + + const MeterSection& first_meter() const; + const TempoSection& first_tempo() const; + + jack_nframes_t count_frames_between (const BBT_Time&, const BBT_Time&) const; + jack_nframes_t count_frames_between_metrics (const Meter&, const Tempo&, const BBT_Time&, const BBT_Time&) const; + + int move_metric_section (MetricSection&, const BBT_Time& to); + void do_insert (MetricSection* section); + + Change restore_state (StateManager::State&); + StateManager::State* state_factory (std::string why) const; + + bool in_set_state; + + /* override state_manager::save_state so we can check in_set_state */ + + void save_state (std::string why); + +}; + +}; /* namespace ARDOUR */ + +#endif /* __ardour_tempo_h__ */ diff --git a/libs/ardour/ardour/timestamps.h b/libs/ardour/ardour/timestamps.h new file mode 100644 index 0000000000..4ebc28b2f9 --- /dev/null +++ b/libs/ardour/ardour/timestamps.h @@ -0,0 +1,13 @@ +#ifndef __ardour_timestamps_h__ +#define __ardour_timestamps_h__ + +#ifdef WITH_JACK_TIMESTAMPS +#include <jack/timestamps.h> +#else +#define jack_timestamp(s) +#define jack_init_timestamps(n) +#define jack_dump_timestamps(o) +#define jack_reset_timestamps() +#endif + +#endif /* __ardour_timestamps_h__ */ diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h new file mode 100644 index 0000000000..95f3c471f2 --- /dev/null +++ b/libs/ardour/ardour/types.h @@ -0,0 +1,243 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_types_h__ +#define __ardour_types_h__ + +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS /* PRI<foo>; C++ requires explicit requesting of these */ +#endif + +#include <inttypes.h> +#include <jack/types.h> +#include <map> + +#if __GNUC__ < 3 + +typedef int intptr_t; +#endif + +namespace ARDOUR { + + class Source; + + typedef jack_default_audio_sample_t Sample; + typedef float pan_t; + typedef float gain_t; + typedef uint32_t layer_t; + typedef uint64_t id_t; + + enum IOChange { + NoChange = 0, + ConfigurationChanged = 0x1, + ConnectionsChanged = 0x2 + }; + + enum OverlapType { + OverlapNone, // no overlap + OverlapInternal, // the overlap is 100% with the object + OverlapStart, // overlap covers start, but ends within + OverlapEnd, // overlap begins within and covers end + OverlapExternal // overlap extends to (at least) begin+end + }; + + OverlapType coverage (jack_nframes_t start_a, jack_nframes_t end_a, + jack_nframes_t start_b, jack_nframes_t end_b); + + enum AutomationType { + GainAutomation = 0x1, + PanAutomation = 0x2, + PluginAutomation = 0x4, + SoloAutomation = 0x8, + MuteAutomation = 0x10, + }; + + enum AutoState { + Off = 0x0, + Write = 0x1, + Touch = 0x2, + Play = 0x4 + }; + + enum AutoStyle { + Absolute = 0x1, + Trim = 0x2 + }; + + enum AlignStyle { + CaptureTime, + ExistingMaterial + }; + + enum MeterPoint { + MeterInput, + MeterPreFader, + MeterPostFader + }; + + enum smpte_wrap_t { + smpte_wrap_none = 0, + smpte_wrap_frames, + smpte_wrap_seconds, + smpte_wrap_minutes, + smpte_wrap_hours + }; + + struct SMPTE_Time { + bool negative; + long hours; + long minutes; + long seconds; + long frames; + long subframes; // mostly not used + + SMPTE_Time() { + negative = false; + hours = 0; + minutes = 0; + seconds = 0; + frames = 0; + subframes = 0; + } + + }; + + struct BBT_Time { + uint32_t bars; + uint32_t beats; + uint32_t ticks; + + BBT_Time() { + bars = 1; + beats = 1; + ticks = 0; + } + + /* we can't define arithmetic operators for BBT_Time, because + the results depend on a TempoMap, but we can define + a useful check on the less-than condition. + */ + + bool operator< (const BBT_Time& other) const { + return bars < other.bars || + (bars == other.bars && beats < other.beats) || + (bars == other.bars && beats == other.beats && ticks < other.ticks); + } + + bool operator== (const BBT_Time& other) const { + return bars == other.bars && beats == other.beats && ticks == other.ticks; + } + + }; + + struct AnyTime { + enum Type { + SMPTE, + BBT, + Frames, + Seconds + }; + + Type type; + + SMPTE_Time smpte; + BBT_Time bbt; + + union { + jack_nframes_t frames; + double seconds; + }; + }; + + struct AudioRange { + jack_nframes_t start; + jack_nframes_t end; + uint32_t id; + + AudioRange (jack_nframes_t s, jack_nframes_t e, uint32_t i) : start (s), end (e) , id (i) {} + + jack_nframes_t length() { return end - start + 1; } + + bool operator== (const AudioRange& other) const { + return start == other.start && end == other.end && id == other.id; + } + + bool equal (const AudioRange& other) const { + return start == other.start && end == other.end; + } + + OverlapType coverage (jack_nframes_t s, jack_nframes_t e) const { + return ARDOUR::coverage (start, end, s, e); + } + }; + + struct MusicRange { + BBT_Time start; + BBT_Time end; + uint32_t id; + + MusicRange (BBT_Time& s, BBT_Time& e, uint32_t i) + : start (s), end (e), id (i) {} + + bool operator== (const MusicRange& other) const { + return start == other.start && end == other.end && id == other.id; + } + + bool equal (const MusicRange& other) const { + return start == other.start && end == other.end; + } + }; + + enum EditMode { + Slide, + Splice, + }; + + enum RegionPoint { + Start, + End, + SyncPoint + }; + + enum Change { + range_guarantee = ~0 + }; + + + enum Placement { + PreFader, + PostFader + }; + + enum CrossfadeModel { + FullCrossfade, + ShortCrossfade + }; + + struct InterThreadInfo { + volatile bool done; + volatile bool cancel; + volatile float progress; + pthread_t thread; + }; +}; + +#endif /* __ardour_types_h__ */ + diff --git a/libs/ardour/ardour/utils.h b/libs/ardour/ardour/utils.h new file mode 100644 index 0000000000..36ee6f105f --- /dev/null +++ b/libs/ardour/ardour/utils.h @@ -0,0 +1,59 @@ +/* + Copyright (C) 1999 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_utils_h__ +#define __ardour_utils_h__ + +#include <iostream> +#include <string> +#include <cmath> + +#include "ardour.h" + +class XMLNode; + +using std::ostream; + +void elapsed_time_to_str (char *buf, uint32_t seconds); +string legalize_for_path (std::string str); +ostream& operator<< (ostream& o, const ARDOUR::BBT_Time& bbt); +XMLNode* find_named_node (const XMLNode& node, std::string name); +string placement_as_string (ARDOUR::Placement); + +static inline float f_max(float x, float a) { + x -= a; + x += fabsf (x); + x *= 0.5f; + x += a; + + return (x); +} + +int cmp_nocase (const std::string& s, const std::string& s2); + +int tokenize_fullpath (string fullpath, string& path, string& name); + +int touch_file(string path); + +uint32_t long get_uid(); + +string region_name_from_path (string path); + +#endif /* __ardour_utils_h__ */ diff --git a/libs/ardour/ardour/vst_plugin.h b/libs/ardour/ardour/vst_plugin.h new file mode 100644 index 0000000000..6ae64ab50c --- /dev/null +++ b/libs/ardour/ardour/vst_plugin.h @@ -0,0 +1,112 @@ +/* + Copyright (C) 2004 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_vst_plugin_h__ +#define __ardour_vst_plugin_h__ + +#include <list> +#include <map> +#include <set> +#include <vector> +#include <string> +#include <dlfcn.h> + +#include <midi++/controllable.h> +#include <sigc++/signal.h> + +#include <jack/types.h> +#include <ardour/stateful.h> +#include <ardour/plugin_state.h> +#include <ardour/plugin.h> +#include <ardour/vst_plugin.h> + +using std::string; +using std::vector; +using std::list; +using std::map; + +struct _FSTHandle; +struct _FST; +typedef struct _FSTHandle FSTHandle; +typedef struct _FST FST; +class AEffect; + +namespace ARDOUR { +class AudioEngine; +class Session; + +class VSTPlugin : public ARDOUR::Plugin +{ + public: + VSTPlugin (ARDOUR::AudioEngine&, ARDOUR::Session&, FSTHandle* handle); + VSTPlugin (const VSTPlugin &); + ~VSTPlugin (); + + /* Plugin interface */ + + uint32_t unique_id() const; + const char * label() const; + const char * name() const; + 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 port, float val); + float get_parameter (uint32_t port) const; + int get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const; + std::set<uint32_t> automatable() const; + uint32_t nth_parameter (uint32_t port, bool& ok) const; + void activate (); + void deactivate (); + void set_block_size (jack_nframes_t nframes); + int connect_and_run (vector<Sample*>& bufs, uint32_t maxbuf, int32_t& in, int32_t& out, jack_nframes_t nframes, jack_nframes_t offset); + void store_state (ARDOUR::PluginState&); + void restore_state (ARDOUR::PluginState&); + string describe_parameter (uint32_t); + string state_node_name() const { return "vst"; } + void print_parameter (uint32_t, char*, uint32_t len) const; + + bool parameter_is_audio(uint32_t i) const { return false; } + bool parameter_is_control(uint32_t i) const { return true; } + bool parameter_is_input(uint32_t i) const { return true; } + bool parameter_is_output(uint32_t i) const { return false; } + + bool load_preset (const string preset_label ); + bool save_preset(string name); + + bool has_editor () const; + + XMLNode& get_state(); + int set_state(const XMLNode& node); + + AEffect* plugin() const { return _plugin; } + FST* fst() const { return _fst; } + + + private: + FSTHandle* handle; + FST* _fst; + AEffect* _plugin; + bool been_resumed; +}; + +} + +#endif /* __ardour_vst_plugin_h__ */ |