You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
130 lines
6.3 KiB
130 lines
6.3 KiB
2 months ago
|
// License: Apache 2.0. See LICENSE file in root directory.
|
||
|
// Copyright(c) 2024 Intel Corporation. All Rights Reserved.
|
||
|
|
||
|
#include "pyrealsense2.h"
|
||
|
#include <librealsense2/hpp/rs_options.hpp>
|
||
|
|
||
|
using rsutils::json;
|
||
|
|
||
|
|
||
|
void init_options(py::module &m) {
|
||
|
/** rs_options.hpp **/
|
||
|
|
||
|
// Expose option values as a custom struct rather than 'rs2_option_value*'
|
||
|
struct option_value
|
||
|
{
|
||
|
rs2_option id;
|
||
|
rs2_option_type type;
|
||
|
py::object value;
|
||
|
|
||
|
option_value( rs2::option_value const & value_ )
|
||
|
: id( value_->id )
|
||
|
, type( value_->type )
|
||
|
{
|
||
|
if( ! value_->is_valid )
|
||
|
value = py::cast< py::none >( Py_None );
|
||
|
else if( RS2_OPTION_TYPE_FLOAT == value_->type )
|
||
|
value = py::float_( value_->as_float );
|
||
|
else if( RS2_OPTION_TYPE_STRING == value_->type )
|
||
|
value = py::str( value_->as_string );
|
||
|
else if( RS2_OPTION_TYPE_INTEGER == value_->type )
|
||
|
value = py::int_( value_->as_integer );
|
||
|
else if( RS2_OPTION_TYPE_BOOLEAN == value_->type )
|
||
|
value = py::bool_( value_->as_integer );
|
||
|
else
|
||
|
value = py::cast< py::none >( Py_None );
|
||
|
}
|
||
|
};
|
||
|
py::class_< option_value >( m, "option_value" )
|
||
|
.def_readwrite( "id", &option_value::id )
|
||
|
.def_readwrite( "value", &option_value::value ) // None if no value available
|
||
|
.def_readwrite( "type", &option_value::type )
|
||
|
.def( "__repr__",
|
||
|
[]( option_value const & self )
|
||
|
{
|
||
|
std::ostringstream os;
|
||
|
os << '<' << rs2_option_to_string( self.id );
|
||
|
os << ' ' << py::str( self.value );
|
||
|
os << '>';
|
||
|
return os.str();
|
||
|
} );
|
||
|
// given an iterator, return an option_value
|
||
|
struct option_value_from_iterator
|
||
|
{
|
||
|
option_value operator()( rs2::options_list::iterator const & it ) { return option_value( *it ); }
|
||
|
};
|
||
|
py::class_< rs2::options_list >( m, "options_list" )
|
||
|
.def( "__getitem__",
|
||
|
[]( const rs2::options_list & self, size_t i )
|
||
|
{
|
||
|
if( i >= self.size() )
|
||
|
throw py::index_error();
|
||
|
return option_value( self[i] );
|
||
|
} )
|
||
|
.def( "__len__", &rs2::options_list::size )
|
||
|
.def( "__iter__",
|
||
|
[]( const rs2::options_list & self )
|
||
|
{
|
||
|
return py::detail::make_iterator_impl< option_value_from_iterator, // how to access value from iterator
|
||
|
py::return_value_policy::reference_internal, // pybind default
|
||
|
rs2::options_list::iterator, // iterator type
|
||
|
rs2::options_list::iterator, // sentinel (end) type
|
||
|
option_value // value type
|
||
|
>( self.begin(), self.end() );
|
||
|
},
|
||
|
py::keep_alive< 0, 1 >() );
|
||
|
|
||
|
py::class_<rs2::options> options(m, "options", "Base class for options interface. Should be used via sensor or processing_block."); // No docstring in C++
|
||
|
options.def("is_option_read_only", &rs2::options::is_option_read_only, "Check if particular option "
|
||
|
"is read only.", "option"_a)
|
||
|
.def("get_option", &rs2::options::get_option, "Read option value from the device.", "option"_a, py::call_guard<py::gil_scoped_release>())
|
||
|
.def( "get_option_value",
|
||
|
[]( rs2::options const & self, rs2_option option_id ) -> option_value
|
||
|
{ return self.get_option_value( option_id ); } )
|
||
|
.def( "set_option_value",
|
||
|
[]( rs2::options const & self, rs2_option option_id, json value )
|
||
|
{
|
||
|
rs2::option_value rs2_value;
|
||
|
switch( value.type() )
|
||
|
{
|
||
|
case json::value_t::null:
|
||
|
rs2_value = rs2::option_value( option_id, rs2::option_value::invalid );
|
||
|
break;
|
||
|
|
||
|
case json::value_t::string:
|
||
|
rs2_value = rs2::option_value( option_id, value.string_ref().c_str() );
|
||
|
break;
|
||
|
|
||
|
case json::value_t::number_float:
|
||
|
rs2_value = rs2::option_value( option_id, value.get< float >() );
|
||
|
break;
|
||
|
|
||
|
case json::value_t::number_unsigned:
|
||
|
case json::value_t::number_integer:
|
||
|
rs2_value = rs2::option_value( option_id, value.get< int64_t >() );
|
||
|
break;
|
||
|
|
||
|
case json::value_t::boolean:
|
||
|
rs2_value = rs2::option_value( option_id, value.get< bool >() );
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
throw std::runtime_error( "invalid value type: " + value.dump() );
|
||
|
}
|
||
|
self.set_option_value( rs2_value );
|
||
|
} )
|
||
|
.def("get_option_range", &rs2::options::get_option_range, "Retrieve the available range of values "
|
||
|
"of a supported option", "option"_a, py::call_guard<py::gil_scoped_release>())
|
||
|
.def("set_option", &rs2::options::set_option, "Write new value to device option", "option"_a, "value"_a, py::call_guard<py::gil_scoped_release>())
|
||
|
.def("supports", (bool (rs2::options::*)(rs2_option option) const) &rs2::options::supports, "Check if particular "
|
||
|
"option is supported by a subdevice", "option"_a)
|
||
|
.def("get_option_description", &rs2::options::get_option_description, "Get option description.", "option"_a)
|
||
|
.def("get_option_value_description", &rs2::options::get_option_value_description, "Get option value description "
|
||
|
"(In case a specific option value holds special meaning)", "option"_a, "value"_a)
|
||
|
.def("get_supported_options", &rs2::options::get_supported_options, "Retrieve list of supported options") // No docstring in C++
|
||
|
.def( "on_options_changed", &rs2::options::on_options_changed,
|
||
|
"Sets a callback to notify in case options in this container change value", "callback"_a );
|
||
|
|
||
|
/** end rs_options.hpp **/
|
||
|
}
|