summaryrefslogtreecommitdiffstats
path: root/src/server/RunContext.cpp
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2016-09-11 15:21:25 +0200
committerDavid Robillard <d@drobilla.net>2016-09-11 15:21:25 +0200
commitf3546d49dbd2d673138387a87bc523c26dcece68 (patch)
treeede285a773fc565205f82a2b0a62ebba6ea552e0 /src/server/RunContext.cpp
parentfb2744d4265d26fb98b19689b50d127f32c66eab (diff)
downloadingen-f3546d49dbd2d673138387a87bc523c26dcece68.tar.gz
ingen-f3546d49dbd2d673138387a87bc523c26dcece68.tar.bz2
ingen-f3546d49dbd2d673138387a87bc523c26dcece68.zip
Remove last vestiges of multiple run contexts
Diffstat (limited to 'src/server/RunContext.cpp')
-rw-r--r--src/server/RunContext.cpp142
1 files changed, 142 insertions, 0 deletions
diff --git a/src/server/RunContext.cpp b/src/server/RunContext.cpp
new file mode 100644
index 00000000..ee1eaf04
--- /dev/null
+++ b/src/server/RunContext.cpp
@@ -0,0 +1,142 @@
+/*
+ This file is part of Ingen.
+ Copyright 2007-2015 David Robillard <http://drobilla.net/>
+
+ 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 <http://www.gnu.org/licenses/>.
+*/
+
+#include "ingen/Forge.hpp"
+#include "ingen/Log.hpp"
+#include "ingen/URIMap.hpp"
+
+#include "Broadcaster.hpp"
+#include "BufferFactory.hpp"
+#include "Engine.hpp"
+#include "PortImpl.hpp"
+#include "RunContext.hpp"
+
+namespace Ingen {
+namespace Server {
+
+struct Notification
+{
+ inline Notification(PortImpl* p = 0,
+ FrameTime f = 0,
+ LV2_URID k = 0,
+ uint32_t s = 0,
+ LV2_URID t = 0)
+ : port(p), time(f), key(k), size(s), type(t)
+ {}
+
+ PortImpl* port;
+ FrameTime time;
+ LV2_URID key;
+ uint32_t size;
+ LV2_URID type;
+};
+
+RunContext::RunContext(Engine& engine)
+ : _engine(engine)
+ , _event_sink(
+ new Raul::RingBuffer(engine.event_queue_size() * sizeof(Notification)))
+ , _start(0)
+ , _end(0)
+ , _offset(0)
+ , _nframes(0)
+ , _realtime(true)
+ , _copy(false)
+{}
+
+RunContext::RunContext(const RunContext& copy)
+ : _engine(copy._engine)
+ , _event_sink(copy._event_sink)
+ , _start(copy._start)
+ , _end(copy._end)
+ , _offset(copy._offset)
+ , _nframes(copy._nframes)
+ , _realtime(copy._realtime)
+ , _copy(true)
+{}
+
+RunContext::~RunContext()
+{
+ if (!_copy) {
+ delete _event_sink;
+ }
+}
+
+bool
+RunContext::must_notify(const PortImpl* port) const
+{
+ return (port->is_monitored() || _engine.broadcaster()->must_broadcast());
+}
+
+bool
+RunContext::notify(LV2_URID key,
+ FrameTime time,
+ PortImpl* port,
+ uint32_t size,
+ LV2_URID type,
+ const void* body)
+{
+ const Notification n(port, time, key, size, type);
+ if (_event_sink->write_space() < sizeof(n) + size) {
+ return false;
+ }
+ if (_event_sink->write(sizeof(n), &n) != sizeof(n)) {
+ _engine.log().error("Error writing header to notification ring\n");
+ } else if (_event_sink->write(size, body) != size) {
+ _engine.log().error("Error writing body to notification ring\n");
+ } else {
+ return true;
+ }
+ return false;
+}
+
+void
+RunContext::emit_notifications(FrameTime end)
+{
+ const URIs& uris = _engine.buffer_factory()->uris();
+ const uint32_t read_space = _event_sink->read_space();
+ Notification note;
+ for (uint32_t i = 0; i < read_space; i += sizeof(note)) {
+ if (_event_sink->peek(sizeof(note), &note) != sizeof(note) ||
+ note.time >= end) {
+ return;
+ }
+ if (_event_sink->read(sizeof(note), &note) == sizeof(note)) {
+ Atom value = _engine.world()->forge().alloc(
+ note.size, note.type, NULL);
+ if (_event_sink->read(note.size, value.get_body()) == note.size) {
+ i += note.size;
+ const char* key = _engine.world()->uri_map().unmap_uri(note.key);
+ if (key) {
+ _engine.broadcaster()->set_property(
+ note.port->uri(), Raul::URI(key), value);
+ if (note.port->is_input() && note.key == uris.ingen_value) {
+ // FIXME: not thread safe
+ note.port->set_property(uris.ingen_value, value);
+ }
+ } else {
+ _engine.log().error("Error unmapping notification key URI\n");
+ }
+ } else {
+ _engine.log().error("Error reading body from notification ring\n");
+ }
+ } else {
+ _engine.log().error("Error reading header from notification ring\n");
+ }
+ }
+}
+
+} // namespace Server
+} // namespace Ingen