Merge branch 'master' into windows

This commit is contained in:
Paul Davis 2013-08-02 12:51:24 -04:00
commit aaabaf5d3c
38 changed files with 247 additions and 97 deletions

View file

@ -303,7 +303,12 @@ MidiTracer::tracer (Parser&, byte* msg, size_t len)
s += snprintf ( s += snprintf (
&buf[s], bufsize, " MTC full frame to %02d:%02d:%02d:%02d\n", msg[5] & 0x1f, msg[6], msg[7], msg[8] &buf[s], bufsize, " MTC full frame to %02d:%02d:%02d:%02d\n", msg[5] & 0x1f, msg[6], msg[7], msg[8]
); );
} else if (len == 3 && msg[0] == MIDI::position) {
/* MIDI Song Position */
uint16_t midi_beats = (uint16_t) msg[1];
midi_beats |= msg[2];
s += snprintf (&buf[s], bufsize, "%16s %d\n", "Position", (int) midi_beats);
} else { } else {
/* other sys-ex */ /* other sys-ex */

View file

@ -152,6 +152,7 @@ PortMatrix::init ()
/* and also bundles */ /* and also bundles */
_session->BundleAdded.connect (_session_connections, invalidator (*this), boost::bind (&PortMatrix::setup_global_ports, this), gui_context()); _session->BundleAdded.connect (_session_connections, invalidator (*this), boost::bind (&PortMatrix::setup_global_ports, this), gui_context());
_session->BundleRemoved.connect (_session_connections, invalidator (*this), boost::bind (&PortMatrix::setup_global_ports, this), gui_context());
/* and also ports */ /* and also ports */
_session->engine().PortRegisteredOrUnregistered.connect (_session_connections, invalidator (*this), boost::bind (&PortMatrix::setup_global_ports, this), gui_context()); _session->engine().PortRegisteredOrUnregistered.connect (_session_connections, invalidator (*this), boost::bind (&PortMatrix::setup_global_ports, this), gui_context());
@ -180,6 +181,7 @@ PortMatrix::reconnect_to_routes ()
boost::shared_ptr<RouteList> routes = _session->get_routes (); boost::shared_ptr<RouteList> routes = _session->get_routes ();
for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) { for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
(*i)->processors_changed.connect (_route_connections, invalidator (*this), boost::bind (&PortMatrix::route_processors_changed, this, _1), gui_context()); (*i)->processors_changed.connect (_route_connections, invalidator (*this), boost::bind (&PortMatrix::route_processors_changed, this, _1), gui_context());
(*i)->DropReferences.connect (_route_connections, invalidator (*this), boost::bind (&PortMatrix::routes_changed, this), gui_context());
} }
} }
@ -198,6 +200,7 @@ PortMatrix::route_processors_changed (RouteProcessorChange c)
void void
PortMatrix::routes_changed () PortMatrix::routes_changed ()
{ {
if (!_session) return;
reconnect_to_routes (); reconnect_to_routes ();
setup_global_ports (); setup_global_ports ();
} }
@ -206,7 +209,10 @@ PortMatrix::routes_changed ()
void void
PortMatrix::setup () PortMatrix::setup ()
{ {
if (!_session) return; // session went away if (!_session) {
_route_connections.drop_connections ();
return; // session went away
}
/* this needs to be done first, as the visible_ports() method uses the /* this needs to be done first, as the visible_ports() method uses the
notebook state to decide which ports are being shown */ notebook state to decide which ports are being shown */

View file

@ -61,7 +61,7 @@ Amp::display_name() const
} }
bool bool
Amp::can_support_io_configuration (const ChanCount& in, ChanCount& out) const Amp::can_support_io_configuration (const ChanCount& in, ChanCount& out)
{ {
out = in; out = in;
return true; return true;

View file

@ -40,7 +40,7 @@ public:
bool visible () const; bool visible () const;
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const; bool can_support_io_configuration (const ChanCount& in, ChanCount& out);
bool configure_io (ChanCount in, ChanCount out); bool configure_io (ChanCount in, ChanCount out);
void run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pframes_t nframes, bool); void run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pframes_t nframes, bool);

View file

@ -104,7 +104,7 @@ class AUPlugin : public ARDOUR::Plugin
bool has_editor () const; bool has_editor () const;
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const; bool can_support_io_configuration (const ChanCount& in, ChanCount& out);
ChanCount output_streams() const; ChanCount output_streams() const;
ChanCount input_streams() const; ChanCount input_streams() const;
bool configure_io (ChanCount in, ChanCount out); bool configure_io (ChanCount in, ChanCount out);

View file

@ -38,7 +38,7 @@ class CapturingProcessor : public Processor
int set_block_size (pframes_t nframes); int set_block_size (pframes_t nframes);
void run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pframes_t nframes, bool result_required); void run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pframes_t nframes, bool result_required);
bool configure_io (ChanCount in, ChanCount out); bool configure_io (ChanCount in, ChanCount out);
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const; bool can_support_io_configuration (const ChanCount& in, ChanCount& out);
virtual XMLNode& state (bool); virtual XMLNode& state (bool);
private: private:

View file

