ardour
auditioner.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2001 Paul Davis
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 
18 */
19 
20 #include <glibmm/threads.h>
21 
22 #include "pbd/error.h"
23 
24 #include "ardour/amp.h"
26 #include "ardour/audio_port.h"
27 #include "ardour/audioengine.h"
28 #include "ardour/audioplaylist.h"
29 #include "ardour/audioregion.h"
30 #include "ardour/auditioner.h"
31 #include "ardour/data_type.h"
32 #include "ardour/delivery.h"
33 #include "ardour/midi_diskstream.h"
34 #include "ardour/midi_region.h"
35 #include "ardour/plugin.h"
36 #include "ardour/plugin_insert.h"
37 #include "ardour/region_factory.h"
38 #include "ardour/route.h"
39 #include "ardour/session.h"
40 
41 using namespace std;
42 using namespace ARDOUR;
43 using namespace PBD;
44 
45 #include "i18n.h"
46 
47 Auditioner::Auditioner (Session& s)
48  : Track (s, "auditioner", Route::Auditioner)
49  , current_frame (0)
50  , _auditioning (0)
51  , length (0)
52  , _seek_frame (-1)
53  , _seeking (false)
54  , _seek_complete (false)
55  , via_monitor (false)
56  , _midi_audition (false)
57  , _synth_added (false)
58  , _synth_changed (false)
59  , _queue_panic (false)
60  , _import_position (0)
61 {
62 }
63 
64 int
66 {
67  if (Track::init ()) {
68  return -1;
69  }
70 
71  if (connect ()) {
72  return -1;
73  }
74 
75  _output->add_port ("", this, DataType::MIDI);
76 
77  lookup_synth();
78 
79  _output->changed.connect_same_thread (*this, boost::bind (&Auditioner::output_changed, this, _1, _2));
80  Config->ParameterChanged.connect_same_thread (*this, boost::bind (&Auditioner::config_changed, this, _1));
81 
82  return 0;
83 }
84 
86 {
87 }
88 
89 void
91 {
92  string plugin_id = Config->get_midi_audition_synth_uri();
94  if (!plugin_id.empty()) {
96  p = find_plugin (_session, plugin_id, ARDOUR::LV2);
97  if (!p) {
98  p = find_plugin (_session, "https://community.ardour.org/node/7596", ARDOUR::LV2);
99  if (p) {
100  warning << _("Falling back to Reasonable Synth for Midi Audition") << endmsg;
101  } else {
102  warning << _("No synth for midi-audition found.") << endmsg;
103  Config->set_midi_audition_synth_uri(""); // Don't check again for Reasonable Synth (ie --no-lv2)
104  }
105  }
106  if (p) {
108  }
109  }
110 }
111 
112 void
114 {
115  if (p == "midi-audition-synth-uri") {
116  _synth_changed = true;
117  }
118 }
119 
120 int
122 {
123  string left = Config->get_auditioner_output_left();
124  string right = Config->get_auditioner_output_right();
125 
126  vector<string> outputs;
128 
129  via_monitor = false;
130 
131  if (left.empty() || left == "default") {
132  if (_session.monitor_out()) {
133  left = _session.monitor_out()->input()->audio (0)->name();
134  via_monitor = true;
135  } else {
136  if (outputs.size() > 0) {
137  left = outputs[0];
138  }
139  }
140  }
141 
142  if (right.empty() || right == "default") {
143  if (_session.monitor_out()) {
144  right = _session.monitor_out()->input()->audio (1)->name();
145  via_monitor = true;
146  } else {
147  if (outputs.size() > 1) {
148  right = outputs[1];
149  }
150  }
151  }
152 
153  _output->disconnect (this);
154 
155  if (left.empty() && right.empty()) {
156  if (_output->n_ports().n_audio() == 0) {
157  /* ports not set up, so must be during startup */
158  warning << _("no outputs available for auditioner - manual connection required") << endmsg;
159  }
160  } else {
161 
162  if (_output->n_ports().n_audio() == 0) {
163 
164  /* create (and connect) new ports */
165 
166  _main_outs->defer_pan_reset ();
167 
168  if (left.length()) {
169  _output->add_port (left, this, DataType::AUDIO);
170  }
171 
172  if (right.length()) {
173  _output->add_port (right, this, DataType::AUDIO);
174  }
175 
176  _main_outs->allow_pan_reset ();
177  _main_outs->reset_panner ();
178 
179  } else {
180 
181  /* reconnect existing ports */
182 
183  boost::shared_ptr<Port> oleft (_output->nth (0));
184  boost::shared_ptr<Port> oright (_output->nth (1));
185  if (oleft) {
186  oleft->connect (left);
187  }
188  if (oright) {
189  oright->connect (right);
190  }
191  }
192 
193  }
194 
195  return 0;
196 }
197 
198 
199 DataType
201  if (_midi_audition) {
202  return DataType::MIDI;
203  } else {
204  return DataType::AUDIO;
205  }
206 }
207 
210 
211  {
215  }
216 
217  {
219  dflags = MidiDiskstream::Flag (dflags | MidiDiskstream::Hidden);
221  _diskstream_midi->do_refill_with_alloc ();
222  _diskstream_midi->playlist()->set_orig_track_id (id());
223  }
224 
225  return _diskstream_audio;
226 }
227 
228 int
229 Auditioner::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, int declick, bool& need_butler) {
230  if (_midi_audition) {
231  return roll_midi(nframes, start_frame, end_frame, declick, need_butler);
232  } else {
233  return roll_audio(nframes, start_frame, end_frame, declick, need_butler);
234  }
235 }
236 
237 int
238 Auditioner::roll_midi (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, int declick, bool& need_butler)
239 {
240  Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
241  if (!lm.locked()) {
242  return 0;
243  }
244 
245  assert(_active);
246 
247  framecnt_t playback_distance = nframes;
250  MidiBuffer& mbuf (bufs.get_midi (0));
251  _silent = false;
252 
253  ChanCount cnt (DataType::MIDI, 1);
254  cnt.set (DataType::AUDIO, bufs.count().n_audio());
255  bufs.set_count (cnt);
256 
257  if (_queue_panic) {
258  _queue_panic = false;
259  for (uint8_t chn = 0; chn < 0xf; ++chn) {
260  uint8_t buf[3] = { ((uint8_t) (MIDI_CMD_CONTROL | chn)), ((uint8_t) MIDI_CTL_SUSTAIN), 0 };
261  mbuf.push_back(0, 3, buf);
262  buf[1] = MIDI_CTL_ALL_NOTES_OFF;
263  mbuf.push_back(0, 3, buf);
265  mbuf.push_back(0, 3, buf);
266  }
267  process_output_buffers (bufs, start_frame, start_frame+1, 1, false, false);
268 
269  for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
271  if (d) {
272  d->flush_buffers (nframes);
273  }
274  }
275  }
276 
277  diskstream->get_playback (mbuf, nframes);
278 
279  process_output_buffers (bufs, start_frame, end_frame, nframes,
280  declick, (!diskstream->record_enabled() && !_session.transport_stopped()));
281 
282  for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
284  if (d) {
285  d->flush_buffers (nframes);
286  }
287  }
288 
289  need_butler = diskstream->commit (playback_distance);
290  return 0;
291 }
292 
293 
294 int
295 Auditioner::roll_audio (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, int declick, bool& need_butler) {
296  Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
297  if (!lm.locked()) {
298  return 0;
299  }
300 
301  assert(n_outputs().n_total() > 0);
302  assert(_active);
303 
304  int dret;
305  framecnt_t playback_distance;
306  framepos_t transport_frame = _session.transport_frame();
309 
310  _silent = false;
311  _amp->apply_gain_automation(false);
312 
313  if ((dret = diskstream->process (bufs, transport_frame, nframes, playback_distance, (monitoring_state() == MonitoringDisk))) != 0) {
314  need_butler = diskstream->commit (playback_distance);
315  silence (nframes);
316  return dret;
317  }
318 
319  process_output_buffers (bufs, start_frame, end_frame, nframes, declick, (!diskstream->record_enabled() && _session.transport_rolling()));
320  need_butler = diskstream->commit (playback_distance);
321  return 0;
322 }
323 
324 void
326 {
328 
329  _diskstream->set_track (this);
330  _diskstream->set_destructive (_mode == Destructive);
331  _diskstream->set_non_layered (_mode == NonLayered);
332  _diskstream->set_record_enabled (false);
333  _diskstream->request_input_monitoring (false);
334 
335  DiskstreamChanged (); /* EMIT SIGNAL */
336 }
337 
340 {
341  // used by CrossfadeEditor::audition()
342 
343  _midi_audition = false;
345  if (_synth_added) {
347  _synth_added = false;
348  }
349 
350  // FIXME auditioner is still audio-only
352  assert(apl);
353 
354  apl->clear ();
355  return *apl;
356 }
357 
358 void
360 {
361  if (g_atomic_int_get (&_auditioning)) {
362  /* don't go via session for this, because we are going
363  to remain active.
364  */
365  cancel_audition ();
366  }
367 
369 
370  if (boost::dynamic_pointer_cast<AudioRegion>(region) != 0) {
371 
372  _midi_audition = false;
374  if (_synth_added) {
376  _synth_added = false;
377  }
378  midi_region.reset();
379  _import_position = 0;
380 
381  /* copy it */
384 
385  _diskstream->playlist()->drop_regions ();
386  _diskstream->playlist()->add_region (the_region, 0, 1);
387 
388  if (_diskstream->n_channels().n_audio() < the_region->n_channels()) {
389  audio_diskstream()->add_channel (the_region->n_channels() - _diskstream->n_channels().n_audio());
390  } else if (_diskstream->n_channels().n_audio() > the_region->n_channels()) {
391  audio_diskstream()->remove_channel (_diskstream->n_channels().n_audio() - the_region->n_channels());
392  }
393 
394  ProcessorStreams ps;
395  {
396  Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
397 
398  if (configure_processors (&ps)) {
399  error << string_compose (_("Cannot setup auditioner processing flow for %1 channels"),
400  _diskstream->n_channels()) << endmsg;
401  return;
402  }
403  }
404 
405  } else if (boost::dynamic_pointer_cast<MidiRegion>(region)) {
406  _midi_audition = true;
408  the_region.reset();
409  _import_position = region->position();
410 
411  /* copy it */
413  midi_region->set_position (_import_position);
414 
415  _diskstream->playlist()->drop_regions ();
416  _diskstream->playlist()->add_region (midi_region, _import_position, 1);
417  midi_diskstream()->reset_tracker();
418 
419  ProcessorStreams ps;
420 
421  if (_synth_changed && _synth_added) {
423  _synth_added = false;
424  }
425  if (_synth_changed && !_synth_added) {
426  _synth_added = false;
427  lookup_synth();
428  }
429 
430 
431  if (!_synth_added && asynth) {
432  int rv = add_processor (asynth, PreFader, &ps, true);
433  if (rv) {
434  error << _("Failed to load synth for MIDI-Audition.") << endmsg;
435  } else {
436  _synth_added = true;
437  }
438  } else {
439  _queue_panic = true;
440  }
441 
442  {
443  Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
444 
445  if (configure_processors (&ps)) {
446  error << string_compose (_("Cannot setup auditioner processing flow for %1 channels"),
447  _diskstream->n_channels()) << endmsg;
448  return;
449  }
450  }
451 
452  } else {
453  error << _("Auditioning of regions other than Audio or Midi is not supported.") << endmsg;
454  return;
455  }
456 
457  /* force a panner reset now that we have all channels */
458  _main_outs->reset_panner();
459 
460  _seek_frame = -1;
461  _seeking = false;
462 
463  int dir;
464  framecnt_t offset;
465 
466  if (_midi_audition) {
467  length = midi_region->length();
468  offset = _import_position + midi_region->sync_offset (dir);
469  } else {
470  length = the_region->length();
471  offset = the_region->sync_offset (dir);
472  }
473 
474  /* can't audition from a negative sync point */
475 
476  if (dir < 0) {
477  offset = 0;
478  }
479 
480  _diskstream->seek (offset);
481  current_frame = offset;
482 
483  g_atomic_int_set (&_auditioning, 1);
484 }
485 
486 int
488 {
489  bool need_butler = false;
490  framecnt_t this_nframes;
491  int ret;
492 
493  if (g_atomic_int_get (&_auditioning) == 0) {
494  silence (nframes);
495  return 0;
496  }
497 
498 #if 0 // TODO
499  if (_seeking && _seek_complete) {
500  // set FADE-IN
501  } else if (_seek_frame >= 0 && _seek_frame < length && !_seeking) {
502  // set FADE-OUT -- use/override amp? || use region-gain ?
503  }
504 #endif
505 
506  if (_seeking && _seek_complete) {
507  _seek_complete = false;
508  _seeking = false;
509  _seek_frame = -1;
510  if (_midi_audition && midi_diskstream()) {
511  midi_diskstream()->reset_tracker();
512  }
513  }
514 
515  if(!_seeking) {
516  /* process audio */
517  this_nframes = min (nframes, length - current_frame + _import_position);
518 
519  if ((ret = roll (this_nframes, current_frame, current_frame + nframes, false, need_butler)) != 0) {
520  silence (nframes);
521  return ret;
522  }
523 
524  current_frame += this_nframes;
525 
526  } else {
527  silence (nframes);
528  }
529 
530  if (_seek_frame >= 0 && _seek_frame < length && !_seeking) {
531  _queue_panic = true;
532  _seek_complete = false;
533  _seeking = true;
534  need_butler = true;
535  }
536 
537  if (!_seeking) {
539  }
540 
543  return 0;
544  } else {
545  return need_butler ? 1 : 0;
546  }
547 }
548 
549 void
550 Auditioner::output_changed (IOChange change, void* /*src*/)
551 {
552  if (change.type & IOChange::ConnectionsChanged) {
553  string phys;
554  vector<string> connections;
555  vector<string> outputs;
557  if (_output->nth (0)->get_connections (connections)) {
558  if (outputs.size() > 0) {
559  phys = outputs[0];
560  }
561  if (phys != connections[0]) {
562  Config->set_auditioner_output_left (connections[0]);
563  } else {
564  Config->set_auditioner_output_left ("default");
565  }
566  } else {
567  Config->set_auditioner_output_left ("");
568  }
569 
570  connections.clear ();
571 
572  if (_output->nth (1)->get_connections (connections)) {
573  if (outputs.size() > 1) {
574  phys = outputs[1];
575  }
576  if (phys != connections[0]) {
577  Config->set_auditioner_output_right (connections[0]);
578  } else {
579  Config->set_auditioner_output_right ("default");
580  }
581  } else {
582  Config->set_auditioner_output_right ("");
583  }
584  }
585 }
586 
587 ChanCount
589 {
590  /* auditioner never has any inputs - its channel configuration
591  depends solely on the region we are auditioning.
592  */
593 
594  if (!_midi_audition && audio_diskstream()) {
595  return audio_diskstream()->n_channels();
596  }
597  if (_midi_audition && midi_diskstream()) {
598  ChanCount cnt (DataType::MIDI, 1);
599  return cnt;
600  }
601 
602  return ChanCount ();
603 }
604 
607 {
608  return MonitoringDisk;
609 }
610 
613 {
615 }
616 
619 {
621 }
bool transport_rolling() const
Definition: session.h:592
ARDOUR::Session & _session
boost::shared_ptr< Processor > asynth
Definition: auditioner.h:126
MidiBuffer & get_midi(size_t i)
Definition: buffer_set.h:107
boost::shared_ptr< AudioRegion > the_region
Definition: auditioner.h:109
boost::shared_ptr< Delivery > _main_outs
Definition: route.h:519
framecnt_t length
Definition: auditioner.h:114
bool _silent
Definition: route.h:550
PBD::Signal0< void > DiskstreamChanged
Definition: track.h:163
boost::shared_ptr< Diskstream > _diskstream_midi
Definition: auditioner.h:125
boost::shared_ptr< Amp > _amp
Definition: route.h:588
void flush_buffers(framecnt_t nframes)
Definition: delivery.cc:450
void set_count(const ChanCount &count)
Definition: buffer_set.h:93
void audition_region(boost::shared_ptr< Region >)
Definition: auditioner.cc:359
MonitorState monitoring_state() const
Definition: auditioner.cc:606
shared_ptr< T > dynamic_pointer_cast(shared_ptr< U > const &r)
Definition: shared_ptr.hpp:396
void output_changed(IOChange, void *)
Definition: auditioner.cc:550
bool commit(framecnt_t nframes)
virtual void clear(bool with_signals=true)
Definition: playlist.cc:1669
virtual ChanCount input_streams() const
Definition: auditioner.cc:588
uint32_t pframes_t
Definition: types.h:61
uint32_t n_audio() const
Definition: chan_count.h:63
Definition: Beats.hpp:239
LIBPBD_API Transmitter error
LIBPBD_API Transmitter warning
bool _active
Definition: route.h:510
int remove_processor(boost::shared_ptr< Processor >, ProcessorStreams *err=0, bool need_process_lock=true)
Definition: route.cc:1574
ProcessorList _processors
Definition: route.h:517
std::ostream & endmsg(std::ostream &ostr)
Definition: transmitter.h:71
boost::shared_ptr< AudioDiskstream > audio_diskstream() const
Definition: auditioner.cc:612
static AudioEngine * instance()
Definition: audioengine.h:196
void config_changed(std::string)
Definition: auditioner.cc:113
int process(BufferSet &, framepos_t transport_frame, pframes_t nframes, framecnt_t &, bool need_disk_signal)
void cancel_audition()
Definition: session.cc:4160
framepos_t current_frame
Definition: auditioner.h:111
void cancel_audition()
Definition: auditioner.h:59
#define MIDI_CTL_RESET_CONTROLLERS
Definition: midi_events.h:98
void get_physical_outputs(DataType type, std::vector< std::string > &)
#define _(Text)
Definition: i18n.h:11
DataType data_type() const
Definition: auditioner.cc:200
#define MIDI_CMD_CONTROL
Definition: midi_events.h:110
int add_processor(boost::shared_ptr< Processor >, Placement placement, ProcessorStreams *err=0, bool activation_allowed=true)
Definition: route.cc:1099
int64_t framecnt_t
Definition: types.h:76
LIBARDOUR_API RCConfiguration * Config
Definition: globals.cc:119
void set_position(framepos_t)
Definition: region.cc:579
boost::shared_ptr< IO > _output
Definition: route.h:508
void silence(framecnt_t)
Definition: route.cc:2894
enum ARDOUR::IOChange::Type type
framepos_t transport_frame() const
Definition: session.h:551
Definition: amp.h:29
MonitorState
Definition: types.h:393
#define MIDI_CTL_SUSTAIN
Definition: midi_events.h:65
ChanCount n_outputs() const
Definition: route.h:93
bool record_enabled() const
Definition: diskstream.h:106
frameoffset_t sync_offset(int &dir) const
Definition: region.cc:1041
boost::shared_ptr< Diskstream > _diskstream_audio
Definition: auditioner.h:124
int64_t framepos_t
Definition: types.h:66
int roll_midi(pframes_t nframes, framepos_t start_frame, framepos_t end_frame, int declick, bool &need_butler)
Definition: auditioner.cc:238
Glib::Threads::Mutex lock
Definition: auditioner.h:113
int configure_processors(ProcessorStreams *)
Definition: route.cc:1789
PBD::Signal1< void, std::string > ParameterChanged
Definition: configuration.h:44
framepos_t position() const
Definition: region.h:112
boost::shared_ptr< Diskstream > create_diskstream()
Definition: auditioner.cc:209
frameoffset_t _import_position
Definition: auditioner.h:134
BufferSet & get_route_buffers(ChanCount count=ChanCount::ZERO, bool silence=true)
Definition: session.cc:4857
bool transport_stopped() const
Definition: session.h:591
boost::shared_ptr< MidiDiskstream > midi_diskstream() const
Definition: auditioner.cc:618
uint32_t n_channels() const
Definition: region.h:259
TrackMode _mode
Definition: track.h:176
std::string name() const
const ChanCount & count() const
Definition: buffer_set.h:87
PluginPtr find_plugin(ARDOUR::Session &, std::string unique_id, ARDOUR::PluginType)
void set(DataType t, uint32_t count)
Definition: chan_count.h:58
void set_diskstream(boost::shared_ptr< Diskstream > ds)
Definition: auditioner.cc:325
Definition: debug.h:30
boost::shared_ptr< IO > input() const
Definition: route.h:89
ARDOUR::AudioPlaylist & prepare_playlist()
Definition: auditioner.cc:339
int init()
Definition: track.cc:57
virtual void process_output_buffers(BufferSet &bufs, framepos_t start_frame, framepos_t end_frame, pframes_t nframes, int declick, bool gain_automation_ok)
Definition: route.cc:457
int play_audition(framecnt_t nframes)
Definition: auditioner.cc:487
framecnt_t length() const
Definition: region.h:114
frameoffset_t _seek_frame
Definition: auditioner.h:115
Glib::Threads::RWLock _processor_lock
Definition: route.h:518
boost::shared_ptr< Diskstream > _diskstream
Definition: track.h:174
static boost::shared_ptr< Region > create(boost::shared_ptr< const Region > other, bool announce=false)
virtual void set_diskstream(boost::shared_ptr< Diskstream >)
Definition: track.cc:554
#define MIDI_CTL_ALL_NOTES_OFF
Definition: midi_events.h:100
int roll_audio(pframes_t nframes, framepos_t start_frame, framepos_t end_frame, int declick, bool &need_butler)
Definition: auditioner.cc:295
void get_playback(MidiBuffer &dst, framecnt_t)
int roll(pframes_t nframes, framepos_t start_frame, framepos_t end_frame, int declick, bool &need_butler)
Definition: auditioner.cc:229
boost::shared_ptr< Route > monitor_out() const
Definition: session.h:717
ChanCount n_process_buffers()
Definition: route.cc:714
AudioEngine & engine()
Definition: session.h:546
std::string string_compose(const std::string &fmt, const T1 &o1)
Definition: compose.h:208
LIBARDOUR_API PBD::PropertyDescriptor< framecnt_t > length
Definition: region.cc:64
PBD::Signal2< void, ARDOUR::framecnt_t, ARDOUR::framecnt_t > AuditionProgress
Definition: auditioner.h:74
boost::shared_ptr< MidiRegion > midi_region
Definition: auditioner.h:110