/* This file is part of Ingen. Copyright 2007-2017 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 . */ #ifndef INGEN_ENGINE_ENGINE_HPP #define INGEN_ENGINE_ENGINE_HPP #include "Event.hpp" #include "Load.hpp" #include "types.hpp" #include "ingen/Clock.hpp" #include "ingen/EngineBase.hpp" #include "ingen/Properties.hpp" #include "ingen/ingen.h" #include "ingen/types.hpp" #include #include #include #include #include #include #include namespace Raul { class Maid; class RingBuffer; } // namespace Raul namespace ingen { class AtomReader; class Interface; class Log; class Store; class World; namespace server { class BlockFactory; class Broadcaster; class BufferFactory; class ControlBindings; class Driver; class EventWriter; class GraphImpl; class LV2Options; class PostProcessor; class PreProcessor; class RunContext; class SocketListener; class Task; class UndoStack; class Worker; /** The engine which executes the process graph. This is a simple class that provides pointers to the various components that make up the engine implementation. In processes with a local engine, it can be accessed via the ingen::World. @ingroup engine */ class INGEN_API Engine final : public EngineBase { public: explicit Engine(ingen::World& world); ~Engine() override; Engine(const Engine&) = delete; Engine& operator=(const Engine&) = delete; // EngineBase methods void init(double sample_rate, uint32_t block_length, size_t seq_size) override; bool supports_dynamic_ports() const override; bool activate() override; void deactivate() override; bool pending_events() const override; unsigned run(uint32_t sample_count) override; void quit() override; bool main_iteration() override; void register_client(const SPtr& client) override; bool unregister_client(const SPtr& client) override; void listen() override; /** Return a random [0..1] float with uniform distribution */ float frand() { return _uniform_dist(_rand_engine); } void set_driver(const SPtr& driver); /** Return the frame time to execute an event that arrived now. * * This aims to return a time one cycle from "now", so that events ideally * have 1 cycle of latency with no jitter. */ SampleCount event_time(); /** Return the time this cycle began processing in microseconds. * * This value is comparable to the value returned by current_time(). */ inline uint64_t cycle_start_time(const RunContext&) const { return _cycle_start_time; } /** Return the current time in microseconds. */ uint64_t current_time() const; /** Reset the load statistics (when the expected DSP load changes). */ void reset_load(); /** Enqueue an event to be processed (non-realtime threads only). */ void enqueue_event(Event* ev, Event::Mode mode=Event::Mode::NORMAL); /** Process events (process thread only). */ unsigned process_events(); /** Process all events (no RT limits). */ unsigned process_all_events(); ingen::World& world() const { return _world; } Log& log() const; const SPtr& interface() const { return _interface; } const SPtr& event_writer() const { return _event_writer; } const UPtr& atom_interface() const { return _atom_interface; } const UPtr& block_factory() const { return _block_factory; } const UPtr& broadcaster() const { return _broadcaster; } const UPtr& buffer_factory() const { return _buffer_factory; } const UPtr& control_bindings() const { return _control_bindings; } const SPtr& driver() const { return _driver; } const UPtr& post_processor() const { return _post_processor; } const UPtr& maid() const { return _maid; } const UPtr& undo_stack() const { return _undo_stack; } const UPtr& redo_stack() const { return _redo_stack; } const UPtr& worker() const { return _worker; } const UPtr& sync_worker() const { return _sync_worker; } GraphImpl* root_graph() const { return _root_graph; } void set_root_graph(GraphImpl* graph); RunContext& run_context() { return *_run_contexts[0]; } void flush_events(const std::chrono::milliseconds& sleep_ms) override; void advance(SampleCount nframes) override; void locate(FrameTime s, SampleCount nframes) override; void emit_notifications(FrameTime end); bool pending_notifications(); bool wait_for_tasks(); void signal_tasks_available(); Task* steal_task(unsigned start_thread); SPtr store() const; SampleRate sample_rate() const; SampleCount block_length() const; size_t sequence_size() const; size_t event_queue_size() const; size_t n_threads() const { return _run_contexts.size(); } bool atomic_bundles() const { return _atomic_bundles; } bool activated() const { return _activated; } Properties load_properties() const; private: ingen::World& _world; SPtr _options; UPtr _buffer_factory; UPtr _maid; SPtr _driver; UPtr _worker; UPtr _sync_worker; UPtr _broadcaster; UPtr _control_bindings; UPtr _block_factory; UPtr _undo_stack; UPtr _redo_stack; UPtr _post_processor; UPtr _pre_processor; UPtr _listener; SPtr _event_writer; SPtr _interface; UPtr _atom_interface; GraphImpl* _root_graph; std::vector> _notifications; std::vector> _run_contexts; uint64_t _cycle_start_time; Load _run_load; Clock _clock; std::mt19937 _rand_engine; std::uniform_real_distribution _uniform_dist; std::condition_variable _tasks_available; std::mutex _tasks_mutex; bool _quit_flag; bool _reset_load_flag; bool _atomic_bundles; bool _activated; }; } // namespace server } // namespace ingen #endif // INGEN_ENGINE_ENGINE_HPP