There was an old UML diagram created at the time of the first draft. It is integrated into the »OutputSlot« page in TiddlyWiki. This description and the diagram are highly relevant for understanding the design in this case. Unfortunately, Umbrello was "improved" with a lot of features since I used it for the last time, but the **quality** of the software has been **degraded**, it is now buggy and the layout is imprecise and gets messed up easily.
165 lines
5.6 KiB
C++
165 lines
5.6 KiB
C++
/*
|
||
RenderConfigurator - strategy to help building an actual render calculation stream
|
||
|
||
Copyright (C)
|
||
2011, Hermann Vosseler <Ichthyostega@web.de>
|
||
|
||
**Lumiera** 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. See the file COPYING for further details.
|
||
|
||
* *****************************************************************/
|
||
|
||
|
||
/** @file render-configurator.cpp
|
||
** Implementation functionality to bridge between engine::PlayService and engine::EngineService.
|
||
** The former allows to start playback (or rendering) as a high-level activity, while the latter
|
||
** can manage and perform [calculation streams](\ref CalcStream)
|
||
**
|
||
** @todo 2026 : the concept seems valid, but needs to be refined and integrated with play processing ///////TICKET #868
|
||
*/
|
||
|
||
|
||
#include "lib/error.hpp"
|
||
#include "steam/play/render-configurator.hpp"
|
||
#include "steam/play/output-manager.hpp"
|
||
#include "steam/engine/engine-service.hpp"
|
||
//#include "lib/itertools.hpp"
|
||
|
||
//#include <string>
|
||
//#include <memory>
|
||
#include <memory>
|
||
#include <functional>
|
||
|
||
|
||
|
||
namespace steam {
|
||
namespace play {
|
||
|
||
namespace error = lumiera::error;
|
||
// using std::string;
|
||
using std::shared_ptr;
|
||
using std::bind;
|
||
using std::placeholders::_1;
|
||
using engine::EngineService;
|
||
|
||
typedef EngineService::QoS_Definition RenderQuality;
|
||
|
||
|
||
namespace { // Implementation details...
|
||
|
||
// using std::bind;
|
||
// using std::function;
|
||
// using std::placeholders::_1;
|
||
// using lib::transform;
|
||
|
||
class LumieraRenderProcessBuilder
|
||
: public RenderConfigurator
|
||
{
|
||
|
||
POutputManager outputResolver_;
|
||
Timings playbackTimings_;
|
||
RenderQuality renderQuality_;
|
||
|
||
|
||
OutputSlot&
|
||
getOutputFor (ModelPort port)
|
||
{
|
||
REQUIRE (outputResolver_);
|
||
OutputSlot& slot = outputResolver_->getOutputFor (port);
|
||
if (!slot.isFree())
|
||
throw error::State{"unable to acquire a suitable output slot" /////////////////////TICKET #197 #816 --- could use util::_Fmt here
|
||
, LERR_(CANT_PLAY)};
|
||
return slot;
|
||
}
|
||
|
||
|
||
engine::CalcStreams
|
||
buildCalculationStreams (ModelPort port, OutputSlot& output)
|
||
{
|
||
OutputSlot::Allocation& activeOutputConnection = output.allocate();
|
||
Timings nominalTimings = activeOutputConnection.timingConstraints()
|
||
.constrainedBy(playbackTimings_);
|
||
|
||
return activateEngine (port, nominalTimings, activeOutputConnection, renderQuality_);
|
||
}
|
||
|
||
|
||
engine::CalcStreams
|
||
activateEngine (ModelPort port, Timings timings, OutputSlot::Allocation& activeOutputConnection, RenderQuality quality)
|
||
{
|
||
return EngineService::instance().calculate (port, timings, activeOutputConnection, quality);
|
||
}
|
||
|
||
|
||
public:
|
||
LumieraRenderProcessBuilder (POutputManager outputManager, Timings playbackSpeed)
|
||
: outputResolver_(outputManager)
|
||
, playbackTimings_(playbackSpeed)
|
||
, renderQuality_(EngineService::QoS_DEFAULT)
|
||
{ }
|
||
|
||
};
|
||
|
||
|
||
|
||
/** @internal decision point about how to configure the rendering.
|
||
* This would be the point for possibly switching the concrete render engine used. */
|
||
inline RenderConfigurator*
|
||
how_to_render (POutputManager outputPossibilities, Timings playTimings)
|
||
{
|
||
return new LumieraRenderProcessBuilder (outputPossibilities, playTimings);
|
||
}
|
||
|
||
|
||
} // (End) hidden service impl details
|
||
|
||
|
||
|
||
|
||
RenderConfigurator::~RenderConfigurator() { } // emit VTable here...
|
||
|
||
|
||
/** Template Method: how to build an active render feed,
|
||
* pulling from the given exit point of the model and
|
||
* feeding the OutputSlot established appropriately
|
||
* to deliver media data of suitable type */
|
||
Feed
|
||
RenderConfigurator::buildActiveFeed (ModelPort port)
|
||
{
|
||
OutputSlot& slot = getOutputFor (port);
|
||
return Feed (buildCalculationStreams (port,slot));
|
||
}
|
||
|
||
|
||
|
||
|
||
/** @internal this builder function is used by the PlayService
|
||
* when it comes to creating a new PlayProcess. The generated ConnectFunction
|
||
* treats a single ModelPort to produce a suitable rendering setup, pulling data
|
||
* from this port; it thus embodies the specific knowledge how to configure and
|
||
* setup the rendering or playback at the EngineFacade, based on the playback
|
||
* speed and quality desirable for this playback process to be initiated.
|
||
* @remarks building a special subclass here and managing this instance
|
||
* by smart-ptr. Then wrapping all of this up into a functor,
|
||
* which can thus be passed on by value. This functor will
|
||
* later on be used to transform each desired model port
|
||
* into a suitable output connection, where the actual
|
||
* output will be resolved through the given
|
||
* OutputManager
|
||
*/
|
||
RenderConfigurator::ConnectFunction
|
||
buildRenderConfiguration (POutputManager outputPossibilities, Timings playTimings)
|
||
{
|
||
shared_ptr<RenderConfigurator> specialConfig{how_to_render (outputPossibilities,playTimings)};
|
||
|
||
return [specialConfig](ModelPort port)
|
||
{
|
||
return specialConfig->buildActiveFeed(port);
|
||
};
|
||
}
|
||
|
||
|
||
|
||
}} // namespace steam::play
|