diff --git a/src/include/play-facade.h b/src/include/play-facade.h index 852fe5b78..c1739bac6 100644 --- a/src/include/play-facade.h +++ b/src/include/play-facade.h @@ -112,6 +112,8 @@ namespace lumiera { double getSpeed() const; uint getQuality() const; bool usesProxy() const; + + operator std::tr1::weak_ptr(); }; diff --git a/src/proc/play/output-manager.hpp b/src/proc/play/output-manager.hpp index a6fd3b91a..165c1af2f 100644 --- a/src/proc/play/output-manager.hpp +++ b/src/proc/play/output-manager.hpp @@ -33,6 +33,7 @@ #include "lib/error.hpp" #include "proc/play/output-slot.hpp" +#include "proc/mobject/model-port.hpp" #include //#include @@ -48,6 +49,10 @@ namespace play { using std::tr1::shared_ptr; + LUMIERA_ERROR_DECLARE(CANT_PLAY); ///< unable to build playback or render process for this configuration + + + @@ -62,7 +67,10 @@ namespace play { : boost::noncopyable { public: - OutputManager() {} + virtual ~OutputManager() { } + + + virtual OutputSlot& getOutputFor (mobject::ModelPort port) =0; }; typedef shared_ptr POutputManager; diff --git a/src/proc/play/play-process.hpp b/src/proc/play/play-process.hpp index 5045544b7..aebd971dd 100644 --- a/src/proc/play/play-process.hpp +++ b/src/proc/play/play-process.hpp @@ -56,6 +56,8 @@ //#include "include/display-facade.h" //#include "common/instancehandle.hpp" //#include "lib/singleton-ref.hpp" +#include "proc/play/output-manager.hpp" +#include "lib/util.hpp" // #include //#include @@ -69,6 +71,7 @@ namespace play { // using lumiera::Subsys; // using lumiera::Display; // using lumiera::DummyPlayer; + using util::isnil; namespace error = lumiera::error; @@ -110,7 +113,8 @@ namespace play { PlayProcess (CONS pipeConnections) { if (isnil (pipeConnections)) - throw error::State ("creating a PlayProcess without any usable output connections"); + throw error::State ("creating a PlayProcess without any usable output connections" + , LUMIERA_ERROR_CANT_PLAY); UNIMPLEMENTED ("iterate over the connections and allocate/establish each of them, creating and storing Feed objects"); } diff --git a/src/proc/play/play-service.cpp b/src/proc/play/play-service.cpp index 72e89fa35..802823631 100644 --- a/src/proc/play/play-service.cpp +++ b/src/proc/play/play-service.cpp @@ -24,6 +24,7 @@ #include "proc/play/play-service.hpp" #include "proc/play/play-process.hpp" #include "lib/itertools.hpp" +#include "lib/util.hpp" #include @@ -54,10 +55,15 @@ namespace play { //using std::tr1::bind; using lib::Sync; using lib::RecursiveLock_NoWait; - using lib::filterIterator; + using lib::transformIterator; using std::tr1::weak_ptr; using std::tr1::bind; + using std::tr1::function; using std::tr1::placeholders::_1; + using util::remove_if; + using mobject::ModelPort; + + typedef proc::play::POutputManager POutputManager; namespace { // hidden local details of the service implementation.... @@ -74,7 +80,8 @@ namespace play { class ProcessTable : public Sync { - typedef std::vector > ProcTable; + typedef weak_ptr Entry; + typedef std::vector ProcTable; ProcTable processes_; @@ -85,6 +92,7 @@ namespace play { { lumiera::Play::Controller frontend; + Lock sync(this); frontend.activate (newProcess, bind (&ProcessTable::endProcess, this, _1 )); processes_.push_back (frontend); return frontend; @@ -95,7 +103,15 @@ namespace play { endProcess (PlayProcess* dyingProcess) { delete dyingProcess; - UNIMPLEMENTED ("process deregistration"); /// note the process might not be registered at all + + Lock sync(this); + remove_if (processes_, isDead); + } + + static bool + isDead (Entry const& e) + { + return e.expired(); } }; @@ -112,13 +128,39 @@ namespace play { * rendered data for output. Client code is assumed to access * this service through the lumiera::Play facade. */ - PlayService::PlayService() /////TODO Subsys::SigTerm terminationHandle); + PlayService::PlayService() : facadeAccess_(*this, "Player") , pTable_(new ProcessTable) { } + namespace { // details... + + OutputSlot& + resolveOutputConnection (ModelPort port, POutputManager outputResolver) + { + REQUIRE (outputResolver); + OutputSlot& slot = outputResolver->getOutputFor (port); + if (!slot.isFree()) + throw error::State("unable to acquire a suitable output slot" /////////////////////TICKET #197 #816 + , LUMIERA_ERROR_CANT_PLAY); + } + + /** try to establish an output slot for the given + * global bus or data production exit point. + * @param outputResolver a facility able to resolve to + * a concrete output slot within the actual context + * @throw error::State when resolution fails + */ + function + resolve (POutputManager outputResolver) + { + return bind (resolveOutputConnection, _1, outputResolver); + } + } + + /** * @note this is the core operation of the play and render service * @@ -133,12 +175,15 @@ namespace play { Play::Controller PlayService::connect(ModelPorts dataGenerators, Output outputDestinations) { - UNIMPLEMENTED ("build a PlayProcess"); - pTable_->establishProcess( - new PlayProcess (filterIterator (dataGenerators, - resolve(outputDestinations)))); + return pTable_->establishProcess( + new PlayProcess (transformIterator (dataGenerators, + resolve(outputDestinations)))); } + + + LUMIERA_ERROR_DEFINE (CANT_PLAY, "unable to build playback or render process for this configuration"); + }} // namespace proc::play diff --git a/src/proc/play/play-service.hpp b/src/proc/play/play-service.hpp index b0b39e4a1..9d70e23b6 100644 --- a/src/proc/play/play-service.hpp +++ b/src/proc/play/play-service.hpp @@ -58,6 +58,7 @@ namespace play { + /****************************************************** * Implementation access point: Player subsystem. * The PlayService is the primary way for clients to