From 138a87e915ad3aff184730415105f94c874174bf Mon Sep 17 00:00:00 2001 From: David Robillard Date: Wed, 20 Apr 2011 16:26:40 +0000 Subject: Rename Ingen::Engine to Ingen::Server (hopefully avoid odd name clases and fix #675). git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@3184 a436a847-0d15-0410-975c-d299462d15a1 --- src/server/PortImpl.cpp | 251 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 251 insertions(+) create mode 100644 src/server/PortImpl.cpp (limited to 'src/server/PortImpl.cpp') diff --git a/src/server/PortImpl.cpp b/src/server/PortImpl.cpp new file mode 100644 index 00000000..a448916e --- /dev/null +++ b/src/server/PortImpl.cpp @@ -0,0 +1,251 @@ +/* This file is part of Ingen. + * Copyright 2007-2011 David Robillard + * + * 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 "raul/Array.hpp" +#include "raul/Maid.hpp" +#include "shared/LV2URIMap.hpp" +#include "lv2/lv2plug.in/ns/ext/contexts/contexts.h" +#include "ingen/PortType.hpp" +#include "events/SendPortValue.hpp" +#include "events/SendPortActivity.hpp" +#include "AudioBuffer.hpp" +#include "BufferFactory.hpp" +#include "Engine.hpp" +#include "EventBuffer.hpp" +#include "LV2Atom.hpp" +#include "NodeImpl.hpp" +#include "ObjectBuffer.hpp" +#include "PortImpl.hpp" +#include "ThreadManager.hpp" + +using namespace std; +using namespace Raul; + +namespace Ingen { +namespace Server { + +PortImpl::PortImpl(BufferFactory& bufs, + NodeImpl* const node, + const Raul::Symbol& name, + uint32_t index, + uint32_t poly, + PortType type, + const Atom& value, + size_t buffer_size) + : GraphObjectImpl(bufs.uris(), node, name) + , _bufs(bufs) + , _index(index) + , _poly(poly) + , _buffer_size(buffer_size) + , _buffer_type(type) + , _value(value) + , _broadcast(false) + , _set_by_user(false) + , _last_broadcasted_value(value) + , _context(Context::AUDIO) + , _buffers(new Array(static_cast(poly))) + , _prepared_buffers(NULL) +{ + _types.insert(type); + assert(node != NULL); + assert(_poly > 0); + + if (_buffer_size == 0) + _buffer_size = bufs.default_buffer_size(type); + + const Ingen::Shared::LV2URIMap& uris = bufs.uris(); + add_property(uris.rdf_type, type.uri()); + set_property(uris.lv2_index, Atom((int32_t)index)); + set_context(_context); + + if (type == PortType::EVENTS) + _broadcast = true; // send activity blips +} + +PortImpl::~PortImpl() +{ + delete _buffers; +} + +bool +PortImpl::supports(const Raul::URI& value_type) const +{ + return has_property(_bufs.uris().atom_supports, value_type); +} + +Raul::Array* +PortImpl::set_buffers(Raul::Array* buffers) +{ + ThreadManager::assert_thread(THREAD_PROCESS); + + Raul::Array* ret = NULL; + if (buffers != _buffers) { + ret = _buffers; + _buffers = buffers; + } + + connect_buffers(); + + return ret; +} + +bool +PortImpl::prepare_poly(BufferFactory& bufs, uint32_t poly) +{ + ThreadManager::assert_thread(THREAD_PRE_PROCESS); + if (buffer_type() != PortType::CONTROL && buffer_type() != PortType::AUDIO) + return false; + + if (_poly == poly) + return true; + + if (_prepared_buffers && _prepared_buffers->size() != poly) { + delete _prepared_buffers; + _prepared_buffers = NULL; + } + + if (!_prepared_buffers) + _prepared_buffers = new Array(poly, *_buffers, NULL); + + return true; +} + +void +PortImpl::prepare_poly_buffers(BufferFactory& bufs) +{ + if (_prepared_buffers) + get_buffers(bufs, _prepared_buffers, _prepared_buffers->size()); +} + +bool +PortImpl::apply_poly(Maid& maid, uint32_t poly) +{ + ThreadManager::assert_thread(THREAD_PROCESS); + if (buffer_type() != PortType::CONTROL && buffer_type() != PortType::AUDIO) + return false; + + if (!_prepared_buffers) + return true; + + assert(poly == _prepared_buffers->size()); + + _poly = poly; + + // Apply a new set of buffers from a preceding call to prepare_poly + maid.push(set_buffers(_prepared_buffers)); + assert(_buffers == _prepared_buffers); + _prepared_buffers = NULL; + + if (is_a(PortType::CONTROL)) + for (uint32_t v = 0; v < _poly; ++v) + if (_buffers->at(v)) + boost::static_pointer_cast(_buffers->at(v))->set_value( + _value.get_float(), 0, 0); + + assert(_buffers->size() >= poly); + assert(this->poly() == poly); + assert(!_prepared_buffers); + + return true; +} + +void +PortImpl::set_buffer_size(Context& context, BufferFactory& bufs, size_t size) +{ + _buffer_size = size; + + for (uint32_t v = 0; v < _poly; ++v) + _buffers->at(v)->resize(size); + + connect_buffers(); +} + +void +PortImpl::connect_buffers(SampleCount offset) +{ + for (uint32_t v = 0; v < _poly; ++v) + PortImpl::parent_node()->set_port_buffer(v, _index, buffer(v), offset); +} + +void +PortImpl::recycle_buffers() +{ + for (uint32_t v = 0; v < _poly; ++v) + _buffers->at(v) = NULL; +} + +void +PortImpl::clear_buffers() +{ + for (uint32_t v = 0; v < _poly; ++v) + buffer(v)->clear(); +} + +void +PortImpl::broadcast_value(Context& context, bool force) +{ + Raul::Atom val; + switch (buffer_type().symbol()) { + case PortType::UNKNOWN: + break; + case PortType::AUDIO: + case PortType::CONTROL: + val = ((AudioBuffer*)buffer(0).get())->value_at(0); + break; + case PortType::EVENTS: + if (((EventBuffer*)buffer(0).get())->event_count() > 0) { + const Events::SendPortActivity ev(context.engine(), context.start(), this); + context.event_sink().write(sizeof(ev), &ev); + } + break; + case PortType::VALUE: + case PortType::MESSAGE: + Ingen::Shared::LV2Atom::to_atom(_bufs.uris(), ((ObjectBuffer*)buffer(0).get())->atom(), val); + break; + } + + if (val.is_valid() && (force || val != _last_broadcasted_value)) { + _last_broadcasted_value = val; + const Events::SendPortValue ev(context.engine(), context.start(), this, true, 0, val); + context.event_sink().write(sizeof(ev), &ev); + } +} + +void +PortImpl::set_context(Context::ID c) +{ + const Ingen::Shared::LV2URIMap& uris = _bufs.uris(); + _context = c; + switch (c) { + case Context::AUDIO: + remove_property(uris.ctx_context, uris.wildcard); + break; + case Context::MESSAGE: + set_property(uris.ctx_context, uris.ctx_MessageContext); + break; + } +} + +PortType +PortImpl::buffer_type() const +{ + // TODO: multiple types + return *_types.begin(); +} + +} // namespace Server +} // namespace Ingen -- cgit v1.2.1