Skip to content

Commit

Permalink
Added Support for CONTROL_SELECTOR type for CONTROL descriptors
Browse files Browse the repository at this point in the history
  • Loading branch information
christophe-calmejane committed Apr 25, 2023
1 parent 63b30e7 commit 3675fff
Show file tree
Hide file tree
Showing 3 changed files with 187 additions and 15 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- [ClockDomain locked state in entities list](https://github.com/christophe-calmejane/Hive/issues/133)
- Support for JACK Inputs and JACK Outputs
- Support for CONTROLs at non-configuration level
- Support for CONTROL_SELECTOR type for CONTROL descriptors

### Changed
- Complete rework of the `entities list`
Expand Down
160 changes: 148 additions & 12 deletions src/nodeTreeDynamicWidgets/controlValuesDynamicTreeWidgetItem.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class ControlValuesDynamicTreeWidgetItem : public QObject, public QTreeWidgetIte
virtual void updateValues(la::avdecc::entity::model::ControlValues const& controlValues) noexcept = 0;
};

/** Linear Values */
/** Linear Values - Clause 7.3.5.2.1 */
template<class StaticValueType, class DynamicValueType>
class LinearControlValuesDynamicTreeWidgetItem : public ControlValuesDynamicTreeWidgetItem
{
Expand Down Expand Up @@ -203,7 +203,7 @@ class LinearControlValuesDynamicTreeWidgetItem : public ControlValuesDynamicTree
if (controlValues.size() != _widgets.size())
{
// This should probably be detected by the AVDECC library
LOG_HIVE_WARN("ControlValues update not valid: Static/Dynamic count mismatch");
LOG_HIVE_WARN("ControlValues update not valid: Dynamic count mismatch");
return;
}

Expand Down Expand Up @@ -232,7 +232,142 @@ class LinearControlValuesDynamicTreeWidgetItem : public ControlValuesDynamicTree
std::vector<QWidget*> _widgets{};
};

/** Array Values */
/** Selector Values - Clause 7.3.5.2.2 */
template<class StaticValueType, class DynamicValueType>
class SelectorControlValuesDynamicTreeWidgetItem : public ControlValuesDynamicTreeWidgetItem
{
using value_size = typename DynamicValueType::control_value_details_traits::size_type;
using WidgetType = AecpCommandComboBox<value_size>;

public:
SelectorControlValuesDynamicTreeWidgetItem(la::avdecc::UniqueIdentifier const entityID, la::avdecc::entity::model::ControlIndex const controlIndex, la::avdecc::entity::model::ControlNodeStaticModel const& staticModel, la::avdecc::entity::model::ControlNodeDynamicModel const& dynamicModel, QTreeWidget* parent = nullptr)
: ControlValuesDynamicTreeWidgetItem{ entityID, controlIndex, staticModel, dynamicModel, parent }
{
_isReadOnly = staticModel.controlValueType.isReadOnly();

try
{
auto const staticValue = staticModel.values.getValues<StaticValueType>();
auto const dynamicValue = dynamicModel.values.getValues<DynamicValueType>();
if (dynamicValue.countValues() != 1)
{
LOG_HIVE_WARN("ControlValues not valid: Dynamic count is not equal to 1");
return;
}

auto* valueItem = new QTreeWidgetItem(this);
valueItem->setText(0, "Current Value");

if (_isReadOnly)
{
auto* label = new QLabel(QString::number(dynamicValue.currentValue));
parent->setItemWidget(valueItem, 1, label);
_widget = label;
}
else
{
auto* widget = new WidgetType{};
parent->setItemWidget(valueItem, 1, widget);


{
auto data = typename std::remove_pointer_t<decltype(widget)>::Data{};
for (auto const& option : staticValue.options)
{
data.insert(option);
}
widget->setAllData(data,
[](auto const& value)
{
return QString::number(value);
});
}

// Send changes
widget->setDataChangedHandler(
[this, widget](auto const& previousValue, auto const& newValue)
{
sendControlValues(widget, previousValue);
});

_widget = widget;
}


_isValid = true;

// Update now
updateValues(dynamicModel.values);
}
catch (...)
{
}
}

private:
void sendControlValues(WidgetType* const changedWidget, value_size const previousValue) noexcept
{
if (AVDECC_ASSERT_WITH_RET(!_isReadOnly, "Should never call sendControlValues with read only values"))
{
auto values = DynamicValueType{};
{
auto const* widget = static_cast<WidgetType const*>(_widget);
values.currentValue = static_cast<decltype(DynamicValueType::currentValue)>(widget->getCurrentData());
}
hive::modelsLibrary::ControllerManager::getInstance().setControlValues(_entityID, _controlIndex, la::avdecc::entity::model::ControlValues{ std::move(values) },
[this, changedWidget](la::avdecc::UniqueIdentifier const /*entityID*/)
{
changedWidget->setEnabled(false);
},
[this, changedWidget, previousValue](la::avdecc::UniqueIdentifier const entityID, la::avdecc::entity::ControllerEntity::AemCommandStatus const status)
{
QMetaObject::invokeMethod(this,
[this, changedWidget, previousValue, status]()
{
if (status != la::avdecc::entity::ControllerEntity::AemCommandStatus::Success)
{
changedWidget->setCurrentData(previousValue);

QMessageBox::warning(changedWidget, "", "<i>" + hive::modelsLibrary::ControllerManager::typeToString(hive::modelsLibrary::ControllerManager::AecpCommandType::SetControl) + "<//>/ failed:<br>" + QString::fromStdString(la::avdecc::entity::ControllerEntity::statusToString(status)));
}
changedWidget->setEnabled(true);
});
});
}
}

virtual void updateValues(la::avdecc::entity::model::ControlValues const& controlValues) noexcept override
{
if (_isValid)
{
if (controlValues.size() != 1u)
{
// This should probably be detected by the AVDECC library
LOG_HIVE_WARN("ControlValues update not valid: Dynamic count is not equal to 1");
return;
}

auto const& dynamicValue = controlValues.getValues<DynamicValueType>();

if (_isReadOnly)
{
auto* label = static_cast<QLabel*>(_widget);
label->setText(QString::number(dynamicValue.currentValue));
}
else
{
auto* widget = static_cast<WidgetType*>(_widget);
widget->setCurrentData(dynamicValue.currentValue);
}
}
}

bool _isValid{ false };
bool _isReadOnly{ false };
QWidget* _widget{};
};