@ -67,7 +67,7 @@ public:
std::string display_name() const; std::string display_name() const;
Role role() const { return _role; } Role role() const { return _role; }
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const; bool can_support_io_configuration (const ChanCount& in, ChanCount& out);
bool configure_io (ChanCount in, ChanCount out); bool configure_io (ChanCount in, ChanCount out);
void run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pframes_t nframes, bool); void run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pframes_t nframes, bool);

View file

@ -39,7 +39,7 @@ class InternalReturn : public Return
void run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pframes_t nframes, bool); void run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pframes_t nframes, bool);
bool configure_io (ChanCount, ChanCount); bool configure_io (ChanCount, ChanCount);
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const; bool can_support_io_configuration (const ChanCount& in, ChanCount& out);
void add_send (InternalSend *); void add_send (InternalSend *);
void remove_send (InternalSend *); void remove_send (InternalSend *);

View file

@ -42,7 +42,7 @@ class InternalSend : public Send
void cycle_start (pframes_t); void cycle_start (pframes_t);
void run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pframes_t nframes, bool); void run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pframes_t nframes, bool);
bool feeds (boost::shared_ptr<Route> other) const; bool feeds (boost::shared_ptr<Route> other) const;
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const; bool can_support_io_configuration (const ChanCount& in, ChanCount& out);
bool configure_io (ChanCount in, ChanCount out); bool configure_io (ChanCount in, ChanCount out);
int set_block_size (pframes_t); int set_block_size (pframes_t);

View file

@ -56,7 +56,7 @@ public:
void reset (); void reset ();
void reset_max (); void reset_max ();
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const; bool can_support_io_configuration (const ChanCount& in, ChanCount& out);
bool configure_io (ChanCount in, ChanCount out); bool configure_io (ChanCount in, ChanCount out);
/* special method for meter, to ensure that it can always handle the maximum /* special method for meter, to ensure that it can always handle the maximum

View file

@ -118,7 +118,7 @@ public:
int set_state (const XMLNode&, int /* version */); int set_state (const XMLNode&, int /* version */);
bool configure_io (ChanCount in, ChanCount out); bool configure_io (ChanCount in, ChanCount out);
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const; bool can_support_io_configuration (const ChanCount& in, ChanCount& out);
void set_cut_all (bool); void set_cut_all (bool);
void set_dim_all (bool); void set_dim_all (bool);

View file

@ -53,7 +53,7 @@ public:
std::string describe_parameter (Evoral::Parameter param); std::string describe_parameter (Evoral::Parameter param);
bool can_support_io_configuration (const ChanCount& /*in*/, ChanCount& /*out*/) const { return true; }; bool can_support_io_configuration (const ChanCount& /*in*/, ChanCount& /*out*/) { return true; };
void configure_io (ChanCount in, ChanCount out); void configure_io (ChanCount in, ChanCount out);
/// The fundamental Panner function /// The fundamental Panner function

View file

@ -242,7 +242,7 @@ class Plugin : public PBD::StatefulDestructible, public Latent
/* specific types of plugins can overload this. As of September 2008, only /* specific types of plugins can overload this. As of September 2008, only
AUPlugin does this. AUPlugin does this.
*/ */
virtual bool can_support_io_configuration (const ChanCount& /*in*/, ChanCount& /*out*/) const { return false; } virtual bool can_support_io_configuration (const ChanCount& /*in*/, ChanCount& /*out*/) { return false; }
virtual ChanCount output_streams() const; virtual ChanCount output_streams() const;
virtual ChanCount input_streams() const; virtual ChanCount input_streams() const;

View file

@ -69,7 +69,7 @@ class PluginInsert : public Processor
bool set_count (uint32_t num); bool set_count (uint32_t num);
uint32_t get_count () const { return _plugins.size(); } uint32_t get_count () const { return _plugins.size(); }
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const; bool can_support_io_configuration (const ChanCount& in, ChanCount& out);
bool configure_io (ChanCount in, ChanCount out); bool configure_io (ChanCount in, ChanCount out);
bool has_no_inputs() const; bool has_no_inputs() const;
@ -160,6 +160,8 @@ class PluginInsert : public Processor
BufferSet _signal_analysis_inputs; BufferSet _signal_analysis_inputs;
BufferSet _signal_analysis_outputs; BufferSet _signal_analysis_outputs;
ChanCount midi_bypass;
/** Description of how we can match our plugin's IO to our own insert IO */ /** Description of how we can match our plugin's IO to our own insert IO */
struct Match { struct Match {
Match () : method (Impossible), plugins (0) {} Match () : method (Impossible), plugins (0) {}
@ -170,7 +172,7 @@ class PluginInsert : public Processor
ChanCount hide; ///< number of channels to hide ChanCount hide; ///< number of channels to hide
}; };
Match private_can_support_io_configuration (ChanCount const &, ChanCount &) const; Match private_can_support_io_configuration (ChanCount const &, ChanCount &);
/** details of the match currently being used */ /** details of the match currently being used */
Match _match; Match _match;

View file

