mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-13 19:29:58 +01:00
New Generalize option to restart on deactivation to any StreamSource
StreamSource now have the option 'restart on deactivation' like MediaPlayer. This option is saved in XML (added Visitors for Stream and StreamSource). The GUI is added as sub-menu in play bar (like for MediaPlayer). Some StreamSource subclasses needed to be fixed to allow this feature (e.g. MultiFileSource).
This commit is contained in:
@@ -526,7 +526,7 @@ void DeviceSource::setActive (bool on)
|
|||||||
|
|
||||||
void DeviceSource::accept(Visitor& v)
|
void DeviceSource::accept(Visitor& v)
|
||||||
{
|
{
|
||||||
Source::accept(v);
|
StreamSource::accept(v);
|
||||||
v.visit(*this);
|
v.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -129,6 +129,16 @@ void MultiFile::close ()
|
|||||||
Stream::close();
|
Stream::close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MultiFile::rewind ()
|
||||||
|
{
|
||||||
|
if (src_) {
|
||||||
|
int begin = 0;
|
||||||
|
g_object_get (src_, "start-index", &begin, NULL);
|
||||||
|
setIndex (begin);
|
||||||
|
}
|
||||||
|
Stream::rewind();
|
||||||
|
}
|
||||||
|
|
||||||
void MultiFile::setIndex(int val)
|
void MultiFile::setIndex(int val)
|
||||||
{
|
{
|
||||||
if (src_) {
|
if (src_) {
|
||||||
@@ -219,10 +229,8 @@ void MultiFileSource::setRange (int begin, int end)
|
|||||||
|
|
||||||
void MultiFileSource::replay ()
|
void MultiFileSource::replay ()
|
||||||
{
|
{
|
||||||
if (multifile()) {
|
if (multifile())
|
||||||
multifile()->setIndex (begin_);
|
multifile()->rewind();
|
||||||
stream_->rewind();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
guint64 MultiFileSource::playtime () const
|
guint64 MultiFileSource::playtime () const
|
||||||
@@ -240,7 +248,7 @@ guint64 MultiFileSource::playtime () const
|
|||||||
|
|
||||||
void MultiFileSource::accept (Visitor& v)
|
void MultiFileSource::accept (Visitor& v)
|
||||||
{
|
{
|
||||||
Source::accept(v);
|
StreamSource::accept(v);
|
||||||
v.visit(*this);
|
v.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ public:
|
|||||||
MultiFile ();
|
MultiFile ();
|
||||||
void open (const MultiFileSequence &sequence, uint framerate = 30);
|
void open (const MultiFileSequence &sequence, uint framerate = 30);
|
||||||
void close () override;
|
void close () override;
|
||||||
|
void rewind () override;
|
||||||
|
|
||||||
// dynamic change of gstreamer multifile source properties
|
// dynamic change of gstreamer multifile source properties
|
||||||
void setProperties(int begin, int end, int loop);
|
void setProperties(int begin, int end, int loop);
|
||||||
|
|||||||
@@ -341,7 +341,7 @@ std::string NetworkSource::connection() const
|
|||||||
|
|
||||||
void NetworkSource::accept(Visitor& v)
|
void NetworkSource::accept(Visitor& v)
|
||||||
{
|
{
|
||||||
Source::accept(v);
|
StreamSource::accept(v);
|
||||||
v.visit(*this);
|
v.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ void PatternSource::setPattern(uint type, glm::ivec2 resolution)
|
|||||||
|
|
||||||
void PatternSource::accept(Visitor& v)
|
void PatternSource::accept(Visitor& v)
|
||||||
{
|
{
|
||||||
Source::accept(v);
|
StreamSource::accept(v);
|
||||||
v.visit(*this);
|
v.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,6 @@
|
|||||||
#include "NetworkSource.h"
|
#include "NetworkSource.h"
|
||||||
#include "SrtReceiverSource.h"
|
#include "SrtReceiverSource.h"
|
||||||
#include "MultiFileSource.h"
|
#include "MultiFileSource.h"
|
||||||
#include "StreamSource.h"
|
|
||||||
#include "RenderSource.h"
|
#include "RenderSource.h"
|
||||||
#include "Session.h"
|
#include "Session.h"
|
||||||
#include "ImageShader.h"
|
#include "ImageShader.h"
|
||||||
@@ -1169,6 +1168,24 @@ void SessionLoader::visit (RenderSource& s)
|
|||||||
s.setSession( session_ );
|
s.setSession( session_ );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SessionLoader::visit(Stream &n)
|
||||||
|
{
|
||||||
|
XMLElement* streamNode = xmlCurrent_->FirstChildElement("Stream");
|
||||||
|
|
||||||
|
if (streamNode) {
|
||||||
|
bool rewind_on_disabled = false;
|
||||||
|
streamNode->QueryBoolAttribute("rewind_on_disabled", &rewind_on_disabled);
|
||||||
|
n.setRewindOnDisabled(rewind_on_disabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionLoader::visit (StreamSource& s)
|
||||||
|
{
|
||||||
|
// set config stream
|
||||||
|
if (s.stream() != nullptr)
|
||||||
|
s.stream()->accept(*this);
|
||||||
|
}
|
||||||
|
|
||||||
void SessionLoader::visit (PatternSource& s)
|
void SessionLoader::visit (PatternSource& s)
|
||||||
{
|
{
|
||||||
uint t = xmlCurrent_->UnsignedAttribute("pattern");
|
uint t = xmlCurrent_->UnsignedAttribute("pattern");
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ public:
|
|||||||
|
|
||||||
// Elements with attributes
|
// Elements with attributes
|
||||||
void visit (MediaPlayer& n) override;
|
void visit (MediaPlayer& n) override;
|
||||||
|
void visit (Stream& n) override;
|
||||||
void visit (Shader& n) override;
|
void visit (Shader& n) override;
|
||||||
void visit (ImageShader& n) override;
|
void visit (ImageShader& n) override;
|
||||||
void visit (MaskShader& n) override;
|
void visit (MaskShader& n) override;
|
||||||
@@ -53,6 +54,7 @@ public:
|
|||||||
// Sources
|
// Sources
|
||||||
void visit (Source& s) override;
|
void visit (Source& s) override;
|
||||||
void visit (MediaSource& s) override;
|
void visit (MediaSource& s) override;
|
||||||
|
void visit (StreamSource& s) override;
|
||||||
void visit (SessionFileSource& s) override;
|
void visit (SessionFileSource& s) override;
|
||||||
void visit (SessionGroupSource& s) override;
|
void visit (SessionGroupSource& s) override;
|
||||||
void visit (RenderSource& s) override;
|
void visit (RenderSource& s) override;
|
||||||
|
|||||||
@@ -405,6 +405,18 @@ void SessionVisitor::visit(FrameBufferSurface &)
|
|||||||
xmlCurrent_->SetAttribute("type", "FrameBufferSurface");
|
xmlCurrent_->SetAttribute("type", "FrameBufferSurface");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SessionVisitor::visit(Stream &n)
|
||||||
|
{
|
||||||
|
XMLElement *newelement = xmlDoc_->NewElement("Stream");
|
||||||
|
newelement->SetAttribute("id", n.id());
|
||||||
|
|
||||||
|
if (!n.singleFrame()) {
|
||||||
|
newelement->SetAttribute("rewind_on_disabled", n.rewindOnDisabled());
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlCurrent_->InsertEndChild(newelement);
|
||||||
|
}
|
||||||
|
|
||||||
void SessionVisitor::visit(MediaPlayer &n)
|
void SessionVisitor::visit(MediaPlayer &n)
|
||||||
{
|
{
|
||||||
XMLElement *newelement = xmlDoc_->NewElement("MediaPlayer");
|
XMLElement *newelement = xmlDoc_->NewElement("MediaPlayer");
|
||||||
@@ -808,6 +820,12 @@ void SessionVisitor::visit (CloneSource& s)
|
|||||||
xmlCurrent_ = cloneNode; // parent for next visits (other subtypes of Source)
|
xmlCurrent_ = cloneNode; // parent for next visits (other subtypes of Source)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SessionVisitor::visit (StreamSource& s)
|
||||||
|
{
|
||||||
|
if (s.stream() != nullptr)
|
||||||
|
s.stream()->accept(*this);
|
||||||
|
}
|
||||||
|
|
||||||
void SessionVisitor::visit (PatternSource& s)
|
void SessionVisitor::visit (PatternSource& s)
|
||||||
{
|
{
|
||||||
xmlCurrent_->SetAttribute("type", "PatternSource");
|
xmlCurrent_->SetAttribute("type", "PatternSource");
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ public:
|
|||||||
|
|
||||||
// Elements with attributes
|
// Elements with attributes
|
||||||
void visit (MediaPlayer& n) override;
|
void visit (MediaPlayer& n) override;
|
||||||
|
void visit (Stream& n) override;
|
||||||
void visit (Shader& n) override;
|
void visit (Shader& n) override;
|
||||||
void visit (ImageShader& n) override;
|
void visit (ImageShader& n) override;
|
||||||
void visit (MaskShader& n) override;
|
void visit (MaskShader& n) override;
|
||||||
@@ -58,6 +59,7 @@ public:
|
|||||||
// Sources
|
// Sources
|
||||||
void visit (Source& s) override;
|
void visit (Source& s) override;
|
||||||
void visit (MediaSource& s) override;
|
void visit (MediaSource& s) override;
|
||||||
|
void visit (StreamSource& s) override;
|
||||||
void visit (SessionFileSource& s) override;
|
void visit (SessionFileSource& s) override;
|
||||||
void visit (SessionGroupSource& s) override;
|
void visit (SessionGroupSource& s) override;
|
||||||
void visit (RenderSource&) override;
|
void visit (RenderSource&) override;
|
||||||
|
|||||||
@@ -375,8 +375,8 @@ void SourceControlWindow::Render()
|
|||||||
if (ImGui::BeginMenu(ICON_FA_PHOTO_VIDEO " Media", mediaplayer_active_) )
|
if (ImGui::BeginMenu(ICON_FA_PHOTO_VIDEO " Media", mediaplayer_active_) )
|
||||||
{
|
{
|
||||||
if ( !mediaplayer_active_->singleFrame() ) {
|
if ( !mediaplayer_active_->singleFrame() ) {
|
||||||
if (ImGui::MenuItem( ICON_FA_REDO_ALT " Reload" ))
|
// if (ImGui::MenuItem( ICON_FA_REDO_ALT " Reload" ))
|
||||||
mediaplayer_active_->reopen();
|
// mediaplayer_active_->reopen();
|
||||||
if (ImGuiToolkit::MenuItemIcon(16, 16, "Gstreamer effect", nullptr,
|
if (ImGuiToolkit::MenuItemIcon(16, 16, "Gstreamer effect", nullptr,
|
||||||
false, mediaplayer_active_->videoEffectAvailable()) )
|
false, mediaplayer_active_->videoEffectAvailable()) )
|
||||||
mediaplayer_edit_pipeline_ = true;
|
mediaplayer_edit_pipeline_ = true;
|
||||||
@@ -390,16 +390,6 @@ void SourceControlWindow::Render()
|
|||||||
mediaplayer_active_->setSoftwareDecodingForced(true);
|
mediaplayer_active_->setSoftwareDecodingForced(true);
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
if (ImGui::BeginMenu(ICON_FA_SNOWFLAKE " On deactivation"))
|
|
||||||
{
|
|
||||||
bool option = !mediaplayer_active_->rewindOnDisabled();
|
|
||||||
if (ImGui::MenuItem(ICON_FA_STOP " Stop", NULL, &option ))
|
|
||||||
mediaplayer_active_->setRewindOnDisabled(false);
|
|
||||||
option = mediaplayer_active_->rewindOnDisabled();
|
|
||||||
if (ImGui::MenuItem(ICON_FA_FAST_BACKWARD " Rewind & Stop", NULL, &option ))
|
|
||||||
mediaplayer_active_->setRewindOnDisabled(true);
|
|
||||||
ImGui::EndMenu();
|
|
||||||
}
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
ImGui::TextDisabled("Timeline");
|
ImGui::TextDisabled("Timeline");
|
||||||
|
|
||||||
@@ -1410,8 +1400,10 @@ void SourceControlWindow::RenderSingleSource(Source *s)
|
|||||||
///
|
///
|
||||||
DrawButtonBar(bottom, rendersize.x);
|
DrawButtonBar(bottom, rendersize.x);
|
||||||
|
|
||||||
// If possibly a media source, but is not playable
|
///
|
||||||
// then offer to make it playable by adding a timeline
|
/// Special possibly : selected a media source that is not playable
|
||||||
|
/// then offer to make it playable by adding a timeline
|
||||||
|
///
|
||||||
if ( ms != nullptr )
|
if ( ms != nullptr )
|
||||||
{
|
{
|
||||||
if (ms->mediaplayer()->isImage()) {
|
if (ms->mediaplayer()->isImage()) {
|
||||||
@@ -1450,6 +1442,43 @@ void SourceControlWindow::RenderSingleSource(Source *s)
|
|||||||
ImGui::PopStyleColor(2);
|
ImGui::PopStyleColor(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
///
|
||||||
|
/// Not a media source, but playable source
|
||||||
|
/// Offer context menu if it is a Stream source
|
||||||
|
///
|
||||||
|
else if ( s->active() && s->playable() ) {
|
||||||
|
StreamSource *ss = dynamic_cast<StreamSource *>(s);
|
||||||
|
if ( ss != nullptr ) {
|
||||||
|
|
||||||
|
static uint counter_menu_timeout = 0;
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::SetCursorPosX(rendersize.x - buttons_height_ / 1.4f);
|
||||||
|
if (ImGuiToolkit::IconButton(5, 8) || ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) {
|
||||||
|
counter_menu_timeout=0;
|
||||||
|
ImGui::OpenPopup( "MenuStreamOptions" );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::BeginPopup( "MenuStreamOptions" ))
|
||||||
|
{
|
||||||
|
// NB: ss is playable (tested above), and thus ss->stream() is not null
|
||||||
|
if (ImGui::MenuItem( ICON_FA_REDO_ALT " Reload" )) {
|
||||||
|
ss->stream()->reopen();
|
||||||
|
}
|
||||||
|
bool option = ss->stream()->rewindOnDisabled();
|
||||||
|
if (ImGui::MenuItem(ICON_FA_SNOWFLAKE " Restart on deactivation", NULL, &option )) {
|
||||||
|
ss->stream()->setRewindOnDisabled(option);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::IsWindowHovered())
|
||||||
|
counter_menu_timeout=0;
|
||||||
|
else if (++counter_menu_timeout > 10)
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1740,7 +1769,7 @@ void SourceControlWindow::RenderMediaPlayer(MediaSource *ms)
|
|||||||
ImGui::SetCursorPosX(rendersize.x - buttons_height_ / 1.4f);
|
ImGui::SetCursorPosX(rendersize.x - buttons_height_ / 1.4f);
|
||||||
if (ImGuiToolkit::IconButton(5, 8) || ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) {
|
if (ImGuiToolkit::IconButton(5, 8) || ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) {
|
||||||
counter_menu_timeout=0;
|
counter_menu_timeout=0;
|
||||||
ImGui::OpenPopup( "MenuPlaySpeed" );
|
ImGui::OpenPopup( "MenuMediaPlayerOptions" );
|
||||||
}
|
}
|
||||||
|
|
||||||
// restore buttons style
|
// restore buttons style
|
||||||
@@ -1784,7 +1813,7 @@ void SourceControlWindow::RenderMediaPlayer(MediaSource *ms)
|
|||||||
DrawButtonBar(bottom, rendersize.x);
|
DrawButtonBar(bottom, rendersize.x);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::BeginPopup( "MenuPlaySpeed" ))
|
if (ImGui::BeginPopup( "MenuMediaPlayerOptions" ))
|
||||||
{
|
{
|
||||||
if (ImGuiToolkit::MenuItemIcon(8,0, "Play forward", nullptr, current_play_speed>0)) {
|
if (ImGuiToolkit::MenuItemIcon(8,0, "Play forward", nullptr, current_play_speed>0)) {
|
||||||
mediaplayer_active_->setPlaySpeed( ABS(mediaplayer_active_->playSpeed()) );
|
mediaplayer_active_->setPlaySpeed( ABS(mediaplayer_active_->playSpeed()) );
|
||||||
@@ -1801,6 +1830,15 @@ void SourceControlWindow::RenderMediaPlayer(MediaSource *ms)
|
|||||||
oss << ": Speed x 1.0";
|
oss << ": Speed x 1.0";
|
||||||
Action::manager().store(oss.str());
|
Action::manager().store(oss.str());
|
||||||
}
|
}
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
if (ImGui::MenuItem( ICON_FA_REDO_ALT " Reload" ))
|
||||||
|
mediaplayer_active_->reopen();
|
||||||
|
|
||||||
|
bool option = mediaplayer_active_->rewindOnDisabled();
|
||||||
|
if (ImGui::MenuItem(ICON_FA_SNOWFLAKE " Restart on deactivation", NULL, &option )) {
|
||||||
|
mediaplayer_active_->setRewindOnDisabled(option);
|
||||||
|
}
|
||||||
|
|
||||||
if (ImGui::IsWindowHovered())
|
if (ImGui::IsWindowHovered())
|
||||||
counter_menu_timeout=0;
|
counter_menu_timeout=0;
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ std::string SrtReceiverSource::uri() const
|
|||||||
|
|
||||||
void SrtReceiverSource::accept(Visitor& v)
|
void SrtReceiverSource::accept(Visitor& v)
|
||||||
{
|
{
|
||||||
Source::accept(v);
|
StreamSource::accept(v);
|
||||||
v.visit(*this);
|
v.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ Stream::Stream()
|
|||||||
single_frame_ = false;
|
single_frame_ = false;
|
||||||
live_ = false;
|
live_ = false;
|
||||||
failed_ = false;
|
failed_ = false;
|
||||||
|
rewind_on_disable_ = false;
|
||||||
decoder_name_ = "";
|
decoder_name_ = "";
|
||||||
|
|
||||||
// start index in frame_ stack
|
// start index in frame_ stack
|
||||||
@@ -216,6 +217,15 @@ void Stream::open(const std::string &gstreamer_description, guint w, guint h)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Stream::reopen()
|
||||||
|
{
|
||||||
|
// re-openning is meaningfull only if it was already open
|
||||||
|
if (pipeline_ != nullptr) {
|
||||||
|
// reload : terminate pipeline and re-create it
|
||||||
|
close();
|
||||||
|
execute_open();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string Stream::description() const
|
std::string Stream::description() const
|
||||||
{
|
{
|
||||||
@@ -407,6 +417,10 @@ void Stream::enable(bool on)
|
|||||||
|
|
||||||
if ( enabled_ != on ) {
|
if ( enabled_ != on ) {
|
||||||
|
|
||||||
|
// option to automatically rewind each time the player is disabled
|
||||||
|
if (!on && rewind_on_disable_ && desired_state_ == GST_STATE_PLAYING)
|
||||||
|
rewind();
|
||||||
|
|
||||||
enabled_ = on;
|
enabled_ = on;
|
||||||
|
|
||||||
// default to pause
|
// default to pause
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ public:
|
|||||||
* Open a media using gstreamer pipeline keyword
|
* Open a media using gstreamer pipeline keyword
|
||||||
* */
|
* */
|
||||||
void open(const std::string &gstreamer_description, guint w = 0, guint h = 0);
|
void open(const std::string &gstreamer_description, guint w = 0, guint h = 0);
|
||||||
|
void reopen ();
|
||||||
/**
|
/**
|
||||||
* Get description string
|
* Get description string
|
||||||
* */
|
* */
|
||||||
@@ -143,6 +144,12 @@ public:
|
|||||||
* NB: perform request on pipeline on first call
|
* NB: perform request on pipeline on first call
|
||||||
* */
|
* */
|
||||||
std::string decoderName();
|
std::string decoderName();
|
||||||
|
/**
|
||||||
|
* Option to automatically rewind each time the player is disabled
|
||||||
|
* (i.e. when enable(false) is called )
|
||||||
|
* */
|
||||||
|
inline void setRewindOnDisabled(bool on) { rewind_on_disable_ = on; }
|
||||||
|
inline bool rewindOnDisabled() const { return rewind_on_disable_; }
|
||||||
/**
|
/**
|
||||||
* Get logs
|
* Get logs
|
||||||
* */
|
* */
|
||||||
@@ -176,6 +183,7 @@ protected:
|
|||||||
std::atomic<bool> opened_;
|
std::atomic<bool> opened_;
|
||||||
std::atomic<bool> failed_;
|
std::atomic<bool> failed_;
|
||||||
bool enabled_;
|
bool enabled_;
|
||||||
|
bool rewind_on_disable_;
|
||||||
std::string decoder_name_;
|
std::string decoder_name_;
|
||||||
|
|
||||||
// fps counter
|
// fps counter
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ std::list<std::string> GenericStreamSource::gstElements() const
|
|||||||
|
|
||||||
void GenericStreamSource::accept(Visitor& v)
|
void GenericStreamSource::accept(Visitor& v)
|
||||||
{
|
{
|
||||||
Source::accept(v);
|
StreamSource::accept(v);
|
||||||
v.visit(*this);
|
v.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,3 +197,9 @@ void StreamSource::update(float dt)
|
|||||||
if ( stream_ )
|
if ( stream_ )
|
||||||
stream_->update();
|
stream_->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StreamSource::accept(Visitor& v)
|
||||||
|
{
|
||||||
|
Source::accept(v);
|
||||||
|
v.visit(*this);
|
||||||
|
}
|
||||||
|
|||||||
@@ -41,6 +41,9 @@ public:
|
|||||||
// pure virtual interface
|
// pure virtual interface
|
||||||
virtual Stream *stream() const = 0;
|
virtual Stream *stream() const = 0;
|
||||||
|
|
||||||
|
// Source interface
|
||||||
|
virtual void accept (Visitor& v) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void init() override;
|
void init() override;
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ class ImageProcessingShader;
|
|||||||
|
|
||||||
class Source;
|
class Source;
|
||||||
class MediaSource;
|
class MediaSource;
|
||||||
|
class StreamSource;
|
||||||
class PatternSource;
|
class PatternSource;
|
||||||
class DeviceSource;
|
class DeviceSource;
|
||||||
class GenericStreamSource;
|
class GenericStreamSource;
|
||||||
@@ -101,6 +102,7 @@ public:
|
|||||||
virtual void visit (MixingGroup&) {}
|
virtual void visit (MixingGroup&) {}
|
||||||
virtual void visit (Source&) {}
|
virtual void visit (Source&) {}
|
||||||
virtual void visit (MediaSource&) {}
|
virtual void visit (MediaSource&) {}
|
||||||
|
virtual void visit (StreamSource&) {}
|
||||||
virtual void visit (NetworkSource&) {}
|
virtual void visit (NetworkSource&) {}
|
||||||
virtual void visit (SrtReceiverSource&) {}
|
virtual void visit (SrtReceiverSource&) {}
|
||||||
virtual void visit (GenericStreamSource&) {}
|
virtual void visit (GenericStreamSource&) {}
|
||||||
|
|||||||
Reference in New Issue
Block a user