Ardour  9.2-192-g63870a7930
cmdpipe_writer.h
Go to the documentation of this file.
1 #ifndef AUDIOGRAPHER_CMDPIPE_WRITER_H
2 #define AUDIOGRAPHER_CMDPIPE_WRITER_H
3 
4 #include <string>
5 
6 #include <glib.h>
7 
9 #include "audiographer/sink.h"
10 #include "audiographer/types.h"
11 
12 #include "pbd/gstdio_compat.h"
13 #include "pbd/signals.h"
14 
15 #include "ardour/system_exec.h"
16 #include "ardour/export_failed.h"
17 
18 #if defined(COMPILER_MSVC) && defined(WAF_BUILD)
19 #include <io.h> //for write, close
20 #endif
21 
22 namespace AudioGrapher
23 {
24 
28 template <typename T = DefaultSampleType>
30  : public Sink<T>
31  , public Throwing<>
32  , public FlagDebuggable<>
33 {
34 public:
35  CmdPipeWriter (ARDOUR::SystemExec* proc, std::string const& path, int tmp_fd = -1, gchar* tmp_file = 0)
36  : samples_written (0)
37  , _proc (proc)
38  , _path (path)
39  , _tmp_fd (tmp_fd)
40  , _tmp_file (tmp_file)
41  {
43 
44  if (tmp_fd >= 0) {
45  ;
46  } else if (proc->start (ARDOUR::SystemExec::ShareWithParent)) {
47  throw ARDOUR::ExportFailed ("External encoder (ffmpeg) cannot be started.");
48  }
49  proc->Terminated.connect_same_thread (exec_connections, std::bind (&CmdPipeWriter::encode_complete, this));
50  }
51 
52  virtual ~CmdPipeWriter () {
53  delete _proc;
54  if (_tmp_fd >= 0) {
55  ::close (_tmp_fd);
56  }
57  if (_tmp_file) {
58  g_unlink (_tmp_file);
59  g_free (_tmp_file);
60  }
61  }
62 
65 
66  void flush (void)
67  {
68  _proc->close_stdin ();
69  _proc->wait ();
70  }
71 
72  void close (void)
73  {
74  _proc->terminate ();
75  }
76 
77  virtual void process (ProcessContext<T> const & c)
78  {
79  check_flags (*this, c);
80 
81  if (_tmp_fd < 0 && (!_proc || !_proc->is_running())) {
82  throw Exception (*this, "Target encoder process is not running");
83  }
84 
85  const size_t bytes_per_sample = sizeof (T);
86  samplecnt_t written;
87  if (_tmp_fd >= 0) {
88  written = write (_tmp_fd, (const void*) c.data(), c.samples() * bytes_per_sample) / bytes_per_sample;
89  } else {
90  written = _proc->write_to_stdin ((const void*) c.data(), c.samples() * bytes_per_sample) / bytes_per_sample;
91  }
92 
93  samples_written += written;
94 
95  if (throw_level (ThrowProcess) && written != c.samples()) {
96  throw Exception (*this, "Could not write data to output file");
97  }
98 
100  if (_tmp_fd >= 0) {
101  ::close (_tmp_fd);
102  _tmp_fd = -1;
104  throw ARDOUR::ExportFailed ("External encoder (ffmpeg) cannot be started.");
105  }
106  assert (_proc->is_running ());
107  } else {
108  _proc->close_stdin ();
109  }
110  _proc->wait ();
111  }
112  }
113 
114  using Sink<T>::process;
115 
116  PBD::Signal<void(std::string)> FileWritten;
117 
118 private:
119  CmdPipeWriter (CmdPipeWriter const & other) {}
120 
123  std::string _path;
124  int _tmp_fd;
125  gchar* _tmp_file;
126 
127  void encode_complete () {
128  if (_tmp_file) {
129  g_unlink (_tmp_file);
130  g_free (_tmp_file);
131  _tmp_file = NULL;
132  }
133  FileWritten (_path);
134  }
135 
137 };
138 
139 } // namespace
140 
141 #endif
142 
int start(StdErrMode stderr_mode=IgnoreAndClose)
samplecnt_t get_samples_written() const
CmdPipeWriter(CmdPipeWriter const &other)
virtual void process(ProcessContext< T > const &c)
CmdPipeWriter(ARDOUR::SystemExec *proc, std::string const &path, int tmp_fd=-1, gchar *tmp_file=0)
PBD::Signal< void(std::string)> FileWritten
PBD::ScopedConnectionList exec_connections
ARDOUR::SystemExec * _proc
A debugging class for nodes that support a certain set of flags.
void check_flags(SelfType &self, ProcessContext< ContextType > context)
Prints debug output if context contains flags that are not supported by this class.
void add_supported_flag(Flag flag)
Adds a flag to the set of flags supported.
bool has_flag(Flag flag) const
T const * data() const
data points to the array of data to process
samplecnt_t const & samples() const
samples tells how many samples the array pointed by data contains
bool throw_level(ThrowLevel level)
Definition: throwing.h:47
int wait(int options=0)
PBD::Signal< void()> Terminated
size_t write_to_stdin(std::string const &d, size_t len=0)
@ ThrowProcess
Process cycle level stuff.
Definition: throwing.h:23