/** Array Values - Clause 7.3.5.2.3 */
template<class StaticValueType, class DynamicValueType>
class ArrayControlValuesDynamicTreeWidgetItem : public ControlValuesDynamicTreeWidgetItem
{
Expand Down Expand Up @@ -370,7 +505,7 @@ class ArrayControlValuesDynamicTreeWidgetItem : public ControlValuesDynamicTreeW
if (controlValues.size() != _widgets.size())
{
// This should probably be detected by the AVDECC library
LOG_HIVE_WARN("ControlValues update not valid: Static/Dynamic count mismatch");
LOG_HIVE_WARN("ControlValues update not valid: Dynamic count mismatch");
return;
}

Expand Down Expand Up @@ -399,7 +534,7 @@ class ArrayControlValuesDynamicTreeWidgetItem : public ControlValuesDynamicTreeW
std::vector<QWidget*> _widgets{};
};

/** UTF-8 String Value */
/** UTF-8 String Value - Clause 7.3.5.2.4 */
class UTF8ControlValuesDynamicTreeWidgetItem : public ControlValuesDynamicTreeWidgetItem
{
//using value_size = typename DynamicValueType::control_value_details_traits::size_type;
Expand Down Expand Up @@ -465,10 +600,11 @@ class UTF8ControlValuesDynamicTreeWidgetItem : public ControlValuesDynamicTreeWi
if (AVDECC_ASSERT_WITH_RET(!_isReadOnly, "Should never call sendControlValues with read only values"))
{
auto values = DynamicValueType{};

auto const* widget = static_cast<WidgetType const*>(_widget);
auto data = widget->getCurrentData().toUtf8();
std::memcpy(values.currentValue.data(), data.constData(), std::min(static_cast<size_t>(data.size()), values.currentValue.size()));
{
auto const* widget = static_cast<WidgetType const*>(_widget);
auto data = widget->getCurrentData().toUtf8();
std::memcpy(values.currentValue.data(), data.constData(), std::min(static_cast<size_t>(data.size()), values.currentValue.size()));
}
hive::modelsLibrary::ControllerManager::getInstance().setControlValues(_entityID, _controlIndex, la::avdecc::entity::model::ControlValues{ std::move(values) },
[this, changedWidget](la::avdecc::UniqueIdentifier const /*entityID*/)
{
Expand Down Expand Up @@ -498,12 +634,12 @@ class UTF8ControlValuesDynamicTreeWidgetItem : public ControlValuesDynamicTreeWi
if (controlValues.size() != 1u)
{
// This should probably be detected by the AVDECC library
LOG_HIVE_WARN("ControlValues update not valid: Static/Dynamic count mismatch");
LOG_HIVE_WARN("ControlValues update not valid: Dynamic count is not equal to 1");
return;
}

auto const dynamicValues = controlValues.getValues<DynamicValueType>(); // We have to store the copy or it will go out of scope if using it directly in the range-based loop
auto const text = QString::fromUtf8(reinterpret_cast<char const*>(dynamicValues.currentValue.data()));
auto const& dynamicValue = controlValues.getValues<DynamicValueType>();
auto const text = QString::fromUtf8(reinterpret_cast<char const*>(dynamicValue.currentValue.data()));

if (_isReadOnly)
{
Expand Down
41 changes: 38 additions & 3 deletions src/nodeTreeWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1575,7 +1575,7 @@ class NodeTreeWidgetPrivate : public QObject, public NodeVisitor
la::avdecc::UniqueIdentifier _controlledEntityID{};
};

/** Linear Values */
/** Linear Values - Clause 7.3.5.2.1 */
template<class StaticValueType, class DynamicValueType>
class VisitControlLinearValues final : public NodeTreeWidgetPrivate::VisitControlValues
{
Expand Down Expand Up @@ -1609,7 +1609,26 @@ class VisitControlLinearValues final : public NodeTreeWidgetPrivate::VisitContro
}
};

/** Array Values */
/** Selector Values - Clause 7.3.5.2.2 */
template<typename SizeType, typename StaticValueType = la::avdecc::entity::model::SelectorValueStatic<SizeType>, typename DynamicValueType = la::avdecc::entity::model::SelectorValueDynamic<SizeType>>
class VisitControlSelectorValues final : public NodeTreeWidgetPrivate::VisitControlValues
{
virtual void visitStaticControlValues(NodeTreeWidgetPrivate* self, la::avdecc::controller::ControlledEntity const* const controlledEntity, QTreeWidgetItem* const item, la::avdecc::entity::model::ControlNodeStaticModel const& staticModel, la::avdecc::entity::model::ControlNodeDynamicModel const& /*dynamicModel*/) noexcept override
{
auto valNumber = decltype(std::declval<decltype(staticModel.values)>().size()){ 0u };
auto const& selectorValue = staticModel.values.getValues<StaticValueType>();

self->addTextItem(item, "Default Value", selectorValue.defaultValue);
self->addTextItem(item, "Unit Type", ::avdecc::helper::controlValueUnitToString(selectorValue.unit.getUnit()));
}
virtual void visitDynamicControlValues(QTreeWidget* const tree, la::avdecc::UniqueIdentifier const entityID, la::avdecc::entity::model::ControlIndex const controlIndex, la::avdecc::entity::model::ControlNodeStaticModel const& staticModel, la::avdecc::entity::model::ControlNodeDynamicModel const& dynamicModel) noexcept override
{
auto* dynamicItem = new SelectorControlValuesDynamicTreeWidgetItem<StaticValueType, DynamicValueType>(entityID, controlIndex, staticModel, dynamicModel, tree);
dynamicItem->setText(0, "Dynamic Info");
}
};

/** Array Values - Clause 7.3.5.2.3 */
template<typename SizeType, typename StaticValueType = la::avdecc::entity::model::ArrayValueStatic<SizeType>, typename DynamicValueType = la::avdecc::entity::model::ArrayValueDynamic<SizeType>>
class VisitControlArrayValues final : public NodeTreeWidgetPrivate::VisitControlValues
{
Expand All @@ -1634,7 +1653,7 @@ class VisitControlArrayValues final : public NodeTreeWidgetPrivate::VisitControl
}
};

/** UTF-8 String Value */
/** UTF-8 String Value - Clause 7.3.5.2.4 */
class VisitControlUtf8Values final : public NodeTreeWidgetPrivate::VisitControlValues
{
public:
Expand All @@ -1651,6 +1670,7 @@ class VisitControlUtf8Values final : public NodeTreeWidgetPrivate::VisitControlV

void NodeTreeWidgetPrivate::createControlValuesDispatchTable(VisitControlValuesDispatchTable& dispatchTable)
{
/** Linear Values - Clause 7.3.5.2.1 */
dispatchTable[la::avdecc::entity::model::ControlValueType::Type::ControlLinearInt8] = std::make_unique<VisitControlLinearValues<la::avdecc::entity::model::LinearValues<la::avdecc::entity::model::LinearValueStatic<std::int8_t>>, la::avdecc::entity::model::LinearValues<la::avdecc::entity::model::LinearValueDynamic<std::int8_t>>>>();
dispatchTable[la::avdecc::entity::model::ControlValueType::Type::ControlLinearUInt8] = std::make_unique<VisitControlLinearValues<la::avdecc::entity::model::LinearValues<la::avdecc::entity::model::LinearValueStatic<std::uint8_t>>, la::avdecc::entity::model::LinearValues<la::avdecc::entity::model::LinearValueDynamic<std::uint8_t>>>>();
dispatchTable[la::avdecc::entity::model::ControlValueType::Type::ControlLinearInt16] = std::make_unique<VisitControlLinearValues<la::avdecc::entity::model::LinearValues<la::avdecc::entity::model::LinearValueStatic<std::int16_t>>, la::avdecc::entity::model::LinearValues<la::avdecc::entity::model::LinearValueDynamic<std::int16_t>>>>();
Expand All @@ -1662,6 +1682,20 @@ void NodeTreeWidgetPrivate::createControlValuesDispatchTable(VisitControlValuesD
dispatchTable[la::avdecc::entity::model::ControlValueType::Type::ControlLinearFloat] = std::make_unique<VisitControlLinearValues<la::avdecc::entity::model::LinearValues<la::avdecc::entity::model::LinearValueStatic<float>>, la::avdecc::entity::model::LinearValues<la::avdecc::entity::model::LinearValueDynamic<float>>>>();
dispatchTable[la::avdecc::entity::model::ControlValueType::Type::ControlLinearDouble] = std::make_unique<VisitControlLinearValues<la::avdecc::entity::model::LinearValues<la::avdecc::entity::model::LinearValueStatic<double>>, la::avdecc::entity::model::LinearValues<la::avdecc::entity::model::LinearValueDynamic<double>>>>();

/** Selector Value - Clause 7.3.5.2.2 */
dispatchTable[la::avdecc::entity::model::ControlValueType::Type::ControlSelectorInt8] = std::make_unique<VisitControlSelectorValues<std::int8_t>>();
dispatchTable[la::avdecc::entity::model::ControlValueType::Type::ControlSelectorUInt8] = std::make_unique<VisitControlSelectorValues<std::uint8_t>>();
dispatchTable[la::avdecc::entity::model::ControlValueType::Type::ControlSelectorInt16] = std::make_unique<VisitControlSelectorValues<std::int16_t>>();
dispatchTable[la::avdecc::entity::model::ControlValueType::Type::ControlSelectorUInt16] = std::make_unique<VisitControlSelectorValues<std::uint16_t>>();
dispatchTable[la::avdecc::entity::model::ControlValueType::Type::ControlSelectorInt32] = std::make_unique<VisitControlSelectorValues<std::int32_t>>();
dispatchTable[la::avdecc::entity::model::ControlValueType::Type::ControlSelectorUInt32] = std::make_unique<VisitControlSelectorValues<std::uint32_t>>();
dispatchTable[la::avdecc::entity::model::ControlValueType::Type::ControlSelectorInt64] = std::make_unique<VisitControlSelectorValues<std::int64_t>>();
dispatchTable[la::avdecc::entity::model::ControlValueType::Type::ControlSelectorUInt64] = std::make_unique<VisitControlSelectorValues<std::uint64_t>>();
dispatchTable[la::avdecc::entity::model::ControlValueType::Type::ControlSelectorFloat] = std::make_unique<VisitControlSelectorValues<float>>();
dispatchTable[la::avdecc::entity::model::ControlValueType::Type::ControlSelectorDouble] = std::make_unique<VisitControlSelectorValues<double>>();
dispatchTable[la::avdecc::entity::model::ControlValueType::Type::ControlSelectorString] = std::make_unique<VisitControlSelectorValues<la::avdecc::entity::model::LocalizedStringReference>>();

/** Array Values - Clause 7.3.5.2.3 */
dispatchTable[la::avdecc::entity::model::ControlValueType::Type::ControlArrayInt8] = std::make_unique<VisitControlArrayValues<std::int8_t>>();
dispatchTable[la::avdecc::entity::model::ControlValueType::Type::ControlArrayUInt8] = std::make_unique<VisitControlArrayValues<std::uint8_t>>();
dispatchTable[la::avdecc::entity::model::ControlValueType::Type::ControlArrayInt16] = std::make_unique<VisitControlArrayValues<std::int16_t>>();
Expand All @@ -1673,6 +1707,7 @@ void NodeTreeWidgetPrivate::createControlValuesDispatchTable(VisitControlValuesD
dispatchTable[la::avdecc::entity::model::ControlValueType::Type::ControlArrayFloat] = std::make_unique<VisitControlArrayValues<float>>();
dispatchTable[la::avdecc::entity::model::ControlValueType::Type::ControlArrayDouble] = std::make_unique<VisitControlArrayValues<double>>();

/** UTF-8 String Value - Clause 7.3.5.2.4 */
dispatchTable[la::avdecc::entity::model::ControlValueType::Type::ControlUtf8] = std::make_unique<VisitControlUtf8Values>();
}

Expand Down

0 comments on commit 3675fff

Please sign in to comment.