2011-05-23 04:43:56 +02:00
/*
2011-05-23 05:46:40 +02:00
PlayService - interface : render - and playback control
2011-05-23 04:43:56 +02:00
Copyright ( C ) Lumiera . org
2011-05-23 05:46:40 +02:00
2011 , Hermann Vosseler < Ichthyostega @ web . de >
2011-05-23 04:43:56 +02:00
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 0213 9 , USA .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-12-10 03:18:48 +01:00
# include "lib/error.hpp"
# include "include/play-facade.h"
2011-05-23 05:46:40 +02:00
# include "proc/play/play-service.hpp"
2011-06-15 03:51:06 +02:00
# include "proc/play/play-process.hpp"
2011-12-17 04:45:42 +01:00
# include "proc/play/render-configurator.hpp"
2011-12-17 22:37:53 +01:00
# include "proc/play/output-manager.hpp"
2011-12-17 02:20:48 +01:00
# include "lib/util-foreach.hpp"
2011-05-23 04:43:56 +02:00
# include <string>
2011-05-23 05:46:40 +02:00
//#include <memory>
2011-12-17 22:37:53 +01:00
////#include <tr1/functional>
2011-06-23 17:54:28 +02:00
# include <tr1/memory>
2011-05-23 05:46:40 +02:00
//#include <boost/scoped_ptr.hpp>
2011-05-23 04:43:56 +02:00
2011-06-13 20:07:30 +02:00
namespace lumiera {
Play : : ~ Play ( ) { } // emit VTables here...
2012-01-27 00:14:21 +01:00
/** Storage for the lumiera::Play facade access point
* @ note PlayService uses a InterfaceFacadeLink member
* for actually establishing the PlayService instance
* as implementation of lumiera : : Play
*/
facade : : Accessor < Play > Play : : facade ;
2011-06-13 20:07:30 +02:00
} //(End) namespace lumiera
2011-05-28 01:46:06 +02:00
namespace proc {
namespace play {
//using std::string;
//using lumiera::Subsys;
//using std::auto_ptr;
//using boost::scoped_ptr;
//using std::tr1::bind;
2011-06-15 03:51:06 +02:00
using lib : : Sync ;
using lib : : RecursiveLock_NoWait ;
2011-06-23 17:54:28 +02:00
using std : : tr1 : : weak_ptr ;
using std : : tr1 : : bind ;
2011-06-25 17:44:28 +02:00
//using std::tr1::function;
2011-06-23 17:54:28 +02:00
using std : : tr1 : : placeholders : : _1 ;
2011-06-24 18:40:19 +02:00
using util : : remove_if ;
2011-12-17 02:20:48 +01:00
using util : : and_all ;
2011-12-17 04:45:42 +01:00
2011-05-28 01:46:06 +02:00
namespace { // hidden local details of the service implementation....
2011-05-23 04:43:56 +02:00
2011-05-28 01:46:06 +02:00
} // (End) hidden service impl details
2011-12-17 04:45:42 +01:00
using lumiera : : Play ;
typedef POutputManager Output ;
2011-05-23 04:43:56 +02:00
2011-06-15 03:51:06 +02:00
class ProcessTable
: public Sync < RecursiveLock_NoWait >
{
2011-06-24 18:40:19 +02:00
typedef weak_ptr < PlayProcess > Entry ;
typedef std : : vector < Entry > ProcTable ;
2011-06-15 03:51:06 +02:00
2011-12-17 02:20:48 +01:00
/** @note holding just weak references
* to any ongoing playback processes */
2011-06-15 03:51:06 +02:00
ProcTable processes_ ;
public :
2011-12-17 04:45:42 +01:00
Play : : Controller
2011-06-23 17:54:28 +02:00
establishProcess ( PlayProcess * newProcess )
{
2011-12-17 04:45:42 +01:00
Play : : Controller frontend ;
2011-12-17 02:20:48 +01:00
try {
frontend . activate ( newProcess , bind ( & ProcessTable : : endProcess , this , _1 ) ) ;
}
catch ( . . . )
{
delete newProcess ;
throw ;
}
2011-06-23 17:54:28 +02:00
2011-06-24 18:40:19 +02:00
Lock sync ( this ) ;
2011-12-17 02:20:48 +01:00
processes_ . push_back ( frontend ) ; // keeping a weak-reference
2011-06-23 17:54:28 +02:00
return frontend ;
}
2011-12-17 04:45:42 +01:00
2011-12-17 02:20:48 +01:00
bool
isActive ( ) const
{
return ! and_all ( processes_ , isDead ) ;
}
2011-06-23 17:54:28 +02:00
private :
void
endProcess ( PlayProcess * dyingProcess )
{
2011-12-10 03:18:48 +01:00
/////////////////////////////////////////////TICKET #867 : somehow ensure sane abort of all attached calculation efforts
2011-06-23 17:54:28 +02:00
delete dyingProcess ;
2011-06-24 18:40:19 +02:00
Lock sync ( this ) ;
remove_if ( processes_ , isDead ) ;
}
static bool
isDead ( Entry const & e )
{
return e . expired ( ) ;
2011-06-23 17:54:28 +02:00
}
2011-06-15 03:51:06 +02:00
} ;
2011-12-17 04:45:42 +01:00
2011-06-13 20:07:30 +02:00
2011-12-10 03:18:48 +01:00
PlayService : : ~ PlayService ( )
{
2011-12-17 02:20:48 +01:00
if ( pTable_ - > isActive ( ) )
{
UNIMPLEMENTED ( " block waiting for any ongoing play processes. Ensure the process table is empty -- OR -- hand it over to some kind of cleanup service " ) ;
}
ENSURE ( ! pTable_ - > isActive ( ) ) ;
2011-12-10 03:18:48 +01:00
}
2011-06-15 03:51:06 +02:00
2011-06-13 20:07:30 +02:00
/** bring up the global render- and playback service.
* This service allows to create individual PlayProcess instances
* to \ em perform a timeline or similar model object , creating
* rendered data for output . Client code is assumed to access
2011-12-17 02:20:48 +01:00
* this service through the lumiera : : Play facade .
2011-06-13 20:07:30 +02:00
*/
2011-06-24 18:40:19 +02:00
PlayService : : PlayService ( )
2011-06-13 20:07:30 +02:00
: facadeAccess_ ( * this , " Player " )
2011-06-15 03:51:06 +02:00
, pTable_ ( new ProcessTable )
2011-06-13 20:07:30 +02:00
{ }
2011-05-23 04:43:56 +02:00
2011-05-28 01:46:06 +02:00
2011-06-24 18:40:19 +02:00
2011-06-13 20:07:30 +02:00
/**
* @ note this is the core operation of the play and render service
*
* Invoking this function investigates the given exit nodes of the
* render nodes network and retrieves actual output destinations
2012-02-05 00:25:22 +01:00
* through the given OutputManager . The goal is to configure a
2011-06-13 20:07:30 +02:00
* PlayProcess , based on the renderengine and the collection of
* OutputSlot instances retrieved for each of the given exit nodes .
* Running this PlayProcess will activate the render engine to deliver
2011-12-17 02:20:48 +01:00
* calculated media data to the outputs .
2011-06-13 20:07:30 +02:00
*/
Play : : Controller
2011-12-17 22:37:53 +01:00
PlayService : : connect ( ModelPorts dataGenerators , POutputManager outputPossibilities )
2011-06-13 20:07:30 +02:00
{
2012-02-06 02:49:54 +01:00
Timings playbackTimings ( lib : : time : : FrameRate : : PAL ) ; //////////////////////////////////////////////////////TICKET #875
2011-12-17 22:37:53 +01:00
2011-06-24 18:40:19 +02:00
return pTable_ - > establishProcess (
2011-12-17 04:45:42 +01:00
PlayProcess : : initiate ( dataGenerators ,
2011-12-17 22:37:53 +01:00
buildRenderConfiguration ( outputPossibilities , playbackTimings ) ) ) ;
2011-12-17 04:45:42 +01:00
}
/** */
2011-06-24 18:40:19 +02:00
2011-06-15 03:51:06 +02:00
2011-12-17 04:45:42 +01:00
2011-06-24 18:40:19 +02:00
LUMIERA_ERROR_DEFINE ( CANT_PLAY , " unable to build playback or render process for this configuration " ) ;
2011-05-28 01:46:06 +02:00
2011-05-23 05:46:40 +02:00
} } // namespace proc::play
2011-06-15 03:51:06 +02:00
namespace lumiera {
/* ==== convenience shortcuts for creating a PlayProcess ==== */
2013-06-03 05:25:13 +02:00
/**
* Generic point - of - Service for starting playback .
* Activating this service will " perform " the given exit points
* of the model , by " pulling " calculated data from these ports and
* feeding the results into suitable external outputs .
* @ return a state machine front - end to control the ongoing
* play / render process .
*/
Play : : Controller
Play : : perform ( ModelPorts ports , Output output )
{
return this - > connect ( ports , output ) ;
}
2011-06-15 03:51:06 +02:00
/**
*
*/
Play : : Controller
2013-06-03 05:25:13 +02:00
Play : : perform ( Pipes , Output )
2011-06-15 03:51:06 +02:00
{
UNIMPLEMENTED ( " build PlayProcess based on a set of pipes " ) ;
}
/**
*
*/
Play : : Controller
2013-06-03 05:25:13 +02:00
Play : : perform ( Timeline )
2011-06-15 03:51:06 +02:00
{
UNIMPLEMENTED ( " build PlayProcess for a Timeline " ) ;
}
/**
*
*/
Play : : Controller
2013-06-03 05:25:13 +02:00
Play : : perform ( Viewer )
2011-06-15 03:51:06 +02:00
{
2011-12-17 02:20:48 +01:00
UNIMPLEMENTED ( " build PlayProcess directly for a Viewer element " ) ;
2011-06-15 03:51:06 +02:00
}
/**
*
*/
Play : : Controller
2013-06-03 05:25:13 +02:00
Play : : perform ( Track )
2011-06-15 03:51:06 +02:00
{
UNIMPLEMENTED ( " build PlayProcess for a single Track " ) ;
}
/**
*
*/
Play : : Controller
2013-06-03 05:25:13 +02:00
Play : : perform ( Clip )
2011-06-15 03:51:06 +02:00
{
UNIMPLEMENTED ( " build virtual Timeline and PlayProcess to show a single Clip " ) ;
}
}