/*
This file is part of Ingen.
Copyright 2007-2015 David Robillard
Ingen is free software: you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free
Software Foundation, either version 3 of the License, or 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 Affero General Public License for details.
You should have received a copy of the GNU Affero General Public License
along with Ingen. If not, see .
*/
#include "ingen/URIs.hpp"
#include "lv2/lv2plug.in/ns/ext/atom/util.h"
#include "ArcImpl.hpp"
#include "BlockImpl.hpp"
#include "Buffer.hpp"
#include "BufferFactory.hpp"
#include "Engine.hpp"
#include "InputPort.hpp"
#include "OutputPort.hpp"
#include "PortImpl.hpp"
namespace Ingen {
namespace Server {
/** Constructor for an arc from a block's output port.
*
* This handles both polyphonic and monophonic blocks, transparently to the
* user (InputPort).
*/
ArcImpl::ArcImpl(PortImpl* tail, PortImpl* head)
: _tail(tail)
, _head(head)
{
assert(tail != head);
assert(tail->path() != head->path());
}
const Raul::Path&
ArcImpl::tail_path() const
{
return _tail->path();
}
const Raul::Path&
ArcImpl::head_path() const
{
return _head->path();
}
BufferRef
ArcImpl::buffer(uint32_t voice, SampleCount offset) const
{
assert(_tail->poly() == 1 || _tail->poly() > voice);
if (_tail->poly() == 1) {
voice = 0;
}
if (_tail->buffer(0)->is_sequence()) {
if (_head->type() == PortType::CONTROL) {
_tail->update_values(offset, voice); // Update value buffer
return _tail->value_buffer(voice); // Return value buffer
} else if (_head->type() == PortType::CV) {
// Return full tail buffer below
}
}
return _tail->buffer(voice);
}
bool
ArcImpl::must_mix() const
{
return (_tail->poly() > _head->poly() ||
(_tail->buffer(0)->is_sequence() != _head->buffer(0)->is_sequence()));
}
bool
ArcImpl::can_connect(const OutputPort* src, const InputPort* dst)
{
const Ingen::URIs& uris = src->bufs().uris();
return (
// (Audio | Control | CV) => (Audio | Control | CV)
( (src->is_a(PortType::ID::CONTROL) ||
src->is_a(PortType::ID::AUDIO) ||
src->is_a(PortType::ID::CV))
&& (dst->is_a(PortType::ID::CONTROL)
|| dst->is_a(PortType::ID::AUDIO)
|| dst->is_a(PortType::ID::CV)))
// Equal types
|| (src->type() == dst->type() &&
src->buffer_type() == dst->buffer_type())
// Control => atom:Float Value
|| (src->is_a(PortType::ID::CONTROL) && dst->supports(uris.atom_Float))
// Audio => atom:Sound Value
|| (src->is_a(PortType::ID::AUDIO) && dst->supports(uris.atom_Sound))
// atom:Float Value => Control
|| (src->supports(uris.atom_Float) && dst->is_a(PortType::ID::CONTROL))
// atom:Float Value => CV
|| (src->supports(uris.atom_Float) && dst->is_a(PortType::ID::CV))
// atom:Sound Value => Audio
|| (src->supports(uris.atom_Sound) && dst->is_a(PortType::ID::AUDIO)));
}
} // namespace Server
} // namespace Ingen