diff --git a/src/lib/iter-tree-explorer.hpp b/src/lib/iter-tree-explorer.hpp index b78ce532c..18e7efc5c 100644 --- a/src/lib/iter-tree-explorer.hpp +++ b/src/lib/iter-tree-explorer.hpp @@ -1704,13 +1704,13 @@ namespace lib { /** start building a TreeExplorer * by suitably wrapping the given iterable source. * @return a TreeEplorer, which is an Iterator to yield all the source elements, - * but may also be used to build an processing pipeline. + * but may also be used to build up a complex processing pipeline. * @warning if you capture the result of this call by an auto variable, * be sure to understand that invoking any further builder operation on * TreeExplorer will invalidate that variable (by moving it into the * augmented iterator returned from such builder call). * - * # usage + * # Usage * * This function starts a *Builder* expression. It picks up the given source, * which can be something "sequence-like" or "iterable", and will automatically diff --git a/src/steam/engine/dispatcher.hpp b/src/steam/engine/dispatcher.hpp index 1db71684f..b2083afba 100644 --- a/src/steam/engine/dispatcher.hpp +++ b/src/steam/engine/dispatcher.hpp @@ -43,7 +43,9 @@ #include "steam/engine/job-ticket.hpp" #include "steam/engine/job-planning.hpp" #include "steam/play/output-slot.hpp" +#include "lib/iter-tree-explorer.hpp" #include "lib/time/timevalue.hpp" +//#include "lib/nocopy.hpp" #include @@ -82,7 +84,7 @@ namespace engine { * which, for the purpose of dispatching a series of jobs just looks * like a sequence of job descriptors * - * @todo 10/12 still WIP, but conceptually settled by now + * @todo 6/23 API is remoulded from ground up (»Playback Vertical Slice« integration effort) */ class Dispatcher : public FrameLocator @@ -106,13 +108,28 @@ namespace engine { }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1301 : obsolete + using FrameNrIter = lib::NumIter; + struct PipelineBuilder - : lib::SingleValIter ////////////////////////////////////////OOO placeholder type; should rather be a TreeExplorer! + : FrameNrIter { - PipelineBuilder& + Dispatcher* dispatcher; + Timings timings; + ModelPort port; + DataSink sink; + + auto timeRange (Time start, Time after) { - UNIMPLEMENTED ("setup dispatch time range"); + auto frame = [&](Time t){ return timings.getBreakPointAfter(t); }; + auto reset = [&](auto i){ static_cast(*this) = i; }; + + reset (lib::eachNum (frame(start), frame(after))); + return lib::treeExplore (move(*this)) + .transform ([&](FrameCnt frameNr) -> TimeVar //////////////////////////////TICKET #1261 : transform-iterator unable to handle immutable time + { + return timings.getFrameStartAt (frameNr); + }); } }; @@ -126,7 +143,7 @@ namespace engine { PipelineBuilder forCalcStream(Timings timings, ModelPort port, DataSink sink) { - UNIMPLEMENTED ("create Pipeline builder"); + return PipelineBuilder{FrameNrIter(), this, timings, port, sink}; } diff --git a/tests/core/steam/engine/timings-test.cpp b/tests/core/steam/engine/timings-test.cpp index fa65f565f..549ccbeaf 100644 --- a/tests/core/steam/engine/timings-test.cpp +++ b/tests/core/steam/engine/timings-test.cpp @@ -30,40 +30,33 @@ #include "lib/test/run.hpp" #include "lib/test/test-helper.hpp" -//#include "steam/engine/procnode.hpp" -#include "steam/play/dummy-play-connection.hpp" -#include "steam/mobject/model-port.hpp" -#include "steam/engine/dispatcher.hpp" #include "steam/play/timings.hpp" #include "lib/time/timevalue.hpp" //#include "lib/time/timequant.hpp" //#include "lib/format-cout.hpp" -#include "lib/depend.hpp" -#include "lib/itertools.hpp" -#include "lib/util-coll.hpp" +//#include "lib/util-coll.hpp" #include "lib/util.hpp" -#include -#include +//#include +//#include using test::Test; using util::isnil; -using util::last; -using std::vector; -using std::function; -//using std::rand; +//using std::vector; +//using std::function; +using std::rand; namespace steam { namespace engine{ namespace test { + using lib::time::FSecs; + using lib::time::FrameCnt; using lib::time::FrameRate; using lib::time::Duration; using lib::time::Offset; - using lib::time::TimeValue; using lib::time::Time; - using mobject::ModelPort; using play::Timings; namespace { // Test fixture... @@ -75,17 +68,6 @@ namespace test { const uint DUMMY_CHANNEL(0); /////////////////////////////////////////////////////////////TICKET #1297 : get rid of the channels (use different ModelPort) -// ModelPort -// getTestPort() -// { -// using play::test::ModelPorts; -// using play::test::PlayTestFrames_Strategy; -// using DummyPlaybackSetup = play::test::DummyPlayConnection; -// -// DummyPlaybackSetup dummySetup; -// ModelPorts mockModelPorts = dummySetup.provide_testModelPorts(); -// return *mockModelPorts; // using just the first dummy port -// } FSecs diff --git a/tests/core/steam/play/dummy-builder-context.hpp b/tests/core/steam/play/dummy-builder-context.hpp new file mode 100644 index 000000000..95d7c97d9 --- /dev/null +++ b/tests/core/steam/play/dummy-builder-context.hpp @@ -0,0 +1,265 @@ +/* + DUMMY-BUILDER-CONTEXT.hpp - fake simulated builder result for player tests + + Copyright (C) Lumiera.org + 2011, Hermann Vosseler + + This program 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. + + This program 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 more 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/** @file dummy-builder-context.hpp + ** Simulated result of a builder run for test purposes, without actual session and model content. + ** Integration tests for the render engine or the player have to deal with a lot of prerequisites, + ** since both an external environment and actual content form the Session is required to start any + ** processing. Effectively the complete core application is required — while in fact the engine is + ** built in an abstracted way and does not need to know much about the rest of the application. + ** Thus, as a remedy, it is possible to establish a _faked context,_ exposing just those interfaces + ** used by the engine for processing. As additional benefit, dedicated test operations can be rigged + ** and verification routines can be used in place of actual media output. + ** + ** This faked builder context provides a selection of consistent media element IDs with sensible + ** properties and type markers, plus the attachment points for a simulated model structure, as + ** if generated from an actual session model by a real Builder run. + ** - a set of ModelPort elements + ** - a set of DataSink handles, as if an actual playback connection has been established + ** @todo 5/2023 add more elements as needed for test driven integration of Player and engine + ** @todo this was invented in 2012 -- but development of the player subsystem stalled thereafter. + ** + ** @see mock-dispatcher.hpp + ** @see JobPlanningSetup_test + */ + + +#ifndef STEAM_PLAY_DUMMY_BUILDER_CONTEXT_H +#define STEAM_PLAY_DUMMY_BUILDER_CONTEXT_H + + +#include "steam/mobject/model-port.hpp" +#include "steam/mobject/builder/model-port-registry.hpp" +#include "steam/play/output-slot-connection.hpp" +#include "steam/play/output-manager.hpp" +#include "steam/asset/timeline.hpp" +#include "steam/asset/pipe.hpp" +#include "common/query.hpp" + +#include "lib/iter-source.hpp" +#include "lib/nocopy.hpp" +#include "lib/util.hpp" + +#include + + +namespace steam{ +namespace play { +namespace test { + + + /** + * @todo 5/2023 quick-n-dirty placeholder to be able to fabricate fake DataSink handles (`Handle`) + */ + class UnimplementedConnection + : public play::OutputSlot::Connection + { + BuffHandle claimBufferFor(FrameID) override { UNIMPLEMENTED ("claimBufferFor(FrameID)"); } + bool isTimely (FrameID, TimeValue) override { return true; } + void transfer (BuffHandle const&) override { UNIMPLEMENTED ("transfer (BuffHandle const&)"); } + void pushout (BuffHandle const&) override { UNIMPLEMENTED ("pushout (BuffHandle const&)"); } + void discard (BuffHandle const&) override { UNIMPLEMENTED ("discard (BuffHandle const&)"); } + void shutDown () override { UNIMPLEMENTED ("shutDown() Connection"); } + + public: + ~UnimplementedConnection(); + UnimplementedConnection() = default; + }; + + + using asset::Pipe; + using asset::PPipe; + using asset::Struct; + using asset::Timeline; + using asset::PTimeline; + using mobject::ModelPort; + using mobject::builder::ModelPortRegistry; + using util::contains; + using lumiera::Query; + + + using PID = asset::ID; + using TID = asset::ID; + + using ModelPorts = lib::IterSource::iterator; + using DummyOutputLink = std::pair; + + + inline PID + getPipe (string id) + { + return Pipe::query ("id("+id+")"); + } + + inline TID + getTimeline (string id) + { + return asset::Struct::retrieve (Query ("id("+id+")"))->getID(); + } + + const uint NUMBER_OF_PORTS = 2; + const string namePortA("bus-A"); + const string namePortB("bus-B"); + + /** + * helper for dummy render engine: + * Simulate the result of a build process, + * without actually running the builder. + * Produces some mock pipes, model ports etc. + */ + struct SimulatedBuilderContext + { + ModelPortRegistry registry_; + ModelPortRegistry* existingRegistry_; + + std::vector modelPorts_; + std::vector dataSinks_; + + /** setup */ + SimulatedBuilderContext() + : registry_() + , existingRegistry_(ModelPortRegistry::setActiveInstance (registry_)) + { + performMockBuild(); + } + + /** tear-down */ + ~SimulatedBuilderContext() + { + if (existingRegistry_) + ModelPortRegistry::setActiveInstance (*existingRegistry_); + else + ModelPortRegistry::shutdown(); + } + + void + performMockBuild() + { + PID pipeA = getPipe (namePortA); + PID pipeB = getPipe (namePortB); + TID someTimeline = getTimeline ("dummy_Timeline"); + + // start out with defining some new model ports...... + registry_.definePort (pipeA, someTimeline); + registry_.definePort (pipeB, someTimeline); + + registry_.commit(); + + // now "bus-A" and "bus-B" are known as model ports + modelPorts_.push_back (ModelPort(pipeA)); + modelPorts_.push_back (ModelPort(pipeB)); + + // prepare corresponding placeholder DataSink (a fake active output connection) + dataSinks_.emplace_back().activate(std::make_shared()); + dataSinks_.emplace_back().activate(std::make_shared()); + } + + + ModelPorts + getAllModelPorts() + { + return lib::iter_source::eachEntry (modelPorts_.begin(), modelPorts_.end()); + } + + DummyOutputLink + getModelPort (uint index) + { + REQUIRE (index < modelPorts_.size()); + return {modelPorts_[index] + ,dataSinks_[index] + }; + } + }; + +#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1301 + /****************************************************************//** + * Framework for dummy playback and rendering. + * A DummyPlayConnection provides a coherent set of placeholders, + * allowing to start a data producing process while leaving out + * various parts of the real engine implementation. The specific + * mode of operation, suitable for various test scenarios, may be + * fine tuned by the strategy object defined as template parameter. + * + * @todo not-yet-implemented as of 2016 -- but the design can be considered valid. + */ + template + class DummyPlayConnection + : util::NonCopyable + { + SimulatedBuilderContext mockBuilder_; + + public: + + ModelPorts + getAllModelPorts() + { + return mockBuilder_.getAllModelPorts(); + } + + DummyOutputLink + getModelPort (uint index) + { + return mockBuilder_.getModelPort (index); + } + + POutputManager + provide_testOutputSlot() + { + UNIMPLEMENTED ("provide a suitable output sink simulation"); + } + + + /* === Test Support API === */ + + bool + isWired() + { + UNIMPLEMENTED ("is this dummy in activated state?"); + } + + Duration + getPlannedTestDuration() + { + UNIMPLEMENTED ("manage the a planned test duration"); + } + + /** test helper: blocking wait during an output test. + * The waiting time should be in accordance with the + * \link #getPlannedTestduration planned value \endlink, + */ + void + waitUntilDue() + { + UNIMPLEMENTED ("do a blocking wait, while an output test is performed in other threads"); + } + + bool + gotCorrectOutput() + { + UNIMPLEMENTED ("verify proper operation by inspecting the provided test dummy components"); + } + }; +#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1301 + + +}}} // namespace steam::play::test +#endif /*STEAM_PLAY_DUMMY_BUILDER_CONTEXT_H*/ diff --git a/tests/core/steam/play/dummy-play-connection-test.cpp b/tests/core/steam/play/dummy-play-connection-test.cpp index db21f7661..2d38150c4 100644 --- a/tests/core/steam/play/dummy-play-connection-test.cpp +++ b/tests/core/steam/play/dummy-play-connection-test.cpp @@ -28,8 +28,6 @@ #include "lib/test/run.hpp" #include "steam/play/dummy-play-connection.hpp" -//#include "steam/engine/buffhandle.hpp" -//#include "steam/engine/testframe.hpp" #include "include/play-facade.hpp" #include "lib/time/control.hpp" diff --git a/src/steam/play/dummy-play-connection.cpp b/tests/core/steam/play/dummy-play-connection.cpp similarity index 100% rename from src/steam/play/dummy-play-connection.cpp rename to tests/core/steam/play/dummy-play-connection.cpp diff --git a/src/steam/play/dummy-play-connection.hpp b/tests/core/steam/play/dummy-play-connection.hpp similarity index 93% rename from src/steam/play/dummy-play-connection.hpp rename to tests/core/steam/play/dummy-play-connection.hpp index 36f557197..7d0bbcae0 100644 --- a/src/steam/play/dummy-play-connection.hpp +++ b/tests/core/steam/play/dummy-play-connection.hpp @@ -78,19 +78,9 @@ #define STEAM_PLAY_DUMMY_PLAY_CONNECTION_H -//#include "include/dummy-player-facade.h" -//#include "include/display-facade.h" -//#include "common/instancehandle.hpp" -//#include "lib/singleton-ref.hpp" -#include "steam/play/output-slot-connection.hpp" +#include "steam/play/dummy-builder-context.hpp" #include "steam/play/output-manager.hpp" -#include "steam/mobject/model-port.hpp" #include "lib/time/timequant.hpp" -//#include "lib/scoped-collection.hpp" -#include "steam/mobject/builder/model-port-registry.hpp" -#include "steam/asset/timeline.hpp" -#include "steam/asset/pipe.hpp" -#include "common/query.hpp" #include "lib/iter-source.hpp" #include "lib/nocopy.hpp" @@ -104,18 +94,12 @@ namespace play { namespace test { // using std::string; -// using lumiera::Subsys; -// using lumiera::Display; -// using lumiera::DummyPlayer; using lib::time::Duration; - using ModelPorts = lib::IterSource::iterator; - using DummyOutputLink = std::pair; - - /** + /* * @todo 5/2023 quick-n-dirty placeholder to be able to fabricate fake DataSink handles (`Handle`) - */ + * / class UnimplementedConnection : public play::OutputSlot::Connection { @@ -130,7 +114,7 @@ namespace test { ~UnimplementedConnection(); UnimplementedConnection() = default; }; - +*/ @@ -139,7 +123,7 @@ namespace test { }; - +/* namespace { // simulated builder environment using asset::Pipe; @@ -176,12 +160,12 @@ namespace test { const string namePortA("bus-A"); const string namePortB("bus-B"); - /** + / ** * helper for dummy render engine: * Simulate the result of a build process, * without actually running the builder. * Produces some mock pipes, model ports etc. - */ + * / struct SimulatedBuilderContext { ModelPortRegistry registry_; @@ -190,7 +174,6 @@ namespace test { std::vector modelPorts_; std::vector dataSinks_; - /** setup */ SimulatedBuilderContext() : registry_() , existingRegistry_(ModelPortRegistry::setActiveInstance (registry_)) @@ -198,7 +181,6 @@ namespace test { performMockBuild(); } - /** tear-down */ ~SimulatedBuilderContext() { if (existingRegistry_) @@ -246,7 +228,7 @@ namespace test { } }; } - +*/ /****************************************************************//** * Framework for dummy playback and rendering. diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 993d97633..9d29b5c18 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -73527,12 +73527,73 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + - - + + + + + + +

+ siehe iter-chain-search.hpp +

+ +
+ + + + + + +

+ ...man packt den eigentlichen TreeExplorer-Builder-Aufruf in eine Hilfsunktion und greift den decltype vom Rückgabewert ab; von diesem Typ kann man dann erben (und verwendet die erwähnte Hilfsfunktion im Konstruktor, um den Parent-Typ zu initialisieren)i +

+ +
+
+
+ + + + + + + + + + + + + + + + +

+ In diesem Zusammenhang ist type inference praktisch unvermeidbar, denn die komplexen Typen vom TreeExplorer können anders nicht explizit gemacht werden — aber das Problem ist, die Typen sind rekursiv, denn den neuen, erweiterten Builder-Typ muß ich schon kennen, um ihn in dem TreeEplorer-Builder als Core zu übergeben, aber erst durch diesen Aufruf wird dieser neue erweiterte Builder überhaupt definiert +

+ +
+
+ + + + + + +

+ ...also zunächst einen deaktivierten NumIter als Basisklasse, und an diesen später einen aktivierten NumIter zuweisen...  ziemlich häßlich, aber damit bekomme ich es überhaupt erst mal durch den Compiler... +

+ +
+ +
+
+ + +