summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2007-09-29 21:39:53 +0000
committerDavid Robillard <d@drobilla.net>2007-09-29 21:39:53 +0000
commitc0af61632938f161dd2e15dec3c5260a3d5427ca (patch)
tree950bcfc1bc1fb232f8244c42504b8da3d5b511f5
parent85923e8b4f9f1601f008a9120d376d944f2478a2 (diff)
downloadingen-c0af61632938f161dd2e15dec3c5260a3d5427ca.tar.gz
ingen-c0af61632938f161dd2e15dec3c5260a3d5427ca.tar.bz2
ingen-c0af61632938f161dd2e15dec3c5260a3d5427ca.zip
Work towards port monitoring and better (higher utilization) parallel execution.
git-svn-id: http://svn.drobilla.net/lad/ingen@784 a436a847-0d15-0410-975c-d299462d15a1
-rw-r--r--src/libs/engine/CompiledPatch.hpp3
-rw-r--r--src/libs/engine/DSSINode.cpp4
-rw-r--r--src/libs/engine/DSSINode.hpp2
-rw-r--r--src/libs/engine/DuplexPort.cpp24
-rw-r--r--src/libs/engine/DuplexPort.hpp1
-rw-r--r--src/libs/engine/EventSink.hpp59
-rw-r--r--src/libs/engine/EventSource.hpp3
-rw-r--r--src/libs/engine/GraphObject.hpp8
-rw-r--r--src/libs/engine/InputPort.cpp43
-rw-r--r--src/libs/engine/InputPort.hpp2
-rw-r--r--src/libs/engine/JackAudioDriver.cpp5
-rw-r--r--src/libs/engine/JackAudioDriver.hpp2
-rw-r--r--src/libs/engine/LADSPANode.cpp2
-rw-r--r--src/libs/engine/LADSPANode.hpp2
-rw-r--r--src/libs/engine/LV2Node.cpp2
-rw-r--r--src/libs/engine/LV2Node.hpp2
-rw-r--r--src/libs/engine/Makefile.am2
-rw-r--r--src/libs/engine/MidiControlNode.cpp2
-rw-r--r--src/libs/engine/MidiControlNode.hpp2
-rw-r--r--src/libs/engine/MidiNoteNode.cpp2
-rw-r--r--src/libs/engine/MidiNoteNode.hpp2
-rw-r--r--src/libs/engine/MidiTriggerNode.cpp2
-rw-r--r--src/libs/engine/MidiTriggerNode.hpp2
-rw-r--r--src/libs/engine/Node.hpp2
-rw-r--r--src/libs/engine/NodeBase.cpp13
-rw-r--r--src/libs/engine/NodeBase.hpp2
-rw-r--r--src/libs/engine/OutputPort.cpp12
-rw-r--r--src/libs/engine/OutputPort.hpp1
-rw-r--r--src/libs/engine/Patch.cpp29
-rw-r--r--src/libs/engine/Patch.hpp6
-rw-r--r--src/libs/engine/Port.cpp6
-rw-r--r--src/libs/engine/Port.hpp16
-rw-r--r--src/libs/engine/ProcessContext.cpp25
-rw-r--r--src/libs/engine/ProcessContext.hpp50
-rw-r--r--src/libs/engine/ProcessSlave.cpp2
-rw-r--r--src/libs/engine/ProcessSlave.hpp11
-rw-r--r--src/libs/engine/TransportNode.cpp2
-rw-r--r--src/libs/engine/TransportNode.hpp2
-rw-r--r--src/libs/engine/events/EnablePortNotificationEvent.cpp80
-rw-r--r--src/libs/engine/events/EnablePortNotificationEvent.hpp58
-rw-r--r--src/libs/engine/events/Makefile.am4
-rw-r--r--src/libs/engine/events/RequestPortValueEvent.cpp21
-rw-r--r--src/libs/engine/events/SendPortValueEvent.cpp61
-rw-r--r--src/libs/engine/events/SendPortValueEvent.hpp80
-rw-r--r--src/libs/engine/events/SetPortValueEvent.cpp14
45 files changed, 575 insertions, 100 deletions
diff --git a/src/libs/engine/CompiledPatch.hpp b/src/libs/engine/CompiledPatch.hpp
index f5de52e1..953d94d6 100644
--- a/src/libs/engine/CompiledPatch.hpp
+++ b/src/libs/engine/CompiledPatch.hpp
@@ -39,7 +39,8 @@ struct CompiledNode {
{
// Copy to a vector for maximum iteration speed and cache optimization
// (Need to take a copy anyway)
-
+
+ _dependants.reserve(d->size());
for (List<Node*>::iterator i = d->begin(); i != d->end(); ++i)
_dependants.push_back(*i);
}
diff --git a/src/libs/engine/DSSINode.cpp b/src/libs/engine/DSSINode.cpp
index c2d05d36..af9be208 100644
--- a/src/libs/engine/DSSINode.cpp
+++ b/src/libs/engine/DSSINode.cpp
@@ -172,7 +172,7 @@ DSSINode::has_midi_input() const
void
-DSSINode::process(SampleCount nframes, FrameTime start, FrameTime end)
+DSSINode::process(ProcessContext& context, SampleCount nframes, FrameTime start, FrameTime end)
{
NodeBase::pre_process(nframes, start, end);
@@ -188,7 +188,7 @@ DSSINode::process(SampleCount nframes, FrameTime start, FrameTime end)
_dssi_descriptor->run_multiple_synths(1, _instances, nframes,
events, events_sizes);
} else {
- LADSPANode::process(nframes, start, end);
+ LADSPANode::process(context, nframes, start, end);
}
NodeBase::post_process(nframes, start, end);
diff --git a/src/libs/engine/DSSINode.hpp b/src/libs/engine/DSSINode.hpp
index 2c97fdc3..1e24836d 100644
--- a/src/libs/engine/DSSINode.hpp
+++ b/src/libs/engine/DSSINode.hpp
@@ -54,7 +54,7 @@ public:
void configure(const string& key, const string& val);
void program(int bank, int program);
- void process(SampleCount nframes, FrameTime start, FrameTime end);
+ void process(ProcessContext& events, SampleCount nframes, FrameTime start, FrameTime end);
void set_port_buffer(uint32_t voice, uint32_t port_num, Buffer* buf);
diff --git a/src/libs/engine/DuplexPort.cpp b/src/libs/engine/DuplexPort.cpp
index a0d370db..f0b138ed 100644
--- a/src/libs/engine/DuplexPort.cpp
+++ b/src/libs/engine/DuplexPort.cpp
@@ -30,10 +30,10 @@ namespace Ingen {
DuplexPort::DuplexPort(Node* parent, const string& name, uint32_t index, uint32_t poly, DataType type, size_t buffer_size, bool is_output)
-: Port(parent, name, index, poly, type, buffer_size)
-, InputPort(parent, name, index, poly, type, buffer_size)
-, OutputPort(parent, name, index, poly, type, buffer_size)
-, _is_output(is_output)
+ : Port(parent, name, index, poly, type, buffer_size)
+ , InputPort(parent, name, index, poly, type, buffer_size)
+ , OutputPort(parent, name, index, poly, type, buffer_size)
+ , _is_output(is_output)
{
assert(Port::_parent == parent);
}
@@ -43,11 +43,19 @@ void
DuplexPort::pre_process(SampleCount nframes, FrameTime start, FrameTime end)
{
// Think about it...
-
- if (_is_output)
+
+// if (_is_output) {
InputPort::pre_process(nframes, start, end);
- else
- OutputPort::pre_process(nframes, start, end);
+// } else {
+ //for (uint32_t i=0; i < _poly; ++i)
+ // _buffers->at(i)->rewind();
+// OutputPort::pre_process(nframes, start, end);
+// }
+}
+
+void
+DuplexPort::process(ProcessContext& events, SampleCount nframes, FrameTime start, FrameTime end)
+{
}
diff --git a/src/libs/engine/DuplexPort.hpp b/src/libs/engine/DuplexPort.hpp
index b6d2578c..4c98ea88 100644
--- a/src/libs/engine/DuplexPort.hpp
+++ b/src/libs/engine/DuplexPort.hpp
@@ -45,6 +45,7 @@ public:
virtual ~DuplexPort() {}
void pre_process(SampleCount nframes, FrameTime start, FrameTime end);
+ void process(ProcessContext& events, SampleCount nframes, FrameTime start, FrameTime end);
void post_process(SampleCount nframes, FrameTime start, FrameTime end);
bool is_input() const { return !_is_output; }
diff --git a/src/libs/engine/EventSink.hpp b/src/libs/engine/EventSink.hpp
new file mode 100644
index 00000000..27407684
--- /dev/null
+++ b/src/libs/engine/EventSink.hpp
@@ -0,0 +1,59 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef EVENTSINK_H
+#define EVENTSINK_H
+
+#include <list>
+#include <utility>
+#include <raul/DoubleBuffer.hpp>
+#include "types.hpp"
+
+namespace Ingen {
+
+class Port;
+
+
+/** Sink for events generated in the audio thread.
+ *
+ * Implemented as a flat ringbuffer of events, which are constructed directly
+ * in the ringbuffer rather than allocated on the heap (in order to make
+ * writing realtime safe).
+ *
+ * \ingroup engine
+ */
+class EventSink
+{
+public:
+ EventSink(size_t capacity) : _capacity(capacity) {}
+
+ /* FIXME: Figure out variable sized event queues and make this a generic
+ * interface (ie don't add a method for every event type, crap..) */
+
+ void control_change(Port* port, float val);
+
+private:
+ size_t _capacity;
+ //Raul::List<std::pair<Port*, Raul::DoubleBuffer<float> > > _ports;
+};
+
+
+
+} // namespace Ingen
+
+#endif // EVENTSINK_H
+
diff --git a/src/libs/engine/EventSource.hpp b/src/libs/engine/EventSource.hpp
index 2bf40527..803fa8c9 100644
--- a/src/libs/engine/EventSource.hpp
+++ b/src/libs/engine/EventSource.hpp
@@ -42,7 +42,6 @@ class PostProcessor;
class EventSource
{
public:
-
virtual ~EventSource() {}
virtual void activate() = 0;
@@ -54,7 +53,7 @@ public:
FrameTime cycle_end) = 0;
protected:
- EventSource() {}
+ size_t _capacity;
};
diff --git a/src/libs/engine/GraphObject.hpp b/src/libs/engine/GraphObject.hpp
index a2cfd5f0..3da9c64f 100644
--- a/src/libs/engine/GraphObject.hpp
+++ b/src/libs/engine/GraphObject.hpp
@@ -27,16 +27,16 @@
#include <raul/Atom.hpp>
#include "types.hpp"
-using std::string;
using Raul::Atom;
using Raul::Path;
-
namespace Raul { class Maid; }
namespace Ingen {
class Patch;
+class ProcessContext;
+
/** An object on the audio graph - Patch, Node, Port, etc.
*
@@ -67,7 +67,7 @@ public:
inline GraphObject* parent() const { return _parent; }
inline const string& name() const { return _name; }
- virtual void process(SampleCount nframes, FrameTime start, FrameTime end) = 0;
+ virtual void process(ProcessContext& events, SampleCount nframes, FrameTime start, FrameTime end) = 0;
/** Rename */
virtual void set_path(const Path& new_path) {
@@ -102,7 +102,7 @@ public:
protected:
GraphObject* _parent;
- string _name;
+ std::string _name;
bool _polyphonic;
private:
diff --git a/src/libs/engine/InputPort.cpp b/src/libs/engine/InputPort.cpp
index 1adb53a0..4f2147c4 100644
--- a/src/libs/engine/InputPort.cpp
+++ b/src/libs/engine/InputPort.cpp
@@ -23,17 +23,30 @@
#include "Connection.hpp"
#include "OutputPort.hpp"
#include "Node.hpp"
+#include "ProcessContext.hpp"
#include "util.hpp"
-using std::cerr; using std::cout; using std::endl;
-
+using namespace std;
namespace Ingen {
InputPort::InputPort(Node* parent, const string& name, uint32_t index, uint32_t poly, DataType type, size_t buffer_size)
-: Port(parent, name, index, poly, type, buffer_size)
+ : Port(parent, name, index, poly, type, buffer_size)
+ , _last_reported_value(0.0f) // default?
+{
+}
+
+
+void
+InputPort::set_buffer_size(size_t size)
{
+ Port::set_buffer_size(size);
+ assert(_buffer_size = size);
+
+ for (Raul::List<Connection*>::iterator c = _connections.begin(); c != _connections.end(); ++c)
+ (*c)->set_buffer_size(size);
+
}
@@ -64,6 +77,10 @@ InputPort::add_connection(Raul::ListNode<Connection*>* const c)
}
Port::connect_buffers();
}
+
+ // Automatically monitor connected control inputs
+ if (_type == DataType::FLOAT && _buffer_size == 1)
+ _monitor = true;
}
@@ -104,6 +121,10 @@ InputPort::remove_connection(const OutputPort* src_port)
if (modify_buffers)
Port::connect_buffers();
+
+ // Turn off monitoring if we're not connected any more (FIXME: not quite right..)
+ if (_type == DataType::FLOAT && _buffer_size == 1 && _connections.size() == 0)
+ _monitor = false;
return connection;
}
@@ -195,16 +216,18 @@ InputPort::pre_process(SampleCount nframes, FrameTime start, FrameTime end)
void
-InputPort::set_buffer_size(size_t size)
+InputPort::process(ProcessContext& context, SampleCount nframes, FrameTime start, FrameTime end)
{
- Port::set_buffer_size(size);
- assert(_buffer_size = size);
-
- for (Raul::List<Connection*>::iterator c = _connections.begin(); c != _connections.end(); ++c)
- (*c)->set_buffer_size(size);
-
+ if (_monitor && _type == DataType::FLOAT && _buffer_size == 1) {
+ const Sample value = ((AudioBuffer*)(*_buffers)[0])->value_at(0);
+ if (value != _last_reported_value) {
+ context.event_sink().control_change(this, ((AudioBuffer*)(*_buffers)[0])->value_at(0));
+ _last_reported_value = value;
+ }
+ }
}
+
void
InputPort::post_process(SampleCount nframes, FrameTime start, FrameTime end)
{
diff --git a/src/libs/engine/InputPort.hpp b/src/libs/engine/InputPort.hpp
index a7da6250..6aa86b9c 100644
--- a/src/libs/engine/InputPort.hpp
+++ b/src/libs/engine/InputPort.hpp
@@ -57,6 +57,7 @@ public:
const Connections& connections() { return _connections; }
void pre_process(SampleCount nframes, FrameTime start, FrameTime end);
+ void process(ProcessContext& events, SampleCount nframes, FrameTime start, FrameTime end);
void post_process(SampleCount nframes, FrameTime start, FrameTime end);
bool is_connected() const { return (_connections.size() > 0); }
@@ -69,6 +70,7 @@ public:
private:
Connections _connections;
+ Sample _last_reported_value;
};
diff --git a/src/libs/engine/JackAudioDriver.cpp b/src/libs/engine/JackAudioDriver.cpp
index b9cbdb60..4f32beb4 100644
--- a/src/libs/engine/JackAudioDriver.cpp
+++ b/src/libs/engine/JackAudioDriver.cpp
@@ -299,8 +299,9 @@ JackAudioDriver::_process_cb(jack_nframes_t nframes)
// Run root patch
if (_root_patch)
- _root_patch->process(nframes, start_of_current_cycle, start_of_current_cycle + nframes);
-
+ _root_patch->process(_process_context, nframes, start_of_current_cycle,
+ start_of_current_cycle + nframes);
+
return 0;
}
diff --git a/src/libs/engine/JackAudioDriver.hpp b/src/libs/engine/JackAudioDriver.hpp
index 9b195b13..28007d77 100644
--- a/src/libs/engine/JackAudioDriver.hpp
+++ b/src/libs/engine/JackAudioDriver.hpp
@@ -25,6 +25,7 @@
#include <raul/List.hpp>
#include "AudioDriver.hpp"
#include "Buffer.hpp"
+#include "ProcessContext.hpp"
namespace Ingen {
@@ -136,6 +137,7 @@ private:
jack_transport_state_t _transport_state;
Raul::List<JackAudioPort*> _ports;
+ ProcessContext _process_context;
Patch* _root_patch;
};
diff --git a/src/libs/engine/LADSPANode.cpp b/src/libs/engine/LADSPANode.cpp
index ad1761e8..b2725131 100644
--- a/src/libs/engine/LADSPANode.cpp
+++ b/src/libs/engine/LADSPANode.cpp
@@ -188,7 +188,7 @@ LADSPANode::deactivate()
void
-LADSPANode::process(SampleCount nframes, FrameTime start, FrameTime end)
+LADSPANode::process(ProcessContext& context, SampleCount nframes, FrameTime start, FrameTime end)
{
NodeBase::pre_process(nframes, start, end);
diff --git a/src/libs/engine/LADSPANode.hpp b/src/libs/engine/LADSPANode.hpp
index 3c673f0b..a4ea1031 100644
--- a/src/libs/engine/LADSPANode.hpp
+++ b/src/libs/engine/LADSPANode.hpp
@@ -42,7 +42,7 @@ public:
void activate();
void deactivate();
- void process(SampleCount nframes, FrameTime start, FrameTime end);
+ void process(ProcessContext& events, SampleCount nframes, FrameTime start, FrameTime end);
void set_port_buffer(uint32_t voice, uint32_t port_num, Buffer* buf);
diff --git a/src/libs/engine/LV2Node.cpp b/src/libs/engine/LV2Node.cpp
index f1b61997..88c002e5 100644
--- a/src/libs/engine/LV2Node.cpp
+++ b/src/libs/engine/LV2Node.cpp
@@ -241,7 +241,7 @@ LV2Node::deactivate()
void
-LV2Node::process(SampleCount nframes, FrameTime start, FrameTime end)
+LV2Node::process(ProcessContext& context, SampleCount nframes, FrameTime start, FrameTime end)
{
NodeBase::pre_process(nframes, start, end);
diff --git a/src/libs/engine/LV2Node.hpp b/src/libs/engine/LV2Node.hpp
index c566b138..d0941b93 100644
--- a/src/libs/engine/LV2Node.hpp
+++ b/src/libs/engine/LV2Node.hpp
@@ -51,7 +51,7 @@ public:
void activate();
void deactivate();
- void process(SampleCount nframes, FrameTime start, FrameTime end);
+ void process(ProcessContext& events, SampleCount nframes, FrameTime start, FrameTime end);
void set_port_buffer(uint32_t voice, uint32_t port_num, Buffer* buf);
diff --git a/src/libs/engine/Makefile.am b/src/libs/engine/Makefile.am
index 44d3825b..5a5879d5 100644
--- a/src/libs/engine/Makefile.am
+++ b/src/libs/engine/Makefile.am
@@ -83,6 +83,8 @@ libingen_engine_la_SOURCES = \
Port.hpp \
PostProcessor.cpp \
PostProcessor.hpp \
+ ProcessContext.hpp \
+ ProcessContext.cpp \
ProcessSlave.hpp \
ProcessSlave.cpp \
QueuedEngineInterface.cpp \
diff --git a/src/libs/engine/MidiControlNode.cpp b/src/libs/engine/MidiControlNode.cpp
index 3d4924b6..a2db6696 100644
--- a/src/libs/engine/MidiControlNode.cpp
+++ b/src/libs/engine/MidiControlNode.cpp
@@ -71,7 +71,7 @@ MidiControlNode::MidiControlNode(const string& path, bool polyphonic, Patch* par
void
-MidiControlNode::process(SampleCount nframes, FrameTime start, FrameTime end)
+MidiControlNode::process(ProcessContext& context, SampleCount nframes, FrameTime start, FrameTime end)
{
NodeBase::pre_process(nframes, start, end);
diff --git a/src/libs/engine/MidiControlNode.hpp b/src/libs/engine/MidiControlNode.hpp
index ee97fa8a..d06e2288 100644
--- a/src/libs/engine/MidiControlNode.hpp
+++ b/src/libs/engine/MidiControlNode.hpp
@@ -41,7 +41,7 @@ class MidiControlNode : public NodeBase
public:
MidiControlNode(const std::string& path, bool polyphonic, Patch* parent, SampleRate srate, size_t buffer_size);
- void process(SampleCount nframes, FrameTime start, FrameTime end);
+ void process(ProcessContext& events, SampleCount nframes, FrameTime start, FrameTime end);
void control(uchar control_num, uchar val, SampleCount offset);
diff --git a/src/libs/engine/MidiNoteNode.cpp b/src/libs/engine/MidiNoteNode.cpp
index 42d96dfa..bfab7ed0 100644
--- a/src/libs/engine/MidiNoteNode.cpp
+++ b/src/libs/engine/MidiNoteNode.cpp
@@ -119,7 +119,7 @@ MidiNoteNode::apply_poly(Raul::Maid& maid, uint32_t poly)
void
-MidiNoteNode::process(SampleCount nframes, FrameTime start, FrameTime end)
+MidiNoteNode::process(ProcessContext& context, SampleCount nframes, FrameTime start, FrameTime end)
{
NodeBase::pre_process(nframes, start, end);
diff --git a/src/libs/engine/MidiNoteNode.hpp b/src/libs/engine/MidiNoteNode.hpp
index f2fbbf5d..e86102db 100644
--- a/src/libs/engine/MidiNoteNode.hpp
+++ b/src/libs/engine/MidiNoteNode.hpp
@@ -45,7 +45,7 @@ public:
bool prepare_poly(uint32_t poly);
bool apply_poly(Raul::Maid& maid, uint32_t poly);
- void process(SampleCount nframes, FrameTime start, FrameTime end);
+ void process(ProcessContext& events, SampleCount nframes, FrameTime start, FrameTime end);
void note_on(uchar note_num, uchar velocity, FrameTime time, SampleCount nframes, FrameTime start, FrameTime end);
void note_off(uchar note_num, FrameTime time, SampleCount nframes, FrameTime start, FrameTime end);
diff --git a/src/libs/engine/MidiTriggerNode.cpp b/src/libs/engine/MidiTriggerNode.cpp
index 7d8fa952..7a889d43 100644
--- a/src/libs/engine/MidiTriggerNode.cpp
+++ b/src/libs/engine/MidiTriggerNode.cpp
@@ -59,7 +59,7 @@ MidiTriggerNode::MidiTriggerNode(const string& path, bool polyphonic, Patch* par
void
-MidiTriggerNode::process(SampleCount nframes, FrameTime start, FrameTime end)
+MidiTriggerNode::process(ProcessContext& context, SampleCount nframes, FrameTime start, FrameTime end)
{
NodeBase::pre_process(nframes, start, end);
diff --git a/src/libs/engine/MidiTriggerNode.hpp b/src/libs/engine/MidiTriggerNode.hpp
index 83dbe65f..389768f8 100644
--- a/src/libs/engine/MidiTriggerNode.hpp
+++ b/src/libs/engine/MidiTriggerNode.hpp
@@ -43,7 +43,7 @@ class MidiTriggerNode : public NodeBase
public:
MidiTriggerNode(const std::string& path, bool polyphonic, Patch* parent, SampleRate srate, size_t buffer_size);
- void process(SampleCount nframes, FrameTime start, FrameTime end);
+ void process(ProcessContext& events, SampleCount nframes, FrameTime start, FrameTime end);
void note_on(uchar note_num, uchar velocity, FrameTime time, SampleCount nframes, FrameTime start, FrameTime end);
void note_off(uchar note_num, FrameTime time, SampleCount nframes, FrameTime start, FrameTime end);
diff --git a/src/libs/engine/Node.hpp b/src/libs/engine/Node.hpp
index 83a31c67..8db11ad8 100644
--- a/src/libs/engine/Node.hpp
+++ b/src/libs/engine/Node.hpp
@@ -117,7 +117,7 @@ public:
* @a start and @a end are transport times: end is not redundant in the case
* of varispeed, where end-start != nframes.
*/
- virtual void process(SampleCount nframes, FrameTime start, FrameTime end) = 0;
+ virtual void process(ProcessContext& events, SampleCount nframes, FrameTime start, FrameTime end) = 0;
virtual void set_port_buffer(uint32_t voice, uint32_t port_num, Buffer* buf) = 0;
diff --git a/src/libs/engine/NodeBase.cpp b/src/libs/engine/NodeBase.cpp
index 4f3d37b2..5e6176f0 100644
--- a/src/libs/engine/NodeBase.cpp
+++ b/src/libs/engine/NodeBase.cpp
@@ -175,10 +175,10 @@ NodeBase::signal_input_ready()
void
NodeBase::pre_process(SampleCount nframes, FrameTime start, FrameTime end)
{
- assert(_activated);
// Mix down any ports with multiple inputs
- for (size_t i=0; i < _ports->size(); ++i)
- _ports->at(i)->pre_process(nframes, start, end);
+ if (_ports)
+ for (size_t i=0; i < _ports->size(); ++i)
+ _ports->at(i)->pre_process(nframes, start, end);
}
@@ -187,11 +187,10 @@ NodeBase::pre_process(SampleCount nframes, FrameTime start, FrameTime end)
void
NodeBase::post_process(SampleCount nframes, FrameTime start, FrameTime end)
{
- assert(_activated);
-
/* Write output ports */
- for (size_t i=0; i < _ports->size(); ++i)
- _ports->at(i)->post_process(nframes, start, end);
+ if (_ports)
+ for (size_t i=0; i < _ports->size(); ++i)
+ _ports->at(i)->post_process(nframes, start, end);
}
diff --git a/src/libs/engine/NodeBase.hpp b/src/libs/engine/NodeBase.hpp
index 9f12c95f..d43a84a6 100644
--- a/src/libs/engine/NodeBase.hpp
+++ b/src/libs/engine/NodeBase.hpp
@@ -70,7 +70,7 @@ public:
virtual unsigned n_inputs_ready() const { return _n_inputs_ready.get(); }
virtual void pre_process(SampleCount nframes, FrameTime start, FrameTime end);
- virtual void process(SampleCount nframes, FrameTime start, FrameTime end) = 0;
+ virtual void process(ProcessContext& events, SampleCount nframes, FrameTime start, FrameTime end) = 0;
virtual void post_process(SampleCount nframes, FrameTime start, FrameTime end);
virtual void set_port_buffer(uint32_t voice, uint32_t port_num, Buffer* buf) {}
diff --git a/src/libs/engine/OutputPort.cpp b/src/libs/engine/OutputPort.cpp
index 9724c4c7..b7da8956 100644
--- a/src/libs/engine/OutputPort.cpp
+++ b/src/libs/engine/OutputPort.cpp
@@ -16,7 +16,8 @@
*/
#include "OutputPort.hpp"
-#include "Buffer.hpp"
+#include "AudioBuffer.hpp"
+#include "ProcessContext.hpp"
namespace Ingen {
@@ -30,6 +31,15 @@ OutputPort::pre_process(SampleCount nframes, FrameTime start, FrameTime end)
void
+OutputPort::process(ProcessContext& context, SampleCount nframes, FrameTime start, FrameTime end)
+{
+ if (_monitor && _type == DataType::FLOAT && _buffer_size == 1) {
+ context.event_sink().control_change(this, ((AudioBuffer*)(*_buffers)[0])->value_at(0));
+ }
+}
+
+
+void
OutputPort::post_process(SampleCount nframes, FrameTime start, FrameTime end)
{
for (uint32_t i=0; i < _poly; ++i)
diff --git a/src/libs/engine/OutputPort.hpp b/src/libs/engine/OutputPort.hpp
index 0c2e0443..8f12d252 100644
--- a/src/libs/engine/OutputPort.hpp
+++ b/src/libs/engine/OutputPort.hpp
@@ -50,6 +50,7 @@ public:
{}
void pre_process(SampleCount nframes, FrameTime start, FrameTime end);
+ void process(ProcessContext& events, SampleCount nframes, FrameTime start, FrameTime end);
void post_process(SampleCount nframes, FrameTime start, FrameTime end);
virtual ~OutputPort() {}
diff --git a/src/libs/engine/Patch.cpp b/src/libs/engine/Patch.cpp
index 2705db36..80d59768 100644
--- a/src/libs/engine/Patch.cpp
+++ b/src/libs/engine/Patch.cpp
@@ -147,33 +147,25 @@ Patch::apply_internal_poly(Raul::Maid& maid, uint32_t poly)
* Calls all Nodes in (roughly, if parallel) the order _compiled_patch specifies.
*/
void
-Patch::process(SampleCount nframes, FrameTime start, FrameTime end)
+Patch::process(ProcessContext& context, SampleCount nframes, FrameTime start, FrameTime end)
{
if (_compiled_patch == NULL || _compiled_patch->size() == 0 || !_process)
return;
- /* Prepare input ports */
- /* FIXME: Pre-processing input ports breaks MIDI somehow? */
- if (_ports)
- for (size_t i=0; i < _ports->size(); ++i)
- if (_ports->at(i)->is_output())
- _ports->at(i)->pre_process(nframes, start, end);
+ NodeBase::pre_process(nframes, start, end);
/* Run */
if (_engine.process_slaves().size() > 0)
- process_parallel(nframes, start, end);
+ process_parallel(context, nframes, start, end);
else
- process_single(nframes, start, end);
+ process_single(context, nframes, start, end);
- /* Write output ports */
- if (_ports)
- for (size_t i=0; i < _ports->size(); ++i)
- _ports->at(i)->post_process(nframes, start, end);
+ NodeBase::post_process(nframes, start, end);
}
void
-Patch::process_parallel(SampleCount nframes, FrameTime start, FrameTime end)
+Patch::process_parallel(ProcessContext& context, SampleCount nframes, FrameTime start, FrameTime end)
{
size_t n_slaves = _engine.process_slaves().size();
@@ -209,7 +201,7 @@ Patch::process_parallel(SampleCount nframes, FrameTime start, FrameTime end)
if (n.node()->process_lock()) {
if (n.node()->n_inputs_ready() == n.n_providers()) {
- n.node()->process(nframes, start, end);
+ n.node()->process(context, nframes, start, end);
/* Signal dependants their input is ready */
for (size_t i=0; i < n.dependants().size(); ++i)
@@ -232,7 +224,8 @@ Patch::process_parallel(SampleCount nframes, FrameTime start, FrameTime end)
/* Tell slaves we're done in case we beat them, and pray they're
* really done by the start of next cycle.
- * FIXME: This probably breaks (race) at extremely small nframes.
+ * FIXME: This probably breaks (race) at extremely small nframes where
+ * ingen is the majority of the DSP load.
*/
for (size_t i=0; i < n_slaves; ++i)
_engine.process_slaves()[i]->finish();
@@ -240,12 +233,12 @@ Patch::process_parallel(SampleCount nframes, FrameTime start, FrameTime end)
void
-Patch::process_single(SampleCount nframes, FrameTime start, FrameTime end)
+Patch::process_single(ProcessContext& context, SampleCount nframes, FrameTime start, FrameTime end)
{
CompiledPatch* const cp = _compiled_patch;
for (size_t i=0; i < cp->size(); ++i)
- (*cp)[i].node()->process(nframes, start, end);
+ (*cp)[i].node()->process(context, nframes, start, end);
}
diff --git a/src/libs/engine/Patch.hpp b/src/libs/engine/Patch.hpp
index 32a02f76..75de93cb 100644
--- a/src/libs/engine/Patch.hpp
+++ b/src/libs/engine/Patch.hpp
@@ -54,7 +54,7 @@ public:
void activate();
void deactivate();
- void process(SampleCount nframes, FrameTime start, FrameTime end);
+ void process(ProcessContext& events, SampleCount nframes, FrameTime start, FrameTime end);
void set_buffer_size(size_t size);
@@ -113,8 +113,8 @@ public:
private:
inline void compile_recursive(Node* n, CompiledPatch* output) const;
- void process_parallel(SampleCount nframes, FrameTime start, FrameTime end);
- void process_single(SampleCount nframes, FrameTime start, FrameTime end);
+ void process_parallel(ProcessContext& context, SampleCount nframes, FrameTime start, FrameTime end);
+ void process_single(ProcessContext& context, SampleCount nframes, FrameTime start, FrameTime end);
Engine& _engine;
uint32_t _internal_poly;
diff --git a/src/libs/engine/Port.cpp b/src/libs/engine/Port.cpp
index 8613581d..d1813f3f 100644
--- a/src/libs/engine/Port.cpp
+++ b/src/libs/engine/Port.cpp
@@ -20,8 +20,9 @@
#include "Port.hpp"
#include "Node.hpp"
#include "DataType.hpp"
-#include "Buffer.hpp"
+#include "AudioBuffer.hpp"
#include "BufferFactory.hpp"
+#include "ProcessContext.hpp"
namespace Ingen {
@@ -34,9 +35,10 @@ Port::Port(Node* const node, const string& name, uint32_t index, uint32_t poly,
: GraphObject(node, name, true)
, _index(index)
, _poly(poly)
- , _type(type)
, _buffer_size(buffer_size)
+ , _type(type)
, _fixed_buffers(false)
+ , _monitor(false)
, _buffers(new Raul::Array<Buffer*>(poly))
{
assert(node != NULL);
diff --git a/src/libs/engine/Port.hpp b/src/libs/engine/Port.hpp
index f0b7ec25..f02d6ba4 100644
--- a/src/libs/engine/Port.hpp
+++ b/src/libs/engine/Port.hpp
@@ -31,6 +31,7 @@ namespace Ingen {
class Node;
class Buffer;
+class ProcessContext;
/** A port on a Node.
@@ -67,7 +68,6 @@ public:
/** Called once per process cycle */
virtual void pre_process(SampleCount nframes, FrameTime start, FrameTime end) = 0;
- virtual void process(SampleCount nframes, FrameTime start, FrameTime end) {}
virtual void post_process(SampleCount nframes, FrameTime start, FrameTime end) {};
/** Empty buffer contents completely (ie silence) */
@@ -85,6 +85,9 @@ public:
void fixed_buffers(bool b) { _fixed_buffers = b; }
bool fixed_buffers() { return _fixed_buffers; }
+
+ void monitor(bool b) { _monitor = b; }
+ bool monitor() { return _monitor; }
protected:
Port(Node* const node, const std::string& name, uint32_t index, uint32_t poly, DataType type, size_t buffer_size);
@@ -92,11 +95,12 @@ protected:
virtual void allocate_buffers();
virtual void connect_buffers();
- uint32_t _index;
- uint32_t _poly;
- DataType _type;
- size_t _buffer_size;
- bool _fixed_buffers;
+ uint32_t _index;
+ uint32_t _poly;
+ uint32_t _buffer_size;
+ DataType _type;
+ bool _fixed_buffers;
+ bool _monitor;
Raul::Array<Buffer*>* _buffers;
diff --git a/src/libs/engine/ProcessContext.cpp b/src/libs/engine/ProcessContext.cpp
new file mode 100644
index 00000000..306f3dba
--- /dev/null
+++ b/src/libs/engine/ProcessContext.cpp
@@ -0,0 +1,25 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "ProcessContext.hpp"
+
+using namespace std;
+
+namespace Ingen {
+
+
+} // namespace Ingen
diff --git a/src/libs/engine/ProcessContext.hpp b/src/libs/engine/ProcessContext.hpp
new file mode 100644
index 00000000..4d5f733f
--- /dev/null
+++ b/src/libs/engine/ProcessContext.hpp
@@ -0,0 +1,50 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef PROCESSCONTEXT_H
+#define PROCESSCONTEXT_H
+
+#include "EventSink.hpp"
+
+namespace Ingen {
+
+
+/** Context of a process() call.
+ *
+ * This is used to pass whatever information a GraphObject might need to
+ * process in the audio thread, e.g. the available thread pool, sink for
+ * events (generated in the audio thread, not user initiated events), etc.
+ *
+ * \ingroup engine
+ */
+class ProcessContext
+{
+public:
+ ProcessContext() : _event_sink(1024) {} // FIXME: size?
+
+ EventSink& event_sink() { return _event_sink; }
+
+private:
+ EventSink _event_sink;
+};
+
+
+
+} // namespace Ingen
+
+#endif // PROCESSCONTEXT_H
+
diff --git a/src/libs/engine/ProcessSlave.cpp b/src/libs/engine/ProcessSlave.cpp
index 749f6a5c..d8f2e575 100644
--- a/src/libs/engine/ProcessSlave.cpp
+++ b/src/libs/engine/ProcessSlave.cpp
@@ -49,7 +49,7 @@ ProcessSlave::_whipped()
n.node()->wait_for_input(n.n_providers());
- n.node()->process(_nframes, _start, _end);
+ n.node()->process(_process_context, _nframes, _start, _end);
/* Signal dependants their input is ready */
for (size_t i=0; i < n.dependants().size(); ++i)
diff --git a/src/libs/engine/ProcessSlave.hpp b/src/libs/engine/ProcessSlave.hpp
index a5d2d9cc..c341fe64 100644
--- a/src/libs/engine/ProcessSlave.hpp
+++ b/src/libs/engine/ProcessSlave.hpp
@@ -24,6 +24,7 @@
#include <raul/Slave.hpp>
#include <raul/Array.hpp>
#include <raul/AtomicInt.hpp>
+#include "ProcessContext.hpp"
#include "types.hpp"
namespace Ingen {
@@ -35,7 +36,7 @@ class CompiledPatch;
class ProcessSlave : protected Raul::Slave {
public:
ProcessSlave(bool realtime)
- : _id(_next_id++), _state(STATE_FINISHED), _index(0), _compiled_patch(NULL)
+ : _id(_next_id++), _index(0), _state(STATE_FINISHED), _compiled_patch(NULL)
{
std::stringstream ss;
ss << "Process Slave ";
@@ -55,12 +56,13 @@ public:
inline void whip(CompiledPatch* compiled_patch, size_t start_index,
SampleCount nframes, FrameTime start, FrameTime end) {
assert(_state == STATE_FINISHED);
+ _index = start_index;
+ _state = STATE_RUNNING;
_nframes = nframes;
_start = start;
_end = end;
- _index = start_index;
_compiled_patch = compiled_patch;
- _state = STATE_RUNNING;
+
Raul::Slave::whip();
}
@@ -82,12 +84,13 @@ private:
static const int STATE_FINISHED = 2;
size_t _id;
+ size_t _index;
Raul::AtomicInt _state;
SampleCount _nframes;
FrameTime _start;
FrameTime _end;
- size_t _index;
CompiledPatch* _compiled_patch;
+ ProcessContext _process_context;
};
diff --git a/src/libs/engine/TransportNode.cpp b/src/libs/engine/TransportNode.cpp
index afa4cf21..6ee9835d 100644
--- a/src/libs/engine/TransportNode.cpp
+++ b/src/libs/engine/TransportNode.cpp
@@ -82,7 +82,7 @@ TransportNode::TransportNode(const string& path, bool polyphonic, Patch* parent,
void
-TransportNode::process(SampleCount nframes, FrameTime start, FrameTime end)
+TransportNode::process(ProcessContext& context, SampleCount nframes, FrameTime start, FrameTime end)
{
NodeBase::pre_process(nframes, start, end);
#if 0
diff --git a/src/libs/engine/TransportNode.hpp b/src/libs/engine/TransportNode.hpp
index 2d90d501..a12a8cfe 100644
--- a/src/libs/engine/TransportNode.hpp
+++ b/src/libs/engine/TransportNode.hpp
@@ -36,7 +36,7 @@ class TransportNode : public NodeBase
public:
TransportNode(const std::string& path, bool polyphonic, Patch* parent, SampleRate srate, size_t buffer_size);
- virtual void process(SampleCount nframes, FrameTime start, FrameTime end);
+ virtual void process(ProcessContext& events, SampleCount nframes, FrameTime start, FrameTime end);
};
diff --git a/src/libs/engine/events/EnablePortNotificationEvent.cpp b/src/libs/engine/events/EnablePortNotificationEvent.cpp
new file mode 100644
index 00000000..992c1615
--- /dev/null
+++ b/src/libs/engine/events/EnablePortNotificationEvent.cpp
@@ -0,0 +1,80 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "RequestPortValueEvent.hpp"
+#include <string>
+#include "interface/ClientInterface.hpp"
+#include "Responder.hpp"
+#include "Engine.hpp"
+#include "Port.hpp"
+#include "ObjectStore.hpp"
+#include "ClientBroadcaster.hpp"
+#include "AudioBuffer.hpp"
+
+using std::string;
+
+namespace Ingen {
+
+
+RequestPortValueEvent::RequestPortValueEvent(Engine& engine, SharedPtr<Responder> responder, SampleCount timestamp, const string& port_path)
+: QueuedEvent(engine, responder, timestamp),
+ _port_path(port_path),
+ _port(NULL),
+ _value(0.0)
+{
+}
+
+
+void
+RequestPortValueEvent::pre_process()
+{
+ _port = _engine.object_store()->find_port(_port_path);
+
+ QueuedEvent::pre_process();
+}
+
+
+void
+RequestPortValueEvent::execute(SampleCount nframes, FrameTime start, FrameTime end)
+{
+ QueuedEvent::execute(nframes, start, end);
+ assert(_time >= start && _time <= end);
+
+ if (_port != NULL && _port->type() == DataType::FLOAT)
+ _value = ((AudioBuffer*)_port->buffer(0))->value_at(0/*_time - start*/);
+ else
+ _port = NULL; // triggers error response
+}
+
+
+void
+RequestPortValueEvent::post_process()
+{
+ string msg;
+ if (!_port) {
+ _responder->respond_error("Unable to find port for get_value responder.");
+ } else if (_responder->client()) {
+ _responder->respond_ok();
+ _responder->client()->control_change(_port_path, _value);
+ } else {
+ _responder->respond_error("Unable to find client to send port value");
+ }
+}
+
+
+} // namespace Ingen
+
diff --git a/src/libs/engine/events/EnablePortNotificationEvent.hpp b/src/libs/engine/events/EnablePortNotificationEvent.hpp
new file mode 100644
index 00000000..522af143
--- /dev/null
+++ b/src/libs/engine/events/EnablePortNotificationEvent.hpp
@@ -0,0 +1,58 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef ENABLEPORTNOTIFICATIONEVENT_H
+#define ENABLEPORTNOTIFICATIONEVENT_H
+
+#include <string>
+#include "QueuedEvent.hpp"
+#include "types.hpp"
+
+using std::string;
+
+namespace Ingen {
+
+class Port;
+namespace Shared { class ClientInterface; }
+using Shared::ClientInterface;
+
+
+/** Enable sending of dynamic value change notifications for a port.
+ *
+ * \ingroup engine
+ */
+class EnablePortNotificationEvent : public QueuedEvent
+{
+public:
+ EnablePortNotificationEvent(Engine& engine,
+ SharedPtr<Responder> responder,
+ SampleCount timestamp,
+ const std::string& port_path);
+
+ void pre_process();
+ void execute(SampleCount nframes, FrameTime start, FrameTime end);
+ void post_process();
+
+private:
+ const std::string _port_path;
+ Port* _port;
+};
+
+
+} // namespace Ingen
+
+#endif // ENABLEPORTNOTIFICATIONEVENT_H
diff --git a/src/libs/engine/events/Makefile.am b/src/libs/engine/events/Makefile.am
index f3190756..a97c3bba 100644
--- a/src/libs/engine/events/Makefile.am
+++ b/src/libs/engine/events/Makefile.am
@@ -33,6 +33,8 @@ EXTRA_DIST = \
DisconnectionEvent.hpp \
EnablePatchEvent.cpp \
EnablePatchEvent.hpp \
+ EnablePortNotificationEvent.cpp \
+ EnablePortNotificationEvent.hpp \
LoadPluginsEvent.cpp \
LoadPluginsEvent.hpp \
MidiLearnEvent.cpp \
@@ -58,6 +60,8 @@ EXTRA_DIST = \
RequestPluginsEvent.hpp \
RequestPortValueEvent.cpp \
RequestPortValueEvent.hpp \
+ SendPortValueEvent.cpp \
+ SendPortValueEvent.hpp \
SetMetadataEvent.cpp \
SetMetadataEvent.hpp \
SetPolyphonyEvent.hpp \
diff --git a/src/libs/engine/events/RequestPortValueEvent.cpp b/src/libs/engine/events/RequestPortValueEvent.cpp
index 992c1615..34545670 100644
--- a/src/libs/engine/events/RequestPortValueEvent.cpp
+++ b/src/libs/engine/events/RequestPortValueEvent.cpp
@@ -15,9 +15,9 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "RequestPortValueEvent.hpp"
#include <string>
#include "interface/ClientInterface.hpp"
+#include "events/EnablePortNotificationEvent.hpp"
#include "Responder.hpp"
#include "Engine.hpp"
#include "Port.hpp"
@@ -30,17 +30,19 @@ using std::string;
namespace Ingen {
-RequestPortValueEvent::RequestPortValueEvent(Engine& engine, SharedPtr<Responder> responder, SampleCount timestamp, const string& port_path)
+EnablePortNotificationEvent::EnablePortNotificationEvent(Engine& engine,
+ SharedPtr<Responder> responder,
+ SampleCount timestamp,
+ const std::string& port_path)
: QueuedEvent(engine, responder, timestamp),
_port_path(port_path),
- _port(NULL),
- _value(0.0)
+ _port(NULL)
{
}
void
-RequestPortValueEvent::pre_process()
+EnablePortNotificationEvent::pre_process()
{
_port = _engine.object_store()->find_port(_port_path);
@@ -49,21 +51,25 @@ RequestPortValueEvent::pre_process()
void
-RequestPortValueEvent::execute(SampleCount nframes, FrameTime start, FrameTime end)
+EnablePortNotificationEvent::execute(SampleCount nframes, FrameTime start, FrameTime end)
{
QueuedEvent::execute(nframes, start, end);
+
+#if 0
assert(_time >= start && _time <= end);
if (_port != NULL && _port->type() == DataType::FLOAT)
_value = ((AudioBuffer*)_port->buffer(0))->value_at(0/*_time - start*/);
else
_port = NULL; // triggers error response
+#endif
}
void
-RequestPortValueEvent::post_process()
+EnablePortNotificationEvent::post_process()
{
+#if 0
string msg;
if (!_port) {
_responder->respond_error("Unable to find port for get_value responder.");
@@ -73,6 +79,7 @@ RequestPortValueEvent::post_process()
} else {
_responder->respond_error("Unable to find client to send port value");
}
+#endif
}
diff --git a/src/libs/engine/events/SendPortValueEvent.cpp b/src/libs/engine/events/SendPortValueEvent.cpp
new file mode 100644
index 00000000..d537011d
--- /dev/null
+++ b/src/libs/engine/events/SendPortValueEvent.cpp
@@ -0,0 +1,61 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <sstream>
+#include "Responder.hpp"
+#include "SendPortValueEvent.hpp"
+#include "Engine.hpp"
+#include "Port.hpp"
+#include "ClientBroadcaster.hpp"
+#include "Node.hpp"
+#include "ObjectStore.hpp"
+#include "AudioBuffer.hpp"
+#include "MidiBuffer.hpp"
+
+using namespace std;
+
+namespace Ingen {
+
+
+SendPortValueEvent(Engine& engine,
+ SampleCount timestamp,
+ Port* port,
+ bool omni,
+ uint32_t voice_num,
+ float value)
+ : _port(port)
+ , _omni(omni)
+ , _voice_num(voice_num)
+ , _value(value)
+{
+}
+
+
+void
+SendPortValueEvent::post_process()
+{
+ if (_omni) {
+ _engine.broadcaster()->send_control_change(_port->path(), _value);
+ } else {
+ cerr << "NON-OMNI CONTROL CHANGE WHAT?" << endl;
+ _engine.broadcaster()->send_control_change(_port->path(), _value);
+ }
+}
+
+
+} // namespace Ingen
+
diff --git a/src/libs/engine/events/SendPortValueEvent.hpp b/src/libs/engine/events/SendPortValueEvent.hpp
new file mode 100644
index 00000000..d63d43b0
--- /dev/null
+++ b/src/libs/engine/events/SendPortValueEvent.hpp
@@ -0,0 +1,80 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
+ *
+ * Ingen is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef SENDPORTVALUEEVENT_H
+#define SENDPORTVALUEEVENT_H
+
+#include <string>
+#include "Event.hpp"
+#include "types.hpp"
+using std::string;
+
+namespace Ingen {
+
+class Port;
+
+
+/** A special event used internally to send port values from the audio thread.
+ *
+ * This is created in the audio thread (using in-place new on a preallocated
+ * buffer) for processing in the post processing thread (unlike normal events
+ * which are created in the pre-processor thread then run through the audio
+ * thread). This event's job is done entirely in post_process.
+ *
+ * This only works for control ports right now. Variable size data is harder.
+ * Need some clever variable sized event RT allocation in flat buffer thingie..
+ *
+ * \ingroup engine
+ */
+class SendPortValueEvent : public Event
+{
+public:
+ SendPortValueEvent() {}
+
+ inline SendPortValueEvent(Engine& engine,
+ SampleCount timestamp,
+ Port* port,
+ bool omni,
+ uint32_t voice_num,
+ Sample value)
+ : _port(port)
+ , _omni(omni)
+ , _voice_num(voice_num)
+ , _value(value)
+ {
+ }
+
+ inline void operator=(const SendPortValueEvent& ev) {
+ _port = ev._port;
+ _omni = ev._omni;
+ _voice_num = ev._voice_num;
+ _value = ev._value;
+ }
+
+ void post_process();
+
+private:
+ Port* _port;
+ bool _omni;
+ uint32_t _voice_num;
+ Sample _value;
+};
+
+
+} // namespace Ingen
+
+#endif // SENDPORTVALUEEVENT_H
diff --git a/src/libs/engine/events/SetPortValueEvent.cpp b/src/libs/engine/events/SetPortValueEvent.cpp
index 9d1ad0db..c1f3c890 100644
--- a/src/libs/engine/events/SetPortValueEvent.cpp
+++ b/src/libs/engine/events/SetPortValueEvent.cpp
@@ -32,7 +32,7 @@ namespace Ingen {
/** Omni (all voices) control setting */
-SetPortValueEvent::SetPortValueEvent(Engine& engine,
+SetPortValueEvent::SetPortValueEvent(Engine& engine,
SharedPtr<Responder> responder,
SampleCount timestamp,
const string& port_path,
@@ -53,12 +53,12 @@ SetPortValueEvent::SetPortValueEvent(Engine& engine,
/** Voice-specific control setting */
SetPortValueEvent::SetPortValueEvent(Engine& engine,
- SharedPtr<Responder> responder,
- SampleCount timestamp,
- uint32_t voice_num,
- const string& port_path,
- uint32_t data_size,
- const void* data)
+ SharedPtr<Responder> responder,
+ SampleCount timestamp,
+ uint32_t voice_num,
+ const string& port_path,
+ uint32_t data_size,
+ const void* data)
: Event(engine, responder, timestamp),
_omni(false),
_voice_num(voice_num),