Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Options: add BOOLEAN & ENUM; rs2_set_option_value #12708

Merged
merged 17 commits into from
Mar 4, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions common/subdevice-model.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2017 Intel Corporation. All Rights Reserved.
// Copyright(c) 2024 Intel Corporation. All Rights Reserved.

#include "post-processing-filters-list.h"
#include "post-processing-block-model.h"
Expand Down Expand Up @@ -89,7 +89,10 @@ namespace rs2
if( it != options_metadata.end() && ! _destructing ) // Callback runs in different context, check options_metadata still valid
{
if( RS2_OPTION_TYPE_FLOAT == changed_option->type )
it->second.value = changed_option->as_float;
{
if( changed_option->is_valid )
it->second.value = changed_option->as_float;
}
}
}
} );
Expand Down
3 changes: 2 additions & 1 deletion include/librealsense2/h/rs_option.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,8 @@ extern "C" {
typedef struct rs2_option_value
{
rs2_option id;
rs2_option_type type; /**< RS2_OPTION_TYPE_COUNT if no value is available */
int is_valid; /**< 0 if no value available; 1 otherwise */
rs2_option_type type;
union {
char const * as_string; /**< valid only while rs2_option_value is alive! */
float as_float;
Expand Down
69 changes: 47 additions & 22 deletions src/rs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
////////////////////////

using namespace librealsense;
using rsutils::json;

struct rs2_stream_profile_list
{
Expand All @@ -88,34 +89,53 @@ struct rs2_device_list
struct rs2_option_value_wrapper : rs2_option_value
{
// Keep the original json value, so we can refer to it (e.g., with as_string)
std::shared_ptr< const rsutils::json > p_json;
std::shared_ptr< const json > p_json;

// Add a reference count to control lifetime
mutable std::atomic< int > ref_count;

rs2_option_value_wrapper( rs2_option option_id, std::shared_ptr< const rsutils::json > const & p_json_value )
rs2_option_value_wrapper( rs2_option option_id,
rs2_option_type option_type,
std::shared_ptr< const json > const & p_json_value )
: ref_count( 1 )
, p_json( p_json_value )
{
id = option_id;
type = RS2_OPTION_TYPE_COUNT;
if( p_json )
type = option_type;
if( ! p_json || p_json->is_null() )
{
if( p_json->is_number_float() )
is_valid = false;
}
else
{
switch( type )
{
type = RS2_OPTION_TYPE_FLOAT;
case RS2_OPTION_TYPE_FLOAT:
if( ! p_json->is_number() )
throw invalid_value_exception( get_string( option_id )
OhadMeir marked this conversation as resolved.
Show resolved Hide resolved
+ " value is not a float: " + p_json->dump() );
p_json->get_to( as_float );
}
if( p_json->is_number_integer() )
{
type = RS2_OPTION_TYPE_INTEGER;
break;

case RS2_OPTION_TYPE_INTEGER:
if( ! p_json->is_number_integer() )
throw invalid_value_exception( get_string( option_id )
+ " value is not an integer: " + p_json->dump() );
p_json->get_to( as_integer );
}
else if( p_json->is_string() )
{
type = RS2_OPTION_TYPE_STRING;
break;

case RS2_OPTION_TYPE_STRING:
if( ! p_json->is_string() )
throw invalid_value_exception( get_string( option_id )
+ " value is not a string: " + p_json->dump() );
as_string = p_json->string_ref().c_str();
break;

default:
throw invalid_value_exception( "invalid " + get_string( option_id ) + " type "
+ get_string( option_type ) );
}
is_valid = true;
}
}
};
Expand Down Expand Up @@ -229,7 +249,7 @@ rs2_context* rs2_create_context(int api_version, rs2_error** error) BEGIN_API_CA
{
verify_version_compatibility(api_version);

rsutils::json settings;
json settings;
return new rs2_context{ context::make( settings ) };
}
HANDLE_EXCEPTIONS_AND_RETURN(nullptr, api_version)
Expand Down Expand Up @@ -705,10 +725,11 @@ HANDLE_EXCEPTIONS_AND_RETURN(0.0f, options, option)
rs2_option_value const * rs2_get_option_value( const rs2_options * options, rs2_option option_id, rs2_error ** error ) BEGIN_API_CALL
{
VALIDATE_NOT_NULL( options );
VALIDATE_OPTION_ENABLED( options, option_id );
auto wrapper = new rs2_option_value_wrapper(
option_id,
std::make_shared< const rsutils::json >( options->options->get_option( option_id ).query() ) );
auto & option = options->options->get_option( option_id ); // throws
std::shared_ptr< const json > value;
if( option.is_enabled() )
value = std::make_shared< const json >( option.query() );
auto wrapper = new rs2_option_value_wrapper( option_id, option.get_value_type(), value );
return wrapper;
}
HANDLE_EXCEPTIONS_AND_RETURN( nullptr, options, option_id )
Expand Down Expand Up @@ -741,7 +762,9 @@ rs2_options_list* rs2_get_options_list(const rs2_options* options, rs2_error** e
rs2_list->list.reserve( option_ids.size() );
for( auto option_id : option_ids )
{
auto wrapper = new rs2_option_value_wrapper( option_id, {} ); // empty json
auto & option = options->options->get_option( option_id );
auto wrapper
= new rs2_option_value_wrapper( option_id, option.get_value_type(), {} ); // empty json = not valid
rs2_list->list.push_back( wrapper );
}
return rs2_list;
Expand Down Expand Up @@ -1288,7 +1311,9 @@ static void populate_options_list( rs2_options_list * updated_options_list,
{
options_watcher::option_and_value const & option_and_value = id_value.second;
updated_options_list->list.push_back(
new rs2_option_value_wrapper( id_value.first, option_and_value.p_last_known_value ) );
new rs2_option_value_wrapper( id_value.first,
option_and_value.sptr->get_value_type(),
option_and_value.p_last_known_value ) );
}
}

Expand Down Expand Up @@ -2782,7 +2807,7 @@ NOARGS_HANDLE_EXCEPTIONS_AND_RETURN(0)
rs2_device* rs2_create_software_device(rs2_error** error) BEGIN_API_CALL
{
// We're not given a context...
auto ctx = context::make( rsutils::json::object( { { "dds", false } } ) );
auto ctx = context::make( json::object( { { "dds", false } } ) );
auto dev_info = std::make_shared< software_device_info >( ctx );
auto dev = std::make_shared< software_device >( dev_info );
dev_info->set_device( dev );
Expand Down
36 changes: 20 additions & 16 deletions tools/dds/dds-adapter/lrs-device-controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -690,25 +690,29 @@ lrs_device_controller::lrs_device_controller( rs2::device dev, std::shared_ptr<
continue;
}
json value;
switch( changed_option->type )
if( changed_option->is_valid )
{
switch( changed_option->type )
{
case RS2_OPTION_TYPE_FLOAT:
value = changed_option->as_float;
break;
case RS2_OPTION_TYPE_STRING:
value = changed_option->as_string;
break;
case RS2_OPTION_TYPE_INTEGER:
value = changed_option->as_integer;
break;
default:
LOG_ERROR( "Unknown option '" << option_name << "' type: "
<< rs2_option_type_to_string( changed_option->type ) );
continue;
}
}
else
{
case RS2_OPTION_TYPE_FLOAT:
value = changed_option->as_float;
break;
case RS2_OPTION_TYPE_STRING:
value = changed_option->as_string;
break;
case RS2_OPTION_TYPE_INTEGER:
value = changed_option->as_integer;
break;
case RS2_OPTION_TYPE_COUNT:
// No value available
value = rsutils::null_json;
break;
default:
LOG_ERROR( "Unknown option '" << option_name << "' type: "
<< rs2_option_type_to_string( changed_option->type ) );
continue;
}
dds_option->set_value( std::move( value ) );
option_values[stream_name][option_name] = dds_option->get_value();
Expand Down
11 changes: 10 additions & 1 deletion wrappers/python/pyrs_options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,16 @@ void init_options(py::module &m) {
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( RS2_OPTION_TYPE_FLOAT == 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 );
Expand All @@ -29,6 +33,7 @@ void init_options(py::module &m) {
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 )
{
Expand Down Expand Up @@ -68,6 +73,10 @@ void init_options(py::module &m) {
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 ); },
py::call_guard< py::gil_scoped_release >() )
.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>())
Expand Down