kinect/codes/Azure-Kinect-Sensor-SDK/tools/k4aviewer/k4aviewersettingsmanager.cpp

389 lines
11 KiB
C++
Raw Normal View History

2024-03-06 18:05:53 +00:00
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
// Associated header
//
#include "k4aviewersettingsmanager.h"
// System headers
//
#include <cstdio>
#include <sstream>
#include <fstream>
// Library headers
//
// Project headers
//
#include "filesystem17.h"
#include "k4atypeoperators.h"
using namespace k4aviewer;
namespace
{
constexpr char Separator[] = " ";
} // namespace
namespace k4aviewer
{
constexpr char BeginDeviceConfigurationTag[] = "BeginDeviceConfiguration";
constexpr char EndDeviceConfigurationTag[] = "EndDeviceConfiguration";
constexpr char EnableColorCameraTag[] = "EnableColorCamera";
constexpr char EnableDepthCameraTag[] = "EnableDepthCamera";
constexpr char ColorFormatTag[] = "ColorFormat";
constexpr char ColorResolutionTag[] = "ColorResolution";
constexpr char DepthModeTag[] = "DepthMode";
constexpr char FramerateTag[] = "Framerate";
constexpr char DepthDelayOffColorUsecTag[] = "DepthDelayOffColorUsec";
constexpr char WiredSyncModeTag[] = "WiredSyncMode";
constexpr char SubordinateDelayOffMasterUsecTag[] = "SubordinateDelayOffMasterUsec";
constexpr char DisableStreamingIndicatorTag[] = "DisableStreamingIndicator";
constexpr char SynchronizedImagesOnlyTag[] = "SynchronizedImagesOnly";
constexpr char EnableImuTag[] = "EnableImu";
constexpr char EnableMicrophoneTag[] = "EnableMicrophone";
std::ostream &operator<<(std::ostream &s, const K4ADeviceConfiguration &val)
{
static_assert(sizeof(k4a_device_configuration_t) == 36, "Need to add a new setting");
s << BeginDeviceConfigurationTag << std::endl;
s << Separator << EnableColorCameraTag << Separator << val.EnableColorCamera << std::endl;
s << Separator << EnableDepthCameraTag << Separator << val.EnableDepthCamera << std::endl;
s << Separator << ColorFormatTag << Separator << val.ColorFormat << std::endl;
s << Separator << ColorResolutionTag << Separator << val.ColorResolution << std::endl;
s << Separator << DepthModeTag << Separator << val.DepthMode << std::endl;
s << Separator << FramerateTag << Separator << val.Framerate << std::endl;
s << Separator << DepthDelayOffColorUsecTag << Separator << val.DepthDelayOffColorUsec << std::endl;
s << Separator << WiredSyncModeTag << Separator << val.WiredSyncMode << std::endl;
s << Separator << SubordinateDelayOffMasterUsecTag << Separator << val.SubordinateDelayOffMasterUsec << std::endl;
s << Separator << DisableStreamingIndicatorTag << Separator << val.DisableStreamingIndicator << std::endl;
s << Separator << SynchronizedImagesOnlyTag << Separator << val.SynchronizedImagesOnly << std::endl;
s << Separator << EnableImuTag << Separator << val.EnableImu << std::endl;
s << Separator << EnableMicrophoneTag << Separator << val.EnableMicrophone << std::endl;
s << EndDeviceConfigurationTag << std::endl;
return s;
}
std::istream &operator>>(std::istream &s, K4ADeviceConfiguration &val)
{
std::string variableTag;
s >> variableTag;
if (variableTag != BeginDeviceConfigurationTag)
{
s.setstate(std::ios::failbit);
return s;
}
while (variableTag != EndDeviceConfigurationTag && s)
{
static_assert(sizeof(K4ADeviceConfiguration) == 36, "Need to add a new setting");
variableTag.clear();
s >> variableTag;
if (variableTag == EnableColorCameraTag)
{
s >> val.EnableColorCamera;
}
else if (variableTag == EnableDepthCameraTag)
{
s >> val.EnableDepthCamera;
}
else if (variableTag == ColorFormatTag)
{
s >> val.ColorFormat;
}
else if (variableTag == ColorResolutionTag)
{
s >> val.ColorResolution;
}
else if (variableTag == DepthModeTag)
{
s >> val.DepthMode;
}
else if (variableTag == FramerateTag)
{
s >> val.Framerate;
}
else if (variableTag == DepthDelayOffColorUsecTag)
{
s >> val.DepthDelayOffColorUsec;
}
else if (variableTag == WiredSyncModeTag)
{
s >> val.WiredSyncMode;
}
else if (variableTag == SubordinateDelayOffMasterUsecTag)
{
s >> val.SubordinateDelayOffMasterUsec;
}
else if (variableTag == DisableStreamingIndicatorTag)
{
s >> val.DisableStreamingIndicator;
}
else if (variableTag == SynchronizedImagesOnlyTag)
{
s >> val.SynchronizedImagesOnly;
}
else if (variableTag == EnableImuTag)
{
s >> val.EnableImu;
}
else if (variableTag == EnableMicrophoneTag)
{
s >> val.EnableMicrophone;
}
else if (variableTag == EndDeviceConfigurationTag)
{
break;
}
else
{
s.setstate(std::ios::failbit);
break;
}
}
return s;
}
constexpr char BeginViewerOptionsTag[] = "BeginViewerOptions";
constexpr char EndViewerOptionsTag[] = "EndViewerOptions";
std::istream &operator>>(std::istream &s, K4AViewerOptions &val)
{
std::string variableTag;
s >> variableTag;
if (variableTag != BeginViewerOptionsTag)
{
s.setstate(std::ios::failbit);
return s;
}
while (variableTag != EndDeviceConfigurationTag && s)
{
s >> variableTag;
if (variableTag == EndViewerOptionsTag)
{
break;
}
ViewerOption option;
std::stringstream converter;
converter << variableTag;
converter >> option;
if (!converter)
{
s.setstate(std::ios::failbit);
break;
}
bool value;
s >> value;
if (!s)
{
break;
}
val.Options[static_cast<size_t>(option)] = value;
}
return s;
}
std::ostream &operator<<(std::ostream &s, const K4AViewerOptions &val)
{
s << BeginViewerOptionsTag << std::endl;
for (size_t i = 0; i < val.Options.size(); ++i)
{
s << static_cast<ViewerOption>(i) << Separator << val.Options[i] << std::endl;
}
s << EndViewerOptionsTag << std::endl;
return s;
}
constexpr char ShowFrameRateInfoTag[] = "ShowFrameRateInfo";
constexpr char ShowInfoPaneTag[] = "ShowInfoPane";
constexpr char ShowLogDockTag[] = "ShowLogDock";
constexpr char ShowDeveloperOptionsTag[] = "ShowDeveloperOptions";
std::istream &operator>>(std::istream &s, ViewerOption &val)
{
static_assert(static_cast<size_t>(ViewerOption::MAX) == 4, "Need to add a new viewer option conversion");
std::string tag;
s >> tag;
if (tag == ShowFrameRateInfoTag)
{
val = ViewerOption::ShowFrameRateInfo;
}
else if (tag == ShowInfoPaneTag)
{
val = ViewerOption::ShowInfoPane;
}
else if (tag == ShowLogDockTag)
{
val = ViewerOption::ShowLogDock;
}
else if (tag == ShowDeveloperOptionsTag)
{
val = ViewerOption::ShowDeveloperOptions;
}
else
{
s.setstate(std::ios::failbit);
}
return s;
}
std::ostream &operator<<(std::ostream &s, const ViewerOption &val)
{
static_assert(static_cast<size_t>(ViewerOption::MAX) == 4, "Need to add a new viewer option conversion");
switch (val)
{
case ViewerOption::ShowFrameRateInfo:
s << ShowFrameRateInfoTag;
break;
case ViewerOption::ShowInfoPane:
s << ShowInfoPaneTag;
break;
case ViewerOption::ShowLogDock:
s << ShowLogDockTag;
break;
case ViewerOption::ShowDeveloperOptions:
s << ShowDeveloperOptionsTag;
break;
default:
s.setstate(std::ios::failbit);
break;
}
return s;
}
} // namespace k4aviewer
// The UI doesn't quite line up with the struct we actually need to give to the K4A API, so
// we have to do a bit of conversion.
//
k4a_device_configuration_t K4ADeviceConfiguration::ToK4ADeviceConfiguration() const
{
k4a_device_configuration_t deviceConfig;
deviceConfig.color_format = ColorFormat;
deviceConfig.color_resolution = EnableColorCamera ? ColorResolution : K4A_COLOR_RESOLUTION_OFF;
deviceConfig.depth_mode = EnableDepthCamera ? DepthMode : K4A_DEPTH_MODE_OFF;
deviceConfig.camera_fps = Framerate;
deviceConfig.depth_delay_off_color_usec = DepthDelayOffColorUsec;
deviceConfig.wired_sync_mode = WiredSyncMode;
deviceConfig.subordinate_delay_off_master_usec = SubordinateDelayOffMasterUsec;
deviceConfig.disable_streaming_indicator = DisableStreamingIndicator;
deviceConfig.synchronized_images_only = SynchronizedImagesOnly;
return deviceConfig;
}
K4AViewerOptions::K4AViewerOptions()
{
static_assert(static_cast<size_t>(ViewerOption::MAX) == 4, "Need to add a new viewer option default");
Options[static_cast<size_t>(ViewerOption::ShowFrameRateInfo)] = false;
Options[static_cast<size_t>(ViewerOption::ShowInfoPane)] = true;
Options[static_cast<size_t>(ViewerOption::ShowLogDock)] = false;
Options[static_cast<size_t>(ViewerOption::ShowDeveloperOptions)] = false;
}
K4AViewerSettingsManager::K4AViewerSettingsManager()
{
std17::filesystem::path settingsPath = "";
#ifdef WIN32
constexpr size_t bufferSize = 250;
char buffer[bufferSize];
size_t len;
// While not technically part of the C++ spec, MSVC provides the
// C function getenv_s in the C++ standard library headers and
// complains if you use getenv, so we use getenv_s here.
//
errno_t err = getenv_s(&len, buffer, bufferSize, "LOCALAPPDATA");
if (err == 0)
{
settingsPath = buffer;
}
#else
// The Linux compilers, on the other hand, don't provide the 'safe'
// C functions, but they do provide a nonstandard function to do it,
// so we do that instead.
//
const char *home = secure_getenv("HOME");
if (home)
{
settingsPath = home;
}
#endif
settingsPath.append(".k4aviewer");
m_settingsFilePath = settingsPath.string();
LoadSettings();
}
void K4AViewerSettingsManager::SaveSettings()
{
std::ofstream fileWriter(m_settingsFilePath.c_str());
fileWriter << m_settingsPayload.SavedDeviceConfiguration << std::endl;
fileWriter << m_settingsPayload.Options << std::endl;
}
void K4AViewerSettingsManager::LoadSettings()
{
std::ifstream fileReader(m_settingsFilePath.c_str());
if (!fileReader)
{
SetDefaults();
return;
}
SettingsPayload newSettingsPayload;
fileReader >> newSettingsPayload.SavedDeviceConfiguration;
fileReader >> newSettingsPayload.Options;
if (fileReader.fail())
{
// File is corrupt, try to delete it
//
fileReader.close();
SetDefaults();
}
else
{
m_settingsPayload = newSettingsPayload;
}
}
void K4AViewerSettingsManager::SetDefaults()
{
if (!m_settingsFilePath.empty())
{
(void)std::remove(m_settingsFilePath.c_str());
}
m_settingsPayload = SettingsPayload();
}