BugFix: prevent from creating twice a source with the same device:

create a clone of the original device source instead.
This commit is contained in:
brunoherbelin
2020-10-01 23:44:14 +02:00
parent 83a2da6b2b
commit fac798df93
3 changed files with 74 additions and 30 deletions

View File

@@ -251,6 +251,38 @@ bool Device::exists(const std::string &device) const
return d != src_name_.end(); return d != src_name_.end();
} }
struct hasDevice: public std::unary_function<DeviceSource*, bool>
{
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 bool Device::unplugged(const std::string &device) const
{ {
if (list_uptodate_) 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)) ); 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) void DeviceSource::setDevice(const std::string &devicename)
{ {
device_ = devicename; device_ = devicename;
@@ -310,6 +348,9 @@ void DeviceSource::setDevice(const std::string &devicename)
int index = Device::manager().index(device_); int index = Device::manager().index(device_);
if (index > -1) { if (index > -1) {
// register this device source
Device::manager().device_sources_.push_back(this);
// start filling in the gstreamer pipeline // start filling in the gstreamer pipeline
std::ostringstream pipeline; std::ostringstream pipeline;
pipeline << Device::manager().description(index); pipeline << Device::manager().description(index);
@@ -360,7 +401,6 @@ bool DeviceSource::failed() const
return stream_->failed() || Device::manager().unplugged(device_); return stream_->failed() || Device::manager().unplugged(device_);
} }
DeviceConfigSet Device::getDeviceConfigs(const std::string &src_description) DeviceConfigSet Device::getDeviceConfigs(const std::string &src_description)
{ {
DeviceConfigSet configs; DeviceConfigSet configs;

View File

@@ -7,6 +7,30 @@
#include "GstToolkit.h" #include "GstToolkit.h"
#include "StreamSource.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 { struct DeviceConfig {
gint width; gint width;
gint height; gint height;
@@ -60,6 +84,8 @@ typedef std::set<DeviceConfig, better_device_comparator> DeviceConfigSet;
class Device class Device
{ {
friend class DeviceSource;
Device(); Device();
Device(Rendering const& copy); // Not Implemented Device(Rendering const& copy); // Not Implemented
Device& operator=(Rendering const& copy); // Not Implemented Device& operator=(Rendering const& copy); // Not Implemented
@@ -78,9 +104,11 @@ public:
std::string description (int index) const; std::string description (int index) const;
DeviceConfigSet config (int index) const; DeviceConfigSet config (int index) const;
int index (const std::string &device) const;
bool exists (const std::string &device) const; bool exists (const std::string &device) const;
bool unplugged (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 gboolean callback_device_monitor (GstBus *, GstMessage *, gpointer);
static DeviceConfigSet getDeviceConfigs(const std::string &src_description); static DeviceConfigSet getDeviceConfigs(const std::string &src_description);
@@ -88,38 +116,15 @@ public:
private: private:
void remove(const char *device); void remove(const char *device);
std::vector< std::string > src_name_; std::vector< std::string > src_name_;
std::vector< std::string > src_description_; std::vector< std::string > src_description_;
std::vector< DeviceConfigSet > src_config_; std::vector< DeviceConfigSet > src_config_;
bool list_uptodate_; bool list_uptodate_;
GstDeviceMonitor *monitor_; 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 #endif // DEVICESOURCE_H

View File

@@ -294,8 +294,7 @@ Source * Mixer::createSourcePattern(int pattern, glm::ivec2 res)
Source * Mixer::createSourceDevice(const std::string &namedevice) Source * Mixer::createSourceDevice(const std::string &namedevice)
{ {
// ready to create a source // ready to create a source
DeviceSource *s = new DeviceSource(); Source *s = Device::manager().createSource(namedevice);
s->setDevice(namedevice);
// propose a new name based on pattern name // propose a new name based on pattern name
renameSource(s, namedevice); renameSource(s, namedevice);