summaryrefslogtreecommitdiffstats
path: root/src/libs/engine
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2007-04-08 06:04:32 +0000
committerDavid Robillard <d@drobilla.net>2007-04-08 06:04:32 +0000
commite96c36c1a7abb062e36efc0ac95c35fedcef922e (patch)
tree826d5caa0392201472d12c02a1c3df4cf7b275be /src/libs/engine
parent7d69e89f22304e37fa325ce4f39a374a02072a69 (diff)
downloadingen-e96c36c1a7abb062e36efc0ac95c35fedcef922e.tar.gz
ingen-e96c36c1a7abb062e36efc0ac95c35fedcef922e.tar.bz2
ingen-e96c36c1a7abb062e36efc0ac95c35fedcef922e.zip
De-template-ification of port types (req. for LV2 MIDI, but nice code size reduction).
LV2 MIDI patching support (LV2 style MIDI throughout, inc. internal plugins). git-svn-id: http://svn.drobilla.net/lad/ingen@415 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src/libs/engine')
-rw-r--r--src/libs/engine/AlsaMidiDriver.cpp4
-rw-r--r--src/libs/engine/AlsaMidiDriver.h10
-rw-r--r--src/libs/engine/AudioBuffer.cpp (renamed from src/libs/engine/Buffer.cpp)134
-rw-r--r--src/libs/engine/AudioBuffer.h82
-rw-r--r--src/libs/engine/AudioDriver.h10
-rw-r--r--src/libs/engine/Buffer.h56
-rw-r--r--src/libs/engine/BufferFactory.cpp39
-rw-r--r--src/libs/engine/BufferFactory.h35
-rw-r--r--src/libs/engine/ClientBroadcaster.cpp2
-rw-r--r--src/libs/engine/Connection.cpp79
-rw-r--r--src/libs/engine/Connection.h36
-rw-r--r--src/libs/engine/DSSINode.cpp11
-rw-r--r--src/libs/engine/DSSINode.h30
-rw-r--r--src/libs/engine/DataType.h4
-rw-r--r--src/libs/engine/Driver.h16
-rw-r--r--src/libs/engine/DuplexPort.cpp15
-rw-r--r--src/libs/engine/DuplexPort.h7
-rw-r--r--src/libs/engine/Engine.cpp20
-rw-r--r--src/libs/engine/Engine.h7
-rw-r--r--src/libs/engine/InputPort.cpp86
-rw-r--r--src/libs/engine/InputPort.h33
-rw-r--r--src/libs/engine/JackAudioDriver.cpp11
-rw-r--r--src/libs/engine/JackAudioDriver.h18
-rw-r--r--src/libs/engine/JackMidiDriver.cpp26
-rw-r--r--src/libs/engine/JackMidiDriver.h14
-rw-r--r--src/libs/engine/LADSPANode.cpp25
-rw-r--r--src/libs/engine/LADSPANode.h2
-rw-r--r--src/libs/engine/LV2Node.cpp35
-rw-r--r--src/libs/engine/LV2Node.h2
-rw-r--r--src/libs/engine/Makefile.am10
-rw-r--r--src/libs/engine/MidiBuffer.cpp77
-rw-r--r--src/libs/engine/MidiBuffer.h88
-rw-r--r--src/libs/engine/MidiControlNode.cpp58
-rw-r--r--src/libs/engine/MidiControlNode.h23
-rw-r--r--src/libs/engine/MidiDriver.h12
-rw-r--r--src/libs/engine/MidiMessage.h52
-rw-r--r--src/libs/engine/MidiNoteNode.cpp95
-rw-r--r--src/libs/engine/MidiNoteNode.h16
-rw-r--r--src/libs/engine/MidiTriggerNode.cpp77
-rw-r--r--src/libs/engine/MidiTriggerNode.h17
-rw-r--r--src/libs/engine/Node.h11
-rw-r--r--src/libs/engine/NodeBase.h2
-rw-r--r--src/libs/engine/OSCClientSender.cpp2
-rw-r--r--src/libs/engine/ObjectSender.cpp8
-rw-r--r--src/libs/engine/OutputPort.h20
-rw-r--r--src/libs/engine/Patch.cpp8
-rw-r--r--src/libs/engine/Port.cpp71
-rw-r--r--src/libs/engine/Port.h23
-rw-r--r--src/libs/engine/TypedConnection.cpp123
-rw-r--r--src/libs/engine/TypedConnection.h104
-rw-r--r--src/libs/engine/TypedPort.cpp154
-rw-r--r--src/libs/engine/TypedPort.h79
-rw-r--r--src/libs/engine/events/AddPortEvent.cpp4
-rw-r--r--src/libs/engine/events/ConnectionEvent.cpp146
-rw-r--r--src/libs/engine/events/ConnectionEvent.h62
-rw-r--r--src/libs/engine/events/DisconnectNodeEvent.cpp2
-rw-r--r--src/libs/engine/events/DisconnectNodeEvent.h5
-rw-r--r--src/libs/engine/events/DisconnectionEvent.cpp123
-rw-r--r--src/libs/engine/events/DisconnectionEvent.h63
-rw-r--r--src/libs/engine/events/RequestObjectEvent.cpp4
-rw-r--r--src/libs/engine/events/RequestPluginEvent.cpp4
-rw-r--r--src/libs/engine/events/RequestPortValueEvent.cpp7
-rw-r--r--src/libs/engine/events/SetPortValueEvent.cpp13
-rw-r--r--src/libs/engine/events/SetPortValueQueuedEvent.cpp14
-rw-r--r--src/libs/engine/types.h4
65 files changed, 1081 insertions, 1349 deletions
diff --git a/src/libs/engine/AlsaMidiDriver.cpp b/src/libs/engine/AlsaMidiDriver.cpp
index 93d9d803..bbec1ab1 100644
--- a/src/libs/engine/AlsaMidiDriver.cpp
+++ b/src/libs/engine/AlsaMidiDriver.cpp
@@ -23,7 +23,7 @@
#include <raul/Maid.h>
#include "ThreadManager.h"
#include "AudioDriver.h"
-#include "MidiMessage.h"
+#include "MidiBuffer.h"
#include "DuplexPort.h"
#ifdef HAVE_LASH
#include "LashDriver.h"
@@ -35,7 +35,7 @@ namespace Ingen {
//// AlsaMidiPort ////
-AlsaMidiPort::AlsaMidiPort(AlsaMidiDriver* driver, DuplexPort<MidiMessage>* patch_port)
+AlsaMidiPort::AlsaMidiPort(AlsaMidiDriver* driver, DuplexPort<MidiBuffer>* patch_port)
: DriverPort(patch_port->is_input()),
Raul::ListNode<AlsaMidiPort*>(this),
_driver(driver),
diff --git a/src/libs/engine/AlsaMidiDriver.h b/src/libs/engine/AlsaMidiDriver.h
index 85d975b9..6c6debee 100644
--- a/src/libs/engine/AlsaMidiDriver.h
+++ b/src/libs/engine/AlsaMidiDriver.h
@@ -31,7 +31,7 @@ class Node;
class SetPortValueEvent;
class AlsaMidiDriver;
class AudioDriver;
-template <typename T> class DuplexPort;
+class DuplexPort;
static const int MAX_MIDI_EVENT_SIZE = 3;
@@ -43,7 +43,7 @@ static const int MAX_MIDI_EVENT_SIZE = 3;
class AlsaMidiPort : public DriverPort, public Raul::ListNode<AlsaMidiPort*>
{
public:
- AlsaMidiPort(AlsaMidiDriver* driver, DuplexPort<MidiMessage>* port);
+ AlsaMidiPort(AlsaMidiDriver* driver, DuplexPort<MidiBuffer>* port);
virtual ~AlsaMidiPort();
void event(snd_seq_event_t* const ev);
@@ -53,11 +53,11 @@ public:
void set_name(const std::string& name);
int port_id() const { return _port_id; }
- DuplexPort<MidiMessage>* patch_port() const { return _patch_port; }
+ DuplexPort<MidiBuffer>* patch_port() const { return _patch_port; }
private:
AlsaMidiDriver* _driver;
- DuplexPort<MidiMessage>* _patch_port;
+ DuplexPort<MidiBuffer>* _patch_port;
int _port_id;
unsigned char** _midi_pool; ///< Pool of raw MIDI events for MidiMessage::buffer
Raul::SRSWQueue<snd_seq_event_t> _events;
@@ -86,7 +86,7 @@ public:
AudioDriver* audio_driver() { return _audio_driver; }
- DriverPort* create_port(DuplexPort<MidiMessage>* patch_port)
+ DriverPort* create_port(DuplexPort<MidiBuffer>* patch_port)
{ return new AlsaMidiPort(this, patch_port); }
void add_port(DriverPort* port);
diff --git a/src/libs/engine/Buffer.cpp b/src/libs/engine/AudioBuffer.cpp
index 78b77635..525f0b41 100644
--- a/src/libs/engine/Buffer.cpp
+++ b/src/libs/engine/AudioBuffer.cpp
@@ -15,11 +15,10 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "Buffer.h"
#include <iostream>
#include <cassert>
#include <stdlib.h>
-#include "MidiMessage.h"
+#include "AudioBuffer.h"
using std::cerr; using std::endl;
/* TODO: Be sure these functions are vectorized by GCC when it's vectorizer
@@ -28,37 +27,34 @@ using std::cerr; using std::endl;
namespace Ingen {
-template <typename T>
-Buffer<T>::Buffer(size_t size)
-: _data(NULL),
- _local_data(NULL),
- _joined_buf(NULL),
- _size(size),
- _filled_size(0),
- _state(OK),
- _set_value(0)
+AudioBuffer::AudioBuffer(size_t size)
+ : Buffer(DataType::FLOAT, size)
+ , _data(NULL)
+ , _local_data(NULL)
+ , _joined_buf(NULL)
+ , _size(size)
+ , _filled_size(0)
+ , _state(OK)
+ , _set_value(0)
{
assert(_size > 0);
allocate();
assert(data());
}
-template Buffer<Sample>::Buffer(size_t size);
-template Buffer<MidiMessage>::Buffer(size_t size);
-template<typename T>
void
-Buffer<T>::resize(size_t size)
+AudioBuffer::resize(size_t size)
{
_size = size;
- T* const old_data = _data;
+ Sample* const old_data = _data;
const bool using_local_data = (_data == _local_data);
deallocate();
- const int ret = posix_memalign((void**)&_local_data, 16, _size * sizeof(T));
+ const int ret = posix_memalign((void**)&_local_data, 16, _size * sizeof(Sample));
if (ret != 0) {
cerr << "[Buffer] Failed to allocate buffer. Aborting." << endl;
exit(EXIT_FAILURE);
@@ -74,21 +70,18 @@ Buffer<T>::resize(size_t size)
set(0, 0, _size-1);
}
-template void Buffer<Sample>::resize(size_t size);
-template void Buffer<MidiMessage>::resize(size_t size);
/** Allocate and use a locally managed buffer (data).
*/
-template<typename T>
void
-Buffer<T>::allocate()
+AudioBuffer::allocate()
{
assert(!_joined_buf);
assert(_local_data == NULL);
assert(_size > 0);
- const int ret = posix_memalign((void**)&_local_data, 16, _size * sizeof(T));
+ const int ret = posix_memalign((void**)&_local_data, 16, _size * sizeof(Sample));
if (ret != 0) {
cerr << "[Buffer] Failed to allocate buffer. Aborting." << endl;
exit(EXIT_FAILURE);
@@ -101,37 +94,29 @@ Buffer<T>::allocate()
set(0, 0, _size-1);
}
-template void Buffer<Sample>::allocate();
-template void Buffer<MidiMessage>::allocate();
/** Free locally allocated buffer.
*/
-template<typename T>
void
-Buffer<T>::deallocate()
+AudioBuffer::deallocate()
{
assert(!_joined_buf);
free(_local_data);
_local_data = NULL;
_data = NULL;
}
-template void Buffer<Sample>::deallocate();
-template void Buffer<MidiMessage>::deallocate();
/** Empty (ie zero) the buffer.
*/
-template<typename T>
void
-Buffer<T>::clear()
+AudioBuffer::clear()
{
set(0, 0, _size-1);
_state = OK;
_filled_size = 0;
}
-template void Buffer<Sample>::clear();
-template void Buffer<MidiMessage>::clear();
/** Set value of buffer to @a val after @a start_sample.
@@ -140,9 +125,8 @@ template void Buffer<MidiMessage>::clear();
* value on the next cycle automatically (if @a start_sample is > 0), as
* long as pre_process() is called every cycle.
*/
-template <typename T>
void
-Buffer<T>::set(T val, size_t start_sample)
+AudioBuffer::set(Sample val, size_t start_sample)
{
assert(start_sample < _size);
@@ -153,49 +137,42 @@ Buffer<T>::set(T val, size_t start_sample)
_set_value = val;
}
-template void Buffer<Sample>::set(Sample val, size_t start_sample);
-template void Buffer<MidiMessage>::set(MidiMessage val, size_t start_sample);
/** Set a block of buffer to @a val.
*
* @a start_sample and @a end_sample define the inclusive range to be set.
*/
-template <typename T>
void
-Buffer<T>::set(T val, size_t start_sample, size_t end_sample)
+AudioBuffer::set(Sample val, size_t start_sample, size_t end_sample)
{
assert(end_sample >= start_sample);
assert(end_sample < _size);
- T* const buf = data();
+ Sample* const buf = data();
assert(buf);
for (size_t i=start_sample; i <= end_sample; ++i)
buf[i] = val;
}
-template void Buffer<Sample>::set(Sample val, size_t start_sample, size_t end_sample);
-template void Buffer<MidiMessage>::set(MidiMessage val, size_t start_sample, size_t end_sample);
/** Scale a block of buffer by @a val.
*
* @a start_sample and @a end_sample define the inclusive range to be set.
*/
-template <typename T>
void
-Buffer<T>::scale(T val, size_t start_sample, size_t end_sample)
+AudioBuffer::scale(Sample val, size_t start_sample, size_t end_sample)
{
assert(end_sample >= start_sample);
assert(end_sample < _size);
- T* const buf = data();
+ Sample* const buf = data();
assert(buf);
for (size_t i=start_sample; i <= end_sample; ++i)
buf[i] *= val;
}
-template void Buffer<Sample>::scale(Sample val, size_t start_sample, size_t end_sample);
/** Copy a block of @a src into buffer.
@@ -203,25 +180,22 @@ template void Buffer<Sample>::scale(Sample val, size_t start_sample, size_t end_
* @a start_sample and @a end_sample define the inclusive range to be set.
* This function only copies the same range in one buffer to another.
*/
-template <typename T>
void
-Buffer<T>::copy(const Buffer<T>* src, size_t start_sample, size_t end_sample)
+AudioBuffer::copy(const AudioBuffer* src, size_t start_sample, size_t end_sample)
{
assert(end_sample >= start_sample);
assert(end_sample < _size);
assert(src);
- T* const buf = data();
+ Sample* const buf = data();
assert(buf);
- const T* const src_buf = src->data();
+ const Sample* const src_buf = src->data();
assert(src_buf);
for (size_t i=start_sample; i <= end_sample; ++i)
buf[i] = src_buf[i];
}
-template void Buffer<Sample>::copy(const Buffer<Sample>* const src, size_t start_sample, size_t end_sample);
-template void Buffer<MidiMessage>::copy(const Buffer<MidiMessage>* const src, size_t start_sample, size_t end_sample);
/** Accumulate a block of @a src into @a dst.
@@ -229,60 +203,68 @@ template void Buffer<MidiMessage>::copy(const Buffer<MidiMessage>* const src, si
* @a start_sample and @a end_sample define the inclusive range to be accumulated.
* This function only adds the same range in one buffer to another.
*/
-template <typename T>
void
-Buffer<T>::accumulate(const Buffer<T>* const src, size_t start_sample, size_t end_sample)
+AudioBuffer::accumulate(const AudioBuffer* const src, size_t start_sample, size_t end_sample)
{
assert(end_sample >= start_sample);
assert(end_sample < _size);
assert(src);
- T* const buf = data();
+ Sample* const buf = data();
assert(buf);
- const T* const src_buf = src->data();
+ const Sample* const src_buf = src->data();
assert(src_buf);
for (size_t i=start_sample; i <= end_sample; ++i)
buf[i] += src_buf[i];
}
-template void Buffer<Sample>::accumulate(const Buffer<Sample>* const src, size_t start_sample, size_t end_sample);
/** Use another buffer's data instead of the local one.
*
* This buffer will essentially be identical to @a buf after this call.
*/
-template<typename T>
-void
-Buffer<T>::join(Buffer<T>* buf)
+bool
+AudioBuffer::join(Buffer* buf)
{
- assert(buf->size() == _size);
+ AudioBuffer* abuf = dynamic_cast<AudioBuffer*>(buf);
+ if (!abuf)
+ return false;
+
+ assert(abuf->size() == _size);
- _joined_buf = buf;
- _filled_size = buf->filled_size();
+ _joined_buf = abuf;
+ _filled_size = abuf->filled_size();
assert(_filled_size <= _size);
+
+ return true;
}
-template void Buffer<Sample>::join(Buffer<Sample>* buf);
-template void Buffer<MidiMessage>::join(Buffer<MidiMessage>* buf);
-template<typename T>
void
-Buffer<T>::unjoin()
+AudioBuffer::unjoin()
{
_joined_buf = NULL;
_data = _local_data;
}
-template void Buffer<Sample>::unjoin();
-template void Buffer<MidiMessage>::unjoin();
-template<>
+bool
+AudioBuffer::is_joined_to(Buffer* buf) const
+{
+ AudioBuffer* abuf = dynamic_cast<AudioBuffer*>(buf);
+ if (abuf)
+ return (data() == abuf->data());
+
+ return false;
+}
+
+
void
-Buffer<Sample>::prepare(SampleCount nframes)
+AudioBuffer::prepare(SampleCount nframes)
{
// FIXME: nframes parameter doesn't actually work,
// writing starts from 0 every time
@@ -302,27 +284,17 @@ Buffer<Sample>::prepare(SampleCount nframes)
}
-template<>
-void
-Buffer<MidiMessage>::prepare(SampleCount nframes)
-{
-}
-
-
/** Set the buffer (data) used.
*
* This is only to be used by Drivers (to provide zero-copy processing).
*/
-template<typename T>
void
-Buffer<T>::set_data(T* buf)
+AudioBuffer::set_data(Sample* buf)
{
assert(buf);
assert(!_joined_buf);
_data = buf;
}
-template void Buffer<Sample>::set_data(Sample* data);
-template void Buffer<MidiMessage>::set_data(MidiMessage* data);
} // namespace Ingen
diff --git a/src/libs/engine/AudioBuffer.h b/src/libs/engine/AudioBuffer.h
new file mode 100644
index 00000000..fa946108
--- /dev/null
+++ b/src/libs/engine/AudioBuffer.h
@@ -0,0 +1,82 @@
+/* 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 AUDIOBUFFER_H
+#define AUDIOBUFFER_H
+
+#include <cstddef>
+#include <cassert>
+#include <boost/utility.hpp>
+#include "types.h"
+#include "Buffer.h"
+
+namespace Ingen {
+
+
+class AudioBuffer : public Buffer
+{
+public:
+ AudioBuffer(size_t capacity);
+
+ void clear();
+ void set(Sample val, size_t start_sample);
+ void set(Sample val, size_t start_sample, size_t end_sample);
+ void scale(Sample val, size_t start_sample, size_t end_sample);
+ void copy(const AudioBuffer* src, size_t start_sample, size_t end_sample);
+ void accumulate(const AudioBuffer* src, size_t start_sample, size_t end_sample);
+
+ bool join(Buffer* buf);
+ void unjoin();
+ bool is_joined_to(Buffer* buf) const;
+
+ /** For driver use only!! */
+ void set_data(Sample* data);
+
+ inline Sample* data() const
+ { return ((_joined_buf != NULL) ? _joined_buf->data() : _data); }
+
+ inline Sample& value_at(size_t offset) const
+ { assert(offset < _size); return data()[offset]; }
+
+ void prepare(SampleCount nframes);
+
+ void filled_size(size_t size) { _filled_size = size; }
+ size_t filled_size() const { return _filled_size; }
+ bool is_joined() const { return (_joined_buf == NULL); }
+ size_t size() const { return _size; }
+
+ void resize(size_t size);
+
+private:
+ enum State { OK, HALF_SET_CYCLE_1, HALF_SET_CYCLE_2 };
+
+ void allocate();
+ void deallocate();
+
+ Sample* _data; ///< Used data pointer (probably same as _local_data)
+ Sample* _local_data; ///< Locally allocated buffer (possibly unused if joined or set_data used)
+ AudioBuffer* _joined_buf; ///< Buffer to mirror, if joined
+ size_t _size; ///< Allocated buffer size
+ size_t _filled_size; ///< Usable buffer size (for MIDI ports etc)
+ State _state; ///< State of buffer for setting values next cycle
+ Sample _set_value; ///< Value set by @ref set (may need to be set next cycle)
+};
+
+
+} // namespace Ingen
+
+#endif // AUDIOBUFFER_H
diff --git a/src/libs/engine/AudioDriver.h b/src/libs/engine/AudioDriver.h
index 9128c2ed..d9807939 100644
--- a/src/libs/engine/AudioDriver.h
+++ b/src/libs/engine/AudioDriver.h
@@ -18,25 +18,27 @@
#ifndef AUDIODRIVER_H
#define AUDIODRIVER_H
-#include "Driver.h"
-#include "types.h"
#include <raul/List.h>
#include <raul/Path.h>
+#include "Driver.h"
+#include "types.h"
+#include "DataType.h"
namespace Ingen {
class Patch;
class AudioDriver;
-template <typename T> class TypedPort;
+class Port;
/** Audio driver abstract base class.
*
* \ingroup engine
*/
-class AudioDriver : public Driver<Sample>
+class AudioDriver : public Driver
{
public:
+ AudioDriver() : Driver(DataType::FLOAT) {}
virtual void set_root_patch(Patch* patch) = 0;
virtual Patch* root_patch() = 0;
diff --git a/src/libs/engine/Buffer.h b/src/libs/engine/Buffer.h
index 3491b799..ee94b786 100644
--- a/src/libs/engine/Buffer.h
+++ b/src/libs/engine/Buffer.h
@@ -20,55 +20,39 @@
#include <cstddef>
#include <cassert>
+#include <boost/utility.hpp>
#include "types.h"
+#include "DataType.h"
namespace Ingen {
-template <typename T>
-class Buffer
+class Buffer : public boost::noncopyable
{
public:
- Buffer(size_t size);
+ Buffer(DataType type, size_t size)
+ : _type(type)
+ , _size(size)
+ {}
- void clear();
- void set(T val, size_t start_sample);
- void set(T val, size_t start_sample, size_t end_sample);
- void scale(T val, size_t start_sample, size_t end_sample);
- void copy(const Buffer<T>* src, size_t start_sample, size_t end_sample);
- void accumulate(const Buffer<T>* src, size_t start_sample, size_t end_sample);
+ virtual ~Buffer() {}
- void join(Buffer* buf);
- void unjoin();
+ virtual void clear() = 0;
+ virtual void prepare(SampleCount nframes) = 0;
- /** For driver use only!! */
- void set_data(T* data);
-
- inline T& value_at(size_t offset) { assert(offset < _size); return data()[offset]; }
-
- void prepare(SampleCount nframes);
-
- void filled_size(size_t size) { _filled_size = size; }
- size_t filled_size() const { return _filled_size; }
- bool is_joined() const { return (_joined_buf == NULL); }
- size_t size() const { return _size; }
- inline T* data() const { return ((_joined_buf != NULL) ? _joined_buf->data() : _data); }
-
- void resize(size_t size);
+ virtual bool is_joined() const = 0;
+ virtual bool is_joined_to(Buffer* buf) const = 0;
+ virtual bool join(Buffer* buf) = 0;
+ virtual void unjoin() = 0;
-private:
- enum BufferState { OK, HALF_SET_CYCLE_1, HALF_SET_CYCLE_2 };
+ virtual void resize(size_t size) { _size = size; }
- void allocate();
- void deallocate();
+ DataType type() const { return _type; }
+ size_t size() const { return _size; }
- T* _data; ///< Used data pointer (probably same as _local_data)
- T* _local_data; ///< Locally allocated buffer (possibly unused if joined or set_data used)
- Buffer<T>* _joined_buf; ///< Buffer to mirror, if joined
- size_t _size; ///< Allocated buffer size
- size_t _filled_size; ///< Usable buffer size (for MIDI ports etc)
- BufferState _state; ///< State of buffer for setting values next cycle
- T _set_value; ///< Value set by @ref set (may need to be set next cycle)
+protected:
+ DataType _type;
+ size_t _size;
};
diff --git a/src/libs/engine/BufferFactory.cpp b/src/libs/engine/BufferFactory.cpp
new file mode 100644
index 00000000..f2761f08
--- /dev/null
+++ b/src/libs/engine/BufferFactory.cpp
@@ -0,0 +1,39 @@
+/* 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 "BufferFactory.h"
+#include "AudioBuffer.h"
+#include "MidiBuffer.h"
+
+namespace Ingen {
+namespace BufferFactory {
+
+
+Buffer*
+create(DataType type, size_t size)
+{
+ if (type == DataType::FLOAT)
+ return new AudioBuffer(size);
+ else if (type == DataType::MIDI)
+ return new MidiBuffer(size);
+ else
+ return NULL;
+}
+
+
+} // namespace BufferFactory
+} // namespace Ingen
diff --git a/src/libs/engine/BufferFactory.h b/src/libs/engine/BufferFactory.h
new file mode 100644
index 00000000..1887c27c
--- /dev/null
+++ b/src/libs/engine/BufferFactory.h
@@ -0,0 +1,35 @@
+/* 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 BUFFERFACTORY_H
+#define BUFFERFACTORY_H
+
+#include "Buffer.h"
+
+namespace Ingen {
+
+
+namespace BufferFactory {
+
+ Buffer* create(DataType type, size_t size);
+
+}
+
+
+} // namespace Ingen
+
+#endif // BUFFERFACTORY_H
diff --git a/src/libs/engine/ClientBroadcaster.cpp b/src/libs/engine/ClientBroadcaster.cpp
index 0c66575c..f0205d9f 100644
--- a/src/libs/engine/ClientBroadcaster.cpp
+++ b/src/libs/engine/ClientBroadcaster.cpp
@@ -25,7 +25,7 @@
#include "Patch.h"
#include "Node.h"
#include "Plugin.h"
-#include "TypedPort.h"
+#include "Port.h"
#include "Connection.h"
#include "AudioDriver.h"
#include "ObjectSender.h"
diff --git a/src/libs/engine/Connection.cpp b/src/libs/engine/Connection.cpp
index 1f5e0d21..992496c2 100644
--- a/src/libs/engine/Connection.cpp
+++ b/src/libs/engine/Connection.cpp
@@ -19,6 +19,8 @@
#include "util.h"
#include "Node.h"
#include "Port.h"
+#include "BufferFactory.h"
+#include "AudioBuffer.h"
namespace Ingen {
@@ -28,17 +30,82 @@ namespace Ingen {
* This handles both polyphonic and monophonic nodes, transparently to the
* user (InputPort).
*/
-Connection::Connection(Port* const src_port, Port* const dst_port)
-: _src_port(src_port),
- _dst_port(dst_port),
- _pending_disconnection(false)
+Connection::Connection(Port* src_port, Port* dst_port)
+ : _src_port(src_port)
+ , _dst_port(dst_port)
+ , _local_buffer(NULL)
+ , _buffer_size(dst_port->buffer_size())
+ , _must_mix(src_port->poly() != dst_port->poly())
+ , _pending_disconnection(false)
{
- assert(src_port != NULL);
- assert(dst_port != NULL);
+ assert(src_port);
+ assert(dst_port);
+ assert(src_port->type() == dst_port->type());
assert((src_port->parent_node()->poly() == dst_port->parent_node()->poly())
|| (src_port->parent_node()->poly() == 1 || dst_port->parent_node()->poly() == 1));
+
+ if (_must_mix)
+ _local_buffer = BufferFactory::create(dst_port->type(), dst_port->buffer(0)->size());
+}
+
+
+Connection::~Connection()
+{
+ delete _local_buffer;
}
+
+
+void
+Connection::set_buffer_size(size_t size)
+{
+ if (_must_mix) {
+ assert(_local_buffer);
+ delete _local_buffer;
+
+ _local_buffer = BufferFactory::create(_dst_port->type(), _dst_port->buffer(0)->size());
+ }
+
+ _buffer_size = size;
+}
+
+
+void
+Connection::process(SampleCount nframes, FrameTime start, FrameTime end)
+{
+ // FIXME: nframes parameter not used
+ assert(_buffer_size == 1 || _buffer_size == nframes);
+
+ /* Thought: A poly output port can be connected to multiple mono input
+ * ports, which means this mix down would have to happen many times.
+ * Adding a method to OutputPort that mixes down all it's outputs into
+ * a buffer (if it hasn't been done already this cycle) and returns that
+ * would avoid having to mix multiple times. Probably not a very common
+ * case, but it would be faster anyway. */
+
+ // FIXME: Implement MIDI mixing
+
+ if (_must_mix) {
+ assert(type() == DataType::FLOAT);
+
+ AudioBuffer* mix_buf = (AudioBuffer*)_local_buffer;
+
+ //cerr << "Mixing " << src_port()->buffer(0)->data()
+ // << " -> " << _local_buffer->data() << endl;
+
+ mix_buf->copy((AudioBuffer*)src_port()->buffer(0), 0, _buffer_size-1);
+
+ // Mix all the source's voices down into local buffer starting at the second
+ // voice (buffer is already set to first voice above)
+ for (size_t j=1; j < src_port()->poly(); ++j)
+ mix_buf->accumulate((AudioBuffer*)src_port()->buffer(j), 0, _buffer_size-1);
+
+ // Scale the buffer down.
+ if (src_port()->poly() > 1)
+ mix_buf->scale(1.0f/(float)src_port()->poly(), 0, _buffer_size-1);
+ }
+}
+
} // namespace Ingen
diff --git a/src/libs/engine/Connection.h b/src/libs/engine/Connection.h
index a7a2b3fa..7d109d88 100644
--- a/src/libs/engine/Connection.h
+++ b/src/libs/engine/Connection.h
@@ -21,11 +21,14 @@
#include <cstdlib>
#include <boost/utility.hpp>
#include <raul/Deletable.h>
+#include "DataType.h"
+#include "Port.h"
#include "types.h"
namespace Ingen {
class Port;
+class Buffer;
/** Represents a single inbound connection for an InputPort.
@@ -41,7 +44,8 @@ class Port;
class Connection : public Raul::Deletable
{
public:
- virtual ~Connection() {}
+ Connection(Port* src_port, Port* dst_port);
+ virtual ~Connection();
Port* src_port() const { return _src_port; }
Port* dst_port() const { return _dst_port; }
@@ -50,17 +54,41 @@ public:
bool pending_disconnection() { return _pending_disconnection; }
void pending_disconnection(bool b) { _pending_disconnection = b; }
- virtual void set_buffer_size(size_t size) {}
+ void process(SampleCount nframes, FrameTime start, FrameTime end);
-protected:
- Connection(Port* const src_port, Port* const dst_port);
+ /** Get the buffer for a particular voice.
+ * A Connection is smart - it knows the destination port requesting the
+ * buffer, and will return accordingly (ie the same buffer for every voice
+ * in a mono->poly connection).
+ */
+ inline Buffer* buffer(size_t voice) const;
+ void set_buffer_size(size_t size);
+
+ DataType type() const { return _src_port->type(); }
+
+protected:
Port* const _src_port;
Port* const _dst_port;
+ Buffer* _local_buffer;
+ size_t _buffer_size;
+ bool _must_mix;
bool _pending_disconnection;
};
+inline Buffer*
+Connection::buffer(size_t voice) const
+{
+ if (_must_mix)
+ return _local_buffer;
+ else if (_src_port->poly() == 1)
+ return _src_port->buffer(0);
+ else
+ return _src_port->buffer(voice);
+}
+
+
} // namespace Ingen
#endif // CONNECTION_H
diff --git a/src/libs/engine/DSSINode.cpp b/src/libs/engine/DSSINode.cpp
index 6f00af0c..5a23baba 100644
--- a/src/libs/engine/DSSINode.cpp
+++ b/src/libs/engine/DSSINode.cpp
@@ -22,6 +22,7 @@
#include "interface/ClientInterface.h"
#include "InputPort.h"
#include "types.h"
+#include "AudioBuffer.h"
using namespace std;
@@ -63,7 +64,7 @@ DSSINode::instantiate()
if (has_midi_input()) {
_ports = new Raul::Array<Port*>(_descriptor->PortCount + 1);
- _midi_in_port = new InputPort<MidiMessage>(this, "MIDIIn", _ports->size()-1, 1, DataType::MIDI, _buffer_size);
+ _midi_in_port = new InputPort(this, "MIDIIn", _ports->size()-1, 1, DataType::MIDI, _buffer_size);
_ports->at(_ports->size()-1) = _midi_in_port;
}
@@ -108,7 +109,8 @@ void
DSSINode::set_control(size_t port_num, Sample val)
{
assert(port_num < _descriptor->PortCount);
- ((TypedPort<Sample>*)_ports->at(port_num))->set_value(val, 0);
+ cerr << "FIXME: set_control\n";
+ //((TypedPort<Sample>*)_ports->at(port_num))->set_value(val, 0);
}
@@ -137,7 +139,7 @@ DSSINode::convert_events()
{
assert(has_midi_input());
assert(_midi_in_port != NULL);
-
+#if 0
Buffer<MidiMessage>& buffer = *_midi_in_port->buffer(0);
_encoded_events = 0;
@@ -149,6 +151,7 @@ DSSINode::convert_events()
if (_alsa_events[_encoded_events].type != SND_SEQ_EVENT_NONE)
++_encoded_events;
}
+#endif
}
@@ -242,7 +245,7 @@ DSSINode::send_update()
// send "control"s
for (size_t i=0; i < _ports->size(); ++i)
if (_ports->at(i)->type() == DataType::FLOAT && _ports->at(i)->buffer_size() == 1)
- send_control(_ports->at(i)->num(), ((TypedPort<Sample>*)_ports->at(i))->buffer(0)->value_at(0));
+ send_control(_ports->at(i)->num(), ((AudioBuffer*)_ports->at(i)->buffer(0))->value_at(0));
// send "show" FIXME: not to spec
send_show();
diff --git a/src/libs/engine/DSSINode.h b/src/libs/engine/DSSINode.h
index 2521693e..9070410e 100644
--- a/src/libs/engine/DSSINode.h
+++ b/src/libs/engine/DSSINode.h
@@ -22,11 +22,11 @@
#include <dssi.h>
#include <lo/lo.h>
#include "LADSPANode.h"
+#include "MidiBuffer.h"
namespace Ingen {
-class MidiMessage;
-template <typename T> class InputPort;
+class InputPort;
namespace Shared {
class ClientInterface;
} using Shared::ClientInterface;
@@ -71,7 +71,7 @@ private:
// DSSI GUI messages
void send_control(int port_num, float value);
void send_program(int bank, int value);
- void send_configure(const string& key, const string& val);
+ void send_configure(const std::string& key, const std::string& val);
void send_show();
void send_hide();
void send_quit();
@@ -82,20 +82,20 @@ private:
DSSI_Descriptor* _dssi_descriptor;
- string _ui_url;
- string _ui_base_path;
- lo_address _ui_addr;
+ std::string _ui_url;
+ std::string _ui_base_path;
+ lo_address _ui_addr;
// Current values
- int _bank;
- int _program;
- std::map<string, string> _configures;
- std::map<int, Bank> _banks;
-
- InputPort<MidiMessage>* _midi_in_port;
- snd_seq_event_t* _alsa_events;
- unsigned long _encoded_events;
- snd_midi_event_t* _alsa_encoder;
+ int _bank;
+ int _program;
+ std::map<std::string, std::string> _configures;
+ std::map<int, Bank> _banks;
+
+ InputPort* _midi_in_port;
+ snd_seq_event_t* _alsa_events;
+ unsigned long _encoded_events;
+ snd_midi_event_t* _alsa_encoder;
};
diff --git a/src/libs/engine/DataType.h b/src/libs/engine/DataType.h
index 62cec1af..469c48d8 100644
--- a/src/libs/engine/DataType.h
+++ b/src/libs/engine/DataType.h
@@ -36,10 +36,10 @@ public:
MIDI = 2
};
- DataType(const string& uri)
+ DataType(const std::string& uri)
: _symbol(UNKNOWN)
{
- if (uri== type_uris[MIDI]) {
+ if (uri == type_uris[MIDI]) {
_symbol = MIDI;
} else if (uri == type_uris[FLOAT]) {
_symbol = FLOAT;
diff --git a/src/libs/engine/Driver.h b/src/libs/engine/Driver.h
index 6cbfbdff..fbddc828 100644
--- a/src/libs/engine/Driver.h
+++ b/src/libs/engine/Driver.h
@@ -21,10 +21,11 @@
#include <string>
#include <boost/utility.hpp>
#include "raul/Path.h"
+#include "DataType.h"
namespace Ingen {
-template <typename T> class DuplexPort;
+class DuplexPort;
/** Representation of a "system" (eg outside Ingen) port.
@@ -58,15 +59,15 @@ protected:
* interface for managing system ports. An implementation of Driver basically
* needs to manage DriverPorts, and handle writing/reading data to/from them.
*
- * The template parameter T is the type of data this driver manages (ie the
- * data type of the bridge ports it will handle).
- *
* \ingroup engine
*/
-template <typename T>
class Driver : boost::noncopyable
{
public:
+ Driver(DataType type)
+ : _type(type)
+ {}
+
virtual ~Driver() {}
virtual void activate() = 0;
@@ -78,10 +79,13 @@ public:
*
* May return NULL if the Driver can not drive the port for some reason.
*/
- virtual DriverPort* create_port(DuplexPort<T>* patch_port) = 0;
+ virtual DriverPort* create_port(DuplexPort* patch_port) = 0;
virtual void add_port(DriverPort* port) = 0;
virtual DriverPort* remove_port(const Raul::Path& path) = 0;
+
+protected:
+ DataType _type;
};
diff --git a/src/libs/engine/DuplexPort.cpp b/src/libs/engine/DuplexPort.cpp
index 189e0d30..f4a71aae 100644
--- a/src/libs/engine/DuplexPort.cpp
+++ b/src/libs/engine/DuplexPort.cpp
@@ -19,7 +19,7 @@
#include <iostream>
#include <cstdlib>
#include <cassert>
-#include "TypedConnection.h"
+#include "Connection.h"
#include "OutputPort.h"
#include "Node.h"
#include "util.h"
@@ -30,17 +30,14 @@ using std::cerr; using std::cout; using std::endl;
namespace Ingen {
-template <typename T>
-DuplexPort<T>::DuplexPort(Node* parent, const string& name, size_t index, size_t poly, DataType type, size_t buffer_size, bool is_output)
-: TypedPort<T>(parent, name, index, poly, type, buffer_size)
-, InputPort<T>(parent, name, index, poly, type, buffer_size)
-, OutputPort<T>(parent, name, index, poly, type, buffer_size)
+DuplexPort::DuplexPort(Node* parent, const string& name, size_t index, size_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)
{
- assert(TypedPort<T>::_parent == parent);
+ assert(Port::_parent == parent);
}
-template DuplexPort<Sample>::DuplexPort(Node* parent, const string& name, size_t index, size_t poly, DataType type, size_t buffer_size, bool is_output);
-template DuplexPort<MidiMessage>::DuplexPort(Node* parent, const string& name, size_t index, size_t poly, DataType type, size_t buffer_size, bool is_output);
} // namespace Ingen
diff --git a/src/libs/engine/DuplexPort.h b/src/libs/engine/DuplexPort.h
index 1c4e738d..10c305b4 100644
--- a/src/libs/engine/DuplexPort.h
+++ b/src/libs/engine/DuplexPort.h
@@ -28,7 +28,6 @@ using std::string;
namespace Ingen {
-class MidiMessage;
class Node;
@@ -40,8 +39,7 @@ class Node;
*
* \ingroup engine
*/
-template <typename T>
-class DuplexPort : public InputPort<T>, public OutputPort<T>
+class DuplexPort : public InputPort, public OutputPort
{
public:
DuplexPort(Node* parent, const string& name, size_t index, size_t poly, DataType type, size_t buffer_size, bool is_output);
@@ -57,9 +55,6 @@ protected:
};
-template class DuplexPort<Sample>;
-template class DuplexPort<MidiMessage>;
-
} // namespace Ingen
#endif // DUPLEXPORT_H
diff --git a/src/libs/engine/Engine.cpp b/src/libs/engine/Engine.cpp
index 387714f8..053528ff 100644
--- a/src/libs/engine/Engine.cpp
+++ b/src/libs/engine/Engine.cpp
@@ -88,16 +88,16 @@ Engine::~Engine()
}
-/* driver() template specializations.
- * Due to the lack of RTTI, this needs to be implemented manually like this.
- * If more types/drivers start getting added, it may be worth it to enable
- * RTTI and put all the drivers into a map with typeid's as the key. That's
- * more elegant and extensible, but this is faster and simpler - for now.
- */
-template<>
-Driver<MidiMessage>* Engine::driver<MidiMessage>() { return _midi_driver; }
-template<>
-Driver<Sample>* Engine::driver<Sample>() { return _audio_driver.get(); }
+Driver*
+Engine::driver(DataType type)
+{
+ if (type == DataType::FLOAT)
+ return _audio_driver.get();
+ else if (type == DataType::MIDI)
+ return _midi_driver;
+ else
+ return NULL;
+}
int
diff --git a/src/libs/engine/Engine.h b/src/libs/engine/Engine.h
index 163adf68..38d638c3 100644
--- a/src/libs/engine/Engine.h
+++ b/src/libs/engine/Engine.h
@@ -21,6 +21,7 @@
#include <cassert>
#include <boost/utility.hpp>
#include <raul/SharedPtr.h>
+#include "DataType.h"
template<typename T> class Queue;
@@ -39,7 +40,7 @@ class PostProcessor;
class Event;
class QueuedEvent;
class LashDriver;
-template <typename T> class Driver;
+class Driver;
/** The main class for the Engine.
@@ -77,8 +78,8 @@ public:
NodeFactory* node_factory() const { return _node_factory; }
LashDriver* lash_driver() const { return _lash_driver; }
- /** Return the active driver for the given (template parameter) type */
- template<typename T> Driver<T>* driver();
+ /** Return the active driver for the given type */
+ Driver* driver(DataType type);
private:
SharedPtr<EventSource> _event_source;
diff --git a/src/libs/engine/InputPort.cpp b/src/libs/engine/InputPort.cpp
index 1a792c32..9326afd6 100644
--- a/src/libs/engine/InputPort.cpp
+++ b/src/libs/engine/InputPort.cpp
@@ -19,7 +19,8 @@
#include <iostream>
#include <cstdlib>
#include <cassert>
-#include "TypedConnection.h"
+#include "AudioBuffer.h"
+#include "Connection.h"
#include "OutputPort.h"
#include "Node.h"
#include "util.h"
@@ -30,13 +31,10 @@ using std::cerr; using std::cout; using std::endl;
namespace Ingen {
-template <typename T>
-InputPort<T>::InputPort(Node* parent, const string& name, size_t index, size_t poly, DataType type, size_t buffer_size)
-: TypedPort<T>(parent, name, index, poly, type, buffer_size)
+InputPort::InputPort(Node* parent, const string& name, size_t index, size_t poly, DataType type, size_t buffer_size)
+: Port(parent, name, index, poly, type, buffer_size)
{
}
-template InputPort<Sample>::InputPort(Node* parent, const string& name, size_t index, size_t poly, DataType type, size_t buffer_size);
-template InputPort<MidiMessage>::InputPort(Node* parent, const string& name, size_t index, size_t poly, DataType type, size_t buffer_size);
/** Add a connection. Realtime safe.
@@ -44,9 +42,8 @@ template InputPort<MidiMessage>::InputPort(Node* parent, const string& name, siz
* The buffer of this port will be set directly to the connection's buffer
* if there is only one connection, since no mixing needs to take place.
*/
-template<typename T>
void
-InputPort<T>::add_connection(Raul::ListNode<TypedConnection<T>*>* const c)
+InputPort::add_connection(Raul::ListNode<Connection*>* const c)
{
_connections.push_back(c);
@@ -61,7 +58,7 @@ InputPort<T>::add_connection(Raul::ListNode<TypedConnection<T>*>* const c)
_buffers.at(i)->join(c->elem()->buffer(i));
//if (_is_tied)
// _tied_port->buffer(i)->join(_buffers.at(i));
- assert(_buffers.at(i)->data() == c->elem()->buffer(i)->data());
+ //assert(_buffers.at(i)->data() == c->elem()->buffer(i)->data());
}
} else if (_connections.size() == 2) {
// Used to directly use single connection buffer, now there's two
@@ -72,30 +69,26 @@ InputPort<T>::add_connection(Raul::ListNode<TypedConnection<T>*>* const c)
// _tied_port->buffer(i)->join(_buffers.at(i));
}
}
- TypedPort<T>::connect_buffers();
+ Port::connect_buffers();
}
//assert( ! _is_tied || _tied_port != NULL);
//assert( ! _is_tied || _buffers.at(0)->data() == _tied_port->buffer(0)->data());
}
-template void InputPort<Sample>::add_connection(Raul::ListNode<TypedConnection<Sample>*>* const c);
-template void InputPort<MidiMessage>::add_connection(Raul::ListNode<TypedConnection<MidiMessage>*>* const c);
/** Remove a connection. Realtime safe.
*/
-template <typename T>
-Raul::ListNode<TypedConnection<T>*>*
-InputPort<T>::remove_connection(const OutputPort<T>* const src_port)
+Raul::ListNode<Connection*>*
+InputPort::remove_connection(const OutputPort* src_port)
{
bool modify_buffers = !_fixed_buffers;
//if (modify_buffers && _is_tied)
// modify_buffers = !_tied_port->fixed_buffers();
- typedef typename Raul::List<TypedConnection<T>*>::iterator TypedConnectionListIterator;
bool found = false;
- Raul::ListNode<TypedConnection<T>*>* connection = NULL;
- for (TypedConnectionListIterator i = _connections.begin(); i != _connections.end(); ++i) {
+ Raul::ListNode<Connection*>* connection = NULL;
+ for (Connections::iterator i = _connections.begin(); i != _connections.end(); ++i) {
if ((*i)->src_port()->path() == src_port->path()) {
connection = _connections.erase(i);
found = true;
@@ -103,7 +96,7 @@ InputPort<T>::remove_connection(const OutputPort<T>* const src_port)
}
if ( ! found) {
- cerr << "WARNING: [InputPort<T>::remove_connection] Connection not found !" << endl;
+ cerr << "WARNING: [InputPort::remove_connection] Connection not found !" << endl;
exit(EXIT_FAILURE);
} else {
if (_connections.size() == 0) {
@@ -126,63 +119,55 @@ InputPort<T>::remove_connection(const OutputPort<T>* const src_port)
}
if (modify_buffers)
- TypedPort<T>::connect_buffers();
+ Port::connect_buffers();
//assert( ! _is_tied || _tied_port != NULL);
//assert( ! _is_tied || _buffers.at(0)->data() == _tied_port->buffer(0)->data());
return connection;
}
-template Raul::ListNode<TypedConnection<Sample>*>*
-InputPort<Sample>::remove_connection(const OutputPort<Sample>* const src_port);
-template Raul::ListNode<TypedConnection<MidiMessage>*>*
-InputPort<MidiMessage>::remove_connection(const OutputPort<MidiMessage>* const src_port);
/** Returns whether this port is connected to the passed port.
*/
-template <typename T>
bool
-InputPort<T>::is_connected_to(const OutputPort<T>* const port) const
+InputPort::is_connected_to(const OutputPort* port) const
{
- typedef typename Raul::List<TypedConnection<T>*>::const_iterator TypedConnectionListIterator;
- for (TypedConnectionListIterator i = _connections.begin(); i != _connections.end(); ++i)
+ for (Connections::const_iterator i = _connections.begin(); i != _connections.end(); ++i)
if ((*i)->src_port() == port)
return true;
return false;
}
-template bool InputPort<Sample>::is_connected_to(const OutputPort<Sample>* const port) const;
-template bool InputPort<MidiMessage>::is_connected_to(const OutputPort<MidiMessage>* const port) const;
/** Prepare buffer for access, mixing if necessary. Realtime safe.
* FIXME: nframes parameter not used,
*/
-template<>
void
-InputPort<Sample>::process(SampleCount nframes, FrameTime start, FrameTime end)
+InputPort::process(SampleCount nframes, FrameTime start, FrameTime end)
{
+ Port::process(nframes, start, end);
+
//assert(!_is_tied || _tied_port != NULL);
- typedef Raul::List<TypedConnection<Sample>*>::iterator TypedConnectionListIterator;
bool do_mixdown = true;
if (_connections.size() == 0) return;
- for (TypedConnectionListIterator c = _connections.begin(); c != _connections.end(); ++c)
+ for (Connections::iterator c = _connections.begin(); c != _connections.end(); ++c)
(*c)->process(nframes, start, end);
// If only one connection, buffer is (maybe) used directly (no copying)
if (_connections.size() == 1) {
// Buffer changed since connection
- if (_buffers.at(0)->data() != (*_connections.begin())->buffer(0)->data()) {
+ if (!_buffers.at(0)->is_joined_to((*_connections.begin())->buffer(0))) {
if (_fixed_buffers) { // || (_is_tied && _tied_port->fixed_buffers())) {
// can't change buffer, must copy
do_mixdown = true;
} else {
// zero-copy
- assert(_buffers.at(0)->is_joined());
+ //assert(_buffers.at(0)->is_joined());
_buffers.at(0)->join((*_connections.begin())->buffer(0));
do_mixdown = false;
}
@@ -195,7 +180,7 @@ InputPort<Sample>::process(SampleCount nframes, FrameTime start, FrameTime end)
//cerr << path() << " mixing: " << do_mixdown << endl;
if (!do_mixdown) {
- assert(_buffers.at(0)->data() == (*_connections.begin())->buffer(0)->data());
+ assert(_buffers.at(0)->is_joined_to((*_connections.begin())->buffer(0)));
return;
}
@@ -204,28 +189,30 @@ InputPort<Sample>::process(SampleCount nframes, FrameTime start, FrameTime end)
for (size_t voice=0; voice < _poly; ++voice) {
// Copy first connection
- _buffers.at(voice)->copy((*_connections.begin())->buffer(voice), 0, _buffer_size-1);
+ ((AudioBuffer*)_buffers.at(voice))->copy(
+ ((AudioBuffer*)(*_connections.begin())->buffer(voice)), 0, _buffer_size-1);
// Accumulate the rest
if (_connections.size() > 1) {
- TypedConnectionListIterator c = _connections.begin();
+ Connections::iterator c = _connections.begin();
for (++c; c != _connections.end(); ++c)
- _buffers.at(voice)->accumulate((*c)->buffer(voice), 0, _buffer_size-1);
+ ((AudioBuffer*)_buffers.at(voice))->accumulate(
+ ((AudioBuffer*)(*c)->buffer(voice)), 0, _buffer_size-1);
}
}
}
+#if 0
/** Prepare buffer for access, realtime safe.
*
* MIDI mixing not yet implemented.
*/
-template <>
void
-InputPort<MidiMessage>::process(SampleCount nframes, FrameTime start, FrameTime end)
-{
+InputPort<MidiBuffer>::process(SampleCount nframes, FrameTime start, FrameTime end)
+{
//assert(!_is_tied || _tied_port != NULL);
const size_t num_ins = _connections.size();
@@ -233,10 +220,9 @@ InputPort<MidiMessage>::process(SampleCount nframes, FrameTime start, FrameTime
assert(num_ins == 0 || num_ins == 1);
- typedef Raul::List<TypedConnection<MidiMessage>*>::iterator TypedConnectionListIterator;
assert(_poly == 1);
- for (TypedConnectionListIterator c = _connections.begin(); c != _connections.end(); ++c)
+ for (Connections::iterator c = _connections.begin(); c != _connections.end(); ++c)
(*c)->process(nframes, start, end);
@@ -298,21 +284,19 @@ InputPort<MidiMessage>::process(SampleCount nframes, FrameTime start, FrameTime
for (size_t i=0; i < _buffers.at(0)->filled_size(); ++i)
_buffers.at(0)[i] = (*_connections.begin())->buffer(0)[i];
}
+#endif
-template <typename T>
void
-InputPort<T>::set_buffer_size(size_t size)
+InputPort::set_buffer_size(size_t size)
{
- TypedPort<T>::set_buffer_size(size);
+ Port::set_buffer_size(size);
assert(_buffer_size = size);
- for (typename Raul::List<TypedConnection<T>*>::iterator c = _connections.begin(); c != _connections.end(); ++c)
+ for (Raul::List<Connection*>::iterator c = _connections.begin(); c != _connections.end(); ++c)
(*c)->set_buffer_size(size);
}
-template void InputPort<Sample>::set_buffer_size(size_t size);
-template void InputPort<MidiMessage>::set_buffer_size(size_t size);
} // namespace Ingen
diff --git a/src/libs/engine/InputPort.h b/src/libs/engine/InputPort.h
index 14efd605..284f976f 100644
--- a/src/libs/engine/InputPort.h
+++ b/src/libs/engine/InputPort.h
@@ -22,14 +22,14 @@
#include <cstdlib>
#include <cassert>
#include <raul/List.h>
-#include "TypedPort.h"
-#include "MidiMessage.h"
+#include "Port.h"
+#include "MidiBuffer.h"
using std::string;
namespace Ingen {
-template <typename T> class TypedConnection;
-template <typename T> class OutputPort;
+class Connection;
+class OutputPort;
class Node;
@@ -44,22 +44,22 @@ class Node;
*
* \ingroup engine
*/
-template <typename T>
-class InputPort : virtual public TypedPort<T>
+class InputPort : virtual public Port
{
public:
InputPort(Node* parent, const string& name, size_t index, size_t poly, DataType type, size_t buffer_size);
virtual ~InputPort() {}
- void add_connection(Raul::ListNode<TypedConnection<T>*>* const c);
- Raul::ListNode<TypedConnection<T>*>* remove_connection(const OutputPort<T>* const src_port);
+ void add_connection(Raul::ListNode<Connection*>* c);
+ Raul::ListNode<Connection*>* remove_connection(const OutputPort* src_port);
- const Raul::List<TypedConnection<T>*>& connections() { return _connections; }
+ typedef Raul::List<Connection*> Connections;
+ const Connections& connections() { return _connections; }
void process(SampleCount nframes, FrameTime start, FrameTime end);
bool is_connected() const { return (_connections.size() > 0); }
- bool is_connected_to(const OutputPort<T>* const port) const;
+ bool is_connected_to(const OutputPort* port) const;
bool is_input() const { return true; }
bool is_output() const { return false; }
@@ -67,21 +67,10 @@ public:
virtual void set_buffer_size(size_t size);
private:
-
- Raul::List<TypedConnection<T>*> _connections;
-
- // This is just stupid...
- using TypedPort<T>::_buffers;
- using TypedPort<T>::_poly;
- using TypedPort<T>::_index;
- using TypedPort<T>::_buffer_size;
- using TypedPort<T>::_fixed_buffers;
+ Connections _connections;
};
-template class InputPort<Sample>;
-template class InputPort<MidiMessage>;
-
} // namespace Ingen
#endif // INPUTPORT_H
diff --git a/src/libs/engine/JackAudioDriver.cpp b/src/libs/engine/JackAudioDriver.cpp
index df03dcb8..dd52d2b2 100644
--- a/src/libs/engine/JackAudioDriver.cpp
+++ b/src/libs/engine/JackAudioDriver.cpp
@@ -34,6 +34,7 @@
#include "MidiDriver.h"
#include "DuplexPort.h"
#include "EventSource.h"
+#include "AudioBuffer.h"
#ifdef HAVE_LASH
#include "LashDriver.h"
#endif
@@ -46,7 +47,7 @@ namespace Ingen {
//// JackAudioPort ////
-JackAudioPort::JackAudioPort(JackAudioDriver* driver, DuplexPort<Sample>* patch_port)
+JackAudioPort::JackAudioPort(JackAudioDriver* driver, DuplexPort* patch_port)
: DriverPort(patch_port->is_input()),
Raul::ListNode<JackAudioPort*>(this),
_driver(driver),
@@ -83,9 +84,11 @@ JackAudioPort::prepare_buffer(jack_nframes_t nframes)
*/
jack_sample_t* jack_buf = (jack_sample_t*)jack_port_get_buffer(_jack_port, nframes);
+ AudioBuffer* patch_buf = (AudioBuffer*)_patch_port->buffer(0);
+
if (jack_buf != _jack_buffer) {
//cerr << "Jack buffer: " << jack_buf << endl;
- _patch_port->buffer(0)->set_data(jack_buf);
+ patch_buf->set_data(jack_buf);
_jack_buffer = jack_buf;
}
@@ -100,7 +103,7 @@ JackAudioPort::prepare_buffer(jack_nframes_t nframes)
//m_patch_port->fixed_buffers(true);
//assert(_patch_port->buffer(0)->data() == _patch_port->tied_port()->buffer(0)->data());
- assert(_patch_port->buffer(0)->data() == jack_buf);
+ assert(patch_buf->data() == jack_buf);
}
@@ -257,7 +260,7 @@ JackAudioDriver::port(const Path& path)
DriverPort*
-JackAudioDriver::create_port(DuplexPort<Sample>* patch_port)
+JackAudioDriver::create_port(DuplexPort* patch_port)
{
if (patch_port->buffer_size() == _buffer_size)
return new JackAudioPort(this, patch_port);
diff --git a/src/libs/engine/JackAudioDriver.h b/src/libs/engine/JackAudioDriver.h
index 8629335e..a54b4a88 100644
--- a/src/libs/engine/JackAudioDriver.h
+++ b/src/libs/engine/JackAudioDriver.h
@@ -31,7 +31,7 @@ namespace Ingen {
class Engine;
class Patch;
class Port;
-template <typename T> class DuplexPort;
+class DuplexPort;
class JackAudioDriver;
typedef jack_default_audio_sample_t jack_sample_t;
@@ -43,21 +43,21 @@ typedef jack_default_audio_sample_t jack_sample_t;
class JackAudioPort : public DriverPort, public Raul::ListNode<JackAudioPort*>
{
public:
- JackAudioPort(JackAudioDriver* driver, DuplexPort<Sample>* patch_port);
+ JackAudioPort(JackAudioDriver* driver, DuplexPort* patch_port);
~JackAudioPort();
void set_name(const std::string& name) { jack_port_set_name(_jack_port, name.c_str()); };
void prepare_buffer(jack_nframes_t nframes);
- jack_port_t* jack_port() const { return _jack_port; }
- DuplexPort<Sample>* patch_port() const { return _patch_port; }
+ jack_port_t* jack_port() const { return _jack_port; }
+ DuplexPort* patch_port() const { return _patch_port; }
private:
- JackAudioDriver* _driver;
- jack_port_t* _jack_port;
- jack_sample_t* _jack_buffer; ///< Cached for output ports
- DuplexPort<Sample>* _patch_port;
+ JackAudioDriver* _driver;
+ jack_port_t* _jack_port;
+ jack_sample_t* _jack_buffer; ///< Cached for output ports
+ DuplexPort* _patch_port;
};
@@ -85,7 +85,7 @@ public:
void disable();
DriverPort* port(const Raul::Path& path);
- DriverPort* create_port(DuplexPort<Sample>* patch_port);
+ DriverPort* create_port(DuplexPort* patch_port);
void add_port(DriverPort* port);
DriverPort* remove_port(const Raul::Path& path);
diff --git a/src/libs/engine/JackMidiDriver.cpp b/src/libs/engine/JackMidiDriver.cpp
index e2f96ad7..ada9a439 100644
--- a/src/libs/engine/JackMidiDriver.cpp
+++ b/src/libs/engine/JackMidiDriver.cpp
@@ -24,7 +24,7 @@
#include "types.h"
#include "ThreadManager.h"
#include "AudioDriver.h"
-#include "MidiMessage.h"
+#include "MidiBuffer.h"
#include "DuplexPort.h"
#ifdef HAVE_LASH
#include "LashDriver.h"
@@ -36,7 +36,7 @@ namespace Ingen {
//// JackMidiPort ////
-JackMidiPort::JackMidiPort(JackMidiDriver* driver, DuplexPort<MidiMessage>* patch_port)
+JackMidiPort::JackMidiPort(JackMidiDriver* driver, DuplexPort* patch_port)
: DriverPort(patch_port->is_input()),
Raul::ListNode<JackMidiPort*>(this),
_driver(driver),
@@ -75,25 +75,25 @@ JackMidiPort::prepare_block(const SampleCount block_start, const SampleCount blo
void* jack_buffer = jack_port_get_buffer(_jack_port, nframes);
const jack_nframes_t event_count = jack_midi_get_event_count(jack_buffer);
- assert(event_count < _patch_port->buffer_size());
+ assert(_patch_port->poly() == 1);
+
+ MidiBuffer* patch_buf = dynamic_cast<MidiBuffer*>(_patch_port->buffer(0));
+ assert(patch_buf);
+
+ patch_buf->clear();
+ patch_buf->reset_state(nframes);
// Copy events from Jack port buffer into patch port buffer
for (jack_nframes_t i=0; i < event_count; ++i) {
- jack_midi_event_t* ev = (jack_midi_event_t*)&_patch_port->buffer(0)->value_at(i);
- jack_midi_event_get(ev, jack_buffer, i);
-
- // MidiMessage and jack_midi_event_t* are the same thing :/
- MidiMessage* const message = &_patch_port->buffer(0)->data()[i];
- message->time = ev->time;
- message->size = ev->size;
- message->buffer = ev->buffer;
+ jack_midi_event_t ev;
+ jack_midi_event_get(&ev, jack_buffer, i);
- assert(message->time < nframes);
+ patch_buf->put_event(ev.time, ev.size, ev.buffer);
}
//cerr << "Jack MIDI got " << event_count << " events." << endl;
- _patch_port->buffer(0)->filled_size(event_count);
+ //_patch_port->buffer(0)->filled_size(event_count);
//_patch_port->tied_port()->buffer(0)->filled_size(event_count);
}
diff --git a/src/libs/engine/JackMidiDriver.h b/src/libs/engine/JackMidiDriver.h
index d6d2cf51..535a1f22 100644
--- a/src/libs/engine/JackMidiDriver.h
+++ b/src/libs/engine/JackMidiDriver.h
@@ -29,7 +29,7 @@ namespace Ingen {
class Node;
class SetPortValueEvent;
class JackMidiDriver;
-template <typename T> class DuplexPort;
+class DuplexPort;
/** Representation of an JACK MIDI port.
@@ -39,19 +39,19 @@ template <typename T> class DuplexPort;
class JackMidiPort : public DriverPort, public Raul::ListNode<JackMidiPort*>
{
public:
- JackMidiPort(JackMidiDriver* driver, DuplexPort<MidiMessage>* port);
+ JackMidiPort(JackMidiDriver* driver, DuplexPort* port);
virtual ~JackMidiPort();
void prepare_block(const SampleCount block_start, const SampleCount block_end);
void set_name(const std::string& name) { jack_port_set_name(_jack_port, name.c_str()); };
- DuplexPort<MidiMessage>* patch_port() const { return _patch_port; }
+ DuplexPort* patch_port() const { return _patch_port; }
private:
- JackMidiDriver* _driver;
- jack_port_t* _jack_port;
- DuplexPort<MidiMessage>* _patch_port;
+ JackMidiDriver* _driver;
+ jack_port_t* _jack_port;
+ DuplexPort* _patch_port;
};
@@ -78,7 +78,7 @@ public:
void prepare_block(const SampleCount block_start, const SampleCount block_end);
- JackMidiPort* create_port(DuplexPort<MidiMessage>* patch_port)
+ JackMidiPort* create_port(DuplexPort* patch_port)
{ return new JackMidiPort(this, patch_port); }
void add_port(DriverPort* port);
diff --git a/src/libs/engine/LADSPANode.cpp b/src/libs/engine/LADSPANode.cpp
index d9b350b4..3ad197a4 100644
--- a/src/libs/engine/LADSPANode.cpp
+++ b/src/libs/engine/LADSPANode.cpp
@@ -15,13 +15,12 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-
#include "LADSPANode.h"
#include <iostream>
#include <cassert>
-#include "float.h"
#include <stdint.h>
#include <cmath>
+#include "AudioBuffer.h"
#include "InputPort.h"
#include "OutputPort.h"
#include "Plugin.h"
@@ -106,10 +105,10 @@ LADSPANode::instantiate()
|| LADSPA_IS_PORT_OUTPUT(_descriptor->PortDescriptors[j]));
if (LADSPA_IS_PORT_INPUT(_descriptor->PortDescriptors[j])) {
- port = new InputPort<Sample>(this, port_name, j, _poly, DataType::FLOAT, port_buffer_size);
+ port = new InputPort(this, port_name, j, _poly, DataType::FLOAT, port_buffer_size);
_ports->at(j) = port;
} else if (LADSPA_IS_PORT_OUTPUT(_descriptor->PortDescriptors[j])) {
- port = new OutputPort<Sample>(this, port_name, j, _poly, DataType::FLOAT, port_buffer_size);
+ port = new OutputPort(this, port_name, j, _poly, DataType::FLOAT, port_buffer_size);
_ports->at(j) = port;
}
@@ -121,9 +120,8 @@ LADSPANode::instantiate()
// Set default value
if (port->buffer_size() == 1) {
- ((TypedPort<Sample>*)port)->set_value(default_val, 0);
- } else {
- ((TypedPort<Sample>*)port)->set_value(0.0f, 0);
+ for (size_t i=0; i < _poly; ++i)
+ ((AudioBuffer*)port->buffer(i))->set(default_val, 0);
}
if (port->is_input() && port->buffer_size() == 1) {
@@ -150,12 +148,9 @@ LADSPANode::activate()
{
NodeBase::activate();
- TypedPort<Sample>* port = NULL;
-
for (size_t i=0; i < _poly; ++i) {
for (unsigned long j=0; j < _descriptor->PortCount; ++j) {
- port = static_cast<TypedPort<Sample>*>(_ports->at(j));
- set_port_buffer(i, j, ((TypedPort<Sample>*)_ports->at(j))->buffer(i)->data());
+ set_port_buffer(i, j, _ports->at(j)->buffer(i));
/* if (port->type() == DataType::FLOAT && port->buffer_size() == 1)
port->set_value(0.0f, 0); // FIXME
else if (port->type() == DataType::FLOAT && port->buffer_size() > 1)
@@ -188,13 +183,17 @@ LADSPANode::process(SampleCount nframes, FrameTime start, FrameTime end)
void
-LADSPANode::set_port_buffer(size_t voice, size_t port_num, void* buf)
+LADSPANode::set_port_buffer(size_t voice, size_t port_num, Buffer* buf)
{
assert(voice < _poly);
+ AudioBuffer* audio_buffer = dynamic_cast<AudioBuffer*>(buf);
+ assert(audio_buffer);
+
// Could be a MIDI port after this
if (port_num < _descriptor->PortCount)
- _descriptor->connect_port(_instances[voice], port_num, (Sample*)buf);
+ _descriptor->connect_port(_instances[voice], port_num,
+ audio_buffer->data());
}
#if 0
diff --git a/src/libs/engine/LADSPANode.h b/src/libs/engine/LADSPANode.h
index 0f9d7ee9..ff813f4c 100644
--- a/src/libs/engine/LADSPANode.h
+++ b/src/libs/engine/LADSPANode.h
@@ -44,7 +44,7 @@ public:
void process(SampleCount nframes, FrameTime start, FrameTime end);
- void set_port_buffer(size_t voice, size_t port_num, void* buf);
+ void set_port_buffer(size_t voice, size_t port_num, Buffer* buf);
const Plugin* plugin() const { return _plugin; }
void plugin(const Plugin* const pi) { _plugin = pi; }
diff --git a/src/libs/engine/LV2Node.cpp b/src/libs/engine/LV2Node.cpp
index ebc6a72c..0baf41ef 100644
--- a/src/libs/engine/LV2Node.cpp
+++ b/src/libs/engine/LV2Node.cpp
@@ -24,6 +24,7 @@
#include "InputPort.h"
#include "OutputPort.h"
#include "Plugin.h"
+#include "AudioBuffer.h"
namespace Ingen {
@@ -98,16 +99,16 @@ LV2Node::instantiate()
port_buffer_size = 1;
if (port_class == SLV2_CONTROL_INPUT || port_class == SLV2_AUDIO_INPUT) {
- port = new InputPort<Sample>(this, port_name, j, _poly, DataType::FLOAT, port_buffer_size);
+ port = new InputPort(this, port_name, j, _poly, DataType::FLOAT, port_buffer_size);
_ports->at(j) = port;
} else if (port_class == SLV2_CONTROL_OUTPUT || port_class == SLV2_AUDIO_OUTPUT) {
- port = new OutputPort<Sample>(this, port_name, j, _poly, DataType::FLOAT, port_buffer_size);
+ port = new OutputPort(this, port_name, j, _poly, DataType::FLOAT, port_buffer_size);
_ports->at(j) = port;
} else if (port_class == SLV2_MIDI_INPUT) {
- port = new InputPort<MidiMessage>(this, port_name, j, _poly, DataType::MIDI, port_buffer_size);
+ port = new InputPort(this, port_name, j, _poly, DataType::MIDI, port_buffer_size);
_ports->at(j) = port;
} else if (port_class == SLV2_MIDI_OUTPUT) {
- port = new OutputPort<MidiMessage>(this, port_name, j, _poly, DataType::MIDI, port_buffer_size);
+ port = new OutputPort(this, port_name, j, _poly, DataType::MIDI, port_buffer_size);
_ports->at(j) = port;
}
@@ -140,16 +141,16 @@ LV2Node::activate()
{
NodeBase::activate();
- TypedPort<Sample>* port = NULL;
-
for (size_t i=0; i < _poly; ++i) {
for (unsigned long j=0; j < num_ports(); ++j) {
- port = static_cast<TypedPort<Sample>*>(_ports->at(j));
- set_port_buffer(i, j, ((TypedPort<Sample>*)_ports->at(j))->buffer(i)->data());
- if (port->type() == DataType::FLOAT && port->buffer_size() == 1)
- port->set_value(0.0f, 0); // FIXME
- else if (port->type() == DataType::FLOAT && port->buffer_size() > 1)
- port->set_value(0.0f, 0);
+ Port* const port = _ports->at(j);
+ set_port_buffer(i, j, port->buffer(i));
+ if (port->type() == DataType::FLOAT && port->buffer_size() == 1) {
+ cerr << "FIXME: LV2 default value\n";
+ ((AudioBuffer*)port->buffer(i))->set(0.0f, 0); // FIXME
+ } else if (port->type() == DataType::FLOAT && port->buffer_size() > 1) {
+ ((AudioBuffer*)port->buffer(i))->set(0.0f, 0);
+ }
}
slv2_instance_activate(_instances[i]);
}
@@ -176,14 +177,14 @@ LV2Node::process(SampleCount nframes, FrameTime start, FrameTime end)
void
-LV2Node::set_port_buffer(size_t voice, size_t port_num, void* buf)
+LV2Node::set_port_buffer(size_t voice, size_t port_num, Buffer* buf)
{
assert(voice < _poly);
- // Could be a MIDI port after this
- if (port_num < num_ports()) {
- slv2_instance_connect_port(_instances[voice], port_num, buf);
- }
+ if (buf->type() == DataType::FLOAT)
+ slv2_instance_connect_port(_instances[voice], port_num, ((AudioBuffer*)buf)->data());
+ else if (buf->type() == DataType::MIDI)
+ slv2_instance_connect_port(_instances[voice], port_num, ((MidiBuffer*)buf)->data());
}
diff --git a/src/libs/engine/LV2Node.h b/src/libs/engine/LV2Node.h
index f0547161..39b06939 100644
--- a/src/libs/engine/LV2Node.h
+++ b/src/libs/engine/LV2Node.h
@@ -50,7 +50,7 @@ public:
void process(SampleCount nframes, FrameTime start, FrameTime end);
- void set_port_buffer(size_t voice, size_t port_num, void* buf);
+ void set_port_buffer(size_t voice, size_t port_num, Buffer* buf);
protected:
//void get_port_vals(ulong port_index, PortInfo* info);
diff --git a/src/libs/engine/Makefile.am b/src/libs/engine/Makefile.am
index 03c42c52..29b601a9 100644
--- a/src/libs/engine/Makefile.am
+++ b/src/libs/engine/Makefile.am
@@ -38,11 +38,13 @@ libingen_la_SOURCES = \
OSCClientSender.h \
OSCClientSender.cpp \
Buffer.h \
- Buffer.cpp \
+ AudioBuffer.h \
+ AudioBuffer.cpp \
+ MidiBuffer.h \
+ MidiBuffer.cpp \
+ BufferFactory.cpp \
Port.h \
Port.cpp \
- TypedPort.h \
- TypedPort.cpp \
InputPort.h \
InputPort.cpp \
OutputPort.h \
@@ -73,8 +75,6 @@ libingen_la_SOURCES = \
PostProcessor.cpp \
Connection.h \
Connection.cpp \
- TypedConnection.h \
- TypedConnection.cpp \
ObjectStore.h \
ObjectStore.cpp \
TransportNode.h \
diff --git a/src/libs/engine/MidiBuffer.cpp b/src/libs/engine/MidiBuffer.cpp
new file mode 100644
index 00000000..7dfe72e6
--- /dev/null
+++ b/src/libs/engine/MidiBuffer.cpp
@@ -0,0 +1,77 @@
+/* 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 "MidiBuffer.h"
+
+namespace Ingen {
+
+
+/** Use another buffer's data instead of the local one.
+ *
+ * This buffer will essentially be identical to @a buf after this call.
+ */
+bool
+MidiBuffer::join(Buffer* buf)
+{
+ MidiBuffer* mbuf = dynamic_cast<MidiBuffer*>(buf);
+ if (!mbuf)
+ return false;
+
+ //assert(mbuf->size() == _size);
+
+ _joined_buf = mbuf;
+
+ _buf = mbuf->data();
+ _state = mbuf->state();
+
+ return true;
+}
+
+
+void
+MidiBuffer::unjoin()
+{
+ _joined_buf = NULL;
+ _buf = _local_buf;
+ _state = &_local_state;
+}
+
+
+bool
+MidiBuffer::is_joined_to(Buffer* buf) const
+{
+ MidiBuffer* mbuf = dynamic_cast<MidiBuffer*>(buf);
+ if (mbuf)
+ return (data() == mbuf->data());
+
+ return false;
+}
+
+
+void
+MidiBuffer::prepare(SampleCount nframes)
+{
+ if (_joined_buf)
+ _local_state = *_joined_buf->state();
+ else
+ reset_state(nframes);
+
+ _this_nframes = nframes;
+}
+
+
+} // namespace Ingen
diff --git a/src/libs/engine/MidiBuffer.h b/src/libs/engine/MidiBuffer.h
new file mode 100644
index 00000000..459c1209
--- /dev/null
+++ b/src/libs/engine/MidiBuffer.h
@@ -0,0 +1,88 @@
+/* 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 MIDIBUFFER_H
+#define MIDIBUFFER_H
+
+#include <lv2ext/lv2-miditype.h>
+#include <lv2ext/lv2-midifunctions.h>
+#include "Buffer.h"
+#include "DataType.h"
+
+namespace Ingen {
+
+
+class MidiBuffer : public Buffer {
+public:
+ MidiBuffer(size_t capacity)
+ : Buffer(DataType(DataType::MIDI), capacity)
+ , _state(&_local_state)
+ , _buf(lv2midi_new((uint32_t)capacity))
+ , _local_buf(NULL)
+ , _joined_buf(NULL)
+ {
+ clear();
+ reset_state(0);
+ }
+
+ ~MidiBuffer() { lv2midi_free(_buf); }
+
+ void prepare(SampleCount nframes);
+
+ bool is_joined_to(Buffer* buf) const;
+ bool is_joined() const { return (_joined_buf == NULL); }
+ bool join(Buffer* buf);
+ void unjoin();
+
+ uint32_t this_nframes() const { return _this_nframes; }
+
+ inline LV2_MIDI* data() const
+ { return ((_joined_buf != NULL) ? _joined_buf->data() : _buf); }
+
+ inline LV2_MIDIState* state() const
+ { return ((_joined_buf != NULL) ? _joined_buf->state() : _state); }
+
+ inline void clear()
+ { lv2midi_reset_buffer(_buf); }
+
+ inline void reset_state(uint32_t nframes)
+ { lv2midi_reset_state(_state, _buf, nframes); _this_nframes = nframes; }
+
+ inline double increment()
+ { return lv2midi_increment(_state); }
+
+ inline double get_event(double* timestamp, uint32_t* size, unsigned char** data)
+ { return lv2midi_get_event(_state, timestamp, size, data); }
+
+ inline int put_event(double timestamp, uint32_t size, const unsigned char* data)
+ { return lv2midi_put_event(_state, timestamp, size, data); }
+
+private:
+ LV2_MIDIState* _state;
+ LV2_MIDIState _local_state;
+ LV2_MIDI* _buf;
+ LV2_MIDI* _local_buf;
+
+ MidiBuffer* _joined_buf; ///< Buffer to mirror, if joined
+
+ uint32_t _this_nframes;
+};
+
+
+} // namespace Ingen
+
+#endif // MIDIBUFFER_H
diff --git a/src/libs/engine/MidiControlNode.cpp b/src/libs/engine/MidiControlNode.cpp
index 89a04c91..81df8e6c 100644
--- a/src/libs/engine/MidiControlNode.cpp
+++ b/src/libs/engine/MidiControlNode.cpp
@@ -24,7 +24,7 @@
#include "OutputPort.h"
#include "Plugin.h"
#include "util.h"
-
+#include "AudioBuffer.h"
namespace Ingen {
@@ -35,25 +35,25 @@ MidiControlNode::MidiControlNode(const string& path, size_t poly, Patch* parent,
{
_ports = new Raul::Array<Port*>(7);
- _midi_in_port = new InputPort<MidiMessage>(this, "MIDIIn", 0, 1, DataType::MIDI, _buffer_size);
+ _midi_in_port = new InputPort(this, "MIDIIn", 0, 1, DataType::MIDI, _buffer_size);
_ports->at(0) = _midi_in_port;
- _param_port = new InputPort<Sample>(this, "ControllerNumber", 1, 1, DataType::FLOAT, 1);
+ _param_port = new InputPort(this, "ControllerNumber", 1, 1, DataType::FLOAT, 1);
_ports->at(1) = _param_port;
- _log_port = new InputPort<Sample>(this, "Logarithmic", 2, 1, DataType::FLOAT, 1);
+ _log_port = new InputPort(this, "Logarithmic", 2, 1, DataType::FLOAT, 1);
_ports->at(2) = _log_port;
- _min_port = new InputPort<Sample>(this, "Min", 3, 1, DataType::FLOAT, 1);
+ _min_port = new InputPort(this, "Min", 3, 1, DataType::FLOAT, 1);
_ports->at(3) = _min_port;
- _max_port = new InputPort<Sample>(this, "Max", 4, 1, DataType::FLOAT, 1);
+ _max_port = new InputPort(this, "Max", 4, 1, DataType::FLOAT, 1);
_ports->at(4) = _max_port;
- _audio_port = new OutputPort<Sample>(this, "Out(AR)", 5, 1, DataType::FLOAT, _buffer_size);
+ _audio_port = new OutputPort(this, "Out(AR)", 5, 1, DataType::FLOAT, _buffer_size);
_ports->at(5) = _audio_port;
- _control_port = new OutputPort<Sample>(this, "Out(CR)", 6, 1, DataType::FLOAT, 1);
+ _control_port = new OutputPort(this, "Out(CR)", 6, 1, DataType::FLOAT, 1);
_ports->at(6) = _control_port;
plugin()->plug_label("midi_control_in");
@@ -66,14 +66,20 @@ void
MidiControlNode::process(SampleCount nframes, FrameTime start, FrameTime end)
{
InternalNode::process(nframes, start, end);
-
- MidiMessage ev;
- for (size_t i=0; i < _midi_in_port->buffer(0)->filled_size(); ++i) {
- ev = _midi_in_port->buffer(0)->value_at(i);
+ double timestamp = 0;
+ uint32_t size = 0;
+ unsigned char* buffer = NULL;
+
+ MidiBuffer* const midi_in = (MidiBuffer*)_midi_in_port->buffer(0);
+ assert(midi_in->this_nframes() == nframes);
- if ((ev.buffer[0] & 0xF0) == MIDI_CMD_CONTROL)
- control(ev.buffer[1], ev.buffer[2], ev.time);
+ while (midi_in->get_event(&timestamp, &size, &buffer) < nframes) {
+
+ const FrameTime time = start + (FrameTime)timestamp;
+
+ if (size >= 3 && (buffer[0] & 0xF0) == MIDI_CMD_CONTROL)
+ control(buffer[1], buffer[2], time);
}
}
@@ -102,23 +108,25 @@ MidiControlNode::control(uchar control_num, uchar val, SampleCount offset)
#endif
}
- if (_log_port->buffer(0)->value_at(0) > 0.0f) {
+ const Sample min_port_val = ((AudioBuffer*)_min_port->buffer(0))->value_at(0);
+ const Sample max_port_val = ((AudioBuffer*)_max_port->buffer(0))->value_at(0);
+ const Sample log_port_val = ((AudioBuffer*)_log_port->buffer(0))->value_at(0);
+
+ if (log_port_val > 0.0f) {
// haaaaack, stupid negatives and logarithms
Sample log_offset = 0;
- if (_min_port->buffer(0)->value_at(0) < 0)
- log_offset = fabs(_min_port->buffer(0)->value_at(0));
- const Sample min = log(_min_port->buffer(0)->value_at(0)+1+log_offset);
- const Sample max = log(_max_port->buffer(0)->value_at(0)+1+log_offset);
+ if (min_port_val < 0)
+ log_offset = fabs(min_port_val);
+ const Sample min = log(min_port_val+1+log_offset);
+ const Sample max = log(max_port_val+1+log_offset);
scaled_value = expf(nval * (max - min) + min) - 1 - log_offset;
} else {
- const Sample min = _min_port->buffer(0)->value_at(0);
- const Sample max = _max_port->buffer(0)->value_at(0);
- scaled_value = ((nval) * (max - min)) + min;
+ scaled_value = ((nval) * (max_port_val - min_port_val)) + min_port_val;
}
- if (control_num == _param_port->buffer(0)->value_at(0)) {
- _control_port->set_value(scaled_value, offset);
- _audio_port->set_value(scaled_value, offset);
+ if (control_num == ((AudioBuffer*)_param_port->buffer(0))->value_at(0)) {
+ ((AudioBuffer*)_control_port->buffer(0))->set(scaled_value, offset);
+ ((AudioBuffer*)_audio_port->buffer(0))->set(scaled_value, offset);
}
}
diff --git a/src/libs/engine/MidiControlNode.h b/src/libs/engine/MidiControlNode.h
index 997d5dd4..41d02dfb 100644
--- a/src/libs/engine/MidiControlNode.h
+++ b/src/libs/engine/MidiControlNode.h
@@ -21,14 +21,13 @@
#include <string>
#include "NodeBase.h"
#include "InternalNode.h"
-using std::string;
+#include "MidiBuffer.h"
namespace Ingen {
class MidiLearnResponseEvent;
-class MidiMessage;
-template <typename T> class InputPort;
-template <typename T> class OutputPort;
+class InputPort;
+class OutputPort;
/** MIDI control input node.
@@ -41,7 +40,7 @@ template <typename T> class OutputPort;
class MidiControlNode : public InternalNode
{
public:
- MidiControlNode(const string& path, size_t poly, Patch* parent, SampleRate srate, size_t buffer_size);
+ MidiControlNode(const std::string& path, size_t poly, Patch* parent, SampleRate srate, size_t buffer_size);
void process(SampleCount nframes, FrameTime start, FrameTime end);
@@ -52,13 +51,13 @@ public:
private:
bool _learning;
- InputPort<MidiMessage>* _midi_in_port;
- InputPort<Sample>* _param_port;
- InputPort<Sample>* _log_port;
- InputPort<Sample>* _min_port;
- InputPort<Sample>* _max_port;
- OutputPort<Sample>* _control_port;
- OutputPort<Sample>* _audio_port;
+ InputPort* _midi_in_port;
+ InputPort* _param_port;
+ InputPort* _log_port;
+ InputPort* _min_port;
+ InputPort* _max_port;
+ OutputPort* _control_port;
+ OutputPort* _audio_port;
MidiLearnResponseEvent* _learn_event;
};
diff --git a/src/libs/engine/MidiDriver.h b/src/libs/engine/MidiDriver.h
index 1458aca5..ebee458c 100644
--- a/src/libs/engine/MidiDriver.h
+++ b/src/libs/engine/MidiDriver.h
@@ -21,20 +21,20 @@
#include "types.h"
#include "Driver.h"
#include <iostream>
-using std::cout; using std::endl;
+#include "MidiBuffer.h"
namespace Ingen {
-class MidiMessage;
-
/** Midi driver abstract base class.
*
* \ingroup engine
*/
-class MidiDriver : public Driver<MidiMessage>
+class MidiDriver : public Driver
{
public:
+ MidiDriver() : Driver(DataType::MIDI) {}
+
/** Prepare events (however neccessary) for the specified block (realtime safe) */
virtual void prepare_block(const SampleCount block_start, const SampleCount block_end) = 0;
};
@@ -54,7 +54,7 @@ class DummyMidiDriver : public MidiDriver
{
public:
DummyMidiDriver() {
- cout << "[DummyMidiDriver] Started Dummy MIDI driver." << endl;
+ std::cout << "[DummyMidiDriver] Started Dummy MIDI driver." << std::endl;
}
~DummyMidiDriver() {}
@@ -68,7 +68,7 @@ public:
void enable() {}
void disable() {}
- DriverPort* create_port(DuplexPort<MidiMessage>* patch_port) { return NULL; }
+ DriverPort* create_port(DuplexPort* patch_port) { return NULL; }
void add_port(DriverPort* port) {}
DriverPort* remove_port(const Raul::Path& path) { return NULL; }
diff --git a/src/libs/engine/MidiMessage.h b/src/libs/engine/MidiMessage.h
deleted file mode 100644
index 00082acd..00000000
--- a/src/libs/engine/MidiMessage.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* 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 MIDIMESSAGE_H
-#define MIDIMESSAGE_H
-
-namespace Ingen {
-
-
-/** Midi Message (the type a MIDI port connects to).
- *
- * For the time being (ie while it's still possible) this is binary
- * compatible with jack_default_midi_event_t. Don't mess that up without
- * dealing with all the repercussions (in the MidiDriver's).
- *
- * Note that with the current implementation one of these is NOT valid
- * across process cycles (since the buffer is just a pointer to the bufferr
- * given to us by Jack itself. In other words, if one of these needs to be
- * stored, it needs to be deep copied. Less copying anyway.. :/
- */
-struct MidiMessage
-{
-public:
- MidiMessage() : time(0), size(0), buffer(NULL) {}
-
- // Really just to allow setting to zero for generic algos
- MidiMessage(const int& i) : time(0), size(0), buffer(NULL) {}
-
- SampleCount time;
- size_t size;
- unsigned char* buffer;
-};
-
-
-} // namespace Ingen
-
-
-#endif // MIDIMESSAGE_H
diff --git a/src/libs/engine/MidiNoteNode.cpp b/src/libs/engine/MidiNoteNode.cpp
index f2b9e502..6a6b698c 100644
--- a/src/libs/engine/MidiNoteNode.cpp
+++ b/src/libs/engine/MidiNoteNode.cpp
@@ -20,7 +20,8 @@
#include <iostream>
#include <raul/Array.h>
#include <raul/midi_events.h>
-#include "MidiMessage.h"
+#include "MidiBuffer.h"
+#include "AudioBuffer.h"
#include "InputPort.h"
#include "OutputPort.h"
#include "Plugin.h"
@@ -40,22 +41,22 @@ MidiNoteNode::MidiNoteNode(const string& path, size_t poly, Patch* parent, Sampl
{
_ports = new Raul::Array<Port*>(5);
- _midi_in_port = new InputPort<MidiMessage>(this, "MIDIIn", 0, 1, DataType::MIDI, _buffer_size);
+ _midi_in_port = new InputPort(this, "MIDIIn", 0, 1, DataType::MIDI, _buffer_size);
_ports->at(0) = _midi_in_port;
- _freq_port = new OutputPort<Sample>(this, "Frequency", 1, poly, DataType::FLOAT, _buffer_size);
+ _freq_port = new OutputPort(this, "Frequency", 1, poly, DataType::FLOAT, _buffer_size);
// new PortInfo("Frequency", AUDIO, OUTPUT, 440, 0, 99999), _buffer_size);
_ports->at(1) = _freq_port;
- _vel_port = new OutputPort<Sample>(this, "Velocity", 2, poly, DataType::FLOAT, _buffer_size);
+ _vel_port = new OutputPort(this, "Velocity", 2, poly, DataType::FLOAT, _buffer_size);
// new PortInfo("Velocity", AUDIO, OUTPUT, 0, 0, 1), _buffer_size);
_ports->at(2) = _vel_port;
- _gate_port = new OutputPort<Sample>(this, "Gate", 3, poly, DataType::FLOAT, _buffer_size);
+ _gate_port = new OutputPort(this, "Gate", 3, poly, DataType::FLOAT, _buffer_size);
// new PortInfo("Gate", AUDIO, OUTPUT, 0, 0, 1), _buffer_size);
_ports->at(3) = _gate_port;
- _trig_port = new OutputPort<Sample>(this, "Trigger", 4, poly, DataType::FLOAT, _buffer_size);
+ _trig_port = new OutputPort(this, "Trigger", 4, poly, DataType::FLOAT, _buffer_size);
// new PortInfo("Trigger", AUDIO, OUTPUT, 0, 0, 1), _buffer_size);
_ports->at(4) = _trig_port;
@@ -76,42 +77,50 @@ MidiNoteNode::process(SampleCount nframes, FrameTime start, FrameTime end)
{
InternalNode::process(nframes, start, end);
- MidiMessage ev;
-
- for (size_t i=0; i < _midi_in_port->buffer(0)->filled_size(); ++i) {
- ev = _midi_in_port->buffer(0)->value_at(i);
+ double timestamp = 0;
+ uint32_t size = 0;
+ unsigned char* buffer = NULL;
- const FrameTime time = ev.time + start;
+ MidiBuffer* const midi_in = (MidiBuffer*)_midi_in_port->buffer(0);
+ assert(midi_in->this_nframes() == nframes);
- switch (ev.buffer[0] & 0xF0) {
- case MIDI_CMD_NOTE_ON:
- if (ev.buffer[2] == 0)
- note_off(ev.buffer[1], time, nframes, start, end);
- else
- note_on(ev.buffer[1], ev.buffer[2], time, nframes, start, end);
- break;
- case MIDI_CMD_NOTE_OFF:
- note_off(ev.buffer[1], time, nframes, start, end);
- break;
- case MIDI_CMD_CONTROL:
- switch (ev.buffer[1]) {
- case MIDI_CTL_ALL_NOTES_OFF:
- case MIDI_CTL_ALL_SOUNDS_OFF:
- all_notes_off(time, nframes, start, end);
- break;
- case MIDI_CTL_SUSTAIN:
- if (ev.buffer[2] > 63)
- sustain_on(time, nframes, start, end);
+ while (midi_in->get_event(&timestamp, &size, &buffer) < nframes) {
+
+ const FrameTime time = start + (FrameTime)timestamp;
+
+ if (size >= 3) {
+ switch (buffer[0] & 0xF0) {
+ case MIDI_CMD_NOTE_ON:
+ if (buffer[2] == 0)
+ note_off(buffer[1], time, nframes, start, end);
else
- sustain_off(time, nframes, start, end);
+ note_on(buffer[1], buffer[2], time, nframes, start, end);
break;
- case MIDI_CMD_BENDER:
-
+ case MIDI_CMD_NOTE_OFF:
+ note_off(buffer[1], time, nframes, start, end);
+ break;
+ case MIDI_CMD_CONTROL:
+ switch (buffer[1]) {
+ case MIDI_CTL_ALL_NOTES_OFF:
+ case MIDI_CTL_ALL_SOUNDS_OFF:
+ all_notes_off(time, nframes, start, end);
+ break;
+ case MIDI_CTL_SUSTAIN:
+ if (buffer[2] > 63)
+ sustain_on(time, nframes, start, end);
+ else
+ sustain_off(time, nframes, start, end);
+ break;
+ case MIDI_CMD_BENDER:
+
+ break;
+ }
+ default:
break;
}
- default:
- break;
}
+
+ midi_in->increment();
}
}
@@ -183,13 +192,13 @@ MidiNoteNode::note_on(uchar note_num, uchar velocity, FrameTime time, SampleCoun
if (offset == (SampleCount)(_buffer_size-1))
--offset;
- _freq_port->buffer(voice_num)->set(note_to_freq(note_num), offset);
- _vel_port->buffer(voice_num)->set(velocity/127.0, offset);
- _gate_port->buffer(voice_num)->set(1.0f, offset);
+ ((AudioBuffer*)_freq_port->buffer(voice_num))->set(note_to_freq(note_num), offset);
+ ((AudioBuffer*)_vel_port->buffer(voice_num))->set(velocity/127.0, offset);
+ ((AudioBuffer*)_gate_port->buffer(voice_num))->set(1.0f, offset);
// trigger (one sample)
- _trig_port->buffer(voice_num)->set(1.0f, offset, offset);
- _trig_port->buffer(voice_num)->set(0.0f, offset+1);
+ ((AudioBuffer*)_trig_port->buffer(voice_num))->set(1.0f, offset, offset);
+ ((AudioBuffer*)_trig_port->buffer(voice_num))->set(0.0f, offset+1);
assert(key->state == Key::Key::ON_ASSIGNED);
assert(voice->state == Voice::Voice::ACTIVE);
@@ -246,7 +255,7 @@ MidiNoteNode::free_voice(size_t voice, FrameTime time, SampleCount nframes, Fram
assert(replace_key->state == Key::ON_UNASSIGNED);
// Change the freq but leave the gate high and don't retrigger
- _freq_port->buffer(voice)->set(note_to_freq(replace_key_num), time - start);
+ ((AudioBuffer*)_freq_port->buffer(voice))->set(note_to_freq(replace_key_num), time - start);
replace_key->state = Key::ON_ASSIGNED;
replace_key->voice = voice;
@@ -256,7 +265,7 @@ MidiNoteNode::free_voice(size_t voice, FrameTime time, SampleCount nframes, Fram
} else {
// No new note for voice, deactivate (set gate low)
//cerr << "[MidiNoteNode] Note off. Key " << (int)note_num << ", Voice " << voice << " Killed" << endl;
- _gate_port->buffer(voice)->set(0.0f, time - start);
+ ((AudioBuffer*)_gate_port->buffer(voice))->set(0.0f, time - start);
_voices[voice].state = Voice::FREE;
}
}
@@ -273,7 +282,7 @@ MidiNoteNode::all_notes_off(FrameTime time, SampleCount nframes, FrameTime start
// FIXME: set all keys to Key::OFF?
for (size_t i=0; i < _poly; ++i) {
- _gate_port->buffer(i)->set(0.0f, time - start);
+ ((AudioBuffer*)_gate_port->buffer(i))->set(0.0f, time - start);
_voices[i].state = Voice::FREE;
}
}
diff --git a/src/libs/engine/MidiNoteNode.h b/src/libs/engine/MidiNoteNode.h
index a4f22c7f..5be62995 100644
--- a/src/libs/engine/MidiNoteNode.h
+++ b/src/libs/engine/MidiNoteNode.h
@@ -21,14 +21,14 @@
#include <string>
#include "InternalNode.h"
#include "types.h"
+#include "MidiBuffer.h"
using std::string;
namespace Ingen {
-class MidiMessage;
-template <typename T> class InputPort;
-template <typename T> class OutputPort;
+class InputPort;
+class OutputPort;
/** MIDI note input node.
@@ -74,11 +74,11 @@ private:
Key _keys[128];
bool _sustain; ///< Whether or not hold pedal is depressed
- InputPort<MidiMessage>* _midi_in_port;
- OutputPort<Sample>* _freq_port;
- OutputPort<Sample>* _vel_port;
- OutputPort<Sample>* _gate_port;
- OutputPort<Sample>* _trig_port;
+ InputPort* _midi_in_port;
+ OutputPort* _freq_port;
+ OutputPort* _vel_port;
+ OutputPort* _gate_port;
+ OutputPort* _trig_port;
};
diff --git a/src/libs/engine/MidiTriggerNode.cpp b/src/libs/engine/MidiTriggerNode.cpp
index d0beff60..9d78f7b8 100644
--- a/src/libs/engine/MidiTriggerNode.cpp
+++ b/src/libs/engine/MidiTriggerNode.cpp
@@ -15,9 +15,10 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "MidiTriggerNode.h"
#include <cmath>
#include <raul/midi_events.h>
+#include "MidiTriggerNode.h"
+#include "AudioBuffer.h"
#include "InputPort.h"
#include "OutputPort.h"
#include "Plugin.h"
@@ -31,22 +32,22 @@ MidiTriggerNode::MidiTriggerNode(const string& path, size_t poly, Patch* parent,
{
_ports = new Raul::Array<Port*>(5);
- _midi_in_port = new InputPort<MidiMessage>(this, "MIDIIn", 0, 1, DataType::MIDI, _buffer_size);
+ _midi_in_port = new InputPort(this, "MIDIIn", 0, 1, DataType::MIDI, _buffer_size);
_ports->at(0) = _midi_in_port;
- _note_port = new InputPort<Sample>(this, "NoteNumber", 1, 1, DataType::FLOAT, 1);
+ _note_port = new InputPort(this, "NoteNumber", 1, 1, DataType::FLOAT, 1);
// new PortInfo("Note Number", CONTROL, INPUT, INTEGER, 60, 0, 127), 1);
_ports->at(1) = _note_port;
- _gate_port = new OutputPort<Sample>(this, "Gate", 2, 1, DataType::FLOAT, _buffer_size);
+ _gate_port = new OutputPort(this, "Gate", 2, 1, DataType::FLOAT, _buffer_size);
// new PortInfo("Gate", AUDIO, OUTPUT, 0, 0, 1), _buffer_size);
_ports->at(2) = _gate_port;
- _trig_port = new OutputPort<Sample>(this, "Trigger", 3, 1, DataType::FLOAT, _buffer_size);
+ _trig_port = new OutputPort(this, "Trigger", 3, 1, DataType::FLOAT, _buffer_size);
// new PortInfo("Trigger", AUDIO, OUTPUT, 0, 0, 1), _buffer_size);
_ports->at(3) = _trig_port;
- _vel_port = new OutputPort<Sample>(this, "Velocity", 4, poly, DataType::FLOAT, _buffer_size);
+ _vel_port = new OutputPort(this, "Velocity", 4, poly, DataType::FLOAT, _buffer_size);
// new PortInfo("Velocity", AUDIO, OUTPUT, 0, 0, 1), _buffer_size);
_ports->at(4) = _vel_port;
@@ -61,27 +62,35 @@ MidiTriggerNode::process(SampleCount nframes, FrameTime start, FrameTime end)
{
InternalNode::process(nframes, start, end);
- MidiMessage ev;
-
- for (size_t i=0; i < _midi_in_port->buffer(0)->filled_size(); ++i) {
- ev = _midi_in_port->buffer(0)->value_at(i);
-
- switch (ev.buffer[0] & 0xF0) {
- case MIDI_CMD_NOTE_ON:
- if (ev.buffer[2] == 0)
- note_off(ev.buffer[1], ev.time, nframes, start, end);
- else
- note_on(ev.buffer[1], ev.buffer[2], ev.time, nframes, start, end);
- break;
- case MIDI_CMD_NOTE_OFF:
- note_off(ev.buffer[1], ev.time, nframes, start, end);
- break;
- case MIDI_CMD_CONTROL:
- if (ev.buffer[1] == MIDI_CTL_ALL_NOTES_OFF
- || ev.buffer[1] == MIDI_CTL_ALL_SOUNDS_OFF)
- _gate_port->buffer(0)->set(0.0f, ev.time);
- default:
- break;
+ double timestamp = 0;
+ uint32_t size = 0;
+ unsigned char* buffer = NULL;
+
+ MidiBuffer* const midi_in = (MidiBuffer*)_midi_in_port->buffer(0);
+ assert(midi_in->this_nframes() == nframes);
+
+ while (midi_in->get_event(&timestamp, &size, &buffer) < nframes) {
+
+ const FrameTime time = start + (FrameTime)timestamp;
+
+ if (size >= 3) {
+ switch (buffer[0] & 0xF0) {
+ case MIDI_CMD_NOTE_ON:
+ if (buffer[2] == 0)
+ note_off(buffer[1], time, nframes, start, end);
+ else
+ note_on(buffer[1], buffer[2], time, nframes, start, end);
+ break;
+ case MIDI_CMD_NOTE_OFF:
+ note_off(buffer[1], time, nframes, start, end);
+ break;
+ case MIDI_CMD_CONTROL:
+ if (buffer[1] == MIDI_CTL_ALL_NOTES_OFF
+ || buffer[1] == MIDI_CTL_ALL_SOUNDS_OFF)
+ ((AudioBuffer*)_gate_port->buffer(0))->set(0.0f, time);
+ default:
+ break;
+ }
}
}
}
@@ -95,7 +104,7 @@ MidiTriggerNode::note_on(uchar note_num, uchar velocity, FrameTime time, SampleC
//std::cerr << "Note on starting at sample " << offset << std::endl;
- const Sample filter_note = _note_port->buffer(0)->value_at(0);
+ const Sample filter_note = ((AudioBuffer*)_note_port->buffer(0))->value_at(0);
if (filter_note >= 0.0 && filter_note < 127.0 && (note_num == (uchar)filter_note)){
// FIXME FIXME FIXME
@@ -105,10 +114,10 @@ MidiTriggerNode::note_on(uchar note_num, uchar velocity, FrameTime time, SampleC
if (offset == (SampleCount)(_buffer_size-1))
--offset;
- _gate_port->buffer(0)->set(1.0f, offset);
- _trig_port->buffer(0)->set(1.0f, offset, offset);
- _trig_port->buffer(0)->set(0.0f, offset+1);
- _vel_port->buffer(0)->set(velocity/127.0f, offset);
+ ((AudioBuffer*)_gate_port->buffer(0))->set(1.0f, offset);
+ ((AudioBuffer*)_trig_port->buffer(0))->set(1.0f, offset, offset);
+ ((AudioBuffer*)_trig_port->buffer(0))->set(0.0f, offset+1);
+ ((AudioBuffer*)_vel_port->buffer(0))->set(velocity/127.0f, offset);
}
}
@@ -119,8 +128,8 @@ MidiTriggerNode::note_off(uchar note_num, FrameTime time, SampleCount nframes, F
assert(time >= start && time <= end);
assert(time - start < _buffer_size);
- if (note_num == lrintf(_note_port->buffer(0)->value_at(0)))
- _gate_port->buffer(0)->set(0.0f, time - start);
+ if (note_num == lrintf(((AudioBuffer*)_note_port->buffer(0))->value_at(0)))
+ ((AudioBuffer*)_gate_port->buffer(0))->set(0.0f, time - start);
}
diff --git a/src/libs/engine/MidiTriggerNode.h b/src/libs/engine/MidiTriggerNode.h
index 308174fb..f46e6dee 100644
--- a/src/libs/engine/MidiTriggerNode.h
+++ b/src/libs/engine/MidiTriggerNode.h
@@ -15,20 +15,19 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-
#ifndef MIDITRIGGERNODE_H
#define MIDITRIGGERNODE_H
#include <string>
#include "InternalNode.h"
+#include "MidiBuffer.h"
using std::string;
namespace Ingen {
-class MidiMessage;
-template <typename T> class InputPort;
-template <typename T> class OutputPort;
+class InputPort;
+class OutputPort;
/** MIDI trigger input node.
@@ -52,11 +51,11 @@ public:
void note_off(uchar note_num, FrameTime time, SampleCount nframes, FrameTime start, FrameTime end);
private:
- InputPort<MidiMessage>* _midi_in_port;
- InputPort<Sample>* _note_port;
- OutputPort<Sample>* _gate_port;
- OutputPort<Sample>* _trig_port;
- OutputPort<Sample>* _vel_port;
+ InputPort* _midi_in_port;
+ InputPort* _note_port;
+ OutputPort* _gate_port;
+ OutputPort* _trig_port;
+ OutputPort* _vel_port;
};
diff --git a/src/libs/engine/Node.h b/src/libs/engine/Node.h
index 852751fb..4fe43d03 100644
--- a/src/libs/engine/Node.h
+++ b/src/libs/engine/Node.h
@@ -30,13 +30,12 @@ namespace Raul { template <typename T> class List; }
namespace Ingen {
-class Port;
-template <typename T> class OutputPort;
+class Buffer;
class Plugin;
class Patch;
-namespace Shared {
- class ClientInterface;
-}
+class Port;
+class OutputPort;
+namespace Shared { class ClientInterface; }
/** A Node (or "module") in a Patch (which is also a Node).
@@ -73,7 +72,7 @@ public:
*/
virtual void process(SampleCount nframes, FrameTime start, FrameTime end) = 0;
- virtual void set_port_buffer(size_t voice, size_t port_num, void* buf) = 0;
+ virtual void set_port_buffer(size_t voice, size_t port_num, Buffer* buf) = 0;
// FIXME: Only used by client senders. Remove?
virtual const Raul::Array<Port*>& ports() const = 0;
diff --git a/src/libs/engine/NodeBase.h b/src/libs/engine/NodeBase.h
index e78aaab2..8fed6196 100644
--- a/src/libs/engine/NodeBase.h
+++ b/src/libs/engine/NodeBase.h
@@ -55,7 +55,7 @@ public:
virtual void process(SampleCount nframes, FrameTime start, FrameTime end);
- virtual void set_port_buffer(size_t voice, size_t port_num, void* buf) {}
+ virtual void set_port_buffer(size_t voice, size_t port_num, Buffer* buf) {}
virtual void set_buffer_size(size_t size);
diff --git a/src/libs/engine/OSCClientSender.cpp b/src/libs/engine/OSCClientSender.cpp
index ee4653e5..a1f82fd5 100644
--- a/src/libs/engine/OSCClientSender.cpp
+++ b/src/libs/engine/OSCClientSender.cpp
@@ -25,7 +25,7 @@
#include "Patch.h"
#include "Node.h"
#include "Plugin.h"
-#include "TypedPort.h"
+#include "Port.h"
#include "Connection.h"
#include "AudioDriver.h"
#include "interface/ClientInterface.h"
diff --git a/src/libs/engine/ObjectSender.cpp b/src/libs/engine/ObjectSender.cpp
index ce480316..50e47c48 100644
--- a/src/libs/engine/ObjectSender.cpp
+++ b/src/libs/engine/ObjectSender.cpp
@@ -21,9 +21,11 @@
#include "Patch.h"
#include "Node.h"
#include "Port.h"
-#include "TypedPort.h"
+#include "Port.h"
#include "Connection.h"
#include "NodeFactory.h"
+#include "DataType.h"
+#include "AudioBuffer.h"
namespace Ingen {
@@ -144,8 +146,8 @@ ObjectSender::send_port(ClientInterface* client, const Port* port)
// Send control value
if (port->type() == DataType::FLOAT && port->buffer_size() == 1) {
- Sample default_value = dynamic_cast<const TypedPort<Sample>*>(
- port)->buffer(0)->value_at(0);
+ Sample default_value = dynamic_cast<const AudioBuffer*>(
+ port->buffer(0))->value_at(0);
//cerr << port->path() << " sending default value " << default_value << endl;
client->control_change(port->path(), default_value);
}
diff --git a/src/libs/engine/OutputPort.h b/src/libs/engine/OutputPort.h
index 6c029850..10118076 100644
--- a/src/libs/engine/OutputPort.h
+++ b/src/libs/engine/OutputPort.h
@@ -20,13 +20,11 @@
#include <string>
#include <cstdlib>
-#include "TypedPort.h"
+#include "Port.h"
#include "types.h"
namespace Ingen {
-template <typename T> class InputPort;
-
/** An output port.
*
@@ -39,14 +37,16 @@ template <typename T> class InputPort;
*
* \ingroup engine
*/
-template <typename T>
-class OutputPort : virtual public TypedPort<T>
+class OutputPort : virtual public Port
{
public:
- OutputPort(Node* parent, const string& name,
- size_t index, size_t poly,
- DataType type, size_t buffer_size)
- : TypedPort<T>(parent, name, index, poly, type, buffer_size)
+ OutputPort(Node* parent,
+ const string& name,
+ size_t index,
+ size_t poly,
+ DataType type,
+ size_t buffer_size)
+ : Port(parent, name, index, poly, type, buffer_size)
{}
virtual ~OutputPort() {}
@@ -56,8 +56,6 @@ public:
};
-template class OutputPort<Sample>;
-
} // namespace Ingen
#endif // OUTPUTPORT_H
diff --git a/src/libs/engine/Patch.cpp b/src/libs/engine/Patch.cpp
index 9b32b74a..a2b5a85f 100644
--- a/src/libs/engine/Patch.cpp
+++ b/src/libs/engine/Patch.cpp
@@ -271,13 +271,7 @@ Patch::create_port(const string& name, DataType type, size_t buffer_size, bool i
assert( !(type == DataType::UNKNOWN) );
- // FIXME: is it possible to just "pass" the type directly as the template parameter somehow?
- if (type == DataType::FLOAT)
- return new DuplexPort<Sample>(this, name, 0, _poly, type, buffer_size, is_output);
- else if (type == DataType::MIDI)
- return new DuplexPort<MidiMessage>(this, name, 0, _poly, type, buffer_size, is_output);
- else
- return NULL;
+ return new DuplexPort(this, name, 0, _poly, type, buffer_size, is_output);
}
diff --git a/src/libs/engine/Port.cpp b/src/libs/engine/Port.cpp
index 7ab811b2..4b9a014b 100644
--- a/src/libs/engine/Port.cpp
+++ b/src/libs/engine/Port.cpp
@@ -18,6 +18,8 @@
#include "Port.h"
#include "Node.h"
#include "DataType.h"
+#include "Buffer.h"
+#include "BufferFactory.h"
namespace Ingen {
@@ -27,14 +29,73 @@ const char* const DataType::type_uris[3] = { "UNKNOWN", "FLOAT", "MIDI" };
Port::Port(Node* const node, const string& name, size_t index, size_t poly, DataType type, size_t buffer_size)
-: GraphObject(node, name),
- _index(index),
- _poly(poly),
- _type(type),
- _buffer_size(buffer_size)
+ : GraphObject(node, name)
+ , _index(index)
+ , _poly(poly)
+ , _type(type)
+ , _buffer_size(buffer_size)
+ , _fixed_buffers(false)
{
assert(node != NULL);
assert(_poly > 0);
+
+ allocate_buffers();
+ clear_buffers();
+
+ assert(_buffers.size() > 0);
+}
+
+
+Port::~Port()
+{
+ for (size_t i=0; i < _poly; ++i)
+ delete _buffers.at(i);
+}
+
+
+void
+Port::allocate_buffers()
+{
+ _buffers.alloc(_poly);
+
+ for (size_t i=0; i < _poly; ++i)
+ _buffers.at(i) = BufferFactory::create(_type, _buffer_size);
+}
+
+
+void
+Port::set_buffer_size(size_t size)
+{
+ _buffer_size = size;
+
+ for (size_t i=0; i < _poly; ++i)
+ _buffers.at(i)->resize(size);
+
+ connect_buffers();
+}
+
+
+void
+Port::connect_buffers()
+{
+ for (size_t i=0; i < _poly; ++i)
+ Port::parent_node()->set_port_buffer(i, _index, _buffers.at(i));
+}
+
+
+void
+Port::clear_buffers()
+{
+ for (size_t i=0; i < _poly; ++i)
+ _buffers.at(i)->clear();
+}
+
+
+void
+Port::process(SampleCount nframes, FrameTime start, FrameTime end)
+{
+ for (size_t i=0; i < _poly; ++i)
+ _buffers.at(i)->prepare(nframes);
}
diff --git a/src/libs/engine/Port.h b/src/libs/engine/Port.h
index 3473e054..b42231fe 100644
--- a/src/libs/engine/Port.h
+++ b/src/libs/engine/Port.h
@@ -20,6 +20,7 @@
#include <cstdlib>
#include <string>
+#include <raul/Array.h>
#include "types.h"
#include "GraphObject.h"
#include "DataType.h"
@@ -29,6 +30,7 @@ using std::string;
namespace Ingen {
class Node;
+class Buffer;
/** A port on a Node.
@@ -42,36 +44,45 @@ class Node;
class Port : public GraphObject
{
public:
- virtual ~Port() {}
+ virtual ~Port();
/** A port's parent is always a node, so static cast should be safe */
Node* parent_node() const { return (Node*)_parent; }
+ Buffer* buffer(size_t voice) const { return _buffers.at(voice); }
+
/** Called once per process cycle */
- virtual void process(SampleCount nframes, FrameTime start, FrameTime end) = 0;
+ virtual void process(SampleCount nframes, FrameTime start, FrameTime end);
/** Empty buffer contents completely (ie silence) */
- virtual void clear_buffers() = 0;
+ virtual void clear_buffers();
virtual bool is_input() const = 0;
virtual bool is_output() const = 0;
- bool is_sample() const { return false; }
size_t num() const { return _index; }
size_t poly() const { return _poly; }
DataType type() const { return _type; }
size_t buffer_size() const { return _buffer_size; }
- virtual void set_buffer_size(size_t size) = 0;
- virtual void connect_buffers() = 0;
+ virtual void set_buffer_size(size_t size);
+
+ void fixed_buffers(bool b) { _fixed_buffers = b; }
+ bool fixed_buffers() { return _fixed_buffers; }
protected:
Port(Node* const node, const string& name, size_t index, size_t poly, DataType type, size_t buffer_size);
+ virtual void allocate_buffers();
+ virtual void connect_buffers();
+
size_t _index;
size_t _poly;
DataType _type;
size_t _buffer_size;
+ bool _fixed_buffers;
+
+ Raul::Array<Buffer*> _buffers;
};
diff --git a/src/libs/engine/TypedConnection.cpp b/src/libs/engine/TypedConnection.cpp
deleted file mode 100644
index 677a5f4f..00000000
--- a/src/libs/engine/TypedConnection.cpp
+++ /dev/null
@@ -1,123 +0,0 @@
-/* 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 "TypedConnection.h"
-#include "util.h"
-#include "InputPort.h"
-#include "OutputPort.h"
-#include "Node.h"
-#include "Port.h"
-
-namespace Ingen {
-
-
-/** Constructor for a connection from a node's output port.
- *
- * This handles both polyphonic and monophonic nodes, transparently to the
- * user (InputPort).
- */
-template <typename T>
-TypedConnection<T>::TypedConnection(OutputPort<T>* const src_port, InputPort<T>* const dst_port)
-: Connection(src_port, dst_port),
- _local_buffer(NULL),
- _must_mix(true),
- _buffer_size(src_port->buffer_size()),
- _pending_disconnection(false)
-{
- assert((src_port->parent_node()->poly() == dst_port->parent_node()->poly())
- || (src_port->parent_node()->poly() == 1 || dst_port->parent_node()->poly() == 1));
-
- if (src_port->poly() == dst_port->poly())
- _must_mix = false;
- else // Poly -> Mono connection, need a buffer to mix into
- _local_buffer = new Buffer<T>(_buffer_size);
-
- //cerr << "Connection " << src_port->path() << " -> " << dst_port->path()
- // << "\t mixing: " << _must_mix << endl;
-}
-template TypedConnection<Sample>::TypedConnection(OutputPort<Sample>* const src_port, InputPort<Sample>* const dst_port);
-template TypedConnection<MidiMessage>::TypedConnection(OutputPort<MidiMessage>* const src_port, InputPort<MidiMessage>* const dst_port);
-
-
-template <typename T>
-TypedConnection<T>::~TypedConnection()
-{
- delete _local_buffer;
-}
-template TypedConnection<Sample>::~TypedConnection();
-template TypedConnection<MidiMessage>::~TypedConnection();
-
-
-/** Allocate a mixdown buffer if necessary */
-template <typename T>
-void
-TypedConnection<T>::set_buffer_size(size_t size)
-{
- if (_must_mix) {
- assert(_local_buffer);
- delete _local_buffer;
-
- _local_buffer = new Buffer<T>(size);
- }
-
- _buffer_size = size;
-}
-
-
-template <typename Sample>
-void
-TypedConnection<Sample>::process(SampleCount nframes, FrameTime start, FrameTime end)
-{
- // FIXME: nframes parameter not used
- assert(_buffer_size == 1 || _buffer_size == nframes);
-
- /* Thought: A poly output port can be connected to multiple mono input
- * ports, which means this mix down would have to happen many times.
- * Adding a method to OutputPort that mixes down all it's outputs into
- * a buffer (if it hasn't been done already this cycle) and returns that
- * would avoid having to mix multiple times. Probably not a very common
- * case, but it would be faster anyway. */
-
- if (_must_mix) {
- //cerr << "Mixing " << src_port()->buffer(0)->data()
- // << " -> " << _local_buffer->data() << endl;
-
- _local_buffer->copy(src_port()->buffer(0), 0, _buffer_size-1);
-
- // Mix all the source's voices down into local buffer starting at the second
- // voice (buffer is already set to first voice above)
- for (size_t j=1; j < src_port()->poly(); ++j)
- _local_buffer->accumulate(src_port()->buffer(j), 0, _buffer_size-1);
-
- // Scale the buffer down.
- if (src_port()->poly() > 1)
- _local_buffer->scale(1.0f/(float)src_port()->poly(), 0, _buffer_size-1);
- }
-}
-template void TypedConnection<Sample>::process(SampleCount nframes, FrameTime start, FrameTime end);
-
-
-// FIXME: MIDI mixing not implemented
-template <>
-void
-TypedConnection<MidiMessage>::process(SampleCount nframes, FrameTime start, FrameTime end)
-{
-}
-
-
-} // namespace Ingen
-
diff --git a/src/libs/engine/TypedConnection.h b/src/libs/engine/TypedConnection.h
deleted file mode 100644
index 1c7f3dc7..00000000
--- a/src/libs/engine/TypedConnection.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/* 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 TYPEDCONNECTION_H
-#define TYPEDCONNECTION_H
-
-#include "types.h"
-#include "OutputPort.h"
-#include "Connection.h"
-
-namespace Ingen {
-
-class MidiMessage;
-class Port;
-template <typename T> class InputPort;
-
-
-/** A Connection with a type.
- *
- * \ingroup engine
- */
-template <typename T>
-class TypedConnection : public Connection
-{
-public:
- TypedConnection(OutputPort<T>* const src_port, InputPort<T>* const dst_port);
- virtual ~TypedConnection();
-
- void process(SampleCount nframes, FrameTime start, FrameTime end);
-
- inline OutputPort<T>* src_port() const { return dynamic_cast<OutputPort<T>*>(_src_port); }
- inline InputPort<T>* dst_port() const { return dynamic_cast<InputPort<T>*>(_dst_port); }
-
- /** Used by some (recursive) events to prevent double disconnections */
- bool pending_disconnection() { return _pending_disconnection; }
- void pending_disconnection(bool b) { _pending_disconnection = b; }
-
- /** Get the buffer for a particular voice.
- * A TypedConnection is smart - it knows the destination port respondering the
- * buffer, and will return accordingly (ie the same buffer for every voice
- * in a mono->poly connection).
- */
- inline Buffer<T>* buffer(size_t voice) const;
-
- void set_buffer_size(size_t size);
-
-private:
- Buffer<T>* _local_buffer; ///< Only used for poly->mono connections
- bool _must_mix;
- size_t _buffer_size;
- bool _pending_disconnection;
-};
-
-
-template <>
-inline Buffer<Sample>*
-TypedConnection<Sample>::buffer(size_t voice) const
-{
- TypedPort<Sample>* const src_port = (TypedPort<Sample>*)_src_port;
-
- if (_must_mix) {
- return _local_buffer;
- } else {
- if (src_port->poly() == 1)
- return src_port->buffer(0);
- else
- return src_port->buffer(voice);
- }
-}
-
-
-template <>
-inline Buffer<MidiMessage>*
-TypedConnection<MidiMessage>::buffer(size_t voice) const
-{
- // No such thing as polyphonic MIDI ports
- assert(_src_port->poly() == 1);
- assert(_dst_port->poly() == 1);
-
- TypedPort<MidiMessage>* const src_port = (TypedPort<MidiMessage>*)_src_port;
- return src_port->buffer(0);
-}
-
-
-template class TypedConnection<Sample>;
-template class TypedConnection<MidiMessage>;
-
-} // namespace Ingen
-
-#endif // TYPEDCONNECTION_H
diff --git a/src/libs/engine/TypedPort.cpp b/src/libs/engine/TypedPort.cpp
deleted file mode 100644
index 0432ec4c..00000000
--- a/src/libs/engine/TypedPort.cpp
+++ /dev/null
@@ -1,154 +0,0 @@
-/* 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 "TypedPort.h"
-#include <cmath>
-#include <cstdlib>
-#include <iostream>
-#include <cassert>
-#include <sys/mman.h>
-#include "util.h"
-#include "Node.h"
-#include "MidiMessage.h"
-
-namespace Ingen {
-
-
-/** Constructor for a Port.
- */
-template <typename T>
-TypedPort<T>::TypedPort(Node* parent, const string& name, size_t index, size_t poly, DataType type, size_t buffer_size)
-: Port(parent, name, index, poly, type, buffer_size)
-, _fixed_buffers(false)
-{
- allocate_buffers();
- clear_buffers();
-
- assert(_buffers.size() > 0);
-}
-template
-TypedPort<Sample>::TypedPort(Node* parent, const string& name, size_t index, size_t poly, DataType type, size_t buffer_size);
-template
-TypedPort<MidiMessage>::TypedPort(Node* parent, const string& name, size_t index, size_t poly, DataType type, size_t buffer_size);
-
-
-template <typename T>
-TypedPort<T>::~TypedPort()
-{
- for (size_t i=0; i < _poly; ++i)
- delete _buffers.at(i);
-}
-template TypedPort<Sample>::~TypedPort();
-template TypedPort<MidiMessage>::~TypedPort();
-
-
-/** Set the port's value for all voices.
- */
-template<>
-void
-TypedPort<Sample>::set_value(Sample val, size_t offset)
-{
- if (offset >= _buffer_size)
- offset = 0;
- assert(offset < _buffer_size);
-
- for (size_t v=0; v < _poly; ++v)
- _buffers.at(v)->set(val, offset);
-}
-
-/** Set the port's value for a specific voice.
- */
-template<>
-void
-TypedPort<Sample>::set_value(size_t voice, Sample val, size_t offset)
-{
- if (offset >= _buffer_size)
- offset = 0;
- assert(offset < _buffer_size);
-
- cerr << path() << " setting voice value " << val << endl;
-
- _buffers.at(voice)->set(val, offset);
-}
-
-
-template <typename T>
-void
-TypedPort<T>::allocate_buffers()
-{
- _buffers.alloc(_poly);
-
- for (size_t i=0; i < _poly; ++i)
- _buffers.at(i) = new Buffer<T>(_buffer_size);
-}
-template void TypedPort<Sample>::allocate_buffers();
-template void TypedPort<MidiMessage>::allocate_buffers();
-
-
-template <typename T>
-void
-TypedPort<T>::set_buffer_size(size_t size)
-{
- _buffer_size = size;
-
- for (size_t i=0; i < _poly; ++i)
- _buffers.at(i)->resize(size);
-
- connect_buffers();
-}
-template void TypedPort<Sample>::set_buffer_size(size_t size);
-template void TypedPort<MidiMessage>::set_buffer_size(size_t size);
-
-
-/** Update any changed buffers with the plugin this is a port on.
- *
- * This calls ie the LADSPA connect_port function when buffers have been changed
- * due to a connection, disconnection, resize, etc.
- */
-template <typename T>
-void
-TypedPort<T>::connect_buffers()
-{
- for (size_t i=0; i < _poly; ++i)
- TypedPort<T>::parent_node()->set_port_buffer(i, _index, _buffers.at(i)->data());
-}
-template void TypedPort<Sample>::connect_buffers();
-template void TypedPort<MidiMessage>::connect_buffers();
-
-
-template<typename T>
-void
-TypedPort<T>::clear_buffers()
-{
- for (size_t i=0; i < _poly; ++i)
- _buffers.at(i)->clear();
-}
-template void TypedPort<Sample>::clear_buffers();
-template void TypedPort<MidiMessage>::clear_buffers();
-
-
-template <typename T>
-void
-TypedPort<T>::process(SampleCount nframes, FrameTime start, FrameTime end)
-{
- for (size_t i=0; i < _poly; ++i)
- _buffers.at(i)->prepare(nframes);
-}
-
-
-} // namespace Ingen
-
diff --git a/src/libs/engine/TypedPort.h b/src/libs/engine/TypedPort.h
deleted file mode 100644
index 2dc687a5..00000000
--- a/src/libs/engine/TypedPort.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* 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 TYPEDPORT_H
-#define TYPEDPORT_H
-
-#include <string>
-#include "types.h"
-#include <raul/Array.h>
-#include "Port.h"
-#include "Buffer.h"
-
-using std::string;
-
-namespace Ingen {
-
-class MidiMessage;
-class Node;
-
-
-/** A port (with a type).
- *
- * This is basically just a buffer and a bunch of flags and helper methods.
- * All the interesting functionality of ports is in InputPort.
- *
- * \ingroup engine
- */
-template <typename T>
-class TypedPort : public Port
-{
-public:
- virtual ~TypedPort();
-
- void set_value(size_t voice, T val, size_t offset);
- void set_value(T val, size_t offset);
-
- Buffer<T>* buffer(size_t voice) const { return _buffers.at(voice); }
-
- virtual void process(SampleCount nframes, FrameTime start, FrameTime end);
- virtual void clear_buffers();
-
- /** Used by drivers to prevent port from changing buffers */
- void fixed_buffers(bool b) { _fixed_buffers = b; }
- bool fixed_buffers() { return _fixed_buffers; }
-
- virtual void set_buffer_size(size_t size);
-
-protected:
- TypedPort(Node* parent, const string& name, size_t index, size_t poly, DataType type, size_t buffer_size);
-
- void allocate_buffers();
- void connect_buffers();
-
- bool _fixed_buffers;
-
- Raul::Array<Buffer<T>*> _buffers;
-};
-
-
-template class TypedPort<Sample>;
-template class TypedPort<MidiMessage>;
-
-} // namespace Ingen
-
-#endif // TYPEDPORT_H
diff --git a/src/libs/engine/events/AddPortEvent.cpp b/src/libs/engine/events/AddPortEvent.cpp
index 8ca2f85f..c9f22cd1 100644
--- a/src/libs/engine/events/AddPortEvent.cpp
+++ b/src/libs/engine/events/AddPortEvent.cpp
@@ -113,10 +113,10 @@ AddPortEvent::pre_process()
if (!_patch->parent()) {
if (_type == "ingen:audio")
_driver_port = _engine.audio_driver()->create_port(
- dynamic_cast<DuplexPort<Sample>*>(_patch_port));
+ dynamic_cast<DuplexPort*>(_patch_port));
else if (_type == "ingen:midi")
_driver_port = _engine.midi_driver()->create_port(
- dynamic_cast<DuplexPort<MidiMessage>*>(_patch_port));
+ dynamic_cast<DuplexPort*>(_patch_port));
}
assert(_ports_array->size() == _patch->num_ports());
diff --git a/src/libs/engine/events/ConnectionEvent.cpp b/src/libs/engine/events/ConnectionEvent.cpp
index da723a8c..af35265b 100644
--- a/src/libs/engine/events/ConnectionEvent.cpp
+++ b/src/libs/engine/events/ConnectionEvent.cpp
@@ -22,7 +22,7 @@
#include "Responder.h"
#include "types.h"
#include "Engine.h"
-#include "TypedConnection.h"
+#include "Connection.h"
#include "InputPort.h"
#include "OutputPort.h"
#include "Patch.h"
@@ -34,9 +34,6 @@ using std::string;
namespace Ingen {
-//// ConnectionEvent ////
-
-
ConnectionEvent::ConnectionEvent(Engine& engine, SharedPtr<Responder> responder, SampleCount timestamp, const string& src_port_path, const string& dst_port_path)
: QueuedEvent(engine, responder, timestamp),
_src_port_path(src_port_path),
@@ -44,18 +41,15 @@ ConnectionEvent::ConnectionEvent(Engine& engine, SharedPtr<Responder> responder,
_patch(NULL),
_src_port(NULL),
_dst_port(NULL),
- _typed_event(NULL),
+ _process_order(NULL),
+ _connection(NULL),
+ _patch_listnode(NULL),
+ _port_listnode(NULL),
_error(NO_ERROR)
{
}
-ConnectionEvent::~ConnectionEvent()
-{
- delete _typed_event;
-}
-
-
void
ConnectionEvent::pre_process()
{
@@ -67,14 +61,6 @@ ConnectionEvent::pre_process()
return;
}
- /*_patch = _engine.object_store()->find_patch(_src_port_path.parent().parent());
-
- if (_patch == NULL) {
- _error = PORT_NOT_FOUND;
- QueuedEvent::pre_process();
- return;
- }*/
-
_src_port = _engine.object_store()->find_port(_src_port_path);
_dst_port = _engine.object_store()->find_port(_dst_port_path);
@@ -84,96 +70,33 @@ ConnectionEvent::pre_process()
return;
}
- if (_src_port->type() != _dst_port->type() || _src_port->buffer_size() != _dst_port->buffer_size()) {
+ if (_src_port->type() != _dst_port->type()) {
_error = TYPE_MISMATCH;
QueuedEvent::pre_process();
return;
}
-
- /*if (port1->is_output() && port2->is_input()) {
- _src_port = port1;
- _dst_port = port2;
- } else if (port2->is_output() && port1->is_input()) {
- _src_port = port2;
- _dst_port = port1;
- } else {
+
+ // FIXME: MIDI buffer size is a kluge all around
+ if (_src_port->type() == DataType::FLOAT
+ && _src_port->buffer_size() != _dst_port->buffer_size()) {
_error = TYPE_MISMATCH;
QueuedEvent::pre_process();
return;
- }*/
-
- // Create the typed event to actually do the work
- const DataType type = _src_port->type();
- if (type == DataType::FLOAT) {
- _typed_event = new TypedConnectionEvent<Sample>(_engine, _responder, _time,
- dynamic_cast<OutputPort<Sample>*>(_src_port), dynamic_cast<InputPort<Sample>*>(_dst_port));
- } else if (type == DataType::MIDI) {
- _typed_event = new TypedConnectionEvent<MidiMessage>(_engine, _responder, _time,
- dynamic_cast<OutputPort<MidiMessage>*>(_src_port), dynamic_cast<InputPort<MidiMessage>*>(_dst_port));
- } else {
+ }
+
+ /*if ( !( _src_port->is_output() && _dst_port->is_input() ) ) {
_error = TYPE_MISMATCH;
QueuedEvent::pre_process();
return;
- }
-
- assert(_typed_event);
- _typed_event->pre_process();
- assert(_typed_event->is_prepared());
-
- QueuedEvent::pre_process();
-}
-
-
-void
-ConnectionEvent::execute(SampleCount nframes, FrameTime start, FrameTime end)
-{
- QueuedEvent::execute(nframes, start, end);
-
- if (_error == NO_ERROR)
- _typed_event->execute(nframes, start, end);
-}
-
-
-void
-ConnectionEvent::post_process()
-{
- if (_error == NO_ERROR) {
- _typed_event->post_process();
- } else {
- // FIXME: better error messages
- string msg = "Unable to make connection ";
- msg.append(_src_port_path + " -> " + _dst_port_path);
- _responder->respond_error(msg);
- }
-}
-
-
-
-//// TypedConnectionEvent ////
-
-
-template <typename T>
-TypedConnectionEvent<T>::TypedConnectionEvent(Engine& engine, SharedPtr<Responder> responder, SampleCount timestamp, OutputPort<T>* src_port, InputPort<T>* dst_port)
-: QueuedEvent(engine, responder, timestamp),
- _src_port(src_port),
- _dst_port(dst_port),
- _patch(NULL),
- _process_order(NULL),
- _connection(NULL),
- _port_listnode(NULL),
- _succeeded(true)
-{
- assert(src_port != NULL);
- assert(dst_port != NULL);
-}
+ }*/
+ _dst_input_port = dynamic_cast<InputPort*>(_dst_port);
+ _src_output_port = dynamic_cast<OutputPort*>(_src_port);
+ assert(_src_output_port);
+ assert(_dst_input_port);
-template <typename T>
-void
-TypedConnectionEvent<T>::pre_process()
-{
- if (_dst_port->is_connected_to(_src_port)) {
- _succeeded = false;
+ if (_dst_input_port->is_connected_to(_src_output_port)) {
+ _error = ALREADY_CONNECTED;
QueuedEvent::pre_process();
return;
}
@@ -202,19 +125,19 @@ TypedConnectionEvent<T>::pre_process()
assert(_patch);
if (src_node == NULL || dst_node == NULL) {
- _succeeded = false;
+ _error = PARENTS_NOT_FOUND;
QueuedEvent::pre_process();
return;
}
if (_patch != src_node && src_node->parent() != _patch && dst_node->parent() != _patch) {
- _succeeded = false;
+ _error = PARENTS_NOT_FOUND;
QueuedEvent::pre_process();
return;
}
- _connection = new TypedConnection<T>(_src_port, _dst_port);
- _port_listnode = new Raul::ListNode<TypedConnection<T>*>(_connection);
+ _connection = new Connection(_src_port, _dst_port);
+ _port_listnode = new Raul::ListNode<Connection*>(_connection);
_patch_listnode = new Raul::ListNode<Connection*>(_connection);
// Need to be careful about patch port connections here and adding a node's
@@ -227,20 +150,18 @@ TypedConnectionEvent<T>::pre_process()
if (_patch->enabled())
_process_order = _patch->build_process_order();
- _succeeded = true;
QueuedEvent::pre_process();
}
-template <typename T>
void
-TypedConnectionEvent<T>::execute(SampleCount nframes, FrameTime start, FrameTime end)
+ConnectionEvent::execute(SampleCount nframes, FrameTime start, FrameTime end)
{
QueuedEvent::execute(nframes, start, end);
- if (_succeeded) {
+ if (_error == NO_ERROR) {
// These must be inserted here, since they're actually used by the audio thread
- _dst_port->add_connection(_port_listnode);
+ _dst_input_port->add_connection(_port_listnode);
_patch->add_connection(_patch_listnode);
if (_patch->process_order() != NULL)
_engine.maid()->push(_patch->process_order());
@@ -249,18 +170,17 @@ TypedConnectionEvent<T>::execute(SampleCount nframes, FrameTime start, FrameTime
}
-template <typename T>
void
-TypedConnectionEvent<T>::post_process()
+ConnectionEvent::post_process()
{
- if (_succeeded) {
- assert(_connection != NULL);
-
+ if (_error == NO_ERROR) {
_responder->respond_ok();
-
_engine.broadcaster()->send_connection(_connection);
} else {
- _responder->respond_error("Unable to make connection.");
+ // FIXME: better error messages
+ string msg = "Unable to make connection ";
+ msg.append(_src_port_path + " -> " + _dst_port_path);
+ _responder->respond_error(msg);
}
}
diff --git a/src/libs/engine/events/ConnectionEvent.h b/src/libs/engine/events/ConnectionEvent.h
index 79ffeaa3..8f5e1cc2 100644
--- a/src/libs/engine/events/ConnectionEvent.h
+++ b/src/libs/engine/events/ConnectionEvent.h
@@ -36,10 +36,9 @@ class Node;
class Connection;
class MidiMessage;
class Port;
-template <typename T> class TypedConnection;
-template <typename T> class InputPort;
-template <typename T> class OutputPort;
-template <typename T> class TypedConnectionEvent; // helper, defined below
+class Connection;
+class InputPort;
+class OutputPort;
/** Make a Connection between two Ports.
@@ -50,7 +49,6 @@ class ConnectionEvent : public QueuedEvent
{
public:
ConnectionEvent(Engine& engine, SharedPtr<Responder> responder, SampleCount timestamp, const string& src_port_path, const string& dst_port_path);
- ~ConnectionEvent();
void pre_process();
void execute(SampleCount nframes, FrameTime start, FrameTime end);
@@ -58,52 +56,34 @@ public:
private:
- enum ErrorType { NO_ERROR, PARENT_PATCH_DIFFERENT, PORT_NOT_FOUND, TYPE_MISMATCH };
+ enum ErrorType {
+ NO_ERROR,
+ PARENT_PATCH_DIFFERENT,
+ PORT_NOT_FOUND,
+ TYPE_MISMATCH,
+ ALREADY_CONNECTED,
+ PARENTS_NOT_FOUND
+ };
Raul::Path _src_port_path;
Raul::Path _dst_port_path;
- Patch* _patch;
- Port* _src_port;
- Port* _dst_port;
-
- QueuedEvent* _typed_event;
-
- ErrorType _error;
-};
+ Patch* _patch;
+ Port* _src_port;
+ Port* _dst_port;
+ OutputPort* _src_output_port;
+ InputPort* _dst_input_port;
-
-/** Templated ConnectionEvent.
- *
- * Intended to be called from ConnectionEvent so callers (ie OSCReceiver)
- * can use ConnectionEvent without knowing anything about types (which
- * they can't, since all they have is Port paths).
- */
-template <typename T>
-class TypedConnectionEvent : public QueuedEvent
-{
-public:
- TypedConnectionEvent(Engine& engine, SharedPtr<Responder> responder, FrameTime time, OutputPort<T>* src_port, InputPort<T>* dst_port);
+ Raul::Array<Node*>* _process_order; ///< New process order for Patch
- void pre_process();
- void execute(SampleCount nframes, FrameTime start, FrameTime end);
- void post_process();
+ Connection* _connection;
+ Raul::ListNode<Connection*>* _patch_listnode;
+ Raul::ListNode<Connection*>* _port_listnode;
-private:
- OutputPort<T>* _src_port;
- InputPort<T>* _dst_port;
-
- Patch* _patch;
- Raul::Array<Node*>* _process_order; ///< New process order for Patch
- TypedConnection<T>* _connection;
- Raul::ListNode<Connection*>* _patch_listnode;
- Raul::ListNode<TypedConnection<T>*>* _port_listnode;
-
- bool _succeeded;
+ ErrorType _error;
};
-
} // namespace Ingen
#endif // CONNECTIONEVENT_H
diff --git a/src/libs/engine/events/DisconnectNodeEvent.cpp b/src/libs/engine/events/DisconnectNodeEvent.cpp
index 916c1045..8f2a90f2 100644
--- a/src/libs/engine/events/DisconnectNodeEvent.cpp
+++ b/src/libs/engine/events/DisconnectNodeEvent.cpp
@@ -23,7 +23,7 @@
#include "Responder.h"
#include "Engine.h"
#include "Node.h"
-#include "TypedConnection.h"
+#include "Connection.h"
#include "DisconnectionEvent.h"
#include "Port.h"
#include "InputPort.h"
diff --git a/src/libs/engine/events/DisconnectNodeEvent.h b/src/libs/engine/events/DisconnectNodeEvent.h
index bf4644ad..270fa960 100644
--- a/src/libs/engine/events/DisconnectNodeEvent.h
+++ b/src/libs/engine/events/DisconnectNodeEvent.h
@@ -31,10 +31,9 @@ class DisconnectionEvent;
class Patch;
class Node;
class Connection;
-template <typename T> class TypedConnection;
class Port;
-template <typename T> class InputPort;
-template <typename T> class OutputPort;
+class InputPort;
+class OutputPort;
/** An event to disconnect all connections to a Node.
diff --git a/src/libs/engine/events/DisconnectionEvent.cpp b/src/libs/engine/events/DisconnectionEvent.cpp
index d5e788ef..aef271f4 100644
--- a/src/libs/engine/events/DisconnectionEvent.cpp
+++ b/src/libs/engine/events/DisconnectionEvent.cpp
@@ -21,7 +21,7 @@
#include <raul/Path.h>
#include "Responder.h"
#include "Engine.h"
-#include "TypedConnection.h"
+#include "Connection.h"
#include "InputPort.h"
#include "OutputPort.h"
#include "Patch.h"
@@ -44,7 +44,7 @@ DisconnectionEvent::DisconnectionEvent(Engine& engine, SharedPtr<Responder> resp
_src_port(NULL),
_dst_port(NULL),
_lookup(true),
- _typed_event(NULL),
+ _process_order(NULL),
_error(NO_ERROR)
{
}
@@ -58,7 +58,7 @@ DisconnectionEvent::DisconnectionEvent(Engine& engine, SharedPtr<Responder> resp
_src_port(src_port),
_dst_port(dst_port),
_lookup(false),
- _typed_event(NULL),
+ _process_order(NULL),
_error(NO_ERROR)
{
// FIXME: These break for patch ports.. is that ok?
@@ -69,11 +69,6 @@ DisconnectionEvent::DisconnectionEvent(Engine& engine, SharedPtr<Responder> resp
== dst_port->parent_node()->parent_patch()); */
}
-DisconnectionEvent::~DisconnectionEvent()
-{
- delete _typed_event;
-}
-
void
DisconnectionEvent::pre_process()
@@ -87,14 +82,6 @@ DisconnectionEvent::pre_process()
return;
}
- /*_patch = _engine.object_store()->find_patch(_src_port_path.parent().parent());
-
- if (_patch == NULL) {
- _error = PORT_NOT_FOUND;
- QueuedEvent::pre_process();
- return;
- }*/
-
_src_port = _engine.object_store()->find_port(_src_port_path);
_dst_port = _engine.object_store()->find_port(_dst_port_path);
}
@@ -111,76 +98,13 @@ DisconnectionEvent::pre_process()
return;
}
- // Create the typed event to actually do the work
- const DataType type = _src_port->type();
- if (type == DataType::FLOAT) {
- _typed_event = new TypedDisconnectionEvent<Sample>(_engine, _responder, _time,
- dynamic_cast<OutputPort<Sample>*>(_src_port), dynamic_cast<InputPort<Sample>*>(_dst_port));
- } else if (type == DataType::MIDI) {
- _typed_event = new TypedDisconnectionEvent<MidiMessage>(_engine, _responder, _time,
- dynamic_cast<OutputPort<MidiMessage>*>(_src_port), dynamic_cast<InputPort<MidiMessage>*>(_dst_port));
- } else {
- _error = TYPE_MISMATCH;
- QueuedEvent::pre_process();
- return;
- }
-
- assert(_typed_event);
- _typed_event->pre_process();
- assert(_typed_event->is_prepared());
-
- QueuedEvent::pre_process();
-}
-
-
-void
-DisconnectionEvent::execute(SampleCount nframes, FrameTime start, FrameTime end)
-{
- QueuedEvent::execute(nframes, start, end);
-
- if (_error == NO_ERROR)
- _typed_event->execute(nframes, start, end);
-}
-
-
-void
-DisconnectionEvent::post_process()
-{
- if (_error == NO_ERROR) {
- _typed_event->post_process();
- } else {
- // FIXME: better error messages
- string msg = "Unable to disconnect ";
- msg.append(_src_port_path + " -> " + _dst_port_path);
- _responder->respond_error(msg);
- }
-}
-
-
-
-//// TypedDisconnectionEvent ////
-
-
-template <typename T>
-TypedDisconnectionEvent<T>::TypedDisconnectionEvent(Engine& engine, SharedPtr<Responder> responder, SampleCount timestamp, OutputPort<T>* src_port, InputPort<T>* dst_port)
-: QueuedEvent(engine, responder, timestamp),
- _src_port(src_port),
- _dst_port(dst_port),
- _patch(NULL),
- _process_order(NULL),
- _succeeded(true)
-{
- assert(src_port != NULL);
- assert(dst_port != NULL);
-}
-
+ _dst_input_port = dynamic_cast<InputPort*>(_dst_port);
+ _src_output_port = dynamic_cast<OutputPort*>(_src_port);
+ assert(_src_output_port);
+ assert(_dst_input_port);
-template <typename T>
-void
-TypedDisconnectionEvent<T>::pre_process()
-{
- if (!_dst_port->is_connected_to(_src_port)) {
- _succeeded = false;
+ if (!_dst_input_port->is_connected_to(_src_output_port)) {
+ _error = NOT_CONNECTED;
QueuedEvent::pre_process();
return;
}
@@ -209,7 +133,7 @@ TypedDisconnectionEvent<T>::pre_process()
assert(_patch);
if (src_node == NULL || dst_node == NULL) {
- _succeeded = false;
+ _error = PARENTS_NOT_FOUND;
QueuedEvent::pre_process();
return;
}
@@ -229,21 +153,18 @@ TypedDisconnectionEvent<T>::pre_process()
if (_patch->enabled())
_process_order = _patch->build_process_order();
- _succeeded = true;
- QueuedEvent::pre_process();
+ QueuedEvent::pre_process();
}
-template <typename T>
void
-TypedDisconnectionEvent<T>::execute(SampleCount nframes, FrameTime start, FrameTime end)
+DisconnectionEvent::execute(SampleCount nframes, FrameTime start, FrameTime end)
{
QueuedEvent::execute(nframes, start, end);
- if (_succeeded) {
-
- Raul::ListNode<TypedConnection<T>*>* const port_connection
- = _dst_port->remove_connection(_src_port);
+ if (_error == NO_ERROR) {
+ Raul::ListNode<Connection*>* const port_connection
+ = _dst_input_port->remove_connection(_src_output_port);
if (port_connection != NULL) {
Raul::ListNode<Connection*>* const patch_connection
@@ -261,23 +182,23 @@ TypedDisconnectionEvent<T>::execute(SampleCount nframes, FrameTime start, FrameT
_engine.maid()->push(_patch->process_order());
_patch->process_order(_process_order);
} else {
- _succeeded = false; // Ports weren't connected
+ _error = CONNECTION_NOT_FOUND;
}
}
}
-template <typename T>
void
-TypedDisconnectionEvent<T>::post_process()
+DisconnectionEvent::post_process()
{
- if (_succeeded) {
-
+ if (_error == NO_ERROR) {
_responder->respond_ok();
-
_engine.broadcaster()->send_disconnection(_src_port->path(), _dst_port->path());
} else {
- _responder->respond_error("Unable to disconnect ports.");
+ // FIXME: better error messages
+ string msg = "Unable to disconnect ";
+ msg.append(_src_port_path + " -> " + _dst_port_path);
+ _responder->respond_error(msg);
}
}
diff --git a/src/libs/engine/events/DisconnectionEvent.h b/src/libs/engine/events/DisconnectionEvent.h
index 01a72e85..3faeb23e 100644
--- a/src/libs/engine/events/DisconnectionEvent.h
+++ b/src/libs/engine/events/DisconnectionEvent.h
@@ -36,10 +36,9 @@ class Node;
class Connection;
class MidiMessage;
class Port;
-template <typename T> class TypedConnection;
-template <typename T> class InputPort;
-template <typename T> class OutputPort;
-template <typename T> class TypedDisconnectionEvent; // helper, defined below
+class Connection;
+class InputPort;
+class OutputPort;
/** Make a Connection between two Ports.
@@ -51,7 +50,6 @@ class DisconnectionEvent : public QueuedEvent
public:
DisconnectionEvent(Engine& engine, SharedPtr<Responder> responder, SampleCount timestamp, const string& src_port_path, const string& dst_port_path);
DisconnectionEvent(Engine& engine, SharedPtr<Responder> responder, SampleCount timestamp, Port* const src_port, Port* const dst_port);
- ~DisconnectionEvent();
void pre_process();
void execute(SampleCount nframes, FrameTime start, FrameTime end);
@@ -59,50 +57,33 @@ public:
private:
- enum ErrorType { NO_ERROR, PARENT_PATCH_DIFFERENT, PORT_NOT_FOUND, TYPE_MISMATCH };
-
- Path _src_port_path;
- Path _dst_port_path;
+ enum ErrorType {
+ NO_ERROR,
+ PARENT_PATCH_DIFFERENT,
+ PORT_NOT_FOUND,
+ TYPE_MISMATCH,
+ NOT_CONNECTED,
+ PARENTS_NOT_FOUND,
+ CONNECTION_NOT_FOUND
+ };
- Patch* _patch;
- Port* _src_port;
- Port* _dst_port;
-
- bool _lookup;
- QueuedEvent* _typed_event;
+ Path _src_port_path;
+ Path _dst_port_path;
- ErrorType _error;
-};
+ Patch* _patch;
+ Port* _src_port;
+ Port* _dst_port;
+ OutputPort* _src_output_port;
+ InputPort* _dst_input_port;
-
-/** Templated DisconnectionEvent.
- *
- * Intended to be called from DisconnectionEvent so callers (ie OSCReceiver)
- * can use DisconnectionEvent without knowing anything about types (which
- * they can't, since all they have is Port paths).
- */
-template <typename T>
-class TypedDisconnectionEvent : public QueuedEvent
-{
-public:
- TypedDisconnectionEvent(Engine& engine, SharedPtr<Responder> responder, SampleCount timestamp, OutputPort<T>* src_port, InputPort<T>* dst_port);
+ bool _lookup;
- void pre_process();
- void execute(SampleCount nframes, FrameTime start, FrameTime end);
- void post_process();
-
-private:
- OutputPort<T>* _src_port;
- InputPort<T>* _dst_port;
-
- Patch* _patch;
- Raul::Array<Node*>* _process_order; ///< New process order for Patch
+ Raul::Array<Node*>* _process_order; ///< New process order for Patch
- bool _succeeded;
+ ErrorType _error;
};
-
} // namespace Ingen
#endif // DISCONNECTIONEVENT_H
diff --git a/src/libs/engine/events/RequestObjectEvent.cpp b/src/libs/engine/events/RequestObjectEvent.cpp
index d383fdbd..bd25f514 100644
--- a/src/libs/engine/events/RequestObjectEvent.cpp
+++ b/src/libs/engine/events/RequestObjectEvent.cpp
@@ -17,14 +17,14 @@
#include "RequestObjectEvent.h"
#include <string>
+#include "interface/ClientInterface.h"
#include "Responder.h"
#include "Engine.h"
-#include "interface/ClientInterface.h"
-#include "TypedPort.h"
#include "ObjectStore.h"
#include "ClientBroadcaster.h"
#include "Patch.h"
#include "Node.h"
+#include "Port.h"
#include "ObjectSender.h"
using std::string;
diff --git a/src/libs/engine/events/RequestPluginEvent.cpp b/src/libs/engine/events/RequestPluginEvent.cpp
index 9035cbc5..64a63aea 100644
--- a/src/libs/engine/events/RequestPluginEvent.cpp
+++ b/src/libs/engine/events/RequestPluginEvent.cpp
@@ -17,10 +17,10 @@
#include "RequestPluginEvent.h"
#include <string>
+#include "interface/ClientInterface.h"
#include "Responder.h"
#include "Engine.h"
-#include "interface/ClientInterface.h"
-#include "TypedPort.h"
+#include "Port.h"
#include "ObjectStore.h"
#include "ClientBroadcaster.h"
#include "NodeFactory.h"
diff --git a/src/libs/engine/events/RequestPortValueEvent.cpp b/src/libs/engine/events/RequestPortValueEvent.cpp
index 3155e72f..533cac38 100644
--- a/src/libs/engine/events/RequestPortValueEvent.cpp
+++ b/src/libs/engine/events/RequestPortValueEvent.cpp
@@ -17,12 +17,13 @@
#include "RequestPortValueEvent.h"
#include <string>
+#include "interface/ClientInterface.h"
#include "Responder.h"
#include "Engine.h"
-#include "interface/ClientInterface.h"
-#include "TypedPort.h"
+#include "Port.h"
#include "ObjectStore.h"
#include "ClientBroadcaster.h"
+#include "AudioBuffer.h"
using std::string;
@@ -55,7 +56,7 @@ RequestPortValueEvent::execute(SampleCount nframes, FrameTime start, FrameTime e
assert(_time >= start && _time <= end);
if (_port != NULL && _port->type() == DataType::FLOAT)
- _value = ((TypedPort<Sample>*)_port)->buffer(0)->value_at(0/*_time - start*/);
+ _value = ((AudioBuffer*)_port->buffer(0))->value_at(0/*_time - start*/);
else
_port = NULL; // triggers error response
}
diff --git a/src/libs/engine/events/SetPortValueEvent.cpp b/src/libs/engine/events/SetPortValueEvent.cpp
index 4924caa0..5d8127e6 100644
--- a/src/libs/engine/events/SetPortValueEvent.cpp
+++ b/src/libs/engine/events/SetPortValueEvent.cpp
@@ -18,10 +18,11 @@
#include "SetPortValueEvent.h"
#include "Responder.h"
#include "Engine.h"
-#include "TypedPort.h"
+#include "Port.h"
#include "ClientBroadcaster.h"
#include "Node.h"
#include "ObjectStore.h"
+#include "AudioBuffer.h"
namespace Ingen {
@@ -64,11 +65,13 @@ SetPortValueEvent::execute(SampleCount nframes, FrameTime start, FrameTime end)
} else if (!(_port->type() == DataType::FLOAT)) {
_error = TYPE_MISMATCH;
} else {
- if (_voice_num == -1)
- ((TypedPort<Sample>*)_port)->set_value(_val, _time - start);
+ AudioBuffer* const buf = (AudioBuffer*)_port->buffer(0);
+ const size_t offset = (buf->size() == 1) ? 0 : _time - start;
+ if (_voice_num == -1)
+ for (size_t i=0; i < _port->poly(); ++i)
+ ((AudioBuffer*)_port->buffer(i))->set(_val, offset);
else
- ((TypedPort<Sample>*)_port)->set_value(_voice_num, _val, _time - start);
- //((TypedPort<Sample>*)_port)->buffer(_voice_num)->set(_val, offset); // FIXME: check range
+ ((AudioBuffer*)_port->buffer(_voice_num))->set(_val, offset);
}
}
diff --git a/src/libs/engine/events/SetPortValueQueuedEvent.cpp b/src/libs/engine/events/SetPortValueQueuedEvent.cpp
index 139d63a2..1eaa33cb 100644
--- a/src/libs/engine/events/SetPortValueQueuedEvent.cpp
+++ b/src/libs/engine/events/SetPortValueQueuedEvent.cpp
@@ -18,11 +18,12 @@
#include "SetPortValueQueuedEvent.h"
#include "Responder.h"
#include "Engine.h"
-#include "TypedPort.h"
+#include "Port.h"
#include "ClientBroadcaster.h"
#include "Plugin.h"
#include "Node.h"
#include "ObjectStore.h"
+#include "AudioBuffer.h"
namespace Ingen {
@@ -74,11 +75,14 @@ SetPortValueQueuedEvent::execute(SampleCount nframes, FrameTime start, FrameTime
assert(_time >= start && _time <= end);
if (_error == NO_ERROR) {
- assert(_port != NULL);
- if (_voice_num == -1)
- ((TypedPort<Sample>*)_port)->set_value(_val, _time - start);
+ assert(_port);
+ AudioBuffer* const buf = (AudioBuffer*)_port->buffer(0);
+ const size_t offset = (buf->size() == 1) ? 0 : _time - start;
+ if (_voice_num == -1)
+ for (size_t i=0; i < _port->poly(); ++i)
+ ((AudioBuffer*)_port->buffer(i))->set(_val, offset);
else
- ((TypedPort<Sample>*)_port)->buffer(_voice_num)->set(_val, _time - start); // FIXME: check range
+ ((AudioBuffer*)_port->buffer(_voice_num))->set(_val, offset);
}
}
diff --git a/src/libs/engine/types.h b/src/libs/engine/types.h
index 73ad23f8..9aea18e8 100644
--- a/src/libs/engine/types.h
+++ b/src/libs/engine/types.h
@@ -30,8 +30,4 @@ typedef jack_nframes_t SampleCount;
typedef jack_nframes_t SampleRate;
typedef jack_nframes_t FrameTime;
-/** A type that Ingen can process/patch (eg can be stored in a port) */
-enum DataType { FLOAT, MIDI, UNKNOWN };
-
-
#endif // TYPES_H