summaryrefslogtreecommitdiff
path: root/libs/audiographer
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2018-11-19 03:30:40 +0100
committerRobin Gareus <robin@gareus.org>2018-11-19 03:30:40 +0100
commite4cbd5115e34ff99aa8c85b70870e6ca00ea14d6 (patch)
tree8a6907f3dd5859c9013886bbef4aeda8f5b441e1 /libs/audiographer
parenta5b38fd6dc9ce9d1fb450da493adbc02b787c5e8 (diff)
Add Pipe-to-command export backend
A first step towards allowing external encoders without intermediate temporary file.
Diffstat (limited to 'libs/audiographer')
-rw-r--r--libs/audiographer/audiographer/general/cmdpipe_writer.h87
1 files changed, 87 insertions, 0 deletions
diff --git a/libs/audiographer/audiographer/general/cmdpipe_writer.h b/libs/audiographer/audiographer/general/cmdpipe_writer.h
new file mode 100644
index 0000000000..74dc604b8b
--- /dev/null
+++ b/libs/audiographer/audiographer/general/cmdpipe_writer.h
@@ -0,0 +1,87 @@
+#ifndef AUDIOGRAPHER_CMDPIPE_WRITER_H
+#define AUDIOGRAPHER_CMDPIPE_WRITER_H
+
+#include <string>
+
+#include <boost/format.hpp>
+
+#include "audiographer/flag_debuggable.h"
+#include "audiographer/sink.h"
+#include "audiographer/types.h"
+
+#include "pbd/signals.h"
+#include "pbd/system_exec.h"
+
+namespace AudioGrapher
+{
+
+/** Writer for audio files using libsndfile.
+ * Only short, int and float are valid template parameters
+ */
+template <typename T = DefaultSampleType>
+class CmdPipeWriter
+ : public Sink<T>
+ , public Throwing<>
+ , public FlagDebuggable<>
+{
+public:
+ CmdPipeWriter (PBD::SystemExec* proc, std::string const& path)
+ : samples_written (0)
+ , _proc (proc)
+ , _path (path)
+ {
+ add_supported_flag (ProcessContext<T>::EndOfInput);
+ }
+
+ virtual ~CmdPipeWriter () {
+ delete _proc;
+ }
+
+ samplecnt_t get_samples_written() const { return samples_written; }
+ void reset_samples_written_count() { samples_written = 0; }
+
+ void close (void)
+ {
+ _proc->terminate ();
+ }
+
+ virtual void process (ProcessContext<T> const & c)
+ {
+ check_flags (*this, c);
+
+ if (!_proc || !_proc->is_running()) {
+ throw Exception (*this, boost::str (boost::format
+ ("Target encoder process is not running")));
+ }
+
+ const size_t bytes_per_sample = sizeof (T);
+ samplecnt_t const written = _proc->write_to_stdin ((const void*) c.data(), c.samples() * bytes_per_sample) / bytes_per_sample;
+ samples_written += written;
+
+ if (throw_level (ThrowProcess) && written != c.samples()) {
+ throw Exception (*this, boost::str (boost::format
+ ("Could not write data to output file")));
+ }
+
+ if (c.has_flag(ProcessContext<T>::EndOfInput)) {
+ _proc->close_stdin ();
+ FileWritten (_path);
+ }
+ }
+
+ using Sink<T>::process;
+
+ PBD::Signal1<void, std::string> FileWritten;
+
+private:
+ CmdPipeWriter (CmdPipeWriter const & other) {}
+
+ samplecnt_t samples_written;
+ PBD::SystemExec* _proc;
+ std::string _path;
+};
+
+} // namespace
+
+#endif
+