libardour added.
git-svn-id: svn://localhost/trunk/ardour2@17 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
7
libs/ardour/.cvsignore
Normal file
7
libs/ardour/.cvsignore
Normal file
@@ -0,0 +1,7 @@
|
||||
libardour.la
|
||||
libardour.pc
|
||||
version.cc
|
||||
*.lo
|
||||
*.os
|
||||
*.mo
|
||||
*.pot
|
||||
118
libs/ardour/ChangeLog
Normal file
118
libs/ardour/ChangeLog
Normal file
@@ -0,0 +1,118 @@
|
||||
2002-11-24 gettextize <bug-gnu-gettext@gnu.org>
|
||||
|
||||
* configure.ac (AC_OUTPUT): Add intl/Makefile,
|
||||
|
||||
2002-11-24 gettextize <bug-gnu-gettext@gnu.org>
|
||||
|
||||
* Makefile.am (ACLOCAL_AMFLAGS): New variable.
|
||||
|
||||
2001-10-26 Paul Davis <pbd>
|
||||
|
||||
* playlist.cc (recover_backup): restored the backup recovery code
|
||||
for playlists.
|
||||
|
||||
* diskstream.cc (do_refill): added state_lock to diskstream, just
|
||||
to be safe.
|
||||
|
||||
* session.cc (butler_thread_work): changed Session ISA thread to
|
||||
HASA thread.
|
||||
|
||||
2001-10-23 Paul Davis <pbd>
|
||||
|
||||
merged in marcus' patch for edit/mix group save/restore, and
|
||||
rationalized both it and the existing code for Route::set_state()
|
||||
|
||||
2001-10-20 Paul Davis <pbd>
|
||||
|
||||
* session.cc (get_state): in get_state, use the public order for routes.
|
||||
|
||||
2001-10-18 Paul Davis <pbd>
|
||||
|
||||
* playlist.cc (read): stop a muted region from causing a playlist
|
||||
read error.
|
||||
|
||||
2001-10-17 Paul Davis <pbd>
|
||||
|
||||
* region.cc (read_at): remove staccato noise caused by not
|
||||
shifting target buffer when !opaque.
|
||||
|
||||
2001-10-15 Paul Davis <pbd>
|
||||
|
||||
* region.cc (set_fade_out_active): made region fade in/out optional.
|
||||
|
||||
* configure.in: patches from Ben related to libxml++
|
||||
|
||||
2001-10-12 Paul Davis <pbd>
|
||||
|
||||
* session.cc (XMLRegionFactory): move most XML-based Region
|
||||
constructor into region.
|
||||
|
||||
|
||||
2001-10-10 Paul Davis <pbd>
|
||||
|
||||
* session.cc (load_sources): add whole-file regions when loading
|
||||
sources.
|
||||
|
||||
2001-10-09 Paul Davis <pbd>
|
||||
|
||||
* ardour/session.h: fix an ugly bug with a non-reference return type.
|
||||
|
||||
2001-10-04 Paul Davis <pbd>
|
||||
|
||||
* playlist.cc (split_region): ensure that left region after split
|
||||
is in the right place.
|
||||
|
||||
* auditioner.cc (play_audition): stop existing audition before
|
||||
starting a new one.
|
||||
|
||||
2001-10-03 Paul Davis <pbd>
|
||||
|
||||
* session.cc (process): stop regular process() call from operating
|
||||
on hidden diskstreams and routes. the butler thread still works on
|
||||
all diskstreams, every time, which might be a mistake.
|
||||
|
||||
2001-10-02 Paul Davis <pbd>
|
||||
|
||||
* session.cc (set_auto_play_range): added provisional support
|
||||
for play ranges using session events. added code to use
|
||||
auditioner.
|
||||
|
||||
* auditioner.cc: new file/object to support auditioning.
|
||||
|
||||
* route.cc: remove seek() function (didn't exist).
|
||||
|
||||
* session.cc (process): use list<DiskStream *> instead of GList
|
||||
for diskstreams. add auditioner object.
|
||||
|
||||
2001-09-30 Paul Davis <pbd>
|
||||
|
||||
* playlist.cc (split_region): fix problem with region splitting
|
||||
not defining two *smaller* regions of the original.
|
||||
|
||||
* region.cc (set_position): remove RegionTemplate object.
|
||||
|
||||
* playlist.cc (struct RegionSorter ): fix sorting to use position,
|
||||
not start - whatever was i thinking ?
|
||||
|
||||
2001-09-28 Paul Davis <pbd>
|
||||
|
||||
* source.cc: emit source creation signal.
|
||||
|
||||
* session.cc (first_stage_init): catch all source creation events.
|
||||
|
||||
* sndfilesource.cc (init): fix up an off-by-one substr-length
|
||||
error when creating a sndfilesource.
|
||||
|
||||
2001-09-27 Paul Davis <pbd>
|
||||
|
||||
* route.cc (operator): correct loop increment bug that caused a
|
||||
hang when an Insert is added to a Route as a Redirect.
|
||||
|
||||
2001-09-25 Paul Davis <pbd>
|
||||
|
||||
* session.cc: make new file sources be partially named for their
|
||||
initial host diskstream.
|
||||
|
||||
peak file construction now carried out en-masse at the
|
||||
end of capture run.
|
||||
|
||||
206
libs/ardour/SConscript
Normal file
206
libs/ardour/SConscript
Normal file
@@ -0,0 +1,206 @@
|
||||
# -*- python -*-
|
||||
|
||||
import os
|
||||
import glob
|
||||
|
||||
Import('env final_prefix install_prefix final_config_prefix libraries i18n')
|
||||
|
||||
ardour = env.Copy()
|
||||
|
||||
#
|
||||
# this defines the version number of libardour
|
||||
#
|
||||
|
||||
domain = 'libardour'
|
||||
|
||||
ardour.Append(DOMAIN = domain, MAJOR = 1, MINOR = 0, MICRO = 0)
|
||||
ardour.Append(CXXFLAGS = "-DPACKAGE=\\\"" + domain + "\\\"")
|
||||
ardour.Append(CCFLAGS="-DLIBSIGC_DISABLE_DEPRECATED")
|
||||
ardour.Append(PACKAGE = domain)
|
||||
ardour.Append(POTFILE = domain + '.pot')
|
||||
|
||||
ardour_files=Split("""
|
||||
audio_library.cc
|
||||
audio_playlist.cc
|
||||
audio_track.cc
|
||||
audioengine.cc
|
||||
audiofilter.cc
|
||||
audioregion.cc
|
||||
auditioner.cc
|
||||
automation.cc
|
||||
automation_event.cc
|
||||
configuration.cc
|
||||
connection.cc
|
||||
crossfade.cc
|
||||
curve.cc
|
||||
cycle_timer.cc
|
||||
default_click.cc
|
||||
diskstream.cc
|
||||
filesource.cc
|
||||
gain.cc
|
||||
gdither.cc
|
||||
globals.cc
|
||||
import.cc
|
||||
insert.cc
|
||||
io.cc
|
||||
jack_slave.cc
|
||||
ladspa_plugin.cc
|
||||
location.cc
|
||||
mtc_slave.cc
|
||||
named_selection.cc
|
||||
panner.cc
|
||||
playlist.cc
|
||||
playlist_factory.cc
|
||||
plugin.cc
|
||||
plugin_manager.cc
|
||||
port.cc
|
||||
recent_sessions.cc
|
||||
redirect.cc
|
||||
region.cc
|
||||
reverse.cc
|
||||
route.cc
|
||||
route_group.cc
|
||||
send.cc
|
||||
session.cc
|
||||
session_butler.cc
|
||||
session_click.cc
|
||||
session_events.cc
|
||||
session_export.cc
|
||||
session_feedback.cc
|
||||
session_midi.cc
|
||||
session_process.cc
|
||||
session_state.cc
|
||||
session_time.cc
|
||||
session_timefx.cc
|
||||
session_transport.cc
|
||||
sndfile_helpers.cc
|
||||
sndfilesource.cc
|
||||
source.cc
|
||||
state_manager.cc
|
||||
stateful.cc
|
||||
tempo.cc
|
||||
utils.cc
|
||||
version.cc
|
||||
mix.cc
|
||||
""")
|
||||
|
||||
arch_specific_objects = [ ]
|
||||
|
||||
vst_files = [ 'vst_plugin.cc', 'session_vst.cc' ]
|
||||
extra_sources = [ ]
|
||||
|
||||
if ardour['VST']:
|
||||
extra_sources += vst_files
|
||||
|
||||
ardour.Append(CCFLAGS="-D_REENTRANT -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE")
|
||||
ardour.Append(CXXFLAGS="-DDATA_DIR=\\\""+final_prefix+"/share\\\"")
|
||||
ardour.Append(CXXFLAGS="-DCONFIG_DIR=\\\""+final_config_prefix+"\\\"")
|
||||
ardour.Append(CXXFLAGS="-DLOCALEDIR=\\\""+final_prefix+"/share/locale\\\"")
|
||||
|
||||
ardour.Merge ([ libraries['jack'] ])
|
||||
|
||||
#
|
||||
# See if JACK supports jack_client_open()
|
||||
#
|
||||
|
||||
jack_test_source_file = """
|
||||
#include <jack/jack.h>
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
jack_client_open ("foo", 0, 0);
|
||||
return 0;
|
||||
}
|
||||
"""
|
||||
def CheckJackClientOpen(context):
|
||||
context.Message('Checking for jack_client_open()...')
|
||||
result = context.TryLink(jack_test_source_file, '.c')
|
||||
context.Result(result)
|
||||
return result
|
||||
|
||||
#
|
||||
# See if JACK supports jack_recompute_total_latencies()
|
||||
#
|
||||
|
||||
jack_test_source_file = """
|
||||
#include <jack/jack.h>
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
jack_recompute_total_latencies ((jack_client_t*) 0);
|
||||
return 0;
|
||||
}
|
||||
"""
|
||||
def CheckJackRecomputeLatencies(context):
|
||||
context.Message('Checking for jack_recompute_total_latencies()...')
|
||||
result = context.TryLink(jack_test_source_file, '.c')
|
||||
context.Result(result)
|
||||
return result
|
||||
|
||||
conf = Configure(ardour, custom_tests = {
|
||||
'CheckJackClientOpen' : CheckJackClientOpen,
|
||||
'CheckJackRecomputeLatencies' : CheckJackRecomputeLatencies
|
||||
})
|
||||
|
||||
if conf.CheckJackClientOpen():
|
||||
ardour.Append(CXXFLAGS="-DHAVE_JACK_CLIENT_OPEN")
|
||||
|
||||
if conf.CheckJackRecomputeLatencies():
|
||||
ardour.Append(CXXFLAGS="-DHAVE_JACK_RECOMPUTE_LATENCIES")
|
||||
|
||||
#
|
||||
# Optional header files
|
||||
#
|
||||
|
||||
if conf.CheckCHeader('wordexp.h'):
|
||||
ardour.Append(CXXFLAGS="-DHAVE_WORDEXP")
|
||||
|
||||
if conf.CheckCHeader('sys/vfs.h'):
|
||||
ardour.Append(CXXFLAGS="-DHAVE_SYS_VFS_H")
|
||||
|
||||
ardour = conf.Finish ()
|
||||
|
||||
ardour.Merge ([
|
||||
libraries['core'],
|
||||
libraries['xml'],
|
||||
libraries['sndfile'],
|
||||
libraries['lrdf'],
|
||||
libraries['samplerate'],
|
||||
libraries['sigc2'],
|
||||
libraries['pbd3'],
|
||||
libraries['soundtouch'],
|
||||
libraries['midi++2']
|
||||
])
|
||||
|
||||
|
||||
ardour.VersionBuild(['version.cc', 'ardour/version.h'], 'SConscript')
|
||||
|
||||
def SharedAsmObjectEmitter(target, source, env):
|
||||
for tgt in target:
|
||||
tgt.attributes.shared = 1
|
||||
return (target, source)
|
||||
|
||||
|
||||
env['BUILDERS']['SharedAsmObject'] = Builder (action = '$CXX -c -fPIC $SOURCE -o $TARGET',
|
||||
emitter = SharedAsmObjectEmitter,
|
||||
suffix = '$SHOBJSUFFIX',
|
||||
src_suffix = '.s',
|
||||
single_source = 1)
|
||||
|
||||
if env['DEVBUILD'] == 1:
|
||||
if env['BUILD_SSE_OPTIMIZATIONS'] == 1:
|
||||
arch_specific_objects = env.SharedAsmObject('sse_functions.os', 'sse_functions.s')
|
||||
libardour = ardour.SharedLibrary('ardour', ardour_files + extra_sources + arch_specific_objects)
|
||||
else:
|
||||
if env['BUILD_SSE_OPTIMIZATIONS'] == 1:
|
||||
arch_specific_objects = env.StaticObject(target='sse_functions',source='sse_functions.s')
|
||||
|
||||
libardour = ardour.StaticLibrary('ardour', ardour_files + extra_sources + arch_specific_objects)
|
||||
|
||||
Default(libardour)
|
||||
|
||||
if env['NLS']:
|
||||
i18n (ardour, ardour_files + vst_files, env)
|
||||
|
||||
env.Alias('tarball', env.Distribute (env['DISTTREE'],
|
||||
[ 'SConscript', 'i18n.h', 'gettext.h', 'sse_functions.s' ] +
|
||||
ardour_files + vst_files +
|
||||
glob.glob('po/*.po') + glob.glob('ardour/*.h')))
|
||||
1
libs/ardour/ardour/.cvsignore
Normal file
1
libs/ardour/ardour/.cvsignore
Normal file
@@ -0,0 +1 @@
|
||||
version.h
|
||||
80
libs/ardour/ardour/ardour.h
Normal file
80
libs/ardour/ardour/ardour.h
Normal file
@@ -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__ */
|
||||
|
||||
90
libs/ardour/ardour/audio_library.h
Normal file
90
libs/ardour/ardour/audio_library.h
Normal file
@@ -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__
|
||||
162
libs/ardour/ardour/audio_track.h
Normal file
162
libs/ardour/ardour/audio_track.h
Normal file
@@ -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__ */
|
||||
242
libs/ardour/ardour/audioengine.h
Normal file
242
libs/ardour/ardour/audioengine.h
Normal file
@@ -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__ */
|
||||
53
libs/ardour/ardour/audiofilter.h
Normal file
53
libs/ardour/ardour/audiofilter.h
Normal file
@@ -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__ */
|
||||
121
libs/ardour/ardour/audioplaylist.h
Normal file
121
libs/ardour/ardour/audioplaylist.h
Normal file
@@ -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__ */
|
||||
|
||||
|
||||
229
libs/ardour/ardour/audioregion.h
Normal file
229
libs/ardour/ardour/audioregion.h
Normal file
@@ -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__ */
|
||||
73
libs/ardour/ardour/auditioner.h
Normal file
73
libs/ardour/ardour/auditioner.h
Normal file
@@ -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__ */
|
||||
247
libs/ardour/ardour/automation_event.h
Normal file
247
libs/ardour/ardour/automation_event.h
Normal file
@@ -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__ */
|
||||
46
libs/ardour/ardour/click.h
Normal file
46
libs/ardour/ardour/click.h
Normal file
@@ -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__ */
|
||||
57
libs/ardour/ardour/config.h
Normal file
57
libs/ardour/ardour/config.h
Normal file
@@ -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"
|
||||
|
||||
253
libs/ardour/ardour/configuration.h
Normal file
253
libs/ardour/ardour/configuration.h
Normal file
@@ -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__ */
|
||||
94
libs/ardour/ardour/connection.h
Normal file
94
libs/ardour/ardour/connection.h
Normal file
@@ -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__ */
|
||||
|
||||
60
libs/ardour/ardour/constsource.h
Normal file
60
libs/ardour/ardour/constsource.h
Normal file
@@ -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__ */
|
||||
182
libs/ardour/ardour/crossfade.h
Normal file
182
libs/ardour/ardour/crossfade.h
Normal file
@@ -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__ */
|
||||
43
libs/ardour/ardour/crossfade_compare.h
Normal file
43
libs/ardour/ardour/crossfade_compare.h
Normal file
@@ -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__ */
|
||||
86
libs/ardour/ardour/curve.h
Normal file
86
libs/ardour/ardour/curve.h
Normal file
@@ -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__ */
|
||||
53
libs/ardour/ardour/cycle_timer.h
Normal file
53
libs/ardour/ardour/cycle_timer.h
Normal file
@@ -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__ */
|
||||
221
libs/ardour/ardour/cycles.h
Normal file
221
libs/ardour/ardour/cycles.h
Normal file
@@ -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__ */
|
||||
34
libs/ardour/ardour/dB.h
Normal file
34
libs/ardour/ardour/dB.h
Normal file
@@ -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__ */
|
||||
433
libs/ardour/ardour/diskstream.h
Normal file
433
libs/ardour/ardour/diskstream.h
Normal file
@@ -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__ */
|
||||
88
libs/ardour/ardour/export.h
Normal file
88
libs/ardour/ardour/export.h
Normal file
@@ -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__ */
|
||||
163
libs/ardour/ardour/filesource.h
Normal file
163
libs/ardour/ardour/filesource.h
Normal file
@@ -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__ */
|
||||
44
libs/ardour/ardour/gain.h
Normal file
44
libs/ardour/ardour/gain.h
Normal file
@@ -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__ */
|
||||
93
libs/ardour/ardour/gdither.h
Normal file
93
libs/ardour/ardour/gdither.h
Normal file
@@ -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
|
||||
49
libs/ardour/ardour/gdither_types.h
Normal file
49
libs/ardour/ardour/gdither_types.h
Normal file
@@ -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
|
||||
75
libs/ardour/ardour/gdither_types_internal.h
Normal file
75
libs/ardour/ardour/gdither_types_internal.h
Normal file
@@ -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
|
||||
153
libs/ardour/ardour/history.h
Normal file
153
libs/ardour/ardour/history.h
Normal file
@@ -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__ */
|
||||
|
||||
183
libs/ardour/ardour/insert.h
Normal file
183
libs/ardour/ardour/insert.h
Normal file
@@ -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__ */
|
||||
408
libs/ardour/ardour/io.h
Normal file
408
libs/ardour/ardour/io.h
Normal file
@@ -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__ */
|
||||
606
libs/ardour/ardour/ladspa.h
Normal file
606
libs/ardour/ardour/ladspa.h
Normal file
@@ -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 */
|
||||
142
libs/ardour/ardour/ladspa_plugin.h
Normal file
142
libs/ardour/ardour/ladspa_plugin.h
Normal file
@@ -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__ */
|
||||
193
libs/ardour/ardour/location.h
Normal file
193
libs/ardour/ardour/location.h
Normal file
@@ -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__ */
|
||||
133
libs/ardour/ardour/logcurve.h
Normal file
133
libs/ardour/ardour/logcurve.h
Normal file
@@ -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__ */
|
||||
|
||||
|
||||
74
libs/ardour/ardour/mix.h
Normal file
74
libs/ardour/ardour/mix.h
Normal file
@@ -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__ */
|
||||
55
libs/ardour/ardour/named_selection.h
Normal file
55
libs/ardour/ardour/named_selection.h
Normal file
@@ -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__ */
|
||||
|
||||
19
libs/ardour/ardour/noise.h
Normal file
19
libs/ardour/ardour/noise.h
Normal file
@@ -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
|
||||
331
libs/ardour/ardour/panner.h
Normal file
331
libs/ardour/ardour/panner.h
Normal file
@@ -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__ */
|
||||
17
libs/ardour/ardour/peak.h
Normal file
17
libs/ardour/ardour/peak.h
Normal file
@@ -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__ */
|
||||
278
libs/ardour/ardour/playlist.h
Normal file
278
libs/ardour/ardour/playlist.h
Normal file
@@ -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__ */
|
||||
|
||||
|
||||
49
libs/ardour/ardour/playlist_templates.h
Normal file
49
libs/ardour/ardour/playlist_templates.h
Normal file
@@ -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__ */
|
||||
194
libs/ardour/ardour/plugin.h
Normal file
194
libs/ardour/ardour/plugin.h
Normal file
@@ -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__ */
|
||||
63
libs/ardour/ardour/plugin_manager.h
Normal file
63
libs/ardour/ardour/plugin_manager.h
Normal file
@@ -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__ */
|
||||
14
libs/ardour/ardour/plugin_state.h
Normal file
14
libs/ardour/ardour/plugin_state.h
Normal file
@@ -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__ */
|
||||
213
libs/ardour/ardour/port.h
Normal file
213
libs/ardour/ardour/port.h
Normal file
@@ -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__ */
|
||||
39
libs/ardour/ardour/recent_sessions.h
Normal file
39
libs/ardour/ardour/recent_sessions.h
Normal file
@@ -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__
|
||||
153
libs/ardour/ardour/redirect.h
Normal file
153
libs/ardour/ardour/redirect.h
Normal file
@@ -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__ */
|
||||
259
libs/ardour/ardour/region.h
Normal file
259
libs/ardour/ardour/region.h
Normal file
@@ -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__ */
|
||||
22
libs/ardour/ardour/region_factory.h
Normal file
22
libs/ardour/ardour/region_factory.h
Normal file
@@ -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__ */
|
||||
38
libs/ardour/ardour/reverse.h
Normal file
38
libs/ardour/ardour/reverse.h
Normal file
@@ -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__ */
|
||||
359
libs/ardour/ardour/route.h
Normal file
359
libs/ardour/ardour/route.h
Normal file
@@ -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__ */
|
||||
111
libs/ardour/ardour/route_group.h
Normal file
111
libs/ardour/ardour/route_group.h
Normal file
@@ -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__ */
|
||||
22
libs/ardour/ardour/route_group_specialized.h
Normal file
22
libs/ardour/ardour/route_group_specialized.h
Normal file
@@ -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__ */
|
||||
63
libs/ardour/ardour/send.h
Normal file
63
libs/ardour/ardour/send.h
Normal file
@@ -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__ */
|
||||
55
libs/ardour/ardour/seqsource.h
Normal file
55
libs/ardour/ardour/seqsource.h
Normal file
@@ -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__ */
|
||||
1754
libs/ardour/ardour/session.h
Normal file
1754
libs/ardour/ardour/session.h
Normal file
File diff suppressed because it is too large
Load Diff
40
libs/ardour/ardour/session_connection.h
Normal file
40
libs/ardour/ardour/session_connection.h
Normal file
@@ -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__ */
|
||||
42
libs/ardour/ardour/session_diskstream.h
Normal file
42
libs/ardour/ardour/session_diskstream.h
Normal file
@@ -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__ */
|
||||
47
libs/ardour/ardour/session_playlist.h
Normal file
47
libs/ardour/ardour/session_playlist.h
Normal file
@@ -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__ */
|
||||
19
libs/ardour/ardour/session_region.h
Normal file
19
libs/ardour/ardour/session_region.h
Normal file
@@ -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__ */
|
||||
89
libs/ardour/ardour/session_route.h
Normal file
89
libs/ardour/ardour/session_route.h
Normal file
@@ -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__ */
|
||||
40
libs/ardour/ardour/session_selection.h
Normal file
40
libs/ardour/ardour/session_selection.h
Normal file
@@ -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__ */
|
||||
56
libs/ardour/ardour/silentsource.h
Normal file
56
libs/ardour/ardour/silentsource.h
Normal file
@@ -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__ */
|
||||
151
libs/ardour/ardour/slave.h
Normal file
151
libs/ardour/ardour/slave.h
Normal file
@@ -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__ */
|
||||
37
libs/ardour/ardour/sndfile_helpers.h
Normal file
37
libs/ardour/ardour/sndfile_helpers.h
Normal file
@@ -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__ */
|
||||
63
libs/ardour/ardour/sndfilesource.h
Normal file
63
libs/ardour/ardour/sndfilesource.h
Normal file
@@ -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__ */
|
||||
|
||||
54
libs/ardour/ardour/soundseq.h
Normal file
54
libs/ardour/ardour/soundseq.h
Normal file
@@ -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__ */
|
||||
|
||||
|
||||
|
||||
182
libs/ardour/ardour/source.h
Normal file
182
libs/ardour/ardour/source.h
Normal file
@@ -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__ */
|
||||
90
libs/ardour/ardour/spline.h
Normal file
90
libs/ardour/ardour/spline.h
Normal file
@@ -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__ */
|
||||
48
libs/ardour/ardour/state_manager.h
Normal file
48
libs/ardour/ardour/state_manager.h
Normal file
@@ -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__ */
|
||||
51
libs/ardour/ardour/stateful.h
Normal file
51
libs/ardour/ardour/stateful.h
Normal file
@@ -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__ */
|
||||
|
||||
323
libs/ardour/ardour/tempo.h
Normal file
323
libs/ardour/ardour/tempo.h
Normal file
@@ -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__ */
|
||||
13
libs/ardour/ardour/timestamps.h
Normal file
13
libs/ardour/ardour/timestamps.h
Normal file
@@ -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__ */
|
||||
243
libs/ardour/ardour/types.h
Normal file
243
libs/ardour/ardour/types.h
Normal file
@@ -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__ */
|
||||
|
||||
59
libs/ardour/ardour/utils.h
Normal file
59
libs/ardour/ardour/utils.h
Normal file
@@ -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__ */
|
||||
112
libs/ardour/ardour/vst_plugin.h
Normal file
112
libs/ardour/ardour/vst_plugin.h
Normal file
@@ -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__ */
|
||||
513
libs/ardour/audio_library.cc
Normal file
513
libs/ardour/audio_library.cc
Normal file
@@ -0,0 +1,513 @@
|
||||
/*
|
||||
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$
|
||||
*/
|
||||
|
||||
#include <cstdio> // Needed so that libraptor (included in lrdf) won't complain
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <cctype>
|
||||
|
||||
#include <lrdf.h>
|
||||
|
||||
#include <pbd/compose.h>
|
||||
|
||||
#include <ardour/ardour.h>
|
||||
#include <ardour/configuration.h>
|
||||
#include <ardour/audio_library.h>
|
||||
#include <ardour/utils.h>
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace ARDOUR;
|
||||
|
||||
namespace std {
|
||||
struct UriSorter {
|
||||
bool operator() (string a, string b) const {
|
||||
return cmp_nocase(Library->get_label(a), Library->get_label(b)) == -1;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
static char* GROUP = "http://ardour.org/ontology/Group";
|
||||
static char* SOUNDFILE = "http://ardour.org/ontology/Soundfile";
|
||||
static char* hasFile = "http://ardour.org/ontology/hasFile";
|
||||
static char* memberOf = "http://ardour.org/ontology/memberOf";
|
||||
static char* subGroupOf = "http://ardour.org/ontology/subGroupOf";
|
||||
|
||||
AudioLibrary::AudioLibrary ()
|
||||
{
|
||||
src = "file:" + Config->get_user_ardour_path() + "sfdb";
|
||||
|
||||
// workaround for possible bug in raptor that crashes when saving to a
|
||||
// non-existant file.
|
||||
touch_file(Config->get_user_ardour_path() + "sfdb");
|
||||
|
||||
lrdf_read_file(src.c_str());
|
||||
|
||||
lrdf_statement pattern;
|
||||
|
||||
pattern.subject = GROUP;
|
||||
pattern.predicate = RDF_TYPE;
|
||||
pattern.object = RDFS_CLASS;
|
||||
pattern.object_type = lrdf_uri;
|
||||
|
||||
lrdf_statement* matches = lrdf_matches(&pattern);
|
||||
|
||||
// if empty DB, create basic schema
|
||||
if (matches == 0) {
|
||||
initialize_db ();
|
||||
save_changes();
|
||||
}
|
||||
|
||||
lrdf_free_statements(matches);
|
||||
}
|
||||
|
||||
AudioLibrary::~AudioLibrary ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
AudioLibrary::initialize_db ()
|
||||
{
|
||||
// define ardour:Group
|
||||
lrdf_add_triple(src.c_str(), GROUP, RDF_TYPE, RDFS_CLASS, lrdf_uri);
|
||||
// define ardour:Soundfile
|
||||
lrdf_add_triple(src.c_str(), SOUNDFILE, RDF_TYPE, RDFS_CLASS, lrdf_uri);
|
||||
|
||||
// add intergral fields
|
||||
add_field("channels");
|
||||
add_field("samplerate");
|
||||
add_field("resolution");
|
||||
add_field("format");
|
||||
}
|
||||
|
||||
void
|
||||
AudioLibrary::save_changes ()
|
||||
{
|
||||
if (lrdf_export_by_source(src.c_str(), src.substr(5).c_str())) {
|
||||
warning << compose(_("Could not open %1. Audio Library not saved"), src) << endmsg;
|
||||
}
|
||||
}
|
||||
|
||||
string
|
||||
AudioLibrary::add_group (string group, string parent_uri)
|
||||
{
|
||||
string local_group(compose("file:sfbd/group/%1", get_uid()));
|
||||
|
||||
lrdf_add_triple(src.c_str(), local_group.c_str(),
|
||||
RDFS_BASE "label", group.c_str(), lrdf_literal);
|
||||
|
||||
if (parent_uri == ""){
|
||||
lrdf_add_triple(src.c_str(), local_group.c_str(),
|
||||
subGroupOf, GROUP, lrdf_uri);
|
||||
} else {
|
||||
lrdf_add_triple(src.c_str(), local_group.c_str(),
|
||||
subGroupOf, parent_uri.c_str(), lrdf_uri);
|
||||
}
|
||||
|
||||
added_group(local_group, parent_uri); /* EMIT SIGNAL */
|
||||
|
||||
return local_group;
|
||||
}
|
||||
|
||||
void
|
||||
AudioLibrary::remove_group (string uri)
|
||||
{
|
||||
list<string> items;
|
||||
list<string>::iterator i;
|
||||
|
||||
get_members(items, uri);
|
||||
for (i = items.begin(); i != items.end(); ++i) {
|
||||
remove_member(*i);
|
||||
}
|
||||
|
||||
items.clear();
|
||||
|
||||
get_groups(items, uri);
|
||||
for (i = items.begin(); i != items.end(); ++i) {
|
||||
remove_group(*i);
|
||||
}
|
||||
|
||||
lrdf_remove_uri_matches(uri.c_str());
|
||||
save_changes ();
|
||||
|
||||
removed_group(uri); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
void
|
||||
AudioLibrary::get_groups (list<string>& groups, string parent_uri)
|
||||
{
|
||||
lrdf_statement pattern;
|
||||
|
||||
pattern.subject = 0;
|
||||
pattern.predicate = subGroupOf;
|
||||
if (parent_uri == ""){
|
||||
pattern.object = strdup(GROUP);
|
||||
} else {
|
||||
pattern.object = strdup(parent_uri.c_str());
|
||||
}
|
||||
|
||||
lrdf_statement* matches = lrdf_matches(&pattern);
|
||||
|
||||
lrdf_statement* current = matches;
|
||||
while (current != 0) {
|
||||
groups.push_back(current->subject);
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
lrdf_free_statements(matches);
|
||||
free (pattern.object);
|
||||
|
||||
UriSorter cmp;
|
||||
groups.sort(cmp);
|
||||
groups.unique();
|
||||
}
|
||||
|
||||
string
|
||||
AudioLibrary::add_member (string member, string parent_uri)
|
||||
{
|
||||
string local_member(compose("file:sfdb/soundfile/%1", get_uid()));
|
||||
string file_uri(compose("file:%1", member));
|
||||
|
||||
lrdf_add_triple(src.c_str(), local_member.c_str(), RDF_TYPE,
|
||||
SOUNDFILE, lrdf_uri);
|
||||
lrdf_add_triple(src.c_str(), local_member.c_str(), hasFile,
|
||||
file_uri.c_str(), lrdf_uri);
|
||||
|
||||
string::size_type size = member.find_last_of('/');
|
||||
string label = member.substr(++size);
|
||||
|
||||
lrdf_add_triple(src.c_str(), local_member.c_str(), RDFS_BASE "label",
|
||||
label.c_str(), lrdf_literal);
|
||||
|
||||
if (parent_uri == ""){
|
||||
lrdf_add_triple(src.c_str(), local_member.c_str(), memberOf,
|
||||
GROUP, lrdf_uri);
|
||||
} else {
|
||||
lrdf_add_triple(src.c_str(), local_member.c_str(), memberOf,
|
||||
parent_uri.c_str(), lrdf_uri);
|
||||
}
|
||||
|
||||
save_changes ();
|
||||
|
||||
added_member (local_member, parent_uri); /* EMIT SIGNAL */
|
||||
|
||||
return local_member;
|
||||
}
|
||||
|
||||
void
|
||||
AudioLibrary::remove_member (string uri)
|
||||
{
|
||||
lrdf_remove_uri_matches (uri.c_str());
|
||||
|
||||
save_changes ();
|
||||
|
||||
removed_member(uri); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
void
|
||||
AudioLibrary::get_members (list<string>& members, string parent_uri)
|
||||
{
|
||||
lrdf_statement pattern;
|
||||
|
||||
pattern.subject = 0;
|
||||
pattern.predicate = memberOf;
|
||||
if (parent_uri == ""){
|
||||
pattern.object = strdup(GROUP);
|
||||
} else {
|
||||
pattern.object = strdup(parent_uri.c_str());
|
||||
}
|
||||
|
||||
lrdf_statement* matches = lrdf_matches(&pattern);
|
||||
|
||||
lrdf_statement* current = matches;
|
||||
while (current != 0) {
|
||||
members.push_back(current->subject);
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
lrdf_free_statements(matches);
|
||||
free (pattern.object);
|
||||
|
||||
UriSorter cmp;
|
||||
members.sort(cmp);
|
||||
members.unique();
|
||||
}
|
||||
|
||||
void
|
||||
AudioLibrary::search_members_and (list<string>& members,
|
||||
const map<string,string>& fields)
|
||||
{
|
||||
lrdf_statement **head;
|
||||
lrdf_statement* pattern = 0;
|
||||
lrdf_statement* old = 0;
|
||||
head = &pattern;
|
||||
|
||||
map<string,string>::const_iterator i;
|
||||
for (i = fields.begin(); i != fields.end(); ++i){
|
||||
pattern = new lrdf_statement;
|
||||
pattern->subject = "?";
|
||||
pattern->predicate = strdup(field_uri(i->first).c_str());
|
||||
pattern->object = strdup((i->second).c_str());
|
||||
pattern->next = old;
|
||||
|
||||
old = pattern;
|
||||
}
|
||||
|
||||
if (*head != 0) {
|
||||
lrdf_uris* ulist = lrdf_match_multi(*head);
|
||||
for (uint32_t j = 0; ulist && j < ulist->count; ++j) {
|
||||
// printf("AND: %s\n", ulist->items[j]);
|
||||
members.push_back(ulist->items[j]);
|
||||
}
|
||||
lrdf_free_uris(ulist);
|
||||
|
||||
UriSorter cmp;
|
||||
members.sort(cmp);
|
||||
members.unique();
|
||||
}
|
||||
|
||||
// memory clean up
|
||||
pattern = *head;
|
||||
while(pattern){
|
||||
free(pattern->predicate);
|
||||
free(pattern->object);
|
||||
old = pattern;
|
||||
pattern = pattern->next;
|
||||
delete old;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AudioLibrary::search_members_or (list<string>& members,
|
||||
const map<string,string>& fields)
|
||||
{
|
||||
map<string,string>::const_iterator i;
|
||||
|
||||
lrdf_statement pattern;
|
||||
for (i = fields.begin(); i != fields.end(); ++i) {
|
||||
pattern.subject = 0;
|
||||
pattern.predicate = strdup(field_uri(i->first).c_str());
|
||||
pattern.object = strdup((i->second).c_str());
|
||||
pattern.object_type = lrdf_literal;
|
||||
|
||||
lrdf_statement* matched = lrdf_matches(&pattern);
|
||||
|
||||
lrdf_statement* old = matched;
|
||||
while(matched) {
|
||||
// printf ("OR: %s\n", matched->subject);
|
||||
members.push_back(matched->subject);
|
||||
matched = matched->next;
|
||||
}
|
||||
|
||||
free(pattern.predicate);
|
||||
free(pattern.object);
|
||||
lrdf_free_statements (old);
|
||||
}
|
||||
|
||||
UriSorter cmp;
|
||||
members.sort(cmp);
|
||||
members.unique();
|
||||
}
|
||||
|
||||
string
|
||||
AudioLibrary::get_member_filename (string uri)
|
||||
{
|
||||
lrdf_statement pattern;
|
||||
pattern.subject = strdup(uri.c_str());
|
||||
pattern.predicate = hasFile;
|
||||
pattern.object = 0;
|
||||
pattern.object_type = lrdf_uri;
|
||||
|
||||
lrdf_statement* matches = lrdf_matches(&pattern);
|
||||
if (matches) {
|
||||
string file = matches->object;
|
||||
lrdf_free_statements(matches);
|
||||
|
||||
string::size_type pos = file.find(":");
|
||||
return file.substr(++pos);
|
||||
} else {
|
||||
warning << _("Could not find member filename") << endmsg;
|
||||
return "-Unknown-";
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AudioLibrary::add_field (string name)
|
||||
{
|
||||
string local_field = field_uri(name);
|
||||
lrdf_statement pattern;
|
||||
pattern.subject = strdup(local_field.c_str());
|
||||
pattern.predicate = RDF_TYPE;
|
||||
pattern.object = RDF_BASE "Property";
|
||||
pattern.object_type = lrdf_uri;
|
||||
|
||||
if(lrdf_exists_match(&pattern)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// of type rdf:Property
|
||||
lrdf_add_triple(src.c_str(), local_field.c_str(), RDF_TYPE,
|
||||
RDF_BASE "Property", lrdf_uri);
|
||||
// of range ardour:Soundfile
|
||||
lrdf_add_triple(src.c_str(), local_field.c_str(), RDFS_BASE "range",
|
||||
SOUNDFILE, lrdf_uri);
|
||||
// of domain rdf:Literal
|
||||
lrdf_add_triple(src.c_str(), local_field.c_str(), RDFS_BASE "domain",
|
||||
RDF_BASE "Literal", lrdf_uri);
|
||||
|
||||
set_label (local_field, name);
|
||||
|
||||
save_changes();
|
||||
|
||||
fields_changed(); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
void
|
||||
AudioLibrary::get_fields (list<string>& fields)
|
||||
{
|
||||
lrdf_statement pattern;
|
||||
|
||||
pattern.subject = 0;
|
||||
pattern.predicate = RDFS_BASE "range";
|
||||
pattern.object = SOUNDFILE;
|
||||
pattern.object_type = lrdf_uri;
|
||||
|
||||
lrdf_statement* matches = lrdf_matches(&pattern);
|
||||
|
||||
lrdf_statement* current = matches;
|
||||
while (current != 0) {
|
||||
fields.push_back(get_label(current->subject));
|
||||
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
lrdf_free_statements(matches);
|
||||
|
||||
fields.sort();
|
||||
fields.unique();
|
||||
}
|
||||
|
||||
void
|
||||
AudioLibrary::remove_field (string name)
|
||||
{
|
||||
lrdf_remove_uri_matches(field_uri(name).c_str());
|
||||
save_changes();
|
||||
fields_changed (); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
string
|
||||
AudioLibrary::get_field (string uri, string field)
|
||||
{
|
||||
lrdf_statement pattern;
|
||||
|
||||
pattern.subject = strdup(uri.c_str());
|
||||
|
||||
pattern.predicate = strdup(field_uri(field).c_str());
|
||||
|
||||
pattern.object = 0;
|
||||
pattern.object_type = lrdf_literal;
|
||||
|
||||
lrdf_statement* matches = lrdf_matches(&pattern);
|
||||
free(pattern.subject);
|
||||
free(pattern.predicate);
|
||||
|
||||
stringstream object;
|
||||
if (matches != 0){
|
||||
object << matches->object;
|
||||
}
|
||||
|
||||
lrdf_free_statements(matches);
|
||||
return object.str();
|
||||
}
|
||||
|
||||
void
|
||||
AudioLibrary::set_field (string uri, string field, string literal)
|
||||
{
|
||||
lrdf_statement pattern;
|
||||
|
||||
pattern.subject = strdup(uri.c_str());
|
||||
|
||||
string local_field = field_uri(field);
|
||||
pattern.predicate = strdup(local_field.c_str());
|
||||
|
||||
pattern.object = 0;
|
||||
pattern.object_type = lrdf_literal;
|
||||
|
||||
lrdf_remove_matches(&pattern);
|
||||
free(pattern.subject);
|
||||
free(pattern.predicate);
|
||||
|
||||
lrdf_add_triple(src.c_str(), uri.c_str(), local_field.c_str(),
|
||||
literal.c_str(), lrdf_literal);
|
||||
|
||||
save_changes();
|
||||
|
||||
fields_changed(); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
string
|
||||
AudioLibrary::field_uri (string name)
|
||||
{
|
||||
stringstream local_field;
|
||||
local_field << "file:sfdb/fields/" << name;
|
||||
|
||||
return local_field.str();
|
||||
}
|
||||
|
||||
string
|
||||
AudioLibrary::get_label (string uri)
|
||||
{
|
||||
lrdf_statement pattern;
|
||||
pattern.subject = strdup(uri.c_str());
|
||||
pattern.predicate = RDFS_BASE "label";
|
||||
pattern.object = 0;
|
||||
pattern.object_type = lrdf_literal;
|
||||
|
||||
lrdf_statement* matches = lrdf_matches (&pattern);
|
||||
free(pattern.subject);
|
||||
|
||||
stringstream label;
|
||||
if (matches != 0){
|
||||
label << matches->object;
|
||||
}
|
||||
|
||||
lrdf_free_statements(matches);
|
||||
|
||||
return label.str();
|
||||
}
|
||||
|
||||
void
|
||||
AudioLibrary::set_label (string uri, string label)
|
||||
{
|
||||
lrdf_statement pattern;
|
||||
pattern.subject = strdup(uri.c_str());
|
||||
pattern.predicate = RDFS_BASE "label";
|
||||
pattern.object = 0;
|
||||
pattern.object_type = lrdf_literal;
|
||||
|
||||
lrdf_remove_matches(&pattern);
|
||||
free(pattern.subject);
|
||||
|
||||
lrdf_add_triple(src.c_str(), uri.c_str(), RDFS_BASE "label",
|
||||
label.c_str(), lrdf_literal);
|
||||
}
|
||||
|
||||
873
libs/ardour/audio_playlist.cc
Normal file
873
libs/ardour/audio_playlist.cc
Normal file
@@ -0,0 +1,873 @@
|
||||
/*
|
||||
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$
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <sigc++/bind.h>
|
||||
|
||||
#include <ardour/types.h>
|
||||
#include <ardour/configuration.h>
|
||||
#include <ardour/audioplaylist.h>
|
||||
#include <ardour/audioregion.h>
|
||||
#include <ardour/crossfade.h>
|
||||
#include <ardour/crossfade_compare.h>
|
||||
#include <ardour/session.h>
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
using namespace ARDOUR;
|
||||
using namespace sigc;
|
||||
using namespace std;
|
||||
|
||||
AudioPlaylist::State::~State ()
|
||||
{
|
||||
}
|
||||
|
||||
AudioPlaylist::AudioPlaylist (Session& session, const XMLNode& node, bool hidden)
|
||||
: Playlist (session, node, hidden)
|
||||
{
|
||||
in_set_state = true;
|
||||
set_state (node);
|
||||
in_set_state = false;
|
||||
|
||||
save_state (_("initial state"));
|
||||
|
||||
if (!hidden) {
|
||||
PlaylistCreated (this); /* EMIT SIGNAL */
|
||||
}
|
||||
}
|
||||
|
||||
AudioPlaylist::AudioPlaylist (Session& session, string name, bool hidden)
|
||||
: Playlist (session, name, hidden)
|
||||
{
|
||||
save_state (_("initial state"));
|
||||
|
||||
if (!hidden) {
|
||||
PlaylistCreated (this); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
AudioPlaylist::AudioPlaylist (const AudioPlaylist& other, string name, bool hidden)
|
||||
: Playlist (other, name, hidden)
|
||||
{
|
||||
save_state (_("initial state"));
|
||||
|
||||
if (!hidden) {
|
||||
PlaylistCreated (this); /* EMIT SIGNAL */
|
||||
}
|
||||
}
|
||||
|
||||
AudioPlaylist::AudioPlaylist (const AudioPlaylist& other, jack_nframes_t start, jack_nframes_t cnt, string name, bool hidden)
|
||||
: Playlist (other, start, cnt, name, hidden)
|
||||
{
|
||||
save_state (_("initial state"));
|
||||
|
||||
/* this constructor does NOT notify others (session) */
|
||||
}
|
||||
|
||||
AudioPlaylist::~AudioPlaylist ()
|
||||
{
|
||||
set<Crossfade*> all_xfades;
|
||||
set<Region*> all_regions;
|
||||
|
||||
GoingAway (this);
|
||||
|
||||
/* find every region we've ever used, and add it to the set of
|
||||
all regions. same for xfades;
|
||||
*/
|
||||
|
||||
for (RegionList::iterator x = regions.begin(); x != regions.end(); ++x) {
|
||||
all_regions.insert (*x);
|
||||
}
|
||||
|
||||
for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end(); ++x) {
|
||||
all_xfades.insert (*x);
|
||||
}
|
||||
|
||||
for (StateMap::iterator i = states.begin(); i != states.end(); ++i) {
|
||||
|
||||
AudioPlaylist::State* apstate = dynamic_cast<AudioPlaylist::State*> (*i);
|
||||
|
||||
for (RegionList::iterator r = apstate->regions.begin(); r != apstate->regions.end(); ++r) {
|
||||
all_regions.insert (*r);
|
||||
}
|
||||
for (Crossfades::iterator xf = apstate->crossfades.begin(); xf != apstate->crossfades.end(); ++xf) {
|
||||
all_xfades.insert (*xf);
|
||||
}
|
||||
|
||||
delete apstate;
|
||||
}
|
||||
|
||||
/* delete every region */
|
||||
|
||||
for (set<Region *>::iterator ar = all_regions.begin(); ar != all_regions.end(); ++ar) {
|
||||
(*ar)->unlock_sources ();
|
||||
delete *ar;
|
||||
}
|
||||
|
||||
/* delete every crossfade */
|
||||
|
||||
for (set<Crossfade *>::iterator axf = all_xfades.begin(); axf != all_xfades.end(); ++axf) {
|
||||
delete *axf;
|
||||
}
|
||||
}
|
||||
|
||||
struct RegionSortByLayer {
|
||||
bool operator() (Region *a, Region *b) {
|
||||
return a->layer() < b->layer();
|
||||
}
|
||||
};
|
||||
|
||||
jack_nframes_t
|
||||
AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, jack_nframes_t start,
|
||||
jack_nframes_t cnt, unsigned chan_n)
|
||||
{
|
||||
jack_nframes_t ret = cnt;
|
||||
jack_nframes_t end;
|
||||
jack_nframes_t read_frames;
|
||||
jack_nframes_t skip_frames;
|
||||
|
||||
/* optimizing this memset() away involves a lot of conditionals
|
||||
that may well cause more of a hit due to cache misses
|
||||
and related stuff than just doing this here.
|
||||
|
||||
it would be great if someone could measure this
|
||||
at some point.
|
||||
|
||||
one way or another, parts of the requested area
|
||||
that are not written to by Region::region_at()
|
||||
for all Regions that cover the area need to be
|
||||
zeroed.
|
||||
*/
|
||||
|
||||
memset (buf, 0, sizeof (Sample) * cnt);
|
||||
|
||||
/* this function is never called from a realtime thread, so
|
||||
its OK to block (for short intervals).
|
||||
*/
|
||||
|
||||
LockMonitor rm (region_lock, __LINE__, __FILE__);
|
||||
|
||||
end = start + cnt - 1;
|
||||
|
||||
read_frames = 0;
|
||||
skip_frames = 0;
|
||||
_read_data_count = 0;
|
||||
|
||||
map<uint32_t,vector<Region*> > relevant_regions;
|
||||
map<uint32_t,vector<Crossfade*> > relevant_xfades;
|
||||
vector<uint32_t> relevant_layers;
|
||||
|
||||
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
|
||||
if ((*i)->coverage (start, end) != OverlapNone) {
|
||||
|
||||
relevant_regions[(*i)->layer()].push_back (*i);
|
||||
relevant_layers.push_back ((*i)->layer());
|
||||
}
|
||||
}
|
||||
|
||||
for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
|
||||
if ((*i)->coverage (start, end) != OverlapNone) {
|
||||
relevant_xfades[(*i)->upper_layer()].push_back (*i);
|
||||
}
|
||||
}
|
||||
|
||||
// RegionSortByLayer layer_cmp;
|
||||
// relevant_regions.sort (layer_cmp);
|
||||
|
||||
/* XXX this whole per-layer approach is a hack that
|
||||
should be removed once Crossfades become
|
||||
CrossfadeRegions and we just grab a list of relevant
|
||||
regions and call read_at() on all of them.
|
||||
*/
|
||||
|
||||
sort (relevant_layers.begin(), relevant_layers.end());
|
||||
|
||||
for (vector<uint32_t>::iterator l = relevant_layers.begin(); l != relevant_layers.end(); ++l) {
|
||||
|
||||
vector<Region*>& r (relevant_regions[*l]);
|
||||
vector<Crossfade*>& x (relevant_xfades[*l]);
|
||||
|
||||
for (vector<Region*>::iterator i = r.begin(); i != r.end(); ++i) {
|
||||
(*i)->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n, read_frames, skip_frames);
|
||||
_read_data_count += (*i)->read_data_count();
|
||||
}
|
||||
|
||||
for (vector<Crossfade*>::iterator i = x.begin(); i != x.end(); ++i) {
|
||||
|
||||
(*i)->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n);
|
||||
|
||||
/* don't JACK up _read_data_count, since its the same data as we just
|
||||
read from the regions, and the OS should handle that for us.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioPlaylist::remove_dependents (Region& region)
|
||||
{
|
||||
Crossfades::iterator i, tmp;
|
||||
AudioRegion* r = dynamic_cast<AudioRegion*> (®ion);
|
||||
|
||||
if (r == 0) {
|
||||
fatal << _("programming error: non-audio Region passed to remove_overlap in audio playlist")
|
||||
<< endmsg;
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = _crossfades.begin(); i != _crossfades.end(); ) {
|
||||
tmp = i;
|
||||
tmp++;
|
||||
|
||||
if ((*i)->involves (*r)) {
|
||||
/* do not delete crossfades */
|
||||
_crossfades.erase (i);
|
||||
}
|
||||
|
||||
i = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioPlaylist::flush_notifications ()
|
||||
{
|
||||
Playlist::flush_notifications();
|
||||
|
||||
if (in_flush) {
|
||||
return;
|
||||
}
|
||||
|
||||
in_flush = true;
|
||||
|
||||
Crossfades::iterator a;
|
||||
for (a = _pending_xfade_adds.begin(); a != _pending_xfade_adds.end(); ++a) {
|
||||
NewCrossfade (*a); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
_pending_xfade_adds.clear ();
|
||||
|
||||
in_flush = false;
|
||||
}
|
||||
|
||||
void
|
||||
AudioPlaylist::refresh_dependents (Region& r)
|
||||
{
|
||||
AudioRegion* ar = dynamic_cast<AudioRegion*>(&r);
|
||||
set<Crossfade*> updated;
|
||||
|
||||
if (ar == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Crossfades::iterator x = _crossfades.begin(); x != _crossfades.end();) {
|
||||
|
||||
Crossfades::iterator tmp;
|
||||
|
||||
tmp = x;
|
||||
++tmp;
|
||||
|
||||
/* only update them once */
|
||||
|
||||
if ((*x)->involves (*ar)) {
|
||||
|
||||
if (find (updated.begin(), updated.end(), *x) == updated.end()) {
|
||||
if ((*x)->refresh ()) {
|
||||
/* not invalidated by the refresh */
|
||||
updated.insert (*x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
x = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AudioPlaylist::check_dependents (Region& r, bool norefresh)
|
||||
{
|
||||
AudioRegion* other;
|
||||
AudioRegion* region;
|
||||
AudioRegion* top;
|
||||
AudioRegion* bottom;
|
||||
Crossfade* xfade;
|
||||
|
||||
if (in_set_state || in_partition) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((region = dynamic_cast<AudioRegion*> (&r)) == 0) {
|
||||
fatal << _("programming error: non-audio Region tested for overlap in audio playlist")
|
||||
<< endmsg;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!norefresh) {
|
||||
refresh_dependents (r);
|
||||
}
|
||||
|
||||
if (!Config->get_auto_xfade()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
|
||||
|
||||
other = dynamic_cast<AudioRegion*> (*i);
|
||||
|
||||
if (other == region) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (other->muted() || region->muted()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (other->layer() < region->layer()) {
|
||||
top = region;
|
||||
bottom = other;
|
||||
} else {
|
||||
top = other;
|
||||
bottom = region;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
if (top->coverage (bottom->position(), bottom->last_frame()) != OverlapNone) {
|
||||
|
||||
/* check if the upper region is within the lower region */
|
||||
|
||||
if (top->first_frame() > bottom->first_frame() &&
|
||||
top->last_frame() < bottom->last_frame()) {
|
||||
|
||||
|
||||
/* [ -------- top ------- ]
|
||||
* {=========== bottom =============}
|
||||
*/
|
||||
|
||||
/* to avoid discontinuities at the region boundaries of an internal
|
||||
overlap (this region is completely within another), we create
|
||||
two hidden crossfades at each boundary. this is not dependent
|
||||
on the auto-xfade option, because we require it as basic
|
||||
audio engineering.
|
||||
*/
|
||||
|
||||
jack_nframes_t xfade_length = min ((jack_nframes_t) 720, top->length());
|
||||
|
||||
/* in, out */
|
||||
xfade = new Crossfade (*top, *bottom, xfade_length, top->first_frame(), StartOfIn);
|
||||
add_crossfade (*xfade);
|
||||
xfade = new Crossfade (*bottom, *top, xfade_length, top->last_frame() - xfade_length, EndOfOut);
|
||||
add_crossfade (*xfade);
|
||||
|
||||
} else {
|
||||
|
||||
xfade = new Crossfade (*other, *region, _session.get_xfade_model(), _session.get_crossfades_active());
|
||||
add_crossfade (*xfade);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
catch (failed_constructor& err) {
|
||||
continue;
|
||||
}
|
||||
|
||||
catch (Crossfade::NoCrossfadeHere& err) {
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AudioPlaylist::add_crossfade (Crossfade& xfade)
|
||||
{
|
||||
Crossfades::iterator ci;
|
||||
|
||||
for (ci = _crossfades.begin(); ci != _crossfades.end(); ++ci) {
|
||||
if (*(*ci) == xfade) { // Crossfade::operator==()
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ci != _crossfades.end()) {
|
||||
delete &xfade;
|
||||
} else {
|
||||
_crossfades.push_back (&xfade);
|
||||
|
||||
xfade.Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated));
|
||||
xfade.StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed));
|
||||
|
||||
notify_crossfade_added (&xfade);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioPlaylist::notify_crossfade_added (Crossfade *x)
|
||||
{
|
||||
if (atomic_read(&block_notifications)) {
|
||||
_pending_xfade_adds.insert (_pending_xfade_adds.end(), x);
|
||||
} else {
|
||||
NewCrossfade (x); /* EMIT SIGNAL */
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AudioPlaylist::crossfade_invalidated (Crossfade* xfade)
|
||||
{
|
||||
Crossfades::iterator i;
|
||||
|
||||
xfade->in().resume_fade_in ();
|
||||
xfade->out().resume_fade_out ();
|
||||
|
||||
if ((i = find (_crossfades.begin(), _crossfades.end(), xfade)) != _crossfades.end()) {
|
||||
_crossfades.erase (i);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
AudioPlaylist::set_state (const XMLNode& node)
|
||||
{
|
||||
XMLNode *child;
|
||||
XMLNodeList nlist;
|
||||
XMLNodeConstIterator niter;
|
||||
|
||||
if (!in_set_state) {
|
||||
Playlist::set_state (node);
|
||||
}
|
||||
|
||||
nlist = node.children();
|
||||
|
||||
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
||||
|
||||
child = *niter;
|
||||
|
||||
if (child->name() == "Crossfade") {
|
||||
|
||||
Crossfade *xfade;
|
||||
|
||||
try {
|
||||
xfade = new Crossfade (*((const Playlist *)this), *child);
|
||||
}
|
||||
|
||||
catch (failed_constructor& err) {
|
||||
// cout << compose (_("could not create crossfade object in playlist %1"),
|
||||
// _name)
|
||||
// << endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
Crossfades::iterator ci;
|
||||
|
||||
for (ci = _crossfades.begin(); ci != _crossfades.end(); ++ci) {
|
||||
if (*(*ci) == *xfade) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ci == _crossfades.end()) {
|
||||
_crossfades.push_back (xfade);
|
||||
xfade->Invalidated.connect (mem_fun (*this, &AudioPlaylist::crossfade_invalidated));
|
||||
xfade->StateChanged.connect (mem_fun (*this, &AudioPlaylist::crossfade_changed));
|
||||
/* no need to notify here */
|
||||
} else {
|
||||
delete xfade;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
AudioPlaylist::drop_all_states ()
|
||||
{
|
||||
set<Crossfade*> all_xfades;
|
||||
set<Region*> all_regions;
|
||||
|
||||
/* find every region we've ever used, and add it to the set of
|
||||
all regions. same for xfades;
|
||||
*/
|
||||
|
||||
for (StateMap::iterator i = states.begin(); i != states.end(); ++i) {
|
||||
|
||||
AudioPlaylist::State* apstate = dynamic_cast<AudioPlaylist::State*> (*i);
|
||||
|
||||
for (RegionList::iterator r = apstate->regions.begin(); r != apstate->regions.end(); ++r) {
|
||||
all_regions.insert (*r);
|
||||
}
|
||||
for (Crossfades::iterator xf = apstate->crossfades.begin(); xf != apstate->crossfades.end(); ++xf) {
|
||||
all_xfades.insert (*xf);
|
||||
}
|
||||
}
|
||||
|
||||
/* now remove from the "all" lists every region that is in the current list. */
|
||||
|
||||
for (list<Region*>::iterator i = regions.begin(); i != regions.end(); ++i) {
|
||||
set<Region*>::iterator x = all_regions.find (*i);
|
||||
if (x != all_regions.end()) {
|
||||
all_regions.erase (x);
|
||||
}
|
||||
}
|
||||
|
||||
/* ditto for every crossfade */
|
||||
|
||||
for (list<Crossfade*>::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
|
||||
set<Crossfade*>::iterator x = all_xfades.find (*i);
|
||||
if (x != all_xfades.end()) {
|
||||
all_xfades.erase (x);
|
||||
}
|
||||
}
|
||||
|
||||
/* delete every region that is left - these are all things that are part of our "history" */
|
||||
|
||||
for (set<Region *>::iterator ar = all_regions.begin(); ar != all_regions.end(); ++ar) {
|
||||
(*ar)->unlock_sources ();
|
||||
delete *ar;
|
||||
}
|
||||
|
||||
/* delete every crossfade that is left (ditto as per regions) */
|
||||
|
||||
for (set<Crossfade *>::iterator axf = all_xfades.begin(); axf != all_xfades.end(); ++axf) {
|
||||
delete *axf;
|
||||
}
|
||||
|
||||
/* Now do the generic thing ... */
|
||||
|
||||
StateManager::drop_all_states ();
|
||||
}
|
||||
|
||||
StateManager::State*
|
||||
AudioPlaylist::state_factory (std::string why) const
|
||||
{
|
||||
State* state = new State (why);
|
||||
|
||||
state->regions = regions;
|
||||
state->region_states.clear ();
|
||||
for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
|
||||
state->region_states.push_back ((*i)->get_memento());
|
||||
}
|
||||
|
||||
state->crossfades = _crossfades;
|
||||
state->crossfade_states.clear ();
|
||||
for (Crossfades::const_iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
|
||||
state->crossfade_states.push_back ((*i)->get_memento());
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
Change
|
||||
AudioPlaylist::restore_state (StateManager::State& state)
|
||||
{
|
||||
{
|
||||
RegionLock rlock (this);
|
||||
State* apstate = dynamic_cast<State*> (&state);
|
||||
|
||||
in_set_state = true;
|
||||
|
||||
regions = apstate->regions;
|
||||
|
||||
for (list<UndoAction>::iterator s = apstate->region_states.begin(); s != apstate->region_states.end(); ++s) {
|
||||
*s;
|
||||
}
|
||||
|
||||
_crossfades = apstate->crossfades;
|
||||
|
||||
for (list<UndoAction>::iterator s = apstate->crossfade_states.begin(); s != apstate->crossfade_states.end(); ++s) {
|
||||
*s;
|
||||
}
|
||||
|
||||
in_set_state = false;
|
||||
}
|
||||
|
||||
notify_length_changed ();
|
||||
return Change (~0);
|
||||
}
|
||||
|
||||
UndoAction
|
||||
AudioPlaylist::get_memento () const
|
||||
{
|
||||
return sigc::bind (mem_fun (*(const_cast<AudioPlaylist*> (this)), &StateManager::use_state), _current_state_id);
|
||||
}
|
||||
|
||||
void
|
||||
AudioPlaylist::clear (bool with_delete, bool with_save)
|
||||
{
|
||||
if (with_delete) {
|
||||
for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
|
||||
delete *i;
|
||||
}
|
||||
}
|
||||
|
||||
_crossfades.clear ();
|
||||
|
||||
Playlist::clear (with_delete, with_save);
|
||||
}
|
||||
|
||||
XMLNode&
|
||||
AudioPlaylist::state (bool full_state)
|
||||
{
|
||||
XMLNode& node = Playlist::state (full_state);
|
||||
|
||||
if (full_state) {
|
||||
for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
|
||||
node.add_child_nocopy ((*i)->get_state());
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
void
|
||||
AudioPlaylist::dump () const
|
||||
{
|
||||
Region *r;
|
||||
Crossfade *x;
|
||||
|
||||
cerr << "Playlist \"" << _name << "\" " << endl
|
||||
<< regions.size() << " regions "
|
||||
<< _crossfades.size() << " crossfades"
|
||||
<< endl;
|
||||
|
||||
for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
|
||||
r = *i;
|
||||
cerr << " " << r->name() << " @ " << r << " ["
|
||||
<< r->start() << "+" << r->length()
|
||||
<< "] at "
|
||||
<< r->position()
|
||||
<< " on layer "
|
||||
<< r->layer ()
|
||||
<< endl;
|
||||
}
|
||||
|
||||
for (Crossfades::const_iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
|
||||
x = *i;
|
||||
cerr << " xfade ["
|
||||
<< x->out().name()
|
||||
<< ','
|
||||
<< x->in().name()
|
||||
<< " @ "
|
||||
<< x->position()
|
||||
<< " length = "
|
||||
<< x->length ()
|
||||
<< " active ? "
|
||||
<< (x->active() ? "yes" : "no")
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
AudioPlaylist::destroy_region (Region* region)
|
||||
{
|
||||
AudioRegion* r = dynamic_cast<AudioRegion*> (region);
|
||||
bool changed = false;
|
||||
Crossfades::iterator c, ctmp;
|
||||
set<Crossfade*> unique_xfades;
|
||||
|
||||
if (r == 0) {
|
||||
fatal << _("programming error: non-audio Region passed to remove_overlap in audio playlist")
|
||||
<< endmsg;
|
||||
/*NOTREACHED*/
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
RegionLock rlock (this);
|
||||
RegionList::iterator i;
|
||||
RegionList::iterator tmp;
|
||||
|
||||
for (i = regions.begin(); i != regions.end(); ) {
|
||||
|
||||
tmp = i;
|
||||
++tmp;
|
||||
|
||||
if ((*i) == region) {
|
||||
(*i)->unlock_sources ();
|
||||
regions.erase (i);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
i = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
for (c = _crossfades.begin(); c != _crossfades.end(); ) {
|
||||
ctmp = c;
|
||||
++ctmp;
|
||||
|
||||
if ((*c)->involves (*r)) {
|
||||
unique_xfades.insert (*c);
|
||||
_crossfades.erase (c);
|
||||
}
|
||||
|
||||
c = ctmp;
|
||||
}
|
||||
|
||||
for (StateMap::iterator s = states.begin(); s != states.end(); ) {
|
||||
StateMap::iterator tmp;
|
||||
|
||||
tmp = s;
|
||||
++tmp;
|
||||
|
||||
State* astate = dynamic_cast<State*> (*s);
|
||||
|
||||
for (c = astate->crossfades.begin(); c != astate->crossfades.end(); ) {
|
||||
|
||||
ctmp = c;
|
||||
++ctmp;
|
||||
|
||||
if ((*c)->involves (*r)) {
|
||||
unique_xfades.insert (*c);
|
||||
_crossfades.erase (c);
|
||||
}
|
||||
|
||||
c = ctmp;
|
||||
}
|
||||
|
||||
list<UndoAction>::iterator rsi, rsitmp;
|
||||
RegionList::iterator ri, ritmp;
|
||||
|
||||
for (ri = astate->regions.begin(), rsi = astate->region_states.begin();
|
||||
ri != astate->regions.end() && rsi != astate->region_states.end();) {
|
||||
|
||||
|
||||
ritmp = ri;
|
||||
++ritmp;
|
||||
|
||||
rsitmp = rsi;
|
||||
++rsitmp;
|
||||
|
||||
if (region == (*ri)) {
|
||||
astate->regions.erase (ri);
|
||||
astate->region_states.erase (rsi);
|
||||
}
|
||||
|
||||
ri = ritmp;
|
||||
rsi = rsitmp;
|
||||
}
|
||||
|
||||
s = tmp;
|
||||
}
|
||||
|
||||
for (set<Crossfade*>::iterator c = unique_xfades.begin(); c != unique_xfades.end(); ++c) {
|
||||
delete *c;
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
/* overload this, it normally means "removed", not destroyed */
|
||||
notify_region_removed (region);
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
void
|
||||
AudioPlaylist::crossfade_changed (Change ignored)
|
||||
{
|
||||
if (in_flush) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* XXX is there a loop here? can an xfade change not happen
|
||||
due to a playlist change? well, sure activation would
|
||||
be an example. maybe we should check the type of change
|
||||
that occured.
|
||||
*/
|
||||
|
||||
maybe_save_state (_("xfade change"));
|
||||
notify_modified ();
|
||||
}
|
||||
|
||||
void
|
||||
AudioPlaylist::get_equivalent_regions (const AudioRegion& other, vector<AudioRegion*>& results)
|
||||
{
|
||||
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
|
||||
|
||||
AudioRegion* ar = dynamic_cast<AudioRegion*> (*i);
|
||||
|
||||
if (ar && ar->equivalent (other)) {
|
||||
results.push_back (ar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AudioPlaylist::get_region_list_equivalent_regions (const AudioRegion& other, vector<AudioRegion*>& results)
|
||||
{
|
||||
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
|
||||
|
||||
AudioRegion* ar = dynamic_cast<AudioRegion*> (*i);
|
||||
|
||||
if (ar && ar->region_list_equivalent (other)) {
|
||||
results.push_back (ar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
AudioPlaylist::region_changed (Change what_changed, Region* region)
|
||||
{
|
||||
if (in_flush || in_set_state) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Change our_interests = Change (AudioRegion::FadeInChanged|
|
||||
AudioRegion::FadeOutChanged|
|
||||
AudioRegion::FadeInActiveChanged|
|
||||
AudioRegion::FadeOutActiveChanged|
|
||||
AudioRegion::EnvelopeActiveChanged|
|
||||
AudioRegion::ScaleAmplitudeChanged|
|
||||
AudioRegion::EnvelopeChanged);
|
||||
bool parent_wants_notify;
|
||||
|
||||
parent_wants_notify = Playlist::region_changed (what_changed, region);
|
||||
|
||||
maybe_save_state (_("region modified"));
|
||||
|
||||
if (parent_wants_notify || (what_changed & our_interests)) {
|
||||
notify_modified ();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
AudioPlaylist::crossfades_at (jack_nframes_t frame, Crossfades& clist)
|
||||
{
|
||||
RegionLock rlock (this);
|
||||
|
||||
for (Crossfades::iterator i = _crossfades.begin(); i != _crossfades.end(); ++i) {
|
||||
jack_nframes_t start, end;
|
||||
|
||||
start = (*i)->position();
|
||||
end = start + (*i)->overlap_length(); // not length(), important difference
|
||||
|
||||
if (frame >= start && frame <= end) {
|
||||
clist.push_back (*i);
|
||||
}
|
||||
}
|
||||
}
|
||||
1063
libs/ardour/audio_track.cc
Normal file
1063
libs/ardour/audio_track.cc
Normal file
File diff suppressed because it is too large
Load Diff
1115
libs/ardour/audioengine.cc
Normal file
1115
libs/ardour/audioengine.cc
Normal file
File diff suppressed because it is too large
Load Diff
87
libs/ardour/audiofilter.cc
Normal file
87
libs/ardour/audiofilter.cc
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
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$
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
#include <cerrno>
|
||||
|
||||
#include <pbd/basename.h>
|
||||
#include <ardour/filesource.h>
|
||||
#include <ardour/session.h>
|
||||
#include <ardour/audioregion.h>
|
||||
#include <ardour/audiofilter.h>
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
using namespace ARDOUR;
|
||||
|
||||
int
|
||||
AudioFilter::make_new_sources (AudioRegion& region, AudioRegion::SourceList& nsrcs)
|
||||
{
|
||||
vector<string> names = region.master_source_names();
|
||||
|
||||
for (uint32_t i = 0; i < region.n_channels(); ++i) {
|
||||
|
||||
string path = session.path_from_region_name (PBD::basename_nosuffix (names[i]), string (""));
|
||||
|
||||
if (path.length() == 0) {
|
||||
error << compose (_("audiofilter: error creating name for new audio file based on %1"), region.name())
|
||||
<< endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
try {
|
||||
nsrcs.push_back (new FileSource (path, session.frame_rate()));
|
||||
}
|
||||
|
||||
catch (failed_constructor& err) {
|
||||
error << compose (_("audiofilter: error creating new audio file %1 (%2)"), path, strerror (errno)) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
AudioFilter::finish (AudioRegion& region, AudioRegion::SourceList& nsrcs)
|
||||
{
|
||||
string region_name;
|
||||
|
||||
/* update headers on new sources */
|
||||
|
||||
time_t xnow;
|
||||
struct tm* now;
|
||||
|
||||
time (&xnow);
|
||||
now = localtime (&xnow);
|
||||
|
||||
for (AudioRegion::SourceList::iterator si = nsrcs.begin(); si != nsrcs.end(); ++si) {
|
||||
dynamic_cast<FileSource*>((*si))->update_header (session.transport_frame(), *now, xnow);
|
||||
}
|
||||
|
||||
/* create a new region */
|
||||
|
||||
region_name = session.new_region_name (region.name());
|
||||
results.clear ();
|
||||
results.push_back (new AudioRegion (nsrcs, 0, region.length(), region_name, 0,
|
||||
Region::Flag (Region::WholeFile|Region::DefaultFlags)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
1405
libs/ardour/audioregion.cc
Normal file
1405
libs/ardour/audioregion.cc
Normal file
File diff suppressed because it is too large
Load Diff
181
libs/ardour/auditioner.cc
Normal file
181
libs/ardour/auditioner.cc
Normal file
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
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$
|
||||
*/
|
||||
|
||||
#include <pbd/lockmonitor.h>
|
||||
|
||||
#include <ardour/diskstream.h>
|
||||
#include <ardour/audioregion.h>
|
||||
#include <ardour/route.h>
|
||||
#include <ardour/session.h>
|
||||
#include <ardour/auditioner.h>
|
||||
#include <ardour/audioplaylist.h>
|
||||
#include <ardour/panner.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace ARDOUR;
|
||||
|
||||
Auditioner::Auditioner (Session& s)
|
||||
: AudioTrack (s, "auditioner", Route::Hidden)
|
||||
{
|
||||
string left = Config->get_auditioner_output_left();
|
||||
string right = Config->get_auditioner_output_right();
|
||||
|
||||
if ((left.length() == 0) && (right.length() == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
defer_pan_reset ();
|
||||
|
||||
if (left.length()) {
|
||||
add_output_port (left, this);
|
||||
}
|
||||
|
||||
if (right.length()) {
|
||||
disk_stream().add_channel();
|
||||
add_output_port (right, this);
|
||||
}
|
||||
|
||||
allow_pan_reset ();
|
||||
|
||||
IO::output_changed.connect (mem_fun (*this, &Auditioner::output_changed));
|
||||
|
||||
the_region = 0;
|
||||
atomic_set (&_active, 0);
|
||||
}
|
||||
|
||||
Auditioner::~Auditioner ()
|
||||
{
|
||||
}
|
||||
|
||||
AudioPlaylist&
|
||||
Auditioner::prepare_playlist ()
|
||||
{
|
||||
diskstream->playlist()->clear (false, false);
|
||||
return *diskstream->playlist();
|
||||
}
|
||||
|
||||
void
|
||||
Auditioner::audition_current_playlist ()
|
||||
{
|
||||
if (atomic_read (&_active)) {
|
||||
/* don't go via session for this, because we are going
|
||||
to remain active.
|
||||
*/
|
||||
cancel_audition ();
|
||||
}
|
||||
|
||||
LockMonitor lm (lock, __LINE__, __FILE__);
|
||||
diskstream->seek (0);
|
||||
length = diskstream->playlist()->get_maximum_extent();
|
||||
current_frame = 0;
|
||||
|
||||
/* force a panner reset now that we have all channels */
|
||||
|
||||
_panner->reset (n_outputs(), diskstream->n_channels());
|
||||
|
||||
atomic_set (&_active, 1);
|
||||
}
|
||||
|
||||
void
|
||||
Auditioner::audition_region (AudioRegion& region)
|
||||
{
|
||||
if (atomic_read (&_active)) {
|
||||
/* don't go via session for this, because we are going
|
||||
to remain active.
|
||||
*/
|
||||
cancel_audition ();
|
||||
}
|
||||
|
||||
LockMonitor lm (lock, __LINE__, __FILE__);
|
||||
|
||||
the_region = new AudioRegion (region);
|
||||
the_region->set_position (0, this);
|
||||
|
||||
diskstream->playlist()->clear (true, false);
|
||||
diskstream->playlist()->add_region (*the_region, 0, 1, false);
|
||||
|
||||
while (diskstream->n_channels() < the_region->n_channels()) {
|
||||
diskstream->add_channel ();
|
||||
}
|
||||
|
||||
while (diskstream->n_channels() > the_region->n_channels()) {
|
||||
diskstream->remove_channel ();
|
||||
}
|
||||
|
||||
/* force a panner reset now that we have all channels */
|
||||
|
||||
_panner->reset (n_outputs(), diskstream->n_channels());
|
||||
|
||||
length = the_region->length();
|
||||
diskstream->seek (0);
|
||||
current_frame = 0;
|
||||
atomic_set (&_active, 1);
|
||||
}
|
||||
|
||||
int
|
||||
Auditioner::play_audition (jack_nframes_t nframes)
|
||||
{
|
||||
bool need_butler;
|
||||
jack_nframes_t this_nframes;
|
||||
int ret;
|
||||
|
||||
if (atomic_read (&_active) == 0) {
|
||||
silence (nframes, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
this_nframes = min (nframes, length - current_frame);
|
||||
|
||||
diskstream->prepare ();
|
||||
|
||||
if ((ret = roll (this_nframes, current_frame, current_frame + nframes, 0, false, false, false)) != 0) {
|
||||
silence (nframes, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
need_butler = diskstream->commit (this_nframes);
|
||||
current_frame += this_nframes;
|
||||
|
||||
if (current_frame >= length) {
|
||||
_session.cancel_audition ();
|
||||
return 0;
|
||||
} else {
|
||||
return need_butler ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Auditioner::output_changed (IOChange change, void* src)
|
||||
{
|
||||
if (change & ConnectionsChanged) {
|
||||
const char ** connections;
|
||||
connections = output (0)->get_connections ();
|
||||
if (connections) {
|
||||
Config->set_auditioner_output_left (connections[0]);
|
||||
free (connections);
|
||||
}
|
||||
|
||||
connections = output (1)->get_connections ();
|
||||
if (connections) {
|
||||
Config->set_auditioner_output_right (connections[0]);
|
||||
free (connections);
|
||||
}
|
||||
}
|
||||
}
|
||||
13
libs/ardour/automation.cc
Normal file
13
libs/ardour/automation.cc
Normal file
@@ -0,0 +1,13 @@
|
||||
#include <stdint.h>
|
||||
|
||||
template<class AutomatedObject>
|
||||
struct AutomationEvent {
|
||||
uint32_t frame;
|
||||
AutomatedObject *object;
|
||||
void (AutomatedObject::*function) (void *);
|
||||
void *arg;
|
||||
|
||||
void operator() (){
|
||||
object->function (arg);
|
||||
}
|
||||
};
|
||||
1211
libs/ardour/automation_event.cc
Normal file
1211
libs/ardour/automation_event.cc
Normal file
File diff suppressed because it is too large
Load Diff
1105
libs/ardour/configuration.cc
Normal file
1105
libs/ardour/configuration.cc
Normal file
File diff suppressed because it is too large
Load Diff
275
libs/ardour/connection.cc
Normal file
275
libs/ardour/connection.cc
Normal file
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
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$
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <pbd/failed_constructor.h>
|
||||
#include <ardour/ardour.h>
|
||||
#include <ardour/connection.h>
|
||||
#include <pbd/xml++.h>
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
using namespace ARDOUR;
|
||||
using namespace PBD;
|
||||
|
||||
Connection::Connection (const XMLNode& node)
|
||||
{
|
||||
if (set_state (node)) {
|
||||
throw failed_constructor();
|
||||
}
|
||||
}
|
||||
|
||||
InputConnection::InputConnection (const XMLNode& node)
|
||||
: Connection (node)
|
||||
{
|
||||
}
|
||||
|
||||
OutputConnection::OutputConnection (const XMLNode& node)
|
||||
: Connection (node)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Connection::set_name (string name, void *src)
|
||||
{
|
||||
_name = name;
|
||||
NameChanged (src);
|
||||
}
|
||||
|
||||
void
|
||||
Connection::add_connection (int port, string portname)
|
||||
{
|
||||
{
|
||||
LockMonitor lm (port_lock, __LINE__, __FILE__);
|
||||
_ports[port].push_back (portname);
|
||||
}
|
||||
ConnectionsChanged (port); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
void
|
||||
Connection::remove_connection (int port, string portname)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
{
|
||||
LockMonitor lm (port_lock, __LINE__, __FILE__);
|
||||
PortList& pl = _ports[port];
|
||||
PortList::iterator i = find (pl.begin(), pl.end(), portname);
|
||||
|
||||
if (i != pl.end()) {
|
||||
pl.erase (i);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
ConnectionsChanged (port); /* EMIT SIGNAL */
|
||||
}
|
||||
}
|
||||
|
||||
const Connection::PortList&
|
||||
Connection::port_connections (int port) const
|
||||
{
|
||||
LockMonitor lm (port_lock, __LINE__, __FILE__);
|
||||
return _ports[port];
|
||||
}
|
||||
|
||||
bool
|
||||
Connection::operator== (const Connection& other) const
|
||||
{
|
||||
return other._ports == _ports;
|
||||
}
|
||||
|
||||
void
|
||||
Connection::add_port ()
|
||||
{
|
||||
{
|
||||
LockMonitor lm (port_lock, __LINE__, __FILE__);
|
||||
_ports.push_back (PortList());
|
||||
}
|
||||
ConfigurationChanged(); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
void
|
||||
Connection::remove_port (int which_port)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
{
|
||||
LockMonitor lm (port_lock, __LINE__, __FILE__);
|
||||
vector<PortList>::iterator i;
|
||||
int n;
|
||||
|
||||
for (n = 0, i = _ports.begin(); i != _ports.end() && n < which_port; ++i, ++n);
|
||||
|
||||
if (i != _ports.end()) {
|
||||
_ports.erase (i);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
ConfigurationChanged(); /* EMIT SIGNAL */
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Connection::clear ()
|
||||
{
|
||||
{
|
||||
LockMonitor lm (port_lock, __LINE__, __FILE__);
|
||||
_ports.clear ();
|
||||
}
|
||||
|
||||
ConfigurationChanged(); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
XMLNode&
|
||||
Connection::get_state ()
|
||||
{
|
||||
XMLNode *node;
|
||||
string str;
|
||||
|
||||
if (dynamic_cast<InputConnection *> (this)) {
|
||||
node = new XMLNode ("InputConnection");
|
||||
} else {
|
||||
node = new XMLNode ("OutputConnection");
|
||||
}
|
||||
|
||||
node->add_property ("name", _name);
|
||||
|
||||
for (vector<PortList>::iterator i = _ports.begin(); i != _ports.end(); ++i) {
|
||||
|
||||
str += '{';
|
||||
|
||||
for (vector<string>::iterator ii = (*i).begin(); ii != (*i).end(); ++ii) {
|
||||
if (ii != (*i).begin()) {
|
||||
str += ',';
|
||||
}
|
||||
str += *ii;
|
||||
}
|
||||
str += '}';
|
||||
}
|
||||
|
||||
node->add_property ("connections", str);
|
||||
|
||||
return *node;
|
||||
}
|
||||
|
||||
int
|
||||
Connection::set_state (const XMLNode& node)
|
||||
{
|
||||
const XMLProperty *prop;
|
||||
|
||||
if ((prop = node.property ("name")) == 0) {
|
||||
error << _("Node for Connection has no \"name\" property") << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
_name = prop->value();
|
||||
_sysdep = false;
|
||||
|
||||
if ((prop = node.property ("connections")) == 0) {
|
||||
error << _("Node for Connection has no \"connections\" property") << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
set_connections (prop->value());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
Connection::set_connections (const string& str)
|
||||
{
|
||||
vector<string> ports;
|
||||
int i;
|
||||
int n;
|
||||
int nports;
|
||||
|
||||
if ((nports = count (str.begin(), str.end(), '{')) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (n = 0; n < nports; ++n) {
|
||||
add_port ();
|
||||
}
|
||||
|
||||
string::size_type start, end, ostart;
|
||||
|
||||
ostart = 0;
|
||||
start = 0;
|
||||
end = 0;
|
||||
i = 0;
|
||||
|
||||
while ((start = str.find_first_of ('{', ostart)) != string::npos) {
|
||||
start += 1;
|
||||
|
||||
if ((end = str.find_first_of ('}', start)) == string::npos) {
|
||||
error << compose(_("IO: badly formed string in XML node for inputs \"%1\""), str) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
|
||||
error << compose(_("bad input string in XML node \"%1\""), str) << endmsg;
|
||||
|
||||
return -1;
|
||||
|
||||
} else if (n > 0) {
|
||||
|
||||
for (int x = 0; x < n; ++x) {
|
||||
add_connection (i, ports[x]);
|
||||
}
|
||||
}
|
||||
|
||||
ostart = end+1;
|
||||
i++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
Connection::parse_io_string (const string& str, vector<string>& ports)
|
||||
{
|
||||
string::size_type pos, opos;
|
||||
|
||||
if (str.length() == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
pos = 0;
|
||||
opos = 0;
|
||||
|
||||
ports.clear ();
|
||||
|
||||
while ((pos = str.find_first_of (',', opos)) != string::npos) {
|
||||
ports.push_back (str.substr (opos, pos - opos));
|
||||
opos = pos + 1;
|
||||
}
|
||||
|
||||
if (opos < str.length()) {
|
||||
ports.push_back (str.substr(opos));
|
||||
}
|
||||
|
||||
return ports.size();
|
||||
}
|
||||
|
||||
877
libs/ardour/crossfade.cc
Normal file
877
libs/ardour/crossfade.cc
Normal file
@@ -0,0 +1,877 @@
|
||||
/*
|
||||
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$
|
||||
*/
|
||||
|
||||
#include <sigc++/bind.h>
|
||||
|
||||
#include <ardour/types.h>
|
||||
#include <ardour/crossfade.h>
|
||||
#include <ardour/crossfade_compare.h>
|
||||
#include <ardour/audioregion.h>
|
||||
#include <ardour/playlist.h>
|
||||
#include <ardour/utils.h>
|
||||
#include <ardour/session.h>
|
||||
|
||||
#include "i18n.h"
|
||||
#include <locale.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace ARDOUR;
|
||||
//using namespace sigc;
|
||||
|
||||
jack_nframes_t Crossfade::_short_xfade_length = 0;
|
||||
Change Crossfade::ActiveChanged = ARDOUR::new_change();
|
||||
|
||||
/* XXX if and when we ever implement parallel processing of the process()
|
||||
callback, these will need to be handled on a per-thread basis.
|
||||
*/
|
||||
|
||||
Sample* Crossfade::crossfade_buffer_out = 0;
|
||||
Sample* Crossfade::crossfade_buffer_in = 0;
|
||||
|
||||
void
|
||||
Crossfade::set_buffer_size (jack_nframes_t sz)
|
||||
{
|
||||
if (crossfade_buffer_out) {
|
||||
delete [] crossfade_buffer_out;
|
||||
crossfade_buffer_out = 0;
|
||||
}
|
||||
|
||||
if (crossfade_buffer_in) {
|
||||
delete [] crossfade_buffer_in;
|
||||
crossfade_buffer_in = 0;
|
||||
}
|
||||
|
||||
if (sz) {
|
||||
crossfade_buffer_out = new Sample[sz];
|
||||
crossfade_buffer_in = new Sample[sz];
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Crossfade::operator== (const Crossfade& other)
|
||||
{
|
||||
return (_in == other._in) && (_out == other._out);
|
||||
}
|
||||
|
||||
Crossfade::Crossfade (ARDOUR::AudioRegion& in, ARDOUR::AudioRegion& out,
|
||||
jack_nframes_t length,
|
||||
jack_nframes_t position,
|
||||
AnchorPoint ap)
|
||||
: _fade_in (0.0, 2.0, 1.0), // linear (gain coefficient) => -inf..+6dB
|
||||
_fade_out (0.0, 2.0, 1.0) // linear (gain coefficient) => -inf..+6dB
|
||||
{
|
||||
_in = ∈
|
||||
_out = &out;
|
||||
_length = length;
|
||||
_position = position;
|
||||
_anchor_point = ap;
|
||||
_follow_overlap = false;
|
||||
_active = true;
|
||||
_fixed = true;
|
||||
|
||||
initialize ();
|
||||
}
|
||||
|
||||
Crossfade::Crossfade (ARDOUR::AudioRegion& a, ARDOUR::AudioRegion& b, CrossfadeModel model, bool act)
|
||||
: _fade_in (0.0, 2.0, 1.0), // linear (gain coefficient) => -inf..+6dB
|
||||
_fade_out (0.0, 2.0, 1.0) // linear (gain coefficient) => -inf..+6dB
|
||||
{
|
||||
_in_update = false;
|
||||
_fixed = false;
|
||||
|
||||
if (compute (a, b, model)) {
|
||||
throw failed_constructor();
|
||||
}
|
||||
|
||||
_active = act;
|
||||
|
||||
initialize ();
|
||||
|
||||
}
|
||||
|
||||
Crossfade::Crossfade (const Playlist& playlist, XMLNode& node)
|
||||
: _fade_in (0.0, 2.0, 1.0), // linear (gain coefficient) => -inf..+6dB
|
||||
_fade_out (0.0, 2.0, 1.0) // linear (gain coefficient) => -inf..+6dB
|
||||
{
|
||||
Region* r;
|
||||
XMLProperty* prop;
|
||||
id_t id;
|
||||
LocaleGuard lg (X_("POSIX"));
|
||||
|
||||
/* we have to find the in/out regions before we can do anything else */
|
||||
|
||||
if ((prop = node.property ("in")) == 0) {
|
||||
error << _("Crossfade: no \"in\" region in state") << endmsg;
|
||||
throw failed_constructor();
|
||||
}
|
||||
|
||||
sscanf (prop->value().c_str(), "%llu", &id);
|
||||
|
||||
if ((r = playlist.find_region (id)) == 0) {
|
||||
error << compose (_("Crossfade: no \"in\" region %1 found in playlist %2"), id, playlist.name())
|
||||
<< endmsg;
|
||||
throw failed_constructor();
|
||||
}
|
||||
|
||||
if ((_in = dynamic_cast<AudioRegion*> (r)) == 0) {
|
||||
throw failed_constructor();
|
||||
}
|
||||
|
||||
if ((prop = node.property ("out")) == 0) {
|
||||
error << _("Crossfade: no \"out\" region in state") << endmsg;
|
||||
throw failed_constructor();
|
||||
}
|
||||
|
||||
sscanf (prop->value().c_str(), "%llu", &id);
|
||||
|
||||
if ((r = playlist.find_region (id)) == 0) {
|
||||
error << compose (_("Crossfade: no \"out\" region %1 found in playlist %2"), id, playlist.name())
|
||||
<< endmsg;
|
||||
throw failed_constructor();
|
||||
}
|
||||
|
||||
if ((_out = dynamic_cast<AudioRegion*> (r)) == 0) {
|
||||
throw failed_constructor();
|
||||
}
|
||||
|
||||
_length = 0;
|
||||
initialize();
|
||||
|
||||
if (set_state (node)) {
|
||||
throw failed_constructor();
|
||||
}
|
||||
}
|
||||
|
||||
Crossfade::~Crossfade ()
|
||||
{
|
||||
for (StateMap::iterator i = states.begin(); i != states.end(); ++i) {
|
||||
delete *i;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Crossfade::initialize ()
|
||||
{
|
||||
_in_update = false;
|
||||
|
||||
_out->suspend_fade_out ();
|
||||
_in->suspend_fade_in ();
|
||||
|
||||
_fade_out.freeze ();
|
||||
_fade_out.clear ();
|
||||
_fade_out.add (0.0, 1.0);
|
||||
_fade_out.add ((_length * 0.1), 0.99);
|
||||
_fade_out.add ((_length * 0.2), 0.97);
|
||||
_fade_out.add ((_length * 0.8), 0.03);
|
||||
_fade_out.add ((_length * 0.9), 0.01);
|
||||
_fade_out.add (_length, 0.0);
|
||||
_fade_out.thaw ();
|
||||
|
||||
_fade_in.freeze ();
|
||||
_fade_in.clear ();
|
||||
_fade_in.add (0.0, 0.0);
|
||||
_fade_in.add ((_length * 0.1), 0.01);
|
||||
_fade_in.add ((_length * 0.2), 0.03);
|
||||
_fade_in.add ((_length * 0.8), 0.97);
|
||||
_fade_in.add ((_length * 0.9), 0.99);
|
||||
_fade_in.add (_length, 1.0);
|
||||
_fade_in.thaw ();
|
||||
|
||||
// _in->StateChanged.connect (slot (*this, &Crossfade::member_changed));
|
||||
// _out->StateChanged.connect (slot (*this, &Crossfade::member_changed));
|
||||
|
||||
overlap_type = _in->coverage (_out->position(), _out->last_frame());
|
||||
|
||||
save_state ("initial");
|
||||
}
|
||||
|
||||
int
|
||||
Crossfade::compute (AudioRegion& a, AudioRegion& b, CrossfadeModel model)
|
||||
{
|
||||
AudioRegion* top;
|
||||
AudioRegion* bottom;
|
||||
jack_nframes_t short_xfade_length;
|
||||
|
||||
short_xfade_length = _short_xfade_length;
|
||||
|
||||
if (a.layer() < b.layer()) {
|
||||
top = &b;
|
||||
bottom = &a;
|
||||
} else {
|
||||
top = &a;
|
||||
bottom = &b;
|
||||
}
|
||||
|
||||
/* first check for matching ends */
|
||||
|
||||
if (top->first_frame() == bottom->first_frame()) {
|
||||
|
||||
/* Both regions start at the same point */
|
||||
|
||||
if (top->last_frame() < bottom->last_frame()) {
|
||||
|
||||
/* top ends before bottom, so put an xfade
|
||||
in at the end of top.
|
||||
*/
|
||||
|
||||
/* [-------- top ---------- ]
|
||||
* {====== bottom =====================}
|
||||
*/
|
||||
|
||||
_in = bottom;
|
||||
_out = top;
|
||||
|
||||
if (top->last_frame() < short_xfade_length) {
|
||||
_position = 0;
|
||||
} else {
|
||||
_position = top->last_frame() - short_xfade_length;
|
||||
}
|
||||
|
||||
_length = min (short_xfade_length, top->length());
|
||||
_follow_overlap = false;
|
||||
_anchor_point = EndOfIn;
|
||||
_active = true;
|
||||
_fixed = true;
|
||||
|
||||
} else {
|
||||
/* top ends after (or same time) as bottom - no xfade
|
||||
*/
|
||||
|
||||
/* [-------- top ------------------------ ]
|
||||
* {====== bottom =====================}
|
||||
*/
|
||||
|
||||
throw NoCrossfadeHere();
|
||||
}
|
||||
|
||||
} else if (top->last_frame() == bottom->last_frame()) {
|
||||
|
||||
/* Both regions end at the same point */
|
||||
|
||||
if (top->first_frame() > bottom->first_frame()) {
|
||||
|
||||
/* top starts after bottom, put an xfade in at the
|
||||
start of top
|
||||
*/
|
||||
|
||||
/* [-------- top ---------- ]
|
||||
* {====== bottom =====================}
|
||||
*/
|
||||
|
||||
_in = top;
|
||||
_out = bottom;
|
||||
_position = top->first_frame();
|
||||
_length = min (short_xfade_length, top->length());
|
||||
_follow_overlap = false;
|
||||
_anchor_point = StartOfIn;
|
||||
_active = true;
|
||||
_fixed = true;
|
||||
|
||||
} else {
|
||||
/* top starts before bottom - no xfade
|
||||
*/
|
||||
|
||||
/* [-------- top ------------------------ ]
|
||||
* {====== bottom =====================}
|
||||
*/
|
||||
|
||||
throw NoCrossfadeHere();
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* OK, time to do more regular overlapping */
|
||||
|
||||
OverlapType ot = top->coverage (bottom->first_frame(), bottom->last_frame());
|
||||
|
||||
switch (ot) {
|
||||
case OverlapNone:
|
||||
/* should be NOTREACHED as a precondition of creating
|
||||
a new crossfade, but we need to handle it here.
|
||||
*/
|
||||
throw NoCrossfadeHere();
|
||||
break;
|
||||
|
||||
case OverlapInternal:
|
||||
case OverlapExternal:
|
||||
/* should be NOTREACHED because of tests above */
|
||||
throw NoCrossfadeHere();
|
||||
break;
|
||||
|
||||
case OverlapEnd: /* top covers start of bottom but ends within it */
|
||||
|
||||
/* [---- top ------------------------]
|
||||
* { ==== bottom ============ }
|
||||
*/
|
||||
|
||||
_in = bottom;
|
||||
_out = top;
|
||||
_position = bottom->first_frame();
|
||||
_anchor_point = StartOfIn;
|
||||
|
||||
if (model == FullCrossfade) {
|
||||
_length = _out->first_frame() + _out->length() - _in->first_frame();
|
||||
/* leave active alone */
|
||||
_follow_overlap = true;
|
||||
} else {
|
||||
_length = min (short_xfade_length, top->length());
|
||||
_active = true;
|
||||
_follow_overlap = false;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case OverlapStart: /* top starts within bottom but covers bottom's end */
|
||||
|
||||
/* { ==== top ============ }
|
||||
* [---- bottom -------------------]
|
||||
*/
|
||||
|
||||
_in = top;
|
||||
_out = bottom;
|
||||
_position = top->first_frame();
|
||||
_anchor_point = StartOfIn;
|
||||
|
||||
if (model == FullCrossfade) {
|
||||
_length = _out->first_frame() + _out->length() - _in->first_frame();
|
||||
/* leave active alone */
|
||||
_follow_overlap = true;
|
||||
} else {
|
||||
_length = min (short_xfade_length, top->length());
|
||||
_active = true;
|
||||
_follow_overlap = false;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
jack_nframes_t
|
||||
Crossfade::read_at (Sample *buf, Sample *mixdown_buffer,
|
||||
float *gain_buffer, jack_nframes_t start, jack_nframes_t cnt, uint32_t chan_n,
|
||||
jack_nframes_t read_frames, jack_nframes_t skip_frames)
|
||||
{
|
||||
jack_nframes_t offset;
|
||||
jack_nframes_t to_write;
|
||||
|
||||
if (!_active) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (start < _position) {
|
||||
|
||||
/* handle an initial section of the read area that we do not
|
||||
cover.
|
||||
*/
|
||||
|
||||
offset = _position - start;
|
||||
|
||||
if (offset < cnt) {
|
||||
cnt -= offset;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
start = _position;
|
||||
buf += offset;
|
||||
to_write = min (_length, cnt);
|
||||
|
||||
} else {
|
||||
|
||||
to_write = min (_length - (start - _position), cnt);
|
||||
|
||||
}
|
||||
|
||||
offset = start - _position;
|
||||
|
||||
_out->read_at (crossfade_buffer_out, mixdown_buffer, gain_buffer, start, to_write, chan_n, read_frames, skip_frames);
|
||||
_in->read_at (crossfade_buffer_in, mixdown_buffer, gain_buffer, start, to_write, chan_n, read_frames, skip_frames);
|
||||
|
||||
float* fiv = new float[to_write];
|
||||
float* fov = new float[to_write];
|
||||
|
||||
_fade_in.get_vector (offset, offset+to_write, fiv, to_write);
|
||||
_fade_out.get_vector (offset, offset+to_write, fov, to_write);
|
||||
|
||||
/* note: although we have not explicitly taken into account the return values
|
||||
from _out->read_at() or _in->read_at(), the length() function does this
|
||||
implicitly. why? because it computes a value based on the in+out regions'
|
||||
position and length, and so we know precisely how much data they could return.
|
||||
*/
|
||||
|
||||
for (jack_nframes_t n = 0; n < to_write; ++n) {
|
||||
buf[n] = (crossfade_buffer_out[n] * fov[n]) + (crossfade_buffer_in[n] * fiv[n]);
|
||||
}
|
||||
|
||||
delete [] fov;
|
||||
delete [] fiv;
|
||||
|
||||
return to_write;
|
||||
}
|
||||
|
||||
OverlapType
|
||||
Crossfade::coverage (jack_nframes_t start, jack_nframes_t end) const
|
||||
{
|
||||
jack_nframes_t my_end = _position + _length;
|
||||
|
||||
if ((start >= _position) && (end <= my_end)) {
|
||||
return OverlapInternal;
|
||||
}
|
||||
if ((end >= _position) && (end <= my_end)) {
|
||||
return OverlapStart;
|
||||
}
|
||||
if ((start >= _position) && (start <= my_end)) {
|
||||
return OverlapEnd;
|
||||
}
|
||||
if ((_position >= start) && (_position <= end) && (my_end <= end)) {
|
||||
return OverlapExternal;
|
||||
}
|
||||
return OverlapNone;
|
||||
}
|
||||
|
||||
void
|
||||
Crossfade::set_active (bool yn)
|
||||
{
|
||||
if (_active != yn) {
|
||||
_active = yn;
|
||||
save_state (_("active changed"));
|
||||
send_state_changed (ActiveChanged);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Crossfade::refresh ()
|
||||
{
|
||||
/* crossfades must be between non-muted regions */
|
||||
|
||||
if (_out->muted() || _in->muted()) {
|
||||
Invalidated (this);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* overlap type must be Start, End or External */
|
||||
|
||||
OverlapType ot;
|
||||
|
||||
ot = _in->coverage (_out->first_frame(), _out->last_frame());
|
||||
|
||||
switch (ot) {
|
||||
case OverlapNone:
|
||||
case OverlapInternal:
|
||||
Invalidated (this);
|
||||
return false;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* overlap type must not have altered */
|
||||
|
||||
if (ot != overlap_type) {
|
||||
Invalidated (this);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* time to update */
|
||||
|
||||
return update (false);
|
||||
}
|
||||
|
||||
bool
|
||||
Crossfade::update (bool force)
|
||||
{
|
||||
jack_nframes_t newlen;
|
||||
bool save = false;
|
||||
|
||||
if (_follow_overlap) {
|
||||
newlen = _out->first_frame() + _out->length() - _in->first_frame();
|
||||
} else {
|
||||
newlen = _length;
|
||||
}
|
||||
|
||||
if (newlen == 0) {
|
||||
Invalidated (this);
|
||||
return false;
|
||||
}
|
||||
|
||||
_in_update = true;
|
||||
|
||||
if (force || (_follow_overlap && newlen != _length) || (_length > newlen)) {
|
||||
|
||||
double factor = newlen / (double) _length;
|
||||
|
||||
_fade_out.x_scale (factor);
|
||||
_fade_in.x_scale (factor);
|
||||
|
||||
_length = newlen;
|
||||
|
||||
save = true;
|
||||
|
||||
}
|
||||
|
||||
switch (_anchor_point) {
|
||||
case StartOfIn:
|
||||
if (_position != _in->first_frame()) {
|
||||
_position = _in->first_frame();
|
||||
save = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case EndOfIn:
|
||||
if (_position != _in->last_frame() - _length) {
|
||||
_position = _in->last_frame() - _length;
|
||||
save = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case EndOfOut:
|
||||
if (_position != _out->last_frame() - _length) {
|
||||
_position = _out->last_frame() - _length;
|
||||
save = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (save) {
|
||||
save_state ("updated");
|
||||
}
|
||||
|
||||
/* UI's may need to know that the overlap changed even
|
||||
though the xfade length did not.
|
||||
*/
|
||||
|
||||
send_state_changed (BoundsChanged); /* EMIT SIGNAL */
|
||||
|
||||
_in_update = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Crossfade::member_changed (Change what_changed)
|
||||
{
|
||||
Change what_we_care_about = Change (Region::MuteChanged|
|
||||
Region::LayerChanged|
|
||||
ARDOUR::BoundsChanged);
|
||||
|
||||
if (what_changed & what_we_care_about) {
|
||||
refresh ();
|
||||
}
|
||||
}
|
||||
|
||||
Change
|
||||
Crossfade::restore_state (StateManager::State& state)
|
||||
{
|
||||
CrossfadeState* xfstate = dynamic_cast<CrossfadeState*> (&state);
|
||||
Change what_changed = Change (0);
|
||||
|
||||
_in_update = true;
|
||||
|
||||
xfstate->fade_in_memento ();
|
||||
xfstate->fade_out_memento ();
|
||||
|
||||
if (_length != xfstate->length) {
|
||||
what_changed = Change (what_changed|LengthChanged);
|
||||
_length = xfstate->length;
|
||||
}
|
||||
if (_active != xfstate->active) {
|
||||
what_changed = Change (what_changed|ActiveChanged);
|
||||
_active = xfstate->active;
|
||||
}
|
||||
if (_position != xfstate->position) {
|
||||
what_changed = Change (what_changed|PositionChanged);
|
||||
_position = xfstate->position;
|
||||
}
|
||||
|
||||
/* XXX what to do about notifications for these? I don't
|
||||
think (G)UI cares about them because they are
|
||||
implicit in the bounds.
|
||||
*/
|
||||
|
||||
_follow_overlap = xfstate->follow_overlap;
|
||||
_anchor_point = xfstate->anchor_point;
|
||||
|
||||
_in_update = false;
|
||||
|
||||
return Change (what_changed);
|
||||
}
|
||||
|
||||
StateManager::State*
|
||||
Crossfade::state_factory (std::string why) const
|
||||
{
|
||||
CrossfadeState* state = new CrossfadeState (why);
|
||||
|
||||
state->fade_in_memento = _fade_in.get_memento ();
|
||||
state->fade_out_memento = _fade_out.get_memento ();
|
||||
state->active = _active;
|
||||
state->length = _length;
|
||||
state->position = _position;
|
||||
state->follow_overlap = _follow_overlap;
|
||||
state->anchor_point = _anchor_point;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
UndoAction
|
||||
Crossfade::get_memento() const
|
||||
{
|
||||
return sigc::bind (mem_fun (*(const_cast<Crossfade *> (this)), &StateManager::use_state), _current_state_id);
|
||||
}
|
||||
|
||||
XMLNode&
|
||||
Crossfade::get_state ()
|
||||
{
|
||||
XMLNode* node = new XMLNode (X_("Crossfade"));
|
||||
XMLNode* child;
|
||||
char buf[64];
|
||||
LocaleGuard lg (X_("POSIX"));
|
||||
|
||||
snprintf (buf, sizeof(buf), "%" PRIu64, _out->id());
|
||||
node->add_property ("out", buf);
|
||||
snprintf (buf, sizeof(buf), "%" PRIu64, _in->id());
|
||||
node->add_property ("in", buf);
|
||||
node->add_property ("active", (_active ? "yes" : "no"));
|
||||
node->add_property ("follow-overlap", (_follow_overlap ? "yes" : "no"));
|
||||
node->add_property ("fixed", (_fixed ? "yes" : "no"));
|
||||
snprintf (buf, sizeof(buf), "%" PRIu32, _length);
|
||||
node->add_property ("length", buf);
|
||||
snprintf (buf, sizeof(buf), "%" PRIu32, (uint32_t) _anchor_point);
|
||||
node->add_property ("anchor-point", buf);
|
||||
snprintf (buf, sizeof(buf), "%" PRIu32, (uint32_t) _position);
|
||||
node->add_property ("position", buf);
|
||||
|
||||
child = node->add_child ("FadeIn");
|
||||
|
||||
for (AutomationList::iterator ii = _fade_in.begin(); ii != _fade_in.end(); ++ii) {
|
||||
XMLNode* pnode;
|
||||
|
||||
pnode = new XMLNode ("point");
|
||||
|
||||
snprintf (buf, sizeof (buf), "%" PRIu32, (jack_nframes_t) floor ((*ii)->when));
|
||||
pnode->add_property ("x", buf);
|
||||
snprintf (buf, sizeof (buf), "%f", (*ii)->value);
|
||||
pnode->add_property ("y", buf);
|
||||
child->add_child_nocopy (*pnode);
|
||||
}
|
||||
|
||||
child = node->add_child ("FadeOut");
|
||||
|
||||
for (AutomationList::iterator ii = _fade_out.begin(); ii != _fade_out.end(); ++ii) {
|
||||
XMLNode* pnode;
|
||||
|
||||
pnode = new XMLNode ("point");
|
||||
|
||||
snprintf (buf, sizeof (buf), "%" PRIu32, (jack_nframes_t) floor ((*ii)->when));
|
||||
pnode->add_property ("x", buf);
|
||||
snprintf (buf, sizeof (buf), "%f", (*ii)->value);
|
||||
pnode->add_property ("y", buf);
|
||||
child->add_child_nocopy (*pnode);
|
||||
}
|
||||
|
||||
return *node;
|
||||
}
|
||||
|
||||
int
|
||||
Crossfade::set_state (const XMLNode& node)
|
||||
{
|
||||
XMLNodeConstIterator i;
|
||||
XMLNodeList children;
|
||||
XMLNode* fi;
|
||||
XMLNode* fo;
|
||||
const XMLProperty* prop;
|
||||
LocaleGuard lg (X_("POSIX"));
|
||||
|
||||
if ((prop = node.property ("position")) != 0) {
|
||||
_position = atoi (prop->value().c_str());
|
||||
} else {
|
||||
warning << _("old-style crossfade information - no position information") << endmsg;
|
||||
_position = _in->first_frame();
|
||||
}
|
||||
|
||||
if ((prop = node.property ("active")) != 0) {
|
||||
_active = (prop->value() == "yes");
|
||||
} else {
|
||||
_active = true;
|
||||
}
|
||||
|
||||
if ((prop = node.property ("follow-overlap")) != 0) {
|
||||
_follow_overlap = (prop->value() == "yes");
|
||||
} else {
|
||||
_follow_overlap = false;
|
||||
}
|
||||
|
||||
if ((prop = node.property ("fixed")) != 0) {
|
||||
_fixed = (prop->value() == "yes");
|
||||
} else {
|
||||
_fixed = false;
|
||||
}
|
||||
|
||||
if ((prop = node.property ("anchor-point")) != 0) {
|
||||
_anchor_point = AnchorPoint (atoi ((prop->value().c_str())));
|
||||
} else {
|
||||
_anchor_point = StartOfIn;
|
||||
}
|
||||
|
||||
if ((prop = node.property ("length")) != 0) {
|
||||
|
||||
_length = atol (prop->value().c_str());
|
||||
|
||||
} else {
|
||||
|
||||
/* XXX this branch is legacy code from before
|
||||
the point where we stored xfade lengths.
|
||||
*/
|
||||
|
||||
if ((_length = overlap_length()) == 0) {
|
||||
throw failed_constructor();
|
||||
}
|
||||
}
|
||||
|
||||
if ((fi = find_named_node (node, "FadeIn")) == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((fo = find_named_node (node, "FadeOut")) == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* fade in */
|
||||
|
||||
_fade_in.clear ();
|
||||
|
||||
children = fi->children();
|
||||
|
||||
for (i = children.begin(); i != children.end(); ++i) {
|
||||
if ((*i)->name() == "point") {
|
||||
jack_nframes_t x;
|
||||
float y;
|
||||
|
||||
prop = (*i)->property ("x");
|
||||
sscanf (prop->value().c_str(), "%" PRIu32, &x);
|
||||
|
||||
prop = (*i)->property ("y");
|
||||
sscanf (prop->value().c_str(), "%f", &y);
|
||||
|
||||
_fade_in.add (x, y);
|
||||
}
|
||||
}
|
||||
|
||||
/* fade out */
|
||||
|
||||
_fade_out.clear ();
|
||||
|
||||
children = fo->children();
|
||||
|
||||
for (i = children.begin(); i != children.end(); ++i) {
|
||||
if ((*i)->name() == "point") {
|
||||
jack_nframes_t x;
|
||||
float y;
|
||||
XMLProperty* prop;
|
||||
|
||||
prop = (*i)->property ("x");
|
||||
sscanf (prop->value().c_str(), "%" PRIu32, &x);
|
||||
|
||||
prop = (*i)->property ("y");
|
||||
sscanf (prop->value().c_str(), "%f", &y);
|
||||
|
||||
_fade_out.add (x, y);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
Crossfade::can_follow_overlap () const
|
||||
{
|
||||
return !_fixed;
|
||||
}
|
||||
|
||||
void
|
||||
Crossfade::set_follow_overlap (bool yn)
|
||||
{
|
||||
if (yn == _follow_overlap || _fixed) {
|
||||
return;
|
||||
}
|
||||
|
||||
_follow_overlap = yn;
|
||||
|
||||
if (!yn) {
|
||||
set_length (_short_xfade_length);
|
||||
} else {
|
||||
set_length (_out->first_frame() + _out->length() - _in->first_frame());
|
||||
}
|
||||
}
|
||||
|
||||
jack_nframes_t
|
||||
Crossfade::set_length (jack_nframes_t len)
|
||||
{
|
||||
jack_nframes_t limit;
|
||||
|
||||
switch (_anchor_point) {
|
||||
case StartOfIn:
|
||||
limit = _in->length();
|
||||
break;
|
||||
|
||||
case EndOfIn:
|
||||
limit = _in->length();
|
||||
break;
|
||||
|
||||
case EndOfOut:
|
||||
limit = _out->length();
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
len = min (limit, len);
|
||||
|
||||
double factor = len / (double) _length;
|
||||
|
||||
_in_update = true;
|
||||
_fade_out.x_scale (factor);
|
||||
_fade_in.x_scale (factor);
|
||||
_in_update = false;
|
||||
|
||||
_length = len;
|
||||
|
||||
save_state ("length changed");
|
||||
|
||||
send_state_changed (LengthChanged);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
jack_nframes_t
|
||||
Crossfade::overlap_length () const
|
||||
{
|
||||
if (_fixed) {
|
||||
return _length;
|
||||
}
|
||||
return _out->first_frame() + _out->length() - _in->first_frame();
|
||||
}
|
||||
|
||||
void
|
||||
Crossfade::set_short_xfade_length (jack_nframes_t n)
|
||||
{
|
||||
_short_xfade_length = n;
|
||||
}
|
||||
449
libs/ardour/curve.cc
Normal file
449
libs/ardour/curve.cc
Normal file
@@ -0,0 +1,449 @@
|
||||
/*
|
||||
Copyright (C) 2001-2003 Paul Davis
|
||||
|
||||
Contains ideas derived from "Constrained Cubic Spline Interpolation"
|
||||
by CJC Kruger (www.korf.co.uk/spline.pdf).
|
||||
|
||||
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$
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <float.h>
|
||||
#include <cmath>
|
||||
#include <climits>
|
||||
#include <cfloat>
|
||||
#include <cmath>
|
||||
|
||||
#include <pbd/lockmonitor.h>
|
||||
#include <sigc++/bind.h>
|
||||
|
||||
#include "ardour/curve.h"
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace ARDOUR;
|
||||
using namespace PBD;
|
||||
using namespace sigc;
|
||||
|
||||
Curve::Curve (double minv, double maxv, double canv, bool nostate)
|
||||
: AutomationList (canv, nostate)
|
||||
{
|
||||
min_yval = minv;
|
||||
max_yval = maxv;
|
||||
}
|
||||
|
||||
Curve::Curve (const Curve& other)
|
||||
: AutomationList (other)
|
||||
{
|
||||
min_yval = other.min_yval;
|
||||
max_yval = other.max_yval;
|
||||
}
|
||||
|
||||
Curve::Curve (const Curve& other, double start, double end)
|
||||
: AutomationList (other, start, end)
|
||||
{
|
||||
min_yval = other.min_yval;
|
||||
max_yval = other.max_yval;
|
||||
}
|
||||
|
||||
Curve::~Curve ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Curve::solve ()
|
||||
{
|
||||
uint32_t npoints;
|
||||
|
||||
if (!_dirty) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((npoints = events.size()) > 2) {
|
||||
|
||||
/* Compute coefficients needed to efficiently compute a constrained spline
|
||||
curve. See "Constrained Cubic Spline Interpolation" by CJC Kruger
|
||||
(www.korf.co.uk/spline.pdf) for more details.
|
||||
*/
|
||||
|
||||
double x[npoints];
|
||||
double y[npoints];
|
||||
uint32_t i;
|
||||
AutomationEventList::iterator xx;
|
||||
|
||||
for (i = 0, xx = events.begin(); xx != events.end(); ++xx, ++i) {
|
||||
x[i] = (double) (*xx)->when;
|
||||
y[i] = (double) (*xx)->value;
|
||||
}
|
||||
|
||||
double lp0, lp1, fpone;
|
||||
|
||||
lp0 =(x[1] - x[0])/(y[1] - y[0]);
|
||||
lp1 = (x[2] - x[1])/(y[2] - y[1]);
|
||||
|
||||
if (lp0*lp1 < 0) {
|
||||
fpone = 0;
|
||||
} else {
|
||||
fpone = 2 / (lp1 + lp0);
|
||||
}
|
||||
|
||||
double fplast = 0;
|
||||
|
||||
for (i = 0, xx = events.begin(); xx != events.end(); ++xx, ++i) {
|
||||
|
||||
CurvePoint* cp = dynamic_cast<CurvePoint*>(*xx);
|
||||
|
||||
if (cp == 0) {
|
||||
fatal << _("programming error: ")
|
||||
<< X_("non-CurvePoint event found in event list for a Curve")
|
||||
<< endmsg;
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
double xdelta; /* gcc is wrong about possible uninitialized use */
|
||||
double xdelta2; /* ditto */
|
||||
double ydelta; /* ditto */
|
||||
double fppL, fppR;
|
||||
double fpi;
|
||||
|
||||
if (i > 0) {
|
||||
xdelta = x[i] - x[i-1];
|
||||
xdelta2 = xdelta * xdelta;
|
||||
ydelta = y[i] - y[i-1];
|
||||
}
|
||||
|
||||
/* compute (constrained) first derivatives */
|
||||
|
||||
if (i == 0) {
|
||||
|
||||
/* first segment */
|
||||
|
||||
fplast = ((3 * (y[1] - y[0]) / (2 * (x[1] - x[0]))) - (fpone * 0.5));
|
||||
|
||||
/* we don't store coefficients for i = 0 */
|
||||
|
||||
continue;
|
||||
|
||||
} else if (i == npoints - 1) {
|
||||
|
||||
/* last segment */
|
||||
|
||||
fpi = ((3 * ydelta) / (2 * xdelta)) - (fplast * 0.5);
|
||||
|
||||
} else {
|
||||
|
||||
/* all other segments */
|
||||
|
||||
double slope_before = ((x[i+1] - x[i]) / (y[i+1] - y[i]));
|
||||
double slope_after = (xdelta / ydelta);
|
||||
|
||||
if (slope_after * slope_before < 0.0) {
|
||||
/* slope changed sign */
|
||||
fpi = 0.0;
|
||||
} else {
|
||||
fpi = 2 / (slope_before + slope_after);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* compute second derivative for either side of control point `i' */
|
||||
|
||||
fppL = (((-2 * (fpi + (2 * fplast))) / (xdelta))) +
|
||||
((6 * ydelta) / xdelta2);
|
||||
|
||||
fppR = (2 * ((2 * fpi) + fplast) / xdelta) -
|
||||
((6 * ydelta) / xdelta2);
|
||||
|
||||
/* compute polynomial coefficients */
|
||||
|
||||
double b, c, d;
|
||||
|
||||
d = (fppR - fppL) / (6 * xdelta);
|
||||
c = ((x[i] * fppL) - (x[i-1] * fppR))/(2 * xdelta);
|
||||
|
||||
double xim12, xim13;
|
||||
double xi2, xi3;
|
||||
|
||||
xim12 = x[i-1] * x[i-1]; /* "x[i-1] squared" */
|
||||
xim13 = xim12 * x[i-1]; /* "x[i-1] cubed" */
|
||||
xi2 = x[i] * x[i]; /* "x[i] squared" */
|
||||
xi3 = xi2 * x[i]; /* "x[i] cubed" */
|
||||
|
||||
b = (ydelta - (c * (xi2 - xim12)) - (d * (xi3 - xim13))) / xdelta;
|
||||
|
||||
/* store */
|
||||
|
||||
cp->coeff[0] = y[i-1] - (b * x[i-1]) - (c * xim12) - (d * xim13);
|
||||
cp->coeff[1] = b;
|
||||
cp->coeff[2] = c;
|
||||
cp->coeff[3] = d;
|
||||
|
||||
fplast = fpi;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_dirty = false;
|
||||
}
|
||||
|
||||
bool
|
||||
Curve::rt_safe_get_vector (double x0, double x1, float *vec, int32_t veclen)
|
||||
{
|
||||
TentativeLockMonitor lm (lock, __LINE__, __FILE__);
|
||||
|
||||
if (!lm.locked()) {
|
||||
return false;
|
||||
} else {
|
||||
_get_vector (x0, x1, vec, veclen);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Curve::get_vector (double x0, double x1, float *vec, int32_t veclen)
|
||||
{
|
||||
LockMonitor lm (lock, __LINE__, __FILE__);
|
||||
_get_vector (x0, x1, vec, veclen);
|
||||
}
|
||||
|
||||
void
|
||||
Curve::_get_vector (double x0, double x1, float *vec, int32_t veclen)
|
||||
{
|
||||
double rx, dx, lx, hx, max_x, min_x;
|
||||
int32_t i;
|
||||
int32_t original_veclen;
|
||||
int32_t npoints;
|
||||
|
||||
if ((npoints = events.size()) == 0) {
|
||||
for (i = 0; i < veclen; ++i) {
|
||||
vec[i] = default_value;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* events is now known not to be empty */
|
||||
|
||||
max_x = events.back()->when;
|
||||
min_x = events.front()->when;
|
||||
|
||||
lx = max (min_x, x0);
|
||||
|
||||
if (x1 < 0) {
|
||||
x1 = events.back()->when;
|
||||
}
|
||||
|
||||
hx = min (max_x, x1);
|
||||
|
||||
original_veclen = veclen;
|
||||
|
||||
if (x0 < min_x) {
|
||||
|
||||
/* fill some beginning section of the array with the
|
||||
initial (used to be default) value
|
||||
*/
|
||||
|
||||
double frac = (min_x - x0) / (x1 - x0);
|
||||
int32_t subveclen = (int32_t) floor (veclen * frac);
|
||||
|
||||
subveclen = min (subveclen, veclen);
|
||||
|
||||
for (i = 0; i < subveclen; ++i) {
|
||||
vec[i] = events.front()->value;
|
||||
}
|
||||
|
||||
veclen -= subveclen;
|
||||
vec += subveclen;
|
||||
}
|
||||
|
||||
if (veclen && x1 > max_x) {
|
||||
|
||||
/* fill some end section of the array with the default or final value */
|
||||
|
||||
double frac = (x1 - max_x) / (x1 - x0);
|
||||
|
||||
int32_t subveclen = (int32_t) floor (original_veclen * frac);
|
||||
|
||||
float val;
|
||||
|
||||
subveclen = min (subveclen, veclen);
|
||||
|
||||
val = events.back()->value;
|
||||
|
||||
i = veclen - subveclen;
|
||||
|
||||
for (i = veclen - subveclen; i < veclen; ++i) {
|
||||
vec[i] = val;
|
||||
}
|
||||
|
||||
veclen -= subveclen;
|
||||
}
|
||||
|
||||
if (veclen == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (npoints == 1 ) {
|
||||
|
||||
for (i = 0; i < veclen; ++i) {
|
||||
vec[i] = events.front()->value;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (npoints == 2) {
|
||||
|
||||
/* linear interpolation between 2 points */
|
||||
|
||||
/* XXX I'm not sure that this is the right thing to
|
||||
do here. but its not a common case for the envisaged
|
||||
uses.
|
||||
*/
|
||||
|
||||
if (veclen > 1) {
|
||||
dx = (hx - lx) / (veclen - 1) ;
|
||||
} else {
|
||||
dx = 0; // not used
|
||||
}
|
||||
|
||||
double slope = (events.back()->value - events.front()->value)/
|
||||
(events.back()->when - events.front()->when);
|
||||
double yfrac = dx*slope;
|
||||
|
||||
vec[0] = events.front()->value + slope * (lx - events.front()->when);
|
||||
|
||||
for (i = 1; i < veclen; ++i) {
|
||||
vec[i] = vec[i-1] + yfrac;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (_dirty) {
|
||||
solve ();
|
||||
}
|
||||
|
||||
rx = lx;
|
||||
|
||||
if (veclen > 1) {
|
||||
|
||||
dx = (hx - lx) / veclen;
|
||||
|
||||
for (i = 0; i < veclen; ++i, rx += dx) {
|
||||
vec[i] = multipoint_eval (rx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double
|
||||
Curve::unlocked_eval (double x)
|
||||
{
|
||||
if (_dirty) {
|
||||
solve ();
|
||||
}
|
||||
|
||||
return shared_eval (x);
|
||||
}
|
||||
|
||||
double
|
||||
Curve::multipoint_eval (double x)
|
||||
{
|
||||
pair<AutomationEventList::iterator,AutomationEventList::iterator> range;
|
||||
|
||||
if ((lookup_cache.left < 0) ||
|
||||
((lookup_cache.left > x) ||
|
||||
(lookup_cache.range.first == events.end()) ||
|
||||
((*lookup_cache.range.second)->when < x))) {
|
||||
|
||||
TimeComparator cmp;
|
||||
ControlEvent cp (x, 0.0);
|
||||
|
||||
lookup_cache.range = equal_range (events.begin(), events.end(), &cp, cmp);
|
||||
}
|
||||
|
||||
range = lookup_cache.range;
|
||||
|
||||
/* EITHER
|
||||
|
||||
a) x is an existing control point, so first == existing point, second == next point
|
||||
|
||||
OR
|
||||
|
||||
b) x is between control points, so range is empty (first == second, points to where
|
||||
to insert x)
|
||||
|
||||
*/
|
||||
|
||||
if (range.first == range.second) {
|
||||
|
||||
/* x does not exist within the list as a control point */
|
||||
|
||||
lookup_cache.left = x;
|
||||
|
||||
if (range.first == events.begin()) {
|
||||
/* we're before the first point */
|
||||
// return default_value;
|
||||
events.front()->value;
|
||||
}
|
||||
|
||||
if (range.second == events.end()) {
|
||||
/* we're after the last point */
|
||||
return events.back()->value;
|
||||
}
|
||||
|
||||
double x2 = x * x;
|
||||
CurvePoint* cp = dynamic_cast<CurvePoint*> (*range.second);
|
||||
|
||||
return cp->coeff[0] + (cp->coeff[1] * x) + (cp->coeff[2] * x2) + (cp->coeff[3] * x2 * x);
|
||||
}
|
||||
|
||||
/* x is a control point in the data */
|
||||
/* invalidate the cached range because its not usable */
|
||||
lookup_cache.left = -1;
|
||||
return (*range.first)->value;
|
||||
}
|
||||
|
||||
ControlEvent*
|
||||
Curve::point_factory (double when, double val) const
|
||||
{
|
||||
return new CurvePoint (when, val);
|
||||
}
|
||||
|
||||
ControlEvent*
|
||||
Curve::point_factory (const ControlEvent& other) const
|
||||
{
|
||||
return new CurvePoint (other.when, other.value);
|
||||
}
|
||||
|
||||
Change
|
||||
Curve::restore_state (StateManager::State& state)
|
||||
{
|
||||
mark_dirty ();
|
||||
return AutomationList::restore_state (state);
|
||||
}
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
void
|
||||
curve_get_vector_from_c (void *arg, double x0, double x1, float* vec, int32_t vecsize)
|
||||
{
|
||||
static_cast<Curve*>(arg)->get_vector (x0, x1, vec, vecsize);
|
||||
}
|
||||
|
||||
}
|
||||
73
libs/ardour/cycle_timer.cc
Normal file
73
libs/ardour/cycle_timer.cc
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
Copyright (C) 2002 Andrew Morton
|
||||
|
||||
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$
|
||||
*/
|
||||
|
||||
#include <cstdio>
|
||||
#include <pbd/error.h>
|
||||
#include <ardour/cycle_timer.h>
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
float CycleTimer::cycles_per_usec = 0;
|
||||
|
||||
float
|
||||
CycleTimer::get_mhz()
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
if ((f = fopen("/proc/cpuinfo", "r")) == 0) {
|
||||
fatal << _("CycleTimer::get_mhz(): can't open /proc/cpuinfo") << endmsg;
|
||||
/*NOTREACHED*/
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
|
||||
float mhz;
|
||||
int ret;
|
||||
char buf[1000];
|
||||
|
||||
if (fgets (buf, sizeof(buf), f) == 0) {
|
||||
fatal << _("CycleTimer::get_mhz(): cannot locate cpu MHz in /proc/cpuinfo") << endmsg;
|
||||
/*NOTREACHED*/
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
#ifdef __powerpc__
|
||||
|
||||
int imhz;
|
||||
|
||||
/* why can't the PPC crew standardize their /proc/cpuinfo format ? */
|
||||
ret = sscanf (buf, "clock\t: %dMHz", &imhz);
|
||||
mhz = (float) imhz;
|
||||
|
||||
#else /* XXX don't assume its x86 just because its not power pc */
|
||||
ret = sscanf (buf, "cpu MHz : %f", &mhz);
|
||||
|
||||
#endif
|
||||
if (ret == 1) {
|
||||
fclose(f);
|
||||
return mhz;
|
||||
}
|
||||
}
|
||||
|
||||
fatal << _("cannot locate cpu MHz in /proc/cpuinfo") << endmsg;
|
||||
/*NOTREACHED*/
|
||||
return 0.0f;
|
||||
}
|
||||
1175
libs/ardour/default_click.cc
Normal file
1175
libs/ardour/default_click.cc
Normal file
File diff suppressed because it is too large
Load Diff
2338
libs/ardour/diskstream.cc
Normal file
2338
libs/ardour/diskstream.cc
Normal file
File diff suppressed because it is too large
Load Diff
1101
libs/ardour/filesource.cc
Normal file
1101
libs/ardour/filesource.cc
Normal file
File diff suppressed because it is too large
Load Diff
62
libs/ardour/gain.cc
Normal file
62
libs/ardour/gain.cc
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
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$
|
||||
*/
|
||||
|
||||
#include <ardour/gain.h>
|
||||
|
||||
using namespace ARDOUR;
|
||||
|
||||
Gain::Gain ()
|
||||
: Curve (0.0, 2.0, 1.0f) /* XXX yuck; clamps gain to -inf .. +6db */
|
||||
{
|
||||
}
|
||||
|
||||
Gain::Gain (const Gain& other)
|
||||
: Curve (other)
|
||||
{
|
||||
}
|
||||
|
||||
Gain&
|
||||
Gain::operator= (const Gain& other)
|
||||
{
|
||||
if (this != &other) {
|
||||
Curve::operator= (other);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void
|
||||
Gain::fill_linear_volume_fade_in (Gain& gain, jack_nframes_t frames)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Gain::fill_linear_volume_fade_out (Gain& gain, jack_nframes_t frames)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Gain::fill_linear_fade_in (Gain& gain, jack_nframes_t frames)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Gain::fill_linear_fade_out (Gain& gain, jack_nframes_t frames)
|
||||
{
|
||||
}
|
||||
475
libs/ardour/gdither.cc
Normal file
475
libs/ardour/gdither.cc
Normal file
@@ -0,0 +1,475 @@
|
||||
/*
|
||||
* 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$
|
||||
*/
|
||||
|
||||
#include <ardour/gdither_types_internal.h>
|
||||
#include <ardour/gdither.h>
|
||||
#include <ardour/noise.h>
|
||||
|
||||
/* this monstrosity is necessary to get access to lrintf() and random().
|
||||
whoever is writing the glibc headers <cmath> and <cstdlib> should be
|
||||
hauled off to a programmer re-education camp. for the rest of
|
||||
their natural lives. or longer. <paul@linuxaudiosystems.com>
|
||||
*/
|
||||
|
||||
#define _ISOC9X_SOURCE 1
|
||||
#define _ISOC99_SOURCE 1
|
||||
#ifdef __cplusplus
|
||||
#include <cmath>
|
||||
#else
|
||||
#include <math.h>
|
||||
#endif
|
||||
|
||||
#undef __USE_SVID
|
||||
#define __USE_SVID 1
|
||||
#ifdef __cplusplus
|
||||
#include <cstdlib>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
/* Lipshitz's minimally audible FIR, only really works for 46kHz-ish signals */
|
||||
static const float shaped_bs[] = { 2.033f, -2.165f, 1.959f, -1.590f, 0.6149f };
|
||||
|
||||
/* Some useful constants */
|
||||
#define MAX_U8 255
|
||||
#define MIN_U8 0
|
||||
#define SCALE_U8 128.0f
|
||||
|
||||
#define MAX_S16 32767
|
||||
#define MIN_S16 -32768
|
||||
#define SCALE_S16 32768.0f
|
||||
|
||||
#define MAX_S24 8388607
|
||||
#define MIN_S24 -8388608
|
||||
#define SCALE_S24 8388608.0f
|
||||
|
||||
GDither gdither_new(GDitherType type, uint32_t channels,
|
||||
|
||||
GDitherSize bit_depth, int dither_depth)
|
||||
{
|
||||
GDither s;
|
||||
|
||||
s = (GDither)calloc(1, sizeof(struct GDither_s));
|
||||
s->type = type;
|
||||
s->channels = channels;
|
||||
s->bit_depth = (int)bit_depth;
|
||||
|
||||
if (dither_depth <= 0 || dither_depth > (int)bit_depth) {
|
||||
dither_depth = (int)bit_depth;
|
||||
}
|
||||
s->dither_depth = dither_depth;
|
||||
|
||||
s->scale = (float)(1LL << (dither_depth - 1));
|
||||
if (bit_depth == GDitherFloat || bit_depth == GDitherDouble) {
|
||||
s->post_scale_fp = 1.0f / s->scale;
|
||||
s->post_scale = 0;
|
||||
} else {
|
||||
s->post_scale_fp = 0.0f;
|
||||
s->post_scale = 1 << ((int)bit_depth - dither_depth);
|
||||
}
|
||||
|
||||
switch (bit_depth) {
|
||||
case GDither8bit:
|
||||
/* Unsigned 8 bit */
|
||||
s->bias = 1.0f;
|
||||
s->clamp_u = 255;
|
||||
s->clamp_l = 0;
|
||||
break;
|
||||
case GDither16bit:
|
||||
/* Signed 16 bit */
|
||||
s->bias = 0.0f;
|
||||
s->clamp_u = 32767;
|
||||
s->clamp_l = -32768;
|
||||
break;
|
||||
case GDither32bit:
|
||||
/* Signed 24 bit, in upper 24 bits of 32 bit word */
|
||||
s->bias = 0.0f;
|
||||
s->clamp_u = 8388607;
|
||||
s->clamp_l = -8388608;
|
||||
break;
|
||||
case GDitherFloat:
|
||||
/* normalised float */
|
||||
s->bias = 0.0f;
|
||||
s->clamp_u = lrintf(s->scale);
|
||||
s->clamp_l = lrintf(-s->scale);
|
||||
break;
|
||||
case GDitherDouble:
|
||||
/* normalised float */
|
||||
s->bias = 0.0f;
|
||||
s->clamp_u = lrintf(s->scale);
|
||||
s->clamp_l = lrintf(-s->scale);
|
||||
break;
|
||||
case 23:
|
||||
/* special performance test case */
|
||||
s->scale = SCALE_S24;
|
||||
s->post_scale = 256;
|
||||
s->bias = 0.0f;
|
||||
s->clamp_u = 8388607;
|
||||
s->clamp_l = -8388608;
|
||||
break;
|
||||
default:
|
||||
/* Not a bit depth we can handle */
|
||||
free(s);
|
||||
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case GDitherNone:
|
||||
case GDitherRect:
|
||||
/* No state */
|
||||
break;
|
||||
|
||||
case GDitherTri:
|
||||
/* The last whitenoise sample */
|
||||
s->tri_state = (float *) calloc(channels, sizeof(float));
|
||||
break;
|
||||
|
||||
case GDitherShaped:
|
||||
/* The error from the last few samples encoded */
|
||||
s->shaped_state = (GDitherShapedState*)
|
||||
calloc(channels, sizeof(GDitherShapedState));
|
||||
break;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void gdither_free(GDither s)
|
||||
{
|
||||
if (s) {
|
||||
free(s->tri_state);
|
||||
free(s->shaped_state);
|
||||
free(s);
|
||||
}
|
||||
}
|
||||
|
||||
inline static void gdither_innner_loop(const GDitherType dt,
|
||||
const uint32_t stride, const float bias, const float scale,
|
||||
|
||||
const uint32_t post_scale, const int bit_depth,
|
||||
const uint32_t channel, const uint32_t length, float *ts,
|
||||
|
||||
GDitherShapedState *ss, float *x, void *y, const int clamp_u,
|
||||
|
||||
const int clamp_l)
|
||||
{
|
||||
uint32_t pos, i;
|
||||
u_int8_t *o8 = (u_int8_t*) y;
|
||||
int16_t *o16 = (int16_t*) y;
|
||||
int32_t *o32 = (int32_t*) y;
|
||||
float tmp, r, ideal;
|
||||
int64_t clamped;
|
||||
|
||||
i = channel;
|
||||
for (pos = 0; pos < length; pos++, i += stride) {
|
||||
tmp = x[i] * scale + bias;
|
||||
|
||||
switch (dt) {
|
||||
case GDitherNone:
|
||||
break;
|
||||
case GDitherRect:
|
||||
tmp -= GDITHER_NOISE;
|
||||
break;
|
||||
case GDitherTri:
|
||||
r = GDITHER_NOISE - 0.5f;
|
||||
tmp -= r - ts[channel];
|
||||
ts[channel] = r;
|
||||
break;
|
||||
case GDitherShaped:
|
||||
/* Save raw value for error calculations */
|
||||
ideal = tmp;
|
||||
|
||||
/* Run FIR and add white noise */
|
||||
ss->buffer[ss->phase] = GDITHER_NOISE * 0.5f;
|
||||
tmp += ss->buffer[ss->phase] * shaped_bs[0]
|
||||
+ ss->buffer[(ss->phase - 1) & GDITHER_SH_BUF_MASK]
|
||||
* shaped_bs[1]
|
||||
+ ss->buffer[(ss->phase - 2) & GDITHER_SH_BUF_MASK]
|
||||
* shaped_bs[2]
|
||||
+ ss->buffer[(ss->phase - 3) & GDITHER_SH_BUF_MASK]
|
||||
* shaped_bs[3]
|
||||
+ ss->buffer[(ss->phase - 4) & GDITHER_SH_BUF_MASK]
|
||||
* shaped_bs[4];
|
||||
|
||||
/* Roll buffer and store last error */
|
||||
ss->phase = (ss->phase + 1) & GDITHER_SH_BUF_MASK;
|
||||
ss->buffer[ss->phase] = (float)lrintf(tmp) - ideal;
|
||||
break;
|
||||
}
|
||||
|
||||
clamped = lrintf(tmp);
|
||||
if (clamped > clamp_u) {
|
||||
clamped = clamp_u;
|
||||
} else if (clamped < clamp_l) {
|
||||
clamped = clamp_l;
|
||||
}
|
||||
|
||||
switch (bit_depth) {
|
||||
case GDither8bit:
|
||||
o8[i] = (u_int8_t) (clamped * post_scale);
|
||||
break;
|
||||
case GDither16bit:
|
||||
o16[i] = (int16_t) (clamped * post_scale);
|
||||
break;
|
||||
case GDither32bit:
|
||||
o32[i] = (int32_t) (clamped * post_scale);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* floating pint version of the inner loop function */
|
||||
inline static void gdither_innner_loop_fp(const GDitherType dt,
|
||||
const uint32_t stride, const float bias, const float scale,
|
||||
|
||||
const float post_scale, const int bit_depth,
|
||||
const uint32_t channel, const uint32_t length, float *ts,
|
||||
|
||||
GDitherShapedState *ss, float *x, void *y, const int clamp_u,
|
||||
|
||||
const int clamp_l)
|
||||
{
|
||||
uint32_t pos, i;
|
||||
float *oflt = (float*) y;
|
||||
double *odbl = (double*) y;
|
||||
float tmp, r, ideal;
|
||||
double clamped;
|
||||
|
||||
i = channel;
|
||||
for (pos = 0; pos < length; pos++, i += stride) {
|
||||
tmp = x[i] * scale + bias;
|
||||
|
||||
switch (dt) {
|
||||
case GDitherNone:
|
||||
break;
|
||||
case GDitherRect:
|
||||
tmp -= GDITHER_NOISE;
|
||||
break;
|
||||
case GDitherTri:
|
||||
r = GDITHER_NOISE - 0.5f;
|
||||
tmp -= r - ts[channel];
|
||||
ts[channel] = r;
|
||||
break;
|
||||
case GDitherShaped:
|
||||
/* Save raw value for error calculations */
|
||||
ideal = tmp;
|
||||
|
||||
/* Run FIR and add white noise */
|
||||
ss->buffer[ss->phase] = GDITHER_NOISE * 0.5f;
|
||||
tmp += ss->buffer[ss->phase] * shaped_bs[0]
|
||||
+ ss->buffer[(ss->phase - 1) & GDITHER_SH_BUF_MASK]
|
||||
* shaped_bs[1]
|
||||
+ ss->buffer[(ss->phase - 2) & GDITHER_SH_BUF_MASK]
|
||||
* shaped_bs[2]
|
||||
+ ss->buffer[(ss->phase - 3) & GDITHER_SH_BUF_MASK]
|
||||
* shaped_bs[3]
|
||||
+ ss->buffer[(ss->phase - 4) & GDITHER_SH_BUF_MASK]
|
||||
* shaped_bs[4];
|
||||
|
||||
/* Roll buffer and store last error */
|
||||
ss->phase = (ss->phase + 1) & GDITHER_SH_BUF_MASK;
|
||||
ss->buffer[ss->phase] = (float)lrintf(tmp) - ideal;
|
||||
break;
|
||||
}
|
||||
|
||||
clamped = rintf(tmp);
|
||||
if (clamped > clamp_u) {
|
||||
clamped = clamp_u;
|
||||
} else if (clamped < clamp_l) {
|
||||
clamped = clamp_l;
|
||||
}
|
||||
|
||||
switch (bit_depth) {
|
||||
case GDitherFloat:
|
||||
oflt[i] = (float) (clamped * post_scale);
|
||||
break;
|
||||
case GDitherDouble:
|
||||
odbl[i] = (double) (clamped * post_scale);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define GDITHER_CONV_BLOCK 512
|
||||
|
||||
void gdither_run(GDither s, uint32_t channel, uint32_t length,
|
||||
double *x, void *y)
|
||||
{
|
||||
float conv[GDITHER_CONV_BLOCK];
|
||||
uint32_t i, pos;
|
||||
char *ycast = (char *)y;
|
||||
|
||||
int step;
|
||||
|
||||
switch (s->bit_depth) {
|
||||
case GDither8bit:
|
||||
step = 1;
|
||||
break;
|
||||
case GDither16bit:
|
||||
step = 2;
|
||||
break;
|
||||
case GDither32bit:
|
||||
case GDitherFloat:
|
||||
step = 4;
|
||||
break;
|
||||
case GDitherDouble:
|
||||
step = 8;
|
||||
break;
|
||||
default:
|
||||
step = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
pos = 0;
|
||||
while (pos < length) {
|
||||
for (i=0; (i + pos) < length && i < GDITHER_CONV_BLOCK; i++) {
|
||||
conv[i] = x[pos + i];
|
||||
}
|
||||
gdither_runf(s, channel, i, conv, ycast + s->channels * step);
|
||||
pos += i;
|
||||
}
|
||||
}
|
||||
|
||||
void gdither_runf(GDither s, uint32_t channel, uint32_t length,
|
||||
float *x, void *y)
|
||||
{
|
||||
uint32_t pos, i;
|
||||
float tmp;
|
||||
int64_t clamped;
|
||||
GDitherShapedState *ss = NULL;
|
||||
|
||||
if (!s || channel >= s->channels) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (s->shaped_state) {
|
||||
ss = s->shaped_state + channel;
|
||||
}
|
||||
|
||||
if (s->type == GDitherNone && s->bit_depth == 23) {
|
||||
int32_t *o32 = (int32_t*) y;
|
||||
|
||||
for (pos = 0; pos < length; pos++) {
|
||||
i = channel + (pos * s->channels);
|
||||
tmp = x[i] * 8388608.0f;
|
||||
|
||||
clamped = lrintf(tmp);
|
||||
if (clamped > 8388607) {
|
||||
clamped = 8388607;
|
||||
} else if (clamped < -8388608) {
|
||||
clamped = -8388608;
|
||||
}
|
||||
|
||||
o32[i] = (int32_t) (clamped * 256);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* some common case handling code - looks a bit wierd, but it allows
|
||||
* the compiler to optiomise out the branches in the inner loop */
|
||||
if (s->bit_depth == 8 && s->dither_depth == 8) {
|
||||
switch (s->type) {
|
||||
case GDitherNone:
|
||||
gdither_innner_loop(GDitherNone, s->channels, 128.0f, SCALE_U8,
|
||||
1, 8, channel, length, NULL, NULL, x, y,
|
||||
MAX_U8, MIN_U8);
|
||||
break;
|
||||
case GDitherRect:
|
||||
gdither_innner_loop(GDitherRect, s->channels, 128.0f, SCALE_U8,
|
||||
1, 8, channel, length, NULL, NULL, x, y,
|
||||
MAX_U8, MIN_U8);
|
||||
break;
|
||||
case GDitherTri:
|
||||
gdither_innner_loop(GDitherTri, s->channels, 128.0f, SCALE_U8,
|
||||
1, 8, channel, length, s->tri_state,
|
||||
NULL, x, y, MAX_U8, MIN_U8);
|
||||
break;
|
||||
case GDitherShaped:
|
||||
gdither_innner_loop(GDitherShaped, s->channels, 128.0f, SCALE_U8,
|
||||
1, 8, channel, length, NULL,
|
||||
ss, x, y, MAX_U8, MIN_U8);
|
||||
break;
|
||||
}
|
||||
} else if (s->bit_depth == s->dither_depth == 16) {
|
||||
switch (s->type) {
|
||||
case GDitherNone:
|
||||
gdither_innner_loop(GDitherNone, s->channels, 0.0f, SCALE_S16,
|
||||
1, 16, channel, length, NULL, NULL, x, y,
|
||||
MAX_S16, MIN_S16);
|
||||
break;
|
||||
case GDitherRect:
|
||||
gdither_innner_loop(GDitherRect, s->channels, 0.0f, SCALE_S16,
|
||||
1, 16, channel, length, NULL, NULL, x, y,
|
||||
MAX_S16, MIN_S16);
|
||||
break;
|
||||
case GDitherTri:
|
||||
gdither_innner_loop(GDitherTri, s->channels, 0.0f, SCALE_S16,
|
||||
1, 16, channel, length, s->tri_state,
|
||||
NULL, x, y, MAX_S16, MIN_S16);
|
||||
break;
|
||||
case GDitherShaped:
|
||||
gdither_innner_loop(GDitherShaped, s->channels, 0.0f,
|
||||
SCALE_S16, 1, 16, channel, length, NULL,
|
||||
ss, x, y, MAX_S16, MIN_S16);
|
||||
break;
|
||||
}
|
||||
} else if (s->bit_depth == 32 && s->dither_depth == 24) {
|
||||
switch (s->type) {
|
||||
case GDitherNone:
|
||||
gdither_innner_loop(GDitherNone, s->channels, 0.0f, SCALE_S24,
|
||||
256, 32, channel, length, NULL, NULL, x,
|
||||
y, MAX_S24, MIN_S24);
|
||||
break;
|
||||
case GDitherRect:
|
||||
gdither_innner_loop(GDitherRect, s->channels, 0.0f, SCALE_S24,
|
||||
256, 32, channel, length, NULL, NULL, x,
|
||||
y, MAX_S24, MIN_S24);
|
||||
break;
|
||||
case GDitherTri:
|
||||
gdither_innner_loop(GDitherTri, s->channels, 0.0f, SCALE_S24,
|
||||
256, 32, channel, length, s->tri_state,
|
||||
NULL, x, y, MAX_S24, MIN_S24);
|
||||
break;
|
||||
case GDitherShaped:
|
||||
gdither_innner_loop(GDitherShaped, s->channels, 0.0f, SCALE_S24,
|
||||
256, 32, channel, length,
|
||||
NULL, ss, x, y, MAX_S24, MIN_S24);
|
||||
break;
|
||||
}
|
||||
} else if (s->bit_depth == GDitherFloat || s->bit_depth == GDitherDouble) {
|
||||
gdither_innner_loop_fp(s->type, s->channels, s->bias, s->scale,
|
||||
s->post_scale_fp, s->bit_depth, channel, length,
|
||||
s->tri_state, ss, x, y, s->clamp_u, s->clamp_l);
|
||||
} else {
|
||||
/* no special case handling, just process it from the struct */
|
||||
|
||||
gdither_innner_loop(s->type, s->channels, s->bias, s->scale,
|
||||
s->post_scale, s->bit_depth, channel,
|
||||
length, s->tri_state, ss, x, y, s->clamp_u,
|
||||
s->clamp_l);
|
||||
}
|
||||
}
|
||||
|
||||
/* vi:set ts=8 sts=4 sw=4: */
|
||||
82
libs/ardour/gettext.h
Normal file
82
libs/ardour/gettext.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/* Convenience header for conditional use of GNU <libintl.h>.
|
||||
Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc.
|
||||
|
||||
This program 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, 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
USA. */
|
||||
|
||||
#ifndef _LIBGETTEXT_H
|
||||
#define _LIBGETTEXT_H 1
|
||||
|
||||
/* NLS can be disabled through the configure --disable-nls option. */
|
||||
#if ENABLE_NLS
|
||||
|
||||
/* Get declarations of GNU message catalog functions. */
|
||||
# include <libintl.h>
|
||||
|
||||
#else
|
||||
|
||||
/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
|
||||
chokes if dcgettext is defined as a macro. So include it now, to make
|
||||
later inclusions of <locale.h> a NOP. We don't include <libintl.h>
|
||||
as well because people using "gettext.h" will not include <libintl.h>,
|
||||
and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
|
||||
is OK. */
|
||||
#if defined(__sun)
|
||||
# include <locale.h>
|
||||
#endif
|
||||
|
||||
/* Disabled NLS.
|
||||
The casts to 'const char *' serve the purpose of producing warnings
|
||||
for invalid uses of the value returned from these functions.
|
||||
On pre-ANSI systems without 'const', the config.h file is supposed to
|
||||
contain "#define const". */
|
||||
|
||||
/* other headers may have included libintl.h */
|
||||
|
||||
# undef gettext
|
||||
# undef dgettext
|
||||
# undef dcgettext
|
||||
# undef ngettext
|
||||
# undef dngettext
|
||||
# undef dcngettext
|
||||
# undef textdomain
|
||||
# undef bindtextdomain
|
||||
# undef bind_textdomain_codeset
|
||||
|
||||
# define gettext(Msgid) ((const char *) (Msgid))
|
||||
# define dgettext(Domainname, Msgid) ((const char *) (Msgid))
|
||||
# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid))
|
||||
# define ngettext(Msgid1, Msgid2, N) \
|
||||
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
|
||||
# define dngettext(Domainname, Msgid1, Msgid2, N) \
|
||||
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
|
||||
# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
|
||||
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
|
||||
# define textdomain(Domainname) ((const char *) (Domainname))
|
||||
# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
|
||||
# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset))
|
||||
|
||||
#endif
|
||||
|
||||
/* A pseudo function call that serves as a marker for the automated
|
||||
extraction of messages, but does not call gettext(). The run-time
|
||||
translation is done at a different place in the code.
|
||||
The argument, String, should be a literal string. Concatenated strings
|
||||
and other string expressions won't work.
|
||||
The macro's expansion is not parenthesized, so that it is suitable as
|
||||
initializer for static 'char[]' or 'const char[]' variables. */
|
||||
#define gettext_noop(String) String
|
||||
|
||||
#endif /* _LIBGETTEXT_H */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user