/*
This file is part of Ingen.
Copyright 2007-2012 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
#include "ingen/URIs.hpp"
#include "ingen/client/BlockModel.hpp"
#include "ingen/client/ClientStore.hpp"
#include "ingen/client/EdgeModel.hpp"
#include "ingen/client/GraphModel.hpp"
using namespace std;
namespace Ingen {
namespace Client {
void
GraphModel::add_child(SharedPtr c)
{
assert(c->parent().get() == this);
SharedPtr pm = PtrCast(c);
if (pm) {
add_port(pm);
return;
}
SharedPtr bm = PtrCast(c);
if (bm) {
_signal_new_block.emit(bm);
}
}
bool
GraphModel::remove_child(SharedPtr o)
{
assert(o->path().is_child_of(path()));
assert(o->parent().get() == this);
// Remove any connections which referred to this object,
// since they can't possibly exist anymore
for (Edges::iterator j = _edges.begin(); j != _edges.end();) {
Edges::iterator next = j;
++next;
SharedPtr cm = PtrCast(j->second);
assert(cm);
if (cm->tail_path().parent() == o->path()
|| cm->tail_path() == o->path()
|| cm->head_path().parent() == o->path()
|| cm->head_path() == o->path()) {
_signal_removed_edge.emit(cm);
_edges.erase(j); // cuts our reference
}
j = next;
}
SharedPtr pm = PtrCast(o);
if (pm)
remove_port(pm);
SharedPtr bm = PtrCast(o);
if (bm) {
_signal_removed_block.emit(bm);
}
return true;
}
void
GraphModel::clear()
{
_edges.clear();
BlockModel::clear();
assert(_edges.empty());
assert(_ports.empty());
}
SharedPtr
GraphModel::get_edge(const GraphObject* tail, const GraphObject* head)
{
Edges::iterator i = _edges.find(make_pair(tail, head));
if (i != _edges.end())
return PtrCast(i->second);
else
return SharedPtr();
}
/** Add a connection to this graph.
*
* A reference to @a cm is taken, released on deletion or removal.
* If @a cm only contains paths (not pointers to the actual ports), the ports
* will be found and set. The ports referred to not existing as children of
* this graph is a fatal error.
*/
void
GraphModel::add_edge(SharedPtr cm)
{
// Store should have 'resolved' the connection already
assert(cm);
assert(cm->tail());
assert(cm->head());
assert(cm->tail()->parent());
assert(cm->head()->parent());
assert(cm->tail_path() != cm->head_path());
assert(cm->tail()->parent().get() == this
|| cm->tail()->parent()->parent().get() == this);
assert(cm->head()->parent().get() == this
|| cm->head()->parent()->parent().get() == this);
SharedPtr existing = get_edge(
cm->tail().get(), cm->head().get());
if (existing) {
assert(cm->tail() == existing->tail());
assert(cm->head() == existing->head());
} else {
_edges.insert(make_pair(make_pair(cm->tail().get(),
cm->head().get()), cm));
_signal_new_edge.emit(cm);
}
}
void
GraphModel::remove_edge(const GraphObject* tail, const GraphObject* head)
{
Edges::iterator i = _edges.find(make_pair(tail, head));
if (i != _edges.end()) {
SharedPtr c = PtrCast(i->second);
_signal_removed_edge.emit(c);
_edges.erase(i);
}
}
bool
GraphModel::enabled() const
{
const Raul::Atom& enabled = get_property(_uris.ingen_enabled);
return (enabled.is_valid() && enabled.get_bool());
}
uint32_t
GraphModel::internal_poly() const
{
const Raul::Atom& poly = get_property(_uris.ingen_polyphony);
return poly.is_valid() ? poly.get_int32() : 1;
}
bool
GraphModel::polyphonic() const
{
const Raul::Atom& poly = get_property(_uris.ingen_polyphonic);
return poly.is_valid() && poly.get_bool();
}
} // namespace Client
} // namespace Ingen