Skip to content

Commit caff529

Browse files
python: add DMX bindings
1 parent 0e2314a commit caff529

File tree

1 file changed

+168
-15
lines changed

1 file changed

+168
-15
lines changed

lang/python/src/kvpp.h

Lines changed: 168 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,175 @@ inline void register_python(py::module_& m) {
1818
auto kvpp = m.def_submodule("kvpp");
1919
using namespace kvpp;
2020

21+
{
22+
auto DMXValue = kvpp.def_submodule("DMXValue");
23+
using namespace DMXValue;
24+
25+
py::class_<Element>(DMXValue, "Element")
26+
.def(py::init())
27+
.def_rw("index", &Element::index)
28+
.def_rw("external_guid", &Element::externalGUID);
29+
30+
py::class_<Time>(DMXValue, "Time")
31+
.def(py::init())
32+
.def_rw("seconds", &Time::seconds);
33+
34+
py::class_<Color>(DMXValue, "Color")
35+
.def(py::init())
36+
.def_rw("r", &Color::r)
37+
.def_rw("g", &Color::g)
38+
.def_rw("b", &Color::b)
39+
.def_rw("a", &Color::a);
40+
41+
py::class_<EulerAngles, sourcepp::math::EulerAngles>(DMXValue, "EulerAngles");
42+
43+
py::class_<Quaternion>(DMXValue, "Quaternion");
44+
45+
py::enum_<ID>(DMXValue, "ID")
46+
.value("INVALID", ID::INVALID)
47+
.value("VALUE_START", ID::VALUE_START)
48+
.value("ELEMENT", ID::ELEMENT)
49+
.value("INT32", ID::INT32)
50+
.value("FLOAT", ID::FLOAT)
51+
.value("BOOL", ID::BOOL)
52+
.value("STRING", ID::STRING)
53+
.value("BYTEARRAY", ID::BYTEARRAY)
54+
.value("TIME", ID::TIME)
55+
.value("COLOR", ID::COLOR)
56+
.value("VECTOR2", ID::VECTOR2)
57+
.value("VECTOR3", ID::VECTOR3)
58+
.value("VECTOR4", ID::VECTOR4)
59+
.value("EULER_ANGLES", ID::EULER_ANGLES)
60+
.value("QUATERNION", ID::QUATERNION)
61+
.value("MATRIX_4X4", ID::MATRIX_4X4)
62+
.value("VALUE_END", ID::VALUE_END)
63+
.value("ARRAY_START", ID::ARRAY_START)
64+
.value("ARRAY_ELEMENT", ID::ARRAY_ELEMENT)
65+
.value("ARRAY_INT32", ID::ARRAY_INT32)
66+
.value("ARRAY_FLOAT", ID::ARRAY_FLOAT)
67+
.value("ARRAY_BOOL", ID::ARRAY_BOOL)
68+
.value("ARRAY_STRING", ID::ARRAY_STRING)
69+
.value("ARRAY_BYTEARRAY", ID::ARRAY_BYTEARRAY)
70+
.value("ARRAY_TIME", ID::ARRAY_TIME)
71+
.value("ARRAY_COLOR", ID::ARRAY_COLOR)
72+
.value("ARRAY_VECTOR2", ID::ARRAY_VECTOR2)
73+
.value("ARRAY_VECTOR3", ID::ARRAY_VECTOR3)
74+
.value("ARRAY_VECTOR4", ID::ARRAY_VECTOR4)
75+
.value("ARRAY_EULER_ANGLES", ID::ARRAY_EULER_ANGLES)
76+
.value("ARRAY_QUATERNION", ID::ARRAY_QUATERNION)
77+
.value("ARRAY_MATRIX_4X4", ID::ARRAY_MATRIX_4X4)
78+
.value("ARRAY_END", ID::ARRAY_END);
79+
80+
DMXValue.def("array_id_to_inner_id", &arrayIDToInnerID, "id"_a);
81+
82+
DMXValue.def("inner_id_to_array_id", &innerIDToArrayID, "id"_a);
83+
84+
DMXValue.def("id_to_string", &IDToString, "id"_a);
85+
86+
DMXValue.def("string_to_id", &stringToID, "id"_a);
87+
}
88+
89+
py::class_<DMXAttribute>(kvpp, "DMXAttribute")
90+
.def("is_invalid", &DMXAttribute::isInvalid)
91+
.def("__bool__", &DMXAttribute::operator bool)
92+
.def_prop_rw("key", &DMXAttribute::getKey, &DMXAttribute::setKey)
93+
.def_prop_ro("value_type", &DMXAttribute::getValueType)
94+
.def("is_value_array", &DMXAttribute::isValueArray)
95+
.def_prop_rw("value", [](const DMXAttribute& self) {
96+
return self.getValue();
97+
}, [](DMXAttribute& self, DMXValue::Generic value) {
98+
self.setValue(std::move(value));
99+
})
100+
.def("get_value_string", &DMXAttribute::getValueString);
101+
102+
py::class_<DMXElement>(kvpp, "DMXElement")
103+
.def("__bool__", &DMXElement::operator bool)
104+
.def_prop_rw("type", &DMXElement::getType, &DMXElement::setType)
105+
.def_prop_rw("key", &DMXElement::getKey, &DMXElement::setKey)
106+
.def_prop_rw("guid", &DMXElement::getGUID, &DMXElement::setGUID)
107+
.def("has_attribute", &DMXElement::hasAttribute, "attribute_key"_a)
108+
.def("__contains__", &DMXElement::hasAttribute, "attribute_key"_a)
109+
.def("add_attribute", &DMXElement::addAttribute, "key"_a, "value"_a = DMXValue::Generic{}, py::rv_policy::reference_internal)
110+
.def("get_attribute_count", py::overload_cast<>(&DMXElement::getAttributeCount, py::const_))
111+
.def("__len__", py::overload_cast<>(&DMXElement::getAttributeCount, py::const_))
112+
.def("get_attribute_count_with_key", py::overload_cast<std::string_view>(&DMXElement::getAttributeCount, py::const_))
113+
.def("__iter__", [](const DMXElement& self) {
114+
return py::make_iterator(py::type<DMXElement>(), "iterator", self);
115+
}, py::keep_alive<0, 1>())
116+
.def("__getitem__", py::overload_cast<unsigned int>(&DMXElement::operator[]), "n"_a, py::rv_policy::reference_internal)
117+
.def("__getitem__", py::overload_cast<std::string_view>(&DMXElement::operator[]), "attribute_key"_a, py::rv_policy::reference_internal)
118+
.def("get_child", py::overload_cast<std::string_view, unsigned int>(&DMXElement::operator()), "attribute_key"_a, "n"_a, py::rv_policy::reference_internal)
119+
.def("remove_child", py::overload_cast<unsigned int>(&DMXElement::removeAttribute), "n"_a)
120+
.def("__delitem__", py::overload_cast<unsigned int>(&DMXElement::removeAttribute), "n"_a)
121+
.def("remove_child", py::overload_cast<std::string_view, int>(&DMXElement::removeAttribute), "attribute_key"_a, "n"_a = -1)
122+
.def("get_invalid_attribute", &DMXElement::getInvalidAttribute);
123+
124+
auto cDMX = py::class_<DMX>(kvpp, "DMX");
125+
126+
py::enum_<DMX::Encoding>(cDMX, "Encoding")
127+
.value("INVALID", DMX::ENCODING_INVALID)
128+
.value("BINARY_OLD", DMX::ENCODING_BINARY_OLD)
129+
.value("BINARY_OLD_SFM", DMX::ENCODING_BINARY_OLD_SFM)
130+
.value("BINARY", DMX::ENCODING_BINARY)
131+
.value("BINARY_UTF8", DMX::ENCODING_BINARY_UTF8)
132+
.value("KEYVALUES2_OLD", DMX::ENCODING_KEYVALUES2_OLD)
133+
.value("KEYVALUES2", DMX::ENCODING_KEYVALUES2)
134+
.value("KEYVALUES2_UTF8", DMX::ENCODING_KEYVALUES2_UTF8)
135+
.value("KEYVALUES2_FLAT_OLD", DMX::ENCODING_KEYVALUES2_FLAT_OLD)
136+
.value("KEYVALUES2_FLAT", DMX::ENCODING_KEYVALUES2_FLAT)
137+
.value("KEYVALUES2_NOGUIDS", DMX::ENCODING_KEYVALUES2_NOGUIDS);
138+
139+
cDMX
140+
.def(py::init<DMX::Encoding, int, std::string, int>(), "encoding_type"_a, "encoding_version"_a, "format_type"_a, "format_version"_a)
141+
.def("__init__", [](DMX* self, const py::bytes& dmxData) {
142+
return new(self) DMX{std::span{static_cast<const std::byte*>(dmxData.data()), dmxData.size()}};
143+
}, "dmx_data"_a)
144+
.def(py::init<std::string_view>(), "dmx_data"_a)
145+
.def("__bool__", &DMX::operator bool)
146+
.def_prop_rw("encoding_type", &DMX::getEncodingType, &DMX::setEncodingType)
147+
.def_prop_rw("encoding_version", &DMX::getEncodingVersion, &DMX::setEncodingVersion)
148+
.def_prop_rw("format_type", &DMX::getFormatType, &DMX::setFormatType)
149+
.def_prop_rw("format_version", &DMX::getFormatVersion, &DMX::setFormatVersion)
150+
.def("has_element", &DMX::hasElement, "key"_a)
151+
.def("__contains__", &DMX::hasElement, "key"_a)
152+
.def("add_element", &DMX::addElement, "type"_a, "key"_a)
153+
.def("get_element_count", py::overload_cast<>(&DMX::getElementCount, py::const_))
154+
.def("__len__", py::overload_cast<>(&DMX::getElementCount, py::const_))
155+
.def("get_element_count_with_key", py::overload_cast<std::string_view>(&DMX::getElementCount, py::const_), "key"_a)
156+
.def("__iter__", [](const DMX& self) {
157+
return py::make_iterator(py::type<DMX>(), "iterator", self);
158+
}, py::keep_alive<0, 1>())
159+
.def("__getitem__", py::overload_cast<unsigned int>(&DMX::operator[]), "n"_a, py::rv_policy::reference_internal)
160+
.def("__getitem__", py::overload_cast<std::string_view>(&DMX::operator[]), "key"_a, py::rv_policy::reference_internal)
161+
.def("get_child", py::overload_cast<std::string_view, unsigned int>(&DMX::operator()), "key"_a, "n"_a, py::rv_policy::reference_internal)
162+
.def("remove_child", py::overload_cast<unsigned int>(&DMX::removeElement), "n"_a)
163+
.def("__delitem__", py::overload_cast<unsigned int>(&DMX::removeElement), "n"_a)
164+
.def("bake", [](const DMX& self) {
165+
const auto d = self.bake();
166+
return py::bytes{d.data(), d.size()};
167+
})
168+
.def("bake_to_file", py::overload_cast<const std::string&>(&DMX::bake, py::const_), "dmx_path"_a)
169+
.def_static("is_encoding_version_valid", &DMX::isEncodingVersionValid, "encoding_type"_a, "encoding_version"_a)
170+
.def_static("create_random_guid", &DMX::createRandomGUID)
171+
.def_static("get_invalid_element", &DMX::getInvalidElement);
172+
21173
py::class_<KV1ElementReadable<>>(kvpp, "KV1ElementReadable")
22174
.def_prop_ro("key", &KV1ElementReadable<>::getKey)
23175
.def_prop_ro("value", [](const KV1ElementReadable<>& self) {
24176
return self.getValue();
25177
})
26178
.def_prop_ro("conditional", &KV1ElementReadable<>::getConditional)
27179
.def("has_child", &KV1ElementReadable<>::hasChild, "child_key"_a)
180+
.def("__contains__", &KV1ElementReadable<>::hasChild, "child_key"_a)
28181
.def_prop_ro("child_count", py::overload_cast<>(&KV1ElementReadable<>::getChildCount, py::const_))
29182
.def("__len__", py::overload_cast<>(&KV1ElementReadable<>::getChildCount, py::const_))
30183
.def("get_child_count_with_key", py::overload_cast<std::string_view>(&KV1ElementReadable<>::getChildCount, py::const_), "child_key"_a)
31184
.def("__iter__", [](const KV1ElementReadable<>& self) {
32185
return py::make_iterator(py::type<KV1ElementReadable<>>(), "iterator", self);
33186
}, py::keep_alive<0, 1>())
34-
.def("__getitem__", py::overload_cast<unsigned int>(&KV1ElementReadable<>::operator[], py::const_), "n"_a)
35-
.def("__getitem__", py::overload_cast<std::string_view>(&KV1ElementReadable<>::operator[], py::const_), "child_key"_a)
36-
.def("get_child", py::overload_cast<std::string_view, unsigned int>(&KV1ElementReadable<>::operator(), py::const_), "child_key"_a, "n"_a)
187+
.def("__getitem__", py::overload_cast<unsigned int>(&KV1ElementReadable<>::operator[], py::const_), "n"_a, py::rv_policy::reference_internal)
188+
.def("__getitem__", py::overload_cast<std::string_view>(&KV1ElementReadable<>::operator[], py::const_), "child_key"_a, py::rv_policy::reference_internal)
189+
.def("get_child", py::overload_cast<std::string_view, unsigned int>(&KV1ElementReadable<>::operator(), py::const_), "child_key"_a, "n"_a, py::rv_policy::reference_internal)
37190
.def("is_invalid", &KV1ElementReadable<>::isInvalid)
38191
.def("get_invalid", &KV1ElementReadable<>::getInvalid)
39192
.def("__bool__", &KV1ElementReadable<>::operator bool);
@@ -48,20 +201,20 @@ inline void register_python(py::module_& m) {
48201
}, &KV1ElementWritable<>::setValue<std::string_view>)
49202
.def_prop_rw("conditional", &KV1ElementWritable<>::getConditional, &KV1ElementWritable<>::setConditional)
50203
.def("has_child", &KV1ElementWritable<>::hasChild, "child_key"_a)
51-
.def("add_child", &KV1ElementWritable<>::addChild<>, "key"_a, "value"_a = "", "conditional"_a = "")
204+
.def("__contains__", &KV1ElementWritable<>::hasChild, "child_key"_a)
205+
.def("add_child", &KV1ElementWritable<>::addChild<>, "key"_a, "value"_a = "", "conditional"_a = "", py::rv_policy::reference_internal)
52206
.def_prop_ro("child_count", py::overload_cast<>(&KV1ElementWritable<>::getChildCount, py::const_))
53207
.def("__len__", py::overload_cast<>(&KV1ElementWritable<>::getChildCount, py::const_))
54208
.def("get_child_count_with_key", py::overload_cast<std::string_view>(&KV1ElementWritable<>::getChildCount, py::const_), "child_key"_a)
55209
.def("__iter__", [](const KV1ElementWritable<>& self) {
56210
return py::make_iterator(py::type<KV1ElementWritable<>>(), "iterator", self);
57211
}, py::keep_alive<0, 1>())
58-
.def("__getitem__", py::overload_cast<unsigned int>(&KV1ElementWritable<>::operator[]), "n"_a)
59-
.def("__getitem__", py::overload_cast<std::string_view>(&KV1ElementWritable<>::operator[]), "child_key"_a)
60-
.def("get_child", py::overload_cast<std::string_view, unsigned int>(&KV1ElementWritable<>::operator()), "child_key"_a, "n"_a)
212+
.def("__getitem__", py::overload_cast<unsigned int>(&KV1ElementWritable<>::operator[]), "n"_a, py::rv_policy::reference_internal)
213+
.def("__getitem__", py::overload_cast<std::string_view>(&KV1ElementWritable<>::operator[]), "child_key"_a, py::rv_policy::reference_internal)
214+
.def("get_child", py::overload_cast<std::string_view, unsigned int>(&KV1ElementWritable<>::operator()), "child_key"_a, "n"_a, py::rv_policy::reference_internal)
61215
.def("remove_child", py::overload_cast<unsigned int>(&KV1ElementWritable<>::removeChild), "n"_a)
62216
.def("__delitem__", py::overload_cast<unsigned int>(&KV1ElementWritable<>::removeChild), "n"_a)
63217
.def("remove_child", py::overload_cast<std::string_view, int>(&KV1ElementWritable<>::removeChild), "child_key"_a, "n"_a = -1)
64-
.def("__delitem__", py::overload_cast<std::string_view, int>(&KV1ElementWritable<>::removeChild), "child_key"_a, "n"_a = -1)
65218
.def("is_invalid", &KV1ElementWritable<>::isInvalid)
66219
.def("get_invalid", &KV1ElementWritable<>::getInvalid)
67220
.def("__bool__", &KV1ElementWritable<>::operator bool);
@@ -91,22 +244,22 @@ inline void register_python(py::module_& m) {
91244
self.setValue(std::move(value));
92245
})
93246
.def("has_child", &KV1BinaryElement::hasChild, "child_key"_a)
94-
.def("add_child", [](KV1BinaryElement& self, std::string_view key, KV1BinaryValue value = {}) {
95-
self.addChild(key, std::move(value));
96-
}, "key"_a, "value"_a = KV1BinaryValue{})
247+
.def("__contains__", &KV1BinaryElement::hasChild, "child_key"_a)
248+
.def("add_child", [](KV1BinaryElement& self, std::string_view key, KV1BinaryValue value = {}) -> KV1BinaryElement& {
249+
return self.addChild(key, std::move(value));
250+
}, "key"_a, "value"_a = KV1BinaryValue{}, py::rv_policy::reference_internal)
97251
.def_prop_ro("child_count", py::overload_cast<>(&KV1BinaryElement::getChildCount, py::const_))
98252
.def("__len__", py::overload_cast<>(&KV1BinaryElement::getChildCount, py::const_))
99253
.def("get_child_count_with_key", py::overload_cast<std::string_view>(&KV1BinaryElement::getChildCount, py::const_), "child_key"_a)
100254
.def("__iter__", [](const KV1BinaryElement& self) {
101255
return py::make_iterator(py::type<KV1BinaryElement>(), "iterator", self);
102256
}, py::keep_alive<0, 1>())
103-
.def("__getitem__", py::overload_cast<unsigned int>(&KV1BinaryElement::operator[]), "n"_a)
104-
.def("__getitem__", py::overload_cast<std::string_view>(&KV1BinaryElement::operator[]), "child_key"_a)
105-
.def("get_child", py::overload_cast<std::string_view, unsigned int>(&KV1BinaryElement::operator()), "child_key"_a, "n"_a)
257+
.def("__getitem__", py::overload_cast<unsigned int>(&KV1BinaryElement::operator[]), "n"_a, py::rv_policy::reference_internal)
258+
.def("__getitem__", py::overload_cast<std::string_view>(&KV1BinaryElement::operator[]), "child_key"_a, py::rv_policy::reference_internal)
259+
.def("get_child", py::overload_cast<std::string_view, unsigned int>(&KV1BinaryElement::operator()), "child_key"_a, "n"_a, py::rv_policy::reference_internal)
106260
.def("remove_child", py::overload_cast<unsigned int>(&KV1BinaryElement::removeChild), "n"_a)
107261
.def("__delitem__", py::overload_cast<unsigned int>(&KV1BinaryElement::removeChild), "n"_a)
108262
.def("remove_child", py::overload_cast<std::string_view, int>(&KV1BinaryElement::removeChild), "child_key"_a, "n"_a = -1)
109-
.def("__delitem__", py::overload_cast<std::string_view, int>(&KV1BinaryElement::removeChild), "child_key"_a, "n"_a = -1)
110263
.def("is_invalid", &KV1BinaryElement::isInvalid)
111264
.def("get_invalid", &KV1BinaryElement::getInvalid)
112265
.def("__bool__", &KV1BinaryElement::operator bool);

0 commit comments

Comments
 (0)