Skip to content

Commit f74c1b8

Browse files
hodoulpmichdolan
andauthored
Port from main to RB-2.0 - Add virtual display python bindings (#1464) (#1611)
* Add virtual display python bindings (#1464) * Add virtual display python bindings Signed-off-by: Michael Dolan <[email protected]> * Add virtual display test, missing methods Signed-off-by: Michael Dolan <[email protected]> * Fix the Config Python binding Signed-off-by: Patrick Hodoul <[email protected]> Co-authored-by: Michael Dolan <[email protected]>
1 parent 14f13c8 commit f74c1b8

File tree

2 files changed

+247
-4
lines changed

2 files changed

+247
-4
lines changed

src/bindings/python/PyConfig.cpp

Lines changed: 145 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@ enum ConfigIterator
3333
IT_NAMED_TRANSFORM_NAME,
3434
IT_NAMED_TRANSFORM,
3535
IT_ACTIVE_NAMED_TRANSFORM_NAME,
36-
IT_ACTIVE_NAMED_TRANSFORM
36+
IT_ACTIVE_NAMED_TRANSFORM,
37+
IT_DISPLAY_ALL,
38+
IT_DISPLAY_VIEW_TYPE,
39+
IT_VIRTUAL_DISPLAY_VIEW,
3740
};
3841

3942
using EnvironmentVarNameIterator = PyIterator<ConfigRcPtr, IT_ENVIRONMENT_VAR_NAME>;
@@ -45,16 +48,21 @@ using ColorSpaceNameIterator = PyIterator<ConfigRcPtr,
4548
using ColorSpaceIterator = PyIterator<ConfigRcPtr,
4649
IT_COLOR_SPACE,
4750
SearchReferenceSpaceType,
48-
ColorSpaceVisibility>;
51+
ColorSpaceVisibility>;
4952
using ActiveColorSpaceNameIterator = PyIterator<ConfigRcPtr, IT_ACTIVE_COLOR_SPACE_NAME>;
5053
using ActiveColorSpaceIterator = PyIterator<ConfigRcPtr, IT_ACTIVE_COLOR_SPACE>;
5154
using RoleNameIterator = PyIterator<ConfigRcPtr, IT_ROLE_NAME>;
5255
using RoleColorSpaceIterator = PyIterator<ConfigRcPtr, IT_ROLE_COLOR_SPACE>;
5356
using DisplayIterator = PyIterator<ConfigRcPtr, IT_DISPLAY>;
57+
using DisplayAllIterator = PyIterator<ConfigRcPtr, IT_DISPLAY_ALL>;
5458
using SharedViewIterator = PyIterator<ConfigRcPtr, IT_SHARED_VIEW>;
59+
using VirtualViewIterator = PyIterator<ConfigRcPtr, IT_VIRTUAL_DISPLAY_VIEW,
60+
ViewType>;
5561
using ViewIterator = PyIterator<ConfigRcPtr, IT_DISPLAY_VIEW, std::string>;
5662
using ViewForColorSpaceIterator = PyIterator<ConfigRcPtr, IT_DISPLAY_VIEW_COLORSPACE,
5763
std::string, std::string>;
64+
using ViewForViewTypeIterator = PyIterator<ConfigRcPtr, IT_DISPLAY_VIEW_TYPE,
65+
ViewType, std::string>;
5866
using LookNameIterator = PyIterator<ConfigRcPtr, IT_LOOK_NAME>;
5967
using LookIterator = PyIterator<ConfigRcPtr, IT_LOOK>;
6068
using ViewTransformNameIterator = PyIterator<ConfigRcPtr, IT_VIEW_TRANSFORM_NAME>;
@@ -110,10 +118,18 @@ void bindPyConfig(py::module & m)
110118
py::class_<DisplayIterator>(
111119
clsConfig, "DisplayIterator");
112120

121+
auto clsDisplayAllIterator =
122+
py::class_<DisplayAllIterator>(
123+
clsConfig, "DisplayAllIterator");
124+
113125
auto clsSharedViewIterator =
114126
py::class_<SharedViewIterator>(
115127
clsConfig, "SharedViewIterator");
116128

129+
auto clsVirtualViewIterator =
130+
py::class_<VirtualViewIterator>(
131+
clsConfig, "VirtualViewIterator");
132+
117133
auto clsViewIterator =
118134
py::class_<ViewIterator>(
119135
clsConfig, "ViewIterator");
@@ -122,6 +138,10 @@ void bindPyConfig(py::module & m)
122138
py::class_<ViewForColorSpaceIterator>(
123139
clsConfig, "ViewForColorSpaceIterator");
124140

141+
auto clsViewForViewTypeIterator =
142+
py::class_<ViewForViewTypeIterator>(
143+
clsConfig, "ViewForViewTypeIterator");
144+
125145
auto clsLookNameIterator =
126146
py::class_<LookNameIterator>(
127147
clsConfig, "LookNameIterator");
@@ -342,13 +362,24 @@ void bindPyConfig(py::module & m)
342362
{
343363
return DisplayIterator(self);
344364
})
345-
.def("getDefaultView", &Config::getDefaultView, "display"_a,
365+
.def("getDisplaysAll", [](ConfigRcPtr & self)
366+
{
367+
return DisplayAllIterator(self);
368+
})
369+
.def("getDefaultView",
370+
(const char * (Config::*)(const char *) const)
371+
&Config::getDefaultView, "display"_a,
346372
DOC(Config, getDefaultView))
347373
.def("getViews", [](ConfigRcPtr & self, const std::string & display)
348374
{
349375
return ViewIterator(self, display);
350376
},
351377
"display"_a)
378+
.def("getViews", [](ConfigRcPtr & self, ViewType type, const std::string & display)
379+
{
380+
return ViewForViewTypeIterator(self, type, display);
381+
},
382+
"type"_a, "display"_a)
352383
.def("getViews", [](ConfigRcPtr & self,
353384
const std::string & display,
354385
const std::string & colorSpaceName)
@@ -394,6 +425,59 @@ void bindPyConfig(py::module & m)
394425
DOC(Config, removeDisplayView))
395426
.def("clearDisplays", &Config::clearDisplays,
396427
DOC(Config, clearDisplays))
428+
429+
// Virtual Display
430+
.def("addVirtualDisplayView", &Config::addVirtualDisplayView,
431+
"view"_a, "viewTransformName"_a, "colorSpaceName"_a,
432+
"looks"_a = "",
433+
"ruleName"_a = "",
434+
"description"_a = "",
435+
DOC(Config, addVirtualDisplayView))
436+
.def("addVirtualDisplaySharedView", &Config::addVirtualDisplaySharedView, "sharedView"_a,
437+
DOC(Config, addVirtualDisplaySharedView))
438+
.def("getVirtualDisplayViews", [](ConfigRcPtr & self, ViewType type)
439+
{
440+
return VirtualViewIterator(self, type);
441+
},
442+
"display"_a)
443+
.def("getVirtualDisplayViewTransformName", &Config::getVirtualDisplayViewTransformName,
444+
"view"_a,
445+
DOC(Config, getVirtualDisplayViewTransformName))
446+
.def("getVirtualDisplayViewColorSpaceName", &Config::getVirtualDisplayViewColorSpaceName,
447+
"view"_a,
448+
DOC(Config, getVirtualDisplayViewColorSpaceName))
449+
.def("getVirtualDisplayViewLooks", &Config::getVirtualDisplayViewLooks, "view"_a,
450+
DOC(Config, getVirtualDisplayViewLooks))
451+
.def("getVirtualDisplayViewRule", &Config::getVirtualDisplayViewRule, "view"_a,
452+
DOC(Config, getVirtualDisplayViewRule))
453+
.def("getVirtualDisplayViewDescription", &Config::getVirtualDisplayViewDescription,
454+
"view"_a,
455+
DOC(Config, getVirtualDisplayViewDescription))
456+
.def("removeVirtualDisplayView", &Config::removeVirtualDisplayView, "view"_a,
457+
DOC(Config, removeVirtualDisplayView))
458+
.def("clearVirtualDisplay", &Config::clearVirtualDisplay,
459+
DOC(Config, clearVirtualDisplay))
460+
.def("instantiateDisplayFromMonitorName", &Config::instantiateDisplayFromMonitorName,
461+
"monitorName"_a,
462+
DOC(Config, instantiateDisplayFromMonitorName))
463+
.def("instantiateDisplayFromICCProfile", &Config::instantiateDisplayFromICCProfile,
464+
"ICCProfileFilepath"_a,
465+
DOC(Config, instantiateDisplayFromICCProfile))
466+
.def("isDisplayTemporary", [](ConfigRcPtr & self, const std::string & display) -> bool
467+
{
468+
for (int i = 0; i < self->getNumDisplaysAll(); i++)
469+
{
470+
std::string other(self->getDisplayAll(i));
471+
if (StringUtils::Compare(display, other))
472+
{
473+
return self->isDisplayTemporary(i);
474+
}
475+
}
476+
return false;
477+
},
478+
"display"_a)
479+
480+
// Active Displays and Views
397481
.def("setActiveDisplays", &Config::setActiveDisplays, "displays"_a,
398482
DOC(Config, setActiveDisplays))
399483
.def("getActiveDisplays", &Config::getActiveDisplays,
@@ -844,6 +928,20 @@ void bindPyConfig(py::module & m)
844928
return it.m_obj->getDisplay(i);
845929
});
846930

931+
clsDisplayAllIterator
932+
.def("__len__", [](DisplayAllIterator & it) { return it.m_obj->getNumDisplaysAll(); })
933+
.def("__getitem__", [](DisplayAllIterator & it, int i)
934+
{
935+
it.checkIndex(i, it.m_obj->getNumDisplaysAll());
936+
return it.m_obj->getDisplayAll(i);
937+
})
938+
.def("__iter__", [](DisplayAllIterator & it) -> DisplayAllIterator & { return it; })
939+
.def("__next__", [](DisplayAllIterator & it)
940+
{
941+
int i = it.nextIndex(it.m_obj->getNumDisplaysAll());
942+
return it.m_obj->getDisplayAll(i);
943+
});
944+
847945
clsSharedViewIterator
848946
.def("__len__", [](SharedViewIterator & it) { return it.m_obj->getNumViews(VIEW_SHARED,
849947
nullptr); })
@@ -859,6 +957,23 @@ void bindPyConfig(py::module & m)
859957
return it.m_obj->getView(VIEW_SHARED, nullptr, i);
860958
});
861959

960+
clsVirtualViewIterator
961+
.def("__len__", [](VirtualViewIterator & it)
962+
{
963+
return it.m_obj->getVirtualDisplayNumViews(std::get<0>(it.m_args));
964+
})
965+
.def("__getitem__", [](VirtualViewIterator & it, int i)
966+
{
967+
it.checkIndex(i, it.m_obj->getVirtualDisplayNumViews(std::get<0>(it.m_args)));
968+
return it.m_obj->getVirtualDisplayView(std::get<0>(it.m_args), i);
969+
})
970+
.def("__iter__", [](VirtualViewIterator & it) -> VirtualViewIterator & { return it; })
971+
.def("__next__", [](VirtualViewIterator & it)
972+
{
973+
int i = it.nextIndex(it.m_obj->getVirtualDisplayNumViews(std::get<0>(it.m_args)));
974+
return it.m_obj->getVirtualDisplayView(std::get<0>(it.m_args), i);
975+
});
976+
862977
clsViewIterator
863978
.def("__len__", [](ViewIterator & it)
864979
{ return it.m_obj->getNumViews(std::get<0>(it.m_args).c_str()); })
@@ -885,7 +1000,10 @@ void bindPyConfig(py::module & m)
8851000
return it.m_obj->getView(std::get<0>(it.m_args).c_str(),
8861001
std::get<1>(it.m_args).c_str(), i);
8871002
})
888-
.def("__iter__", [](ViewForColorSpaceIterator & it) -> ViewForColorSpaceIterator & { return it; })
1003+
.def("__iter__", [](ViewForColorSpaceIterator & it) -> ViewForColorSpaceIterator &
1004+
{
1005+
return it;
1006+
})
8891007
.def("__next__", [](ViewForColorSpaceIterator & it)
8901008
{
8911009
int i = it.nextIndex(it.m_obj->getNumViews(std::get<0>(it.m_args).c_str(),
@@ -894,6 +1012,29 @@ void bindPyConfig(py::module & m)
8941012
std::get<1>(it.m_args).c_str(), i);
8951013
});
8961014

1015+
clsViewForViewTypeIterator
1016+
.def("__len__", [](ViewForViewTypeIterator & it)
1017+
{ return it.m_obj->getNumViews(std::get<0>(it.m_args),
1018+
std::get<1>(it.m_args).c_str()); })
1019+
.def("__getitem__", [](ViewForViewTypeIterator & it, int i)
1020+
{
1021+
it.checkIndex(i, it.m_obj->getNumViews(std::get<0>(it.m_args),
1022+
std::get<1>(it.m_args).c_str()));
1023+
return it.m_obj->getView(std::get<0>(it.m_args),
1024+
std::get<1>(it.m_args).c_str(), i);
1025+
})
1026+
.def("__iter__", [](ViewForViewTypeIterator & it) -> ViewForViewTypeIterator &
1027+
{
1028+
return it;
1029+
})
1030+
.def("__next__", [](ViewForViewTypeIterator & it)
1031+
{
1032+
int i = it.nextIndex(it.m_obj->getNumViews(std::get<0>(it.m_args),
1033+
std::get<1>(it.m_args).c_str()));
1034+
return it.m_obj->getView(std::get<0>(it.m_args),
1035+
std::get<1>(it.m_args).c_str(), i);
1036+
});
1037+
8971038
clsLookNameIterator
8981039
.def("__len__", [](LookNameIterator & it) { return it.m_obj->getNumLooks(); })
8991040
.def("__getitem__", [](LookNameIterator & it, int i)

tests/python/ConfigTest.py

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -751,3 +751,105 @@ def test_canonical_name(self):
751751
self.assertEqual(cfg.getCanonicalName('NT1'), 'nt1')
752752
self.assertEqual(cfg.getCanonicalName('Alias1'), 'nt1')
753753
self.assertEqual(cfg.getCanonicalName('Test1'), 'nt1')
754+
755+
def test_virtual_display(self):
756+
# Test platform agnostic virtual display interface.
757+
758+
cfg = OCIO.Config().CreateRaw()
759+
cfg.addColorSpace(
760+
OCIO.ColorSpace(OCIO.REFERENCE_SPACE_DISPLAY,
761+
"display_cs",
762+
toReference=OCIO.CDLTransform(sat=1.5)))
763+
cfg.addColorSpace(
764+
OCIO.ColorSpace(OCIO.REFERENCE_SPACE_SCENE,
765+
"raw",
766+
isData=True))
767+
cfg.addViewTransform(
768+
OCIO.ViewTransform(OCIO.REFERENCE_SPACE_SCENE,
769+
"default_vt",
770+
toReference=OCIO.CDLTransform(sat=1.5)))
771+
cfg.addViewTransform(
772+
OCIO.ViewTransform(OCIO.REFERENCE_SPACE_DISPLAY,
773+
"display_vt",
774+
toReference=OCIO.CDLTransform(sat=1.5)))
775+
cfg.addDisplayView("sRGB", "Raw", "raw")
776+
cfg.addDisplayView("sRGB", "view",
777+
viewTransform="display_vt",
778+
displayColorSpaceName="display_cs")
779+
cfg.addSharedView("sview1", "", "raw")
780+
cfg.addSharedView("sview2", "", "raw")
781+
cfg.addDisplaySharedView("sRGB", "sview1")
782+
783+
# Add virtual display and views
784+
cfg.addVirtualDisplayView("Raw", "", "raw")
785+
cfg.addVirtualDisplayView("Film", "display_vt",
786+
OCIO.OCIO_VIEW_USE_DISPLAY_NAME)
787+
cfg.addVirtualDisplaySharedView("sview2")
788+
789+
# Some basic checks
790+
self.assertEqual(3, len(cfg.getViews("sRGB")))
791+
self.assertEqual(2, len(cfg.getViews(OCIO.VIEW_DISPLAY_DEFINED,
792+
"sRGB")))
793+
self.assertEqual(1, len(cfg.getViews(OCIO.VIEW_SHARED, "sRGB")))
794+
795+
# Validate the virtual display information
796+
self.assertEqual(
797+
2,
798+
len(cfg.getVirtualDisplayViews(OCIO.VIEW_DISPLAY_DEFINED)))
799+
800+
view_name = cfg.getVirtualDisplayViews(OCIO.VIEW_DISPLAY_DEFINED)[0]
801+
self.assertEqual("Raw", view_name)
802+
self.assertEqual("", cfg.getVirtualDisplayViewTransformName(view_name))
803+
self.assertEqual("raw",
804+
cfg.getVirtualDisplayViewColorSpaceName(view_name))
805+
self.assertEqual("", cfg.getVirtualDisplayViewLooks(view_name))
806+
self.assertEqual("", cfg.getVirtualDisplayViewRule(view_name))
807+
self.assertEqual("", cfg.getVirtualDisplayViewDescription(view_name))
808+
809+
view_name = cfg.getVirtualDisplayViews(OCIO.VIEW_DISPLAY_DEFINED)[1]
810+
self.assertEqual("Film", view_name)
811+
self.assertEqual("display_vt",
812+
cfg.getVirtualDisplayViewTransformName(view_name))
813+
self.assertEqual(OCIO.OCIO_VIEW_USE_DISPLAY_NAME,
814+
cfg.getVirtualDisplayViewColorSpaceName(view_name))
815+
self.assertEqual("", cfg.getVirtualDisplayViewLooks(view_name))
816+
self.assertEqual("", cfg.getVirtualDisplayViewRule(view_name))
817+
self.assertEqual("", cfg.getVirtualDisplayViewDescription(view_name))
818+
819+
self.assertEqual(1, len(cfg.getVirtualDisplayViews(OCIO.VIEW_SHARED)))
820+
self.assertEqual("sview2",
821+
cfg.getVirtualDisplayViews(OCIO.VIEW_SHARED)[0])
822+
823+
# Remove a view from the virtual display
824+
cfg.removeVirtualDisplayView("Raw")
825+
826+
self.assertEqual(
827+
1,
828+
len(cfg.getVirtualDisplayViews(OCIO.VIEW_DISPLAY_DEFINED)))
829+
self.assertEqual(
830+
"Film",
831+
cfg.getVirtualDisplayViews(OCIO.VIEW_DISPLAY_DEFINED)[0])
832+
833+
self.assertEqual(1, len(cfg.getVirtualDisplayViews(OCIO.VIEW_SHARED)))
834+
self.assertEqual("sview2",
835+
cfg.getVirtualDisplayViews(OCIO.VIEW_SHARED)[0])
836+
837+
# Remove a shared view from the virtual display
838+
cfg.removeVirtualDisplayView("sview2")
839+
self.assertEqual(
840+
1,
841+
len(cfg.getVirtualDisplayViews(OCIO.VIEW_DISPLAY_DEFINED)))
842+
self.assertEqual(0, len(cfg.getVirtualDisplayViews(OCIO.VIEW_SHARED)))
843+
844+
cfg.addVirtualDisplaySharedView("sview2")
845+
self.assertEqual(
846+
1,
847+
len(cfg.getVirtualDisplayViews(OCIO.VIEW_DISPLAY_DEFINED)))
848+
self.assertEqual(1, len(cfg.getVirtualDisplayViews(OCIO.VIEW_SHARED)))
849+
850+
# Remove the virtual display
851+
cfg.clearVirtualDisplay()
852+
self.assertEqual(
853+
0,
854+
len(cfg.getVirtualDisplayViews(OCIO.VIEW_DISPLAY_DEFINED)))
855+
self.assertEqual(0, len(cfg.getVirtualDisplayViews(OCIO.VIEW_SHARED)))

0 commit comments

Comments
 (0)