From bf89d275b957a307167e44d4b73a290420fcb9f8 Mon Sep 17 00:00:00 2001 From: Eran Date: Fri, 6 Oct 2023 10:28:17 +0300 Subject: [PATCH 1/6] make signal::callback public --- third-party/rsutils/include/rsutils/signal.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/third-party/rsutils/include/rsutils/signal.h b/third-party/rsutils/include/rsutils/signal.h index f355f0d0cc..29cfb51d0d 100644 --- a/third-party/rsutils/include/rsutils/signal.h +++ b/third-party/rsutils/include/rsutils/signal.h @@ -33,7 +33,9 @@ using subscription_slot = int; template< typename... Args > class signal { +public: using callback = std::function< void( Args... ) >; +private: using map = std::map< subscription_slot, callback >; // We use a shared_ptr to control lifetime: only while it's alive can we remove subscriptions From 7c5461d3a274e343cbc48aeb135e9b7611189f25 Mon Sep 17 00:00:00 2001 From: Eran Date: Fri, 6 Oct 2023 10:29:25 +0300 Subject: [PATCH 2/6] add dds-participant.domain-id() --- third-party/realdds/include/realdds/dds-participant.h | 4 ++++ third-party/realdds/src/dds-participant.cpp | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/third-party/realdds/include/realdds/dds-participant.h b/third-party/realdds/include/realdds/dds-participant.h index 24143a0868..de4329a9e5 100644 --- a/third-party/realdds/include/realdds/dds-participant.h +++ b/third-party/realdds/include/realdds/dds-participant.h @@ -85,6 +85,10 @@ class dds_participant // dds_guid const & guid() const; + // Returns the domain-ID for this participant + // + dds_domain_id domain_id() const; + // Returns this participant's name from the QoS // rsutils::string::slice name() const; diff --git a/third-party/realdds/src/dds-participant.cpp b/third-party/realdds/src/dds-participant.cpp index 77fe31f87b..f74c11c804 100644 --- a/third-party/realdds/src/dds-participant.cpp +++ b/third-party/realdds/src/dds-participant.cpp @@ -268,6 +268,12 @@ dds_guid const & dds_participant::guid() const } +dds_domain_id dds_participant::domain_id() const +{ + return get()->get_domain_id(); +} + + rsutils::string::slice dds_participant::name() const { auto & string_255 = get()->get_qos().name(); From a3973f12ae8c847f0eaf9a98276d390b64795062 Mon Sep 17 00:00:00 2001 From: Eran Date: Fri, 6 Oct 2023 15:34:09 +0300 Subject: [PATCH 3/6] add dds-topic-reader.has-writers() --- third-party/realdds/include/realdds/dds-topic-reader.h | 3 +++ third-party/realdds/src/dds-topic-reader.cpp | 1 + 2 files changed, 4 insertions(+) diff --git a/third-party/realdds/include/realdds/dds-topic-reader.h b/third-party/realdds/include/realdds/dds-topic-reader.h index d46838e963..3a7a2b7abc 100644 --- a/third-party/realdds/include/realdds/dds-topic-reader.h +++ b/third-party/realdds/include/realdds/dds-topic-reader.h @@ -39,6 +39,8 @@ class dds_topic_reader : public eprosima::fastdds::dds::DataReaderListener eprosima::fastdds::dds::DataReader * _reader = nullptr; + int _n_writers = 0; + public: dds_topic_reader( std::shared_ptr< dds_topic > const & topic ); dds_topic_reader( std::shared_ptr< dds_topic > const & topic, std::shared_ptr< dds_subscriber > const & subscriber ); @@ -48,6 +50,7 @@ class dds_topic_reader : public eprosima::fastdds::dds::DataReaderListener eprosima::fastdds::dds::DataReader * operator->() const { return get(); } bool is_running() const { return ( get() != nullptr ); } + bool has_writers() const { return _n_writers > 0; } std::shared_ptr< dds_topic > const & topic() const { return _topic; } diff --git a/third-party/realdds/src/dds-topic-reader.cpp b/third-party/realdds/src/dds-topic-reader.cpp index f011c40e8f..40e58e5c43 100644 --- a/third-party/realdds/src/dds-topic-reader.cpp +++ b/third-party/realdds/src/dds-topic-reader.cpp @@ -112,6 +112,7 @@ void dds_topic_reader::on_subscription_matched( eprosima::fastdds::dds::DataReader *, eprosima::fastdds::dds::SubscriptionMatchedStatus const & info ) { // Called when the subscriber is matched (un)with a Writer + _n_writers = info.current_count; if( _on_subscription_matched ) _on_subscription_matched( info ); } From 6391fa8e10f368e60ea27269aeadc08520ca16a5 Mon Sep 17 00:00:00 2001 From: Eran Date: Fri, 6 Oct 2023 15:36:37 +0300 Subject: [PATCH 4/6] separate rsdds-device-factory --- src/context.cpp | 130 ++---------------------- src/context.h | 20 ++-- src/dds/rsdds-device-factory.cpp | 169 +++++++++++++++++++++++++++++++ src/dds/rsdds-device-factory.h | 55 ++++++++++ 4 files changed, 239 insertions(+), 135 deletions(-) create mode 100644 src/dds/rsdds-device-factory.cpp create mode 100644 src/dds/rsdds-device-factory.h diff --git a/src/context.cpp b/src/context.cpp index 7aa94c65c9..1322fdf10e 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -2,43 +2,13 @@ // Copyright(c) 2015 Intel Corporation. All Rights Reserved. #include "context.h" - #include "media/playback/playback-device-info.h" -#include "environment.h" -#include - - -#ifdef BUILD_WITH_DDS -#include "dds/rs-dds-device-info.h" - -#include -#include -#include -#include -#include -#include -#include - -// We manage one participant and device-watcher per domain: -// Two contexts with the same domain-id will share the same participant and watcher, while a third context on a -// different domain will have its own. -// -struct dds_domain_context -{ - rsutils::shared_ptr_singleton< realdds::dds_participant > participant; - rsutils::shared_ptr_singleton< realdds::dds_device_watcher > device_watcher; -}; -// -// Domains are mapped by ID: -// Two contexts with the same participant name on different domain-ids are using two different participants! -// -static std::map< realdds::dds_domain_id, dds_domain_context > dds_domain_context_by_id; - -#endif // BUILD_WITH_DDS +#include #include using json = nlohmann::json; + namespace librealsense { context::context( json const & settings ) @@ -49,6 +19,11 @@ namespace librealsense *this, [this]( std::vector< rs2_device_info > & removed, std::vector< rs2_device_info > & added ) { invoke_devices_changed_callbacks( removed, added ); } ) +#ifdef BUILD_WITH_DDS + , _dds_device_factory( *this, + [this]( std::vector< rs2_device_info > & removed, std::vector< rs2_device_info > & added ) + { invoke_devices_changed_callbacks( removed, added ); } ) +#endif { static bool version_logged = false; if( ! version_logged ) @@ -56,40 +31,6 @@ namespace librealsense version_logged = true; LOG_DEBUG( "Librealsense VERSION: " << RS2_API_VERSION_STR ); } - -#ifdef BUILD_WITH_DDS - nlohmann::json dds_settings - = rsutils::json::get< nlohmann::json >( settings, std::string( "dds", 3 ), nlohmann::json::object() ); - if( dds_settings.is_object() ) - { - realdds::dds_domain_id domain_id - = rsutils::json::get< int >( dds_settings, std::string( "domain", 6 ), 0 ); - std::string participant_name = rsutils::json::get< std::string >( dds_settings, - std::string( "participant", 11 ), - rsutils::os::executable_name() ); - - auto & domain = dds_domain_context_by_id[domain_id]; - _dds_participant = domain.participant.instance(); - if( ! _dds_participant->is_valid() ) - { - _dds_participant->init( domain_id, participant_name, std::move( dds_settings ) ); - } - else if( rsutils::json::has_value( dds_settings, std::string( "participant", 11 ) ) - && participant_name != _dds_participant->name() ) - { - throw std::runtime_error( rsutils::string::from() << "A DDS participant '" << _dds_participant->name() - << "' already exists in domain " << domain_id - << "; cannot create '" << participant_name << "'" ); - } - _dds_watcher = domain.device_watcher.instance( _dds_participant ); - - // The DDS device watcher should always be on - if( _dds_watcher && _dds_watcher->is_stopped() ) - { - start_dds_device_watcher(); - } - } -#endif //BUILD_WITH_DDS } @@ -101,10 +42,6 @@ namespace librealsense context::~context() { -#ifdef BUILD_WITH_DDS - if( _dds_watcher ) - _dds_watcher->stop(); -#endif //BUILD_WITH_DDS } @@ -141,34 +78,8 @@ namespace librealsense auto ctx = t->shared_from_this(); #ifdef BUILD_WITH_DDS - if( _dds_watcher ) - _dds_watcher->foreach_device( - [&]( std::shared_ptr< realdds::dds_device > const & dev ) -> bool - { - if( !dev->is_ready() ) - { - LOG_DEBUG( "device '" << dev->device_info().debug_name() << "' is not yet ready" ); - return true; - } - if( dev->device_info().product_line == "D400" ) - { - if( !(mask & RS2_PRODUCT_LINE_D400) ) - return true; - } - else if( dev->device_info().product_line == "D500" ) - { - if( !(mask & RS2_PRODUCT_LINE_D500) ) - return true; - } - else if( !(mask & RS2_PRODUCT_LINE_NON_INTEL) ) - { - return true; - } - - std::shared_ptr< device_info > info = std::make_shared< dds_device_info >( ctx, dev ); - list.push_back( info ); - return true; - } ); + for( auto & info : _dds_device_factory.query_devices( requested_mask ) ) + list.push_back( info ); #endif //BUILD_WITH_DDS for( auto && item : _playback_devices ) @@ -225,29 +136,6 @@ namespace librealsense } -#ifdef BUILD_WITH_DDS - void context::start_dds_device_watcher() - { - _dds_watcher->on_device_added( [this]( std::shared_ptr< realdds::dds_device > const & dev ) { - dev->wait_until_ready(); // make sure handshake is complete - - std::vector rs2_device_info_added; - std::vector rs2_device_info_removed; - auto info = std::make_shared< dds_device_info >( shared_from_this(), dev ); - rs2_device_info_added.push_back( { shared_from_this(), info } ); - invoke_devices_changed_callbacks( rs2_device_info_removed, rs2_device_info_added ); - } ); - _dds_watcher->on_device_removed( [this]( std::shared_ptr< realdds::dds_device > const & dev ) { - std::vector rs2_device_info_added; - std::vector rs2_device_info_removed; - auto info = std::make_shared< dds_device_info >( shared_from_this(), dev ); - rs2_device_info_removed.push_back( { shared_from_this(), info } ); - invoke_devices_changed_callbacks( rs2_device_info_removed, rs2_device_info_added ); - } ); - _dds_watcher->start(); - } -#endif //BUILD_WITH_DDS - uint64_t context::register_internal_device_callback(devices_changed_callback_ptr callback) { std::lock_guard lock(_devices_changed_callbacks_mtx); diff --git a/src/context.h b/src/context.h index 6b5a3b5630..af03fe4f31 100644 --- a/src/context.h +++ b/src/context.h @@ -4,6 +4,9 @@ #pragma once #include "backend-device-factory.h" +#ifdef BUILD_WITH_DDS +#include "dds/rsdds-device-factory.h" +#endif #include "types.h" // devices_changed_callback_ptr #include @@ -38,14 +41,6 @@ struct rs2_stream_profile }; -#ifdef BUILD_WITH_DDS -namespace realdds { - class dds_device_watcher; - class dds_participant; -} // namespace realdds -#endif - - namespace librealsense { class playback_device_info; @@ -93,16 +88,13 @@ namespace librealsense std::map> _playback_devices; std::map _devices_changed_callbacks; -#ifdef BUILD_WITH_DDS - std::shared_ptr< realdds::dds_participant > _dds_participant; - std::shared_ptr< realdds::dds_device_watcher > _dds_watcher; - - void start_dds_device_watcher(); -#endif nlohmann::json _settings; // Save operation settings unsigned const _device_mask; backend_device_factory _backend_device_factory; +#ifdef BUILD_WITH_DDS + rsdds_device_factory _dds_device_factory; +#endif devices_changed_callback_ptr _devices_changed_callback; std::map> _streams; diff --git a/src/dds/rsdds-device-factory.cpp b/src/dds/rsdds-device-factory.cpp new file mode 100644 index 0000000000..128fbe787d --- /dev/null +++ b/src/dds/rsdds-device-factory.cpp @@ -0,0 +1,169 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2023 Intel Corporation. All Rights Reserved. + +#include "rsdds-device-factory.h" +#include "context.h" + +#include "rs-dds-device-info.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + + +namespace librealsense { + + +// The device-watcher is a singleton per domain. It is held alive by the device-factory below, which is held per +// context. I.e., as long as a context is alive, it stays alive alongside the participant. +// +// We are responsible for exposing the single notification from the dds-device-watcher to several subscribers: +// one device-watcher to many contexts, each with further subscriptions. +// +class rsdds_watcher_singleton +{ + std::shared_ptr< realdds::dds_device_watcher > const _device_watcher; + using signal = rsutils::signal< std::shared_ptr< realdds::dds_device > const &, bool /*added*/ >; + signal _callbacks; + +public: + rsdds_watcher_singleton( std::shared_ptr< realdds::dds_participant > const & participant ) + : _device_watcher( std::make_shared< realdds::dds_device_watcher >( participant ) ) + { + assert( _device_watcher->is_stopped() ); + + _device_watcher->on_device_added( + [this]( std::shared_ptr< realdds::dds_device > const & dev ) + { + dev->wait_until_ready(); // make sure handshake is complete + _callbacks.raise( dev, true ); + } ); + + _device_watcher->on_device_removed( [this]( std::shared_ptr< realdds::dds_device > const & dev ) + { _callbacks.raise( dev, false ); } ); + + _device_watcher->start(); + } + + rsutils::subscription subscribe( signal::callback && cb ) { return _callbacks.subscribe( std::move( cb ) ); } + + std::shared_ptr< realdds::dds_device_watcher > const get_device_watcher() const { return _device_watcher; } +}; + + +// We manage one participant and device-watcher per domain: +// Two contexts with the same domain-id will share the same participant and watcher, while a third context on a +// different domain will have its own. +// +struct domain_context +{ + rsutils::shared_ptr_singleton< realdds::dds_participant > participant; + rsutils::shared_ptr_singleton< rsdds_watcher_singleton > device_watcher; +}; +// +// Domains are mapped by ID: +// Two contexts with the same participant name on different domain-ids are using two different participants! +// +static std::map< realdds::dds_domain_id, domain_context > domain_context_by_id; +static std::mutex domain_context_by_id_mutex; + + +rsdds_device_factory::rsdds_device_factory( context & ctx, callback && cb ) + : _context( ctx ) +{ + nlohmann::json dds_settings = rsutils::json::get< nlohmann::json >( _context.get_settings(), + std::string( "dds", 3 ), + nlohmann::json::object() ); + if( dds_settings.is_object() ) + { + auto domain_id = rsutils::json::get< realdds::dds_domain_id >( dds_settings, std::string( "domain", 6 ), 0 ); + std::string participant_name = rsutils::json::get< std::string >( dds_settings, + std::string( "participant", 11 ), + rsutils::os::executable_name() ); + + std::lock_guard< std::mutex > lock( domain_context_by_id_mutex ); + auto & domain = domain_context_by_id[domain_id]; + _participant = domain.participant.instance(); + if( ! _participant->is_valid() ) + { + _participant->init( domain_id, participant_name, std::move( dds_settings ) ); + } + else if( rsutils::json::has_value( dds_settings, std::string( "participant", 11 ) ) + && participant_name != _participant->name() ) + { + throw std::runtime_error( rsutils::string::from() + << "A DDS participant '" << _participant->name() << "' already exists in domain " + << domain_id << "; cannot create '" << participant_name << "'" ); + } + _watcher_singleton = domain.device_watcher.instance( _participant ); + _subscription = _watcher_singleton->subscribe( + [this, cb = std::move( cb )]( std::shared_ptr< realdds::dds_device > const & dev, bool added ) + { + std::vector< rs2_device_info > infos_added; + std::vector< rs2_device_info > infos_removed; + auto ctx = _context.shared_from_this(); + auto dev_info = std::make_shared< dds_device_info >( ctx, dev ); + if( added ) + infos_added.push_back( { ctx, dev_info } ); + else + infos_removed.push_back( { ctx, dev_info } ); + cb( infos_removed, infos_added ); + } ); + } +} + + +rsdds_device_factory::~rsdds_device_factory() {} + + +std::vector< std::shared_ptr< device_info > > rsdds_device_factory::query_devices( unsigned requested_mask ) const +{ + std::vector< std::shared_ptr< device_info > > list; + if( _watcher_singleton ) + { + unsigned const mask = context::combine_device_masks( requested_mask, _context.get_device_mask() ); + + _watcher_singleton->get_device_watcher()->foreach_device( + [&]( std::shared_ptr< realdds::dds_device > const & dev ) -> bool + { + if( ! dev->is_ready() ) + { + LOG_DEBUG( "device '" << dev->device_info().debug_name() << "' is not ready" ); + return true; + } + if( dev->device_info().product_line == "D400" ) + { + if( ! ( mask & RS2_PRODUCT_LINE_D400 ) ) + return true; + } + else if( dev->device_info().product_line == "D500" ) + { + if( ! ( mask & RS2_PRODUCT_LINE_D500 ) ) + return true; + } + else if( ! ( mask & RS2_PRODUCT_LINE_NON_INTEL ) ) + { + return true; + } + + std::shared_ptr< device_info > info + = std::make_shared< dds_device_info >( _context.shared_from_this(), dev ); + list.push_back( info ); + return true; // continue iteration + } ); + } + return list; +} + + +} // namespace librealsense diff --git a/src/dds/rsdds-device-factory.h b/src/dds/rsdds-device-factory.h new file mode 100644 index 0000000000..57a764115c --- /dev/null +++ b/src/dds/rsdds-device-factory.h @@ -0,0 +1,55 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2023 Intel Corporation. All Rights Reserved. + +#pragma once + +#include +#include +#include + + +struct rs2_device_info; + + +namespace realdds { +class dds_participant; +} + + +namespace librealsense { + + +class device_info; +class context; +class rsdds_watcher_singleton; + + +// This factory creates "rsdds devices", or RealSense device proxies around a realdds device core. +// +// The factory abstracts away platform-specific concepts such that all the user has to do is supply a callback to know +// when changes in the list of devices have been made. +// +// Any devices created here will have a device-info that derives from dds_device_info. +// +class rsdds_device_factory +{ + context & _context; + std::shared_ptr< realdds::dds_participant > _participant; + std::shared_ptr< rsdds_watcher_singleton > _watcher_singleton; + rsutils::subscription _subscription; + +public: + using callback = std::function< void( std::vector< rs2_device_info > & rs2_devices_info_removed, + std::vector< rs2_device_info > & rs2_devices_info_added ) >; + + rsdds_device_factory( context &, callback && ); + ~rsdds_device_factory(); + + // Query any subset of available devices and return them as device-info objects + // Devices will match both the requested mask and the device-mask from the context settings + // + std::vector< std::shared_ptr< device_info > > query_devices( unsigned mask ) const; +}; + + +} // namespace librealsense From 52ce0b270a38b67a885bc2970ed86019d30ece6a Mon Sep 17 00:00:00 2001 From: Eran Date: Sun, 8 Oct 2023 08:45:19 +0300 Subject: [PATCH 5/6] rscore/device_factory base class --- src/CMakeLists.txt | 1 + src/backend-device-factory.cpp | 2 +- src/backend-device-factory.h | 18 +++----- src/context.cpp | 70 ++++++++++++++++---------------- src/context.h | 13 ++---- src/dds/rsdds-device-factory.cpp | 2 +- src/dds/rsdds-device-factory.h | 18 +++----- src/rscore/device-factory.h | 57 ++++++++++++++++++++++++++ 8 files changed, 108 insertions(+), 73 deletions(-) create mode 100644 src/rscore/device-factory.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1d1ae8fc83..eddfd8065b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -72,6 +72,7 @@ target_sources(${LRS_TARGET} "${CMAKE_CURRENT_LIST_DIR}/device.cpp" "${CMAKE_CURRENT_LIST_DIR}/device-info.cpp" "${CMAKE_CURRENT_LIST_DIR}/device_hub.cpp" + "${CMAKE_CURRENT_LIST_DIR}/rscore/device-factory.h" "${CMAKE_CURRENT_LIST_DIR}/environment.cpp" "${CMAKE_CURRENT_LIST_DIR}/error-handling.cpp" "${CMAKE_CURRENT_LIST_DIR}/firmware_logger_device.cpp" diff --git a/src/backend-device-factory.cpp b/src/backend-device-factory.cpp index c05d928df2..3edfb6240b 100644 --- a/src/backend-device-factory.cpp +++ b/src/backend-device-factory.cpp @@ -124,7 +124,7 @@ std::shared_ptr< platform::backend > backend_device::get_backend() backend_device_factory::backend_device_factory( context & ctx, callback && cb ) - : _context( ctx ) + : super( ctx ) , _device_watcher( backend_device_watcher.instance() ) , _dtor( _device_watcher->subscribe( [this, cb = std::move( cb )]( platform::backend_device_group const & old, diff --git a/src/backend-device-factory.h b/src/backend-device-factory.h index 0c5fc5a00f..1b71faf922 100644 --- a/src/backend-device-factory.h +++ b/src/backend-device-factory.h @@ -3,19 +3,13 @@ #pragma once +#include #include -#include -#include - - -struct rs2_device_info; namespace librealsense { -class device_info; -class context; class device_watcher_singleton; @@ -35,23 +29,21 @@ class platform_device_info; // manages these device-info objects such that lifetime is tracked and updated appropriately, without the caller's // knowledge. // -class backend_device_factory +class backend_device_factory : public device_factory { - context & _context; + typedef device_factory super; + std::shared_ptr< device_watcher_singleton > const _device_watcher; rsutils::subscription const _dtor; // raii generic code, used to automatically unsubscribe our callback public: - using callback = std::function< void( std::vector< rs2_device_info > & rs2_devices_info_removed, - std::vector< rs2_device_info > & rs2_devices_info_added ) >; - backend_device_factory( context &, callback && ); ~backend_device_factory(); // Query any subset of available devices and return them as device-info objects // Devices will match both the requested mask and the device-mask from the context settings // - std::vector< std::shared_ptr< device_info > > query_devices( unsigned mask ) const; + std::vector< std::shared_ptr< device_info > > query_devices( unsigned mask ) const override; private: std::vector< std::shared_ptr< platform::platform_device_info > > diff --git a/src/context.cpp b/src/context.cpp index 1322fdf10e..89fb99e284 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -4,6 +4,11 @@ #include "context.h" #include "media/playback/playback-device-info.h" +#include "backend-device-factory.h" +#ifdef BUILD_WITH_DDS +#include "dds/rsdds-device-factory.h" +#endif + #include #include using json = nlohmann::json; @@ -15,15 +20,6 @@ namespace librealsense : _settings( settings ) , _device_mask( rsutils::json::get< unsigned >( settings, "device-mask", RS2_PRODUCT_LINE_ANY ) ) , _devices_changed_callback( nullptr, []( rs2_devices_changed_callback * ) {} ) - , _backend_device_factory( - *this, - [this]( std::vector< rs2_device_info > & removed, std::vector< rs2_device_info > & added ) - { invoke_devices_changed_callbacks( removed, added ); } ) -#ifdef BUILD_WITH_DDS - , _dds_device_factory( *this, - [this]( std::vector< rs2_device_info > & removed, std::vector< rs2_device_info > & added ) - { invoke_devices_changed_callbacks( removed, added ); } ) -#endif { static bool version_logged = false; if( ! version_logged ) @@ -31,6 +27,18 @@ namespace librealsense version_logged = true; LOG_DEBUG( "Librealsense VERSION: " << RS2_API_VERSION_STR ); } + + _factories.push_back( std::make_shared< backend_device_factory >( + *this, + [this]( std::vector< rs2_device_info > & removed, std::vector< rs2_device_info > & added ) + { invoke_devices_changed_callbacks( removed, added ); } ) ); + +#ifdef BUILD_WITH_DDS + _factories.push_back( std::make_shared< rsdds_device_factory >( + *this, + [this]( std::vector< rs2_device_info > & removed, std::vector< rs2_device_info > & added ) + { invoke_devices_changed_callbacks( removed, added ); } ) ); +#endif } @@ -57,39 +65,31 @@ namespace librealsense } - std::vector> context::query_devices( int requested_mask ) const + std::vector< std::shared_ptr< device_info > > context::query_devices( int requested_mask ) const { - auto list = _backend_device_factory.query_devices( requested_mask ); - query_software_devices( list, requested_mask ); + std::vector< std::shared_ptr< device_info > > list; + for( auto & factory : _factories ) + { + for( auto & dev_info : factory->query_devices( requested_mask ) ) + { + LOG_INFO( "... " << dev_info->get_address() ); + list.push_back( dev_info ); + } + } + for( auto & item : _playback_devices ) + { + if( auto dev_info = item.second.lock() ) + { + LOG_INFO( "... " << dev_info->get_address() ); + list.push_back( dev_info ); + } + } LOG_INFO( "Found " << list.size() << " RealSense devices (0x" << std::hex << requested_mask << " requested & 0x" << get_device_mask() << " from device-mask in settings)" << std::dec ); - for( auto & item : list ) - LOG_INFO( "... " << item->get_address() ); return list; } - void context::query_software_devices( std::vector< std::shared_ptr< device_info > > & list, unsigned requested_mask ) const - { - unsigned mask = combine_device_masks( requested_mask, get_device_mask() ); - - auto t = const_cast(this); // While generally a bad idea, we need to provide mutable reference to the devices - // to allow them to modify context later on - auto ctx = t->shared_from_this(); - -#ifdef BUILD_WITH_DDS - for( auto & info : _dds_device_factory.query_devices( requested_mask ) ) - list.push_back( info ); -#endif //BUILD_WITH_DDS - - for( auto && item : _playback_devices ) - { - if( auto dev = item.second.lock() ) - list.push_back( dev ); - } - } - - void context::invoke_devices_changed_callbacks( std::vector & rs2_devices_info_removed, std::vector & rs2_devices_info_added ) { diff --git a/src/context.h b/src/context.h index af03fe4f31..e5413c51d7 100644 --- a/src/context.h +++ b/src/context.h @@ -3,10 +3,6 @@ #pragma once -#include "backend-device-factory.h" -#ifdef BUILD_WITH_DDS -#include "dds/rsdds-device-factory.h" -#endif #include "types.h" // devices_changed_callback_ptr #include @@ -45,6 +41,7 @@ namespace librealsense { class playback_device_info; class stream_interface; + class device_factory; class context : public std::enable_shared_from_this { @@ -72,8 +69,6 @@ namespace librealsense void unregister_internal_device_callback(uint64_t cb_id); void set_devices_changed_callback(devices_changed_callback_ptr callback); - void query_software_devices( std::vector< std::shared_ptr< device_info > > & list, unsigned requested_mask ) const; - std::shared_ptr add_device(const std::string& file); void remove_device(const std::string& file); @@ -91,10 +86,8 @@ namespace librealsense nlohmann::json _settings; // Save operation settings unsigned const _device_mask; - backend_device_factory _backend_device_factory; -#ifdef BUILD_WITH_DDS - rsdds_device_factory _dds_device_factory; -#endif + + std::vector< std::shared_ptr< device_factory > > _factories; devices_changed_callback_ptr _devices_changed_callback; std::map> _streams; diff --git a/src/dds/rsdds-device-factory.cpp b/src/dds/rsdds-device-factory.cpp index 128fbe787d..0716c977e5 100644 --- a/src/dds/rsdds-device-factory.cpp +++ b/src/dds/rsdds-device-factory.cpp @@ -79,7 +79,7 @@ static std::mutex domain_context_by_id_mutex; rsdds_device_factory::rsdds_device_factory( context & ctx, callback && cb ) - : _context( ctx ) + : super( ctx ) { nlohmann::json dds_settings = rsutils::json::get< nlohmann::json >( _context.get_settings(), std::string( "dds", 3 ), diff --git a/src/dds/rsdds-device-factory.h b/src/dds/rsdds-device-factory.h index 57a764115c..2fa2f05391 100644 --- a/src/dds/rsdds-device-factory.h +++ b/src/dds/rsdds-device-factory.h @@ -3,12 +3,8 @@ #pragma once +#include #include -#include -#include - - -struct rs2_device_info; namespace realdds { @@ -19,8 +15,6 @@ class dds_participant; namespace librealsense { -class device_info; -class context; class rsdds_watcher_singleton; @@ -31,24 +25,22 @@ class rsdds_watcher_singleton; // // Any devices created here will have a device-info that derives from dds_device_info. // -class rsdds_device_factory +class rsdds_device_factory : public device_factory { - context & _context; + typedef device_factory super; + std::shared_ptr< realdds::dds_participant > _participant; std::shared_ptr< rsdds_watcher_singleton > _watcher_singleton; rsutils::subscription _subscription; public: - using callback = std::function< void( std::vector< rs2_device_info > & rs2_devices_info_removed, - std::vector< rs2_device_info > & rs2_devices_info_added ) >; - rsdds_device_factory( context &, callback && ); ~rsdds_device_factory(); // Query any subset of available devices and return them as device-info objects // Devices will match both the requested mask and the device-mask from the context settings // - std::vector< std::shared_ptr< device_info > > query_devices( unsigned mask ) const; + std::vector< std::shared_ptr< device_info > > query_devices( unsigned mask ) const override; }; diff --git a/src/rscore/device-factory.h b/src/rscore/device-factory.h new file mode 100644 index 0000000000..592f45304b --- /dev/null +++ b/src/rscore/device-factory.h @@ -0,0 +1,57 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2023 Intel Corporation. All Rights Reserved. + +#pragma once + +#include +#include +#include + + +struct rs2_device_info; + + +namespace librealsense { + + +class device_info; +class context; + + +// Interface for device factories, allowing for: +// - notification callbacks for any device additions and removals +// - querying of current devices in the system +// +// A device factory is contained by a context, 1:1. I.e., multiple factory instances may exist at once, each for a +// different context. +// + +class device_factory +{ +protected: + context & _context; + + device_factory( context & ctx ) + : _context( ctx ) + { + } + +public: + // Callbacks take this form. + // + using callback = std::function< void( std::vector< rs2_device_info > & devices_removed, + std::vector< rs2_device_info > & devices_added ) >; + + virtual ~device_factory() = default; + + // Query any subset of available devices and return them as device-info objects from which actual devices can be + // created as needed. + // + // Devices will match both the requested mask and the device-mask from the context settings. See + // RS2_PRODUCT_LINE_... defines for possible values. + // + virtual std::vector< std::shared_ptr< device_info > > query_devices( unsigned mask ) const = 0; +}; + + +} // namespace librealsense From fbccf404387380e2fe804b901bd1a60ce52e38ae Mon Sep 17 00:00:00 2001 From: Eran Date: Sun, 8 Oct 2023 09:07:45 +0300 Subject: [PATCH 6/6] fix warnings --- src/ds/d400/d400-options.h | 4 ++-- src/ds/ds-options.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ds/d400/d400-options.h b/src/ds/d400/d400-options.h index b4a4a3fcc0..2545d9732a 100644 --- a/src/ds/d400/d400-options.h +++ b/src/ds/d400/d400-options.h @@ -63,7 +63,7 @@ namespace librealsense virtual float query() const override; virtual option_range get_range() const override; virtual bool is_enabled() const override { return true; } - virtual bool is_read_only() const { return _sensor && _sensor->is_opened(); } + virtual bool is_read_only() const override { return _sensor && _sensor->is_opened(); } virtual const char* get_description() const override { return "Exposure limit is in microseconds. If the requested exposure limit is greater than frame time, it will be set to frame time at runtime. Setting will not take effect until next streaming session."; @@ -87,7 +87,7 @@ namespace librealsense virtual float query() const override; virtual option_range get_range() const override; virtual bool is_enabled() const override { return true; } - virtual bool is_read_only() const { return _sensor && _sensor->is_opened(); } + virtual bool is_read_only() const override { return _sensor && _sensor->is_opened(); } virtual const char* get_description() const override { return "Gain limits ranges from 16 to 248. If the requested gain limit is less than 16, it will be set to 16. If the requested gain limit is greater than 248, it will be set to 248. Setting will not take effect until next streaming session."; diff --git a/src/ds/ds-options.h b/src/ds/ds-options.h index 50526801f5..7291f8f036 100644 --- a/src/ds/ds-options.h +++ b/src/ds/ds-options.h @@ -201,7 +201,7 @@ namespace librealsense virtual float query() const override; virtual option_range get_range() const override; virtual bool is_enabled() const override { return true; } - virtual bool is_read_only() const { return _sensor && _sensor->is_opened(); } + virtual bool is_read_only() const override { return _sensor && _sensor->is_opened(); } const char* get_description() const override; void enable_recording(std::function record_action) override