lumiera_/src/proc/play/output-director.cpp
Ichthyostega 4e0d99e928 Demote the Play-Facade to a in-language (C++) Interface to get rid of InterfaceFacadeLink
I am fully aware this change has some far reaching ramifications.
Effectively I am hereby abandoning the goal of a highly modularised Lumiera,
where every major component is mapped over the Interface-System. This was
always a goal I accepted only reluctantly, and my now years of experience
confirm my reservation: it will cost us lots of efforts just for the
sake of being "sexy".
2018-04-03 02:14:45 +02:00

154 lines
4.6 KiB
C++

/*
OutputDirector - handling all the real external output connections
Copyright (C) Lumiera.org
2011, Hermann Vosseler <Ichthyostega@web.de>
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 output-director.cpp
** Implementation of global output connection management
*/
#include "proc/play/play-service.hpp"
#include "proc/play/output-manager.hpp"
#include "proc/play/output-director.hpp"
#include "backend/thread-wrapper.hpp"
using backend::Thread;
namespace proc {
namespace play {
namespace { // hidden local details of the service implementation....
} // (End) hidden service impl details
/** storage for the single application wide OutputDirector instance */
lib::Depend<OutputDirector> OutputDirector::instance;
/** bring up the framework for handling input/output connections.
* Creating this object happens on first access and shouldn't be
* confused with actually booting up / shutting down this subsystem.
* Rather, the purpose of the OutputDirector is actively to conduct
* the Lifecycle of booting, connecting, operating, disconnecting.
*/
OutputDirector::OutputDirector()
{ }
OutputDirector::~OutputDirector() { }
/** connect and bring up the external input/output connections,
* handlers and interface services and the render/playback service.
* @return true if the output subsystem can be considered operational
*/
bool
OutputDirector::connectUp()
{
Lock sync(this);
REQUIRE (not shutdown_initiated_);
player_.createInstance();
return this->isOperational();
}
/** @todo WIP-WIP-WIP 6/2011 */
bool
OutputDirector::isOperational() const
{
return bool(player_); ////////////TODO more to check here....
}
/** initiate shutdown of all ongoing render/playback processes
* and closing of all external input/output interfaces.
* Works as an asynchronous operation; the given callback signal
* will be invoked when the shutdown is complete.
* @note starting a new thread, which might fail.
* When this happens, the raised exception will cause
* immediate unconditional termination of the application.
*/
void
OutputDirector::triggerDisconnect (SigTerm completedSignal) noexcept
{
if (not shutdown_initiated_)
{
shutdown_initiated_ = true;
Thread ("Output shutdown supervisor",
[=]{
bringDown (completedSignal);
});
}
}
/** @internal actually bring down any calculation processes
* and finally disconnect any external input/output interfaces.
* This shutdown and cleanup operation is executed in a separate
* "Output shutdown supervisor" thread and has the liability to
* bring down the relevant facilities within a certain timespan.
* When done, the last operation within this thread will be to
* invoke the callback signal given as parameter.
* @note locks the OutputDirector
*/
void
OutputDirector::bringDown (SigTerm completedSignal)
{
Lock sync(this);
string problemLog;
if (not isOperational())
{
WARN (play, "Attempt to OutputDirector::bringDown() -- "
"which it is not in running state. Invocation ignored. "
"This indicates an error in Lifecycle logic.");
return;
}
try
{
TODO ("actually bring down the output generation");
player_.shutdown();
completedSignal(0);
}
catch (lumiera::Error& problem)
{
problemLog = problem.what();
lumiera_error(); // reset error state
completedSignal (&problemLog);
}
catch (...)
{
problemLog = "Unknown error while disconnecting output. "
"Lumiera error flag is = "+string(lumiera_error());
completedSignal (&problemLog);
}
}
}} // namespace proc::play