Changeset 732bfb33 in ingen


Ignore:
Timestamp:
Oct 24, 2015, 12:27:39 PM (2 years ago)
Author:
David Robillard <d@…>
Branches:
groups, master, nodeless, parallel, parameters, sequencefix, tasks
Children:
e4d549a
Parents:
ade7143
Message:

Zero-copy to/from driver ports where possible

git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@5778 a436a847-0d15-0410-975c-d299462d15a1

Files:
2 added
33 edited

Legend:

Unmodified
Added
Removed
  • ingen/AtomReader.hpp

    rade7143 r732bfb33  
    4646    ~AtomReader() {}
    4747
    48     static bool is_message(URIs& uris, const LV2_Atom* msg);
     48    static bool is_message(const URIs& uris, const LV2_Atom* msg);
    4949
    5050    bool write(const LV2_Atom* msg);
  • ingen/URIs.hpp

    rade7143 r732bfb33  
    9292    const Quark atom_URI;
    9393    const Quark atom_URID;
    94     const Quark atom_Vector;
    9594    const Quark atom_bufferType;
    9695    const Quark atom_eventTransfer;
  • src/AtomReader.cpp

    rade7143 r732bfb33  
    114114
    115115bool
    116 AtomReader::is_message(URIs& uris, const LV2_Atom* msg)
     116AtomReader::is_message(const URIs& uris, const LV2_Atom* msg)
    117117{
    118118    if (msg->type != uris.atom_Object) {
  • src/URIs.cpp

    rade7143 r732bfb33  
    7474    , atom_URI              (forge, map, lworld, LV2_ATOM__URI)
    7575    , atom_URID             (forge, map, lworld, LV2_ATOM__URID)
    76     , atom_Vector           (forge, map, lworld, LV2_ATOM__Vector)
    7776    , atom_bufferType       (forge, map, lworld, LV2_ATOM__bufferType)
    7877    , atom_eventTransfer    (forge, map, lworld, LV2_ATOM__eventTransfer)
  • src/server/BlockImpl.hpp

    rade7143 r732bfb33  
    1515*/
    1616
    17 #ifndef INGEN_ENGINE_NODEIMPL_HPP
    18 #define INGEN_ENGINE_NODEIMPL_HPP
     17#ifndef INGEN_ENGINE_BLOCKIMPL_HPP
     18#define INGEN_ENGINE_BLOCKIMPL_HPP
    1919
    2020#include <list>
  • src/server/Buffer.cpp

    rade7143 r732bfb33  
    4343               LV2_URID       type,
    4444               LV2_URID       value_type,
    45                uint32_t       capacity)
     45               uint32_t       capacity,
     46               bool           external,
     47               void*          buf)
    4648    : _factory(bufs)
    4749    , _type(type)
     
    5153    , _next(NULL)
    5254    , _refs(0)
    53 {
     55    , _external(external)
     56{
     57    if (!external) {
    5458#ifdef HAVE_POSIX_MEMALIGN
    55     int ret = posix_memalign((void**)&_atom, 16, capacity);
     59        int ret = posix_memalign((void**)&_buf, 16, capacity);
     60        if (!ret) {
     61            memset(_buf, 0, capacity);
     62        }
    5663#else
    57     _atom = (LV2_Atom*)malloc(capacity);
    58     int ret = (_atom != NULL) ? 0 : -1;
     64        _buf = (LV2_buf*)calloc(1, capacity);
     65        int ret = (_buf != NULL) ? 0 : -1;
    5966#endif
    6067
    61     if (ret) {
    62         bufs.engine().log().error("Failed to allocate event buffer\n");
    63         throw std::bad_alloc();
    64     }
    65 
    66     memset(_atom, 0, capacity);
    67     _atom->size = capacity - sizeof(LV2_Atom);
    68     _atom->type = type;
    69 
    70     if (type == bufs.uris().atom_Sound) {
    71         // Audio port (Vector of float)
    72         LV2_Atom_Vector* vec = (LV2_Atom_Vector*)_atom;
    73         vec->body.child_size = sizeof(float);
    74         vec->body.child_type = bufs.uris().atom_Float;
    75     }
    76 
    77     if (type == bufs.uris().atom_Sequence && value_type) {
    78         _value_buffer = bufs.get_buffer(value_type, 0, 0, false);
    79     }
    80 
    81     clear();
     68        if (ret) {
     69            bufs.engine().log().error("Failed to allocate event buffer\n");
     70            throw std::bad_alloc();
     71        }
     72    }
     73
     74    if (type != bufs.uris().atom_Sound) {
     75        /* Audio buffers are not atoms, the buffer is the start of a float
     76           array which is already silent since the buffer is zeroed.  All other
     77           buffers are atoms. */
     78        if (_buf) {
     79            LV2_Atom* atom = get<LV2_Atom>();
     80            atom->size = capacity - sizeof(LV2_Atom);
     81            atom->type = type;
     82
     83            clear();
     84        }
     85
     86        if (value_type && value_type != type) {
     87            /* Buffer with a different value type.  These buffers (probably
     88               sequences) have a "value" that persists independently of the buffer
     89               contents.  This is used to represent things like a Sequence of
     90               Float, which acts like an individual float (has a value), but the
     91               buffer itself only transmits changes and does not necessarily
     92               contain the current value. */
     93            _value_buffer = bufs.get_buffer(value_type, 0, 0, false);
     94        }
     95    }
    8296}
    8397
    8498Buffer::~Buffer()
    8599{
    86     free(_atom);
     100    if (!_external) {
     101        free(_buf);
     102    }
    87103}
    88104
     
    105121Buffer::clear()
    106122{
    107     if (is_audio() || is_control()) {
    108         _atom->size = _capacity - sizeof(LV2_Atom);
    109         set_block(0, 0, nframes());
     123    if (is_audio() && _buf) {
     124        memset(_buf, 0, _capacity);
     125    } else if (is_control()) {
     126        get<LV2_Atom_Float>()->body = 0;
    110127    } else if (is_sequence()) {
    111         LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)_atom;
    112         _atom->type    = _factory.uris().atom_Sequence;
    113         _atom->size    = sizeof(LV2_Atom_Sequence_Body);
     128        LV2_Atom_Sequence* seq = get<LV2_Atom_Sequence>();
     129        seq->atom.type = _factory.uris().atom_Sequence;
     130        seq->atom.size = sizeof(LV2_Atom_Sequence_Body);
    114131        seq->body.unit = 0;
    115132        seq->body.pad  = 0;
     
    122139{
    123140    const LV2_URID           atom_Float = _factory.uris().atom_Float;
    124     const LV2_Atom_Sequence* seq        = (const LV2_Atom_Sequence*)src->atom();
     141    const LV2_Atom_Sequence* seq        = src->get<const LV2_Atom_Sequence>();
    125142    const LV2_Atom_Float*    init       = (const LV2_Atom_Float*)src->value();
    126143    float                    value      = init ? init->body : 0.0f;
     
    139156Buffer::copy(const Context& context, const Buffer* src)
    140157{
    141     if (_type == src->type() && src->_atom->size + sizeof(LV2_Atom) <= _capacity) {
    142         memcpy(_atom, src->_atom, sizeof(LV2_Atom) + src->_atom->size);
     158    if (!_buf) {
     159        return;
     160    } else if (is_audio() && src->is_audio()) {
     161        memcpy(_buf, src->_buf, src->_capacity);
     162    } else if (_type == src->type()) {
     163        const LV2_Atom* src_atom = src->get<const LV2_Atom>();
     164        if (lv2_atom_total_size(src_atom) <= _capacity) {
     165            memcpy(_buf, src_atom, lv2_atom_total_size(src_atom));
     166        } else {
     167            clear();
     168        }
     169
    143170        if (value() && src->value()) {
    144171            memcpy(value(), src->value(), lv2_atom_total_size(src->value()));
     
    159186Buffer::resize(uint32_t capacity)
    160187{
    161     _atom     = (LV2_Atom*)realloc(_atom, capacity);
    162     _capacity = capacity;
    163     clear();
     188    if (!_external) {
     189        _buf      = realloc(_buf, capacity);
     190        _capacity = capacity;
     191        clear();
     192    } else {
     193        _factory.engine().log().error("Attempt to resize external buffer\n");
     194    }
    164195}
    165196
     
    169200    switch (port_type.id()) {
    170201    case PortType::ID::CONTROL:
     202        if (_type == _factory.uris().atom_Float) {
     203            return &get<LV2_Atom_Float>()->body;
     204        }
     205        break;
    171206    case PortType::ID::CV:
    172207    case PortType::ID::AUDIO:
    173         if (_atom->type == _factory.uris().atom_Float) {
    174             return (float*)LV2_ATOM_BODY(_atom);
    175         } else if (_atom->type == _factory.uris().atom_Sound) {
    176             return (float*)LV2_ATOM_CONTENTS(LV2_Atom_Vector, _atom) + offset;
    177         }
    178         break;
     208        return (Sample*)_buf;
    179209    default:
    180         return _atom;
     210        return _buf;
    181211    }
    182212    return NULL;
     
    247277{
    248278    if (_type == _factory.uris().atom_Sequence) {
    249         _atom->type   = (LV2_URID)_factory.uris().atom_Sequence;
    250         _atom->size   = sizeof(LV2_Atom_Sequence_Body);
     279        LV2_Atom* atom = get<LV2_Atom>();
     280
     281        atom->type    = (LV2_URID)_factory.uris().atom_Sequence;
     282        atom->size    = sizeof(LV2_Atom_Sequence_Body);
    251283        _latest_event = 0;
    252284    }
     
    257289{
    258290    if (_type == _factory.uris().atom_Sequence) {
    259         _atom->type   = (LV2_URID)_factory.uris().atom_Chunk;
    260         _atom->size   = _capacity - sizeof(LV2_Atom);
     291        LV2_Atom* atom = get<LV2_Atom>();
     292
     293        atom->type    = (LV2_URID)_factory.uris().atom_Chunk;
     294        atom->size    = _capacity - sizeof(LV2_Atom);
    261295        _latest_event = 0;
    262296    }
     
    270304{
    271305    assert(frames >= _latest_event);
    272     if (_atom->type == _factory.uris().atom_Chunk) {
     306
     307    LV2_Atom* atom = get<LV2_Atom>();
     308    if (atom->type == _factory.uris().atom_Chunk) {
    273309        // Chunk initialized with prepare_output_write(), clear
    274310        clear();
    275311    }
    276312
    277     if (sizeof(LV2_Atom) + _atom->size + lv2_atom_pad_size(size) > _capacity) {
     313    if (sizeof(LV2_Atom) + atom->size + lv2_atom_pad_size(size) > _capacity) {
    278314        return false;
    279315    }
    280316
    281     LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)_atom;
     317    LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)atom;
    282318    LV2_Atom_Event*    ev  = (LV2_Atom_Event*)(
    283319        (uint8_t*)seq + lv2_atom_total_size(&seq->atom));
     
    288324    memcpy(ev + 1, data, size);
    289325
    290     _atom->size += sizeof(LV2_Atom_Event) + lv2_atom_pad_size(size);
     326    atom->size += sizeof(LV2_Atom_Event) + lv2_atom_pad_size(size);
    291327
    292328    _latest_event = frames;
     
    298334Buffer::next_value_offset(SampleCount offset, SampleCount end) const
    299335{
    300     SampleCount earliest = end;
    301     LV2_ATOM_SEQUENCE_FOREACH((LV2_Atom_Sequence*)_atom, ev) {
     336    SampleCount              earliest = end;
     337    const LV2_Atom_Sequence* seq      = get<const LV2_Atom_Sequence>();
     338    LV2_ATOM_SEQUENCE_FOREACH(seq, ev) {
    302339        if (ev->time.frames >  offset   &&
    303340            ev->time.frames <  earliest &&
     
    313350Buffer::value() const
    314351{
    315     return _value_buffer ? _value_buffer->atom() : NULL;
     352    return _value_buffer ? _value_buffer->get<const LV2_Atom>() : NULL;
    316353}
    317354
     
    319356Buffer::value()
    320357{
    321     return _value_buffer ? _value_buffer->atom() : NULL;
     358    return _value_buffer ? _value_buffer->get<LV2_Atom>() : NULL;
    322359}
    323360
     
    329366    }
    330367
    331     LV2_ATOM_SEQUENCE_FOREACH((LV2_Atom_Sequence*)_atom, ev) {
     368    LV2_Atom_Sequence* seq = get<LV2_Atom_Sequence>();
     369    LV2_ATOM_SEQUENCE_FOREACH(seq, ev) {
    332370        if (ev->time.frames <= offset && ev->body.type == _value_type) {
    333             memcpy(_value_buffer->atom(),
     371            memcpy(_value_buffer->get<LV2_Atom>(),
    334372                   &ev->body,
    335373                   lv2_atom_total_size(&ev->body));
  • src/server/Buffer.hpp

    rade7143 r732bfb33  
    4646           LV2_URID       type,
    4747           LV2_URID       value_type,
    48            uint32_t       capacity);
     48           uint32_t       capacity,
     49           bool           external = false,
     50           void*          buf = NULL);
    4951
    5052    void clear();
     
    7476    }
    7577
    76     inline bool empty() const {
    77         return (_atom->type != _type ||
    78                 (_type == _factory.uris().atom_Sequence &&
    79                  _atom->size <= sizeof(LV2_Atom_Sequence_Body)));
    80     }
    81 
    82     /// Audio buffers only
     78    /// Audio or float buffers only
    8379    inline const Sample* samples() const {
    8480        if (is_control()) {
    85             return (const Sample*)LV2_ATOM_BODY_CONST(atom());
     81            return (const Sample*)LV2_ATOM_BODY_CONST(get<LV2_Atom_Float>());
    8682        } else if (is_audio()) {
    87             return (const Sample*)LV2_ATOM_CONTENTS_CONST(LV2_Atom_Vector, atom());
     83            return (const Sample*)_buf;
    8884        }
    8985        return NULL;
     
    9389    inline Sample* samples() {
    9490        if (is_control()) {
    95             return (Sample*)LV2_ATOM_BODY(atom());
     91            return (Sample*)LV2_ATOM_BODY(get<LV2_Atom_Float>());
    9692        } else if (is_audio()) {
    97             return (Sample*)LV2_ATOM_CONTENTS(LV2_Atom_Vector, atom());
     93            return (Sample*)_buf;
    9894        }
    9995        return NULL;
     
    105101            return 1;
    106102        } else if (is_audio()) {
    107             return (_capacity - sizeof(LV2_Atom_Vector)) / sizeof(Sample);
     103            return (_capacity / sizeof(Sample));
    108104        }
    109105        return 0;
     
    153149        if (add) {
    154150            add_block(val, start, end);
    155         }
    156         set_block(val, start, end);
     151        } else {
     152            set_block(val, start, end);
     153        }
    157154    }
    158155
     
    185182    void render_sequence(const Context& context, const Buffer* src, bool add);
    186183
    187     LV2_Atom*       atom()       { return _atom; }
    188     const LV2_Atom* atom() const { return _atom; }
    189 
    190184    void set_capacity(uint32_t capacity) { _capacity = capacity; }
     185
     186    void set_buffer(void* buf) { assert(_external); _buf = buf; }
     187
     188    template<typename T> const T* get() const { return reinterpret_cast<const T*>(_buf); }
     189    template<typename T> T*       get()       { return reinterpret_cast<T*>(_buf); }
    191190
    192191    inline void ref() { ++_refs; }
     
    200199protected:
    201200    BufferFactory& _factory;
    202     LV2_Atom*      _atom;
     201    void*          _buf;
    203202    LV2_URID       _type;
    204203    LV2_URID       _value_type;
     
    214213    void recycle();
    215214
    216     Buffer*               _next;  ///< Intrusive linked list for BufferFactory
    217     std::atomic<unsigned> _refs;  ///< Intrusive reference count
     215    Buffer*               _next;      ///< Intrusive linked list for BufferFactory
     216    std::atomic<unsigned> _refs;      ///< Intrusive reference count
     217    bool                  _external;  ///< Buffer is externally allocated
    218218};
    219219
  • src/server/BufferFactory.cpp

    rade7143 r732bfb33  
    7272BufferFactory::audio_buffer_size(SampleCount nframes)
    7373{
    74     return sizeof(LV2_Atom_Vector) + (nframes * sizeof(float));
     74    return nframes * sizeof(Sample);
    7575}
    7676
  • src/server/ControlBindings.cpp

    rade7143 r732bfb33  
    412412    }
    413413
    414     LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)buffer->atom();
     414    LV2_Atom_Sequence* seq = buffer->get<LV2_Atom_Sequence>();
    415415    LV2_ATOM_SEQUENCE_FOREACH(seq, ev) {
    416416        if (ev->body.type == uris.midi_MidiEvent) {
  • src/server/DuplexPort.cpp

    rade7143 r732bfb33  
    3030
    3131DuplexPort::DuplexPort(BufferFactory&      bufs,
    32                        BlockImpl*          parent,
     32                       GraphImpl*          parent,
    3333                       const Raul::Symbol& symbol,
    3434                       uint32_t            index,
    3535                       bool                polyphonic,
    36                        uint32_t            poly,
    3736                       PortType            type,
    38                        LV2_URID            buffer_type,
     37                       LV2_URID            buf_type,
     38                       size_t              buf_size,
    3939                       const Atom&         value,
    40                        size_t              buffer_size,
    4140                       bool                is_output)
    42     : PortImpl(bufs, parent, symbol, index, poly, type, buffer_type, value, buffer_size)
    43     , InputPort(bufs, parent, symbol, index, poly, type, buffer_type, value, buffer_size)
    44     , OutputPort(bufs, parent, symbol, index, poly, type, buffer_type, value, buffer_size)
     41    : PortImpl(bufs, parent, symbol, index, parent->polyphony(), type, buf_type, value, buf_size)
     42    , InputPort(bufs, parent, symbol, index, parent->polyphony(), type, buf_type, value, buf_size)
     43    , OutputPort(bufs, parent, symbol, index, parent->polyphony(), type, buf_type, value, buf_size)
    4544    , _is_output(is_output)
    4645{
     
    7978        bufs, parent, symbol, _index,
    8079        polyphonic.type() == bufs.uris().atom_Bool && polyphonic.get<int32_t>(),
    81         _poly, _type, _buffer_type,
    82         _value, _buffer_size, _is_output);
     80        _type, _buffer_type, _buffer_size,
     81        _value, _is_output);
    8382
    8483    dup->set_properties(properties());
     
    130129                        bool                real_time) const
    131130{
    132     if (_is_output) {
    133         return InputPort::get_buffers(bufs, voices, poly, real_time);
    134     } else {
    135         return OutputPort::get_buffers(bufs, voices, poly, real_time);
    136     }
     131    if (!_is_driver_port) {
     132        if (_is_output) {
     133            return InputPort::get_buffers(bufs, voices, poly, real_time);
     134        } else {
     135            return OutputPort::get_buffers(bufs, voices, poly, real_time);
     136        }
     137    }
     138    return false;
     139}
     140
     141void
     142DuplexPort::set_is_driver_port(BufferFactory& bufs)
     143{
     144    _voices->at(0).buffer = new Buffer(bufs, buffer_type(), _value.type(), 0, true, NULL);
     145    PortImpl::set_is_driver_port(bufs);
     146}
     147
     148void
     149DuplexPort::set_driver_buffer(void* buf, uint32_t capacity)
     150{
     151    _voices->at(0).buffer->set_buffer(buf);
     152    _voices->at(0).buffer->set_capacity(capacity);
    137153}
    138154
     
    193209        InputPort::pre_process(context);
    194210        InputPort::pre_run(context);
    195     } else {
    196         monitor(context);
    197     }
     211    }
     212    monitor(context);
    198213}
    199214
  • src/server/DuplexPort.hpp

    rade7143 r732bfb33  
    4444public:
    4545    DuplexPort(BufferFactory&      bufs,
    46                BlockImpl*          parent,
     46               GraphImpl*          parent,
    4747               const Raul::Symbol& symbol,
    4848               uint32_t            index,
    4949               bool                polyphonic,
    50                uint32_t            poly,
    5150               PortType            type,
    52                LV2_URID            buffer_type,
     51               LV2_URID            buf_type,
     52               size_t              buf_size,
    5353               const Atom&         value,
    54                size_t              buffer_size,
    5554               bool                is_output);
    5655
     
    7877                     bool                real_time) const;
    7978
     79
     80    virtual void set_is_driver_port(BufferFactory& bufs);
     81
     82    /** Set the external driver-provided buffer.
     83     *
     84     * This may only be called in the process thread, after an earlier call to
     85     * prepare_driver_buffer().
     86     */
     87    void set_driver_buffer(void* buf, uint32_t capacity);
     88
    8089    void pre_process(Context& context);
    8190    void post_process(Context& context);
  • src/server/GraphImpl.cpp

    rade7143 r732bfb33  
    312312}
    313313
    314 DuplexPort*
    315 GraphImpl::create_port(BufferFactory&      bufs,
    316                        const Raul::Symbol& symbol,
    317                        PortType            type,
    318                        LV2_URID            buffer_type,
    319                        uint32_t            buffer_size,
    320                        bool                is_output,
    321                        bool                polyphonic)
    322 {
    323     if (type == PortType::UNKNOWN) {
    324         bufs.engine().log().error(fmt("Unknown port type %1%\n")
    325                                   % type.uri());
    326         return NULL;
    327     }
    328 
    329     Atom value;
    330     if (type == PortType::CONTROL || type == PortType::CV)
    331         value = bufs.forge().make(0.0f);
    332 
    333     return new DuplexPort(bufs, this, symbol, num_ports_non_rt(), polyphonic, _polyphony,
    334                           type, buffer_type, value, buffer_size, is_output);
    335 }
    336 
    337314void
    338315GraphImpl::remove_port(DuplexPort& port)
  • src/server/GraphImpl.hpp

    rade7143 r732bfb33  
    118118    uint32_t num_ports_non_rt() const;
    119119
    120     /** Create a port to be later added to this graph.
    121      * Not realtime safe.  This function is to be called by events in the
    122      * pre-process thread to create ports which will later be installed in the
    123      * process thread.
    124      */
    125     DuplexPort* create_port(BufferFactory&      bufs,
    126                             const Raul::Symbol& symbol,
    127                             PortType            type,
    128                             LV2_URID            buffer_type,
    129                             uint32_t            buffer_size,
    130                             bool                is_output,
    131                             bool                polyphonic);
    132 
    133120    typedef boost::intrusive::slist<
    134121        DuplexPort, boost::intrusive::constant_time_size<true> > Ports;
  • src/server/JackDriver.cpp

    rade7143 r732bfb33  
    213213{
    214214    _ports.push_back(*port);
     215
     216    DuplexPort* graph_port = port->graph_port();
     217    if (graph_port->is_a(PortType::AUDIO) || graph_port->is_a(PortType::CV)) {
     218        const SampleCount nframes = context.nframes();
     219        jack_port_t*      jport   = (jack_port_t*)port->handle();
     220        void*             jbuf    = jack_port_get_buffer(jport, nframes);
     221        graph_port->set_driver_buffer(jbuf, nframes * sizeof(float));
     222    }
    215223}
    216224
     
    251259        _engine.log().error("Failed to unregister Jack port\n");
    252260    }
     261
     262    port.set_handle(NULL);
    253263}
    254264
     
    303313JackDriver::create_port(DuplexPort* graph_port)
    304314{
    305     if (graph_port &&
    306         (graph_port->is_a(PortType::AUDIO) ||
    307          graph_port->is_a(PortType::CV) ||
    308          (graph_port->is_a(PortType::ATOM) &&
    309           graph_port->buffer_type() == _engine.world()->uris().atom_Sequence))) {
    310         EnginePort* eport = new EnginePort(graph_port);
     315    EnginePort* eport = NULL;
     316    if (graph_port->is_a(PortType::AUDIO) || graph_port->is_a(PortType::CV)) {
     317        // Audio buffer port, use Jack buffer directly
     318        eport = new EnginePort(graph_port);
     319        graph_port->set_is_driver_port(*_engine.buffer_factory());
     320    } else if (graph_port->is_a(PortType::ATOM) &&
     321               graph_port->buffer_type() == _engine.world()->uris().atom_Sequence) {
     322        // Sequence port, make Jack port but use internal LV2 format buffer
     323        eport = new EnginePort(graph_port);
     324    }
     325
     326    if (eport) {
    311327        register_port(*eport);
    312         graph_port->setup_buffers(*_engine.buffer_factory(),
    313                                   graph_port->poly(),
    314                                   false);
    315         graph_port->set_is_driver_port(true);
    316         return eport;
    317     } else {
    318         return NULL;
    319     }
     328    }
     329
     330    return eport;
    320331}
    321332
     
    323334JackDriver::pre_process_port(ProcessContext& context, EnginePort* port)
    324335{
     336    const URIs&       uris       = context.engine().world()->uris();
    325337    const SampleCount nframes    = context.nframes();
    326338    jack_port_t*      jack_port  = (jack_port_t*)port->handle();
    327     PortImpl*         graph_port = port->graph_port();
    328     void*             buffer     = jack_port_get_buffer(jack_port, nframes);
    329 
    330     port->set_buffer(buffer);
    331 
    332     if (!graph_port->is_input()) {
    333         graph_port->buffer(0)->clear();
    334         return;
    335     }
    336 
    337     if (graph_port->is_a(PortType::AUDIO)) {
    338         Buffer* graph_buf = graph_port->buffer(0).get();
    339         memcpy(graph_buf->samples(), buffer, nframes * sizeof(float));
    340 
    341     } else if (graph_port->buffer_type() == graph_port->bufs().uris().atom_Sequence) {
    342         Buffer* graph_buf = (Buffer*)graph_port->buffer(0).get();
    343 
    344         const jack_nframes_t event_count = jack_midi_get_event_count(buffer);
    345 
     339    DuplexPort*       graph_port = port->graph_port();
     340    Buffer*           graph_buf  = graph_port->buffer(0).get();
     341    void*             jack_buf   = jack_port_get_buffer(jack_port, nframes);
     342
     343    if (graph_port->is_a(PortType::AUDIO) || graph_port->is_a(PortType::CV)) {
     344        graph_port->set_driver_buffer(jack_buf, nframes * sizeof(float));
     345        if (graph_port->is_input()) {
     346            graph_port->monitor(context);
     347        } else {
     348            graph_port->buffer(0)->clear(); // TODO: Avoid when possible
     349        }
     350    } else if (graph_port->buffer_type() == uris.atom_Sequence) {
    346351        graph_buf->prepare_write(context);
    347 
    348         // Copy events from Jack port buffer into graph port buffer
    349         for (jack_nframes_t i = 0; i < event_count; ++i) {
    350             jack_midi_event_t ev;
    351             jack_midi_event_get(&ev, buffer, i);
    352 
    353             if (!graph_buf->append_event(
    354                     ev.time, ev.size, _midi_event_type, ev.buffer)) {
    355                 _engine.log().warn("Failed to write to MIDI buffer, events lost!\n");
     352        if (graph_port->is_input()) {
     353            // Copy events from Jack port buffer into graph port buffer
     354            const jack_nframes_t event_count = jack_midi_get_event_count(jack_buf);
     355            for (jack_nframes_t i = 0; i < event_count; ++i) {
     356                jack_midi_event_t ev;
     357                jack_midi_event_get(&ev, jack_buf, i);
     358                if (!graph_buf->append_event(
     359                        ev.time, ev.size, _midi_event_type, ev.buffer)) {
     360                    _engine.log().warn("Failed to write to MIDI buffer, events lost!\n");
     361                }
    356362            }
    357363        }
     364        graph_port->monitor(context);
    358365    }
    359366}
     
    362369JackDriver::post_process_port(ProcessContext& context, EnginePort* port)
    363370{
     371    const URIs&       uris       = context.engine().world()->uris();
    364372    const SampleCount nframes    = context.nframes();
    365373    jack_port_t*      jack_port  = (jack_port_t*)port->handle();
    366     PortImpl*         graph_port = port->graph_port();
    367     void*             buffer     = port->buffer();
    368 
    369     if (graph_port->is_input()) {
    370         return;
    371     }
    372 
    373     if (!buffer) {
    374         // First cycle for a new output, so pre_process wasn't called
    375         buffer = jack_port_get_buffer(jack_port, nframes);
    376         port->set_buffer(buffer);
    377     }
    378 
    379     graph_port->post_process(context);
    380     Buffer* const graph_buf = graph_port->buffer(0).get();
    381     if (graph_port->is_a(PortType::AUDIO)) {
    382         memcpy(buffer, graph_buf->samples(), nframes * sizeof(Sample));
    383     } else if (graph_port->buffer_type() == graph_port->bufs().uris().atom_Sequence) {
    384         jack_midi_clear_buffer(buffer);
    385         LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)graph_buf->atom();
    386         LV2_ATOM_SEQUENCE_FOREACH(seq, ev) {
    387             const uint8_t* buf = (const uint8_t*)LV2_ATOM_BODY(&ev->body);
    388             if (ev->body.type == graph_port->bufs().uris().midi_MidiEvent) {
    389                 jack_midi_event_write(buffer, ev->time.frames, buf, ev->body.size);
     374    DuplexPort*       graph_port = port->graph_port();
     375    void*             jack_buf   = port->buffer();
     376
     377    if (port->graph_port()->is_output()) {
     378        if (!jack_buf) {
     379            // First cycle for a new output, so pre_process wasn't called
     380            jack_buf = jack_port_get_buffer(jack_port, nframes);
     381            port->set_buffer(jack_buf);
     382        }
     383
     384        if (graph_port->buffer_type() == uris.atom_Sequence) {
     385            // Copy LV2 MIDI events to Jack MIDI buffer
     386            Buffer* const      graph_buf = graph_port->buffer(0).get();
     387            LV2_Atom_Sequence* seq       = graph_buf->get<LV2_Atom_Sequence>();
     388
     389            jack_midi_clear_buffer(jack_buf);
     390            LV2_ATOM_SEQUENCE_FOREACH(seq, ev) {
     391                const uint8_t* buf = (const uint8_t*)LV2_ATOM_BODY(&ev->body);
     392                if (ev->body.type == _midi_event_type) {
     393                    jack_midi_event_write(
     394                        jack_buf, ev->time.frames, buf, ev->body.size);
     395                }
    390396            }
    391397        }
     398    }
     399
     400    // Reset graph port buffer pointer to no longer point to the Jack buffer
     401    if (graph_port->is_driver_port()) {
     402        graph_port->set_driver_buffer(NULL, 0);
    392403    }
    393404}
     
    458469    }
    459470
    460     /* Note that Jack can not call this function for a cycle, if overloaded,
     471    /* Note that Jack may not call this function for a cycle, if overloaded,
    461472       so a rolling counter here would not always be correct. */
    462473    const jack_nframes_t start_of_current_cycle = jack_last_frame_time(_client);
  • src/server/PortImpl.cpp

    rade7143 r732bfb33  
    169169PortImpl::deactivate()
    170170{
    171     if (is_output()) {
     171    if (is_output() && !_is_driver_port) {
    172172        for (uint32_t v = 0; v < _poly; ++v) {
    173173            if (_voices->at(v).buffer) {
     
    303303{
    304304    ThreadManager::assert_thread(THREAD_PRE_PROCESS);
    305     if (_parent->path().is_root() ||
     305    if (_is_driver_port || _parent->path().is_root() ||
    306306        (_type == PortType::ATOM && !_value.is_valid())) {
    307307        return false;
     
    383383    for (uint32_t v = 0; v < _poly; ++v)
    384384        _voices->at(v).buffer = NULL;
     385}
     386
     387void
     388PortImpl::set_is_driver_port(BufferFactory& bufs)
     389{
     390    _is_driver_port = true;
    385391}
    386392
     
    443449    case PortType::ATOM:
    444450        if (_buffer_type == _bufs.uris().atom_Sequence) {
    445             const LV2_Atom* atom = buffer(0)->atom();
    446             if (buffer(0)->value() && !_monitored) {
    447                 // Value sequence not fully monitored, monitor as control
    448                 key = uris.ingen_value;
    449                 val = ((LV2_Atom_Float*)buffer(0)->value())->body;
    450             } else if (_monitored && !buffer(0)->empty()) {
    451                 // Monitoring explictly enabled, send everything
     451            const LV2_Atom* atom  = buffer(0)->get<const LV2_Atom>();
     452            const LV2_Atom* value = buffer(0)->value();
     453            if (atom->type != _bufs.uris().atom_Sequence) {
     454                /* Buffer contents are not actually a Sequence.  Probably an
     455                   uninitialized Chunk, so do nothing. */
     456            } else if (_monitored) {
     457                /* Sequence explicitly monitored, send everything. */
    452458                const LV2_Atom_Sequence* seq = (const LV2_Atom_Sequence*)atom;
    453459                LV2_ATOM_SEQUENCE_FOREACH(seq, ev) {
     
    459465                                   LV2_ATOM_BODY(&ev->body));
    460466                }
    461             } else if (!buffer(0)->empty()) {
    462                 // Just send activity for blinkenlights
     467            } else if (value && value->type == _bufs.uris().atom_Float) {
     468                /* Float sequence, monitor as a control. */
     469                key = uris.ingen_value;
     470                val = ((LV2_Atom_Float*)buffer(0)->value())->body;
     471            } else if (atom->size > sizeof(LV2_Atom_Sequence_Body)) {
     472                /* General sequence, send activity for blinkenlights. */
    463473                const int32_t one = 1;
    464474                context.notify(uris.ingen_activity,
  • src/server/PortImpl.hpp

    rade7143 r732bfb33  
    141141                           Sample         value);
    142142
    143     void set_is_driver_port(bool b) { _is_driver_port = b; }
    144     bool is_driver_port() const     { return _is_driver_port; }
     143    /** Prepare this port to use an external driver-provided buffer.
     144     *
     145     * This will avoid allocating a buffer for the port, instead the driver
     146     * buffer is used directly.  This only makes sense for ports on the
     147     * top-level graph, which are monophonic.  Non-real-time, must be called
     148     * before using the port, followed by a call to set_driver_buffer() in the
     149     * processing thread.
     150     */
     151    virtual void set_is_driver_port(BufferFactory& bufs);
     152
     153    bool is_driver_port() const { return _is_driver_port; }
    145154
    146155    /** Called once per process cycle */
  • src/server/events/Connect.cpp

    rade7143 r732bfb33  
    124124    lock.unlock();
    125125
    126     _voices = new Raul::Array<PortImpl::Voice>(_head->poly());
    127     _head->get_buffers(*_engine.buffer_factory(),
    128                        _voices,
    129                        _head->poly(),
    130                        false);
     126    if (!_head->is_driver_port()) {
     127        _voices = new Raul::Array<PortImpl::Voice>(_head->poly());
     128        _head->get_buffers(*_engine.buffer_factory(),
     129                           _voices,
     130                           _head->poly(),
     131                           false);
     132    }
    131133
    132134    if (_graph->enabled()) {
     
    142144    if (_status == Status::SUCCESS) {
    143145        _head->add_arc(context, _arc.get());
    144         _engine.maid()->dispose(_head->set_voices(context, _voices));
     146        if (!_head->is_driver_port()) {
     147            _engine.maid()->dispose(_head->set_voices(context, _voices));
     148        }
    145149        _head->connect_buffers();
    146150        _graph->set_compiled_graph(_compiled_graph);
  • src/server/events/CreatePort.cpp

    rade7143 r732bfb33  
    126126                             poly_i->second.get<int32_t>());
    127127
    128     if (!(_graph_port = _graph->create_port(
    129               bufs, Raul::Symbol(_path.symbol()),
    130               _port_type, _buf_type, buf_size, _is_output, polyphonic))) {
    131         return Event::pre_process_done(Status::CREATION_FAILED, _path);
     128    // Create 0 value if the port requires one
     129    Atom value;
     130    if (_port_type == PortType::CONTROL || _port_type == PortType::CV) {
     131        value = bufs.forge().make(0.0f);
    132132    }
     133
     134    // Create port
     135    _graph_port = new DuplexPort(bufs, _graph, Raul::Symbol(_path.symbol()),
     136                                 _graph->num_ports_non_rt(),
     137                                 polyphonic,
     138                                 _port_type, _buf_type, buf_size,
     139                                 value, _is_output);
    133140
    134141    _graph_port->properties().insert(_properties.begin(), _properties.end());
     
    142149
    143150    if (!_graph->parent()) {
    144         _engine_port = _engine.driver()->create_port(
    145             dynamic_cast<DuplexPort*>(_graph_port));
     151        _engine_port = _engine.driver()->create_port(_graph_port);
    146152    }
    147153
  • src/server/events/Disconnect.cpp

    rade7143 r732bfb33  
    9292
    9393    if (_dst_input_port->num_arcs() == 0) {
    94         _voices = new Raul::Array<PortImpl::Voice>(_dst_input_port->poly());
    95         _dst_input_port->get_buffers(*_engine.buffer_factory(),
    96                                      _voices,
    97                                      _dst_input_port->poly(),
    98                                      false);
    99 
    100         const bool is_control = _dst_input_port->is_a(PortType::CONTROL) ||
    101             _dst_input_port->is_a(PortType::CV);
    102         const float value = is_control ? _dst_input_port->value().get<float>() : 0;
    103         for (uint32_t i = 0; i < _voices->size(); ++i) {
    104             if (is_control) {
    105                 Buffer* buf = _voices->at(i).buffer.get();
    106                 buf->set_block(value, 0, buf->nframes());
     94        if (!_dst_input_port->is_driver_port()) {
     95            _voices = new Raul::Array<PortImpl::Voice>(_dst_input_port->poly());
     96            _dst_input_port->get_buffers(*_engine.buffer_factory(),
     97                                         _voices,
     98                                         _dst_input_port->poly(),
     99                                         false);
     100
     101            if (_dst_input_port->is_a(PortType::CONTROL) ||
     102                _dst_input_port->is_a(PortType::CV)) {
     103                // Reset buffer to control value
     104                const float value = _dst_input_port->value().get<float>();
     105                for (uint32_t i = 0; i < _voices->size(); ++i) {
     106                    Buffer* buf = _voices->at(i).buffer.get();
     107                    buf->set_block(value, 0, buf->nframes());
     108                }
    107109            } else {
    108                 _voices->at(i).buffer->clear();
     110                for (uint32_t i = 0; i < _voices->size(); ++i) {
     111                    _voices->at(i).buffer->clear();
     112                }
    109113            }
    110114        }
     
    178182    ArcImpl* const port_arc =
    179183        _dst_input_port->remove_arc(context, _src_output_port);
     184
    180185    if (!port_arc) {
    181186        return false;
     187    } else if (_dst_input_port->is_driver_port()) {
     188        return true;
    182189    }
    183190
  • src/server/events/SetPortValue.cpp

    rade7143 r732bfb33  
    108108        }
    109109    } else if (buf->type() == uris.atom_URID) {
    110         ((LV2_Atom_URID*)buf->atom())->body = _value.get<int32_t>();
     110        buf->get<LV2_Atom_URID>()->body = _value.get<int32_t>();
    111111    } else {
    112112        _status = Status::BAD_VALUE_TYPE;
  • src/server/ingen_lv2.cpp

    rade7143 r732bfb33  
    119119
    120120    void pre_process_port(ProcessContext& context, EnginePort* port) {
    121         PortImpl* graph_port = port->graph_port();
    122         void*     buffer     = port->buffer();
    123 
    124         if (!graph_port->is_input() || !buffer) {
    125             return;
    126         }
    127 
    128         Buffer* const graph_buf = graph_port->buffer(0).get();
    129         if (graph_port->is_a(PortType::AUDIO) ||
    130             graph_port->is_a(PortType::CV)) {
    131             memcpy(graph_buf->samples(),
    132                    buffer,
    133                    context.nframes() * sizeof(float));
    134         } else if (graph_port->is_a(PortType::CONTROL)) {
    135             graph_buf->samples()[0] = ((float*)buffer)[0];
    136         } else {
    137             LV2_Atom_Sequence* seq      = (LV2_Atom_Sequence*)buffer;
    138             bool               enqueued = false;
    139             URIs&              uris     = graph_port->bufs().uris();
    140             graph_buf->prepare_write(context);
    141             LV2_ATOM_SEQUENCE_FOREACH(seq, ev) {
    142                 if (!graph_buf->append_event(
    143                         ev->time.frames, ev->body.size, ev->body.type,
    144                         (const uint8_t*)LV2_ATOM_BODY(&ev->body))) {
    145                     _engine.log().warn("Failed to write to buffer, event lost!\n");
     121        const URIs&       uris       = _engine.world()->uris();
     122        const SampleCount nframes    = context.nframes();
     123        DuplexPort*       graph_port = port->graph_port();
     124        Buffer*           graph_buf  = graph_port->buffer(0).get();
     125        void*             lv2_buf    = port->buffer();
     126
     127        if (graph_port->is_a(PortType::AUDIO) || graph_port->is_a(PortType::CV)) {
     128            graph_port->set_driver_buffer(lv2_buf, nframes * sizeof(float));
     129        } else if (graph_port->buffer_type() == uris.atom_Sequence) {
     130            graph_port->set_driver_buffer(lv2_buf, lv2_atom_total_size((LV2_Atom*)lv2_buf));
     131            if (graph_port->symbol() == "control_in") {  // TODO: Safe to use index?
     132                LV2_Atom_Sequence* seq      = (LV2_Atom_Sequence*)lv2_buf;
     133                bool               enqueued = false;
     134                LV2_ATOM_SEQUENCE_FOREACH(seq, ev) {
     135                    if (AtomReader::is_message(uris, &ev->body)) {
     136                        enqueued = enqueue_message(&ev->body) || enqueued;
     137                    }
    146138                }
    147139
    148                 if (AtomReader::is_message(uris, &ev->body)) {
    149                     enqueue_message(&ev->body);
    150                     enqueued = true;
     140                if (enqueued) {
     141                    // Enqueued a message for processing, raise semaphore
     142                    _main_sem.post();
    151143                }
    152144            }
    153 
    154             if (enqueued) {
    155                 _main_sem.post();
    156             }
     145        }
     146
     147        if (graph_port->is_input()) {
     148            graph_port->monitor(context);
     149        } else {
     150            graph_buf->prepare_write(context);
    157151        }
    158152    }
    159153
    160154    void post_process_port(ProcessContext& context, EnginePort* port) {
    161         PortImpl* graph_port = port->graph_port();
    162         void*     buffer     = port->buffer();
    163 
    164         if (graph_port->is_input() || !buffer) {
    165             return;
    166         }
    167 
    168         Buffer* graph_buf = graph_port->buffer(0).get();
    169         if (graph_port->is_a(PortType::AUDIO) ||
    170             graph_port->is_a(PortType::CV)) {
    171             memcpy(buffer,
    172                    graph_buf->samples(),
    173                    context.nframes() * sizeof(float));
    174         } else if (graph_port->is_a(PortType::CONTROL)) {
    175             ((float*)buffer)[0] = graph_buf->samples()[0];
    176         } else if (graph_port->index() != 1) {
    177             /* Copy Sequence output to LV2 buffer, except notify output which
    178                is written by flush_to_ui() (TODO: merge) */
    179             memcpy(buffer,
    180                    graph_buf->atom(),
    181                    sizeof(LV2_Atom) + graph_buf->atom()->size);
     155        DuplexPort* graph_port = port->graph_port();
     156
     157        // No copying necessary, host buffers are used directly
     158        // Reset graph port buffer pointer to no longer point to the Jack buffer
     159        if (graph_port->is_driver_port()) {
     160            graph_port->set_driver_buffer(NULL, 0);
    182161        }
    183162    }
     
    259238
    260239    virtual EnginePort* create_port(DuplexPort* graph_port) {
     240        graph_port->set_is_driver_port(*_engine.buffer_factory());
    261241        return new EnginePort(graph_port);
    262242    }
     
    279259
    280260    /** Called in run thread for events received at control input port. */
    281     void enqueue_message(const LV2_Atom* atom) {
     261    bool enqueue_message(const LV2_Atom* atom) {
    282262        if (_from_ui.write(lv2_atom_total_size(atom), atom) == 0) {
    283263#ifndef NDEBUG
    284264            _engine.log().error("Control input buffer overflow\n");
    285265#endif
    286         }
     266            return false;
     267        }
     268        return true;
    287269    }
    288270
     
    586568    std::lock_guard<std::mutex> lock(plugin->world->rdf_mutex());
    587569
     570    fprintf(stderr, "LV2 parse resource %s from %s\n", graph->uri.c_str(), graph->filename.c_str());
    588571    plugin->world->parser()->parse_file(plugin->world,
    589572                                        plugin->world->interface().get(),
  • src/server/internals/Controller.cpp

    rade7143 r732bfb33  
    4848                               GraphImpl*          parent,
    4949                               SampleRate          srate)
    50     : BlockImpl(plugin, symbol, false, parent, srate)
     50    : InternalBlock(plugin, symbol, false, parent, srate)
    5151    , _learning(false)
    5252{
     
    104104{
    105105    Buffer* const      midi_in = _midi_in_port->buffer(0).get();
    106     LV2_Atom_Sequence* seq     = (LV2_Atom_Sequence*)midi_in->atom();
     106    LV2_Atom_Sequence* seq     = midi_in->get<LV2_Atom_Sequence>();
    107107    LV2_ATOM_SEQUENCE_FOREACH(seq, ev) {
    108108        const uint8_t* buf = (const uint8_t*)LV2_ATOM_BODY(&ev->body);
  • src/server/internals/Controller.hpp

    rade7143 r732bfb33  
    1818#define INGEN_INTERNALS_CONTROLLER_HPP
    1919
    20 #include "BlockImpl.hpp"
     20#include "InternalBlock.hpp"
    2121
    2222namespace Ingen {
     
    3636 * \ingroup engine
    3737 */
    38 class ControllerNode : public BlockImpl
     38class ControllerNode : public InternalBlock
    3939{
    4040public:
  • src/server/internals/Delay.cpp

    rade7143 r732bfb33  
    5656                     GraphImpl*          parent,
    5757                     SampleRate          srate)
    58     : BlockImpl(plugin, symbol, polyphonic, parent, srate)
     58    : InternalBlock(plugin, symbol, polyphonic, parent, srate)
    5959    , _buffer(0)
    6060    , _buffer_length(0)
  • src/server/internals/Delay.hpp

    rade7143 r732bfb33  
    2020#include <math.h>
    2121
    22 #include "BlockImpl.hpp"
     22#include "InternalBlock.hpp"
    2323#include "types.hpp"
    2424
     
    3333namespace Internals {
    3434
    35 class DelayNode : public BlockImpl
     35class DelayNode : public InternalBlock
    3636{
    3737public:
  • src/server/internals/Note.cpp

    rade7143 r732bfb33  
    5353                   GraphImpl*          parent,
    5454                   SampleRate          srate)
    55     : BlockImpl(plugin, symbol, polyphonic, parent, srate)
     55    : InternalBlock(plugin, symbol, polyphonic, parent, srate)
    5656    , _voices(new Raul::Array<Voice>(_polyphony))
    5757    , _prepared_voices(NULL)
     
    172172{
    173173    Buffer* const      midi_in = _midi_in_port->buffer(0).get();
    174     LV2_Atom_Sequence* seq     = (LV2_Atom_Sequence*)midi_in->atom();
     174    LV2_Atom_Sequence* seq     = midi_in->get<LV2_Atom_Sequence>();
    175175    LV2_ATOM_SEQUENCE_FOREACH(seq, ev) {
    176176        const uint8_t*  buf  = (const uint8_t*)LV2_ATOM_BODY_CONST(&ev->body);
  • src/server/internals/Note.hpp

    rade7143 r732bfb33  
    1818#define INGEN_INTERNALS_NOTE_HPP
    1919
    20 #include "BlockImpl.hpp"
     20#include "InternalBlock.hpp"
    2121#include "types.hpp"
    2222
     
    3636 * \ingroup engine
    3737 */
    38 class NoteNode : public BlockImpl
     38class NoteNode : public InternalBlock
    3939{
    4040public:
  • src/server/internals/Time.cpp

    rade7143 r732bfb33  
    4343                   GraphImpl*          parent,
    4444                   SampleRate          srate)
    45     : BlockImpl(plugin, symbol, false, parent, srate)
     45    : InternalBlock(plugin, symbol, false, parent, srate)
    4646{
    4747    const Ingen::URIs& uris = bufs.uris();
     
    6161{
    6262    BufferRef          buf = _notify_port->buffer(0);
    63     LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)buf->atom();
     63    LV2_Atom_Sequence* seq = buf->get<LV2_Atom_Sequence>();
    6464
    6565    // Initialise output to the empty sequence
  • src/server/internals/Time.hpp

    rade7143 r732bfb33  
    1818#define INGEN_INTERNALS_TIME_HPP
    1919
    20 #include "BlockImpl.hpp"
     20#include "InternalBlock.hpp"
    2121
    2222namespace Ingen {
     
    3535 * \ingroup engine
    3636 */
    37 class TimeNode : public BlockImpl
     37class TimeNode : public InternalBlock
    3838{
    3939public:
  • src/server/internals/Trigger.cpp

    rade7143 r732bfb33  
    4848                         GraphImpl*          parent,
    4949                         SampleRate          srate)
    50     : BlockImpl(plugin, symbol, false, parent, srate)
     50    : InternalBlock(plugin, symbol, false, parent, srate)
    5151    , _learning(false)
    5252{
     
    100100{
    101101    Buffer* const      midi_in = _midi_in_port->buffer(0).get();
    102     LV2_Atom_Sequence* seq     = (LV2_Atom_Sequence*)midi_in->atom();
     102    LV2_Atom_Sequence* seq     = midi_in->get<LV2_Atom_Sequence>();
    103103    LV2_ATOM_SEQUENCE_FOREACH(seq, ev) {
    104104        const uint8_t* buf = (const uint8_t*)LV2_ATOM_BODY(&ev->body);
  • src/server/internals/Trigger.hpp

    rade7143 r732bfb33  
    1818#define INGEN_INTERNALS_TRIGGER_HPP
    1919
    20 #include "BlockImpl.hpp"
     20#include "InternalBlock.hpp"
    2121
    2222namespace Ingen {
     
    3939 * \ingroup engine
    4040 */
    41 class TriggerNode : public BlockImpl
     41class TriggerNode : public InternalBlock
    4242{
    4343public:
  • src/server/mix.cpp

    rade7143 r732bfb33  
    2727is_end(const Buffer* buf, const LV2_Atom_Event* ev)
    2828{
     29    const LV2_Atom* atom = buf->get<const LV2_Atom>();
    2930    return lv2_atom_sequence_is_end(
    30         (const LV2_Atom_Sequence_Body*)LV2_ATOM_BODY_CONST(buf->atom()),
    31         buf->atom()->size,
     31        (const LV2_Atom_Sequence_Body*)LV2_ATOM_BODY_CONST(atom),
     32        atom->size,
    3233        ev);
    3334}
     
    7374            iters[i] = NULL;
    7475            if (srcs[i]->is_sequence()) {
    75                 iters[i] = lv2_atom_sequence_begin(
    76                     (const LV2_Atom_Sequence_Body*)LV2_ATOM_BODY_CONST(
    77                         srcs[i]->atom()));
     76                const LV2_Atom_Sequence* seq = srcs[i]->get<const LV2_Atom_Sequence>();
     77                iters[i] = lv2_atom_sequence_begin(&seq->body);
    7878                if (is_end(srcs[i], iters[i])) {
    7979                    iters[i] = NULL;
  • src/server/wscript

    rade7143 r732bfb33  
    1717            GraphImpl.cpp
    1818            InputPort.cpp
     19            InternalBlock.cpp
    1920            InternalPlugin.cpp
    2021            LV2Block.cpp
Note: See TracChangeset for help on using the changeset viewer.