@ -57,7 +57,7 @@ class PortInsert : public IOProcessor
bool set_name (const std::string& name); bool set_name (const std::string& name);
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const; bool can_support_io_configuration (const ChanCount& in, ChanCount& out);
bool configure_io (ChanCount in, ChanCount out); bool configure_io (ChanCount in, ChanCount out);
void activate (); void activate ();

View file

@ -82,7 +82,7 @@ class Processor : public SessionObject, public Automatable, public Latent
/* Derived classes should override these, or processor appears as an in-place pass-through */ /* Derived classes should override these, or processor appears as an in-place pass-through */
virtual bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const = 0; virtual bool can_support_io_configuration (const ChanCount& in, ChanCount& out) = 0;
virtual ChanCount input_streams () const { return _configured_input; } virtual ChanCount input_streams () const { return _configured_input; }
virtual ChanCount output_streams() const { return _configured_output; } virtual ChanCount output_streams() const { return _configured_output; }

View file

@ -56,7 +56,7 @@ public:
uint32_t pans_required() const { return _configured_input.n_audio(); } uint32_t pans_required() const { return _configured_input.n_audio(); }
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const; bool can_support_io_configuration (const ChanCount& in, ChanCount& out);
bool configure_io (ChanCount in, ChanCount out); bool configure_io (ChanCount in, ChanCount out);
static uint32_t how_many_returns(); static uint32_t how_many_returns();

View file

@ -56,7 +56,7 @@ class Send : public Delivery
void run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pframes_t nframes, bool); void run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pframes_t nframes, bool);
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const; bool can_support_io_configuration (const ChanCount& in, ChanCount& out);
bool configure_io (ChanCount in, ChanCount out); bool configure_io (ChanCount in, ChanCount out);
void activate (); void activate ();

View file

@ -19,6 +19,7 @@
*/ */
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
#include <boost/scoped_ptr.hpp>
#include "pbd/signals.h" #include "pbd/signals.h"
@ -42,7 +43,7 @@ class MidiClockTicker : public SessionHandlePtr, boost::noncopyable
{ {
public: public:
MidiClockTicker (); MidiClockTicker ();
virtual ~MidiClockTicker() {} virtual ~MidiClockTicker();
void tick (const framepos_t& transport_frames); void tick (const framepos_t& transport_frames);
@ -63,6 +64,9 @@ public:
/// slot for the signal session::TransportLooped /// slot for the signal session::TransportLooped
void transport_looped(); void transport_looped();
/// slot for the signal session::Located
void session_located();
/// pulses per quarter note (default 24) /// pulses per quarter note (default 24)
void set_ppqn(int ppqn) { _ppqn = ppqn; } void set_ppqn(int ppqn) { _ppqn = ppqn; }
@ -71,13 +75,16 @@ private:
int _ppqn; int _ppqn;
double _last_tick; double _last_tick;
class Position;
boost::scoped_ptr<Position> _pos;
double one_ppqn_in_frames (framepos_t transport_position); double one_ppqn_in_frames (framepos_t transport_position);
void send_midi_clock_event (pframes_t offset); void send_midi_clock_event (pframes_t offset);
void send_start_event (pframes_t offset); void send_start_event (pframes_t offset);
void send_continue_event (pframes_t offset); void send_continue_event (pframes_t offset);
void send_stop_event (pframes_t offset); void send_stop_event (pframes_t offset);
void send_position_event (framepos_t transport_position, pframes_t offset); void send_position_event (uint32_t midi_clocks, pframes_t offset);
}; };
} }

View file

@ -49,7 +49,7 @@ public:
return false; return false;
} }
bool can_support_io_configuration (const ChanCount &, ChanCount &) const { bool can_support_io_configuration (const ChanCount &, ChanCount &) {
return false; return false;
} }

View file

@ -998,7 +998,7 @@ AUPlugin::output_streams() const
} }
bool bool
AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out) const AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out)
{ {
// Note: We never attempt to multiply-instantiate plugins to meet io configurations. // Note: We never attempt to multiply-instantiate plugins to meet io configurations.

View file

@ -62,7 +62,7 @@ CapturingProcessor::configure_io (ChanCount in, ChanCount out)
} }
bool bool
CapturingProcessor::can_support_io_configuration (const ChanCount& in, ChanCount& out) const CapturingProcessor::can_support_io_configuration (const ChanCount& in, ChanCount& out)
{ {
out = in; out = in;
return true; return true;

View file

@ -124,7 +124,7 @@ Delivery::display_name () const
} }
bool bool
Delivery::can_support_io_configuration (const ChanCount& in, ChanCount& out) const Delivery::can_support_io_configuration (const ChanCount& in, ChanCount& out)
{ {
if (_role == Main) { if (_role == Main) {

View file

@ -80,7 +80,7 @@ InternalReturn::get_state()
} }
bool bool
InternalReturn::can_support_io_configuration (const ChanCount& in, ChanCount& out) const InternalReturn::can_support_io_configuration (const ChanCount& in, ChanCount& out)
{ {
out = in; out = in;
return true; return true;

View file

@ -284,7 +284,7 @@ InternalSend::connect_when_legal ()
} }
bool bool
InternalSend::can_support_io_configuration (const ChanCount& in, ChanCount& out) const InternalSend::can_support_io_configuration (const ChanCount& in, ChanCount& out)
{ {
out = in; out = in;
return true; return true;

View file

@ -971,7 +971,7 @@ LV2Plugin::find_presets()
lilv_node_as_string(name)))); lilv_node_as_string(name))));
} else { } else {
warning << string_compose( warning << string_compose(
_("Plugin \"%1\% preset \"%2%\" is missing a label\n"), _("Plugin \"%1\" preset \"%2\" is missing a label\n"),
lilv_node_as_string(lilv_plugin_get_uri(_impl->plugin)), lilv_node_as_string(lilv_plugin_get_uri(_impl->plugin)),
lilv_node_as_string(preset)) << endmsg; lilv_node_as_string(preset)) << endmsg;
} }

