diff --git a/libs/ardour/ardour/export_timespan.h b/libs/ardour/ardour/export_timespan.h index 3be722be11..88eca8aa09 100644 --- a/libs/ardour/ardour/export_timespan.h +++ b/libs/ardour/ardour/export_timespan.h @@ -54,6 +54,9 @@ public: std::string range_id () const { return _range_id; } void set_range_id (std::string range_id) { _range_id = range_id; } + std::string vapor () const { return _vapor; } + void set_vapor (std::string vapor) { _vapor = vapor; } + bool realtime () const { return _realtime; } void set_realtime (bool rt) { _realtime = rt; } @@ -80,8 +83,8 @@ private: std::string _name; std::string _range_id; + std::string _vapor; bool _realtime; - }; } // namespace ARDOUR diff --git a/libs/ardour/ardour/lv2_extensions.h b/libs/ardour/ardour/lv2_extensions.h index 48b076eb04..0ff97d6770 100644 --- a/libs/ardour/ardour/lv2_extensions.h +++ b/libs/ardour/ardour/lv2_extensions.h @@ -19,8 +19,10 @@ #ifdef HAVE_LV2_1_18_6 #include +#include #else #include +#include #endif /** @@ -280,6 +282,31 @@ typedef struct { void (*notify)(LV2_BankPatch_Handle handle, uint8_t channel, uint32_t bank, uint8_t pgm); } LV2_BankPatch; +/** + @} +*/ + +/** + @defgroup lv2 export Extension + + Notify plugin to write data to disk + + @{ +*/ + + +#define LV2_EXPORT_URI "http://ardour.org/lv2/export" +#define LV2_EXPORT_PREFIX LV2_EXPORT_URI "#" +#define LV2_EXPORT__interface LV2_EXPORT_PREFIX "interface" + +/** Export interface */ +typedef struct { + /** .. */ + int (*setup)(LV2_Handle, const char*, LV2_Options_Option const*); + /** .. */ + int (*finalize)(LV2_Handle); +} LV2_Export_Interface; + /** @} */ diff --git a/libs/ardour/ardour/lv2_plugin.h b/libs/ardour/ardour/lv2_plugin.h index 8014202322..9f4c4bafb9 100644 --- a/libs/ardour/ardour/lv2_plugin.h +++ b/libs/ardour/ardour/lv2_plugin.h @@ -93,6 +93,12 @@ class LIBARDOUR_API LV2Plugin : public ARDOUR::Plugin, public ARDOUR::Workee const void* extension_data (const char* uri) const; +#ifdef LV2_EXTENDED + int setup_export (const char*); + int finalize_export (); + bool can_export () const { return _export_interface; } +#endif + const void* c_plugin(); const void* c_ui(); const void* c_ui_type(); @@ -312,9 +318,10 @@ class LIBARDOUR_API LV2Plugin : public ARDOUR::Plugin, public ARDOUR::Workee static void midnam_update (LV2_Midnam_Handle); static void bankpatch_notify (LV2_BankPatch_Handle, uint8_t, uint32_t, uint8_t); - const LV2_Inline_Display_Interface* _display_interface; bool _inline_display_in_gui; - const LV2_Midnam_Interface* _midname_interface; + const LV2_Inline_Display_Interface* _display_interface; + const LV2_Midnam_Interface* _midname_interface; + const LV2_Export_Interface* _export_interface; uint32_t _bankpatch[16]; bool seen_bankpatch; diff --git a/libs/ardour/ardour/uri_map.h b/libs/ardour/ardour/uri_map.h index efedf7fa01..35a96450a7 100644 --- a/libs/ardour/ardour/uri_map.h +++ b/libs/ardour/ardour/uri_map.h @@ -113,6 +113,8 @@ public: uint32_t surr_ChannelCount; uint32_t surr_DownmixMode; uint32_t surr_WarpMode; + uint32_t surr_ExportStart; + uint32_t surr_ExportStop; #endif }; diff --git a/libs/ardour/export_graph_builder.cc b/libs/ardour/export_graph_builder.cc index dac160be32..0cf7e1509e 100644 --- a/libs/ardour/export_graph_builder.cc +++ b/libs/ardour/export_graph_builder.cc @@ -276,6 +276,11 @@ ExportGraphBuilder::add_config (FileSpec const & config, bool rt) _realtime = rt; + if (!timespan->vapor().empty()) { + /* plugin export needs no actual channels */ + return; + } + /* If the sample rate is "session rate", change it to the real value. * However, we need to copy it to not change the config which is saved... */ @@ -609,7 +614,7 @@ ExportGraphBuilder::SFC::SFC (ExportGraphBuilder &parent, FileSpec const & new_c if (config.format->format_id() == ExportFormatBase::F_None) { /* do not encode result, stop after chunker/analyzer */ - assert (_analyse); + assert (_analyse || !parent.timespan->vapor().empty()); return; } diff --git a/libs/ardour/lv2_plugin.cc b/libs/ardour/lv2_plugin.cc index 15a8943388..bd3698abb0 100644 --- a/libs/ardour/lv2_plugin.cc +++ b/libs/ardour/lv2_plugin.cc @@ -237,6 +237,7 @@ public: LilvNode* inline_display_interface; // lv2:extensionData LilvNode* inline_display_in_gui; // lv2:optionalFeature LilvNode* inline_mixer_control; // lv2:PortProperty + LilvNode* export_interface; // lv2:extensionData #endif private: @@ -521,6 +522,7 @@ LV2Plugin::init(const void* c_plugin, samplecnt_t rate) _can_write_automation = false; #ifdef LV2_EXTENDED _display_interface = 0; + _export_interface = 0; _inline_display_in_gui = false; #endif _max_latency = 0; @@ -761,6 +763,9 @@ LV2Plugin::init(const void* c_plugin, samplecnt_t rate) if (lilv_nodes_contains (optional_features, _world.inline_display_in_gui)) { _inline_display_in_gui = true; } + if (lilv_plugin_has_extension_data(plugin, _world.export_interface)) { + _export_interface = (const LV2_Export_Interface*) extension_data (LV2_EXPORT__interface); + } #endif lilv_nodes_free(optional_features); @@ -1209,6 +1214,25 @@ LV2Plugin::midnam_model () { _midname_interface->free (model); return rv; } + +int +LV2Plugin::setup_export (const char* fn) +{ + if (!_export_interface) { + return -1; + } + return _export_interface->setup ((void*)_impl->instance->lv2_handle, fn, NULL); +} + +int +LV2Plugin::finalize_export () +{ + if (!_export_interface) { + return -1; + } + return _export_interface->finalize ((void*)_impl->instance->lv2_handle); +} + #endif string @@ -3523,6 +3547,7 @@ LV2World::LV2World() inline_display_interface = lilv_new_uri(world, LV2_INLINEDISPLAY__interface); inline_display_in_gui = lilv_new_uri(world, LV2_INLINEDISPLAY__in_gui); inline_mixer_control = lilv_new_uri(world, "http://ardour.org/lv2/ext#inlineMixerControl"); + export_interface = lilv_new_uri(world, LV2_EXPORT__interface); #endif bufz_powerOf2BlockLength = lilv_new_uri(world, LV2_BUF_SIZE__powerOf2BlockLength); bufz_fixedBlockLength = lilv_new_uri(world, LV2_BUF_SIZE__fixedBlockLength); @@ -3551,6 +3576,7 @@ LV2World::~LV2World() lilv_node_free(inline_display_interface); lilv_node_free(inline_display_in_gui); lilv_node_free(inline_mixer_control); + lilv_node_free(export_interface); #endif lilv_node_free(patch_Message); lilv_node_free(opts_requiredOptions); diff --git a/libs/ardour/simple_export.cc b/libs/ardour/simple_export.cc index becdd01232..ed20fc5855 100644 --- a/libs/ardour/simple_export.cc +++ b/libs/ardour/simple_export.cc @@ -19,6 +19,7 @@ #include #include "ardour/export_channel_configuration.h" +#include "ardour/export_format_specification.h" #include "ardour/export_filename.h" #include "ardour/export_preset.h" #include "ardour/export_profile_manager.h" @@ -189,11 +190,20 @@ SimpleExport::run_export () assert (!fns.empty ()); auto fms = _manager->get_formats (); - for (auto const& fm : fms) { - for (auto const& fn : fns) { - fn->filename->set_folder (_folder); - fn->filename->set_timespan (ts.front ()->timespans->front ()); - info << string_compose (_("Exporting: '%1'"), fn->filename->get_path (fm->format)) << endmsg; + if (ts.front ()->timespans->front ()->vapor().empty ()) { + for (auto const& fm : fms) { + for (auto const& fn : fns) { + fn->filename->set_folder (_folder); + fn->filename->set_timespan (ts.front ()->timespans->front ()); + info << string_compose (_("Exporting: '%1'"), fn->filename->get_path (fm->format)) << endmsg; + } + } + } else { + for (auto const& fm : fms) { + std::shared_ptr fmp = fm->format; + fmp->set_format_id (ExportFormatBase::F_None); + fmp->set_type (ExportFormatBase::T_None); + fmp->set_analyse (false); } } diff --git a/libs/ardour/uri_map.cc b/libs/ardour/uri_map.cc index 88a7caed3e..91bec92ddf 100644 --- a/libs/ardour/uri_map.cc +++ b/libs/ardour/uri_map.cc @@ -90,6 +90,8 @@ URIMap::URIDs::init(URIMap& uri_map) surr_ChannelCount = uri_map.uri_to_id("urn:ardour:a-vapor#ChannelCount"); surr_DownmixMode = uri_map.uri_to_id("urn:ardour:a-vapor#DownmixMode"); surr_WarpMode = uri_map.uri_to_id("urn:ardour:a-vapor#WarpMode"); + surr_ExportStart = uri_map.uri_to_id("urn:ardour:a-vapor#ExportStart"); + surr_ExportStop = uri_map.uri_to_id("urn:ardour:a-vapor#ExportStop"); #endif }