From fac798df934dba45172299d89897a8df8c4e77cb Mon Sep 17 00:00:00 2001 From: brunoherbelin Date: Thu, 1 Oct 2020 23:44:14 +0200 Subject: [PATCH] BugFix: prevent from creating twice a source with the same device: create a clone of the original device source instead. --- DeviceSource.cpp | 42 +++++++++++++++++++++++++++++++++- DeviceSource.h | 59 ++++++++++++++++++++++++++---------------------- Mixer.cpp | 3 +-- 3 files changed, 74 insertions(+), 30 deletions(-) diff --git a/DeviceSource.cpp b/DeviceSource.cpp index e9fc4fe..2b14f0a 100644 --- a/DeviceSource.cpp +++ b/DeviceSource.cpp @@ -251,6 +251,38 @@ bool Device::exists(const std::string &device) const return d != src_name_.end(); } +struct hasDevice: public std::unary_function +{ + inline bool operator()(const DeviceSource* elem) const { + return (elem && elem->device() == _d); + } + hasDevice(std::string d) : _d(d) { } +private: + std::string _d; +}; + +Source *Device::createSource(const std::string &device) const +{ + Source *s = nullptr; + + // find if a DeviceSource with this device is already registered + std::list< DeviceSource *>::const_iterator d = std::find_if(device_sources_.begin(), device_sources_.end(), hasDevice(device)); + + // if already registered, clone the device source + if ( d != device_sources_.end()) { + CloneSource *cs = (*d)->clone(); + s = cs; + } + // otherwise, we are free to create a new device source + else { + DeviceSource *ds = new DeviceSource(); + ds->setDevice(device); + s = ds; + } + + return s; +} + bool Device::unplugged(const std::string &device) const { if (list_uptodate_) @@ -302,6 +334,12 @@ DeviceSource::DeviceSource() : StreamSource() overlays_[View::LAYER]->attach( new Symbol(Symbol::CAMERA, glm::vec3(0.8f, 0.8f, 0.01f)) ); } +DeviceSource::~DeviceSource() +{ + // unregister this device source + Device::manager().device_sources_.remove(this); +} + void DeviceSource::setDevice(const std::string &devicename) { device_ = devicename; @@ -310,6 +348,9 @@ void DeviceSource::setDevice(const std::string &devicename) int index = Device::manager().index(device_); if (index > -1) { + // register this device source + Device::manager().device_sources_.push_back(this); + // start filling in the gstreamer pipeline std::ostringstream pipeline; pipeline << Device::manager().description(index); @@ -360,7 +401,6 @@ bool DeviceSource::failed() const return stream_->failed() || Device::manager().unplugged(device_); } - DeviceConfigSet Device::getDeviceConfigs(const std::string &src_description) { DeviceConfigSet configs; diff --git a/DeviceSource.h b/DeviceSource.h index 7228480..7fc0e78 100644 --- a/DeviceSource.h +++ b/DeviceSource.h @@ -7,6 +7,30 @@ #include "GstToolkit.h" #include "StreamSource.h" +class DeviceSource : public StreamSource +{ +public: + DeviceSource(); + ~DeviceSource(); + + // Source interface + bool failed() const override; + void accept (Visitor& v) override; + + // StreamSource interface + Stream *stream() const override { return stream_; } + + // specific interface + void setDevice(const std::string &devicename); + inline std::string device() const { return device_; } + + glm::ivec2 icon() const override; + +private: + std::string device_; + +}; + struct DeviceConfig { gint width; gint height; @@ -60,6 +84,8 @@ typedef std::set DeviceConfigSet; class Device { + friend class DeviceSource; + Device(); Device(Rendering const& copy); // Not Implemented Device& operator=(Rendering const& copy); // Not Implemented @@ -78,9 +104,11 @@ public: std::string description (int index) const; DeviceConfigSet config (int index) const; + int index (const std::string &device) const; bool exists (const std::string &device) const; bool unplugged (const std::string &device) const; - int index (const std::string &device) const; + + Source *createSource(const std::string &device) const; static gboolean callback_device_monitor (GstBus *, GstMessage *, gpointer); static DeviceConfigSet getDeviceConfigs(const std::string &src_description); @@ -88,38 +116,15 @@ public: private: void remove(const char *device); + std::vector< std::string > src_name_; std::vector< std::string > src_description_; - std::vector< DeviceConfigSet > src_config_; - bool list_uptodate_; GstDeviceMonitor *monitor_; + + std::list< DeviceSource * > device_sources_; }; -class DeviceSource : public StreamSource -{ -public: - DeviceSource(); - - // Source interface - bool failed() const override; - void accept (Visitor& v) override; - - // StreamSource interface - Stream *stream() const override { return stream_; } - - // specific interface - void setDevice(const std::string &devicename); - inline std::string device() const { return device_; } - - glm::ivec2 icon() const override; - -private: - std::string device_; - - -}; - #endif // DEVICESOURCE_H diff --git a/Mixer.cpp b/Mixer.cpp index e43aef9..4c2fa0c 100644 --- a/Mixer.cpp +++ b/Mixer.cpp @@ -294,8 +294,7 @@ Source * Mixer::createSourcePattern(int pattern, glm::ivec2 res) Source * Mixer::createSourceDevice(const std::string &namedevice) { // ready to create a source - DeviceSource *s = new DeviceSource(); - s->setDevice(namedevice); + Source *s = Device::manager().createSource(namedevice); // propose a new name based on pattern name renameSource(s, namedevice);