View file

@ -165,7 +165,7 @@ PeakMeter::reset_max ()
} }
bool bool
PeakMeter::can_support_io_configuration (const ChanCount& in, ChanCount& out) const PeakMeter::can_support_io_configuration (const ChanCount& in, ChanCount& out)
{ {
out = in; out = in;
return true; return true;

View file

@ -355,7 +355,7 @@ MonitorProcessor::configure_io (ChanCount in, ChanCount out)
} }
bool bool
MonitorProcessor::can_support_io_configuration (const ChanCount& in, ChanCount& out) const MonitorProcessor::can_support_io_configuration (const ChanCount& in, ChanCount& out)
{ {
out = in; out = in;
return true; return true;

View file

@ -145,7 +145,7 @@ PluginInsert::output_streams() const
ChanCount out = info->n_outputs; ChanCount out = info->n_outputs;
// DEBUG_TRACE (DEBUG::Processors, string_compose ("Plugin insert, static output streams = %1 for %2 plugins\n", out, _plugins.size())); // DEBUG_TRACE (DEBUG::Processors, string_compose ("Plugin insert, static output streams = %1 for %2 plugins\n", out, _plugins.size()));
out.set_audio (out.n_audio() * _plugins.size()); out.set_audio (out.n_audio() * _plugins.size());
out.set_midi (out.n_midi() * _plugins.size()); out.set_midi (out.n_midi() * _plugins.size() + midi_bypass.n_midi());
return out; return out;
} }
} }
@ -465,7 +465,6 @@ PluginInsert::run (BufferSet& bufs, framepos_t /*start_frame*/, framepos_t /*end
} }
} else { } else {
if (has_no_audio_inputs()) { if (has_no_audio_inputs()) {
/* silence all (audio) outputs. Should really declick /* silence all (audio) outputs. Should really declick
@ -704,7 +703,7 @@ PluginInsert::configure_io (ChanCount in, ChanCount out)
* @return true if the given IO configuration can be supported. * @return true if the given IO configuration can be supported.
*/ */
bool bool
PluginInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out) const PluginInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out)
{ {
return private_can_support_io_configuration (in, out).method != Impossible; return private_can_support_io_configuration (in, out).method != Impossible;
} }
@ -714,9 +713,11 @@ PluginInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out)
* it can be. * it can be.
*/ */
PluginInsert::Match PluginInsert::Match
PluginInsert::private_can_support_io_configuration (ChanCount const & in, ChanCount& out) const PluginInsert::private_can_support_io_configuration (ChanCount const & inx, ChanCount& out)
{ {
PluginInfoPtr info = _plugins.front()->get_info(); PluginInfoPtr info = _plugins.front()->get_info();
ChanCount in; in += inx;
midi_bypass.reset();
if (info->reconfigurable_io()) { if (info->reconfigurable_io()) {
/* Plugin has flexible I/O, so delegate to it */ /* Plugin has flexible I/O, so delegate to it */
@ -731,6 +732,15 @@ PluginInsert::private_can_support_io_configuration (ChanCount const & in, ChanCo
ChanCount inputs = info->n_inputs; ChanCount inputs = info->n_inputs;
ChanCount outputs = info->n_outputs; ChanCount outputs = info->n_outputs;
if (in.get(DataType::MIDI) == 1 && outputs.get(DataType::MIDI) == 0) {
DEBUG_TRACE ( DEBUG::Processors, string_compose ("bypassing midi-data around %1\n", name()));
midi_bypass.set(DataType::MIDI, 1);
}
if (in.get(DataType::MIDI) == 1 && inputs.get(DataType::MIDI) == 0) {
DEBUG_TRACE ( DEBUG::Processors, string_compose ("hiding midi-port from plugin %1\n", name()));
in.set(DataType::MIDI, 0);
}
bool no_inputs = true; bool no_inputs = true;
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
if (inputs.get (*t) != 0) { if (inputs.get (*t) != 0) {
@ -741,13 +751,13 @@ PluginInsert::private_can_support_io_configuration (ChanCount const & in, ChanCo
if (no_inputs) { if (no_inputs) {
/* no inputs so we can take any input configuration since we throw it away */ /* no inputs so we can take any input configuration since we throw it away */
out = outputs; out = outputs + midi_bypass;
return Match (NoInputs, 1); return Match (NoInputs, 1);
} }
/* Plugin inputs match requested inputs exactly */ /* Plugin inputs match requested inputs exactly */
if (inputs == in) { if (inputs == in) {
out = outputs; out = outputs + midi_bypass;
return Match (ExactMatch, 1); return Match (ExactMatch, 1);
} }
@ -789,6 +799,7 @@ PluginInsert::private_can_support_io_configuration (ChanCount const & in, ChanCo
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
out.set (*t, outputs.get(*t) * f); out.set (*t, outputs.get(*t) * f);
} }
out += midi_bypass;
return Match (Replicate, f); return Match (Replicate, f);
} }
@ -812,7 +823,7 @@ PluginInsert::private_can_support_io_configuration (ChanCount const & in, ChanCo
} }
if (can_split) { if (can_split) {
out = outputs; out = outputs + midi_bypass;
return Match (Split, 1); return Match (Split, 1);
} }
@ -836,10 +847,11 @@ PluginInsert::private_can_support_io_configuration (ChanCount const & in, ChanCo
} }
if (could_hide && !cannot_hide) { if (could_hide && !cannot_hide) {
out = outputs; out = outputs + midi_bypass;
return Match (Hide, 1, hide_channels); return Match (Hide, 1, hide_channels);
} }
midi_bypass.reset();
return Match (Impossible, 0); return Match (Impossible, 0);
} }

View file

@ -268,7 +268,7 @@ PortInsert::configure_io (ChanCount in, ChanCount out)
} }
bool bool
PortInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out) const PortInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out)
{ {
out = in; out = in;
return true; return true;

View file

@ -136,7 +136,7 @@ Return::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pfra
} }
bool bool
Return::can_support_io_configuration (const ChanCount& in, ChanCount& out) const Return::can_support_io_configuration (const ChanCount& in, ChanCount& out)
{ {
out = in + _input->n_ports(); out = in + _input->n_ports();
return true; return true;

View file

@ -543,11 +543,10 @@ Route::process_output_buffers (BufferSet& bufs,
if (bufs.count() != (*i)->input_streams()) { if (bufs.count() != (*i)->input_streams()) {
DEBUG_TRACE ( DEBUG_TRACE (
DEBUG::Processors, string_compose ( DEBUG::Processors, string_compose (
"%1 bufs = %2 input for %3 = %4\n", "input port mismatch %1 bufs = %2 input for %3 = %4\n",
_name, bufs.count(), (*i)->name(), (*i)->input_streams() _name, bufs.count(), (*i)->name(), (*i)->input_streams()
) )
); );
continue;
} }
} }
#endif #endif
@ -1656,7 +1655,8 @@ Route::try_configure_processors_unlocked (ChanCount in, ProcessorStreams* err)
if (boost::dynamic_pointer_cast<UnknownProcessor> (*p)) { if (boost::dynamic_pointer_cast<UnknownProcessor> (*p)) {
DEBUG_TRACE (DEBUG::Processors, "--- CONFIGURE ABORTED due to unknown processor.\n"); DEBUG_TRACE (DEBUG::Processors, "--- CONFIGURE ABORTED due to unknown processor.\n");
break; DEBUG_TRACE (DEBUG::Processors, "}\n");
return list<pair<ChanCount, ChanCount> > ();
} }
if ((*p)->can_support_io_configuration(in, out)) { if ((*p)->can_support_io_configuration(in, out)) {

View file

@ -270,7 +270,7 @@ Send::set_state_2X (const XMLNode& node, int /* version */)
} }
bool bool
Send::can_support_io_configuration (const ChanCount& in, ChanCount& out) const Send::can_support_io_configuration (const ChanCount& in, ChanCount& out)
{ {
/* sends have no impact at all on the channel configuration of the /* sends have no impact at all on the channel configuration of the
streams passing through the route. so, out == in. streams passing through the route. so, out == in.

View file

@ -590,7 +590,7 @@ void
Session::send_song_position_pointer (framepos_t t) Session::send_song_position_pointer (framepos_t t)
{ {
if (midi_clock) { if (midi_clock) {
midi_clock->position_changed (t); /* Do nothing for the moment */
} }
} }

