+ if (outbufs.count().n_audio() == 0) {
+ // Failing to deliver audio we were asked to deliver is a bug
+ assert(inbufs.count().n_audio() == 0);
+ return;
+ }
+
+ // We shouldn't be called in the first place...
+ assert(!bypassed());
+ assert(!empty());
+
+ // If we shouldn't play automation defer to distribute_no_automation
+ if (!(automation_state() & Play || ((automation_state() & Touch) && !touching()))) {
+
+ // Speed quietning
+ gain_t gain_coeff = 1.0;
+
+ if (fabsf(_session.transport_speed()) > 1.5f) {
+ gain_coeff = speed_quietning;
+ }
+
+ distribute_no_automation (inbufs, outbufs, nframes, gain_coeff);
+ return;
+ }
+
+ // Otherwise.. let the automation flow, baby
+
+ if (outbufs.count().n_audio() == 1) {
+
+ AudioBuffer& dst = outbufs.get_audio(0);
+
+ // FIXME: apply gain automation?
+
+ // copy the first
+ dst.read_from(inbufs.get_audio(0), nframes);
+
+ // accumulate starting with the second
+ BufferSet::audio_iterator i = inbufs.audio_begin();
+ for (++i; i != inbufs.audio_end(); ++i) {
+ dst.merge_from(*i, nframes);
+ }
+
+ return;
+ }
+
+ // More than 1 output, we should have 1 panner for each input
+ //assert(_streampanners.size() == inbufs.count().n_audio());
+
+ /* the terrible silence ... */
+ for (BufferSet::audio_iterator i = outbufs.audio_begin(); i != outbufs.audio_end(); ++i) {
+ i->silence(nframes);
+ }
+
+ BufferSet::audio_iterator i = inbufs.audio_begin();
+ for (vector<StreamPanner*>::iterator pan = _streampanners.begin(); pan != _streampanners.end(); ++pan, ++i) {
+ (*pan)->distribute_automated (*i, outbufs, start_frame, end_frame, nframes, _session.pan_automation_buffer());
+ }
+}
+
+/* old school automation handling */
+
+/*
+void
+Panner::set_name (string str)
+{
+ automation_path = Glib::build_filename(_session.automation_dir(),
+ _session.snap_name() + "-pan-" + legalize_for_path (str) + ".automation");
+}
+*/
+
+int
+Panner::load ()
+{
+ char line[128];
+ uint32_t linecnt = 0;
+ float version;
+ vector<StreamPanner*>::iterator sp;
+ LocaleGuard lg (X_("POSIX"));
+
+ if (automation_path.length() == 0) {
+ return 0;
+ }
+
+ if (access (automation_path.c_str(), F_OK)) {
+ return 0;
+ }
+
+ ifstream in (automation_path.c_str());
+
+ if (!in) {
+ error << string_compose (_("cannot open pan automation file %1 (%2)"),
+ automation_path, strerror (errno))
+ << endmsg;
+ return -1;
+ }
+
+ sp = _streampanners.begin();
+
+ while (in.getline (line, sizeof(line), '\n')) {
+
+ if (++linecnt == 1) {
+ if (memcmp (line, X_("version"), 7) == 0) {
+ if (sscanf (line, "version %f", &version) != 1) {
+ error << string_compose(_("badly formed version number in pan automation event file \"%1\""), automation_path) << endmsg;
+ return -1;
+ }
+ } else {
+ error << string_compose(_("no version information in pan automation event file \"%1\" (first line = %2)"),
+ automation_path, line) << endmsg;
+ return -1;
+ }
+
+ continue;
+ }
+
+ if (strlen (line) == 0 || line[0] == '#') {
+ continue;
+ }
+
+ if (strcmp (line, "begin") == 0) {
+
+ if (sp == _streampanners.end()) {
+ error << string_compose (_("too many panner states found in pan automation file %1"),
+ automation_path)
+ << endmsg;
+ return -1;
+ }
+
+ if ((*sp)->load (in, automation_path, linecnt)) {
+ return -1;
+ }
+
+ ++sp;