remold OutputSlot implementation structure
Better solution where to place the extension points to be implemented by concrete output systems
This commit is contained in:
parent
63dbc89b6f
commit
7ab7c8073d
4 changed files with 210 additions and 70 deletions
162
src/proc/play/output-slot-connection.hpp
Normal file
162
src/proc/play/output-slot-connection.hpp
Normal file
|
|
@ -0,0 +1,162 @@
|
||||||
|
/*
|
||||||
|
OUTPUT-SLOT-CONNECTION.hpp - implementation API for concrete output slots
|
||||||
|
|
||||||
|
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-slot-connection.hpp
|
||||||
|
** Interface for concrete output implementations to talk to the OutputSlot frontend.
|
||||||
|
** The OutputSlot concept helps to decouple the render engine implementation from the details
|
||||||
|
** of handling external output connections. For this to work, a concrete implementation of such
|
||||||
|
** an external output needs to integrate with the generic OutputSlot frontend, as used by the
|
||||||
|
** engine. This generic frontend uses a PImpl, pointing to a ConnectionState object, which embodies
|
||||||
|
** the actual implementation. Moreover, this actual implementation is free to use specifically crafted
|
||||||
|
** OutputSlot::Connection elements to handle the ongoing output for individual channels. The latter
|
||||||
|
** thus becomes the central implementation side API for providing actual output capabilities.
|
||||||
|
**
|
||||||
|
** @see OutputSlotProtocol_test
|
||||||
|
** @see diagnostic-output-slot.hpp ////TODO
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef PROC_PLAY_OUTPUT_SLOT_CONNECTION_H
|
||||||
|
#define PROC_PLAY_OUTPUT_SLOT_CONNECTION_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "lib/error.hpp"
|
||||||
|
#include "proc/play/output-slot.hpp"
|
||||||
|
#include "lib/handle.hpp"
|
||||||
|
//#include "lib/time/timevalue.hpp"
|
||||||
|
//#include "proc/engine/buffer-provider.hpp"
|
||||||
|
//#include "proc/play/timings.hpp"
|
||||||
|
#include "lib/iter-source.hpp"
|
||||||
|
#include "lib/iter-adapter-stl.hpp"
|
||||||
|
//#include "lib/sync.hpp"
|
||||||
|
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
#include <boost/scoped_ptr.hpp>
|
||||||
|
//#include <string>
|
||||||
|
//#include <vector>
|
||||||
|
//#include <tr1/memory>
|
||||||
|
|
||||||
|
|
||||||
|
namespace proc {
|
||||||
|
namespace play {
|
||||||
|
|
||||||
|
//using ::engine::BuffHandle;
|
||||||
|
//using ::engine::BufferProvider;
|
||||||
|
//using lib::time::Time;
|
||||||
|
//using std::string;
|
||||||
|
using lib::transform;
|
||||||
|
using lib::iter_stl::eachElm;
|
||||||
|
|
||||||
|
//using std::vector;
|
||||||
|
//using std::tr1::shared_ptr;
|
||||||
|
using boost::scoped_ptr;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** established output channel */
|
||||||
|
class OutputSlot::Connection
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~Connection();
|
||||||
|
|
||||||
|
virtual void lock (FrameID) =0;
|
||||||
|
virtual void transfer (FrameID) =0;
|
||||||
|
virtual void pushout (FrameID) =0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class OutputSlot::ConnectionState
|
||||||
|
: public OutputSlot::Allocation
|
||||||
|
, boost::noncopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~ConnectionState() { }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<class CON>
|
||||||
|
class ConnectionStateManager
|
||||||
|
: public OutputSlot::ConnectionState
|
||||||
|
, public vector<CON>
|
||||||
|
{
|
||||||
|
|
||||||
|
typedef OutputSlot::OpenedSinks OpenedSinks;
|
||||||
|
|
||||||
|
|
||||||
|
/* == Allocation Interface == */
|
||||||
|
|
||||||
|
OpenedSinks
|
||||||
|
getOpenedSinks()
|
||||||
|
{
|
||||||
|
REQUIRE (this->isActive());
|
||||||
|
return transform (eachElm(*this), connectOutputSink);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
isActive()
|
||||||
|
{
|
||||||
|
return 0 < vector<CON>::size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
ConnectionStateManager()
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED ("immediately build up the necessary number of connections");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual
|
||||||
|
~ConnectionStateManager()
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED ("shut down all connections");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual
|
||||||
|
CON
|
||||||
|
buildConnection() =0;
|
||||||
|
|
||||||
|
|
||||||
|
private: // Implementation details
|
||||||
|
|
||||||
|
DataSink
|
||||||
|
connectOutputSink (CON& connection)
|
||||||
|
{
|
||||||
|
DataSink newSink;
|
||||||
|
newSink.activate(&connection, shutdownConnection);
|
||||||
|
return newSink;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
shutdownConnection (CON* toClose)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED ("how to mark a connection as closed");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}} // namespace proc::play
|
||||||
|
#endif
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include "lib/error.hpp"
|
#include "lib/error.hpp"
|
||||||
#include "proc/play/output-slot.hpp"
|
#include "proc/play/output-slot.hpp"
|
||||||
|
#include "proc/play/output-slot-connection.hpp"
|
||||||
|
|
||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
@ -42,48 +43,8 @@ namespace play {
|
||||||
} // (End) hidden service impl details
|
} // (End) hidden service impl details
|
||||||
|
|
||||||
|
|
||||||
class Connection
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class ConnectionState
|
|
||||||
: public OutputSlot::Allocation
|
|
||||||
, public vector<Connection>
|
|
||||||
, boost::noncopyable
|
|
||||||
{
|
|
||||||
|
|
||||||
typedef OutputSlot::OpenedSinks OpenedSinks;
|
|
||||||
|
|
||||||
|
|
||||||
private: /* == Allocation Interface == */
|
|
||||||
OpenedSinks
|
|
||||||
getOpenedSinks()
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED ("yield all opened channels");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
isActive()
|
|
||||||
{
|
|
||||||
return 0 < size();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
ConnectionState()
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED ("immediately build up the necessary number of connections");
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual
|
|
||||||
~ConnectionState()
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED ("shut down all connections");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
OutputSlot::~OutputSlot() { } // emit VTables here....
|
OutputSlot::~OutputSlot() { } // emit VTables here....
|
||||||
|
|
@ -114,10 +75,19 @@ namespace play {
|
||||||
|
|
||||||
UNIMPLEMENTED ("internal interface to determine the number of channel-connections");
|
UNIMPLEMENTED ("internal interface to determine the number of channel-connections");
|
||||||
|
|
||||||
this->state_.reset(new ConnectionState());
|
state_.reset (this->buildState());
|
||||||
return *state_;
|
return *state_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
OutputSlot::disconnect()
|
||||||
|
{
|
||||||
|
if (!isFree())
|
||||||
|
state_.reset(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}} // namespace proc::play
|
}} // namespace proc::play
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@
|
||||||
|
|
||||||
#include "lib/error.hpp"
|
#include "lib/error.hpp"
|
||||||
#include "lib/handle.hpp"
|
#include "lib/handle.hpp"
|
||||||
#include "lib/time/timevalue.hpp"
|
//#include "lib/time/timevalue.hpp"
|
||||||
#include "proc/engine/buffer-provider.hpp"
|
#include "proc/engine/buffer-provider.hpp"
|
||||||
#include "proc/play/timings.hpp"
|
#include "proc/play/timings.hpp"
|
||||||
#include "lib/iter-source.hpp"
|
#include "lib/iter-source.hpp"
|
||||||
|
|
@ -56,7 +56,7 @@ namespace play {
|
||||||
|
|
||||||
using ::engine::BuffHandle;
|
using ::engine::BuffHandle;
|
||||||
using ::engine::BufferProvider;
|
using ::engine::BufferProvider;
|
||||||
using lib::time::Time;
|
//using lib::time::Time;
|
||||||
//using std::string;
|
//using std::string;
|
||||||
|
|
||||||
//using std::vector;
|
//using std::vector;
|
||||||
|
|
@ -64,25 +64,10 @@ namespace play {
|
||||||
using boost::scoped_ptr;
|
using boost::scoped_ptr;
|
||||||
|
|
||||||
|
|
||||||
/** established output channel */
|
|
||||||
class Connection;
|
|
||||||
|
|
||||||
/** Table to maintain connection state */
|
class DataSink;
|
||||||
class ConnectionState;
|
|
||||||
|
|
||||||
|
|
||||||
typedef int64_t FrameNr;
|
|
||||||
|
|
||||||
|
|
||||||
class DataSink
|
|
||||||
: public lib::Handle<Connection>
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
BuffHandle lockBufferFor(FrameNr);
|
|
||||||
void emit(FrameNr);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
typedef int64_t FrameID;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -94,8 +79,16 @@ namespace play {
|
||||||
class OutputSlot
|
class OutputSlot
|
||||||
: boost::noncopyable
|
: boost::noncopyable
|
||||||
{
|
{
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/** Table to maintain connection state */
|
||||||
|
class ConnectionState;
|
||||||
|
|
||||||
scoped_ptr<ConnectionState> state_;
|
scoped_ptr<ConnectionState> state_;
|
||||||
|
|
||||||
|
virtual ConnectionState* buildState() =0;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~OutputSlot();
|
virtual ~OutputSlot();
|
||||||
|
|
@ -113,17 +106,19 @@ namespace play {
|
||||||
~Allocation();
|
~Allocation();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** established output channel */
|
||||||
|
class Connection;
|
||||||
|
|
||||||
|
|
||||||
|
/** can this OutputSlot be allocated? */
|
||||||
bool isFree() const;
|
bool isFree() const;
|
||||||
|
|
||||||
|
/** claim this slot for exclusive use */
|
||||||
Allocation& allocate();
|
Allocation& allocate();
|
||||||
|
|
||||||
protected:
|
/** disconnect from this OutputSlot
|
||||||
friend class DataSink;
|
* @warning may block until DataSinks are gone */
|
||||||
|
void disconnect();
|
||||||
virtual void lock (FrameNr, uint channel) =0;
|
|
||||||
virtual void transfer (FrameNr, uint channel) =0;
|
|
||||||
virtual void pushout (FrameNr, uint channel) =0;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
@ -131,5 +126,18 @@ namespace play {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class DataSink
|
||||||
|
: public lib::Handle<OutputSlot::Connection>
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
BuffHandle lockBufferFor(FrameID);
|
||||||
|
void emit(FrameID);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}} // namespace proc::play
|
}} // namespace proc::play
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -105,28 +105,28 @@ namespace play {
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
buffer_was_used (uint channel, FrameNr frame)
|
buffer_was_used (uint channel, FrameID frame)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED ("determine if the denoted buffer was indeed used");
|
UNIMPLEMENTED ("determine if the denoted buffer was indeed used");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
buffer_unused (uint channel, FrameNr frame)
|
buffer_unused (uint channel, FrameID frame)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED ("determine if the specified buffer was never touched/locked for use");
|
UNIMPLEMENTED ("determine if the specified buffer was never touched/locked for use");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
buffer_was_closed (uint channel, FrameNr frame)
|
buffer_was_closed (uint channel, FrameID frame)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED ("determine if the specified buffer was indeed closed properly");
|
UNIMPLEMENTED ("determine if the specified buffer was indeed closed properly");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
emitted (uint channel, FrameNr frame)
|
emitted (uint channel, FrameID frame)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED ("determine if the specivied buffer was indeed handed over for emitting output");
|
UNIMPLEMENTED ("determine if the specivied buffer was indeed handed over for emitting output");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue