/* This file is part of Ingen. * Copyright (C) 2007-2009 Dave 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/log.hpp" #include "QueuedEngineInterface.hpp" #include "tuning.hpp" #include "EventSource.hpp" #include "events.hpp" #include "Engine.hpp" #include "Driver.hpp" #define LOG(s) s << "[QueuedEngineInterface] " using namespace std; using namespace Raul; namespace Ingen { using namespace Shared; QueuedEngineInterface::QueuedEngineInterface(Engine& engine, size_t queue_size) : EventSource(queue_size) , _request(new Request(this, NULL, 0)) , _engine(engine) , _in_bundle(false) { } SampleCount QueuedEngineInterface::now() const { // Exactly one cycle latency (some could run ASAP if we get lucky, but not always, and a slight // constant latency is far better than jittery lower (average) latency if (_engine.driver()) return _engine.driver()->frame_time() + _engine.driver()->block_length(); else return 0; } void QueuedEngineInterface::set_next_response_id(int32_t id) { if (_request) _request->set_id(id); } void QueuedEngineInterface::disable_responses() { _request->set_client(NULL); _request->set_id(0); } /* *** EngineInterface implementation below here *** */ void QueuedEngineInterface::register_client(ClientInterface* client) { push_queued(new Events::RegisterClient(_engine, _request, now(), client->uri(), client)); if (!_request) { _request = SharedPtr(new Request(this, client, 1)); } else { _request->set_id(1); _request->set_client(client); } } void QueuedEngineInterface::unregister_client(const URI& uri) { push_queued(new Events::UnregisterClient(_engine, _request, now(), uri)); if (_request && _request->client() && _request->client()->uri() == uri) { _request->set_id(0); _request->set_client(NULL); } } // Engine commands void QueuedEngineInterface::load_plugins() { push_queued(new Events::LoadPlugins(_engine, _request, now())); } void QueuedEngineInterface::activate() { static bool in_activate = false; if (!in_activate) { in_activate = true; _engine.activate(); } EventSource::activate_source(); push_queued(new Events::Ping(_engine, _request, now())); in_activate = false; } void QueuedEngineInterface::deactivate() { push_queued(new Events::Deactivate(_engine, _request, now())); } void QueuedEngineInterface::quit() { _request->respond_ok(); _engine.quit(); } // Bundle commands void QueuedEngineInterface::bundle_begin() { _in_bundle = true; } void QueuedEngineInterface::bundle_end() { _in_bundle = false; } // Object commands void QueuedEngineInterface::put(const URI& uri, const Resource::Properties& properties) { bool meta = ResourceImpl::is_meta_uri(uri); URI subject(meta ? (string("path:/") + uri.substr(6)) : uri.str()); push_queued(new Events::SetMetadata(_engine, _request, now(), true, meta, subject, properties)); } void QueuedEngineInterface::delta(const URI& uri, const Shared::Resource::Properties& remove, const Shared::Resource::Properties& add) { bool meta = ResourceImpl::is_meta_uri(uri); URI subject(meta ? (string("path:/") + uri.substr(6)) : uri.str()); push_queued(new Events::SetMetadata(_engine, _request, now(), false, meta, subject, add, remove)); } void QueuedEngineInterface::move(const Path& old_path, const Path& new_path) { push_queued(new Events::Move(_engine, _request, now(), old_path, new_path)); } void QueuedEngineInterface::del(const Path& path) { push_queued(new Events::Delete(_engine, _request, now(), path)); } void QueuedEngineInterface::connect(const Path& src_port_path, const Path& dst_port_path) { push_queued(new Events::Connect(_engine, _request, now(), src_port_path, dst_port_path)); } void QueuedEngineInterface::disconnect(const Path& src_port_path, const Path& dst_port_path) { push_queued(new Events::Disconnect(_engine, _request, now(), src_port_path, dst_port_path)); } void QueuedEngineInterface::disconnect_all(const Path& patch_path, const Path& path) { push_queued(new Events::DisconnectAll(_engine, _request, now(), patch_path, path)); } void QueuedEngineInterface::set_property(const URI& uri, const URI& predicate, const Atom& value) { size_t hash = uri.find("#"); bool meta = (hash != string::npos); Path path = meta ? (string("/") + path.chop_start("/")) : uri.str(); Resource::Properties remove; remove.insert(make_pair(predicate, _engine.world()->uris()->wildcard)); Resource::Properties add; add.insert(make_pair(predicate, value)); push_queued(new Events::SetMetadata(_engine, _request, now(), false, meta, path, add, remove)); } // Requests // void QueuedEngineInterface::ping() { if (_engine.activated()) { push_queued(new Events::Ping(_engine, _request, now())); } else if (_request) { _request->respond_ok(); } } void QueuedEngineInterface::get(const URI& uri) { push_queued(new Events::Get(_engine, _request, now(), uri)); } void QueuedEngineInterface::request_property(const URI& uri, const URI& key) { size_t hash = uri.find("#"); bool meta = (hash != string::npos); const string path_str = string("/") + uri.chop_start("/"); if (meta && Path::is_valid(path_str)) push_queued(new Events::RequestMetadata(_engine, _request, now(), meta, path_str, key)); else push_queued(new Events::RequestMetadata(_engine, _request, now(), meta, uri, key)); } } // namespace Ingen