diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2008-09-17 08:44:51 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2008-09-17 08:44:51 +0000 |
commit | 1c299d5a5c493986ca4a19bd55a69281dabada86 (patch) | |
tree | dae18913a2261a157ba32308ef804050e1232542 /libs/ardour | |
parent | 8e9a83dfdc233898e7c470667c7c9b797c83fe8b (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/SConscript | 18 | ||||
-rw-r--r-- | libs/ardour/ardour/audioregion.h | 3 | ||||
-rw-r--r-- | libs/ardour/ardour/midi_region.h | 3 | ||||
-rw-r--r-- | libs/ardour/ardour/session.h | 40 | ||||
-rw-r--r-- | libs/ardour/ardour/types.h | 5 | ||||
-rw-r--r-- | libs/ardour/audioregion.cc | 120 | ||||
-rw-r--r-- | libs/ardour/enums.cc | 106 | ||||
-rw-r--r-- | libs/ardour/session.cc | 4 | ||||
-rw-r--r-- | libs/ardour/session_export.cc | 644 | ||||
-rw-r--r-- | libs/ardour/session_state.cc | 22 | ||||
-rw-r--r-- | libs/ardour/session_time.cc | 2 |
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; |