diff --git a/src/CvSourceImpl.cpp b/src/CvSourceImpl.cpp index 0cf48f4ca4..12f8056e7d 100644 --- a/src/CvSourceImpl.cpp +++ b/src/CvSourceImpl.cpp @@ -30,7 +30,7 @@ CvSourceImpl::~CvSourceImpl() {} void CvSourceImpl::Start() {} -std::unique_ptr CvSourceImpl::CreateEmptyProperty( +std::unique_ptr CvSourceImpl::CreateEmptyProperty( llvm::StringRef name) const { return llvm::make_unique(name); } @@ -57,11 +57,8 @@ void CvSourceImpl::SetProperty(int property, int value, CS_Status* status) { *status = CS_WRONG_PROPERTY_TYPE; return; } - prop->SetValue(value); - if (m_properties_cached) - Notifier::GetInstance().NotifySourceProperty( - *this, CS_SOURCE_PROPERTY_VALUE_UPDATED, property, prop->propKind, - prop->value, prop->valueStr); + + UpdatePropertyValue(property, false, value, llvm::StringRef{}); } void CvSourceImpl::SetStringProperty(int property, llvm::StringRef value, @@ -80,11 +77,8 @@ void CvSourceImpl::SetStringProperty(int property, llvm::StringRef value, *status = CS_WRONG_PROPERTY_TYPE; return; } - prop->SetValue(value); - if (m_properties_cached) - Notifier::GetInstance().NotifySourceProperty( - *this, CS_SOURCE_PROPERTY_VALUE_UPDATED, property, CS_PROP_STRING, - prop->value, prop->valueStr); + + UpdatePropertyValue(property, true, 0, value); } bool CvSourceImpl::SetVideoMode(const VideoMode& mode, CS_Status* status) { diff --git a/src/CvSourceImpl.h b/src/CvSourceImpl.h index d9e9535e46..d0b541c033 100644 --- a/src/CvSourceImpl.h +++ b/src/CvSourceImpl.h @@ -45,13 +45,13 @@ class CvSourceImpl : public SourceImpl { CS_Status* status); // Property data - class PropertyData : public PropertyBase { + class PropertyData : public PropertyImpl { public: PropertyData() = default; - PropertyData(llvm::StringRef name_) : PropertyBase{name_} {} + PropertyData(llvm::StringRef name_) : PropertyImpl{name_} {} PropertyData(llvm::StringRef name_, CS_PropertyKind kind_, int minimum_, int maximum_, int step_, int defaultValue_, int value_) - : PropertyBase{name_, kind_, step_, defaultValue_, value_} { + : PropertyImpl{name_, kind_, step_, defaultValue_, value_} { hasMinimum = true; minimum = minimum_; hasMaximum = true; @@ -63,7 +63,7 @@ class CvSourceImpl : public SourceImpl { }; protected: - std::unique_ptr CreateEmptyProperty( + std::unique_ptr CreateEmptyProperty( llvm::StringRef name) const override; bool CacheProperties(CS_Status* status) const override; diff --git a/src/PropertyImpl.h b/src/PropertyImpl.h new file mode 100644 index 0000000000..26ab6f330c --- /dev/null +++ b/src/PropertyImpl.h @@ -0,0 +1,76 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2016. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#ifndef CS_PROPERTYIMPL_H_ +#define CS_PROPERTYIMPL_H_ + +#include +#include + +#include "llvm/StringRef.h" + +#include "cscore_c.h" + +namespace cs { + +// Property data +class PropertyImpl { + public: + PropertyImpl() = default; + PropertyImpl(llvm::StringRef name_) : name{name_} {} + PropertyImpl(llvm::StringRef name_, CS_PropertyKind kind_, int step_, + int defaultValue_, int value_) + : name{name_}, + propKind{kind_}, + step{step_}, + defaultValue{defaultValue_}, + value{value_} {} + virtual ~PropertyImpl() = default; + PropertyImpl(const PropertyImpl& oth) = delete; + PropertyImpl& operator=(const PropertyImpl& oth) = delete; + + void SetValue(int v) { + if (hasMinimum && v < minimum) + value = minimum; + else if (hasMaximum && v > maximum) + value = maximum; + else + value = v; + valueSet = true; + } + + void SetValue(llvm::StringRef v) { + valueStr = v; + valueSet = true; + } + + void SetDefaultValue(int v) { + if (hasMinimum && v < minimum) + defaultValue = minimum; + else if (hasMaximum && v > maximum) + defaultValue = maximum; + else + defaultValue = v; + } + + std::string name; + CS_PropertyKind propKind{CS_PROP_NONE}; + bool hasMinimum{false}; + bool hasMaximum{false}; + int minimum{0}; + int maximum{100}; + int step{1}; + int defaultValue{0}; + int value{0}; + std::string valueStr; + std::vector enumChoices; + bool valueSet{false}; +}; + +} // namespace cs + +#endif // CS_PROPERTYIMPL_H_ diff --git a/src/SourceImpl.cpp b/src/SourceImpl.cpp index 824ec0b2f1..09462985b8 100644 --- a/src/SourceImpl.cpp +++ b/src/SourceImpl.cpp @@ -335,6 +335,34 @@ void SourceImpl::PutError(llvm::StringRef msg, Frame::Time time) { m_frameCv.notify_all(); } +void SourceImpl::NotifyPropertyCreated(int propIndex, PropertyImpl& prop) { + auto& notifier = Notifier::GetInstance(); + notifier.NotifySourceProperty(*this, CS_SOURCE_PROPERTY_CREATED, propIndex, + prop.propKind, prop.value, prop.valueStr); + // also notify choices updated event for enum types + if (prop.propKind == CS_PROP_ENUM) + notifier.NotifySourceProperty(*this, CS_SOURCE_PROPERTY_CHOICES_UPDATED, + propIndex, prop.propKind, prop.value, + llvm::StringRef{}); +} + +void SourceImpl::UpdatePropertyValue(int property, bool setString, int value, + llvm::StringRef valueStr) { + auto prop = GetProperty(property); + if (!prop) return; + + if (setString) + prop->SetValue(valueStr); + else + prop->SetValue(value); + + // Only notify updates after we've notified created + if (m_properties_cached) + Notifier::GetInstance().NotifySourceProperty( + *this, CS_SOURCE_PROPERTY_VALUE_UPDATED, property, prop->propKind, + prop->value, prop->valueStr); +} + void SourceImpl::ReleaseImage(std::unique_ptr image) { std::lock_guard lock{m_poolMutex}; if (m_destroyFrames) return; diff --git a/src/SourceImpl.h b/src/SourceImpl.h index 4f8ff9e4b2..198da0319f 100644 --- a/src/SourceImpl.h +++ b/src/SourceImpl.h @@ -19,9 +19,11 @@ #include "llvm/ArrayRef.h" #include "llvm/StringMap.h" #include "llvm/StringRef.h" + #include "cscore_cpp.h" #include "Frame.h" #include "Image.h" +#include "PropertyImpl.h" namespace cs { @@ -135,67 +137,13 @@ class SourceImpl { std::atomic_int m_numSinksEnabled{0}; protected: - // Property data - class PropertyBase { - public: - PropertyBase() = default; - PropertyBase(llvm::StringRef name_) : name{name_} {} - PropertyBase(llvm::StringRef name_, CS_PropertyKind kind_, int step_, - int defaultValue_, int value_) - : name{name_}, - propKind{kind_}, - step{step_}, - defaultValue{defaultValue_}, - value{value_} {} - virtual ~PropertyBase() = default; - PropertyBase(const PropertyBase& oth) = delete; - PropertyBase& operator=(const PropertyBase& oth) = delete; - - void SetValue(int v) { - if (hasMinimum && v < minimum) - value = minimum; - else if (hasMaximum && v > maximum) - value = maximum; - else - value = v; - valueSet = true; - } - - void SetValue(llvm::StringRef v) { - valueStr = v; - valueSet = true; - } - - void SetDefaultValue(int v) { - if (hasMinimum && v < minimum) - defaultValue = minimum; - else if (hasMaximum && v > maximum) - defaultValue = maximum; - else - defaultValue = v; - } - - std::string name; - CS_PropertyKind propKind{CS_PROP_NONE}; - bool hasMinimum{false}; - bool hasMaximum{false}; - int minimum{0}; - int maximum{100}; - int step{1}; - int defaultValue{0}; - int value{0}; - std::string valueStr; - std::vector enumChoices; - bool valueSet{false}; - }; - // Get a property; must be called with m_mutex held. - PropertyBase* GetProperty(int property) { + PropertyImpl* GetProperty(int property) { if (property <= 0 || static_cast(property) > m_propertyData.size()) return nullptr; return m_propertyData[property - 1].get(); } - const PropertyBase* GetProperty(int property) const { + const PropertyImpl* GetProperty(int property) const { if (property <= 0 || static_cast(property) > m_propertyData.size()) return nullptr; return m_propertyData[property - 1].get(); @@ -204,15 +152,21 @@ class SourceImpl { // Create an "empty" property. This is called by GetPropertyIndex to create // properties that don't exist (as GetPropertyIndex can't fail). // Note: called with m_mutex held. - virtual std::unique_ptr CreateEmptyProperty( + virtual std::unique_ptr CreateEmptyProperty( llvm::StringRef name) const = 0; // Cache properties. Implementations must return false and set status to // CS_SOURCE_IS_DISCONNECTED if not possible to cache. virtual bool CacheProperties(CS_Status* status) const = 0; + void NotifyPropertyCreated(int propIndex, PropertyImpl& prop); + + // Update property value; must be called with m_mutex held. + void UpdatePropertyValue(int property, bool setString, int value, + llvm::StringRef valueStr); + // Cached properties and video modes (protected with m_mutex) - mutable std::vector> m_propertyData; + mutable std::vector> m_propertyData; mutable llvm::StringMap m_properties; mutable std::vector m_videoModes; // Current video mode diff --git a/src/UsbCameraImpl.cpp b/src/UsbCameraImpl.cpp index 9149eef5a9..9a6d5f9694 100644 --- a/src/UsbCameraImpl.cpp +++ b/src/UsbCameraImpl.cpp @@ -122,27 +122,10 @@ int UsbCameraImpl::PercentageToRaw(const PropertyData& rawProp, (rawProp.maximum - rawProp.minimum) * (percentValue / 100.0); } -void UsbCameraImpl::UpdatePropertyValue(int property, bool setString, int value, - llvm::StringRef valueStr) { - auto prop = static_cast(GetProperty(property)); - if (!prop) return; - - if (setString) - prop->SetValue(valueStr); - else - prop->SetValue(value); - - // Only notify updates after we've notified created - if (m_properties_cached) - Notifier::GetInstance().NotifySourceProperty( - *this, CS_SOURCE_PROPERTY_VALUE_UPDATED, property, prop->propKind, - prop->value, prop->valueStr); -} - #ifdef VIDIOC_QUERY_EXT_CTRL UsbCameraImpl::PropertyData::PropertyData( const struct v4l2_query_ext_ctrl& ctrl) - : PropertyBase(llvm::StringRef{}, CS_PROP_NONE, ctrl.step, + : PropertyImpl(llvm::StringRef{}, CS_PROP_NONE, ctrl.step, ctrl.default_value, 0), id(ctrl.id & V4L2_CTRL_ID_MASK), type(ctrl.type) { @@ -180,7 +163,7 @@ UsbCameraImpl::PropertyData::PropertyData( #endif UsbCameraImpl::PropertyData::PropertyData(const struct v4l2_queryctrl& ctrl) - : PropertyBase(llvm::StringRef{}, CS_PROP_NONE, ctrl.step, + : PropertyImpl(llvm::StringRef{}, CS_PROP_NONE, ctrl.step, ctrl.default_value, 0), id(ctrl.id & V4L2_CTRL_ID_MASK), type(ctrl.type) { @@ -1057,17 +1040,6 @@ void UsbCameraImpl::DeviceCacheMode() { Notifier::GetInstance().NotifySource(*this, CS_SOURCE_VIDEOMODE_CHANGED); } -void UsbCameraImpl::NotifyPropertyCreated(int propIndex, PropertyData& prop) { - auto& notifier = Notifier::GetInstance(); - notifier.NotifySourceProperty(*this, CS_SOURCE_PROPERTY_CREATED, propIndex, - prop.propKind, prop.value, prop.valueStr); - // also notify choices updated event for enum types - if (prop.propKind == CS_PROP_ENUM) - notifier.NotifySourceProperty(*this, CS_SOURCE_PROPERTY_CHOICES_UPDATED, - propIndex, prop.propKind, prop.value, - llvm::StringRef{}); -} - void UsbCameraImpl::DeviceCacheProperty(std::unique_ptr rawProp) { // For percentage properties, we want to cache both the raw and the // percentage versions. This function is always called with prop being @@ -1417,7 +1389,7 @@ void UsbCameraImpl::Send(std::unique_ptr msg) const { eventfd_write(fd, 1); } -std::unique_ptr UsbCameraImpl::CreateEmptyProperty( +std::unique_ptr UsbCameraImpl::CreateEmptyProperty( llvm::StringRef name) const { return llvm::make_unique(name); } diff --git a/src/UsbCameraImpl.h b/src/UsbCameraImpl.h index 01dc3644eb..de7cf156e7 100644 --- a/src/UsbCameraImpl.h +++ b/src/UsbCameraImpl.h @@ -50,15 +50,15 @@ class UsbCameraImpl : public SourceImpl { std::string GetPath() { return m_path; } // Property data - class PropertyData : public PropertyBase { + class PropertyData : public PropertyImpl { public: PropertyData() = default; - PropertyData(llvm::StringRef name_) : PropertyBase{name_} {} + PropertyData(llvm::StringRef name_) : PropertyImpl{name_} {} // Normalized property constructor PropertyData(llvm::StringRef name_, int rawIndex_, const PropertyData& rawProp, int defaultValue_, int value_) - : PropertyBase(name_, rawProp.propKind, 1, defaultValue_, value_), + : PropertyImpl(name_, rawProp.propKind, 1, defaultValue_, value_), percentage{true}, propPair{rawIndex_}, id{rawProp.id}, @@ -111,7 +111,7 @@ class UsbCameraImpl : public SourceImpl { }; protected: - std::unique_ptr CreateEmptyProperty( + std::unique_ptr CreateEmptyProperty( llvm::StringRef name) const override; // Cache properties. Immediately successful if properties are already cached. @@ -169,9 +169,6 @@ class UsbCameraImpl : public SourceImpl { // Property helper functions int RawToPercentage(const PropertyData& rawProp, int rawValue); int PercentageToRaw(const PropertyData& rawProp, int percentValue); - void UpdatePropertyValue(int property, bool setString, int value, - llvm::StringRef valueStr); - void NotifyPropertyCreated(int propIndex, PropertyData& prop); // // Variables only used within camera thread