summaryrefslogtreecommitdiff
path: root/libs/ardour
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2008-09-17 08:44:51 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2008-09-17 08:44:51 +0000
commit1c299d5a5c493986ca4a19bd55a69281dabada86 (patch)
treedae18913a2261a157ba32308ef804050e1232542 /libs/ardour
parent8e9a83dfdc233898e7c470667c7c9b797c83fe8b (diff)
merge Sakari's (sbergen) branch back into 3.0, removing libsndfile and adding taglib
git-svn-id: svn://localhost/ardour2/branches/3.0@3736 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/ardour')
-rw-r--r--libs/ardour/SConscript18
-rw-r--r--libs/ardour/ardour/audioregion.h3
-rw-r--r--libs/ardour/ardour/midi_region.h3
-rw-r--r--libs/ardour/ardour/session.h40
-rw-r--r--libs/ardour/ardour/types.h5
-rw-r--r--libs/ardour/audioregion.cc120
-rw-r--r--libs/ardour/enums.cc106
-rw-r--r--libs/ardour/session.cc4
-rw-r--r--libs/ardour/session_export.cc644
-rw-r--r--libs/ardour/session_state.cc22
-rw-r--r--libs/ardour/session_time.cc2
11 files changed, 354 insertions, 613 deletions
diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript
index ca6fc0553e..3177f05976 100644
--- a/libs/ardour/SConscript
+++ b/libs/ardour/SConscript
@@ -37,6 +37,7 @@ audio_buffer.cc
audio_diskstream.cc
audioengine.cc
audiofilesource.cc
+audiofile_tagger.cc
audio_library.cc
audio_playlist.cc
audio_port.cc
@@ -51,6 +52,7 @@ automation_control.cc
automation_event.cc
base_audio_port.cc
base_midi_port.cc
+broadcast_info.cc
buffer.cc
buffer_set.cc
chan_count.cc
@@ -64,6 +66,19 @@ default_click.cc
directory_names.cc
diskstream.cc
enums.cc
+export_channel_configuration.cc
+export_file_io.cc
+export_filename.cc
+export_format_base.cc
+export_format_manager.cc
+export_formats.cc
+export_format_specification.cc
+export_handler.cc
+export_processor.cc
+export_profile_manager.cc
+export_status.cc
+export_timespan.cc
+export_utilities.cc
filename_extensions.cc
filesystem_paths.cc
filter.cc
@@ -124,6 +139,7 @@ session_command.cc
session_directory.cc
session_events.cc
session_export.cc
+session_metadata.cc
session_midi.cc
session_process.cc
session_state.cc
@@ -139,6 +155,7 @@ sndfilesource.cc
sndfileimportable.cc
source.cc
source_factory.cc
+svn_revision.cc
tape_file_matcher.cc
template_utils.cc
tempo.cc
@@ -318,6 +335,7 @@ ardour.Merge ([
libraries['samplerate'],
libraries['sigc2'],
libraries['sndfile-ardour'],
+ libraries['taglib'],
libraries['vamp'],
libraries['vamphost'],
libraries['xml']
diff --git a/libs/ardour/ardour/audioregion.h b/libs/ardour/ardour/audioregion.h
index 81b7ef7c57..f8bd8a1794 100644
--- a/libs/ardour/ardour/audioregion.h
+++ b/libs/ardour/ardour/audioregion.h
@@ -30,12 +30,13 @@
#include <ardour/region.h>
#include <ardour/gain.h>
#include <ardour/logcurve.h>
-#include <ardour/export.h>
class XMLNode;
namespace ARDOUR {
+using std::vector;
+
class Route;
class Playlist;
class Session;
diff --git a/libs/ardour/ardour/midi_region.h b/libs/ardour/ardour/midi_region.h
index cd2b0d6132..44f775dc1c 100644
--- a/libs/ardour/ardour/midi_region.h
+++ b/libs/ardour/ardour/midi_region.h
@@ -30,11 +30,12 @@
#include <ardour/region.h>
#include <ardour/gain.h>
#include <ardour/logcurve.h>
-#include <ardour/export.h>
#include <ardour/midi_source.h>
class XMLNode;
+using std::vector;
+
namespace ARDOUR {
class Route;
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index 08315c3010..a8601a562a 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -51,6 +51,7 @@
#include <ardour/ardour.h>
#include <ardour/configuration.h>
+#include <ardour/export_status.h>
#include <ardour/location.h>
#include <ardour/gain.h>
#include <ardour/io.h>
@@ -108,8 +109,9 @@ class MidiRegion;
class SMFSource;
class SessionDirectory;
+class SessionMetadata;
+class ExportHandler;
-struct ExportSpecification;
struct RouteGroup;
using std::vector;
@@ -457,7 +459,7 @@ class Session : public PBD::StatefulDestructible
XMLNode& get_template();
/// The instant xml file is written to the session directory
- void add_instant_xml (XMLNode&);
+ void add_instant_xml (XMLNode&, bool write_to_config = true);
XMLNode * instant_xml (const std::string& str);
enum StateOfTheState {
@@ -554,7 +556,7 @@ class Session : public PBD::StatefulDestructible
void set_smpte_offset_negative (bool);
bool smpte_offset_negative () const { return _smpte_offset_negative; }
- nframes_t convert_to_frames_at (nframes_t position, AnyTime&);
+ nframes_t convert_to_frames_at (nframes_t position, AnyTime const &);
static sigc::signal<void> StartTimeChanged;
static sigc::signal<void> EndTimeChanged;
@@ -616,14 +618,27 @@ class Session : public PBD::StatefulDestructible
bool sample_rate_convert (import_status&, string infile, string& outfile);
string build_tmp_convert_name (string file);
+ /* Export stuff */
+
SlaveSource post_export_slave;
nframes_t post_export_position;
+ ExportStatus export_status;
+
+ boost::shared_ptr<ExportHandler> get_export_handler ();
+ void release_export_handler ();
+
int pre_export ();
- int start_export (ARDOUR::ExportSpecification&);
- int stop_export (ARDOUR::ExportSpecification&);
- void finalize_export ();
+ int start_audio_export (nframes_t position, bool realtime);
+ int stop_audio_export ();
+ void finalize_audio_export ();
+ void abort_audio_export ();
+
+ sigc::signal<int, nframes_t> ProcessExport;
+ sigc::signal<void> ExportFinished;
static sigc::signal<void, std::string, std::string> Exported;
+ sigc::connection export_freewheel_connection;
+ sigc::connection export_abort_connection;
void add_source (boost::shared_ptr<Source>);
void remove_source (boost::weak_ptr<Source>);
@@ -1051,7 +1066,8 @@ class Session : public PBD::StatefulDestructible
void process_without_events (nframes_t);
void process_with_events (nframes_t);
void process_audition (nframes_t);
- int process_export (nframes_t, ARDOUR::ExportSpecification*);
+ void process_export (nframes_t);
+ int process_export_fw (nframes_t);
/* slave tracking */
@@ -1076,8 +1092,8 @@ class Session : public PBD::StatefulDestructible
void set_slave_source (SlaveSource);
bool _exporting;
-
- int prepare_to_export (ARDOUR::ExportSpecification&);
+ bool _exporting_realtime;
+ boost::shared_ptr<ExportHandler> export_handler;
void prepare_diskstreams ();
void commit_diskstreams (nframes_t, bool& session_requires_butler);
@@ -1724,6 +1740,12 @@ class Session : public PBD::StatefulDestructible
void sync_order_keys ();
static bool _disable_all_loaded_plugins;
+
+ /* Metadata */
+
+ SessionMetadata * _metadata;
+ public:
+ SessionMetadata & metadata () { return *_metadata; }
};
} // namespace ARDOUR
diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h
index d94683f427..06c055bbe6 100644
--- a/libs/ardour/ardour/types.h
+++ b/libs/ardour/ardour/types.h
@@ -342,6 +342,11 @@ namespace ARDOUR {
FormatInt16
};
+ enum CDMarkerFormat {
+ CDMarkerNone,
+ CDMarkerCUE,
+ CDMarkerTOC
+ };
enum HeaderFormat {
BWF,
diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc
index cbf2e44c5f..271544297d 100644
--- a/libs/ardour/audioregion.cc
+++ b/libs/ardour/audioregion.cc
@@ -1024,65 +1024,67 @@ AudioRegion::read_raw_internal (Sample* buf, nframes_t pos, nframes_t cnt) const
int
AudioRegion::exportme (Session& session, ARDOUR::ExportSpecification& spec)
{
- const nframes_t blocksize = 4096;
- nframes_t to_read;
- int status = -1;
-
- spec.channels = _sources.size();
-
- if (spec.prepare (blocksize, session.frame_rate())) {
- goto out;
- }
-
- spec.pos = 0;
- spec.total_frames = _length;
-
- while (spec.pos < _length && !spec.stop) {
-
-
- /* step 1: interleave */
-
- to_read = min (_length - spec.pos, blocksize);
-
- if (spec.channels == 1) {
-
- if (read_raw_internal (spec.dataF, _start + spec.pos, to_read) != to_read) {
- goto out;
- }
-
- } else {
-
- Sample buf[blocksize];
-
- for (uint32_t chan = 0; chan < spec.channels; ++chan) {
-
- if (audio_source(chan)->read (buf, _start + spec.pos, to_read) != to_read) {
- goto out;
- }
-
- for (nframes_t x = 0; x < to_read; ++x) {
- spec.dataF[chan+(x*spec.channels)] = buf[x];
- }
- }
- }
-
- if (spec.process (to_read)) {
- goto out;
- }
-
- spec.pos += to_read;
- spec.progress = (double) spec.pos /_length;
-
- }
-
- status = 0;
-
- out:
- spec.running = false;
- spec.status = status;
- spec.clear();
-
- return status;
+ // TODO EXPORT
+// const nframes_t blocksize = 4096;
+// nframes_t to_read;
+// int status = -1;
+//
+// spec.channels = _sources.size();
+//
+// if (spec.prepare (blocksize, session.frame_rate())) {
+// goto out;
+// }
+//
+// spec.pos = 0;
+// spec.total_frames = _length;
+//
+// while (spec.pos < _length && !spec.stop) {
+//
+//
+// /* step 1: interleave */
+//
+// to_read = min (_length - spec.pos, blocksize);
+//
+// if (spec.channels == 1) {
+//
+// if (read_raw_internal (spec.dataF, _start + spec.pos, to_read) != to_read) {
+// goto out;
+// }
+//
+// } else {
+//
+// Sample buf[blocksize];
+//
+// for (uint32_t chan = 0; chan < spec.channels; ++chan) {
+//
+// if (audio_source(chan)->read (buf, _start + spec.pos, to_read) != to_read) {
+// goto out;
+// }
+//
+// for (nframes_t x = 0; x < to_read; ++x) {
+// spec.dataF[chan+(x*spec.channels)] = buf[x];
+// }
+// }
+// }
+//
+// if (spec.process (to_read)) {
+// goto out;
+// }
+//
+// spec.pos += to_read;
+// spec.progress = (double) spec.pos /_length;
+//
+// }
+//
+// status = 0;
+//
+// out:
+// spec.running = false;
+// spec.status = status;
+// spec.clear();
+//
+// return status;
+ return 0;
}
void
diff --git a/libs/ardour/enums.cc b/libs/ardour/enums.cc
index 0781f8c8e1..350c6dba9a 100644
--- a/libs/ardour/enums.cc
+++ b/libs/ardour/enums.cc
@@ -29,6 +29,9 @@
#include <ardour/panner.h>
#include <ardour/track.h>
#include <ardour/midi_track.h>
+#include <ardour/export_filename.h>
+#include <ardour/export_format_base.h>
+#include <ardour/export_profile_manager.h>
using namespace std;
using namespace PBD;
@@ -59,6 +62,7 @@ setup_enum_writer ()
LayerModel _LayerModel;
SoloModel _SoloModel;
SampleFormat _SampleFormat;
+ CDMarkerFormat _CDMarkerFormat;
HeaderFormat _HeaderFormat;
PluginType _PluginType;
SlaveSource _SlaveSource;
@@ -86,6 +90,18 @@ setup_enum_writer ()
Region::PositionLockStyle _Region_PositionLockStyle;
Track::FreezeState _Track_FreezeState;
AutomationList::InterpolationStyle _AutomationList_InterpolationStyle;
+ AnyTime::Type _AnyTime_Type;
+ ExportFilename::TimeFormat _ExportFilename_TimeFormat;
+ ExportFilename::DateFormat _ExportFilename_DateFormat;
+ ExportFormatBase::Type _ExportFormatBase_Type;
+ ExportFormatBase::FormatId _ExportFormatBase_FormatId;
+ ExportFormatBase::Endianness _ExportFormatBase_Endianness;
+ ExportFormatBase::SampleFormat _ExportFormatBase_SampleFormat;
+ ExportFormatBase::DitherType _ExportFormatBase_DitherType;
+ ExportFormatBase::Quality _ExportFormatBase_Quality;
+ ExportFormatBase::SampleRate _ExportFormatBase_SampleRate;
+ ExportFormatBase::SRCQuality _ExportFormatBase_SRCQuality;
+ ExportProfileManager::TimeFormat _ExportProfileManager_TimeFormat;
#define REGISTER(e) enum_writer->register_distinct (typeid(e).name(), i, s); i.clear(); s.clear()
#define REGISTER_BITS(e) enum_writer->register_bits (typeid(e).name(), i, s); i.clear(); s.clear()
@@ -213,6 +229,11 @@ setup_enum_writer ()
REGISTER_ENUM (FormatInt16);
REGISTER (_SampleFormat);
+ REGISTER_ENUM (CDMarkerNone);
+ REGISTER_ENUM (CDMarkerCUE);
+ REGISTER_ENUM (CDMarkerTOC);
+ REGISTER (_CDMarkerFormat);
+
REGISTER_ENUM (BWF);
REGISTER_ENUM (WAVE);
REGISTER_ENUM (WAVE64);
@@ -386,4 +407,89 @@ setup_enum_writer ()
REGISTER_CLASS_ENUM (AutomationList, Curved);
REGISTER (_AutomationList_InterpolationStyle);
+ REGISTER_CLASS_ENUM (AnyTime, SMPTE);
+ REGISTER_CLASS_ENUM (AnyTime, BBT);
+ REGISTER_CLASS_ENUM (AnyTime, Frames);
+ REGISTER_CLASS_ENUM (AnyTime, Seconds);
+ REGISTER (_AnyTime_Type);
+
+ REGISTER_CLASS_ENUM (ExportFilename, D_None);
+ REGISTER_CLASS_ENUM (ExportFilename, D_ISO);
+ REGISTER_CLASS_ENUM (ExportFilename, D_ISOShortY);
+ REGISTER_CLASS_ENUM (ExportFilename, D_BE);
+ REGISTER_CLASS_ENUM (ExportFilename, D_BEShortY);
+ REGISTER (_ExportFilename_DateFormat);
+
+ REGISTER_CLASS_ENUM (ExportFilename, T_None);
+ REGISTER_CLASS_ENUM (ExportFilename, T_NoDelim);
+ REGISTER_CLASS_ENUM (ExportFilename, T_Delim);
+ REGISTER (_ExportFilename_TimeFormat);
+
+ REGISTER_CLASS_ENUM (ExportFormatBase, T_None);
+ REGISTER_CLASS_ENUM (ExportFormatBase, T_Sndfile);
+ REGISTER (_ExportFormatBase_Type);
+
+ REGISTER_CLASS_ENUM (ExportFormatBase, F_None);
+ REGISTER_CLASS_ENUM (ExportFormatBase, F_WAV);
+ REGISTER_CLASS_ENUM (ExportFormatBase, F_W64);
+ REGISTER_CLASS_ENUM (ExportFormatBase, F_AIFF);
+ REGISTER_CLASS_ENUM (ExportFormatBase, F_AU);
+ REGISTER_CLASS_ENUM (ExportFormatBase, F_IRCAM);
+ REGISTER_CLASS_ENUM (ExportFormatBase, F_RAW);
+ REGISTER_CLASS_ENUM (ExportFormatBase, F_FLAC);
+ REGISTER_CLASS_ENUM (ExportFormatBase, F_Ogg);
+ REGISTER (_ExportFormatBase_FormatId);
+
+ REGISTER_CLASS_ENUM (ExportFormatBase, E_FileDefault);
+ REGISTER_CLASS_ENUM (ExportFormatBase, E_Little);
+ REGISTER_CLASS_ENUM (ExportFormatBase, E_Big);
+ REGISTER_CLASS_ENUM (ExportFormatBase, E_Cpu);
+ REGISTER (_ExportFormatBase_Endianness);
+
+ REGISTER_CLASS_ENUM (ExportFormatBase, SF_None);
+ REGISTER_CLASS_ENUM (ExportFormatBase, SF_8);
+ REGISTER_CLASS_ENUM (ExportFormatBase, SF_16);
+ REGISTER_CLASS_ENUM (ExportFormatBase, SF_24);
+ REGISTER_CLASS_ENUM (ExportFormatBase, SF_32);
+ REGISTER_CLASS_ENUM (ExportFormatBase, SF_U8);
+ REGISTER_CLASS_ENUM (ExportFormatBase, SF_Float);
+ REGISTER_CLASS_ENUM (ExportFormatBase, SF_Double);
+ REGISTER_CLASS_ENUM (ExportFormatBase, SF_Vorbis);
+ REGISTER (_ExportFormatBase_SampleFormat);
+
+ REGISTER_CLASS_ENUM (ExportFormatBase, D_None);
+ REGISTER_CLASS_ENUM (ExportFormatBase, D_Rect);
+ REGISTER_CLASS_ENUM (ExportFormatBase, D_Tri);
+ REGISTER_CLASS_ENUM (ExportFormatBase, D_Shaped);
+ REGISTER (_ExportFormatBase_DitherType);
+
+ REGISTER_CLASS_ENUM (ExportFormatBase, Q_None);
+ REGISTER_CLASS_ENUM (ExportFormatBase, Q_Any);
+ REGISTER_CLASS_ENUM (ExportFormatBase, Q_LosslessLinear);
+ REGISTER_CLASS_ENUM (ExportFormatBase, Q_LosslessCompression);
+ REGISTER_CLASS_ENUM (ExportFormatBase, Q_LossyCompression);
+ REGISTER (_ExportFormatBase_Quality);
+
+ REGISTER_CLASS_ENUM (ExportFormatBase, SR_None);
+ REGISTER_CLASS_ENUM (ExportFormatBase, SR_22_05);
+ REGISTER_CLASS_ENUM (ExportFormatBase, SR_44_1);
+ REGISTER_CLASS_ENUM (ExportFormatBase, SR_48);
+ REGISTER_CLASS_ENUM (ExportFormatBase, SR_88_2);
+ REGISTER_CLASS_ENUM (ExportFormatBase, SR_96);
+ REGISTER_CLASS_ENUM (ExportFormatBase, SR_192);
+ REGISTER (_ExportFormatBase_SampleRate);
+
+ REGISTER_CLASS_ENUM (ExportFormatBase, SRC_SincBest);
+ REGISTER_CLASS_ENUM (ExportFormatBase, SRC_SincMedium);
+ REGISTER_CLASS_ENUM (ExportFormatBase, SRC_SincFast);
+ REGISTER_CLASS_ENUM (ExportFormatBase, SRC_ZeroOrderHold);
+ REGISTER_CLASS_ENUM (ExportFormatBase, SRC_Linear);
+ REGISTER (_ExportFormatBase_SRCQuality);
+
+ REGISTER_CLASS_ENUM (ExportProfileManager, SMPTE);
+ REGISTER_CLASS_ENUM (ExportProfileManager, BBT);
+ REGISTER_CLASS_ENUM (ExportProfileManager, MinSec);
+ REGISTER_CLASS_ENUM (ExportProfileManager, Frames);
+ REGISTER_CLASS_ENUM (ExportProfileManager, Off);
+ REGISTER (_ExportProfileManager_TimeFormat);
}
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index 311e272903..ffa7d17761 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -47,6 +47,7 @@
#include <ardour/configuration.h>
#include <ardour/session.h>
#include <ardour/session_directory.h>
+#include <ardour/session_metadata.h>
#include <ardour/utils.h>
#include <ardour/audio_diskstream.h>
#include <ardour/audioplaylist.h>
@@ -143,7 +144,8 @@ Session::Session (AudioEngine &eng,
_total_free_4k_blocks (0),
_bundle_xml_node (0),
_click_io ((IO*) 0),
- main_outs (0)
+ main_outs (0),
+ _metadata (new SessionMetadata())
{
bool new_session;
diff --git a/libs/ardour/session_export.cc b/libs/ardour/session_export.cc
index 0111e4ed0b..aed32e278b 100644
--- a/libs/ardour/session_export.cc
+++ b/libs/ardour/session_export.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 1999-2002 Paul Davis
+ Copyright (C) 1999-2008 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
@@ -17,35 +17,18 @@
*/
-/* see gdither.cc for why we have to do this */
-
-#define _ISOC9X_SOURCE 1
-#define _ISOC99_SOURCE 1
-#include <cmath>
-#undef _ISOC99_SOURCE
-#undef _ISOC9X_SOURCE
-#undef __USE_SVID
-#define __USE_SVID 1
-#include <cstdlib>
-#undef __USE_SVID
-
-#include <unistd.h>
-#include <inttypes.h>
-#include <float.h>
-
#include <sigc++/bind.h>
#include <pbd/error.h>
#include <glibmm/thread.h>
-#include <ardour/gdither.h>
+#include <ardour/export_failed.h>
+#include <ardour/export_file_io.h>
+#include <ardour/export_utilities.h>
+#include <ardour/export_handler.h>
#include <ardour/timestamps.h>
#include <ardour/ardour.h>
#include <ardour/session.h>
-#include <ardour/export.h>
-#include <ardour/sndfile_helpers.h>
-#include <ardour/port.h>
-#include <ardour/audio_port.h>
#include <ardour/audioengine.h>
#include <ardour/audio_diskstream.h>
#include <ardour/panner.h>
@@ -56,415 +39,28 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
-static int
-convert_spec_to_info (ExportSpecification& spec, SF_INFO& sfinfo)
-{
- if (spec.path.length() == 0) {
- error << _("Export: no output file specified") << endmsg;
- return -1;
- }
-
- /* XXX add checks that the directory path exists, and also
- check if we are overwriting an existing file...
- */
-
- sfinfo.format = spec.format;
- sfinfo.samplerate = spec.sample_rate;
- sfinfo.frames = spec.end_frame - spec.start_frame + 1;
- sfinfo.channels = min (spec.channels, 2U);
-
- return 0;
-}
-
-ExportSpecification::ExportSpecification ()
+boost::shared_ptr<ExportHandler>
+Session::get_export_handler ()
{
- init ();
-}
-
-ExportSpecification::~ExportSpecification ()
-{
- clear ();
-}
-
-void
-ExportSpecification::init ()
-{
- src_state = 0;
- pos = 0;
- total_frames = 0;
- out = 0;
- channels = 0;
- running = false;
- stop = false;
- progress = 0.0;
- status = 0;
- dither = 0;
- start_frame = 0;
- end_frame = 0;
- dataF = 0;
- dataF2 = 0;
- leftoverF = 0;
- max_leftover_frames = 0;
- leftover_frames = 0;
- output_data = 0;
- out_samples_max = 0;
- data_width = 0;
- do_freewheel = false;
-}
-
-void
-ExportSpecification::clear ()
-{
- if (out) {
- sf_close (out);
- out = 0;
- }
-
- if (src_state) {
- src_delete (src_state);
- src_state = 0;
- }
-
- if (dither) {
- gdither_free (dither);
- dither = 0;
- }
-
- if (output_data) {
- free (output_data);
- output_data = 0;
- }
- if (dataF) {
- delete [] dataF;
- dataF = 0;
- }
- if (dataF2) {
- delete [] dataF2;
- dataF2 = 0;
- }
- if (leftoverF) {
- delete [] leftoverF;
- leftoverF = 0;
- }
-
- freewheel_connection.disconnect ();
-
- init ();
-}
-
-int
-ExportSpecification::prepare (nframes_t blocksize, nframes_t frate)
-{
- char errbuf[256];
- GDitherSize dither_size;
-
- frame_rate = frate;
-
- if (channels == 0) {
- error << _("illegal channel count in export specification") << endmsg;
- return -1;
- }
-
- if (start_frame >= end_frame) {
- error << _("illegal frame range in export specification") << endmsg;
- return -1;
- }
-
- if ((data_width = sndfile_data_width(format)) == 0) {
- error << _("Bad data width size. Report me!") << endmsg;
- return -1;
- }
-
- switch (data_width) {
- case 8:
- dither_size = GDither8bit;
- break;
-
- case 16:
- dither_size = GDither16bit;
- break;
-
- case 24:
- dither_size = GDither32bit;
- break;
-
- default:
- dither_size = GDitherFloat;
- break;
+ if (!export_handler) {
+ export_handler.reset (new ExportHandler (*this));
}
-
- if (convert_spec_to_info (*this, sfinfo)) {
- return -1;
- }
-
- /* XXX make sure we have enough disk space for the output */
-
- if ((out = sf_open (path.c_str(), SFM_WRITE, &sfinfo)) == 0) {
- sf_error_str (0, errbuf, sizeof (errbuf) - 1);
- error << string_compose(_("Export: cannot open output file \"%1\" (%2)"), path, errbuf) << endmsg;
- return -1;
- }
-
- dataF = new float[blocksize * channels];
-
- if (sample_rate != frame_rate) {
- int err;
-
- if ((src_state = src_new (src_quality, channels, &err)) == 0) {
- error << string_compose (_("cannot initialize sample rate conversion: %1"), src_strerror (err)) << endmsg;
- return -1;
- }
-
- src_data.src_ratio = sample_rate / (double) frame_rate;
- out_samples_max = (nframes_t) ceil (blocksize * src_data.src_ratio * channels);
- dataF2 = new float[out_samples_max];
-
- max_leftover_frames = 4 * blocksize;
- leftoverF = new float[max_leftover_frames * channels];
- leftover_frames = 0;
-
- } else {
- out_samples_max = blocksize * channels;
- }
-
- dither = gdither_new (dither_type, channels, dither_size, data_width);
-
- /* allocate buffers where dithering and output will occur */
-
- switch (data_width) {
- case 8:
- sample_bytes = 1;
- break;
-
- case 16:
- sample_bytes = 2;
- break;
-
- case 24:
- case 32:
- sample_bytes = 4;
- break;
-
- default:
- sample_bytes = 0; // float format
- break;
- }
-
- if (sample_bytes) {
- output_data = (void*) malloc (sample_bytes * out_samples_max);
- }
-
- pos = start_frame;
- end_frame = end_frame;
- total_frames = end_frame - start_frame;
- running = true;
- do_freewheel = false; /* force a call to ::prepare_to_export() before proceeding to normal operation */
-
- return 0;
-}
-
-int
-ExportSpecification::process (nframes_t nframes)
-{
- float* float_buffer = 0;
- uint32_t chn;
- uint32_t x;
- uint32_t i;
- sf_count_t written;
- char errbuf[256];
- nframes_t to_write = 0;
- int cnt = 0;
-
- do {
-
- /* now do sample rate conversion */
-
- if (sample_rate != frame_rate) {
-
- int err;
-
- src_data.output_frames = out_samples_max / channels;
- src_data.end_of_input = ((pos + nframes) >= end_frame);
- src_data.data_out = dataF2;
-
- if (leftover_frames > 0) {
-
- /* input data will be in leftoverF rather than dataF */
-
- src_data.data_in = leftoverF;
-
- if (cnt == 0) {
-
- /* first time, append new data from dataF into the leftoverF buffer */
-
- memcpy (leftoverF + (leftover_frames * channels), dataF, nframes * channels * sizeof(float));
- src_data.input_frames = nframes + leftover_frames;
- } else {
-
- /* otherwise, just use whatever is still left in leftoverF; the contents
- were adjusted using memmove() right after the last SRC call (see
- below)
- */
-
- src_data.input_frames = leftover_frames;
- }
-
- } else {
-
- src_data.data_in = dataF;
- src_data.input_frames = nframes;
-
- }
-
- ++cnt;
-
- if ((err = src_process (src_state, &src_data)) != 0) {
- error << string_compose (_("an error occured during sample rate conversion: %1"),
- src_strerror (err))
- << endmsg;
- return -1;
- }
-
- to_write = src_data.output_frames_gen;
- leftover_frames = src_data.input_frames - src_data.input_frames_used;
-
- if (leftover_frames > 0) {
- if (leftover_frames > max_leftover_frames) {
- error << _("warning, leftover frames overflowed, glitches might occur in output") << endmsg;
- leftover_frames = max_leftover_frames;
- }
- memmove (leftoverF, (char *) (src_data.data_in + (src_data.input_frames_used * channels)),
- leftover_frames * channels * sizeof(float));
- }
-
- float_buffer = dataF2;
-
- } else {
-
- /* no SRC, keep it simple */
-
- to_write = nframes;
- leftover_frames = 0;
- float_buffer = dataF;
- }
-
- if (output_data) {
- memset (output_data, 0, sample_bytes * to_write * channels);
- }
-
- switch (data_width) {
- case 8:
- case 16:
- case 24:
- for (chn = 0; chn < channels; ++chn) {
- gdither_runf (dither, chn, to_write, float_buffer, output_data);
- }
- break;
-
- case 32:
- for (chn = 0; chn < channels; ++chn) {
-
- int *ob = (int *) output_data;
- const double int_max = (float) INT_MAX;
- const double int_min = (float) INT_MIN;
-
- for (x = 0; x < to_write; ++x) {
- i = chn + (x * channels);
-
- if (float_buffer[i] > 1.0f) {
- ob[i] = INT_MAX;
- } else if (float_buffer[i] < -1.0f) {
- ob[i] = INT_MIN;
- } else {
- if (float_buffer[i] >= 0.0f) {
- ob[i] = lrintf (int_max * float_buffer[i]);
- } else {
- ob[i] = - lrintf (int_min * float_buffer[i]);
- }
- }
- }
- }
- break;
-
- default:
- for (x = 0; x < to_write * channels; ++x) {
- if (float_buffer[x] > 1.0f) {
- float_buffer[x] = 1.0f;
- } else if (float_buffer[x] < -1.0f) {
- float_buffer[x] = -1.0f;
- }
- }
- break;
- }
-
- /* and export to disk */
-
- switch (data_width) {
- case 8:
- /* XXXX no way to deliver 8 bit audio to libsndfile */
- written = to_write;
- break;
-
- case 16:
- written = sf_writef_short (out, (short*) output_data, to_write);
- break;
-
- case 24:
- case 32:
- written = sf_writef_int (out, (int*) output_data, to_write);
- break;
-
- default:
- written = sf_writef_float (out, float_buffer, to_write);
- break;
- }
- if ((nframes_t) written != to_write) {
- sf_error_str (out, errbuf, sizeof (errbuf) - 1);
- error << string_compose(_("Export: could not write data to output file (%1)"), errbuf) << endmsg;
- return -1;
- }
-
-
- } while (leftover_frames >= nframes);
-
- return 0;
+ return export_handler;
}
-int
-Session::start_export (ExportSpecification& spec)
+void
+Session::release_export_handler ()
{
- if (!_engine.connected()) {
- return -1;
- }
-
- if (spec.prepare (current_block_size, frame_rate())) {
- return -1;
+ if (!_exporting) {
+ export_handler.reset();
}
-
- spec.freewheel_connection = _engine.Freewheel.connect (sigc::bind (mem_fun (*this, &Session::process_export), &spec));
-
- cerr << "Start export at pos = " << spec.pos << endl;
-
- return _engine.freewheel (true);
-}
-
-int
-Session::stop_export (ExportSpecification& spec)
-{
- /* don't stop freewheeling but do stop paying attention to it for now */
-
- spec.freewheel_connection.disconnect ();
- spec.clear (); /* resets running/stop etc */
-
- Exported (spec.path, name());
-
- return 0;
}
int
Session::pre_export ()
{
+
wait_till_butler_finished ();
/* take everyone out of awrite to avoid disasters */
@@ -489,39 +85,41 @@ Session::pre_export ()
post_export_position = _transport_frame;
Config->set_slave_source (None);
+
+ _exporting = true;
+ export_status.running = true;
+ export_abort_connection = export_status.Aborting.connect (sigc::mem_fun (*this, &Session::abort_audio_export));
return 0;
}
-int
-Session::prepare_to_export (ExportSpecification& spec)
+int
+Session::start_audio_export (nframes_t position, bool realtime)
{
- int ret = -1;
-
/* get everyone to the right position */
{
boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
- if ((*i)-> seek (spec.start_frame, true)) {
+ if ((*i)-> seek (position, true)) {
error << string_compose (_("%1: cannot seek to %2 for export"),
- (*i)->name(), spec.start_frame)
+ (*i)->name(), position)
<< endmsg;
- goto out;
+ return -1;
}
}
}
- cerr << "Everybdy is at " << spec.start_frame << endl;
-
/* we just did the core part of a locate() call above, but
for the sake of any GUI, put the _transport_frame in
the right place too.
*/
- _transport_frame = spec.start_frame;
- _exporting = true;
+ _transport_frame = position;
+
+ _exporting_realtime = realtime;
+ export_status.stop = false;
/* get transport ready. note how this is calling butler functions
from a non-butler thread. we waited for the butler to stop
@@ -535,144 +133,107 @@ Session::prepare_to_export (ExportSpecification& spec)
post_transport ();
/* we are ready to go ... */
+
+ if (!_engine.connected()) {
+ return -1;
+ }
- ret = 0;
+ if (realtime) {
+ last_process_function = process_function;
+ process_function = &Session::process_export;
+ } else {
+ export_freewheel_connection = _engine.Freewheel.connect (sigc::mem_fun (*this, &Session::process_export_fw));
+ return _engine.freewheel (true);
+ }
- out:
- return ret;
+ return 0;
}
-int
-Session::process_export (nframes_t nframes, ExportSpecification* spec)
+void
+Session::process_export (nframes_t nframes)
{
- uint32_t chn;
- uint32_t x;
- int ret = -1;
- nframes_t this_nframes;
+ try {
- cerr << "Export process at pos = " << spec->pos << " _exporting = "
- << _exporting << " running = " << spec->running << " stop = "
- << spec->stop << endl;
-
- /* This is not required to be RT-safe because we are running while freewheeling */
-
- if (spec->do_freewheel == false) {
-
- /* first time in export function: get set up */
-
- if (prepare_to_export (*spec)) {
- spec->running = false;
- spec->status = -1;
- return -1;
+ if (export_status.stop) {
+ stop_audio_export ();
+ return;
}
-
- spec->do_freewheel = true;
- }
-
- if (!_exporting) {
- /* finished, but still freewheeling */
- cerr << "\tExport ... not exporting yet, no_roll() for " << nframes <<endl;
- no_roll (nframes, 0);
- return 0;
- }
- if (!spec->running || spec->stop || (this_nframes = min ((spec->end_frame - spec->pos), nframes)) == 0) {
- cerr << "\tExport ... not running or at end, no_roll() for " << nframes <<endl;
- no_roll (nframes, 0);
- return stop_export (*spec);
- }
-
- /* make sure we've caught up with disk i/o, since
- we're running faster than realtime c/o JACK.
- */
-
- wait_till_butler_finished ();
+ if (!_exporting_realtime) {
+ /* make sure we've caught up with disk i/o, since
+ we're running faster than realtime c/o JACK.
+ */
+
+ wait_till_butler_finished ();
+ }
- /* do the usual stuff */
+ /* do the usual stuff */
- process_without_events (nframes);
-
- /* and now export the results */
-
- nframes = this_nframes;
-
- memset (spec->dataF, 0, sizeof (spec->dataF[0]) * nframes * spec->channels);
-
- /* foreach output channel ... */
+ process_without_events (nframes);
- for (chn = 0; chn < spec->channels; ++chn) {
-
- ExportPortMap::iterator mi = spec->port_map.find (chn);
-
- if (mi == spec->port_map.end()) {
- /* no ports exported to this channel */
- continue;
- }
-
- vector<PortChannelPair>& mapped_ports ((*mi).second);
-
- for (vector<PortChannelPair>::iterator t = mapped_ports.begin(); t != mapped_ports.end(); ++t) {
-
- /* OK, this port's output is supposed to appear on this channel
- */
+ /* handle export */
+
+ ProcessExport (nframes);
- AudioPort* const aport = dynamic_cast<AudioPort*>((*t).first);
- MidiPort* const mport = dynamic_cast<MidiPort*>((*t).first);
- if (aport != 0) {
- Sample* port_buffer = aport->get_audio_buffer().data();
+ } catch (ExportFailed e) {
- /* now interleave the data from the channel into the float buffer */
+ std::cerr << e.what() << std::endl;
+ stop_audio_export();
+ finalize_audio_export();
- for (x = 0; x < nframes; ++x) {
- spec->dataF[chn+(x*spec->channels)] += (float) port_buffer[x];
- }
- } else if (mport != 0) {
- cerr << "EXPORT MIDI PORT" << endl;
- }
- }
}
+}
- cerr << "\tprocess " << nframes << endl;
+int
+Session::process_export_fw (nframes_t nframes)
+{
+ process_export (nframes);
+ return 0;
+}
- if (spec->process (nframes)) {
- goto out;
+int
+Session::stop_audio_export ()
+{
+ if (_exporting_realtime) {
+ process_function = last_process_function;
+ } else {
+ export_freewheel_connection.disconnect();
}
-
- spec->pos += nframes;
- spec->progress = 1.0 - (((float) spec->end_frame - spec->pos) / spec->total_frames);
-
- cerr << "\t@ " << spec->pos << " prog = " << spec->progress << endl;
- /* and we're good to go */
+ /* can't use stop_transport() here because we need
+ an immediate halt and don't require all the declick
+ stuff that stop_transport() implements.
+ */
- ret = 0;
+ realtime_stop (true);
+ schedule_butler_transport_work ();
- out:
- if (ret) {
- sf_close (spec->out);
- spec->out = 0;
- unlink (spec->path.c_str());
- spec->running = false;
- spec->status = ret;
- _exporting = false;
+ if (!export_status.aborted()) {
+ ExportFinished ();
}
+
+ return 0;
- return ret;
}
void
-Session::finalize_export ()
+Session::finalize_audio_export ()
{
- _engine.freewheel (false);
_exporting = false;
+ export_status.running = false;
- /* can't use stop_transport() here because we need
- an immediate halt and don't require all the declick
- stuff that stop_transport() implements.
- */
+ if (!_exporting_realtime) {
+ _engine.freewheel (false);
+ _exporting_realtime = false;
+ }
- realtime_stop (true);
- schedule_butler_transport_work ();
+ /* Clean up */
+
+ ProcessExport.clear();
+ ExportFinished.clear();
+ export_freewheel_connection.disconnect();
+ export_abort_connection.disconnect();
+ export_handler.reset();
/* restart slaving */
@@ -682,3 +243,10 @@ Session::finalize_export ()
locate (post_export_position, false, false, false);
}
}
+
+void
+Session::abort_audio_export ()
+{
+ stop_audio_export ();
+ finalize_audio_export ();
+}
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index 8ebf3ab07b..3d5e7fb24e 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -64,6 +64,7 @@
#include <ardour/session_directory.h>
#include <ardour/session_utils.h>
#include <ardour/session_state_utils.h>
+#include <ardour/session_metadata.h>
#include <ardour/buffer.h>
#include <ardour/audio_diskstream.h>
#include <ardour/midi_diskstream.h>
@@ -77,7 +78,6 @@
#include <ardour/midi_source.h>
#include <ardour/sndfile_helpers.h>
#include <ardour/auditioner.h>
-#include <ardour/export.h>
#include <ardour/io_processor.h>
#include <ardour/send.h>
#include <ardour/processor.h>
@@ -200,6 +200,7 @@ Session::first_stage_init (string fullpath, string snapshot_name)
_play_range = false;
waiting_to_start = false;
_exporting = false;
+ _exporting_realtime = false;
_gain_automation_buffer = 0;
_pan_automation_buffer = 0;
_npan_buffers = 0;
@@ -537,6 +538,10 @@ Session::create (bool& new_session, const string& mix_template, nframes_t initia
}
}
+
+ /* Instantiate metadata */
+
+ _metadata = new SessionMetadata ();
/* set initial start + end point */
@@ -977,6 +982,8 @@ Session::state(bool full_state)
node->add_child_nocopy (get_options());
+ node->add_child_nocopy (_metadata->get_state());
+
child = node->add_child ("Sources");
if (full_state) {
@@ -1202,6 +1209,7 @@ Session::set_state (const XMLNode& node)
Path
extra
Options/Config
+ Metadata
Locations
Sources
AudioRegions
@@ -1229,6 +1237,12 @@ Session::set_state (const XMLNode& node)
error << _("Session: XML state has no options section") << endmsg;
}
+ if ((child = find_named_node (node, "Metadata")) == 0) {
+ warning << _("Session: XML state has no metadata section (2.0 session?)") << endmsg;
+ } else if (_metadata->set_state (*child)) {
+ goto out;
+ }
+
if ((child = find_named_node (node, "Locations")) == 0) {
error << _("Session: XML state has no locations section") << endmsg;
goto out;
@@ -2895,10 +2909,12 @@ Session::controllable_by_id (const PBD::ID& id)
}
void
-Session::add_instant_xml (XMLNode& node)
+Session::add_instant_xml (XMLNode& node, bool write_to_config)
{
Stateful::add_instant_xml (node, _path);
- Config->add_instant_xml (node);
+ if (write_to_config) {
+ Config->add_instant_xml (node);
+ }
}
XMLNode*
diff --git a/libs/ardour/session_time.cc b/libs/ardour/session_time.cc
index a388e31d80..77b58853c7 100644
--- a/libs/ardour/session_time.cc
+++ b/libs/ardour/session_time.cc
@@ -568,7 +568,7 @@ Session::jack_timebase_callback (jack_transport_state_t state,
}
ARDOUR::nframes_t
-Session::convert_to_frames_at (nframes_t position, AnyTime& any)
+Session::convert_to_frames_at (nframes_t position, AnyTime const & any)
{
double secs;