View file

@ -384,6 +384,7 @@ Session::butler_transport_work ()
g_atomic_int_dec_and_test (&_butler->should_do_transport_work); g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
DEBUG_TRACE (DEBUG::Transport, X_("Butler transport work all done\n")); DEBUG_TRACE (DEBUG::Transport, X_("Butler transport work all done\n"));
DEBUG_TRACE (DEBUG::Transport, X_(string_compose ("Frame %1\n", _transport_frame)));
} }
void void
@ -1007,6 +1008,7 @@ Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool
send_mmc_locate (_transport_frame); send_mmc_locate (_transport_frame);
} }
_last_roll_location = _last_roll_or_reversal_location = _transport_frame;
Located (); /* EMIT SIGNAL */ Located (); /* EMIT SIGNAL */
} }

View file

@ -32,12 +32,80 @@
#include "ardour/debug.h" #include "ardour/debug.h"
using namespace ARDOUR; using namespace ARDOUR;
using namespace PBD;
/** MIDI Clock Position tracking */
class MidiClockTicker::Position : public Timecode::BBT_Time
{
public:
Position() : speed(0.0f), frame(0) { }
~Position() { }
/** Sync timing information taken from the given Session
@return True if timings differed */
bool sync (Session* s) {
bool didit = false;
double sp = s->transport_speed();
framecnt_t fr = s->transport_frame();
if (speed != sp) {
speed = sp;
didit = true;
}
if (frame != fr) {
frame = fr;
didit = true;
}
/* Midi beats and clocks always gets updated for now */
s->bbt_time (this->frame, *this);
const TempoMap& tempo = s->tempo_map();
const double divisions = tempo.meter_at(frame).divisions_per_bar();
const double divisor = tempo.meter_at(frame).note_divisor();
const double qnote_scale = divisor * 0.25f;
/** Midi Beats in terms of Song Position Pointer is equivalent to total
sixteenth notes at 'time' */
midi_beats = (((bars - 1) * divisions) + beats - 1);
midi_beats += (double)ticks / (double)Position::ticks_per_beat * qnote_scale;
midi_beats *= 16.0f / divisor;
midi_clocks = midi_beats * 6.0f;
return didit;
}
double speed;
framecnt_t frame;
double midi_beats;
double midi_clocks;
void print (std::ostream& s) {
s << "frames: " << frame << " midi beats: " << midi_beats << " speed: " << speed;
}
};
MidiClockTicker::MidiClockTicker () MidiClockTicker::MidiClockTicker ()
: _midi_port (0) : _midi_port (0)
, _ppqn (24) , _ppqn (24)
, _last_tick (0.0) , _last_tick (0.0)
{ {
_pos.reset (new Position());
}
MidiClockTicker::~MidiClockTicker()
{
_midi_port = 0;
_pos.reset (0);
} }
void void
@ -49,10 +117,52 @@ MidiClockTicker::set_session (Session* s)
_session->TransportStateChange.connect_same_thread (_session_connections, boost::bind (&MidiClockTicker::transport_state_changed, this)); _session->TransportStateChange.connect_same_thread (_session_connections, boost::bind (&MidiClockTicker::transport_state_changed, this));
_session->PositionChanged.connect_same_thread (_session_connections, boost::bind (&MidiClockTicker::position_changed, this, _1)); _session->PositionChanged.connect_same_thread (_session_connections, boost::bind (&MidiClockTicker::position_changed, this, _1));
_session->TransportLooped.connect_same_thread (_session_connections, boost::bind (&MidiClockTicker::transport_looped, this)); _session->TransportLooped.connect_same_thread (_session_connections, boost::bind (&MidiClockTicker::transport_looped, this));
_session->Located.connect_same_thread (_session_connections, boost::bind (&MidiClockTicker::session_located, this));
update_midi_clock_port(); update_midi_clock_port();
_pos->sync (_session);
} }
} }
void
MidiClockTicker::session_located()
{
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Session Located: %1, speed: %2\n", _session->transport_frame(), _session->transport_speed()));
if (0 == _session || ! _pos->sync (_session)) {
return;
}
_last_tick = _pos->frame;
if (!Config->get_send_midi_clock()) {
return;
}
if (_pos->speed == 0.0f) {
uint32_t where = llrint (_pos->midi_beats);
send_position_event (where, 0);
} else if (_pos->speed == 1.0f) {
#if 1
/* Experimental. To really do this and have accuracy, the
stop/locate/continue sequence would need queued to send immediately
before the next midi clock. */
send_stop_event (0);
if (_pos->frame == 0) {
send_start_event (0);
} else {
uint32_t where = llrint (_pos->midi_beats);
send_position_event (where, 0);
send_continue_event (0);
}
#endif
} else {
/* Varispeed not supported */
}
}
void void
MidiClockTicker::session_going_away () MidiClockTicker::session_going_away ()
{ {
@ -79,56 +189,61 @@ MidiClockTicker::transport_state_changed()
return; return;
} }
float speed = _session->transport_speed(); if (! _pos->sync (_session)) {
framepos_t position = _session->transport_frame(); return;
}
DEBUG_TRACE (PBD::DEBUG::MidiClock, DEBUG_TRACE (DEBUG::MidiClock,
string_compose ("Transport state change @ %4, speed: %1 position: %2 play loop: %3\n", speed, position, _session->get_play_loop(), position) string_compose ("Transport state change @ %4, speed: %1 position: %2 play loop: %3\n",
_pos->speed, _pos->frame, _session->get_play_loop(), _pos->frame)
); );
if (speed == 1.0f) { _last_tick = _pos->frame;
_last_tick = position;
if (!Config->get_send_midi_clock()) if (! Config->get_send_midi_clock()) {
return; return;
}
if (_pos->speed == 1.0f) {
if (_session->get_play_loop()) { if (_session->get_play_loop()) {
assert(_session->locations()->auto_loop_location()); assert(_session->locations()->auto_loop_location());
if (position == _session->locations()->auto_loop_location()->start()) {
if (_pos->frame == _session->locations()->auto_loop_location()->start()) {
send_start_event(0); send_start_event(0);
} else { } else {
send_continue_event(0); send_continue_event(0);
} }
} else if (position == 0) {
} else if (_pos->frame == 0) {
send_start_event(0); send_start_event(0);
} else { } else {
send_continue_event(0); send_continue_event(0);
} }
send_midi_clock_event(0); // send_midi_clock_event (0);
} else if (speed == 0.0f) { } else if (_pos->speed == 0.0f) {
if (!Config->get_send_midi_clock()) send_stop_event (0);
return; send_position_event (llrint (_pos->midi_beats), 0);
send_stop_event(0);
send_position_event (position, 0);
} }
tick (position); // tick (_pos->frame);
} }
void void
MidiClockTicker::position_changed (framepos_t position) MidiClockTicker::position_changed (framepos_t)
{ {
#if 0
const double speed = _session->transport_speed(); const double speed = _session->transport_speed();
DEBUG_TRACE (PBD::DEBUG::MidiClock, string_compose ("Transport Position Change: %1, speed: %2\n", position, speed)); DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Transport Position Change: %1, speed: %2\n", position, speed));
if (speed == 0.0f && Config->get_send_midi_clock()) { if (speed == 0.0f && Config->get_send_midi_clock()) {
send_position_event (position, 0); send_position_event (position, 0);
} }
_last_tick = position; _last_tick = position;
#endif
} }
void void
@ -137,7 +252,7 @@ MidiClockTicker::transport_looped()
Location* loop_location = _session->locations()->auto_loop_location(); Location* loop_location = _session->locations()->auto_loop_location();
assert(loop_location); assert(loop_location);
DEBUG_TRACE (PBD::DEBUG::MidiClock, DEBUG_TRACE (DEBUG::MidiClock,
string_compose ("Transport looped, position: %1, loop start: %2, loop end: %3, play loop: %4\n", string_compose ("Transport looped, position: %1, loop start: %2, loop end: %3, play loop: %4\n",
_session->transport_frame(), loop_location->start(), loop_location->end(), _session->get_play_loop()) _session->transport_frame(), loop_location->start(), loop_location->end(), _session->get_play_loop())
); );
@ -155,23 +270,28 @@ MidiClockTicker::transport_looped()
} }
void void
MidiClockTicker::tick (const framepos_t& transport_frame) MidiClockTicker::tick (const framepos_t& /* transport_frame */)
{ {
if (!Config->get_send_midi_clock() || _session == 0 || _session->transport_speed() != 1.0f || _midi_port == 0) { if (!Config->get_send_midi_clock() || _session == 0 || _session->transport_speed() != 1.0f || _midi_port == 0) {
return; return;
} }
while (true) { MIDI::JackMIDIPort* mp = dynamic_cast<MIDI::JackMIDIPort*> (_midi_port);
double next_tick = _last_tick + one_ppqn_in_frames (transport_frame); if (! mp) {
frameoffset_t next_tick_offset = llrint (next_tick) - transport_frame; return;
}
MIDI::JackMIDIPort* mp = dynamic_cast<MIDI::JackMIDIPort*> (_midi_port); const framepos_t end = _pos->frame + mp->nframes_this_cycle();
double iter = _last_tick;
/*
DEBUG_TRACE (PBD::DEBUG::MidiClock, while (true) {
string_compose ("Transport: %1, last tick time: %2, next tick time: %3, offset: %4, cycle length: %5\n", double clock_delta = one_ppqn_in_frames (llrint (iter));
transport_frame, _last_tick, next_tick, next_tick_offset, mp ? mp->nframes_this_cycle() : 0)); double next_tick = iter + clock_delta;
*/ frameoffset_t next_tick_offset = llrint (next_tick) - end;
DEBUG_TRACE (DEBUG::MidiClock,
string_compose ("Tick: iter: %1, last tick time: %2, next tick time: %3, offset: %4, cycle length: %5\n",
iter, _last_tick, next_tick, next_tick_offset, mp ? mp->nframes_this_cycle() : 0));
if (!mp || (next_tick_offset >= mp->nframes_this_cycle())) { if (!mp || (next_tick_offset >= mp->nframes_this_cycle())) {
break; break;
@ -181,10 +301,14 @@ MidiClockTicker::tick (const framepos_t& transport_frame)
send_midi_clock_event (next_tick_offset); send_midi_clock_event (next_tick_offset);
} }
_last_tick = next_tick; iter = next_tick;
} }
_last_tick = iter;
_pos->frame = end;
} }
double double
MidiClockTicker::one_ppqn_in_frames (framepos_t transport_position) MidiClockTicker::one_ppqn_in_frames (framepos_t transport_position)
{ {
@ -204,7 +328,7 @@ MidiClockTicker::send_midi_clock_event (pframes_t offset)
return; return;
} }
// DEBUG_TRACE (PBD::DEBUG::MidiClock, string_compose ("Tick with offset %1\n", offset)); DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Tick with offset %1\n", offset));
static uint8_t _midi_clock_tick[1] = { MIDI_CMD_COMMON_CLOCK }; static uint8_t _midi_clock_tick[1] = { MIDI_CMD_COMMON_CLOCK };
_midi_port->write (_midi_clock_tick, 1, offset); _midi_port->write (_midi_clock_tick, 1, offset);
@ -217,7 +341,7 @@ MidiClockTicker::send_start_event (pframes_t offset)
return; return;
} }
DEBUG_TRACE (PBD::DEBUG::MidiClock, string_compose ("Start %1\n", _last_tick)); DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Start %1\n", _last_tick));
static uint8_t _midi_clock_tick[1] = { MIDI_CMD_COMMON_START }; static uint8_t _midi_clock_tick[1] = { MIDI_CMD_COMMON_START };
_midi_port->write (_midi_clock_tick, 1, offset); _midi_port->write (_midi_clock_tick, 1, offset);
@ -230,7 +354,7 @@ MidiClockTicker::send_continue_event (pframes_t offset)
return; return;
} }
DEBUG_TRACE (PBD::DEBUG::MidiClock, string_compose ("Continue %1\n", _last_tick)); DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Continue %1\n", _last_tick));
static uint8_t _midi_clock_tick[1] = { MIDI_CMD_COMMON_CONTINUE }; static uint8_t _midi_clock_tick[1] = { MIDI_CMD_COMMON_CONTINUE };
_midi_port->write (_midi_clock_tick, 1, offset); _midi_port->write (_midi_clock_tick, 1, offset);
@ -243,29 +367,19 @@ MidiClockTicker::send_stop_event (pframes_t offset)
return; return;
} }
DEBUG_TRACE (PBD::DEBUG::MidiClock, string_compose ("Stop %1\n", _last_tick)); DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Stop %1\n", _last_tick));
static uint8_t _midi_clock_tick[1] = { MIDI_CMD_COMMON_STOP }; static uint8_t _midi_clock_tick[1] = { MIDI_CMD_COMMON_STOP };
_midi_port->write (_midi_clock_tick, 1, offset); _midi_port->write (_midi_clock_tick, 1, offset);
} }
void void
MidiClockTicker::send_position_event (framepos_t transport_position, pframes_t offset) MidiClockTicker::send_position_event (uint32_t midi_beats, pframes_t offset)
{ {
if (_midi_port == 0 || _session == 0 || _session->engine().freewheeling()) { if (!_midi_port) {
return; return;
} }
const TempoMap& tempo = _session->tempo_map();
Timecode::BBT_Time time;
_session->bbt_time (transport_position, time);
const double beats_per_bar = tempo.meter_at(transport_position).divisions_per_bar();
/* Midi Beats in terms of Song Position Pointer is equivalent to total
sixteenth notes at 'time' */
const uint32_t midi_beats = 4 * (((time.bars - 1) * beats_per_bar) + time.beats - 1);
/* can only use 14bits worth */ /* can only use 14bits worth */
if (midi_beats > 0x3fff) { if (midi_beats > 0x3fff) {
return; return;
@ -278,7 +392,7 @@ MidiClockTicker::send_position_event (framepos_t transport_position, pframes_t o
midi_beats & 0x3f80 midi_beats & 0x3f80
}; };
DEBUG_TRACE (PBD::DEBUG::MidiClock, string_compose ("Song Position: %1\n", midi_beats));
_midi_port->midimsg (msg, sizeof (msg), offset); _midi_port->midimsg (msg, sizeof (msg), offset);
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Song Position Sent: %1\n", midi_beats));
} }

View file

@ -1,6 +1,7 @@
#include <CoreFoundation/CFLocale.h> #include <CoreFoundation/CFLocale.h>
#import <CoreFoundation/CFString.h> #import <CoreFoundation/CFString.h>
#import <Foundation/NSString.h> #import <Foundation/NSString.h>
#import <Foundation/NSURL.h>
#import <Foundation/NSAutoreleasePool.h> #import <Foundation/NSAutoreleasePool.h>
#import <AppKit/NSWorkspace.h> #import <AppKit/NSWorkspace.h>

View file

@ -132,12 +132,13 @@ def build(bld):
obj.uselib = 'GLIBMM SIGCPP XML UUID SNDFILE GIOMM' obj.uselib = 'GLIBMM SIGCPP XML UUID SNDFILE GIOMM'
if sys.platform == 'darwin': if sys.platform == 'darwin':
TaskGen.task_gen.mappings['.mm'] = TaskGen.task_gen.mappings['.cc'] TaskGen.task_gen.mappings['.mm'] = TaskGen.task_gen.mappings['.cc']
obj.source += [ 'cocoa_open_uri.mm' ] if 'cocoa_open_uri.mm' not in obj.source:
obj.source += [ 'cocoa_open_uri.mm' ]
obj.uselib += ' OSX' obj.uselib += ' OSX'
obj.vnum = LIBPBD_LIB_VERSION obj.vnum = LIBPBD_LIB_VERSION
obj.install_path = os.path.join(bld.env['LIBDIR'], 'ardour3') obj.install_path = os.path.join(bld.env['LIBDIR'], 'ardour3')
obj.defines = ['PACKAGE="' + I18N_PACKAGE + '"'] obj.defines = ['PACKAGE="' + I18N_PACKAGE + '"']
if bld.env['build_target'] == 'x86_64': if bld.env['build_target'] == 'x86_64':
obj.defines += [ 'USE_X86_64_ASM' ] obj.defines += [ 'USE_X86_64_ASM' ]