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.
803 lines
31 KiB
803 lines
31 KiB
// License: Apache 2.0. See LICENSE file in root directory.
|
|
// Copyright(c) 2017 Intel Corporation. All Rights Reserved.
|
|
|
|
|
|
#include <librealsense2/rs.hpp>
|
|
#include "viewer.h"
|
|
#include "os.h"
|
|
#include "ux-window.h"
|
|
#include "fw-update-helper.h"
|
|
|
|
#include <rsutils/os/ensure-console.h>
|
|
#include <tclap/CmdLine.h>
|
|
|
|
#include <cstdarg>
|
|
#include <thread>
|
|
#include <iostream>
|
|
#include <algorithm>
|
|
#include <iomanip>
|
|
#include <map>
|
|
#include <sstream>
|
|
#include <array>
|
|
#include <mutex>
|
|
#include <set>
|
|
#include <regex>
|
|
|
|
#include <imgui_internal.h>
|
|
|
|
#ifdef INTERNAL_FW
|
|
#include "common/fw/D4XX_FW_Image.h"
|
|
#else
|
|
#define FW_D4XX_FW_IMAGE_VERSION ""
|
|
#endif // INTERNAL_FW
|
|
|
|
using namespace rs2;
|
|
using namespace rs400;
|
|
|
|
|
|
void update_viewer_configuration(viewer_model& viewer_model)
|
|
{
|
|
// Hide options from the Viewer application
|
|
viewer_model._hidden_options.emplace(RS2_OPTION_ENABLE_IR_REFLECTIVITY);
|
|
}
|
|
|
|
bool add_remote_device(context& ctx, std::string address)
|
|
{
|
|
// Return true if a network device exists at the given address; throw an error otherwise
|
|
// For now, this is unsupported!
|
|
return false;
|
|
}
|
|
|
|
void add_playback_device( context & ctx,
|
|
std::shared_ptr< device_models_list > device_models,
|
|
std::string & error_message,
|
|
viewer_model & viewer_model,
|
|
const std::string & file )
|
|
{
|
|
bool was_loaded = false;
|
|
bool failed = false;
|
|
try
|
|
{
|
|
auto dev = ctx.load_device(file);
|
|
was_loaded = true;
|
|
device_models->emplace_back( // Will cause the new device to appear in the left panel
|
|
new device_model( dev, error_message, viewer_model ) );
|
|
if (auto p = dev.as<playback>())
|
|
{
|
|
auto filename = p.file_name();
|
|
p.set_status_changed_callback(
|
|
[&viewer_model, weak_device_models = std::weak_ptr< device_models_list >( device_models ), filename](
|
|
rs2_playback_status status )
|
|
{
|
|
auto device_models = weak_device_models.lock();
|
|
if( ! device_models )
|
|
return;
|
|
if( status == RS2_PLAYBACK_STATUS_STOPPED )
|
|
{
|
|
auto it = std::find_if( device_models->begin(),
|
|
device_models->end(),
|
|
[&]( const std::unique_ptr< device_model > & dm )
|
|
{
|
|
if( auto p = dm->dev.as< playback >() )
|
|
return p.file_name() == filename;
|
|
return false;
|
|
} );
|
|
if( it != device_models->end() )
|
|
{
|
|
auto subs = ( *it )->subdevices;
|
|
if( ( *it )->_playback_repeat )
|
|
{
|
|
// Calling from different since playback callback is from reading thread
|
|
std::thread{ [subs, &viewer_model, it]()
|
|
{
|
|
if( ! ( *it )->dev_syncer )
|
|
( *it )->dev_syncer = viewer_model.syncer->create_syncer();
|
|
|
|
for( auto && sub : subs )
|
|
{
|
|
if( sub->streaming )
|
|
{
|
|
auto profiles = sub->get_selected_profiles();
|
|
|
|
sub->play( profiles, viewer_model, ( *it )->dev_syncer );
|
|
}
|
|
}
|
|
} }
|
|
.detach();
|
|
}
|
|
else
|
|
{
|
|
for( auto && sub : subs )
|
|
{
|
|
if( sub->streaming )
|
|
{
|
|
sub->stop( viewer_model.not_model );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} );
|
|
}
|
|
}
|
|
catch (const error& e)
|
|
{
|
|
error_message = rsutils::string::from() << "Failed to load file " << file << ". Reason: " << error_to_string(e);
|
|
failed = true;
|
|
}
|
|
catch (const std::exception& e)
|
|
{
|
|
error_message = rsutils::string::from() << "Failed to load file " << file << ". Reason: " << e.what();
|
|
failed = true;
|
|
}
|
|
if (failed && was_loaded)
|
|
{
|
|
try { ctx.unload_device(file); }
|
|
catch (...) {}
|
|
}
|
|
}
|
|
|
|
// This function is called every frame
|
|
// If between the frames there was an asyncronous connect/disconnect event
|
|
// the function will pick up on this and add the device to the viewer
|
|
bool refresh_devices(std::mutex& m,
|
|
context& ctx,
|
|
device_changes& devices_connection_changes,
|
|
std::vector<device>& current_connected_devices,
|
|
std::vector<std::pair<std::string, std::string>>& device_names,
|
|
device_models_list& device_models,
|
|
viewer_model& viewer_model,
|
|
std::string& error_message)
|
|
{
|
|
event_information info({}, {});
|
|
if (!devices_connection_changes.try_get_next_changes(info))
|
|
return false;
|
|
try
|
|
{
|
|
//Remove disconnected
|
|
auto dev_itr = begin(current_connected_devices);
|
|
while (dev_itr != end(current_connected_devices))
|
|
{
|
|
auto dev = *dev_itr;
|
|
if (info.was_removed(dev))
|
|
{
|
|
//Notify change
|
|
viewer_model.not_model->add_notification({ get_device_name(dev).first + " Disconnected\n",
|
|
RS2_LOG_SEVERITY_INFO, RS2_NOTIFICATION_CATEGORY_UNKNOWN_ERROR });
|
|
|
|
//Remove from devices
|
|
auto dev_model_itr = std::find_if(begin(device_models), end(device_models),
|
|
[&](const std::unique_ptr<device_model>& other) { return get_device_name(other->dev) == get_device_name(dev); });
|
|
|
|
if (dev_model_itr != end(device_models))
|
|
{
|
|
for (auto&& s : (*dev_model_itr)->subdevices)
|
|
s->streaming = false;
|
|
|
|
dev_model_itr->reset();
|
|
device_models.erase(dev_model_itr);
|
|
|
|
if (device_models.size() == 0)
|
|
{
|
|
viewer_model.ppf.depth_stream_active = false;
|
|
|
|
// Stopping post processing filter rendering thread in case of disconnection
|
|
viewer_model.ppf.stop();
|
|
}
|
|
}
|
|
auto dev_name_itr = std::find(begin(device_names), end(device_names), get_device_name(dev));
|
|
if (dev_name_itr != end(device_names))
|
|
device_names.erase(dev_name_itr);
|
|
|
|
dev_itr = current_connected_devices.erase(dev_itr);
|
|
continue;
|
|
}
|
|
++dev_itr;
|
|
}
|
|
|
|
//Add connected
|
|
static bool initial_refresh = true;
|
|
try
|
|
{
|
|
for (auto dev : info.get_new_devices())
|
|
{
|
|
auto dev_descriptor = get_device_name(dev);
|
|
device_names.push_back(dev_descriptor);
|
|
|
|
bool added = false;
|
|
if (device_models.size() == 0 &&
|
|
dev.supports(RS2_CAMERA_INFO_NAME) && std::string(dev.get_info(RS2_CAMERA_INFO_NAME)) != "Platform Camera" && std::string(dev.get_info(RS2_CAMERA_INFO_NAME)).find("IP Device") == std::string::npos)
|
|
{
|
|
device_models.emplace_back(new device_model(dev, error_message, viewer_model));
|
|
viewer_model.not_model->add_log(
|
|
rsutils::string::from() << ( *device_models.rbegin() )->dev.get_info( RS2_CAMERA_INFO_NAME )
|
|
<< " was selected as a default device" );
|
|
added = true;
|
|
}
|
|
|
|
if (!initial_refresh)
|
|
{
|
|
if (added || dev.is<playback>())
|
|
viewer_model.not_model->add_notification({ dev_descriptor.first + " Connected\n",
|
|
RS2_LOG_SEVERITY_INFO, RS2_NOTIFICATION_CATEGORY_UNKNOWN_ERROR });
|
|
else if (added || dev.supports(RS2_CAMERA_INFO_IP_ADDRESS))
|
|
viewer_model.not_model->add_notification({ dev_descriptor.first + " Connected\n",
|
|
RS2_LOG_SEVERITY_INFO, RS2_NOTIFICATION_CATEGORY_UNKNOWN_ERROR });
|
|
else
|
|
viewer_model.not_model->add_notification({ dev_descriptor.first + " Connected\n",
|
|
RS2_LOG_SEVERITY_INFO, RS2_NOTIFICATION_CATEGORY_UNKNOWN_ERROR },
|
|
[&device_models, &viewer_model, &error_message, dev] {
|
|
auto device = dev;
|
|
device_models.emplace_back(
|
|
new device_model(device, error_message, viewer_model));
|
|
});
|
|
}
|
|
|
|
current_connected_devices.push_back(dev);
|
|
for (auto&& s : dev.query_sensors())
|
|
{
|
|
s.set_notifications_callback([&, dev_descriptor](const notification& n)
|
|
{
|
|
if (n.get_category() == RS2_NOTIFICATION_CATEGORY_HARDWARE_EVENT)
|
|
{
|
|
auto data = n.get_serialized_data();
|
|
if (!data.empty())
|
|
{
|
|
auto dev_model_itr = std::find_if(begin(device_models), end(device_models),
|
|
[&](const std::unique_ptr<device_model>& other)
|
|
{ return get_device_name(other->dev) == dev_descriptor; });
|
|
|
|
if (dev_model_itr == end(device_models))
|
|
return;
|
|
|
|
(*dev_model_itr)->handle_hardware_events(data);
|
|
}
|
|
}
|
|
viewer_model.not_model->add_notification({ n.get_description(), n.get_severity(), n.get_category() });
|
|
});
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
catch (std::exception& e) {
|
|
std::stringstream s;
|
|
s << "Couldn't refresh devices - " << e.what();
|
|
log(RS2_LOG_SEVERITY_WARN, s.str().c_str());
|
|
}
|
|
initial_refresh = false;
|
|
}
|
|
catch (const error& e)
|
|
{
|
|
error_message = error_to_string(e);
|
|
}
|
|
catch (const std::exception& e)
|
|
{
|
|
error_message = e.what();
|
|
}
|
|
catch (...)
|
|
{
|
|
error_message = "Unknown error";
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
int main(int argc, const char** argv) try
|
|
{
|
|
TCLAP::CmdLine cmd( "realsense-viewer", ' ', RS2_API_FULL_VERSION_STR );
|
|
#ifdef BUILD_EASYLOGGINGPP
|
|
TCLAP::SwitchArg debug_arg( "", "debug", "Turn on LibRS debug logs" );
|
|
cmd.add( debug_arg );
|
|
#endif
|
|
TCLAP::SwitchArg only_sw_arg( "", "sw-only", "Show only software devices (playback, DDS, etc. -- but not USB/HID/etc.)" );
|
|
cmd.add( only_sw_arg );
|
|
// There isn't always a console... so if we need to show an error/usage, we need to enable it:
|
|
class cmdline_output : public TCLAP::StdOutput
|
|
{
|
|
typedef TCLAP::StdOutput super;
|
|
|
|
public:
|
|
void usage( TCLAP::CmdLineInterface & c ) override
|
|
{
|
|
rsutils::os::ensure_console();
|
|
super::usage( c );
|
|
}
|
|
|
|
void version( TCLAP::CmdLineInterface & c ) override
|
|
{
|
|
rsutils::os::ensure_console();
|
|
super::version( c );
|
|
}
|
|
|
|
void failure( TCLAP::CmdLineInterface & c, TCLAP::ArgException & e ) override
|
|
{
|
|
rsutils::os::ensure_console();
|
|
super::failure( c, e );
|
|
}
|
|
} our_cmdline_output;
|
|
cmd.setOutput( &our_cmdline_output );
|
|
cmd.parse( argc, argv );
|
|
|
|
#ifdef BUILD_EASYLOGGINGPP
|
|
if( debug_arg.getValue() )
|
|
rsutils::os::ensure_console();
|
|
#if defined( WIN32 )
|
|
// In Windows, we have no console unless we start the viewer from one; without one, calling log_to_console will
|
|
// ensure a console, so we want to avoid it by default!
|
|
if( GetStdHandle( STD_OUTPUT_HANDLE ) )
|
|
#endif
|
|
rs2::log_to_console( debug_arg.getValue() ? RS2_LOG_SEVERITY_DEBUG : RS2_LOG_SEVERITY_INFO );
|
|
#endif
|
|
|
|
std::shared_ptr<device_models_list> device_models = std::make_shared<device_models_list>();
|
|
|
|
rsutils::json settings = rsutils::json::object();
|
|
if( only_sw_arg.getValue() )
|
|
{
|
|
#if defined( BUILD_WITH_DDS )
|
|
settings["dds"]["enabled"]; // null: remove global dds:false or dds/enabled:false, if any
|
|
#endif
|
|
settings["device-mask"] = RS2_PRODUCT_LINE_SW_ONLY | RS2_PRODUCT_LINE_ANY;
|
|
}
|
|
|
|
context ctx( settings.dump() );
|
|
ux_window window("Intel RealSense Viewer", ctx);
|
|
|
|
// Create RealSense Context
|
|
device_changes devices_connection_changes(ctx);
|
|
std::vector<std::pair<std::string, std::string>> device_names;
|
|
|
|
std::string error_message;
|
|
std::string label;
|
|
|
|
device_model* device_to_remove = nullptr;
|
|
bool is_ip_device_connected = false;
|
|
std::string ip_address;
|
|
|
|
#ifdef BUILD_EASYLOGGINGPP
|
|
bool const disable_log_to_console = debug_arg.getValue();
|
|
#else
|
|
bool const disable_log_to_console = false;
|
|
#endif
|
|
|
|
viewer_model viewer_model( ctx, disable_log_to_console );
|
|
|
|
update_viewer_configuration(viewer_model);
|
|
|
|
std::vector<device> connected_devs;
|
|
std::mutex m;
|
|
|
|
#ifdef BUILD_EASYLOGGINGPP
|
|
std::weak_ptr<notifications_model> notifications = viewer_model.not_model;
|
|
rs2::log_to_callback( RS2_LOG_SEVERITY_INFO,
|
|
[notifications]( rs2_log_severity severity, rs2::log_message const& msg )
|
|
{
|
|
if (auto not_model = notifications.lock())
|
|
{
|
|
not_model->output.add_log(severity, msg.filename(), (int)(msg.line_number()), msg.raw());
|
|
}
|
|
});
|
|
#endif
|
|
|
|
window.on_file_drop = [&](std::string filename)
|
|
{
|
|
add_playback_device(ctx, device_models, error_message, viewer_model, filename);
|
|
if (!error_message.empty())
|
|
{
|
|
viewer_model.not_model->add_notification({ error_message,
|
|
RS2_LOG_SEVERITY_ERROR, RS2_NOTIFICATION_CATEGORY_UNKNOWN_ERROR });
|
|
}
|
|
};
|
|
|
|
for (int i = 1; i < argc; i++)
|
|
{
|
|
try
|
|
{
|
|
const char* arg = argv[i];
|
|
std::ifstream file(arg);
|
|
if (!file.good())
|
|
continue;
|
|
|
|
add_playback_device(ctx, device_models, error_message, viewer_model, arg);
|
|
}
|
|
catch (const rs2::error& e)
|
|
{
|
|
error_message = error_to_string(e);
|
|
}
|
|
catch (const std::exception& e)
|
|
{
|
|
error_message = e.what();
|
|
}
|
|
}
|
|
|
|
window.on_load = [&]()
|
|
{
|
|
refresh_devices(m, ctx, devices_connection_changes, connected_devs,
|
|
device_names, *device_models, viewer_model, error_message);
|
|
return true;
|
|
};
|
|
|
|
if (argc == 2)
|
|
{
|
|
try
|
|
{
|
|
is_ip_device_connected = add_remote_device(ctx, argv[1]);
|
|
}
|
|
catch (std::runtime_error e)
|
|
{
|
|
error_message = e.what();
|
|
}
|
|
}
|
|
|
|
// Closing the window
|
|
while (window)
|
|
{
|
|
auto device_changed = refresh_devices(m, ctx, devices_connection_changes, connected_devs,
|
|
device_names, *device_models, viewer_model, error_message);
|
|
|
|
auto output_height = viewer_model.get_output_height();
|
|
|
|
rect viewer_rect = { viewer_model.panel_width,
|
|
viewer_model.panel_y, window.width() -
|
|
viewer_model.panel_width,
|
|
window.height() - viewer_model.panel_y - output_height };
|
|
|
|
// Flags for pop-up window - no window resize, move or collaps
|
|
auto flags = ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove |
|
|
ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar |
|
|
ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoBringToFrontOnFocus;
|
|
|
|
ImGui::SetNextWindowPos({ 0, 0 });
|
|
ImGui::SetNextWindowSize({ viewer_model.panel_width, viewer_model.panel_y });
|
|
|
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
|
|
ImGui::Begin("Add Device Panel", nullptr, flags);
|
|
|
|
ImGui::PushFont(window.get_large_font());
|
|
ImGui::PushStyleColor(ImGuiCol_PopupBg, from_rgba(230, 230, 230, 255));
|
|
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, from_rgba(0, 0xae, 0xff, 255));
|
|
ImGui::PushStyleColor(ImGuiCol_TextSelectedBg, from_rgba(255, 255, 255, 255));
|
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(5, 5));
|
|
ImGui::SetNextWindowPos({ 0, viewer_model.panel_y });
|
|
|
|
std::string add_source_button_text = rsutils::string::from()
|
|
<< " " << textual_icons::plus_circle << " Add Source\t\t\t\t\t\t\t\t\t\t\t";
|
|
if (ImGui::Button(add_source_button_text.c_str(), { viewer_model.panel_width - 1, viewer_model.panel_y }))
|
|
ImGui::OpenPopup("select");
|
|
|
|
auto new_devices_count = device_names.size() + 1;
|
|
|
|
for (auto&& dev_model : *device_models)
|
|
{
|
|
auto connected_devs_itr = std::find_if(begin(connected_devs), end(connected_devs),
|
|
[&](const device& d) { return get_device_name(d) == get_device_name(dev_model->dev); });
|
|
|
|
if (connected_devs_itr != end(connected_devs) || dev_model->dev.is<playback>())
|
|
new_devices_count--;
|
|
}
|
|
|
|
|
|
ImGui::PushFont(window.get_font());
|
|
|
|
int multiline_devices_names = 0;
|
|
for (size_t i = 0; i < device_names.size(); i++)
|
|
{
|
|
if (device_names[i].first.find("\n") != std::string::npos)
|
|
{
|
|
bool show_device_in_list = true;
|
|
for (auto&& dev_model : *device_models)
|
|
{
|
|
if (get_device_name(dev_model->dev) == device_names[i])
|
|
{
|
|
show_device_in_list = false;
|
|
break;
|
|
}
|
|
}
|
|
if (show_device_in_list)
|
|
{
|
|
multiline_devices_names++;
|
|
}
|
|
}
|
|
}
|
|
|
|
float line_h = ImGui::GetTextLineHeightWithSpacing() + 2;
|
|
float separator_h = new_devices_count > 1 ? ImGui::GetStyle().ItemSpacing.y : 0;
|
|
float popup_select_h = line_h * ( new_devices_count + multiline_devices_names ) + separator_h + ( is_ip_device_connected ? 0 : line_h );
|
|
ImVec2 popup_select_size = { viewer_model.panel_width, popup_select_h };
|
|
ImGui::SetNextWindowSize( popup_select_size );
|
|
|
|
if (ImGui::BeginPopup("select"))
|
|
{
|
|
ImGui::PushStyleColor(ImGuiCol_Text, dark_grey);
|
|
ImGui::Columns(1, "DevicesList", false);
|
|
for (int i = 0; i < device_names.size(); i++)
|
|
{
|
|
bool skip = false;
|
|
for (auto&& dev_model : *device_models)
|
|
if (get_device_name(dev_model->dev) == device_names[i]) skip = true;
|
|
if (skip) continue;
|
|
|
|
auto dev = connected_devs[i];
|
|
std::string dev_type;
|
|
if( dev.supports( RS2_CAMERA_INFO_USB_TYPE_DESCRIPTOR ) )
|
|
{
|
|
dev_type = "USB";
|
|
dev_type += dev.get_info( RS2_CAMERA_INFO_USB_TYPE_DESCRIPTOR );
|
|
}
|
|
else if( dev.supports( RS2_CAMERA_INFO_PRODUCT_ID ) )
|
|
{
|
|
dev_type = dev.get_info( RS2_CAMERA_INFO_PRODUCT_ID );
|
|
if( dev_type == "ABCD" ) // Specific for D457
|
|
dev_type = "GMSL";
|
|
}
|
|
|
|
std::string line = rsutils::string::from() << dev.get_info( RS2_CAMERA_INFO_NAME ) << " (" << dev_type
|
|
<< ") S/N " << device_names[i].second.c_str();
|
|
|
|
ImGui::PushID(static_cast<int>(i));
|
|
if (ImGui::Selectable(line.c_str(), false, ImGuiSelectableFlags_SpanAllColumns)/* || switch_to_newly_loaded_device*/)
|
|
{
|
|
try
|
|
{
|
|
device_models->emplace_back(new device_model(dev, error_message, viewer_model));
|
|
}
|
|
catch (const error& e)
|
|
{
|
|
error_message = error_to_string(e);
|
|
}
|
|
catch (const std::exception& e)
|
|
{
|
|
error_message = e.what();
|
|
}
|
|
}
|
|
ImGui::PopID();
|
|
}
|
|
|
|
if (new_devices_count > 1) ImGui::Separator();
|
|
|
|
if (ImGui::Selectable("Load Recorded Sequence", false, ImGuiSelectableFlags_SpanAllColumns))
|
|
{
|
|
if (auto ret = file_dialog_open(open_file, "ROS-bag\0*.bag\0", NULL, NULL))
|
|
{
|
|
add_playback_device(ctx, device_models, error_message, viewer_model, ret);
|
|
}
|
|
}
|
|
ImGui::NextColumn();
|
|
|
|
bool close_ip_popup = false;
|
|
|
|
if (!is_ip_device_connected)
|
|
{
|
|
if (ImGui::Selectable("Add Network Device", false, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_DontClosePopups))
|
|
{
|
|
error_message = "RealSense Network Devices are unsupported at this time";
|
|
}
|
|
|
|
float width = 300;
|
|
float height = 125;
|
|
float posx = window.width() * 0.5f - width * 0.5f;
|
|
float posy = window.height() * 0.5f - height * 0.5f;
|
|
ImGui::SetNextWindowPos({ posx, posy });
|
|
ImGui::SetNextWindowSize({ width, height });
|
|
ImGui::PushStyleColor(ImGuiCol_PopupBg, sensor_bg);
|
|
ImGui::PushStyleColor(ImGuiCol_TextSelectedBg, white);
|
|
ImGui::PushStyleColor(ImGuiCol_Text, light_grey);
|
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0);
|
|
|
|
if (ImGui::BeginPopupModal("Network Device", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove))
|
|
{
|
|
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 3);
|
|
ImGui::SetCursorPosX(10);
|
|
ImGui::Text("Connect to a Linux system running rs-server");
|
|
|
|
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5);
|
|
|
|
static char ip_input[255];
|
|
std::copy(ip_address.begin(), ip_address.end(), ip_input);
|
|
ip_input[ip_address.size()] = '\0';
|
|
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5);
|
|
ImGui::SetCursorPosX(10);
|
|
ImGui::Text("Device IP: ");
|
|
ImGui::SameLine();
|
|
//ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 1);
|
|
ImGui::PushItemWidth(width - ImGui::GetCursorPosX() - 10);
|
|
if (ImGui::GetWindowIsFocused() && !ImGui::IsAnyItemActive())
|
|
{
|
|
ImGui::SetKeyboardFocusHere();
|
|
}
|
|
ImGui::PushStyleColor(ImGuiCol_TextSelectedBg, light_blue);
|
|
|
|
ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 3);
|
|
if (ImGui::InputText("##ip", ip_input, 255))
|
|
{
|
|
ip_address = ip_input;
|
|
}
|
|
ImGui::PopStyleColor();
|
|
|
|
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 6);
|
|
|
|
ImGui::PopItemWidth();
|
|
ImGui::SetCursorPosX(width / 2 - 105);
|
|
|
|
if (ImGui::ButtonEx("OK", { 100.f, 25.f }) || ImGui::IsKeyDown(GLFW_KEY_ENTER) || ImGui::IsKeyDown(GLFW_KEY_KP_ENTER))
|
|
{
|
|
try
|
|
{
|
|
is_ip_device_connected = add_remote_device(ctx, ip_address);
|
|
refresh_devices(m, ctx, devices_connection_changes, connected_devs, device_names, *device_models, viewer_model, error_message);
|
|
auto dev = connected_devs[connected_devs.size() - 1];
|
|
device_models->emplace_back(new device_model(dev, error_message, viewer_model));
|
|
config_file::instance().set(configurations::viewer::last_ip, ip_address);
|
|
}
|
|
catch (std::runtime_error e)
|
|
{
|
|
error_message = e.what();
|
|
}
|
|
ip_address = "";
|
|
close_ip_popup = true;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
ImGui::SameLine();
|
|
ImGui::SetCursorPosX(width / 2 + 5);
|
|
if (ImGui::Button("Cancel", { 100.f, 25.f }) || ImGui::IsKeyDown(GLFW_KEY_ESCAPE))
|
|
{
|
|
ip_address = "";
|
|
close_ip_popup = true;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
ImGui::EndPopup();
|
|
}
|
|
ImGui::PopStyleColor(3);
|
|
ImGui::PopStyleVar(1);
|
|
}
|
|
|
|
if (close_ip_popup)
|
|
{
|
|
ImGui::CloseCurrentPopup();
|
|
close_ip_popup = false;
|
|
}
|
|
ImGui::PopStyleColor();
|
|
ImGui::EndPopup();
|
|
}
|
|
ImGui::PopFont();
|
|
ImGui::PopStyleVar();
|
|
ImGui::PopStyleColor();
|
|
ImGui::PopStyleColor();
|
|
ImGui::PopStyleColor();
|
|
ImGui::PopFont();
|
|
|
|
ImGui::End();
|
|
ImGui::PopStyleVar();
|
|
|
|
|
|
viewer_model.show_top_bar(window, viewer_rect, *device_models);
|
|
|
|
auto output_rect = rect{ viewer_model.panel_width,
|
|
window.height() - viewer_model.get_output_height(),
|
|
window.width() - viewer_model.panel_width, float(viewer_model.get_output_height()) };
|
|
|
|
viewer_model.not_model->output.draw(window, output_rect, *device_models);
|
|
|
|
// Set window position and size
|
|
ImGui::SetNextWindowPos({ 0, viewer_model.panel_y });
|
|
ImGui::SetNextWindowSize({ viewer_model.panel_width, window.height() - viewer_model.panel_y });
|
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
|
|
ImGui::PushStyleColor(ImGuiCol_WindowBg, sensor_bg);
|
|
|
|
// *********************
|
|
// Creating window menus
|
|
// *********************
|
|
ImGui::Begin("Control Panel", nullptr, flags | ImGuiWindowFlags_AlwaysVerticalScrollbar);
|
|
|
|
if (device_models->size() > 0)
|
|
{
|
|
std::vector<std::function<void()>> draw_later;
|
|
auto windows_width = ImGui::GetContentRegionMax().x;
|
|
|
|
for (auto&& dev_model : *device_models)
|
|
{
|
|
dev_model->draw_controls(viewer_model.panel_width, viewer_model.panel_y,
|
|
window, error_message, device_to_remove, viewer_model, windows_width, draw_later);
|
|
}
|
|
if (viewer_model.ppf.is_rendering())
|
|
{
|
|
if (!std::any_of(device_models->begin(), device_models->end(),
|
|
[](const std::unique_ptr<device_model>& dm)
|
|
{
|
|
return dm->is_streaming();
|
|
}))
|
|
{
|
|
// Stopping post processing filter rendering thread
|
|
viewer_model.ppf.stop();
|
|
}
|
|
}
|
|
|
|
ImGui::SetContentRegionWidth(windows_width);
|
|
|
|
auto pos = ImGui::GetCursorScreenPos();
|
|
auto h = ImGui::GetWindowHeight();
|
|
if (h > pos.y - viewer_model.panel_y)
|
|
{
|
|
ImGui::GetWindowDrawList()->AddLine({ pos.x,pos.y }, { pos.x + viewer_model.panel_width,pos.y }, ImColor(from_rgba(0, 0, 0, 0xff)));
|
|
ImRect bb(pos, ImVec2(pos.x + ImGui::GetContentRegionAvail().x, pos.y + ImGui::GetContentRegionAvail().y));
|
|
ImGui::GetWindowDrawList()->AddRectFilled(bb.GetTL(), bb.GetBR(), ImColor(dark_window_background));
|
|
}
|
|
|
|
for (auto&& lambda : draw_later)
|
|
{
|
|
try
|
|
{
|
|
lambda();
|
|
}
|
|
catch (const error& e)
|
|
{
|
|
error_message = error_to_string(e);
|
|
}
|
|
catch (const std::exception& e)
|
|
{
|
|
error_message = e.what();
|
|
}
|
|
}
|
|
|
|
if (device_to_remove)
|
|
{
|
|
if (auto p = device_to_remove->dev.as<playback>())
|
|
{
|
|
ctx.unload_device(p.file_name());
|
|
}
|
|
viewer_model.syncer->remove_syncer(device_to_remove->dev_syncer);
|
|
auto it = std::find_if(begin(*device_models), end(*device_models),
|
|
[&](const std::unique_ptr<device_model>& other)
|
|
{ return get_device_name(other->dev) == get_device_name(device_to_remove->dev); });
|
|
|
|
if (it != device_models->end())
|
|
{
|
|
it->reset();
|
|
device_models->erase(it);
|
|
}
|
|
|
|
device_to_remove = nullptr;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const ImVec2 pos = ImGui::GetCursorScreenPos();
|
|
ImRect bb(pos, ImVec2(pos.x + ImGui::GetContentRegionAvail().x, pos.y + ImGui::GetContentRegionAvail().y));
|
|
ImGui::GetWindowDrawList()->AddRectFilled(bb.GetTL(), bb.GetBR(), ImColor(dark_window_background));
|
|
|
|
viewer_model.show_no_device_overlay(window.get_large_font(), 50, static_cast<int>(viewer_model.panel_y + 50));
|
|
}
|
|
|
|
ImGui::End();
|
|
ImGui::PopStyleVar();
|
|
ImGui::PopStyleColor();
|
|
|
|
// Fetch and process frames from queue
|
|
viewer_model.handle_ready_frames(viewer_rect, window, static_cast<int>(device_models->size()), error_message);
|
|
}
|
|
|
|
// Stopping post processing filter rendering thread
|
|
viewer_model.ppf.stop();
|
|
|
|
// Stop all subdevices
|
|
for (auto&& device_model : *device_models)
|
|
for (auto&& sub : device_model->subdevices)
|
|
{
|
|
if (sub->streaming)
|
|
sub->stop(viewer_model.not_model);
|
|
}
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|
|
catch (const error & e)
|
|
{
|
|
std::cerr << "RealSense error calling " << e.get_failed_function() << "(" << e.get_failed_args() << "):\n " << e.what() << std::endl;
|
|
return EXIT_FAILURE;
|
|
}
|
|
catch (const std::exception& e)
|
|
{
|
|
std::cerr << e.what() << std::endl;
|
|
return EXIT_FAILURE;
|
|
}
|